退款接口提示 ACQ.INVALID_PARAMETER 如何解决?
支付老李
结论
ACQ.INVALID_PARAMETER 表示退款请求中缺少用于定位原支付交易的订单号。调用退款接口时,至少要传入以下参数之一:
trade_no:支付宝订单号out_trade_no:商户创建支付订单时生成的商户订单号
这两个参数不能同时为空,通常传入一个即可。如果同时传入,两者必须指向同一笔交易,否则退款仍可能失败。
原因说明
退款接口只有定位到原支付交易后,才能执行退款。以下情况可能触发该错误:
trade_no和out_trade_no都未传入;- 参数所在的请求层级不正确;
- 字段名称拼写错误;
- 参数值是空字符串、空格或
null; - 误将退款单号当作原支付订单号;
- 使用 SDK 时只创建了退款请求对象,没有在业务模型中设置订单号。
trade_no 一般可以从支付成功结果或交易查询结果中获取。out_trade_no 是商户发起支付时传入的原商户订单号。退款请求号不属于原支付订单号,不能代替这两个字段。
解决方法
方式一:传入支付宝订单号
如果已经保存支付成功时返回的支付宝订单号,可以传入 trade_no:
{
"trade_no": "2026XXXXXXXXXXXXXXXXXXXX",
"refund_amount": "10.00"
}
trade_no 必须是原支付交易对应的支付宝订单号,不能填写商户退款单号或其他业务流水号。
方式二:传入商户订单号
如果没有保存支付宝订单号,可以传入发起支付时使用的 out_trade_no:
{
"out_trade_no": "ORDER_202609090001",
"refund_amount": "10.00"
}
out_trade_no 必须与原支付请求中的商户订单号完全一致,不能为此次退款临时生成新订单号。
Java SDK 示例
下面是 alipay.trade.refund 常见的 SDK 调用方式:
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
AlipayTradeRefundModel model = new AlipayTradeRefundModel();
model.setTradeNo("2026XXXXXXXXXXXXXXXXXXXX");
// 或者使用:
// model.setOutTradeNo("ORDER_202609090001");
model.setRefundAmount("10.00");
request.setBizModel(model);
AlipayTradeRefundResponse response = alipayClient.execute(request);
使用 out_trade_no 时:
AlipayTradeRefundModel model = new AlipayTradeRefundModel();
model.setOutTradeNo("ORDER_202609090001");
model.setRefundAmount("10.00");
具体类名和参数设置方式可能随支付宝 SDK 版本而不同,但业务要求相同:trade_no 和 out_trade_no 至少要有一个有效值。
排查步骤
- 打印退款请求的业务参数,确认最终发送的数据中包含
trade_no或out_trade_no。 - 检查字段值是否为
null、空字符串或仅包含空格。 - 确认订单号来自原支付交易,而非退款申请、商品订单或内部流水。
- 使用
out_trade_no时,核对它是否与支付时传入的值完全一致。 - 使用
trade_no时,核对它是否来自支付宝支付成功结果或交易查询结果。 - 检查参数是否位于接口要求的业务参数对象中,例如
biz_content或 SDK 的业务模型。 - 修改后重新发起退款,并记录接口返回的
code、sub_code和sub_msg,以便继续排查。
注意事项
- 不要为退款重新生成
out_trade_no,退款必须关联原支付订单。 - 同时传入两个订单号时,两者必须对应同一笔交易。
- 建议将订单号按字符串处理,防止数字类型转换导致前导零丢失或精度变化。
- 生产日志可以记录订单号和错误码,但不要输出私钥、签名密钥等敏感信息。
- 补全订单号后如果退款仍然失败,需要根据新的
sub_code和sub_msg,继续检查退款金额、交易状态和退款权限等问题。
备注:内容仅供参考。
