在基于 riverslei/payment 实现支付宝退款时,报错:request get failed, msg[Invalid Arguments], sub_msg[验签出错,建议检查签名字符串或签名私钥与应用公钥是否匹配
1、在基于 riverslei/payment 实现支付宝退款时,报错:request get failed, msg[Invalid Arguments], sub_msg[验签出错,建议检查签名字符串或签名私钥与应用公钥是否匹配。如图1
2、你提供的是一个 PKCS#1 格式的 RSA 私钥(以 MIIEvQ… 开头,未带头尾标识),需要通过 OpenSSL 命令将它转换为 PKCS#8 格式的 RSA 私钥,支付宝才能识别。将私钥内容复制至文件 pkcs1.pem,然后执行如下命令。 如图2
$ openssl pkcs8 -topk8 -inform PEM -in pkcs1.pem -out pkcs8.pem -outform PEM -nocrypt wangqiang@DESKTOP-F6AO3M2 MINGW64 /C/wwwroot/apply-server/src (feature/alipay)
3、最后将 pkcs8.pem 中的内容保存至 ali_rsa_private_key。如图3
4、提示有所变化,提示:sign error, sign type is [RSA2]. msg: [您使用的私钥格式错误,请检查RSA私钥配置]。如图4
5、编辑文件 vendor/riverslei/payment/src/Helpers/Rsa2Encrypt.php,
/**
* RSA2签名, 此处秘钥是私有秘钥
* @param string $data 签名的数组
* @throws \Exception
* @return string
* @author Leo
*/
public function encrypt($data)
{
if ($this->key === false) {
return '';
}
\Yii::info(
[
'data' => $data,
'key' => $this->key
]
);
$res = openssl_get_privatekey($this->key);
if (empty($res)) {
throw new \Exception('您使用的私钥格式错误,请检查RSA私钥配置1');
}
openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA256);
openssl_free_key($res);
//base64编码
$sign = base64_encode($sign);
return $sign;
}
6、查看 $this->key,竟然有 2 个 —–BEGIN RSA PRIVATE KEY—–、—–BEGIN PRIVATE KEY—– 。如图5
7、将 pkcs8.pem 中的内容保存至 ali_rsa_private_key 时,先清理掉 —–BEGIN RSA PRIVATE KEY—–。如图6
$aliConfig = [
'use_sandbox' => false, // 是否使用沙盒模式
'app_id' => $payee->ali_app_id,
'sign_type' => $payee->ali_sign_type, // RSA RSA2
// 支付宝公钥字符串
'ali_public_key' => $payee->ali_public_key,
// 自己生成的密钥字符串
'rsa_private_key' => $payee->ali_rsa_private_key,
'fee_type' => 'CNY', // 货币类型 当前仅支持该字段
];
8、再次提示:request get failed, msg[Invalid Arguments], sub_msg[验签出错,建议检查签名字符串或签名私钥与应用公钥是否匹配,网关生成的验签字符串为
9、查看文件 vendor/riverslei/payment/src/Helpers/StrUtil.php ,发现会自动将 PKCS#1 格式的 RSA 私钥(以 MIIEvQ… 开头,未带头尾标识),转换为 旧版 PKCS#1 格式的 RSA 私钥。最后发现仍然报错:sub_msg[验签出错,建议检查签名字符串或签名私钥与应用公钥是否匹配,网关生成的验签字符串为
/**
* 获取rsa密钥内容
* @param string $key 传入的密钥信息, 可能是文件或者字符串
* @param string $type
*
* @return string
*/
public static function getRsaKeyValue($key, $type = 'private')
{
if (is_file($key)) {// 是文件
$keyStr = @file_get_contents($key);
} else {
$keyStr = $key;
}
if (empty($keyStr)) {
return null;
}
$keyStr = str_replace(PHP_EOL, '', $keyStr);
// 为了解决用户传入的密钥格式,这里进行统一处理
if ($type === 'private') {
$beginStr = '-----BEGIN RSA PRIVATE KEY-----' . PHP_EOL;
$endStr = PHP_EOL . '-----END RSA PRIVATE KEY-----';
} else {
$beginStr = '-----BEGIN PUBLIC KEY-----' . PHP_EOL;
$endStr = PHP_EOL . '-----END PUBLIC KEY-----';
}
$rsaKey = $beginStr . wordwrap($keyStr, 64, "\n", true) . $endStr;
return $rsaKey;
}
10、编辑 vendor/riverslei/payment/src/Supports/HttpRequest.php,验签成功
/**
* @param string $method
* @param string $url
* @param array $options
* @return array|ResponseInterface|string|mixed
*/
private function sendRequest(string $method, string $url, array $options = [])
{
\Yii::info(
[
'$method' => $method,
'$url' => $url,
'$options' => $options
]
);
// return $this->unwrapResponse($this->getHttpClient($this->getBaseOptions())->{$method}($url, $options));
return $this->unwrapResponse($this->getHttpClient($this->getBaseOptions())->{$method}($url, [
'headers' => ['Content-Type' => 'application/x-www-form-urlencoded'],
'body' => http_build_query($options['query'], '', '&', PHP_QUERY_RFC3986),
]));
}
11、但是,由于响应中有乱码,进而导致 json_decode 报错。如图7
$ret = $this->get($this->gatewayUrl, $params);
if (!mb_check_encoding($ret, 'UTF-8')) {
$ret = mb_convert_encoding($ret, 'UTF-8', 'GBK');
}
12、报错:验签出错,请确认charset参数放在了URL查询字符串中且各参数值使用charset参数指示的字符集编码 。如图8
13、仔细对比 请求前后的签名字符串,发现 return_url= 丢失,决定在配置时删除 return_url。原因在于
/**
* 获取基础数据
* @param string $method
* @param array $bizContent
* @return array
*/
private function getBaseData(string $method, array $bizContent)
{
$requestData = [
'app_id' => self::$config->get('app_id', ''),
'method' => $method,
'format' => 'JSON',
'return_url' => self::$config->get('return_url', ''),
'charset' => 'utf-8',
'sign_type' => self::$config->get('sign_type', ''),
'timestamp' => date('Y-m-d H:i:s'),
'version' => '1.0',
'notify_url' => self::$config->get('notify_url', ''),
// 'app_auth_token' => '', // 暂时不用
'biz_content' => json_encode($bizContent, JSON_UNESCAPED_UNICODE),
];
return ArrayUtil::arraySort($requestData);
}
echo html_entity_decode('app_id=2021005146654430&biz_content={"out_trade_no":"1831248803313247","refund_amount":"0.01","refund_currency":"CNY","refund_reason":"Refund for Conference Registration Fee (Ticket)","out_request_no":"1831248803313311"}&charset=utf-8&format=JSON&method=alipay.trade.refund&notify_url=https://5347-43-249-50-182.ngrok-free.app/ali-payment/notify-ticket-order/1831248803313247&sign_type=RSA2&timestamp=2025-05-10 16:39:56&version=1.0');
// 请求前的签名字符串
// app_id=2021005146654430&biz_content={"out_trade_no":"1831248803313247","refund_amount":"0.01","refund_currency":"CNY","refund_reason":"Refund for Conference Registration Fee (Ticket)","out_request_no":"1831248803313311"}&charset=utf-8&format=JSON&method=alipay.trade.refund¬ify_url=https://5347-43-249-50-182.ngrok-free.app/ali-payment/notify-ticket-order/1831248803313247&return_url=&sign_type=RSA2×tamp=2025-05-10 16:39:56&version=1.0
// 请求后报错,支付宝使用的签名字符串
// app_id=2021005146654430&biz_content={"out_trade_no":"1831248803313247","refund_amount":"0.01","refund_currency":"CNY","refund_reason":"Refund for Conference Registration Fee (Ticket)","out_request_no":"1831248803313311"}&charset=utf-8&format=JSON&method=alipay.trade.refund¬ify_url=https://5347-43-249-50-182.ngrok-free.app/ali-payment/notify-ticket-order/1831248803313247&sign_type=RSA2×tamp=2025-05-10 16:39:56&version=1.0
14、支付宝返回的验签字符串中确实不会包含空值字段,例如 return_url=(空值)这一项,而你在参与签名时包含了它,导致签名字符串不一致,从而验签失败。最终决定调整配置
$aliConfig = [
'use_sandbox' => false, // 是否使用沙盒模式
'app_id' => $payee->ali_app_id,
'sign_type' => $payee->ali_sign_type, // RSA RSA2
// 支付宝公钥字符串
'ali_public_key' => $payee->ali_public_key,
// 自己生成的密钥字符串
'rsa_private_key' => $payee->ali_rsa_private_key,
'limit_pay' => [
// 'balance', // 余额
// 'moneyFund', // 余额宝
// 'debitCardExpress', // 借记卡快捷
// 'creditCard', // 信用卡
// 'creditCardExpress', // 信用卡快捷
// 'creditCardCartoon', // 信用卡卡通
// 'credit_group', // 信用支付类型(包含信用卡卡通、信用卡快捷、花呗、花呗分期)
], // 用户不可用指定渠道支付当有多个渠道时用“,”分隔
// 与业务相关参数
'notify_url' => 'notify_url',
'return_url' => 'return_url',
'fee_type' => 'CNY', // 货币类型 当前仅支持该字段
];
15、不再报错。打印退款的响应
$result = $client->refund($refundData);
Yii::info(
[
'result' => $result,
'data' => $refundData,
],
'refund ali'
);
[
'result' => [
'code' => '10000',
'msg' => 'Success',
'buyer_logon_id' => 'shu***@163.com',
'fund_change' => 'Y',
'gmt_refund_pay' => '2025-05-10 17:01:59',
'out_trade_no' => '1831248803313320',
'refund_detail_item_list' => [
[
'amount' => '0.01',
'fund_channel' => 'ALIPAYACCOUNT',
],
],
'refund_fee' => '0.01',
'send_back_fee' => '0.01',
'trade_no' => '2025051022001491671421159148',
'buyer_open_id' => '067IqA-DLOIYEoiWWh1KNCyoaiY-qUzekwwoGX_3VQKI9s7',
],
'data' => [
'trade_no' => '1831248803313320',
'refund_fee' => '0.01',
'reason' => 'Refund for Conference Registration Fee (Ticket)',
'refund_no' => '1831248803313321',
],
]
![在基于 riverslei/payment 实现支付宝退款时,报错:request get failed, msg[Invalid Arguments], sub_msg[验签出错,建议检查签名字符串或签名私钥与应用公钥是否匹配。](https://www.shuijingwanwq.com/wp-content/uploads/2025/07/1.jpg)


![提示有所变化,提示:sign error, sign type is [RSA2]. msg: [您使用的私钥格式错误,请检查RSA私钥配置]](https://www.shuijingwanwq.com/wp-content/uploads/2025/07/4.jpg)




近期评论