PAYATHON 2026

如何仅使用 window 对象检查 PaymentResponse 状态?

支付阿杰

结论

不能只通过 window 对象查询某次 PaymentResponse 的支付状态。

window.PaymentRequest 只能用来判断浏览器是否提供了 Payment Request API。支付产生的 PaymentResponse 是 PaymentRequest.show() 返回的 Promise 解析结果,不会自动保存到 window。此外,PaymentResponse 也没有通用的 status 属性。

原因

典型的支付调用如下:

const request = new PaymentRequest(methodData, details, options);
const response = await request.show();

这里的 response 只存在于支付代码的作用域中。除非代码主动将它暴露出来,否则其他代码无法通过下面的方式获取它:

window.PaymentResponse

即使浏览器中存在 window.PaymentResponse,它通常也只是接口构造器,不是某次支付产生的响应实例,其中也没有最近一次支付的状态。

PaymentResponse 主要提供以下数据:

response.requestId
response.methodName
response.details
response.payerName
response.payerEmail
response.payerPhone
response.shippingAddress

这些数据中没有标准的 response.status。而且,获得 PaymentResponse 只能说明用户完成了支付界面的交互,不代表资金一定已经扣款成功。最终支付结果通常要由支付服务商或业务后端确认。

有权修改支付代码时的处理方式

支付代码获得 PaymentResponse 后,应调用后端接口确认支付,并自行记录或广播结果:

async function startPayment() {
  const request = new PaymentRequest(methodData, details, options);
  const response = await request.show();

  try {
    const result = await fetch("/api/payments/confirm", {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        requestId: response.requestId,
        methodName: response.methodName,
        details: response.details
      })
    }).then(res => res.json());

    const status = result.success ? "success" : "fail";

    await response.complete(status);

    window.dispatchEvent(
      new CustomEvent("payment-status", {
        detail: {
          requestId: response.requestId,
          status
        }
      })
    );
  } catch (error) {
    await response.complete("fail");

    window.dispatchEvent(
      new CustomEvent("payment-status", {
        detail: {
          requestId: response.requestId,
          status: "fail"
        }
      })
    );
  }
}

页面中的其他代码可以监听这个自定义事件:

window.addEventListener("payment-status", event => {
  console.log(event.detail.requestId);
  console.log(event.detail.status);
});

支付代码也可以明确将结果写入全局变量:

window.paymentState = {
  requestId: response.requestId,
  status: "success"
};

不过,这属于应用自行实现的状态管理,并不是 Payment Request API 自动提供的功能。

无法访问支付代码时怎么办

如果支付代码没有暴露响应对象、派发事件或提供查询接口,就无法只依靠 window 获取可靠的支付状态。通常可以采用以下办法:

  1. 调用业务后端的订单状态查询接口。
  2. 根据订单号向支付服务端查询结果。
  3. 请支付模块增加回调、自定义事件或共享状态。
  4. 如果支付发生在 iframe 中,让 iframe 通过 postMessage() 主动通知父页面。

父页面可以这样接收消息:

window.addEventListener("message", event => {
  if (event.origin !== "https://payment.example.com") {
    return;
  }

  if (event.data?.type === "payment-status") {
    console.log(event.data.status);
  }
});

这种方式要求支付页面已经实现对应的 postMessage() 发送逻辑,并且双方约定好消息格式。

注意事项

response.complete("success") 主要用于通知浏览器关闭或更新支付界面,不能作为资金结算成功的权威证明。可靠的支付状态应以服务端确认结果为准,例如支付网关回调、订单查询接口或服务端保存的订单状态。

在特定条件下,修改 PaymentRequest.prototype.show 或许可以拦截响应,但代码必须同源、位于同一个 JavaScript Realm,并在正确的时机执行。这种方式容易失效,也可能干扰正常的支付流程,不适合在生产环境中用于判断支付状态。

备注:内容仅供参考。