1. 获取商户API证书
登录商户平台【API安全】->【API证书】->【查看证书】,可查看商户API证书序列号。
商户API证书和微信支付平台证书均可以使用第三方的证书解析工具,查看证书内容。或者使用openssl命令行工具查看证书序列号。
/*
* 加载私钥
* Read private key from file
*
* @param string $filepath PEM encoded private key file path
*
* @return resource|bool Private key resource identifier on success, or FALSE on error
*/
public static function getPrivateKey($filepath) {
return openssl_get_privatekey(file_get_contents($filepath));
}
2. 调用支付API生成签名生成
商户可以按照下述步骤生成请求的签名。
1. 构造签名串
我们希望商户的技术开发人员按照当前文档约定的规则构造签名串。微信支付会使用同样的方式构造签名串。如果商户构造签名串的方式错误,将导致签名验证不通过。下面先说明签名串的具体格式。
签名串一共有五行,每一行为一个参数。行尾以 \n
(换行符,ASCII编码值为0x0A)结束,包括最后一行。如果参数本身以\n
结束,也需要附加一个\n
。
HTTP请求方法\n
URL\n
请求时间戳\n
请求随机串\n
请求报文主体\n
第一步,获取HTTP请求的方法(GET
,POST
,PUT
)等
GET
第二步,获取请求的绝对URL,并去除域名部分得到参与签名的URL。如果请求中有查询参数,URL末尾应附加有'?'和对应的查询字符串。
/v3/certificates
第三步,获取发起请求时的系统当前时间戳,即格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数,作为请求时间戳。微信支付会拒绝处理很久之前发起的请求,请商户保持自身系统的时间准确。
$ date +%s
1554208460
第四步,生成一个请求随机串,可参见生成随机数算法。这里,我们使用命令行直接生成一个。
$ hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random
593BEC0C930BF1AFEB40B4A08C8FB242
第五步,获取请求中的请求报文主体(request body)。
- 请求方法为GET时,报文主体为空。
- 当请求方法为POST或PUT时,请使用真实发送的JSON报文。
- 图片上传API,请使用meta对应的JSON报文。
- 接口参数 json格式
$url3 = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
// 微信 V3 退款
$mch_private_key = openssl_get_privatekey(file_get_contents($api_key));//私钥
$serial_no = '**************************'; // 序列号
// 生成token 验签
$http_method = 'POST';
$timestamp = time();//时间戳
$nonce = $str_32;//随机串
$body = json_encode($data_record2); // 接口参数
$url_parts = parse_url($url3); # 接口地址
$canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ?"?${url_parts['query']}" : ""));
$message = $http_method."\n".
$canonical_url."\n".
$timestamp."\n".
$nonce."\n".
$body."\n";
3.计算签名值
openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
$sign = base64_encode($raw_sign);
$schema = 'WECHATPAY2-SHA256-RSA2048';
$token =sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
$mch_id, $nonce, $timestamp, $serial_no, $sign);
$headerArray = [
'Accept: application/json',
'User-Agent: */*',
'Content-Type: application/json; charset=utf-8',
"Authorization: {$schema} {$token}",
"Wechatpay-Serial:{$serial_no}"
];
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url3);
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, json_encode($data_record2));
curl_setopt($curl,CURLOPT_HTTPHEADER,$headerArray);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output3 = curl_exec($curl);
$output3 = json_decode($output3,true);