您好,欢迎来到惠州网站建设_网页设计制作公司_高端网站建设_模板建站_欣欣仿站



模板搜索:搜索
热门搜索: ALL房产金融汽车室内设计

微信支付v3的jsapi接口接入thinkphp6完整流程--回调部分 2023-06-29 14:39:37

当前位置: >首页>新闻列表>微信支付v3的jsapi接口接入thinkphp6完整流程--回调部分

上一篇,惠州网站建设基本就解决了微信支付v3接口,从下单到拉起支付的问题。现在我们就要探讨下,另一个问题了,那就是回调。支付之后,成功没成功呢??这个就要看微信支付。

        这里有个大坑,就是你要用你的商户证书去下载你的平台证书,而且,这里有个门槛,要用api来下载。一般没基础的朋友,到这里基本就卡住了。很难在往下走。这里我们先将证书下载下来。

        https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_1.shtml  这个找到平台证书部分。

        (图1)

        然后,点击进去。找到  证书下载工具 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/wechatpay5_1.shtml 。其实就是一个命令形式的下载命令。反正就是折腾,使劲的绕,将你绕晕。

        (图2)

        我们找到这个,php的工具,点击进去。到这里,大部分人都晕了。肯定晕了。

        看到这个网址,https://github.com/wechatpay-apiv3/wechatpay-php#%E5%A6%82%E4%BD%95%E4%B8%8B%E8%BD%BD%E5%B9%B3%E5%8F%B0%E8%AF%81%E4%B9%A6

        是不是跟我们之前拿来开发的代码的网址相同,其实就是同一个东西。当你想认真的去读取这个文档的时候,你又开始头晕了。因为他们上面说了一大堆废话,没错,就是废话。他又开始绕了,说什么同步请求,异步请求,说什么加密解密,巴拉巴拉的一大堆。然后知道文档最后面才说,怎么下载。其实好多人进来之后,都是希望直接看到怎么下载的。你给我整一大堆,到最后面不显眼的位置给你卸载怎么下带,而且篇幅很少。引不起别人的注意。

        (图3)


            对真正有用的就只有这个东西,其他的都可以不看。

            

        composer exec CertificateDownloader.php -- -k ${apiV3key} -m ${mchId} -f ${mchPrivateKeyFilePath} -s ${mchSerialNo} -o ${outputFilePath}


        这个东西要怎么用呢?


        看到这玩意,还是很懵啊。其实,这个我还没测试过。我用的是另一个方法。

php vendor/bin/CertificateDownloader.php -k 你的微信支付key v3的密钥 -m 你的商户号 -f /你的证书路径/apiclient_cert.p12 -s 你的商户证书序列号  -o /你用来保存平台证书的路径/zs2/

        其实这个也是很懵的。这个就是用php来执行你的下载api接口,当下载成功之后,会在 /zs2/路径上保存你的平台证书。


        这里也有两个大坑,第一,他不 给你准确的下载证书的代码,或者给你一个看不懂代码。让你使劲折腾。第二,他不告诉你怎么获得证书的序列号。你要自己去找。

        一般生成的时候有的看的。我们这里给大家一个只有证书的时候怎么查看证书的序列号。

        找到你的证书文件,双击这个文件

(图4)   输入你的商户号,默认的密码就是你的商户号。

        (图5)

                然后我们打开qq浏览器,这个你自己喜欢用其他浏览器也可以。

        

        (图6)

(图7)


        这里就可以获得证书的序列号了。到这里,我们还没开始写代码呢。但是,基本把我们绕晕了。更别说,官网上,他不告诉你要怎么操作了。惠州网站建设,今天就给大家做一个比较完整的流程。

        


        到这里了,我们继续写代码。这里,我们还是看文档把

        

use WeChatPay\Crypto\Rsa;
use WeChatPay\Crypto\AesGcm;
use WeChatPay\Formatter;

$inWechatpaySignature = '';// 请根据实际情况获取
$inWechatpayTimestamp = '';// 请根据实际情况获取
$inWechatpaySerial = '';// 请根据实际情况获取
$inWechatpayNonce = '';// 请根据实际情况获取
$inBody = '';// 请根据实际情况获取,例如: file_get_contents('php://input');

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

// 根据通知的平台证书序列号,查询本地平台证书文件,
// 假定为 `/path/to/wechatpay/inWechatpaySerial.pem`
$platformPublicKeyInstance = Rsa::from('file:///path/to/wechatpay/inWechatpaySerial.pem', 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);
    // print_r($inBodyResourceArray);// 打印解密后的结果
}

        看懂了吗?其实他已经笔记本将代码写清楚了。但是他不会告诉你,要怎么把代码放进你的程序中。上面就是他们原生的代码。下面,我们给出,我们整理过的代码。

        

public function wx3_notify(){
        $param=file_get_contents('php://input');
        $header=get_all_header();
       
        $inWechatpaySignature = $header['wechatpay-signature'];// 请根据实际情况获取
        $inWechatpayTimestamp = $header['wechatpay-timestamp'];// 请根据实际情况获取
        $inWechatpaySerial = $header['wechatpay-serial'];// 请根据实际情况获取
        $inWechatpayNonce = $header['wechatpay-nonce'];// 请根据实际情况获取
        $inBody =$param;// 请根据实际情况获取,例如: file_get_contents('php://input');
        $jiamihou=Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody);
        $apiv3Key = 'xxxxxxxxxx';// 在商户平台上设置的APIv3密钥
       
        // 根据通知的平台证书序列号,查询本地平台证书文件,
        // 假定为 `/path/to/wechatpay/inWechatpaySerial.pem`
        $platformPublicKeyInstance = Rsa::from('file:///zs/wechatpay.pem', 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);
           
            $up_payorder_arr=[
                    'transaction_id'=>$inBodyResourceArray['transaction_id'],
                    'success_time'=>$inBodyResourceArray['success_time'],
                    'paystatus'=>1
                ];
            $out_trade_no=$inBodyResourceArray['out_trade_no'];    
            //从数据库提取支付的单号,然后对比订单金额,相同才能更新订单状态,防止黑客篡改订单数据
            $db_payorder=Db::name("payorder")->where("out_trade_no",$out_trade_no)->find();
            $sql1=Db::name("payorder")->getLastsql();
            if($db_payorder['jine']*100==$inBodyResourceArray["amount"]["total"]){
                Db::startTrans();
                try{
                    $openid=$inBodyResourceArray["payer"]["openid"];
                    $data_users=Db::name("users")->where("open_id",$openid)->find();
                    if($data_users['vipendtime']==0){
                        $vipendtime=time()+365*24*3600;
                    }else{
                        $vipendtime=$data_users["vipendtime"]+365*24*3600;
                    }
                    $arr_users=[
                            "vipendtime"=>$vipendtime,
                            "niandu"=>date("Y",time()),
                            "ispay"=>1,
                            "last_payorder"=>$db_payorder['out_trade_no']
                        ];
                    $up_users=Db::name("users")->where("open_id",$openid)->save($arr_users);
                    $up_payorder=Db::name("payorder")->where("out_trade_no",$out_trade_no)->save($up_payorder_arr);
                    if($data_users && $up_users && $up_payorder){
                        Db::commit();
                    }else{
                        Db::rollback();
                    }
                }catch(\Exception $e){
                    Db::rollback();
                }
                print_r($inBodyResourceArray);// 打印解密后的结果
            }else{
                $mark='1订单信息不存在,2订单金额不对,微信支付回调金额是'.($inBodyResourceArray["amount"]["total"]/100);
                $up_payorder=Db::name("payorder")->where("out_trade_no",$out_trade_no)->save(["mark"=>$mark]);}
           
      }else{
          file_put_contents("./tongzhi.txt","timeOffsetStatus=>".$timeOffsetStatus.".....verifiedStatus=>".json_encode($verifiedStatus,true).PHP_EOL,FILE_APPEND);
      }
   
    }

        这里又有两个个大坑,超大的坑。

        

$param=file_get_contents('php://input');

这个地方要原封不动的搬过去,不要用tp6自带的参数接受,这个千万记得。

这里的证书要用我们刚下载到的平台证书,序列号用刚下载到的平台证书。


Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),

这个地方的第三个参数,你接收到的是什么类型就直接传过去,不要重新加工数据,不然直接报错。


        这里给一个get_all_header()的函数代码

        


  function get_all_header()
  {
    // 忽略获取的header数据。这个函数后面会用到。主要是起过滤作用
    $ignore = array('host','accept','content-length','content-type');    $headers = array();    //这里大家有兴趣的话,可以打印一下。会出来很多的header头信息。咱们想要的部分,都是‘http_'开头的。所以下面会进行过滤输出。/*    var_dump($_SERVER); exit;*/

    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;

  }



点击次数:172  更新时间:2023-06-29  【打印此页
下一条:惠州网站建设谈谈微信开发的接口配置信息url老是验证失败
上一条:微信支付v3的jsapi接口接入thinkphp6完整流程?
返回产品列表

扫一扫,添加微信

双十一活动季

1:签到7天,即可下载模板

2:开放包月,包年终身会员

3:包月会员,低至10元每月

4:包年会员,低至100元每年

5:终身会员,低至300元永久