PAYATHON 2026

Converge Lightbox Integration 调用时返回 403

支付阿杰

结论

成功获取 session token,只能证明服务器访问 transaction_token 接口时,认证和 IP 白名单配置有效。PayWithConverge.open() 调用的 hpm/initialize 由浏览器发起,还可能校验 token、运行环境和页面的 Origin/Referer。

出现这类 403 时,重点检查以下问题:

  1. Converge Hosted Payments 未允许当前页面的来源域名或 URL;
  2. session token 已过期、已使用,或者传入的内容不是纯 token 字符串;
  3. demo token 与生产环境的 JavaScript/API 混用;
  4. 创建 token 时使用的 Hosted Payments 配置未启用 Lightbox,或者终端配置受限。

仅把开发服务器的出口 IP 加入白名单,通常还不能满足 Lightbox 的浏览器端授权要求。

首先检查页面来源

transaction_token 是后端请求,Converge 看到的是开发服务器的出口 IP。hpm/initialize 由浏览器发起,通常会携带当前页面的来源信息。

请确认测试页面符合以下条件:

  • 通过 http:// 或 https:// 打开,而不是 file://;
  • 使用固定的主机名和端口;
  • 页面域名、协议和端口已按 Converge 账户的要求登记;
  • 没有在 localhost、IP 地址和开发域名之间切换;
  • 反向代理没有改变外部访问地址。

例如,以下地址可能会被视为不同的 Origin:

http://localhost:3000
http://127.0.0.1:3000
https://dev.example.com
https://dev.example.com:8443

如果管理后台没有 Hosted Payments 来源配置入口,需要向 Converge 支持人员确认当前 demo 账户是否允许实际测试页面的 URL,以及该终端是否已启用 Hosted Payments Lightbox。账户版本不同,具体配置名称也可能不同。

确认 demo 环境完全一致

获取 token 和加载 Lightbox JavaScript 必须使用同一环境。既然 token 来自:

https://api.demo.convergepay.com/hosted-payments/transaction_token

页面加载的 PayWithConverge 脚本也应来自 Converge 的 demo 环境。不要把 demo token 传给生产环境脚本,也不要使用生产凭据调用 demo 接口。

可以在浏览器开发者工具的 Network 面板中确认:

  • Lightbox 脚本来自 api.demo.convergepay.com;
  • hpm/initialize 请求也发往 demo 域名;
  • 页面没有同时加载生产环境或旧地址的 SDK;
  • 控制台中的 PayWithConverge 确实由预期脚本提供。

检查 token 的实际内容

ssl_txn_auth_token 必须是刚生成且未经修改的 token。常见错误包括:

  • 把整个 JSON 响应放进隐藏字段;
  • token 前后带有空格、换行或引号;
  • 页面转义改变了 token 内容;
  • 重复使用已经初始化过的 token;
  • token 生成后等待过久才打开 Lightbox。

客户端至少应清理首尾空白,并阻止重复提交:

let lightboxOpening = false;

function openLightbox() {
    const token = document.getElementById("token").value.trim();

    if (!token) {
        showResult("error", "Missing transaction token");
        return;
    }

    if (lightboxOpening) {
        return;
    }

    lightboxOpening = true;

    const paymentFields = {
        ssl_txn_auth_token: token
    };

    const callback = {
        onError: function (error) {
            lightboxOpening = false;
            showResult(
                "error",
                typeof error === "string" ? error : JSON.stringify(error, null, 2)
            );
        },
        onCancelled: function () {
            lightboxOpening = false;
            showResult("cancelled", "");
        },
        onDeclined: function (response) {
            lightboxOpening = false;
            showResult("declined", JSON.stringify(response, null, 2));
        },
        onApproval: function (response) {
            lightboxOpening = false;
            showResult("approval", JSON.stringify(response, null, 2));
        }
    };

    PayWithConverge.open(paymentFields, callback);
}

不要在日志、页面错误信息或截图中公开完整 token。调试时可以只记录 token 长度或经过掩码处理的片段:

console.log("token length:", token.length);
console.log("token preview:", token.slice(0, 6) + "...");

每次重试前都应从服务器重新申请 token,不要用同一个 token 反复调用 open()。

正确处理后端响应

如果由后端调用 transaction_token,需要先明确提取 token,再返回给前端。不要假设上游响应一定是 JSON,应按照实际的 Content-Type 和响应格式处理。

示意代码如下:

const response = await fetch("/api/create-converge-token", {
    method: "POST"
});

if (!response.ok) {
    throw new Error(`Token request failed: ${response.status}`);
}

const data = await response.json();
const token = String(data.token || "").trim();

if (!token) {
    throw new Error("Converge returned an empty token");
}

document.getElementById("token").value = token;
openLightbox();

这里的 data.token 只是应用后端返回格式的示例,不表示 Converge 原始响应一定包含这个字段。后端需要按实际响应格式解析。

根据 Network 信息进一步定位

在开发者工具中打开失败的 hpm/initialize 请求,检查以下内容:

  • Request URL;
  • Request Headers 中的 Origin 和 Referer;
  • 请求负载中的 token 是否为空;
  • Response Headers;
  • Response body 是否包含错误代码或说明。

可以根据具体表现判断原因:

  • Origin 或 Referer 与登记地址不一致:修正测试地址,或申请将其加入允许列表;
  • token 为空或格式异常:修正后端解析和前端赋值;
  • 新 token 第一次调用就立即返回 403:检查账户、终端和 Lightbox 功能权限;
  • 只有重复调用时失败:将 token 按一次性凭证处理,每次重新生成;
  • demo 与生产域名混用:统一环境和凭据。

不要尝试在前端绕过 403

这个 403 来自 Converge 服务端的授权判断,通常无法通过以下方法解决:

  • 添加 Access-Control-Allow-Origin;
  • 使用 mode: "no-cors";
  • 禁用浏览器安全策略;
  • 修改 hpm-*.js;
  • 在前端暴露商户凭据并重新申请 token。

如果来源、环境和 token 均已确认无误,但请求仍返回 403,应向 Converge 支持提供以下非敏感信息:

  • demo 或 production 环境;
  • 商户或终端标识,但不要提供密码、PIN 或完整 token;
  • 测试页面的完整 Origin;
  • 失败时间和所在时区;
  • hpm/initialize 的 HTTP 状态码;
  • 响应中的错误标识;
  • 从浏览器 Network 导出的请求信息,提交前删除 token 和敏感请求头。

应优先确认两点:Converge 是否只配置了服务器 IP 白名单,却没有允许实际承载 Lightbox 的页面来源;当前终端是否已启用 Hosted Payments Lightbox。

备注:内容仅供参考。