获取支付宝订单号tradeNO后,uniapp(app端)如何唤起支付?
结论
通常情况下,仅凭支付宝交易号 tradeNO,无法在 uni-app App 端直接唤起支付宝支付。
支付宝支付要求 uni.requestPayment 的 orderInfo 参数是完整的签名订单字符串。这个字符串需要由服务端调用支付宝 App 支付接口生成,不能用支付宝交易号代替。支付流程如下:
- App 请求业务服务端创建订单。
- 服务端调用支付宝
alipay.trade.app.pay,生成签名后的orderString。 - App 将
orderString作为orderInfo传给uni.requestPayment。 - 最终支付结果以支付宝服务端异步通知为准。
有些项目虽然把变量命名为 tradeNO,其中保存的却是完整的支付宝签名订单字符串。这种情况下可以直接将它作为 orderInfo 使用,但要先确认变量的实际内容。
tradeNO 和 orderInfo 的区别
以下几个字段容易混淆:
out_trade_no:商户系统生成的业务订单号。trade_no:支付宝创建交易后生成的支付宝交易号。orderInfo:App 支付 SDK 所需的完整签名参数字符串。
支付宝 App 支付除了订单编号,还需要金额、商品信息、应用 ID、回调地址、时间戳和签名等参数。单独的 trade_no 或 out_trade_no 无法完成客户端支付调用。
uni-app App 端调用方式
假设服务端返回以下数据:
{
"code": 0,
"data": {
"orderString": "app_id=...&biz_content=...&charset=utf-8&method=alipay.trade.app.pay&sign=..."
}
}
App 端可以这样调用:
async function payWithAlipay() {
try {
const response = await uni.request({
url: 'https://example.com/api/payment/alipay/create',
method: 'POST',
data: {
orderId: 'YOUR_BUSINESS_ORDER_ID'
}
});
const result = response.data;
if (result.code !== 0 || !result.data?.orderString) {
throw new Error(result.message || '创建支付宝订单失败');
}
uni.requestPayment({
provider: 'alipay',
orderInfo: result.data.orderString,
success(payResult) {
console.log('支付宝 SDK 返回成功:', payResult);
// 不要仅凭这里的结果更新订单状态
// 应继续向业务服务端查询订单的最终支付状态
queryOrderStatus();
},
fail(error) {
console.error('支付宝支付未完成:', error);
// 用户取消、SDK 异常和支付失败都会进入这里,
// 最终状态仍建议向服务端查询确认
}
});
} catch (error) {
console.error('发起支付失败:', error);
uni.showToast({
title: error.message || '发起支付失败',
icon: 'none'
});
}
}
调用支付前,也可以先检查当前 App 是否支持支付宝支付:
uni.getProvider({
service: 'payment',
success(result) {
if (result.provider.includes('alipay')) {
payWithAlipay();
} else {
uni.showToast({
title: '当前环境不支持支付宝支付',
icon: 'none'
});
}
},
fail(error) {
console.error('获取支付服务失败:', error);
}
});
如果 tradeNO 实际是完整订单字符串
有些项目会把服务端返回的支付参数误命名为 tradeNO。如果它的内容类似这样:
app_id=...&biz_content=...&charset=utf-8&method=alipay.trade.app.pay&sign_type=RSA2×tamp=...&sign=...
它就不是单独的支付宝交易号,而是支付 SDK 需要的订单字符串,可以直接使用:
uni.requestPayment({
provider: 'alipay',
orderInfo: tradeNO,
success(result) {
console.log('支付调用完成:', result);
},
fail(error) {
console.error('支付调用失败:', error);
}
});
如果内容只是一个编号,例如:
2026xxxxxxxxxxxxxxxxxxxx
就不能直接传给 orderInfo,需要由服务端重新生成 App 支付订单字符串。
服务端需要做什么
服务端需要完成这些工作:
- 根据业务订单读取实际金额,不能直接信任客户端传入的金额。
- 调用支付宝
alipay.trade.app.pay。 - 使用商户私钥完成签名。
- 将生成的订单字符串返回给 App。
- 接收支付宝异步通知并验签。
- 验证商户号、应用 ID、订单号、金额和支付状态。
- 以幂等方式更新业务订单。
以下伪代码仅用于说明数据流,具体写法取决于服务端语言和使用的支付宝 SDK:
const orderString = alipaySdk.appPay({
notify_url: 'https://example.com/api/payment/alipay/notify',
bizContent: {
out_trade_no: businessOrderNo,
total_amount: orderAmount,
subject: orderSubject,
product_code: 'QUICK_MSECURITY_PAY'
}
});
return {
code: 0,
data: {
orderString
}
};
签名必须由服务端完成,不能把商户私钥放进 uni-app 客户端代码。
注意事项
1. 只适用于 App 端
uni.requestPayment 配合 provider: 'alipay' 的方式适用于打包后的 App。H5 和小程序等平台有各自的支付接入方式,不能直接套用。
2. 检查支付模块配置
需要在 uni-app 项目的 App 模块配置中启用支付宝支付能力,然后重新制作自定义基座或重新打包。如果只修改配置,仍然使用旧基座,支付模块可能不会生效。
3. 使用真机测试
支付宝 App 支付依赖原生 SDK 和支付宝客户端,需要在安装了支付宝的真机上测试。普通浏览器无法完整验证这条支付链路。
4. 客户端回调不是最终凭证
success 只表示支付宝 SDK 返回了成功结果。业务订单是否支付成功,应以服务端收到并通过验签的异步通知为准,也可以由服务端主动查询支付宝订单后确认。
5. 不要重复创建支付订单
用户重复点击支付按钮时,客户端要做好按钮防抖,服务端也要进行幂等处理。订单已经支付、已经关闭或金额不一致时,服务端应拒绝再次生成支付参数。
拿到 tradeNO 后,先确认它是支付宝交易号,还是名称有误的完整支付订单字符串。支付宝交易号不能直接唤起支付,只有完整的支付订单字符串才能传给 uni.requestPayment 的 orderInfo。
备注:内容仅供参考。
