前言
各位小伙伴们大家好啊,最近微信更新了微信支付V3版本。本人也是有幸接到了支付升级的任务,本篇将记录下计算签名的详细过程,以免大家看官方文档有点丈二和尚摸不着头脑。
废话不多说先上才艺
<?php
class Authorization
{
public function get($url, $mch_id, $http_method, $body)
{
$nonce = md5(uniqid());
$timestamp = time();
$serial_no = env('WECHATPAY_V3_SERIAL_NO');
$url_parts = parse_url($url);
$canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
$message = strtoupper($http_method) . "\n" .
$canonical_url . "\n" .
$timestamp . "\n" .
$nonce . "\n" .
$body . "\n";
$path = storage_path('app/') . "CA/apiclient_key.pem";
$mch_private_key = openssl_get_privatekey(file_get_contents($path));
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);
return $schema . $token;
}
}
画重点
$url 请求的接口url
$mch_id 微信支付商户ID
$http_method 接口的请求方法 (!!!转换成大写!!!)
$nonce = md5(uniqid()); 随机字符串
$timestamp = time(); 当前时间戳
$serial_no = env('WECHATPAY_V3_SERIAL_NO'); 图 1-1
图 1-1
拨云见雾
Authorization: <schema> <token>
Authorization: WECHATPAY2-SHA256-RSA2048 mchid="1427527***",nonce_str="93de037816b32b828713a6b7b515ce07",timestamp="1597760164",serial_no="3C282195D6ADE6D6F821A984B36BF032D199***",signature="nbEiZgejeaAEWrzpES6RHzr5JG7Qqkt5gDXY6C9MJP2...jzvvuYwpgJrnWFIgOcA9zLi5/L+HLsQFqoIVaa50AqWoEvG49MSA5dZ7FF+rgL3FiYUQ=="
小试牛刀
# 获取证书
$auth = new Authorization();
$config = config("wechat-v3");
$mch_id = Arr::get($config, 'mch_id', 0);
$request_url = 'https://api.mch.weixin.qq.com/v3/certificates';
$authorization = $auth->get($request_url, $mch_id, "GET", '');
try{
$client = new Client();
$info = $client->request('get', $request_url, [
'headers' => [
'Authorization' => $authorization,
'Content-type' => 'application/json',
'Accept' => 'application/json'
]
]);
}catch (\GuzzleHttp\Exception\ClientException $exception){
$response = $exception->getResponse()->getBody()->getContents();
return json_decode($response, true);
}
return $info->getBody()->getContents();
# return
{
"data": [
{
"effective_time": "2020-08-14T15:25:22+08:00",
"encrypt_certificate": {
"algorithm": "AEAD_AES_256_GCM",
"associated_data": "certificate",
"ciphertext": "1FuwEnWi3eJsXaDMVy5ECeaHQvLMyaA3HGcwoG*****",
"nonce": "c43203286ed2"
},
"expire_time": "2025-08-13T15:25:22+08:00",
"serial_no": "2C2E956394F3294651106ADBD27FF4FE5CB7****"
}
]
}
结语
不识庐山真面目,只缘身在此山中。
代码写不下去的时候,适当地放松自己,找同事来看看,出去转一圈,兴许就能豁然开朗!