php接入jsapi微信支付v3——真.踩坑经历

提前准备

  • 下载微信支付官方sdk 压缩包
  • 商户api证书:获取方式https://kf.qq.com/faq/161222NneAJf161222U7fARv.html
  • 商户私钥:获取证书时,生成的apiclient_key.pem文件
  • 商户证书序列号——商户平台查看
  • 商户号——商户平台查看
  • 微信支付平台证书
    获取方式
    运行 sdk 包中的CertificateDownloader.php 文件
php -f ./bin/CertificateDownloader.php -- -k ${apiV3key} -m ${mchId} -f ${mchPrivateKeyFilePath} -s ${mchSerialNo} -o ${outputFilePath}

参数说明

  -m, --mchid=<merchantId>   商户号
  -s, --serialno=<serialNo>  商户证书的序列号——商户平台查看
  -f, --privatekey=<privateKeyFilePath>
                             apiclient_key.pem文件的位置
  -k, --key=<apiV3key>       ApiV3Key
  -o, --output=[outputFilePath]
                             下载成功后保存证书的路径,可选参数,默认为临时文件目录夹
  -u, --baseuri=[baseUri]    接入点,默认为 https://api.mch.weixin.qq.com/
  -V, --version              Print version information and exit.
  -h, --help                 Show this help message and exit.

安装微信支付sdk

composer require wechatpay/wechatpay

step1:获取支付实例

// 商户号
            $merchantId = env('WECHAT_PAYMENT_MCH_ID');

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

            // 「商户API证书」的「证书序列号」
            $merchantCertificateSerial = env('WECHAT_PAYMENT_SER_NO');
      
            // 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名
            //通过CertificateDownloader.php获取的问价位置
            $platformCertificateFilePath = '7E58755DC38BDB33CFDEA564E6A9A.pem';
            $platformPublicKeyInstance = Rsa::from(file_get_contents($platformCertificateFilePath), Rsa::KEY_TYPE_PUBLIC);

            // 从「微信支付平台证书」中获取「证书序列号」
            $platformCertificateSerial = PemUtil::parseCertificateSerialNo(file_get_contents($platformCertificateFilePath));

             $payapp  = Builder::factory([
                'mchid'      => $merchantId,
                'serial'     => $merchantCertificateSerial,
                'privateKey' => $merchantPrivateKeyInstance,
                'certs'      => [
                    $platformCertificateSerial => $platformPublicKeyInstance,
                ],
            ]);;

step2:获取预订单id

 $notify_url = 'https://api.xinchengxinwuye.com/api/wechat/order-notify';

            //$ordernumber = 'JF' . date("YmdHis") . time() . rand(10000, 99999);

            $resp =  $payapp
                ->chain('v3/pay/transactions/jsapi')
                ->post(['json' => [
                    'mchid'        => env('WECHAT_PAYMENT_MCH_ID'),
                    'out_trade_no' => $param['ordernumber'],
                    'appid'        => env('WECHAT_PAYMENT_APPID'),
                    'description'  => 'Image形象店-深圳腾大-QQ公仔',
                    'notify_url'   => $notify_url,
                    'amount'       => [
                        'total'    => $param['total'],
                        'currency' => 'CNY'
                    ],
                    'payer' => [
                        'openid' => $param['openid']//"oCItw6bCmDtAdIJf2HT4gE2zT2os"
                    ]
                ]
                    ]);

//            echo $resp->getStatusCode(), PHP_EOL;
//            echo $resp->getBody(), PHP_EOL;
           // $this->GetWxPayConfig(json_decode($resp->getBody(),true)['prepay_id']);
            return json_decode($resp->getBody(),true);

step2 获取支付参数

 $merchantPrivateKeyFilePath ='apiclient_key.pem';

        $merchantPrivateKeyInstance = Rsa::from(file_get_contents($merchantPrivateKeyFilePath));

        $timeStamp = (string)Formatter::timestamp();

        $nonceStr = Formatter::nonce();

        $params = [
            'appId'     => env('WECHAT_PAYMENT_APPID'),
            'timeStamp' =>$timeStamp,
            'nonceStr'  => $nonceStr,
            'package'   => 'prepay_id='.$prey_id,//step2中获取的预订单id
           
        ];
        $params += ['sign' => Rsa::sign(
            Formatter::joinedByLineFeed(...array_values($params)),
            $merchantPrivateKeyInstance
        ), 'signType' => 'RSA'];

// 用时间戳和随机字符串计算signature
//url是前端传过来的url 通过post 或request接受
        $signature = get_jsapi_signature($url,$timeStamp,$nonceStr);

        $package =  'prepay_id='.$prey_id;

        $wxconfig = [
            'nonceStr'  => $nonceStr,
            "package"=> $package,
            "prepay_id"=> $prey_id,
            'sign'=>$params['sign'],
            "signature"=> $signature,
            'timestamp' =>intval($timeStamp),
        ];

        return $wxconfig;

step4 用step3中的时间戳和随机字符串计算signature

function get_service_access_token()
{
    $redis_service_access_token = Cache::get('wechat_service_access_token');
    if ($redis_service_access_token) {
        return $redis_service_access_token;
    }

    $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='
        . env("WECHAT_OFFICIAL_ACCOUNT_APPID")
        . '&secret='
        . env("WECHAT_OFFICIAL_ACCOUNT_SECRET");

    $res = request_get($url);

    $errcode = json_decode($res,true);

    if (!isset($errcode['access_token'])) {
        return False;
    }else{
        $access_token = $errcode['access_token'];

        Cache::set('wechat_service_access_token', $access_token, 7200);
        return $access_token;
    }

}
function get_jsapi_ticke
t()
{
    $redis_jsapi_ticket = Cache::get('wechat_service_jsapi_ticket');
    if ($redis_jsapi_ticket) {
        return $redis_jsapi_ticket;
    }

    $access_token = get_service_access_token();

    $url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' . $access_token . '&type=jsapi';

    $res = json_decode(request_get($url),true);

    if ($res['errcode'] and $res['errcode'] != 0) {
        return False;
    }

    $ticket = $res['ticket'];

    Cache::set('wechat_service_jsapi_ticket', $ticket, 7200);

    return $ticket;

}
function get_jsapi_sig
nature($url,$timestamp,$noncestr)
{
    $jsapi_ticket = get_jsapi_ticket();
    //$timestamp = time();
   // $noncestr = md5(time() . round(10000, 9999));
    $string = 'jsapi_ticket=' . $jsapi_ticket
        . '&noncestr=' . $noncestr
        . '&timestamp='
        . $timestamp . 'url=' . $url;
    $signature = sha1($string);
    return $signature;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值