Node.js alipay-sdk 调用 alipay.trade.app.pay 返回 302
结论
这不是支付宝 App 支付的正常响应,也不是需要客户端继续访问的支付跳转。
调用 alipay.trade.app.pay 时,如果收到 HTTP 302,并且 Location 中出现:
http://openapi.alipay.com/none?...
通常是支付宝网关地址配置有误,或者请求路径丢失。最常见的原因是网关只配置了 https://openapi.alipay.com,缺少 /gateway.do。支付宝网关路由请求时得到异常路径 /none,而 alipay-sdk 不会将该重定向视为成功响应,因此抛出:
[AlipaySdk]HTTP 请求错误
遇到这种情况,应先检查 SDK 的网关配置,不要手动跟随 302。
检查支付宝网关地址
生产环境的网关通常应配置为:
https://openapi.alipay.com/gateway.do
沙箱环境使用:
https://openapi-sandbox.dl.alipaydev.com/gateway.do
不要写成:
https://openapi.alipay.com
生产应用和沙箱网关也不能混用。
不同版本的 alipay-sdk 可能使用不同的配置字段,具体应以当前安装版本的类型定义或说明为准。常见配置如下:
import AlipaySdk from 'alipay-sdk';
const alipayClient = new AlipaySdk({
appId: process.env.ALIPAY_APP_ID,
privateKey: process.env.ALIPAY_APP_PRIVATE_KEY,
alipayPublicKey: process.env.ALIPAY_PUBLIC_KEY,
signType: 'RSA2',
gateway: 'https://openapi.alipay.com/gateway.do',
timeout: 10000
});
需要确认最终请求地址确实包含 /gateway.do。如果项目使用了环境变量、配置中心或二次封装,还要检查网关地址是否被覆盖为空值、undefined、none,或者只剩域名。
推荐的调用方式
const orderString = await alipayClient.exec('alipay.trade.app.pay', {
notifyUrl: 'https://example.com/api/alipay/notify',
bizContent: {
outTradeNo: order._id.toString(),
totalAmount: '99.00',
subject: `****${product.title}`,
productCode: 'QUICK_MSECURITY_PAY'
},
needEncrypt: false
});
正常情况下,服务端会得到一段用于调起支付宝 App SDK 的已签名订单字符串,并将它原样返回给 Android 或 iOS 客户端。
alipay.trade.app.pay 不是网页支付接口,所以不能把这里的 302 Location 返回给 App,也不能将其作为浏览器支付地址。网页支付应使用对应的 alipay.trade.page.pay 或 alipay.trade.wap.pay 接口。
仍然报错时的排查顺序
1. 确认实际请求地址
查看异常中的 requestUrls 或 SDK 调试日志,确认请求目标是:
https://openapi.alipay.com/gateway.do
如果请求经过反向代理、API 网关或自建 HTTP 客户端,还要确认这些组件没有删除 /gateway.do,也没有将 HTTPS 改成 HTTP。
2. 确认环境完全匹配
以下配置必须属于同一环境:
appId- 应用私钥
- 支付宝公钥
- 支付宝网关
- 应用授权及签约状态
生产应用不能使用沙箱网关,沙箱应用也不能直接调用生产网关。
3. 检查密钥配置
privateKey 应填写应用私钥,alipayPublicKey 应填写支付宝公钥,不能误填应用公钥。
如果密钥来自环境变量,需要恢复真实换行:
const privateKey = process.env.ALIPAY_APP_PRIVATE_KEY?.replace(/\\n/g, '\n');
const alipayPublicKey = process.env.ALIPAY_PUBLIC_KEY?.replace(/\\n/g, '\n');
密钥或签名错误通常会返回支付宝业务错误码,而不是触发 /none 重定向,但这部分配置仍需检查。
4. 检查业务参数
totalAmount 建议使用字符串,并明确保留两位小数:
totalAmount: '99.00'
不要直接依赖 JavaScript 浮点数计算支付金额。更稳妥的方式是在系统内部以整数分保存金额,提交前再转换为元。
outTradeNo 必须在商户侧保持唯一,subject 不能为空。App 支付建议明确传入:
productCode: 'QUICK_MSECURITY_PAY'
5. 检查 AES 加密配置
如果应用没有启用接口内容加密,可以保留:
needEncrypt: false
如果支付宝开放平台中已启用 AES 加密,则需要按照当前 SDK 的要求配置 AES 密钥并启用加密。AES 配置不一致通常会产生明确的验签或解密错误,因此不是此次 302 的首要排查方向。
不要通过跟随 302 解决
Location 中的 alipay_exterface_invoke_assign_target、invoke_id 等参数是支付宝网关的内部路由信息,业务代码不应解析、保存或重新签名这些参数。
即使 HTTP 客户端支持自动重定向,也不建议以此绕过问题。应修复初始网关地址和 SDK 配置,让请求直接发送到 /gateway.do。如果网关地址正确后仍然收到 302,需要记录 trace_id、invoke_id、请求时间以及脱敏后的实际请求 URL,再通过支付宝开放平台技术支持继续定位。
备注:内容仅供参考。
