调用的接口:https://api.mch.weixin.qq.com/v3/refund/domestic/refunds;
退款代码(PHP):
static public function tuikuan($money_fen,$total,$out_trade_no,$reason="协商退款"){
$url = 'https://api.mch.weixin.qq.com/v3/refund/domestic/refunds';
$data = [
"out_trade_no"=>$out_trade_no,//商户订单号
"out_refund_no"=>$out_trade_no,//商户退款单号
"reason"=>$reason,//
"notify_url"=>"https://api.huodongbaobao.com/pay/weixinpay_tuikuan_notify",//退款结果回调url
"amount"=>[
"refund"=>$money_fen,//退款金额,单位为分。示例值:100
"total"=>$total,//原支付交易的订单总金额,单位为分。示例值:100
"currency"=>"CNY"
],
];
$header = [
"Accept: application/json",
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
self::getSign($url,json_encode($data)),
];
$res = curl($url,$data,true,$header);
if(!isset($res['body'])){
return ["status"=>"error","msg"=>"微信申请退款请求失败"];
}
$data = json_decode($res['body'],true);
if(
isset($data['refund_id']) &&
isset($data['status']) &&
!empty($data['refund_id']) &&
!empty($data['status'])
){
$res_status = $data['status'];//$data['status']枚举值:SUCCESS:退款成功 CLOSED:退款关闭 PROCESSING:退款处理中 ABNORMAL:退款异常
if($res_status == "SUCCESS"){
return ["status"=>"ok","data"=>"success"];
}else if($res_status == "PROCESSING"){
return ["status"=>"ok","data"=>"processing"];
}else{
return ["status"=>"error","msg"=>"退款异常"];
}
}
$msg = isset($data['code']) ? $data['code'] : "";
$msg .= isset($data['message']) ? "【".$data['message']."】" : "";
return ["status"=>"error","msg"=>$msg];
}
生成签名的代码:
static private function getSign($url,$body,$http_method = "POST",$timestamp = 0,$nonce = ""){
$url_parts = parse_url($url);
$canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?{$url_parts['query']}" : ""));
if(empty($timestamp)){
$timestamp = time();
}
if(empty($nonce)){
$nonce = makeCode(32,true);
}
$message = $http_method."\n".$canonical_url."\n".$timestamp."\n".$nonce."\n".$body."\n";
openssl_sign($message, $raw_sign, file_get_contents(config("app.weixin_mchid_api_cert_pem")), 'sha256WithRSAEncryption');
$sign = base64_encode($raw_sign);
$schema = 'WECHATPAY2-SHA256-RSA2048';
$token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"',config("app.weixin_mchid"),config("app.weixin_mchid_api_cert_serial"), $nonce, $timestamp, $sign);
return "Authorization: " . $schema . " " . $token;
}
入参:
(
[out_trade_no] => 20250**********82541
[out_refund_no] => 2025030**********541
[reason] => 协商退款
[notify_url] => https:/xx.yy.com/pay/weixinpay_tuikuan_notify
[amount] => Array
(
[refund] => 1
[total] => 1
[currency] => CNY
)
)
打印出的参数:
生成签名用的数据:
POST
/v3/refund/domestic/refunds
1742463956
evhvqt02e7b125wsuienffzt4bgzv7mt
{"out_trade_no":"20250309151620582541","out_refund_no":"20250309151620582541","reason":"\u534f\u5546\u9000\u6b3e","notify_url":"https:\/\/api.huodongbaobao.com\/pay\/weixinpay_tuikuan_notify","amount":{"refund":1,"total":1,"currency":"CNY"}}
生成的header Authorization:
Kimj2a4kl/A8zG/xtGG5RneTVRrHVBvkDaccFhK1NzXwP1GReutazJtdKXpOOXl6rtwx/ke4DzV8zmt8XHUunX/3wIPZ3DZrlV/F+xM9lX3um1VudL6yxLovB4djfcloO0QlzN8XzRhf1k9f25hvDiBgAMzZ9omNp06Xigpnjy2lgaTS/CpihjG2j+qKtHg0t/cIvVdfkYW59cX/t+XBRNBGozFpTm6OnxqnbCj/r90da1GQ20AZQMjYl3X4gWBIOqyBrCt5yJk2atFq/6fRA2Zc3cFzwSlTJjx11phIyGsrgG5X+JVosTW1eWGceDNGhoFy6vJmU6C8HSNWSW9kzQ==authorization-admin:
Authorization: WECHATPAY2-SHA256-RSA2048 mchid="165****008",serial_no="4498A82FCC548B7B4932AA4939807C395109770B",nonce_str="evhvqt02e7b125wsuienffzt4bgzv7mt",timestamp="1742463956",signature="Kimj2a4kl/A8zG/xtGG5RneTVRrHVBvkDaccFhK1NzXwP1GReutazJtdKXpOOXl6rtwx/ke4DzV8zmt8XHUunX/3wIPZ3DZrlV/F+xM9lX3um1VudL6yxLovB4djfcloO0QlzN8XzRhf1k9f25hvDiBgAMzZ9omNp06Xigpnjy2lgaTS/CpihjG2j+qKtHg0t/cIvVdfkYW59cX/t+XBRNBGozFpTm6OnxqnbCj/r90da1GQ20AZQMjYl3X4gWBIOqyBrCt5yJk2atFq/6fRA2Zc3cFzwSlTJjx11phIyGsrgG5X+JVosTW1eWGceDNGhoFy6vJmU6C8HSNWSW9kzQ=="
~
最终的问题:
调用微信退款接口后,微信返回内容打印如下:
Array
(
[request_header] => POST /v3/refund/domestic/refunds HTTP/1.1
Host: api.mch.weixin.qq.com
Accept: application/json
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36
Authorization: WECHATPAY2-SHA256-RSA2048 mchid="16****008",serial_no="4498A82FCC548B7B4932AA4939807C395109770B",nonce_str="evhvqt02e7b125wsuienffzt4bgzv7mt",timestamp="1742463956",signature="Kimj2a4kl/A8zG/xtGG5RneTVRrHVBvkDaccFhK1NzXwP1GReutazJtdKXpOOXl6rtwx/ke4DzV8zmt8XHUunX/3wIPZ3DZrlV/F+xM9lX3um1VudL6yxLovB4djfcloO0QlzN8XzRhf1k9f25hvDiBgAMzZ9omNp06Xigpnjy2lgaTS/CpihjG2j+qKtHg0t/cIvVdfkYW59cX/t+XBRNBGozFpTm6OnxqnbCj/r90da1GQ20AZQMjYl3X4gWBIOqyBrCt5yJk2atFq/6fRA2Zc3cFzwSlTJjx11phIyGsrgG5X+JVosTW1eWGceDNGhoFy6vJmU6C8HSNWSW9kzQ=="
Content-Type: application/json; charset=utf-8
Content-Length:229
[request_body] => {"out_trade_no":"20250309151620582541","out_refund_no":"20250309151620582541","reason":"协商退款","notify_url":"https:\/\/api.huodongbaobao.com\/pay\/weixinpay_tuikuan_notify","amount":{"refund":1,"total":1,"currency":"CNY"}}
[header] => HTTP/1.1 401 Unauthorized
Server: nginx
Date: Thu, 20 Mar 2025 09:45:57 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 377
Connection: keep-alive
Keep-Alive: timeout=8
Cache-Control: no-cache, must-revalidate
X-Content-Type-Options: nosniff
Request-ID: 08D5C7EFBE061053189DDFEEA30620A8B50128DA38-269546525
Content-Language: zh-CN
[body] => {"code":"SIGN_ERROR","detail":{"detail":{"issue":"sign not match"},"field":"signature","location":"authorization","sign_information":{"method":"POST","sign_message_length":307,"truncated_sign_message":"POST\n/v3/refund/domestic/refunds\n1742463956\nevhvqt02e7b125wsuienffzt4bgzv7mt\n{\"out_tr\n","url":"/v3/refund/domestic/refunds"}},"message":"错误的签名,验签失败"}
)
最下面的[body]中返回了报错信息:{"code":"SIGN_ERROR","detail":{"detail":{"issue":"sign not match"},"field":"signature","location":"authorization","sign_information":{"method":"POST","sign_message_length":307,"truncated_sign_message":"POST\n/v3/refund/domestic/refunds\n1742463956\nevhvqt02e7b125wsuienffzt4bgzv7mt\n{\"out_tr\n","url":"/v3/refund/domestic/refunds"}},"message":"错误的签名,验签失败"}
我小程序上有一个退款功能,电脑端管理后台也有一个退款功能,小程序端退款功能的代码和电脑端退款功能的代码是处于两个地方,但代码内容是一模一样的(复制的),二者使用的是同一套证书、密钥,小程序上的支付、退款功能都好用,但电脑端的退款功能就不好用,请求退款接口时提示上面的报错内容,调试了很久,确实没找到问题原因,请大家帮忙看看。
微信没有人工客服吧,就像支付宝小程序那样的人工客服,只能从这里发帖子,被动的等着别人帮忙看看,要求官方回复的话需要达到4级!
PHP 应该看这个sdk及示例代码,不走失不迷失 https://wechatpay.im/openapi/v3/refund/domestic/refunds