收藏
回答

签名工具签名验证通过,但是小程序报签名错误?

签名工具签名验证通过,但是小程序里面报{code: "SIGN_ERROR", detail: {…}, message: "签名错误,请检查后再试"}?

回答关注问题邀请回答
收藏

2 个回答

  • 豚鼠公社
    豚鼠公社
    2023-02-05

    已解决,贴下解决方案,方便后来人。

    1、对 prepay_id 的获取从小程序改到了服务端,怀疑是Authorization的秘钥加密时间和提交请求的时间戳不一致;

    2、另外不是加密字符串中不是 /v3/certificates 而是 /v3/pay/transactions/jsapi。回头重新看了下文档(获取请求的绝对URL ,也就是https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi,并去除域名部分得到参与签名的URL。如果请求中有查询参数,URL末尾应附加有'?'和对应的查询字符串),这点容易混淆忽略过去。

    3、需要加密的字符串中的body内容。即请求的json参数内容,也就是下面的 $data。不能随便填。

    下面贴代码:

    $privateKeyFilePath = 'apiclient_key.pem';  
    extension_loaded('openssl') or die('php需要openssl扩展支持');  
    (file_exists($privateKeyFilePath) )  or die('密钥或者公钥的文件路径不正确');  
    $privateKey = openssl_pkey_get_private(file_get_contents($privateKeyFilePath));  
    
    $openid = '';
    $appid = '';
    $mchid = '';
    $description = '';
    $out_trade_no = date('Ymd') . str_pad(mt_rand(1, 99999), 10, '0', STR_PAD_LEFT);
    $notify_url = '';
    $money = '';
     
    $url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi';
    $data = '{"mchid":"'.$mchid.'","out_trade_no":"'.$out_trade_no.'","appid":"'.$appid.'","description":"'.$description.'","notify_url":"'.$notify_url.'","amount":{"total":'.$money.',"currency":"CNY"},"payer": {"openid":"'.$openid.'"}}';
    
    $serial_no = '';
     
    $url_parts = parse_url($url);
    $timestamp = time();
    $nonce = $out_trade_no;
    $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
    $message = "POST".chr(10).$canonical_url.chr(10).$timestamp.chr(10).$nonce.chr(10).$data.chr(10);
    
    openssl_sign($message, $raw_sign, $privateKey, 'sha256WithRSAEncryption');
    $sign = base64_encode($raw_sign);
    $schema = 'WECHATPAY2-SHA256-RSA2048';
    $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', $mchid, $nonce, $timestamp, $serial_no, $sign);
     
    $ret = posturl($url,$data,$schema.' '.$token); 
    $json = json_encode($ret,JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    echo $json;   //输出返回的prepay_id
    
    function posturl($url, $data, $Authorization){
        $headerArray =array("Content-type:application/json;charset='utf-8'","Accept:application/json","Authorization:".$Authorization,"User-Agent:".$_SERVER['HTTP_USER_AGENT']);
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,FALSE);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl,CURLOPT_HTTPHEADER,$headerArray);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }
    
    2023-02-05
    有用
    回复
  • Jianbo
    Jianbo
    发表于小程序端
    2023-02-02

    支付的 api 需要服务端程序调用,你这是小程序里调用的。

    2023-02-02
    有用
    回复 1
    • 豚鼠公社
      豚鼠公社
      2023-02-02
      虽然这个有安全性问题,但是请求头也不应该报签名错误吧?
      2023-02-02
      回复
登录 后发表内容