记录一下PHP使用微信小程序支付

记录一下PHP使用微信小程序支付V3版本经历

官方文档:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_0.shtml

请详细查看文档中小程序支付接入前准备(https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_1.shtml)

注意:配置好需要将已生成的证书下载放在自己的项目中

示例:

配置好后需要拿到以下参数:

  1. 小程序appid
  2. 商户号
  3. 微信支付API证书序列号
  4. 微信支付v3密钥(回调时需要)

支付大概流程:

1.小程序端提交订单

小程序端提交的订单就不做示例了

2.后端根据订单信息生成预订单通过小程序JSAPI下单返回预支付交易会话标识

php 复制代码
	  private $appid = '**********';//应用ID
    private $mchid = '************';//商户号
    private $serial_number = '***********';//微信支付API证书序列号
    private $v3_key = '***********';//微信支付v3密钥

    public function placeOrder()
    {
        //通过jsapi下单所需参数
        $pay_info = [
            'out_trade_no' => '',//自己平台的订单号
            'total' => '',//付款金额,单位为分
            'openid' => '',//付款用户的openid
        ];
        // 1、请求参数
        $postJson = [
            "appid" => $this->appid,
            "mchid" => $this->mchid,
            "description" => '商品信息',//商品信息
            "out_trade_no" => $pay_info['out_trade_no'],//自己平台的订单号
            //用于接收微信支付结果的回调接口(注意回调接口不能加什么是否登录验证信息,需要外网能直接访问的地址)
            "notify_url" => 'https://ffe8-113-249-28-138.ngrok-free.app/api/Pay/payBack',
            "amount" => [
                "total" => $pay_info['total'] //付款金额,单位为分
            ],
            "payer" => [
                "openid" => $pay_info['openid'],//付款用户的openid
            ],
        ];
        $time = time();
        // 2、头部签名
        $url = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
        $urlarr = parse_url($url);
        $data = json_encode($postJson);
        $noncestr = randstrpay();//签名所需随机字符串
        $key = $this->getSign($data, $urlarr['path'], $noncestr, $time);//签名

//        $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"', '商户号', '微信支付API证书序列号', $noncestr, $time, $key);//头部信息
        $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"', $this->mchid, $this->serial_number, $noncestr, $time, $key);//头部信息
        $header = [
            'Content-Type:' . 'application/json; charset=UTF-8',
            'Accept:application/json',
            'User-Agent:*/*',
            'Authorization: WECHATPAY2-SHA256-RSA2048 ' . $token
        ];
        $resp = postCurl($url, $data, $header);
        $resp = json_decode($resp, true);
        if (isset($resp['prepay_id'])) {
            $return = [
                "appId" => $this->appid,
                "timeStamp" => $time,
                'prepay_id' => 'prepay_id=' . $resp['prepay_id'],
                'paySign' => $this->getWechartSign('wxf1edd999226319ea', $time, $noncestr, 'prepay_id=' . $resp['prepay_id']),//微信支付(小程序)签名
                "nonceStr" => $noncestr
            ];
            return $return;
        } else {
            //apiReturn是我自己封装的返回的json格式
            apiReturn(303, '支付订单创建失败!', $resp);
        }

    }


    /**
     *Api Name:生成微信支付签名
     *Developer:TH
     *Time:2024年05月30日 09:31
     */
    public function getSign($data = [], $url, $randstr, $time)
    {
        $str = "POST" . "\n" . $url . "\n" . $time . "\n" . $randstr . "\n" . $data . "\n";
        $key = file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/apiclient_key.pem');//在商户平台下载的秘钥
        $str = $this->getSha256WithRSA($str, $key);
        return $str;
    }


    /**
     *Api Name:调起支付的签名
     *Developer:TH
     *Time:2024年05月30日 09:32
     */
    public function getWechartSign($appid, $timeStamp, $noncestr, $prepay_id)
    {
        $str = $appid . "\n" . $timeStamp . "\n" . $noncestr . "\n" . $prepay_id . "\n";

        $key = file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/apiclient_key.pem');
        $str = $this->getSha256WithRSA($str, $key);
        return $str;
    }


    public function getSha256WithRSA($content, $privateKey)
    {
        $binary_signature = "";
        $algo = "SHA256";
        openssl_sign($content, $binary_signature, $privateKey, $algo);
        $sign = base64_encode($binary_signature);
        return $sign;
    }

JSAPI下单成功后会返回以下参数

3.小程序端根据预支付交易会话标识 调起支付API

小程序端示例:

php 复制代码
		// 模拟支付
		pay: function() {
			
			wx.requestPayment
			(
				{
					"timeStamp": "1718348859",
					"nonceStr": "R5AK20MQQZIZFMAD170J2124CE6WLJ1J",
					"package": "prepay_id=wx14150738126675942c8a76a8a13b8a0000",
					"signType": "RSA",
					"paySign": "q2ZVp5DUpYSxgUu5aCNrlLj7m81mL9GDMw0TE2EkYvqAI29/jFKP9FctE0f78S+qs1p3STaHKpOnHc6gy0K4FOW7CO8tER00FlNyxVYwhTOV0SsGwLaKV239iizt3iYVQS2VkfwdyH3mTn27PHyBdww1LvDLLlXdLCmdrcE4OM5VGemAHgJuPR0PcZC19ufweC8ALoKF/FHYra9uX3Rbph1LVeu6VpB2nCDO6fVR5TpY27cehJY7tGemar/f+9NAMvmgIZOpFps4kUNOV1wqcDjAkTJYIb5LmVdgiZbUwJYz9LCxvXEjXpsrj9VvTrwjyLc1Ifvj4JPzNlfIrf0fzw==",
					"success":function(res){
						console.log(res);
					},
					"fail":function(res){},
					"complete":function(res){}
				}
			)
			},

4.支付成功后通过第二步设置的回调地址进行支付成功后订单逻辑支付

示例:

php 复制代码
    /**
     *Api Name:支付回调结果处理
     *Developer:TH
     *Time:2024年06月14日 10:06
     */
    public function payBack()
    {
        $xml = file_get_contents('php://input');//微信回调返回的结果

        $post = json_decode($xml, true);

        $text = base64_decode($post['resource']['ciphertext']);
        //对加密数据解密 注:sodium_crypto_aead_aes256gcm_decrypt需要你运行的PHP版本>=7.1
        $str = sodium_crypto_aead_aes256gcm_decrypt($text, $post['resource']['associated_data'], $post['resource']['nonce'], '微信支付v3密钥');
        $res = json_decode($str, true);
        if ($res['trade_state'] == 'SUCCESS') {
            //按照自己的需求,进行订单逻辑处理
            
        } else {
            apiReturn(303, '发生未知错误,请联系管理员处理');
        }
    }

小程序支付到这基本就算完成了,中途发生问题可以百度解决,实际请按自己的需求进行代码完善

相关推荐
拉不动的猪9 小时前
移动端调试工具VConsole初始化时的加载阻塞问题
前端·javascript·微信小程序
JaguarJack13 小时前
为什么 PHP 闭包要加 static?
后端·php·服务端
ServBay2 天前
垃圾堆里编码?真的不要怪 PHP 不行
后端·php
用户962377954482 天前
CTF 伪协议
php
WangHappy3 天前
不写 Canvas 也能搞定!小程序图片导出的 WebView 通信方案
前端·微信小程序
小时前端3 天前
微信小程序选不了本地文件?用 web-view + H5 一招搞定
前端·微信小程序·uni-app
icebreaker4 天前
Weapp-vite:原生模式之外,多一种 Vue SFC 选择
前端·vue.js·微信小程序
icebreaker4 天前
重走 Vue 长征路 Weapp-vite:编译链路与 Wevu 运行时原理拆解
前端·vue.js·微信小程序
BingoGo4 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack4 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端