Android 接入支付宝支付提示系统繁忙的原因
支付小周
结论
这份请求生成的是手机网站支付(WAP)订单,但实际用于 Android App 支付。由于产品接口不匹配,支付宝客户端很可能只显示”系统繁忙”。
当前参数是:
method=alipay.trade.wap.pay
product_code=QUICK_WAP_WAY
Android 原生 App 通过支付宝 SDK 发起支付时,应使用:
method=alipay.trade.app.pay
product_code=QUICK_MSECURITY_PAY
问题不在 appid 或支付金额,而是服务端调用了错误的支付产品接口。
参数检查
请求中的关键业务参数解码后大致如下:
{
"out_trade_no": "C1655372930809",
"total_amount": 0.01,
"subject": "途乎商品购买",
"product_code": "QUICK_WAP_WAY"
}
具体来看:
app_id=2021003131627312:仅凭这个值,无法判断应用是否已经签约 App 支付能力。method=alipay.trade.wap.pay:这是手机网站支付接口。product_code=QUICK_WAP_WAY:这是手机网站支付产品码。- Android App 使用
PayTask.payV2()时,需要传入由alipay.trade.app.pay生成的订单字符串。 sign_type=RSA2:签名类型没有问题,但还要确认私钥、应用公钥配置和签名原文完全一致。timestamp=2022-06-16 17:48:50:如果这只是历史请求样例,无需处理。如果现在仍在重复使用这份订单信息,时间戳和订单号都要重新生成。notify_url未出现:这通常不会直接引发”系统繁忙”,但生产环境中应配置异步通知地址。
alipay_sdk=alipay-sdk-java-dynamicVersionNo 通常是服务端 SDK 生成的系统参数,与本次接口类型错误没有直接关系。
正确的解决方式
1. 服务端改用 App 支付接口
Java 服务端应使用 AlipayTradeAppPayRequest,并将产品码设为 QUICK_MSECURITY_PAY:
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do",
appId,
merchantPrivateKey,
"json",
"UTF-8",
alipayPublicKey,
"RSA2"
);
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
request.setNotifyUrl("https://example.com/alipay/notify");
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setOutTradeNo("C" + System.currentTimeMillis());
model.setTotalAmount("0.01");
model.setSubject("途乎商品购买");
model.setProductCode("QUICK_MSECURITY_PAY");
request.setBizModel(model);
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
if (!response.isSuccess()) {
throw new IllegalStateException(
response.getCode() + ": " + response.getSubMsg()
);
}
String orderInfo = response.getBody();
response.getBody() 返回的是已经签名的订单字符串,服务端应将它原样返回给 Android 客户端。
2. Android 使用支付宝 App SDK 发起支付
Runnable payRunnable = () -> {
PayTask payTask = new PayTask(activity);
Map<String, String> result = payTask.payV2(orderInfo, true);
activity.runOnUiThread(() -> {
String resultStatus = result.get("resultStatus");
String memo = result.get("memo");
String rawResult = result.get("result");
Log.d("Alipay", "resultStatus=" + resultStatus);
Log.d("Alipay", "memo=" + memo);
Log.d("Alipay", "result=" + rawResult);
});
};
Thread payThread = new Thread(payRunnable);
payThread.start();
客户端不要自行拼接参数,也不要重新编码或修改服务端返回的 orderInfo,否则可能导致签名失效。
如果业务确实需要 WAP 支付
如果实际需求是在浏览器或 WebView 中使用手机网站支付,可以保留:
method=alipay.trade.wap.pay
product_code=QUICK_WAP_WAY
此时应跳转到手机网站支付页面,不能把这段请求串交给 Android 的 PayTask.payV2()。WAP 支付通常还要按业务需要设置:
quit_url
return_url
WAP 支付和 App 支付是两套不同的接入流程,不能因为它们都在手机上运行就混用。
仍然报错时的排查项
修改接口后,还需要检查以下内容:
- 确认应用已经签约并开通”App 支付”产品。
- 确认服务端使用的是应用私钥,不是支付宝公钥或应用公钥。
- 确认开放平台中配置的应用公钥与当前私钥配对。
- 正式环境应使用
https://openapi.alipay.com/gateway.do。沙箱应用和正式应用的网关、账号、密钥不能混用。 - 每次支付都要生成唯一的
out_trade_no,不要重复使用失败或已经支付的订单号。 - 保存服务端响应中的
code、sub_code、msg、sub_msg和request_id。客户端显示的”系统繁忙”只是通用提示,服务端响应更适合用来排查签名、权限和参数问题。 - 不要只根据客户端返回值判断支付结果,应以支付宝异步通知或服务端主动查询的结果为准。
针对这份请求,应先将 alipay.trade.wap.pay + QUICK_WAP_WAY 改为 alipay.trade.app.pay + QUICK_MSECURITY_PAY,重新生成并签名订单,再将订单交给 Android 支付 SDK。
备注:内容仅供参考。
