原创TP6下微信支付wechatpay-apiv3之wechatpay-php使用,包括下单、支付、查询、关闭

PHP 17015 3 2022-12-15

TP6下微信支付wechatpay-apiv3之wechatpay-php使用,包括下单、支付、查询、关闭

所有的操作都来自参考:https://github.com/wechatpay-apiv3/wechatpay-php,包括安装等。

第一步安装wechatpay-php


composer require wechatpay/wechatpay
//注意安装目录,最好先cd到你的项目下再运行该安装命令


第二步:下载微信支付平台证书

具体请参考另一篇文章“windows系统下PHP版微信支付 wechatpay-php APIv3 平台证书下载(composer)


第三步:所有功能实现代码


use WeChatPay\Formatter;
use WeChatPay\Builder;
use WeChatPay\Crypto\AesGcm;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Util\PemUtil;

class Pay
{
	private $appid='';  //微信公众号ID,唯一标识
	private $secret='';  //微信公众号的appsecret
	private $mchid=''; // 商户号
	private $keyCert='apiclient_key.pem';  //商户API私钥
	private $serialNo='';  // 「商户API证书」的「证书序列号」
	private $wechatpayCert='wechatpay_cert.pem'; //微信支付平台证书

	//JSAPI下单,同时获取相关参数,包括:code、access_token、openid、prepay_id
	public function toCode(){
		$url='https://open.weixin.qq.com/connect/oauth2/authorize?appid='.$this->appid.'&redirect_uri='.urlencode('http://www.shiyunkj.com/wx/pay/getCode').'&response_type=code&scope=snsapi_base&state=syno'.time().'#wechat_redirect';
		return redirect($url);
	}
	public function getCode(){
		$gv=input('get.'); //获取code、state参数
		if(isset($gv['code']) && $gv['code']!=''){
			$url='https://api.weixin.qq.com/sns/oauth2/access_token?appid='.$this->appid.'&secret='.$this->secret.'&code='.$gv['code'].'&grant_type=authorization_code';
			$res=$this->curlContents($url); //正常返回 access_token、openid等参数
			if(isset($res['openid'])){
				$data=[
					'appid'=>$this->appid, //公众号的服务号APPID
					'mchid'=>$this->mchid, //商户号
					'description'=>哈喽吧1分礼品-1号', //商品描述
					'out_trade_no'=>'20221005003252001', //商户订单号
					'attach'=>'ceshi_'.time(), //附加数据,在查询API和支付通知中原样返回
					'notify_url'=>'http://www.hilo8.com/wx/pay/notify', //异步接收微信支付结果通知的回调地址
					'amount'=>['total'=>0.1*100], //订单总金额,单位为分
					'payer'=>['openid'=>$res['openid']]  //用户标识,用户在直连商户appid下的唯一标识
				];
				$instance=$this->APIv3();
				try {
				    $resp = $instance->chain('v3/pay/transactions/jsapi')->post(['json' => $data]); //jsapi下单
					$prepay_id=json_decode($resp->getBody(),true)['prepay_id'];
					if(isset($prepay_id)){
						echo '下单成功:prepay_id='.$prepay_id;
					}else{
						echo $resp->getStatusCode(), PHP_EOL;
						echo $resp->getBody(), PHP_EOL;
					}
				} catch (\Exception $e) {
				    // 进行错误处理
				    echo $e->getMessage(), PHP_EOL;
				    if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
				        $r = $e->getResponse();
				        echo $r->getStatusCode() . ' ' . $r->getReasonPhrase(), PHP_EOL;
				        echo $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
				    }
				    echo $e->getTraceAsString(), PHP_EOL;
				}
			}else{
				echo '获取openid失败,错误信息:'.json_encode($res,JSON_UNESCAPED_UNICODE);
			}
		}else{
			echo '授权获取code失败,错误信息:'.json_encode($gv,JSON_UNESCAPED_UNICODE);
		}
	}
	
	//异步接收微信支付结果通知,自行编写数据处理
	public function notify(){
		
	}
	
	//获取支付参数
	public function payConfig(){
		$config=$this->sign('prepay_id值');
		return json($config);
	}
	
	//微信支付订单号查询
	public function cxTransactionId(){
		$id='420000***93';
		$resp = $this->APIv3()
		->chain('v3/pay/transactions/id/'.$id)
		->get(['query' => ['mchid' => $this->mchid]]);
		echo $resp->getBody();
	}
	
	//商户订单号查询
	public function cxOutTradeNo(){
		$out_trade_no='20221004***02';
		$resp = $this->APIv3()
		->chain('v3/pay/transactions/out-trade-no/'.$out_trade_no)
		->get(['query' => ['mchid' => $this->mchid]]);
		echo $resp->getBody();
	}
	
	//关闭订单
	public function closeOutTradeNo(){
		$out_trade_no='20221004***02';
		$resp = $this->APIv3()
		->chain('v3/pay/transactions/out-trade-no/'.$out_trade_no.'/close')
		->post(['json' => ['mchid' => $this->mchid]]);
		echo $resp->getBody(); //正常无返回数据
	}
	
	//=============================================================================
	
	//构造 APIv3 客户端实例
	private function APIv3(){
		$merchantId = $this->mchid; // 商户号
		// 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
		$merchantPrivateKeyFilePath = $this->certPath().$this->keyCert;
		$merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);
		// 「商户API证书」的「证书序列号」
		$merchantCertificateSerial = $this->serialNo;
		// 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名
		$platformCertificateFilePath = $this->certPath().$this->wechatpayCert;
		$platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
		// 从「微信支付平台证书」中获取「证书序列号」
		$platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath);
		// 构造一个 APIv3 客户端实例
		$instance = Builder::factory([
		    'mchid'      => $merchantId,
		    'serial'     => $merchantCertificateSerial,
		    'privateKey' => $merchantPrivateKeyInstance,
		    'certs'      => [$platformCertificateSerial => $platformPublicKeyInstance],
		]);
		return $instance;
	}
	
	//签名
	private function sign($prepay_id)
	{
		$merchantPrivateKeyFilePath = $this->certPath().$this->keyCert;
		$merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath);
		
		$params = [
		    'appId'     => $this->appid,
		    'timeStamp' => (string)Formatter::timestamp(),
		    'nonceStr'  => Formatter::nonce(),
		    'package'   => 'prepay_id='.$prepay_id,
		];
		$params += ['paySign' => Rsa::sign(
		    Formatter::joinedByLineFeed(...array_values($params)),
		    $merchantPrivateKeyInstance
		), 'signType' => 'RSA'];
		return $params;
	}
	
}


说明:以上的一些参数需要换成自己的,curlContents()需要自己编写,实际就是curl方式获取内容,如不会可以使用file_get_contents()。


支付调用:

//<a href="javascript:onBridgeReady();">支付订单</a>

function onBridgeReady() {
				$.get('/wx/pay/payConfig', function(sign){
					WeixinJSBridge.invoke('getBrandWCPayRequest', sign, function(res) {
					    if (res.err_msg == "get_brand_wcpay_request:ok") {
					        // 使用以上方式判断前端返回,微信团队郑重提示:
					        //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
							alert('支付成功');
					    }else{
							alert(JSON.stringify(res));
						}
					});
				})
			}

上一篇:windows系统下PHP版微信支付 wechatpay-php APIv3 平台证书下载(composer)

下一篇:PHP将十六进制颜色值转RGB/RGBA颜色值的方法

讨论数量:2

天涯网魂 3 杠 5 星2023-03-23 00:35:38

$gv=input('get.'); 就是获取code和state参数。

code说明:code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。

state说明:state值为toCode()里链接上state参数的值,重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节。

更多说明请参数官方文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html

BANG 0 杠 0 星2023-03-21 15:27:29

  1. $gv=input('get.'); //获取code、state参数都有些什么

请先登录再发表讨论。 2024-04-20

天涯网魂
3 杠 5 星
TA 的文章
TA 的随言
TA 的资源链