PAYATHON 2026

如何通过 Global Payments API 查询历史付款

支付阿杰

明确结论

可以查询,但接入的 Global Payments HPP 产品和账户必须支持 HPP Status Query(状态查询)。

查询通常使用创建付款请求时的 order ID,不能依赖浏览器重定向。重定向只用于改善用户体验,不能单独证明付款成功。用户可能关闭页面,网络可能中断,商户服务也可能暂时不可用。

推荐处理方式

生成 HPP JSON 之前,应为每次付款创建一个全局唯一、可追踪的订单号,并先将其保存到本地数据库。不要等到 JSON 序列化完成后再临时提取订单号。

示意代码如下:

String orderId = UUID.randomUUID().toString();

// 先保存订单,初始状态设置为 PENDING
paymentRepository.create(
    orderId,
    paymentDTO.getAmount(),
    paymentDTO.getCurrency(),
    "PENDING"
);

hppJson = service
    .charge(new BigDecimal(paymentDTO.getAmount()))
    .withCurrency(paymentDTO.getCurrency())
    .withOrderId(orderId)
    .withHostedPaymentData(hostedPaymentData)
    .withAddress(billingAddress, AddressType.Billing)
    .withAddress(shippingAddress, AddressType.Shipping)
    .serialize();

orderId 应由商户系统生成,并保证唯一。具体的长度、字符集和重复规则,应以当前 Global Payments 账户和 SDK 版本的要求为准。

查询历史付款状态

部分版本的 Global Payments Java SDK 通过 HostedService 提供状态查询,典型调用形式如下:

Transaction transaction = service.getTransactionStatus(orderId);

取得结果后,应检查网关返回的交易状态和响应码,再更新本地订单:

Transaction transaction = service.getTransactionStatus(orderId);

String responseCode = transaction.getResponseCode();
String responseMessage = transaction.getResponseMessage();

if ("00".equals(responseCode)) {
    paymentRepository.markPaid(
        orderId,
        transaction.getTransactionId()
    );
} else {
    paymentRepository.recordGatewayStatus(
        orderId,
        responseCode,
        responseMessage
    );
}

这段代码只用于说明处理流程。Global Payments 的产品线、地区、账户配置和 Java SDK 版本不同,getTransactionStatus、返回字段以及成功状态的判断方式也可能不同。未核对对应的 HPP 集成文档前,不能假定所有环境都用 "00" 表示最终付款成功。

如果当前 SDK 没有提供该方法,需要确认所用网关是否有独立的 HPP Status Query 接口,或者是否需要通过 Global Payments 的交易查询或报表 API 查询。Global Payments 不同平台的 API 并不完全通用。

服务恢复后的补偿流程

可以通过定时任务核对本地状态仍为 PENDING 的订单:

List<Payment> pendingPayments =
    paymentRepository.findPendingPaymentsOlderThan(Duration.ofMinutes(5));

for (Payment payment : pendingPayments) {
    try {
        Transaction transaction =
            service.getTransactionStatus(payment.getOrderId());

        reconcile(payment, transaction);
    } catch (Exception ex) {
        // 保持 PENDING,记录错误并在稍后重试
        log.warn(
            "Unable to reconcile payment, orderId={}",
            payment.getOrderId(),
            ex
        );
    }
}

完整流程如下:

  1. 跳转到 HPP 前,保存 orderId、金额、币种和 PENDING 状态。
  2. 正常收到 HPP 返回结果后,验证响应签名并更新订单。
  3. 未收到返回结果时,主动查询付款状态。
  4. 查询超时或网关暂时不可用时,保留 PENDING 状态并稍后重试。
  5. 只有经过签名验证的返回结果或服务端状态查询结果,才能将订单状态改为 PAID。

注意事项

不要把发生重定向直接视为付款成功。返回 URL 中的参数未经签名校验,也不能作为支付凭证。

查询状态时还需要注意:

  • 保存请求付款时实际提交的 orderId。
  • 不要为同一个业务订单无控制地创建多个付款请求,以免造成重复扣款。
  • 为查询任务设置退避重试和最大查询期限。
  • 保存网关返回的 transaction ID、response code 和原始状态,方便后续退款、撤销和对账。
  • 不要只核对本地金额。查询结果中的订单号、金额和币种都应与本地记录一致。
  • 如果账户启用了 webhook 或服务器通知,应将其作为主要的异步通知渠道,状态查询用于补偿。
  • 长时间无法确认的订单应转入人工对账流程,不能自动判定为失败后立即重新扣款。

备注:内容仅供参考。