PAYATHON 2026

APP支付退款仅传out_trade_no提示支付宝交易号不存在

支付阿杰

结论

退款接口可以只传 out_trade_no,不需要同时提供支付宝交易号。出现“支付宝交易号不存在”时,通常不是因为缺少 trade_no,而是支付宝无法在当前请求对应的交易上下文中找到这笔商户订单。

可以优先检查:

  • out_trade_no 是否以字符串形式放在 biz_content 中。
  • 退款请求使用的 app_id、支付宝环境和收款账号是否与原支付交易一致。
  • 订单号是否因整数精度、类型转换或多余空格发生变化。
  • 原支付是否成功,以及该订单是否属于当前应用。
  • SDK 字段映射是否正确,商户订单号有没有被误传到 trade_no。

如果已经取得支付宝交易号 2021123122001405421404780777,可以直接使用 trade_no 发起退款。排查订单关联问题时,这也是最直接的方式。

两个订单号的区别

退款接口中的两个字段含义不同:

参数含义示例
out_trade_no商户系统生成的订单号202112311352268842
trade_no支付宝生成的交易号2021123122001405421404780777

两个字段不能同时为空,提供其中一个即可。注意不要传反:

{
  "out_trade_no": "202112311352268842",
  "refund_amount": "0.01"
}

也可以使用:

{
  "trade_no": "2021123122001405421404780777",
  "refund_amount": "0.01"
}

如果两个字段都传,它们必须指向同一笔交易。实际调用时通常选择其中一个,以免发生字段冲突。

为什么只传 out_trade_no 仍可能查询不到交易

1. 退款请求与原支付使用了不同的 app_id

out_trade_no 是商户侧订单号。支付宝还需要结合应用和商户身份等信息定位交易。如果支付与退款使用了不同应用的密钥或 app_id,即使订单号没有问题,也可能找不到原交易。

需要核对:

  • APP 支付时使用的 app_id
  • 退款时使用的 app_id
  • 应用绑定的支付宝账号
  • 应用私钥及支付宝公钥配置

2. 支付和退款不在同一个环境

沙箱环境与正式环境的数据彼此隔离。如果支付发生在正式环境,退款请求却发到了沙箱网关,支付宝就无法查到这笔交易。

请确认支付和退款使用的是同一个网关环境。

3. out_trade_no 没有放入 biz_content

调用 alipay.trade.refund 时,业务参数需要放在 biz_content 中。如果将 out_trade_no 作为普通公共参数拼接在请求外层,SDK 或网关可能无法正确解析。

业务参数的结构应类似:

{
  "out_trade_no": "202112311352268842",
  "refund_amount": "0.01"
}

这段 JSON 应作为 biz_content 提交。

4. 订单号被当成数字处理

202112311352268842 是一个 18 位订单号,已经超过 JavaScript 的安全整数范围:

Number.MAX_SAFE_INTEGER = 9007199254740991

如果前端或 Node.js 程序将订单号写成数字:

const outTradeNo = 202112311352268842;

它可能在序列化前就已经丢失精度。订单号从生成、存储到传输都必须使用字符串:

const outTradeNo = "202112311352268842";

在 JSON 中也要加引号:

{
  "out_trade_no": "202112311352268842",
  "refund_amount": "0.01"
}

5. 原交易不属于当前收款主体

在服务商模式、代商户调用或应用授权调用等场景中,还要确认退款请求使用的授权主体、收款商户与原支付一致。仅凭一个商户订单号,无法跨应用或跨商户查询其他主体的交易。

正确的请求示例

使用支付宝 Java SDK 时,可以通过支付宝交易号发起退款:

AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();

request.setBizContent("""
{
  "trade_no": "2021123122001405421404780777",
  "refund_amount": "0.01",
  "out_request_no": "REFUND_202112311352268842_001"
}
""");

AlipayTradeRefundResponse response = alipayClient.execute(request);

if (response.isSuccess()) {
    System.out.println("退款请求成功");
} else {
    System.out.println("code: " + response.getCode());
    System.out.println("subCode: " + response.getSubCode());
    System.out.println("msg: " + response.getMsg());
    System.out.println("subMsg: " + response.getSubMsg());
}

只使用商户订单号时:

AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();

request.setBizContent("""
{
  "out_trade_no": "202112311352268842",
  "refund_amount": "0.01",
  "out_request_no": "REFUND_202112311352268842_001"
}
""");

AlipayTradeRefundResponse response = alipayClient.execute(request);

out_request_no 是商户退款请求号。一次性全额退款是否必须填写该字段,应以当前接口文档和具体业务场景为准。对于部分退款或同一笔交易的多次退款,建议为每次退款生成唯一值;重试同一次退款时则继续使用原值,避免重复受理。

建议的排查步骤

  1. 先使用支付宝交易号 2021123122001405421404780777 调用退款接口。
  2. 确认 refund_amount 以字符串 "0.01" 传递。
  3. 打印签名前的完整 biz_content,检查订单号是否发生了精度变化。
  4. 核对支付和退款使用的 app_id、网关环境及商户身份。
  5. 调用交易查询接口,分别使用 trade_no 和 out_trade_no 查询原订单。
  6. 如果 trade_no 能查到而 out_trade_no 查不到,重点检查原支付请求中实际提交的商户订单号,以及当前退款请求所属的应用或授权主体。
  7. 如果两个编号都查不到,优先排查环境、应用身份、授权关系和原支付状态。

不要仅凭错误描述认定必须补传 trade_no。按照参数约束,单独传入正确的 out_trade_no 是合法的。该错误表示支付宝没有在当前请求上下文中找到对应交易。如果已有准确的 trade_no,可以先用它完成退款,再继续核对商户订单号和应用配置。

备注:内容仅供参考。