支付宝浏览器登录沙箱账号后跳转“哇哦,出错了”页面
结论
“哇哦,出错了”是支付宝收银台的通用错误页,仅凭这条提示无法判断是否为账号或支付密码错误。如果已经进入沙箱收银台,但提交登录信息后报错,建议依次检查:
- 整个请求是否都在沙箱环境中,包括网关、
app_id、密钥以及买卖双方账号。 - 支付产品是否与 API 对应,例如手机网站支付应使用
alipay.trade.wap.pay。 - 订单号、金额、商品信息等业务参数是否合法。
- 沙箱应用是否已配置并开通相应的支付能力。
- 服务端日志中是否有支付宝返回的
sub_code、sub_msg或验签异常。
如果问题出在环境或订单配置上,反复修改沙箱账号密码通常没有作用。
常见原因
沙箱与正式环境混用
这类问题很常见,例如:
- 使用沙箱
app_id,请求的却是正式环境网关。 - 使用沙箱账号登录,但订单由正式应用创建。
- 应用公钥、支付宝公钥或应用私钥来自另一套应用。
- 买家使用沙箱账号,收款方却配置成正式支付宝账号。
所有配置都应来自同一个沙箱应用。沙箱网关地址可能随平台调整,请以当前沙箱控制台或官方文档显示的地址为准,不要直接沿用年代较早的示例。
支付接口与访问场景不匹配
在手机支付宝浏览器或普通手机浏览器中发起支付,通常使用:
alipay.trade.wap.pay
对应的 product_code 通常是:
QUICK_WAP_WAY
电脑网站支付通常使用:
alipay.trade.page.pay
对应的产品码是:
FAST_INSTANT_TRADE_PAY
如果接口、产品码与应用实际签约的支付能力不一致,收银台可能在提交后显示通用错误页。
订单参数不合法
需要重点检查:
out_trade_no是否为空或重复。total_amount是否为合法的金额字符串,例如0.01。- 金额是否小于等于零,或者包含货币符号、千位分隔符。
subject是否为空。- 同一个订单号是否曾以不同金额重复发起支付。
- 参数 JSON 是否被二次转义或错误编码。
- 系统时间是否明显不准确。
调试时,建议每次请求都生成新的商户订单号,避免旧订单状态干扰判断。
沙箱账号使用错误
沙箱通常会提供买家账号、买家支付密码及对应的卖家信息。请确认:
- 输入的是沙箱买家登录账号,不是应用账号或卖家账号。
- 使用的是沙箱控制台中显示的支付密码。
- 没有在沙箱交易中使用正式支付宝账号。
- 沙箱账号状态正常,测试余额充足。
如果怀疑账号数据异常,可以在沙箱控制台重置相关账号,或换一组沙箱买家账号进行验证。
应用密钥或签名配置错误
能够打开收银台,并不代表签名配置完全正确。还要检查:
sign_type是否与应用配置一致,通常为RSA2。- SDK 中填写的是应用私钥,而不是应用公钥。
- 验签使用的是支付宝公钥,而不是应用公钥。
- 公钥和私钥是否属于当前沙箱应用。
- 密钥内容是否因换行、空格或复制不完整而损坏。
charset是否统一为UTF-8。
建议的排查步骤
1. 确认请求环境
打印支付请求实际使用的配置,但不要在日志中输出完整私钥:
gateway=https://沙箱控制台显示的网关地址
app_id=沙箱应用的 APPID
sign_type=RSA2
charset=UTF-8
api=alipay.trade.wap.pay
如果网关指向正式环境,先修正环境配置。
2. 使用最小订单测试
先去掉非必需参数,只保留订单号、金额、标题和产品码:
{
"out_trade_no": "TEST202609090001",
"total_amount": "0.01",
"subject": "沙箱支付测试",
"product_code": "QUICK_WAP_WAY"
}
如果最小请求可以正常支付,再逐项恢复自定义参数,以便找出具体问题。
3. 检查服务端响应
不要只看浏览器最终显示的页面。创建支付请求时,应记录支付宝 SDK 返回的信息,尤其是:
code
msg
sub_code
sub_msg
接口返回失败时,sub_code 和 sub_msg 往往比“哇哦,出错了”更有助于定位问题。记录日志时,请隐藏私钥、密码、完整签名及用户敏感信息。
4. 更换订单号重新测试
订单号在商户系统内必须唯一。不要重复使用已经支付、已经关闭或金额发生过变化的 out_trade_no。
调试时可以采用类似格式:
String outTradeNo = "TEST" + System.currentTimeMillis();
这种方式只适合调试。生产环境应采用可追踪且能够保证唯一性的订单号生成规则。
5. 检查异步通知地址
notify_url 必须是支付宝服务器可以访问的公网 HTTPS 地址。以下地址通常不能接收异步通知:
http://localhost:8080/alipay/notify
http://127.0.0.1:8080/alipay/notify
不过,异步通知地址无法访问,通常不会直接导致登录后立即显示错误页。如果错误出现在付款确认之前,应先排查环境、订单和产品配置。
Java SDK 示例
下面是手机网站支付的基本结构。网关、密钥及 SDK 的具体构造方式,请以当前使用的支付宝 SDK 版本为准。
AlipayClient alipayClient = new DefaultAlipayClient(
"沙箱控制台显示的网关地址",
"沙箱应用APPID",
"应用私钥",
"json",
"UTF-8",
"支付宝公钥",
"RSA2"
);
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setReturnUrl("https://example.com/alipay/return");
request.setNotifyUrl("https://example.com/alipay/notify");
String outTradeNo = "TEST" + System.currentTimeMillis();
String bizContent = "{"
+ "\"out_trade_no\":\"" + outTradeNo + "\","
+ "\"total_amount\":\"0.01\","
+ "\"subject\":\"沙箱支付测试\","
+ "\"product_code\":\"QUICK_WAP_WAY\""
+ "}";
request.setBizContent(bizContent);
AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);
if (response.isSuccess()) {
// response.getBody() 通常是需要输出给浏览器的表单或页面内容
System.out.println(response.getBody());
} else {
System.err.println("code: " + response.getCode());
System.err.println("msg: " + response.getMsg());
System.err.println("sub_code: " + response.getSubCode());
System.err.println("sub_msg: " + response.getSubMsg());
}
不要把 response.getBody() 当作普通 URL 随意拼接。对于网页支付,它可能是一段自动提交的 HTML 表单,应按照 SDK 接口说明直接返回给浏览器。
回调验签示例
收到异步通知后,必须先验签,再根据 out_trade_no、trade_no、total_amount 和订单状态更新业务数据:
Map<String, String> params = new HashMap<>();
for (Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
String value = String.join(",", entry.getValue());
params.put(entry.getKey(), value);
}
boolean verified = AlipaySignature.rsaCheckV1(
params,
alipayPublicKey,
"UTF-8",
"RSA2"
);
if (!verified) {
throw new SecurityException("支付宝通知验签失败");
}
验签成功并完成幂等处理后,通知接口应按支付宝要求返回成功响应。具体返回格式请以当前接口文档为准。
注意事项
- 应用私钥不能保存在前端代码中,签名必须由服务端完成。
- 正式环境账号、密钥和沙箱配置不能混用。
- 排查时不要只保留错误页面截图,还应记录请求时间、订单号、API 名称和服务端错误码。
- 如果使用最小订单、完整的沙箱配置和另一组沙箱买家账号后仍能复现问题,请整理
app_id、接口名、请求时间、out_trade_no、sub_code和sub_msg,再联系支付宝开放平台技术支持核查。 - 提交问题时,不要公开应用私钥、支付密码、完整签名或个人账号信息。
备注:内容仅供参考。
