PHP 微信支付APIV3 回调签名验证与回调通知

//回调首先是要接收头部信息,回调方法里最好保存回调信息用来调试 $response_body回调主体接收 : $response_body= file_get_contents(‘php://input’); $header的接收要注意,如果服务器不是Apche不要用getallheaders

//百度Nginx getallheaders 就可以找到替代方法

我用的CI框架$header = $this->input->request_headers();

TP应该是$this->request->header();具体看官方文档

在这里插入代码片
  	public
    function verify_wechatnotify($header, $response_body)
    {
          
   
    //$header 回调头部信息 //$response_body回调主体
        //获取平台证书
        $plat = $this->get_cert();
//        $path =  XX/Wechat/wxp_cert.pem;//平台证书
//        $plat_cert = file_get_contents($path);
//        $plat = json_decode($plat_cert, true);
        //serial_no平台证书序列号 //跟商户证书序列号不一样 不要搞混了
        $serial_no = $plat[data][0][serial_no];
        //验证回调头部信息中的平台证书序列号跟平台证书序列号是否一致
        if ($header[Wechatpay-Serial] != $serial_no) {
          
   
            return $data=[code=>0,msg=> 平台证书序列号不一致,签名验证不通过];
        }
        //解密平台证书序列
        $associatedData = $plat[data][0][encrypt_certificate][associated_data];
        $nonceStr = $plat[data][0][encrypt_certificate][nonce];
        $ciphertext = $plat[data][0][encrypt_certificate][ciphertext];
		//官方解密文档 https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/zheng-shu-he-hui-tiao-bao-wen-jie-mi
        $plat_cert_decrtpt = $this->decryptToString($associatedData, $nonceStr, $ciphertext);//平台证书解密后即生成公钥 //这个解密方法看官方文档https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/zheng-shu-he-hui-tiao-bao-wen-jie-mi
        //$pub_path = XX/Wechat/wxp_pub.pem;
//        file_put_contents($pub_path, $plat_cert_decrtpt);//平台公钥 //保存平台公钥 回调验签要用
        //$plat_cert_decrtpt = file_get_contents($pub_path);
        $pub_key = openssl_pkey_get_public($plat_cert_decrtpt);//平台公钥
        $Signature = $header[Wechatpay-Signature];
        $message = $header[Wechatpay-Timestamp] . "
" . $header[Wechatpay-Nonce] . "
" . $response_body . "
";
        $sign = base64_decode($Signature);
        $ok = openssl_verify($message, $sign, $pub_key, OPENSSL_ALGO_SHA256);//回调验签
        if ($ok == 1) {
          
   
//            return $this->error(1, 回调签名验证成功);
            return 1;
        } else {
          
   
            return false;
        }
    }

注意:商户证书跟平台证书是不一样的,我一开始一直拿商户证书来验签,浪费了时间。后面的获取平台证书序列了之后,一直不知道怎么生成平台公钥。其实解密之后就是公钥了

经验分享 程序员 微信小程序 职场和发展