PHP实现API接口SHA256签名返回Secret key does not exist问题咨询
问题修复方案
核心错误点
- 签名模式逻辑混淆:你请求头声明使用
HmacSHA256签名,但代码中混用RSA非对称签名逻辑,两种签名方式的密钥要求、计算逻辑完全不同,参数不匹配直接触发密钥校验失败 - 待签名预处理字符串计算错误:文档要求MD5计算后得到大写十六进制字符串,你额外对MD5结果做了base64编码,完全不符合接口要求
- RSA签名函数逻辑错误:
- 对MD5结果额外做了一次SHA256哈希,文档要求直接对MD5大写十六进制字符串做RSA-SHA256签名,无需二次哈希
- 签名结果先转十六进制再做base64,正确逻辑是直接对二进制签名结果做base64编码
- HmacSHA256签名函数逻辑完全错误:Hmac是对称签名算法,不需要调用RSA类,你现有逻辑是用RSA加密密钥本身,和Hmac签名没有任何关系
- 密钥格式不匹配:如果使用RSA模式,
secret需要传入完整的PEM格式私钥(通常是多行以-----BEGIN RSA PRIVATE KEY-----开头的长字符串),你填写的短字符串密钥大概率是Hmac对称签名使用的密钥,应该使用Hmac模式
修复后代码
场景1:使用HmacSHA256签名(匹配你当前请求头配置)
<?php $echostr = "SS...AD"; $api_key = "17...e0"; $secret = "EB....D"; // Hmac对称密钥 $timeStamp = time(); // 补充时间戳赋值 // 1. 拼接待签名字符串 $parameters = "api_key=".$api_key."&echostr=".$echostr."&signature_method=HmacSHA256×tamp=".$timeStamp; // 2. 计算MD5大写十六进制(符合文档要求) $md5Str = strtoupper(md5($parameters)); // 3. 计算HmacSHA256签名,结果base64编码 $sign = base64_encode(hash_hmac("sha256", $md5Str, $secret, true)); // 发起请求 $cURLConnection = curl_init('你的接口地址'); curl_setopt($cURLConnection, CURLOPT_POSTFIELDS, http_build_query([ 'sign' => $sign, 'api_key' => $api_key ])); curl_setopt($cURLConnection, CURLOPT_HTTPHEADER, [ 'Content-Type: application/x-www-form-urlencoded', 'timestamp: '.$timeStamp, 'signature_method: HmacSHA256', 'echostr: '.$echostr ]); curl_setopt($cURLConnection, CURLOPT_RETURNTRANSFER, true); $apiResponse = curl_exec($cURLConnection); curl_close($cURLConnection); var_dump($apiResponse);
场景2:使用RSA签名(需对应修改请求头)
<?php use phpseclib\Crypt\RSA; // 确认已安装phpseclib依赖库 $echostr = "SS...AD"; $api_key = "17...e0"; $secret = "-----BEGIN RSA PRIVATE KEY----- 你的完整RSA私钥内容 -----END RSA PRIVATE KEY-----"; // 必须为完整PEM格式私钥 $timeStamp = time(); // 1. 拼接待签名字符串 $parameters = "api_key=".$api_key."&echostr=".$echostr."&signature_method=RSA×tamp=".$timeStamp; // 2. 计算MD5大写十六进制 $md5Str = strtoupper(md5($parameters)); // 3. RSA-SHA256签名后base64编码 $rsa = new RSA(); $rsa->setHash("sha256"); $rsa->setSignatureMode(RSA::SIGNATURE_PKCS1); $rsa->loadKey($secret); $signature = $rsa->sign($md5Str); $sign = base64_encode($signature); // 发起请求 $cURLConnection = curl_init('你的接口地址'); curl_setopt($cURLConnection, CURLOPT_POSTFIELDS, http_build_query([ 'sign' => $sign, 'api_key' => $api_key ])); curl_setopt($cURLConnection, CURLOPT_HTTPHEADER, [ 'Content-Type: application/x-www-form-urlencoded', 'timestamp: '.$timeStamp, 'signature_method: RSA', // 签名模式改为RSA 'echostr: '.$echostr ]); curl_setopt($cURLConnection, CURLOPT_RETURNTRANSFER, true); $apiResponse = curl_exec($cURLConnection); curl_close($cURLConnection); var_dump($apiResponse);
额外注意事项
- 拼接参数时要保证参数顺序和文档要求完全一致,不要随意调整参数顺序
- 发起POST请求时,
application/x-www-form-urlencoded格式需要用http_build_query处理参数数组,不要直接传数组 - 如果接口要求使用URL安全的base64编码,用你之前写的
encode函数替换对应位置的base64_encode即可
内容的提问来源于stack exchange,提问作者058WistWol
相关产品推荐
相关产品推荐

