之前提示 签名失败
{"errcode":40234,"errmsg":"invalid signature rid: 660bbf5d-42122766-7111a136"}
目前一直提示无效的加密
{"errcode":40235,"errmsg":"invalid encrypt rid: 660bbb51-3e9b99bb-5a26a227"}
目前感觉应该是签名通过了,但是加密不对,实在找不到问题,下面是所有相关代码,求大佬解答
这是加密的方法
public function getRequestParams($requestParams = [])
{
$timestamp = time();
$appid = get_setting('app_id');// 能拿到 appid
$nonce = rtrim(base64_encode(random_bytes(16)), '=');
$iv = random_bytes(12);
$AES256GCM = [
'sn' => '596f0ce97*************f25ad51ad',
'key' => 'ZDdlNDBl******************YjdiZTYwNWQ=',
];
$aad = $this->urlpath . "|" . $appid . "|" . $timestamp . "|" . $AES256GCM['sn'];
$requestParams = array_merge($requestParams, [
'_n' => $nonce,
'_appid' => $appid,
'_timestamp' => $timestamp,
]);
$requestParams = json_encode($requestParams);
$cipher = openssl_encrypt($requestParams, "aes-256-gcm", base64_decode($AES256GCM['key']), OPENSSL_RAW_DATA, $iv, $tag, $aad);
$iv = base64_encode($iv);
$data = base64_encode($cipher);
$authTag = base64_encode($tag);
$finalRequestParams = ["iv" => $iv, "data" => $data, "authtag" => $authTag];
// 这里结果能正常的打印出来
return ['timestamp' => $timestamp, 'request_params' => json_encode($finalRequestParams)];
}
这是签名的方法
public function getSignureHeaders($requestParams)
{
$RSAwithSHA256 = [
'sn' => '7a01f48****************f09ee3',
'private_key' => '-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAtcBZzC2x7hBMH/kWWn/XClEtGrzkgPyj2+CiCA0OogwAL6Q/
CSK2tahY3GFFIP/7zLd3OC16V4Gb93Hf+n9YDjjoExQgkEX06sBzwSwC8PFGAZPw
Jr5DEQGoKt64xydIkIAMHynNzltHInz7XD4fuJLxdi3CYitUd6pNATjax3a1OuO5
******************* 这里打一下码, 删除了很多行 *******************
liDw02EvRE3BWL3nqgEPt/PP1us+LUg3uOKOrOTD+w7hUPRaBIR41hz+9V+YszTs
oZk51Bq+/vZG7FoUXc7hB8cS9HANC2kOBU32Yf8fNWlpEMzg08N3yAw=
-----END RSA PRIVATE KEY-----'
];
$appid = get_setting('app_id'); // 这里可以拿到 appid
$rs_time = $requestParams['timestamp']; // 上一步加密时候的时间戳
$rs_data = $requestParams['request_params']; // 上一步最终加密的数据
$payload = "$this->urlpath\n$appid\n$rs_time\n$rs_data";
// 使用phpseclib3\Crypt\RSA(phpseclib V3)版本生成签名
$signature = RSA::loadPrivateKey($RSAwithSHA256['private_key'])
->withPadding(RSA::SIGNATURE_PSS)
->withHash('sha256')
->withMGFHash('sha256')
->sign($payload);
$signature = base64_encode($signature);
$checkLocalSig = $this->checkLocalSignature($requestParams, $signature); // 这里验签是可以通过的
if (!$checkLocalSig) {
throw new EStoreException('本地验签错误');
}
$headers['Wechatmp-Appid'] = $appid;
$headers['Wechatmp-TimeStamp'] = $requestParams['timestamp'];
$headers['Wechatmp-Signature'] = $signature;
return $headers;
}
private function checkLocalSignature(array $requestParams, string $signature)
{
$signature = base64_decode($signature);
$rsaPubKey = '-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtcBZzC2x7hBMH/kWWn/X
ClEtGrzkgPyj2+CiCA0OogwAL6Q/CSK2tahY3GFFIP/7zLd3OC16V4Gb93Hf+n9Y
******************* 这里打一下码 *******************
wLx6tzfnHvRz0vTf5KEoOvbk3UOUJ8xR/J753cHxh9MumN+4IUgoVF01ju64b95B
VQIDAQAB
-----END PUBLIC KEY-----';
$appid = get_setting('app_id'); // 这里能拿到 appid
$rs_time = $requestParams['timestamp']; // 上一步加密时候的时间戳
$rs_data = $requestParams['request_params']; // 上一步最终加密的数据
$payload = "$this->urlpath\n$appid\n$rs_time\n$rs_data";
return RSA::loadPublicKey($rsaPubKey)
->withPadding(RSA::SIGNATURE_PSS)
->withHash('sha256')
->withMGFHash('sha256')
->verify($payload, $signature);
}
请求的方法
/**
* 微信api 安全请求,自动加密数据,添加签名
*/
public function safeRequest($method = 'post', $url = '', $data = [])
{
$body = $data['body'] ?? [];
$query = $data['query'] ?? [];
$headers = $data['headers'] ?? [];
// 获取加密请求参数
$apiSignure = new ApiSignure($url); // 就是上面的方法的类名
$resultParams = $apiSignure->getRequestParams($body); // 上面的加密方法
$newBody = $resultParams['request_params']; // 加密的结果
// 获取签名 headers 参数
$signureHeaders = $apiSignure->getSignureHeaders($resultParams); // 上面的签名方法
$access_token = $this->getAccessToken(); // 获取 access_token
$result = \HttpClient::request($method, $url, [ // 这里用的是 guzzlehttp
'body' => $newBody,
'query' => array_merge(["access_token" => $access_token['access_token']], $query),
'headers' => array_merge(['Content-Type' => 'application/json'], $headers, $signureHeaders),
]);
print_r($result->getBody()->getContents());exit;
return $result;
}
调用方法
// 查询 门店 接口
$url = 'https://api.weixin.qq.com/cgi-bin/express/intracity/querystore';
$result = $this->safeRequest('post', $url, [
'body' => ['wx_store_id' => '400000*********4017'], // id 打码了
]);
把你的 \HttpClient::request() 换成下面这个试试
(new \GuzzleHttp\Client())->request("POST", $url, [ // 这里用的是 guzzlehttp 'body' => $newBody, 'query' => array_merge(["access_token" => $access_token['access_token']], $query), 'headers' => array_merge(['Content-Type' => 'application/json'], $headers, $signureHeaders), ] );