支付宝能否关闭非支付宝创建的订单交易?
结论
如果订单从未在支付宝侧创建,就无法通过支付宝接口关闭。
alipay.trade.close 只能关闭支付宝系统中已存在、尚未支付且符合关闭条件的交易。如果本地订单既没有调用支付宝支付接口,也没有生成对应的支付宝交易记录,只需在商户系统中取消或关闭,不必调用支付宝接口。
原因说明
商户订单和支付宝交易是两个不同的对象:
- 商户订单由商户自己的业务系统创建和管理。
- 调用当面付、App 支付或手机网站支付等接口后,支付宝侧会建立相应交易。
out_trade_no是商户提交给支付宝的商户订单号。trade_no是支付宝在交易创建后生成的支付宝交易号。
支付宝关闭交易接口需要通过 out_trade_no 或 trade_no 查找支付宝侧的交易。如果订单从未提交给支付宝,支付宝侧就没有对应记录,自然也没有可以关闭的交易。此时调用关闭接口通常不会产生实际效果,具体错误码和返回内容以接口响应为准。
需要注意的是,“订单不是支付宝创建的”不等于”支付宝侧没有交易”。商户订单本来通常就是由商户创建的。只要订单已经通过支付接口提交给支付宝,并在支付宝侧生成交易,就可以在符合接口条件时调用关闭接口。
处理步骤
1. 确认支付宝侧是否存在交易
先使用 alipay.trade.query 查询交易状态。查询时可以传入:
trade_no:支付宝交易号;out_trade_no:创建支付宝交易时提交的商户订单号。
如果查不到对应交易,支付宝侧可能没有创建这笔交易。此时直接在商户系统中关闭本地订单即可。
2. 判断交易是否允许关闭
关闭接口主要用于尚未完成支付的交易,例如等待买家付款的交易。
交易已经支付成功时,不应调用 alipay.trade.close。如果需要撤销交易或退回资金,应根据支付场景和交易状态选择撤销或退款接口,例如:
alipay.trade.cancelalipay.trade.refund
两者的适用条件不同,不能用”关闭订单”代替退款。
3. 调用交易关闭接口
确认支付宝侧存在可关闭的交易后,调用:
alipay.trade.close
通常选择 out_trade_no 或 trade_no 中的一个来定位交易。如果同时持有两者,需要确保它们指向同一笔交易。
4. 根据同步响应更新本地状态
接口调用没有抛出异常,并不代表交易一定关闭成功。还需要检查支付宝返回的业务结果,并记录请求号、订单号和响应内容。确认交易关闭成功后,再把本地订单状态更新为已关闭。
Java 示例
下面是基本调用示例。网关地址、应用 ID、密钥、签名方式和字符集需要替换为商户自己的支付宝开放平台配置。
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeCloseRequest;
import com.alipay.api.response.AlipayTradeCloseResponse;
public class AlipayTradeCloseExample {
public static void main(String[] args) throws Exception {
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do",
"YOUR_APP_ID",
"YOUR_APP_PRIVATE_KEY",
"json",
"UTF-8",
"ALIPAY_PUBLIC_KEY",
"RSA2"
);
AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
request.setBizContent("""
{
"out_trade_no": "MERCHANT_ORDER_202609090001"
}
""");
AlipayTradeCloseResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
System.out.println("支付宝交易关闭成功");
System.out.println("trade_no: " + response.getTradeNo());
System.out.println("out_trade_no: " + response.getOutTradeNo());
} else {
System.out.println("支付宝交易关闭失败");
System.out.println("code: " + response.getCode());
System.out.println("sub_code: " + response.getSubCode());
System.out.println("sub_msg: " + response.getSubMsg());
}
}
}
如果只有支付宝交易号,也可以改为:
request.setBizContent("""
{
"trade_no": "ALIPAY_TRADE_NO"
}
""");
注意事项
- 不要把”商户创建的订单”理解为”支付宝侧没有交易”。判断依据是该订单是否已经通过支付接口提交到支付宝。
- 本地订单号必须与创建支付宝交易时使用的
out_trade_no一致,不能临时换用其他订单号调用关闭接口。 - 已支付交易通常不能使用
alipay.trade.close处理,应根据实际状态选择撤销或退款接口。 - 如果查不到支付宝交易,不必反复调用关闭接口,直接关闭商户系统中的本地订单即可。
- 支付和关单可能同时发生。更新本地状态前,需要核对关单响应、支付结果通知和主动查询结果,避免把已经支付的订单误标为已关闭。
- 正式环境和沙箱环境的数据相互隔离。订单在哪个环境创建,就应在同一环境中查询和关闭。
- 接口是否可用、当前交易状态能否关闭以及具体返回码,均以支付宝开放平台的现行接口文档和实际响应为准。
备注:内容仅供参考。
