HEX
Server: nginx/1.28.1
System: Linux 10-41-63-61 6.8.0-31-generic #31-Ubuntu SMP PREEMPT_DYNAMIC Sat Apr 20 00:40:06 UTC 2024 x86_64
User: www (1001)
PHP: 7.4.33
Disabled: passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv
Upload Files
File: /www/wwwroot/bs.kntsleep.com/system/basic/class/wechatpay.class.php
<?php
/*
 * Copyright (c) Huyin Information Technology Co., Ltd. All Rights Reserved.
 * BOSSCMS Content Management System (https://www.bosscms.net/)
 */
defined('IS_OK') or exit('Access Forbidden');

if(is_file($file = ROOT_PATH.'system/extend/wechatpay/autoload.php')){
	require_once $file;
}
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Handler\CurlHandler;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use WechatPay\GuzzleMiddleware\WechatPayMiddleware;
use WechatPay\GuzzleMiddleware\Validator;
use WechatPay\GuzzleMiddleware\Util\PemUtil;
use WechatPay\GuzzleMiddleware\Util\AesUtil;
use WechatPay\GuzzleMiddleware\Auth\CertificateVerifier;
use WechatPay\GuzzleMiddleware\Auth\WechatPay2Validator;

class wechatpay
{
	public static $config = array();

	public static function init()
	{
		global $G;
		self::$config = array(
            'appid'          => $G['config']['pay4_appid'],
            'appsecret'      => $G['config']['pay4_appsecret'],
            'mchid'          => $G['config']['pay4_mchid'],
			'serialno'       => $G['config']['pay4_serialno'],
			'apiv3_key'      => $G['config']['pay4_apiv3_key'],
			'apiclient_key'  => $G['config']['pay4_apiclient_key'],
			'certificate'    => $G['config']['pay4_certificate']
		);
	}

	public static function client($cert=true)
	{
		global $G;
		if($G['config']['pay4_open'] && is_file(ROOT_PATH.'system/extend/wechatpay/autoload.php')){
			if($cert && !self::$config['certificate']){
				if($client = self::client(false)){
					$resp = $client->request('GET', 'https://api.mch.weixin.qq.com/v3/certificates', array('headers'=>array('Accept'=>'application/json')));
					if($resp->getStatusCode() == 200){
						$list = json_decode($resp->getBody(), true);
						$plainCerts = [];
						$x509Certs = [];
						$decrypter = new AesUtil(self::$config['apiv3_key']);
						foreach($list['data'] as $item){
							$encCert = $item['encrypt_certificate'];
							if(!$plain = $decrypter->decryptToString($encCert['associated_data'], $encCert['nonce'], $encCert['ciphertext'])){
								return;
							}
							if(!$cert = \openssl_x509_read($plain)){
								return;
							}
							$plainCerts[] = $plain;
							$x509Certs[] = $cert;
						}
						$validator = new WechatPay2Validator(new CertificateVerifier($x509Certs));
						if($validator->validate($resp)){
							foreach($list['data'] as $index=>$item){
								$G['config']['pay4_certificate'] = self::$config['certificate'] = $plainCerts[$index];
								mysql::select_set(array('name'=>'pay4_certificate','value'=>$plainCerts[$index],'parent'=>'0','type'=>'0'),'config',array('value'));
							}
						}
					}
				}
			}
			$wechatpayMiddleware = WechatPayMiddleware::builder();
			$wechatpayMiddleware = $wechatpayMiddleware->withMerchant(self::$config['mchid'], self::$config['serialno'], PemUtil::loadPrivateKeyFromString(self::$config['apiclient_key']));
			if($cert){
				$wechatpayMiddleware = $wechatpayMiddleware->withWechatPay([ PemUtil::loadCertificateFromString(self::$config['certificate']) ]);
			}else{
				$wechatpayMiddleware = $wechatpayMiddleware->withValidator(new NoopValidator);
			}
			$wechatpayMiddleware = $wechatpayMiddleware->build();
			$stack = GuzzleHttp\HandlerStack::create();
			$stack->push($wechatpayMiddleware, 'wechatpay');
			return new GuzzleHttp\Client(['handler' => $stack]);
		}
	}

	public static function pay($data, $info=null, $output=true)
	{
		global $G;
		if(!isset($info)){
			if(isMobile()){
				if(stripos($_SERVER['HTTP_USER_AGENT'],'MicroMessenger') === false){
					$info = 'wap';
				}else{
					$info = 'weixin';
				}
			}else{
				$info = 'pc';
			}
		}
		if($info == 'pc'){
			if($data['pc_url']){ //电脑端跳转链接
				if($output){
					location($data['pc_url']);
				}else{
					return array('info'=>'pc','pc_url'=>$data['pc_url']);
				}
			}
		}else if($info == 'weixin'){
			if(!$data['openid'] && !$data['code'] && !session::get('wechatpay_openid') && $data['wxauth_url']){
				$url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid='.self::$config['appid'].'&redirect_uri='.urlencode($data['wxauth_url']).'&response_type=code&scope=snsapi_base#wechat_redirect';
				if($output){
					location($url);
				}else{
					return array('info'=>'weixin','url'=>$url);
				}
			}
		}
		if($client = self::client()){
			$json = array(
				'appid' => self::$config['appid'],
				'mchid' => self::$config['mchid'],
				'description' => $data['name'], //商品描述
				'out_trade_no' => $data['num'], //商户订单号
				'attach' => setDefault($data['attach'],''), //传递信息
				'notify_url' =>  $data['notify_url'],
				'amount' => array(
					'total' => floor($data['price']*100), //付款金额(单位:分)
					'currency' => 'CNY'
				),
				'scene_info' => array(
					'payer_client_ip' => getIP()
				)
			);
			if($info == 'pc'){
			    $json['time_expire'] = $data['etime'];
				$resp = $client->request('POST', 'https://api.mch.weixin.qq.com/v3/pay/transactions/native', array('json'=>$json,'headers'=>array('Accept'=>'application/json')));
				$url = arrExist(json_decode($resp->getBody(),true),'code_url');
				if($output){
					location($url);
				}else{
					return array('info'=>'pc','url'=>$url);
				}
			}else if($info == 'wap'){
				$json['scene_info']['h5_info'] = array('type'=>'Wap');
				$resp = $client->request('POST', 'https://api.mch.weixin.qq.com/v3/pay/transactions/h5', array('json'=>$json,'headers'=>array('Accept'=>'application/json')));
				$url = arrExist(json_decode($resp->getBody(),true),'h5_url');
				if($output){
					location($url);
				}else{
					return array('info'=>'wap','url'=>$url);
				}
			}else if($info == 'weixin'){
			    $json['time_expire'] = $data['etime'];
				$json['payer']['openid'] = $data['openid']?$data['openid']:(setDefault(session::get('wechatpay_openid'),self::sns($data['code'])));
				$resp = $client->request('POST', 'https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi', array('json'=>$json,'headers'=>array('Accept'=>'application/json')));
				$pid = arrExist(json_decode($resp->getBody(),true),'prepay_id');
				$html = '<script>'.self::bridge($pid,$data['return_url']).'</script>';
				if($output){
					echo $html;
				}else{
					return array('info'=>'weixin','pid'=>$pid,'html'=>$html);
				}
			}
		}
	}

	public static function receive()
	{
		global $G;
		if($G['config']['pay4_open'] && is_file(ROOT_PATH.'system/extend/wechatpay/autoload.php')){
			if($post = json::decode(file_get_contents('php://input'))){
				if($post['event_type'] == 'TRANSACTION.SUCCESS'){
					$decrypter = new AesUtil(self::$config['apiv3_key']);
					$encCert = $post['resource'];
					if($plain = json::decode($decrypter->decryptToString($encCert['associated_data'],$encCert['nonce'], $encCert['ciphertext']))){
						return array(
							'notify' => true,
							'price' => $plain['amount']['total']/100,
							'num' => $plain['out_trade_no'],
							'no' => $plain['transaction_id'],
							'plain' => $plain
						);
					}
				}
			}
		}
	}

	public static function sns($code, $key='openid')
	{
		into::basic_class('curl');
		$res = json::decode(curl::request("https://api.weixin.qq.com/sns/oauth2/access_token?".
			"appid=".self::$config['appid']."&secret=".self::$config['appsecret']."&code={$code}&grant_type=authorization_code"));
		if($res['openid']){
			session::set('wechatpay_openid',$res['openid']);
		}
		return isset($key)?$res[$key]:$res;
	}

	public static function bridge($pid, $url)
	{
		$nonceStr = strRand(32);
		openssl_sign(self::$config['appid']."\n".TIME."\n".$nonceStr."\n".'prepay_id='.$pid."\n", $paySign, self::$config['apiclient_key'], OPENSSL_ALGO_SHA256);
		return "function onBridgeReady(){
			WeixinJSBridge.invoke('getBrandWCPayRequest',{
				'appId': '".self::$config['appid']."',
				'timeStamp': '".TIME."',
				'nonceStr': '{$nonceStr}',
				'package': 'prepay_id={$pid}',
				'signType': 'RSA',
				'paySign': '".base64_encode($paySign)."'
			},
			function(res){
				if(res.err_msg=='get_brand_wcpay_request:ok') {
					window.location.href='{$url}';
				}
			});
		}
		if(typeof WeixinJSBridge == 'undefined') {
			if(document.addEventListener) {
				document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
			}else if(document.attachEvent) {
				document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
				document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
			}
		}else{
			onBridgeReady();
		}";
	}
}

class NoopValidator implements Validator
{
    public function validate(\Psr\Http\Message\ResponseInterface $response)
    {
        return true;
    }
}
?>