PAYATHON 2026

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 对失败结果的封装,可能表示订单加载或支付初始化失败,但不等同于 HTTP 502。
  • 如果订单通过 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。

备注:内容仅供参考。