php对接微信H5支付 wechatpay-apiv3 / 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;

    }

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值