App 未上架时如何在测试环境调试支付宝 App 支付 API?
结论
App 还没上架,也可以联调支付宝 App 支付接口。只要已经在支付宝开放平台创建应用,并取得沙箱环境的 app_id、密钥和沙箱买家账号,就能在测试安装包中接入 App 支付 SDK,通过沙箱网关测试下单、唤起支付宝和接收支付结果通知等流程。
沙箱能力、测试钱包支持的平台以及应用签约要求可能会随开放平台调整,请以当前控制台显示的信息为准。沙箱配置和生产环境配置不能混用。
调试流程
1. 创建开放平台应用并进入沙箱环境
先在支付宝开放平台控制台创建应用,再进入开发工具或沙箱相关页面,获取以下信息:
- 沙箱应用
app_id - 应用私钥
- 支付宝公钥,或支付宝公钥证书
- 沙箱买家账号及登录密码
- 沙箱网关地址
常见的沙箱网关是:
https://openapi.alipaydev.com/gateway.do
生产网关通常是:
https://openapi.alipay.com/gateway.do
具体地址请以控制台当前配置为准。
2. 在服务端生成支付订单
不要在 App 中保存应用私钥,也不要让 App 自行拼接和签名支付请求。支付流程应当是:
- App 请求业务服务端创建订单。
- 服务端调用
alipay.trade.app.pay,生成签名后的订单字符串。 - 服务端将订单字符串返回给 App。
- App 通过支付宝客户端 SDK 发起支付。
- 服务端根据异步通知确认最终支付结果。
Java 服务端示例:
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipaydev.com/gateway.do",
APP_ID,
APP_PRIVATE_KEY,
"json",
"UTF-8",
ALIPAY_PUBLIC_KEY,
"RSA2"
);
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
request.setNotifyUrl("https://example.com/api/alipay/notify");
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setSubject("测试商品");
model.setOutTradeNo("TEST_" + System.currentTimeMillis());
model.setTotalAmount("0.01");
model.setProductCode("QUICK_MSECURITY_PAY");
request.setBizModel(model);
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
if (!response.isSuccess()) {
throw new IllegalStateException(
response.getCode() + ": " + response.getSubMsg()
);
}
String orderString = response.getBody();
orderString 是已经完成签名的完整支付参数,需要原样返回给 App,不能再次编码或重新拼接。
如果使用证书模式,需要通过对应的证书客户端初始化方式,配置应用公钥证书、支付宝公钥证书和支付宝根证书,不能按普通公钥模式处理。
3. App 调用支付 SDK
以 Android 为例,App 拿到服务端返回的 orderString 后,可以调用支付宝 SDK:
Runnable payRunnable = () -> {
PayTask payTask = new PayTask(activity);
Map<String, String> result = payTask.payV2(orderString, true);
activity.runOnUiThread(() -> {
String resultStatus = result.get("resultStatus");
String memo = result.get("memo");
// 客户端结果仅用于页面展示,
// 订单最终状态应由服务端查询或异步通知确认。
});
};
Thread payThread = new Thread(payRunnable);
payThread.start();
支付 SDK 的依赖配置、Android 清单要求和 iOS 回跳配置,请按照当前版本的支付宝 App 支付接入文档处理。不同版本的 SDK 可能采用不同的初始化方式,不要直接照搬过旧的示例。
4. 使用沙箱账号完成支付
测试时,需要使用沙箱提供的买家账号,以及与沙箱环境匹配的支付宝测试客户端。普通支付宝账号通常不能直接用于沙箱交易。
如果控制台只提供某个平台的沙箱钱包,例如只提供 Android 测试客户端,就需要在该平台完成整个沙箱支付流程。其他平台可以先验证下单、签名、回跳和服务端业务逻辑,再根据开放平台当前的支持情况安排真机联调。
5. 验证异步通知
支付完成后,支付宝会向 notify_url 发送异步通知。该地址必须能够被支付宝服务器访问,localhost、局域网 IP 等地址通常无法直接接收通知。
服务端收到通知后,至少需要完成以下处理:
- 验证支付宝签名。
- 校验
app_id。 - 确认
out_trade_no属于当前系统。 - 确认
total_amount与订单金额一致。 - 判断
trade_status。 - 以幂等方式更新订单。
- 处理成功后返回纯文本
success。
示意代码:
boolean valid = AlipaySignature.rsaCheckV1(
requestParams,
ALIPAY_PUBLIC_KEY,
"UTF-8",
"RSA2"
);
if (!valid) {
return "failure";
}
String appId = requestParams.get("app_id");
String outTradeNo = requestParams.get("out_trade_no");
String totalAmount = requestParams.get("total_amount");
String tradeStatus = requestParams.get("trade_status");
if (!APP_ID.equals(appId)) {
return "failure";
}
// 继续校验订单号、金额和订单状态。
// 更新操作必须保证幂等。
if ("TRADE_SUCCESS".equals(tradeStatus)
|| "TRADE_FINISHED".equals(tradeStatus)) {
return "success";
}
return "failure";
常见问题
唤不起支付宝客户端
可以重点检查以下配置:
- 是否使用 App 支付 SDK,而不是手机网站支付接口。
- Android 包配置或 iOS URL Scheme 是否正确。
- 测试设备是否安装了沙箱支持的支付宝客户端。
orderString是否完整传递,是否经过重复 URL 编码。- 服务端是否使用沙箱
app_id和沙箱网关。
出现签名错误
常见原因包括:
- 应用私钥与平台配置的应用公钥不匹配。
- 把支付宝公钥误当成应用公钥。
- 混用普通公钥模式和证书模式。
RSA2、字符集或签名算法的配置不一致。- 修改了已经签名的订单字符串。
- 混用沙箱环境和生产环境的密钥。
App 返回支付成功,但服务端订单仍未支付
客户端返回的结果可能受到网络中断、回跳失败或结果伪造的影响,不能据此发货。服务端应优先通过支付宝异步通知确认订单状态,必要时再调用交易查询接口核实。
注意事项
- App 是否上架和能否进行技术联调没有直接关系,内部测试包、真机安装包也可以接入支付 SDK。
- 沙箱数据与生产数据完全隔离。切换到生产环境时,需要同时更换网关、
app_id、密钥或证书、账号及相关配置。 - 应用私钥只能保存在服务端,不能写入 App、前端代码或公开仓库。
- 测试订单号必须唯一。重复使用
out_trade_no,可能导致重复下单错误或返回旧交易状态。 - 异步通知可能会重复发送,因此订单更新必须具备幂等性。
- 上线前,仍需按照开放平台当时的要求完成应用审核、能力签约和生产配置,并在真实环境中重新进行小额支付验证。
备注:内容仅供参考。
