当前位置:   article > 正文

php对接微信H5支付 wechatpay-apiv3 / wechatpay-php 下单和回调

wechatpay-php

1、下载官方提供的sdk(https://github.com/wechatpay-apiv3/wechatpay-php)
2、创建订单

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

   /**
     * @param $out_trade_no 订单号
     * @param $total_fee 支付金额
     * @param $attach 扩展字段
     * @param $body 描述
     * @return mixed
     */
    public static function h5($out_trade_no, $total_fee, $attach, $body){
        // 商户号
        $merchantId = 'xxx';

        // 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
        $merchantPrivateKeyFilePath = 'file://这里写apiclient_key.pem文件地址绝对路径';
        $merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);

       // 「商户API证书」的「证书序列号」
        $merchantCertificateSerial = 'xxx';

       // 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名(php需要用工具或者时接口获取,见我的另一篇文章记录)
        $platformCertificateFilePath = 'file://这里写平台证书地址绝对路径';
        $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,
            ],
        ]);

        try {
            $resp = $instance
                ->chain('v3/pay/transactions/h5')
                ->post(['json' => [
                    'mchid'        => '',
                    'attach'        => $attach,
                    'out_trade_no' => $out_trade_no,
                    'appid'        => '',
                    'description'  => $body,
                    'notify_url'   => '',
                    'amount'       => [
                        'total'    => $total_fee,
                        'currency' => 'CNY'
                    ],
                    'scene_info' => [
                        'payer_client_ip' => '',
                        'h5_info' => [
                            'type' => 'Wap',
                        ],
                    ],
                ]]);

            $res = json_decode($resp->getBody(),true);
            return $res['h5_url']; // 返回给前端,前端在浏览器跳转该地址就可以唤起微信支付
        } 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;
        }
    }
/**
     * 微信支付回调
     * @param $input 获取的body数据
     * @param $header 获取的请求头数据
     * @return bool
     */
    public function notify($input,$header)
    {
        $inWechatpaySignature = $header['wechatpay-signature'];// 请根据实际情况获取
        $inWechatpayTimestamp = $header['wechatpay-timestamp'];// 请根据实际情况获取
        $inWechatpaySerial = $header['wechatpay-serial'];// 请根据实际情况获取
        $inWechatpayNonce = $header['wechatpay-nonce'];// 请根据实际情况获取
        $inBody = $input;// 请根据实际情况获取,例如: file_get_contents('php://input');

        $apiv3Key = '';// 在商户平台上设置的APIv3密钥

         // 根据通知的平台证书序列号,查询本地平台证书文件,
        // 假定为 `/path/to/wechatpay/inWechatpaySerial.pem`
        $platformPublicKeyInstance = Rsa::from('file://平台证书地址', Rsa::KEY_TYPE_PUBLIC);

        // 检查通知时间偏移量,允许5分钟之内的偏移
        $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);

        $verifiedStatus = Rsa::verify(
        // 构造验签名串
            Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
            $inWechatpaySignature,
            $platformPublicKeyInstance
        );
        if ($timeOffsetStatus && $verifiedStatus) {
            // 转换通知的JSON文本消息为PHP Array数组
            $inBodyArray = (array)json_decode($inBody, true);
            // 使用PHP7的数据解构语法,从Array中解构并赋值变量
            ['resource' => [
                'ciphertext'      => $ciphertext,
                'nonce'           => $nonce,
                'associated_data' => $aad
            ]] = $inBodyArray;
            // 加密文本消息解密
            $inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
            // 把解密后的文本转换为PHP Array数组
            $inBodyResourceArray = (array)json_decode($inBodyResource, true);
            if ($inBodyResourceArray['trade_state'] == 'SUCCESS') {
                // 这里写业务逻辑

                $result = [
		            'code'=>'SUCCESS',
		            'message'=>'成功',
        			];
        		echo json_encode($result);exit;
            }

        }

    }
    // 获取header头的方法
	public function get_all_header()
    {
        // 忽略获取的header数据。这个函数后面会用到。主要是起过滤作用
        $ignore = array('host','accept','content-length','content-type','connection','accept-encoding');    $headers = array();    //这里大家有兴趣的话,可以打印一下。会出来很多的header头信息。咱们想要的部分,都是‘http_'开头的。所以下面会进行过滤输出。/*    var_dump($_SERVER);
        foreach($_SERVER as $key=>$value){      if(substr($key, 0, 5)==='HTTP_'){      //这里取到的都是'http_'开头的数据。
            //前去开头的前5位
            $key = substr($key, 5);        //把$key中的'_'下划线都替换为空字符串
            $key = str_replace('_', ' ', $key);        //再把$key中的空字符串替换成‘-’
            $key = str_replace(' ', '-', $key);        //把$key中的所有字符转换为小写
            $key = strtolower($key);    //这里主要是过滤上面写的$ignore数组中的数据
            if(!in_array($key, $ignore)){          $headers[$key] = $value;
            }
        }
        }//输出获取到的header
        return $headers;

    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/122931
推荐阅读
相关标签
  

闽ICP备14008679号