沙箱模式下调用alipay.trade.query返回ACQ.SYSTEM_ERROR
结论
code="20000"、sub_code="ACQ.SYSTEM_ERROR"表示支付宝网关或收单业务系统在处理查询请求时出现了通用系统异常。这不是“交易不存在”的明确业务结果,也不能仅凭这段响应认定签名、密钥或参数有误。
沙箱环境中常见的原因有:
- 沙箱服务临时异常,或相关能力不稳定;
- 被查询的订单不是由当前沙箱应用创建的;
- 混用了正式环境和沙箱环境的
app_id、密钥、账号或订单号; - 原交易尚未创建完成,查询时后台数据还未同步;
- 请求参数、SDK 配置或字符编码有问题,但网关没有返回更具体的子错误码。
建议先核对运行环境和订单归属,再延迟一段时间进行有限次数的重试。如果同一请求持续返回这个错误,应保留完整的请求和响应信息,提交给支付宝开放平台技术支持进一步排查。
排查步骤
1. 确认请求发送到沙箱网关
沙箱环境应使用:
https://openapi-sandbox.dl.alipaydev.com/gateway.do
不要使用正式网关:
https://openapi.alipay.com/gateway.do
以下配置也必须全部来自同一个沙箱应用:
app_id- 应用私钥
- 支付宝公钥,或支付宝公钥证书
- 沙箱买家、卖家账号
- 被查询订单的
trade_no或out_trade_no
只把网关地址换成沙箱地址并不够。如果仍在使用正式应用的配置,或查询正式环境生成的订单,查询结果没有可比性。
2. 检查订单是否确实创建成功
alipay.trade.query只查询交易,不会创建交易。调用前应确认原支付接口已成功受理,并且已经保存对应的订单号。
查询参数至少要提供以下字段之一:
{
"out_trade_no": "202609090001"
}
或者:
{
"trade_no": "2026090922000000000000000000"
}
优先使用支付宝实际返回的 trade_no。如果使用 out_trade_no,它必须与创建交易时提交的值完全一致,而且该订单必须属于当前 app_id。
不要自行构造 trade_no,也不要查询由其他应用、正式环境或另一套沙箱账号生成的订单。
3. 避免创建订单后立即高频查询
沙箱环境可能存在短暂的数据同步延迟。如果创建交易后立即查询并收到 ACQ.SYSTEM_ERROR,可以等待几秒再试。
建议设置有限次数的退避重试,例如:
第 1 次失败:等待 1 秒
第 2 次失败:等待 2 秒
第 3 次失败:等待 4 秒
仍然失败:停止自动重试并记录现场
alipay.trade.query是只读查询接口,可以进行有限重试,但不要无间隔地循环调用,以免放大沙箱故障或触发频率限制。
4. 检查公共请求参数和 SDK 配置
重点检查以下项目:
method是否为alipay.trade.querycharset是否为utf-8sign_type是否与应用配置一致,通常为RSA2- 私钥格式是否符合当前 SDK 的要求
- 支付宝公钥和应用私钥是否配置颠倒
timestamp是否为有效时间- 系统时间是否明显不准确
biz_content是否为合法 JSON- 请求参数是否在签名后被再次修改或编码
签名错误通常会返回更具体的错误码,所以看到 ACQ.SYSTEM_ERROR时,不能直接判断为签名问题。不过,仍有必要完整检查配置,尤其是在自行拼装 HTTP 请求时。
Java SDK 调用示例
下面的示例使用 out_trade_no查询沙箱订单。具体的 SDK 版本和证书模式,应以项目的实际配置为准。
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
public class AlipayTradeQueryExample {
private static final String GATEWAY =
"https://openapi-sandbox.dl.alipaydev.com/gateway.do";
public static void main(String[] args) throws Exception {
String appId = "你的沙箱APP_ID";
String appPrivateKey = "你的应用私钥";
String alipayPublicKey = "你的沙箱支付宝公钥";
AlipayClient alipayClient = new DefaultAlipayClient(
GATEWAY,
appId,
appPrivateKey,
"json",
"utf-8",
alipayPublicKey,
"RSA2"
);
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
model.setOutTradeNo("202609090001");
request.setBizModel(model);
AlipayTradeQueryResponse response = alipayClient.execute(request);
System.out.println("body: " + response.getBody());
System.out.println("code: " + response.getCode());
System.out.println("msg: " + response.getMsg());
System.out.println("subCode: " + response.getSubCode());
System.out.println("subMsg: " + response.getSubMsg());
if (response.isSuccess()) {
System.out.println("tradeStatus: " + response.getTradeStatus());
System.out.println("tradeNo: " + response.getTradeNo());
} else if ("20000".equals(response.getCode())
&& "ACQ.SYSTEM_ERROR".equals(response.getSubCode())) {
System.err.println("收单系统异常,可延迟后进行有限次数重试");
} else {
System.err.println("查询失败,应根据具体错误码检查请求");
}
}
}
不要只看 HTTP 状态码。支付宝网关可能返回 HTTP 成功,但业务响应中的 code 并非 10000。判断业务是否成功,应以 SDK 的 response.isSuccess()或响应体中的业务码为准。
建议记录的诊断信息
如果多次重试后仍出现同样的错误,应记录以下信息:
请求时间:
沙箱应用 app_id:
调用网关:
接口名称:alipay.trade.query
查询方式:trade_no / out_trade_no
订单号:
响应 code:
响应 msg:
响应 sub_code:
响应 sub_msg:
完整原始响应:
SDK名称及版本:
是否使用证书模式:
原支付接口的请求时间和响应:
日志中的私钥、完整签名、身份证号和手机号等敏感信息需要脱敏,不要直接提交或公开。
如果响应头、SDK 日志或开放平台日志中包含请求流水号,也应一并保留。只提供“返回系统错误”通常不足以定位后台调用链。
如何判断问题位于哪一侧
可以找一个刚刚由当前沙箱应用成功创建的订单,进行对照查询:
- 如果所有订单都返回
ACQ.SYSTEM_ERROR,优先检查网关地址、应用配置和沙箱服务状态。 - 如果只有某个订单返回异常,重点检查该订单是否创建成功、归属是否正确,以及订单号是否有误。
- 如果延迟后查询成功,原因可能是沙箱服务短暂异常或数据同步延迟。
- 如果长时间稳定复现,而且配置和订单都已确认无误,则更可能需要支付宝根据请求流水进行定位。
ACQ.SYSTEM_ERROR是通用错误码,响应本身不会显示具体的后台异常。排除环境混用和订单问题后,客户端代码无法进一步确认内部原因。此时应携带完整的诊断信息,联系支付宝开放平台技术支持。
备注:内容仅供参考。
