客户端接入支付宝支付提示“系统繁忙,请稍候再试”
结论
支付宝页面显示“系统繁忙,请稍候再试”时,仅凭这条通用提示和 PID 无法判断具体原因。调用 alipay.wap.create.direct.pay.by.user 时,建议先检查产品权限、请求参数、签名方式、调用流程和商户账号状态。
这是支付宝旧版手机网站支付接口。如果项目刚接入,或者支付宝调整过商户可用产品,需要先确认该 PID 是否仍有相应的签约权限。原生客户端不应自行拼装请求,更不能保存商户私钥。支付请求应由服务端生成,再交给浏览器或 WebView 跳转。
常见原因
1. 未签约或接口权限不匹配
商户账号可能没有开通手机网站支付,或者已签约产品与所调用的接口不一致。PID 正确并不代表它有权调用:
alipay.wap.create.direct.pay.by.user
请在支付宝商家平台中核对:
- 对应产品是否已经签约并生效;
- 签约主体、PID 和当前商户账号是否一致;
- 接口是否已停用、迁移或停止接受新接入;
- 是否需要改用开放平台当前提供的手机网站支付或 App 支付接口。
如果是原生 App,还要确认业务需要的究竟是 App 支付还是手机网站支付。
2. 请求参数缺失或格式错误
旧版接口通常要求提交完整的公共参数和业务参数。下面这些问题都有可能被前端统一显示为“系统繁忙”:
partner填写错误;seller_id与签约账号不一致;service拼写错误;out_trade_no为空、重复或含有不支持的字符;total_fee格式不正确;notify_url或return_url不是合法 URL;_input_charset与实际编码不一致;- 缺少
payment_type、subject等必填参数; - 参数签名后又被修改;
- 不应参与签名的空值参数被加入了签名。
可以先记录服务端最终发出的完整参数集合,但必须隐藏商户密钥、用户隐私和完整支付凭证。
3. 签名计算错误
签名错误是旧版支付宝接口调用失败的常见原因。计算签名时通常需要:
- 排除
sign、sign_type; - 排除值为空的参数;
- 按参数名进行字典序排序;
- 使用未经 URL 编码的原始参数值拼接;
- 按签约方式计算签名;
- 最后对请求参数进行 URL 编码。
下面的代码只展示旧版 MD5 签名的基本过程。当前商户能否使用这种方式,仍应以实际签约配置为准:
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
public class AlipayLegacySign {
public static String sign(Map<String, String> requestParams, String md5Key)
throws Exception {
Map<String, String> sorted = new TreeMap<>();
for (Map.Entry<String, String> entry : requestParams.entrySet()) {
String name = entry.getKey();
String value = entry.getValue();
if ("sign".equals(name) || "sign_type".equals(name)) {
continue;
}
if (value == null || value.isEmpty()) {
continue;
}
sorted.put(name, value);
}
String content = sorted.entrySet()
.stream()
.map(entry -> entry.getKey() + "=" + entry.getValue())
.collect(Collectors.joining("&"));
return md5(content + md5Key);
}
private static String md5(String value) throws Exception {
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] bytes = digest.digest(value.getBytes(StandardCharsets.UTF_8));
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02x", b & 0xff));
}
return result.toString();
}
}
还要注意以下几点:
- MD5 密钥不能保存在客户端;
- 签名前不要对参数值进行 URL 编码;
- 签名完成后不能再修改参数;
- 参数编码必须与
_input_charset一致; - 如果签约配置使用 RSA 或 RSA2,不能直接套用上面的 MD5 示例;
- 不要混用新版开放平台 SDK 和旧版 PID/Key 接口的签名规则。
建议的排查步骤
第一步:确认实际调用链路
先确认客户端通过什么方式发起支付。正常链路应为:
客户端 → 商户服务端生成支付请求 → 返回支付 URL 或表单 → 浏览器/WebView 跳转支付宝
如果客户端保存了密钥并自行计算签名,应立即改为服务端签名。这既便于记录请求和响应,也能防止密钥泄露。
第二步:保存完整的服务端日志
日志至少应包含:
- 请求时间;
- 请求网关地址;
service;partner和seller_id;out_trade_no;_input_charset;sign_type;- 签名前的待签名字符串;
- 支付宝返回的原始响应或跳转地址;
- HTTP 状态码;
- 支付宝返回的错误码、
sub_code、sub_msg或 request ID。
密钥、签名原文、手机号和身份证号等敏感信息必须脱敏。客户端页面上的“系统繁忙”无法提供足够的定位依据,排查时真正有用的是服务端原始响应和支付宝侧请求标识。
第三步:核对参数和签名
针对同一笔请求逐项检查:
- 参数名是否完全正确;
- 参数中是否含有多余空格、换行或不可见字符;
- 签名前后的字符编码是否一致;
- 金额是否采用合法的十进制格式;
out_trade_no是否唯一;- URL 是否被重复编码;
- 签名参数的排序是否正确;
- 所用密钥是否属于当前 PID;
- 测试环境与正式环境的账号、网关和密钥是否发生混用。
第四步:检查商户产品状态
登录对应的商户账号,检查 PID 2088141122714984 所属账号的签约情况和产品状态。PID 只是商户识别信息,不能单独用来判断接口权限。
如果后台找不到 alipay.wap.create.direct.pay.by.user 对应的产品,或者产品已经迁移,应根据开放平台当前文档改用合适的接口。迁移时不能只替换接口名,网关地址、应用身份、签名算法和参数结构通常也要随之调整。
第五步:取得支付宝侧的明确错误信息
如果请求参数、签名和签约状态都没有明显问题,可以向支付宝技术支持提供:
- PID;
- 问题发生的准确时间;
out_trade_no;- 服务端原始响应;
- 支付宝返回的 request ID 或错误码;
- 已脱敏的请求参数;
- 问题能否稳定复现。
是否存在风控拦截、账号状态异常、产品权限问题或短时服务异常,只能通过支付宝侧日志确认。
注意事项
不要反复重试同一个失败请求。重复提交可能让订单状态难以判断,也可能触发限流或风控。再次发起支付前,应先查询订单状态,再按照业务规则决定继续支付,还是生成新的商户订单号。
页面显示“系统繁忙”并不等于支付宝服务出现故障。参数校验失败、签名错误、产品未签约或账号受限,都可能触发同一条通用提示。排查应以服务端原始返回、错误码和支付宝侧请求日志为准。
备注:内容仅供参考。
