tp6/thinkphp6实现微信小程序支付/微信支付v3版本,全部流程代码

前言:

微信小程序中的微信支付已经更新到了v3版本, 最近刚好做了一些这个需求, 感觉过程挺坎坷的, 特来分享给大家.

吐槽:

微信文档是真的让人头晕, v3文档中掺杂着v2的文档, 并且文档写的也不够清晰. 第一次写微信支付的人真的是太痛苦了, 简单的一个签名, 写个例子, 或者封装个方法就好, 非要让开发者自己琢磨,可伶我的头发, 吐槽完舒服多了, 下边进入正文.

支付原理:

后台调用微信统一下单api, 换取prepay_id, 然后把信息给小程序, 小程序调取微信支付.

期间麻烦的就是签名, 签名就是把很多信息加密后放到请求中.

注意事项:

微信文档中提供了实现了请求签名的生成和应答签名的验证, 但我引入工具后并没有成功, 所以就没有使用. 

工具链接https://github.com/wechatpay-apiv3/wechatpay-guzzle-middleware

v3支付回调解密需要使用api v3密钥.

代码:

    //微信支付
    public function config()
    {
        // 商户相关配置
        $merchantId = ''; // 商户号
        $merchantSerialNumber = ''; // 商户API证书序列号
        $filepath = "uploads/attach/2020/12/20201202/afba9ad6b68a66c144a36d9abbb8c52b.pem"; //私钥在本地的位置
        $file = file_get_contents($filepath);
        $mch_private_key = openssl_get_privatekey($file);

        $appid = ''; //小程序appid
        $out_trade_no = date('YmdHis', time()) . rand(1000, 9999);
        
        $data = [
            "appid" => $appid,
            "mchid" => $merchantId,
            "description" => '标题',
            'out_trade_no' => $out_trade_no,
            'notify_url' => '',  //回调地址
            "amount" => [
                "total" => 1,
                "currency" => "CNY"
            ],
            "payer" => [
                "openid" => "" //用户openid
            ]
        ];

        $timestamp = time();
        $nonce = date('YmdHis', time()) . rand(1000, 9999);
        $url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi';
        $url_parts = parse_url($url);
        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));

        $data = json_encode($data);
        $message = 'POST' . "\n" .
            $canonical_url . "\n" .
            $timestamp . "\n" .
            $nonce . "\n" .
            $data . "\n";

        openssl_sign($message, $signature, $mch_private_key, "sha256WithRSAEncryption");
        $sign = base64_encode($signature);
        $schema = 'WECHATPAY2-SHA256-RSA2048';
        $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', $merchantId, $nonce, $timestamp, $merchantSerialNumber, $sign);

        $header = "Authorization: " . $schema . " " . $token;

        $res = $this->http_post($url, $header, $data);
        $arr = json_decode($res, true);

        $time = time();
        $str = time() . round('1000', '9999');
        $prepay = 'prepay_id=' . $arr['prepay_id'];

        $message1 = $appid . "\n" .
            $time . "\n" .
            $str . "\n" .
            $prepay . "\n";

        openssl_sign($message1, $signature, $mch_private_key, "sha256WithRSAEncryption");
        $sign1 = base64_encode($signature);


        $data = array();
        $data['timeStamp'] = $time;
        $data['nonce'] = $str;
        $data['prepay_id'] = $arr['prepay_id'];
        $data['sign'] = $sign1;

        return app('json')->status('', $data);
    }


    function http_post($url, $header, $data)
    {
        $headers[] = "Accept:application/json";
        $headers[] = "Content-Type:application/json";
        $headers[] = "User-Agent:application/json";
        $headers[] = $header;

        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);  // 从证书中检查SSL加密算法是否存在
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        $tmpInfo = curl_exec($curl);
        //关闭URL请求
        curl_close($curl);
        return $tmpInfo;
    }

    //支付回调
    public function sharenotify()
    {
        $post = input('');
        $key = '';//商户平台设置的api v3 密码
        $text = base64_decode($post['resource']['ciphertext']);
        $str = sodium_crypto_aead_aes256gcm_decrypt($text,$post['resource']['associated_data'],$post['resource']['nonce'],$key);
        $res = json_decode($str, true);

        if($res['trade_state'] == 'SUCCESS'){
            //成功操作
        }
    }

 

  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值