沙箱支付宝扫码支付提示二维码失效,部分用户仍可支付
结论
同一个沙箱二维码,不同用户扫码后出现不同结果,通常不是二维码随机失效,而是部分用户的支付宝客户端或账号不符合沙箱支付条件。
能够正常支付的同事,一般使用了沙箱环境支持的客户端,并登录了沙箱买家账号。无法支付的同事则可能使用了正式支付宝账号、错误的沙箱账号,或者客户端登录状态与当前沙箱应用不匹配。当支付宝客户端无法识别沙箱交易或当前账号无权支付时,可能统一提示”码已失效,请刷新二维码重试”。这个提示并不一定表示二维码已经过期。
常见原因
1. 扫码账号不是沙箱买家账号
沙箱应用发起的交易只能在对应的沙箱环境中完成,普通支付宝账号无法直接支付沙箱订单。
测试人员需要前往支付宝开放平台的沙箱账号页面获取买家账号,并按照页面提供的方式登录沙箱支付环境。自行注册的普通支付宝账号不能代替沙箱买家账号。
2. 客户端或登录环境不匹配
部分沙箱能力可能要求使用指定的沙箱客户端,具体支持方式以当前支付宝开放平台沙箱页面的说明为准。
如果一名同事使用沙箱客户端和沙箱买家账号,另一名同事使用正式支付宝客户端或正式账号,即使两人扫描同一个二维码,也可能看到不同结果。
3. 二维码对应的订单已经失效
二维码对应的是一笔预创建交易,不是普通网址。出现以下任一情况后,订单都可能无法继续支付:
- 订单已经支付成功;
- 订单已经关闭;
- 超过了订单允许的支付时间;
- 商户重新生成订单时错误复用了
out_trade_no; - 二维码来自旧的沙箱应用或旧配置;
- 生成二维码后切换了网关、应用、密钥或商户身份。
如果某位同事已经完成支付,其他人再次扫描这笔订单的二维码,也无法重复完成同一笔交易。
4. 不同用户扫描的不是同一笔有效订单
页面缓存、前端轮询异常或二维码没有及时更新,都可能让部分用户看到旧二维码。二维码图片表面上相同,但测试时对应的订单状态可能已经发生变化。
因此,不要仅凭客户端提示判断订单是否过期,还需要通过交易查询接口确认服务端记录的状态。
排查步骤
第一步:统一测试环境
先让所有测试人员逐项确认以下信息:
- 使用当前沙箱环境要求的支付客户端;
- 登录的是开放平台提供的沙箱买家账号;
- 没有登录正式支付宝账号;
- 使用的是同一个沙箱应用;
- 服务端请求发送到沙箱网关;
- 应用 ID、商户私钥和支付宝公钥属于同一套沙箱配置。
不要让多人同时共用一个沙箱买家账号进行测试,否则登录状态或交易状态可能互相影响。
第二步:每次测试生成新的订单号
out_trade_no 是商户订单号,在商户侧必须保持唯一。重新测试时,不要反复使用旧订单号。
String outTradeNo =
"SANDBOX_" + System.currentTimeMillis() + "_"
+ UUID.randomUUID().toString().replace("-", "");
生成二维码时,可以明确设置订单标题、金额和超时时间:
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
model.setOutTradeNo(outTradeNo);
model.setSubject("沙箱扫码支付测试");
model.setTotalAmount("0.01");
model.setTimeoutExpress("10m");
request.setBizModel(model);
AlipayTradePrecreateResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
String qrCode = response.getQrCode();
System.out.println("QR Code: " + qrCode);
} else {
System.err.println("subCode: " + response.getSubCode());
System.err.println("subMsg: " + response.getSubMsg());
}
这段示例只展示关键调用方式。相关类名和方法是否可用,取决于项目使用的支付宝 Java SDK 版本。
第三步:查询订单的真实状态
扫码失败后,应立即调用 alipay.trade.query 查询订单,不要只记录客户端显示的”码已失效”。
AlipayTradeQueryRequest queryRequest = new AlipayTradeQueryRequest();
AlipayTradeQueryModel queryModel = new AlipayTradeQueryModel();
queryModel.setOutTradeNo(outTradeNo);
queryRequest.setBizModel(queryModel);
AlipayTradeQueryResponse queryResponse =
alipayClient.execute(queryRequest);
System.out.println("code: " + queryResponse.getCode());
System.out.println("subCode: " + queryResponse.getSubCode());
System.out.println("subMsg: " + queryResponse.getSubMsg());
System.out.println("tradeStatus: " + queryResponse.getTradeStatus());
主要检查以下交易状态:
WAIT_BUYER_PAY:订单有效,正在等待买家付款;TRADE_SUCCESS:支付成功;TRADE_FINISHED:交易结束,不可继续操作;TRADE_CLOSED:交易已经关闭。
如果查询结果仍是 WAIT_BUYER_PAY,但只有部分账号扫码失败,应先检查失败用户使用的客户端、登录账号和沙箱资格。
如果状态是 TRADE_SUCCESS 或 TRADE_CLOSED,说明二维码对应的交易确实无法再次支付。此时应创建新的商户订单,并生成新的二维码。
第四步:记录接口完整返回
建议在日志中记录以下信息:
app_id
out_trade_no
code
msg
sub_code
sub_msg
trade_no
trade_status
二维码生成时间
扫码账号类型
客户端类型
不要在日志中记录账号密码、私钥、完整授权令牌等敏感信息。
建议的验证方法
可以创建两笔全新的沙箱订单进行交叉验证:
- 使用确认有效的沙箱买家账号扫描第一笔订单;
- 使用出现问题的账号扫描第二笔订单;
- 两次测试使用相同的服务端应用配置;
- 分别调用
alipay.trade.query查询两笔订单的状态; - 对比两个账号使用的客户端、登录环境和接口返回。
如果有效的沙箱账号始终可以支付,而普通账号或其他环境中的账号始终提示失效,基本可以判断问题出在扫码用户的沙箱环境,而不是二维码生成逻辑。
注意事项
- 沙箱订单和正式环境订单不能混用。
- 沙箱应用配置、网关、密钥和买家账号必须属于相互匹配的环境。
- 同一笔订单只能完成一次支付,不适合多人将其作为公共测试订单反复扫码。
- 前端展示二维码时,应根据订单有效期及时刷新,并停止展示已经支付成功或关闭的订单。
- 客户端显示的”二维码失效”只是面向用户的概括性提示。判断交易状态时,应以预创建接口返回、交易查询结果和服务端日志为准。
- 如果账号和环境已经确认一致,但结果仍然不同,应保存
out_trade_no、code、sub_code、sub_msg等信息,再根据支付宝开放平台当前的沙箱说明或通过技术支持渠道进一步核对。
备注:内容仅供参考。
