支付宝 Android SDK Demo 返回“系统繁忙”及授权参数获取问题
排查结论
系统繁忙,请稍后再试通常是支付宝客户端显示的兜底提示,并不代表支付宝服务确实繁忙。结合当前配置,问题更可能出在沙箱环境、应用身份或订单签名没有完全匹配。
可以按以下几项逐一检查。
1. 沙箱钱包与包可见性配置
沙箱测试需要安装并使用支付宝开放平台提供的沙箱版支付宝,常见包名是:
com.eg.android.AlipayGphoneRC
正式版支付宝的包名通常是:
com.eg.android.AlipayGphone
如果设备上只有正式版支付宝,沙箱订单通常无法正常完成。香港版钱包和大陆支付宝沙箱支付不属于同一条测试链路,一般不用加入。
Android 11 及以上版本可以在 AndroidManifest.xml 的 <manifest> 节点下声明包可见性:
<queries>
<package android:name="com.eg.android.AlipayGphoneRC" />
<package android:name="com.eg.android.AlipayGphone" />
</queries>
<queries> 只能解决应用查询和钱包拉起问题,不能决定订单使用沙箱还是正式环境。实际环境由服务端网关、应用配置、签名密钥和 SDK 环境设置共同决定。
2. APPID、网关和密钥必须属于同一个沙箱应用
以下信息必须来自同一个支付宝沙箱应用:
APPID- 应用私钥
- 支付宝公钥
- 沙箱网关
- 沙箱买家账号
- 沙箱版支付宝客户端
服务端请求应使用开放平台控制台当前提供的沙箱网关,常见地址是:
https://openapi-sandbox.dl.alipaydev.com/gateway.do
不要混用正式环境和沙箱环境的 APPID、支付宝公钥或网关,也不要弄反密钥的用途:
- 应用私钥:商户服务端用它为请求或订单签名。
- 支付宝公钥:商户服务端用它验证支付宝返回结果和异步通知。
- 应用公钥:上传到支付宝开放平台,用于生成或匹配支付宝公钥配置。
如果应用采用公钥证书模式,还需要使用配套的应用证书、支付宝公钥证书和支付宝根证书,不能再按照普通公钥模式拼装参数。
3. 不要在 Android 客户端生成正式支付签名
Android 客户端只需要向业务服务端请求订单,再把服务端返回的完整订单字符串原样交给支付宝 SDK:
PayTask payTask = new PayTask(activity);
Map<String, String> result = payTask.payV2(orderInfo, true);
推荐的调用链路如下:
Android 客户端
→ 业务服务端创建订单并签名
→ 服务端返回完整 orderInfo
→ 客户端调用 payV2
→ 支付宝异步通知业务服务端
→ 服务端验签并更新订单状态
不要把应用私钥硬编码或打包进 APK。即使测试时能够支付,私钥也很容易被反编译提取,攻击者可能借此伪造订单请求。
如果当前 Demo 在本地拼接 app_id、biz_content、timestamp,并使用应用私钥签名,应尽快改为由服务端下单。
4. 检查支付 SDK 的沙箱环境设置
部分版本的支付宝 SDK 需要显式切换到沙箱环境,例如在调用支付前设置沙箱模式:
EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);
不同 SDK 版本使用的类名和支持方式可能不同,应以当前接入版本的官方说明为准。不要自行替换支付宝客户端包名、网关域名或 SDK 内部常量来”模拟”沙箱。
切换环境后,建议清除应用并重新打开,同时清理之前生成的旧订单。正式环境创建的订单不能直接交给沙箱钱包支付,沙箱订单也不能用于正式环境。
5. 核对服务端生成的订单参数
调用 alipay.trade.app.pay 时,至少需要检查:
app_id是否为当前沙箱应用的 APPID。method是否为alipay.trade.app.pay。sign_type是否与控制台配置一致,通常使用RSA2。charset是否为utf-8。timestamp和服务器时间是否准确。out_trade_no是否唯一。total_amount是否为合法的两位小数金额。product_code是否为QUICK_MSECURITY_PAY。- 签名是否包含全部应签参数,签名完成后是否又修改了订单内容。
- 客户端是否原样传递完整订单字符串,没有再次进行 URL 编码、截断或重新排序。
还要查看 payV2 返回的完整结果,不要只显示”系统繁忙”:
String resultStatus = result.get("resultStatus");
String memo = result.get("memo");
String rawResult = result.get("result");
常见状态包括:
9000:支付成功,但最终结果仍应以服务端异步通知和主动查询为准。6001:用户取消。8000:正在处理或结果未知,需要由服务端查询。- 其他状态:结合
memo、完整返回内容和支付宝服务端日志排查。
如果服务端下单接口已经返回 sub_code 或 sub_msg,应先处理对应错误。客户端显示的”系统繁忙”往往只是对实际错误的二次包装。
PID 和 target_id 应该填写什么
PID
pid 是支付宝分配给商户或开发者的合作伙伴身份标识,也称支付宝用户 ID。通常可以在支付宝开放平台或商家平台的账号信息中找到,常见形式是一串以 2088 开头的数字。
它不是以下内容:
- APPID
- 登录手机号
- 支付宝登录邮箱
- 商户订单号
- 应用公钥编号
如果授权 Demo 要求填写 PID,应填写当前沙箱应用所属沙箱商户账号对应的 PID。不要将正式商户 PID 与沙箱 APPID 混用。
target_id
target_id 是商户为本次授权请求生成的唯一业务标识,用于区分不同的授权请求。它不是支付宝分配的固定值,也不是用户的支付宝账号。
可以由服务端生成,例如:
auth_20260908_a83f17c29d4b
生成时需要注意:
- 在商户系统内保持唯一。
- 每次发起新的授权流程时使用新值。
- 只使用安全、稳定的字母和数字组合。
- 长度符合当前授权接口文档的限制。
- 最好由服务端生成并记录,以便关联授权结果并防止重放。
PID、APPID、应用私钥和授权产品配置也必须属于同一个应用环境。授权信息同样应由服务端签名,客户端只负责调用授权 SDK,不应保存应用私钥。
建议的最短排查顺序
先确认手机已安装并登录沙箱版支付宝,再确认 APPID、沙箱网关和密钥全部来自同一个沙箱应用。接着检查服务端 alipay.trade.app.pay 的原始响应,最后记录客户端 payV2 返回的 resultStatus、memo 和完整 result。
如果服务端尚未成功生成完整且已签名的 orderInfo,应先修复服务端配置。如果服务端下单正常,但客户端无法拉起钱包,再检查 SDK 版本、沙箱环境设置和 Android 11 的 <queries> 配置。
备注:内容仅供参考。
