已解决,贴下解决方案,方便后来人。 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; }
签名工具签名验证通过,但是小程序报签名错误?签名工具签名验证通过,但是小程序里面报{code: "SIGN_ERROR", detail: {…}, message: "签名错误,请检查后再试"}? [图片][图片]
2023-02-05