Revolut merchant API 支付失败:code 2007 与 502
结论
502 是 HTTP Bad Gateway,表示 Revolut Checkout 请求经过网关时,上游服务没有返回有效响应。2007 是 Checkout SDK 返回的业务错误码,不属于 HTTP 状态码。仅凭 2007 无法准确判断原因。如果使用的是 Sandbox,首先应检查是否把 Sandbox 创建的 public_id 传给了默认连接生产环境的 Checkout SDK。
初始化 Checkout 时,需要明确指定与订单一致的环境:
RevolutCheckout(public_id, "sandbox").then((instance) => {
instance.payWithPopup({
onSuccess: () => this.$emit("success"),
onError: (error) => {
console.error("Revolut payment failed:", error);
},
});
});
生产订单应使用生产环境配置,不要添加 "sandbox",也可以按照当前 SDK 文档显式指定生产模式。
为什么会同时出现 2007 和 502
这两个错误来自不同层级:
502是服务端或网关层返回的 HTTP 状态码,表示网关未能从上游服务获得有效响应。2007是 Revolut Checkout SDK 对失败结果的封装,可能表示订单加载或支付初始化失败,但不等同于 HTTP502。- 如果订单通过 Sandbox API 创建,而前端 SDK 连接的是生产环境,生产环境将无法识别该
public_id。最终可能同时出现 SDK 错误和异常的服务端响应。
因此,不能把 2007 当成标准 HTTP 错误码单独查询并据此定位问题。失败请求的 URL、HTTP 响应正文、订单所属环境和 Revolut 返回的请求标识更有诊断价值。
排查步骤
1. 确认前后端环境一致
检查后端创建订单时使用的 API 地址和凭据:
- Sandbox API、Sandbox API key 和 Sandbox
public_id必须配合 Sandbox Checkout。 - Production API、Production API key 和 Production
public_id必须配合 Production Checkout。
Sandbox 初始化示例:
async function openRevolutCheckout(publicId) {
try {
const checkout = await RevolutCheckout(publicId, "sandbox");
checkout.payWithPopup({
onSuccess() {
console.log("Checkout completed");
},
onError(error) {
console.error("Checkout error:", error);
},
onCancel() {
console.log("Checkout cancelled");
},
});
} catch (error) {
console.error("Failed to initialize Revolut Checkout:", error);
}
}
环境参数的取值可能随 SDK 版本变化,请以当前加载版本的官方文档为准。
2. 检查传入的标识
确认 public_id 确实来自“创建订单”接口的响应,而不是以下字段或标识:
- 内部数据库订单 ID;
- 商户自定义的
merchant_order_ext_ref; - 支付 ID、交易 ID 或其他字段;
- 已过期、已取消或已完成的订单标识;
- 由另一套 Sandbox 或 Production 商户账户创建的订单。
还应输出实际值及其类型,排除 undefined、空字符串或对象字段取错等情况:
console.log({
publicId: public_id,
type: typeof public_id,
});
if (typeof public_id !== "string" || public_id.length === 0) {
throw new Error("Invalid Revolut public_id");
}
不要将 API key、Authorization header 或其他密钥输出到浏览器控制台。
3. 查看真正失败的网络请求
打开浏览器开发者工具的 Network 面板,重新发起支付,然后检查失败的请求:
- Request URL 指向 Sandbox 还是 Production;
- HTTP 状态码是否确实为
502; - Response body 是否包含
message、code、request_id或类似字段; - 请求是否受到代理、VPN、广告拦截器或企业网络的影响;
- 页面是否受到 Content Security Policy、第三方 Cookie 或弹窗限制。
alert(message) 遇到对象时通常只会显示 [object Object],不利于诊断。应先记录完整错误:
onError(error) {
console.error("Revolut Checkout error:", error);
const message =
typeof error === "string"
? error
: error?.message || "Payment failed";
alert(message);
}
4. 核对订单创建响应
后端创建订单后,需要检查:
- HTTP 状态码是否表示请求成功;
- 响应中是否包含有效的
public_id; - 金额和币种是否合法;
- API key 是否属于对应的商户和环境;
- 是否错误缓存或重复使用了旧订单。
后端不能只将上游响应中的 public_id 原样返回,还需要处理非成功状态:
async function createCheckoutOrder() {
const response = await fetch("/api/revolut/orders", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
const body = await response.json();
if (!response.ok) {
throw new Error(body.message || `Order creation failed: ${response.status}`);
}
if (!body.public_id) {
throw new Error("Revolut response does not contain public_id");
}
return body.public_id;
}
如果环境和参数都正确
如果相同请求此前可以正常运行,但现在持续返回 502,原因也可能是 Revolut 上游服务、网关或区域网络暂时发生故障。可以对订单查询或初始化进行有限次数的重试,但不要无条件重复创建订单或发起扣款。
联系 Revolut Merchant 支持时,请提供:
- 错误发生的准确时间和时区;
- Sandbox 或 Production 环境;
- HTTP 状态码和经过脱敏的响应正文;
- Network 面板中的请求 URL;
- Revolut 返回的 request ID、trace ID 或 correlation ID;
- 相关订单 ID 或
public_id; - Checkout SDK 版本或脚本地址。
不要提交 API key、Authorization token、完整银行卡信息或其他敏感数据。
注意事项
502 不表示银行卡被拒绝,也不能据此直接提示用户“余额不足”或“支付被银行拒绝”。它表示当前请求未能获得有效的上游响应。确认订单环境、标识和请求参数均无误后,才能继续判断是否属于 Revolut 服务端故障。
对于示例中的情况,应先检查是否混用了 Sandbox 和 Production。进行 Sandbox 测试时,将初始化代码改为:
RevolutCheckout(public_id, "sandbox")
如果修改后仍然出现 2007 和 502,应根据浏览器中失败请求的响应正文和请求标识继续排查,不要只依赖 SDK 显示的 2007。
备注:内容仅供参考。
