Antom, leading provider of tailored payment solutions

集成快捷支付(API)

Antom EasySafePay 是一款专注于小额高频支付场景的极简支付解决方案。买家可在首次支付时完成钱包绑定或直接支付。后续支付时无需输入密码即可一次点击完成支付。
该方案依托行业领先的智能风控系统、动态轮询技术和支付失败挽回策略,在确保交易安全的同时将支付成功率提升至行业顶尖水平,实现了买家支付体验、商户转化率和平台生态价值的三方共赢。
本文主要介绍如何通过 API 方式集成 EasySafePay 产品。

用户体验

各支付方式在 PC 端和移动端的用户体验存在差异,具体交互方式详见以下表格及用户体验图:
Web
支付方式类别
支付方式
端类型
首次支付
后续支付
电子钱包
Web
在支付方式侧完成支付。
在商户页面完成支付。
网银转账
Web
在支付方式侧完成支付。
在支付方式侧完成支付。
以下分别为电子钱包和网银转账两种支付类别在桌面浏览器上(Web)的用户体验图。
电子钱包
电子钱包场景下,首次支付和后续支付体验图如下。
首次支付
首次支付时买家需要完成支付授权流程以确保后续免密支付。
后续支付
后续支付若需要买家参与,买家仅需提交订单即可完成免密支付。若不需要买家参与,您直接从后台发起支付请求即可。
网银转账
网银转账支付场景体验图如下所示:
首次支付
首次支付时买家需要完成支付授权流程以确保后续免密支付。
后续支付
后续支付若需要买家参与,买家仅需提交订单即可完成免密支付。若不需要买家参与,您直接从后台发起支付请求即可。
WAP
支付方式类别
支付方式
端类型
首次支付
后续支付
电子钱包
​
WAP
在商户页面完成支付。
注意:当买家关闭Enable One-Click Payment按钮时,会跳转至支付方式侧进行单笔支付。
在商户页面完成支付。
WAP
跳转至支付方式应用程序完成支付。
在商户页面完成支付。
网银转账
WAP
在商户页面完成支付。
在商户页面完成支付。
以下分别为电子钱包和网银转账两种支付类别在移动端浏览器(WAP)上的用户体验图。
电子钱包
电子钱包场景下,首次支付和后续支付体验图如下。
首次支付
首次支付时,系统将引导买家在商户页面或支付方式侧完成交易。买家完成授权后,后续支付可以免密支付。
在商户页面支付
跳转至支付方式应用程序支付
后续支付
后续支付若需要买家参与,买家仅需提交订单即可完成免密支付。若不需要买家参与,您直接从后台发起支付请求即可。
网银转账
网银转账场景下,首次支付和后续支付体验图如下。
首次支付
首次支付时买家需要完成支付授权流程以确保后续免密支付。
后续支付
后续无需重新绑定账号即可完成支付。
App
支付方式类别
支付方式
端类型
首次支付
后续支付
电子钱包
​
App
在商户页面完成支付。
注意:当买家关闭Enable One-Click Payment按钮时,会跳转至支付方式侧进行单笔支付。
在商户页面完成支付。
App
跳转至支付方式应用程序完成支付。
在商户页面完成支付。
网银转账
App
在商户页面完成支付。
在商户页面完成支付。
以下分别为电子钱包和网银转账两种支付类别在移动端(App)的用户体验图。
电子钱包
电子钱包场景下,首次支付和后续支付体验图如下。
首次支付
首次支付时,系统将引导买家在商户页面或支付方式侧完成交易。买家完成授权后,后续支付可以免密支付。
在商户页面支付
跳转至支付方式应用程序支付
后续支付
后续支付若需要买家参与,买家仅需提交订单即可完成免密支付。若不需要买家参与,您直接从后台发起支付请求即可。
网银转账
网银转账场景下,首次支付和后续支付体验图如下。
首次支付
首次支付时买家需要完成支付授权流程以确保后续免密支付。
后续支付
后续无需重新绑定账号即可完成支付。

支付流程

首次支付
  1. 买家进入商户收银台页面
  2. 买家选择支付方式后提交支付请求
  3. 创建支付请求
    买家选择支付方式并提交订单后,商户服务端根据支付方式、金额、币种、商品等交易信息,调用
    pay(令牌支付) 接口发起支付请求。
  4. 处理支付推进链接
    商户客户端跳转至支付请求返回的 URL 页面,或唤起相关应用程序完成授权支付。
  5. 获取授权结果
    当授权成功时, Antom 会通过
    notifyAuthorization 接口向您发送异步通知。
  6. 获取支付结果
    通过以下两种方法获取支付结果:
    • 异步通知:在 pay(令牌支付) 接口中指定 paymentNotifyUrl 或门户设置接收异步通知的地址。当支付完成后,Antom 会使用 notifyPayment 接口向您发送异步通知。
    • 同步查询:调用 inquiryPayment 接口检查支付状态。
后续支付
  1. 买家进入商户收银台页面
  2. 买家选择支付方式后提交支付请求
  3. 创建支付请求
    在获得买家授权后,您可以直接调用
    pay(令牌支付) 接口发起支付。
  4. 买家完成风险验证
    当交易出现风险时,需要跳转到前端页面完成验证。若是商家从后台直接发起订阅扣款,则不会出现验证页面。
  1. 获取支付结果
    通过以下两种方法获取支付结果:
    • 异步通知:在 pay(令牌支付) 接口中指定 paymentNotifyUrl 或门户设置接收异步通知的地址。当支付完成后,Antom 会使用 notifyPayment 接口向您发送异步通知。
    • 同步查询:调用 inquiryPayment 接口检查支付状态。

集成准备

在您开始集成前,请阅读集成指南及接口概述文档,了解服务端接口的集成步骤及调用接口的注意事项,并确保已完成以下预配置:
  • 已获得 client ID。
  • 已完成密钥配置。
  • 已完成异步通知接收地址的配置。
  • 集成服务端 SDK 资源包,并完成接口库安装及请求示例初始化。具体操作请参阅服务端 SDK。

集成步骤

开始集成,请按照以下步骤操作:
  1. 创建支付请求
  2. 获取跳转支付推进链接
  3. 获取授权和支付结果

步骤 1:创建支付请求

买家点击支付按钮后,调用 pay(令牌支付) 接口传入订单信息。
首次支付和后续支付调用接口参数说明:
注意:
类型
参数
是否必传
(首次支付)
是否必传
(后续支付 买家操作)
是否必传
(后续支付 商家直接扣款)
参数描述
​
​
基础参数
productCode
是
是
是
EasySafePay 场景设置为 AGREEMENT_PAYMENT。
paymentRequestId
是
是
是
商户为识别支付请求而分配的专属 ID。
paymentMethod.paymentMethodType
是
是
是
授权签约的支付方式。参见支付方式以查看有效值。
paymentMethod.paymentMethodId
不需要
是
是
传入首次支付后在 notifyAuthorization 接口中获得的 accessToken 的值。
paymentMethodMetadata.smartPaymentEnabled
否
否
该场景不支持
PayPay 钱包需要指定为 true。
paymentMethod.paymentMethodMetaData.recurringType
不需要
否
是
当支付是商户发起的交易(MIT)时,指定此参数。有效值为:
  • SCHEDULED: 表示定期自动扣款支付。
  • UNSCHEDULED: 表示不定期自动扣款支付。
如果此参数的值为空或未指定此参数,表示支付不是自动扣款,付款人将参与支付过程。
settlementStrategy
否
否
否
该笔支付的结算策略。若业务签约了多个结算币种,需在接口中指定。若业务只签约了1个结算币种,不需要在接口里指定。
paymentAmount.value
是
是
是
以最小币种单位的正整数形式表示的金额值。
paymentExpiryTime
否
否
否
支付过期的特定日期和时间。默认过期时间为 14 分钟。
paymentRedirectUrl
是
是
否
商户端支付结果页,需根据服务端结果展示,非固定为成功页。
paymentNotifyUrl
否
否
否
支付结果异步通知地址,如通过门户配置,则该参数可不传,必须为 HTTPS 地址。
环境参数
​
order.env.terminalType
是
是
不需要
商户服务适用的终端类型。有效值包括:
  • WEB: 客户端终端类型为通过网络浏览器打开的网站。
  • WAP: 客户端终端类型为通过移动浏览器打开的 HTML 页面。
  • APP: 客户端终端类型为移动应用程序。
order.env.osType
是
是
不需要
操作系统类型。有效值为:
  • IOS: 表示操作系统为苹果的 iOS。
  • ANDROID: 表示操作系统为谷歌的 Android。
注意:当 terminalType 为 APP或WAP 时,此参数必填。
order.env.clientIp
是
是
不需要
客户端设备的 IP 地址。
order.env.deviceId
是
是
不需要
买家下单设备的专属 ID。
授权参数
agreementInfo.authState
是
不需要
不需要
您用于发起授权而分配的专属 ID。该参数仅在首次支付时传递,后续支付无需传递此参数。
订单参数

​
​
​
​
order.orderAmount
是
是
是
订单金额。
order.referenceOrderId​
是
是
是
商户端订单号。
order.orderDescription​
是
是
是
商户端订单描述。
order.buyer.referenceBuyerId
否
否
否
识别买家的买家 ID。
注意:
  • 当您有风控需求时指定此参数。提供此信息有助于提高反洗钱和欺诈检测的准确性,从而提高支付成功率。
  • 该参数与 buyerEmail、buyerPhoneNo 任选其一传入。
order.buyer.buyerEmail
否
否
否
买家的电子邮件地址。
注意:
  • 当您有风控需求时指定此参数。提供此信息有助于提高反洗钱和欺诈检测的准确性,从而提高支付成功率。
  • 该参数与 referenceBuyerId、buyerPhoneNo 任选其一传入。
order.buyer.buyerPhoneNo
否
否
否
买家的手机号码。
注意:
  • 当您有风控需求时指定此参数。提供此信息有助于提高反洗钱和欺诈检测的准确性,从而提高支付成功率。
  • 该参数与 referenceBuyerId、buyerEmail 任选其一传入。
  • 对于 AlipayHK 和 DANA,传入该参数以后会展示签约并支付的页面,具体格式请参考以下表格。
AlipayHK 和 DANA 支持的 buyerPhoneNo 格式如下:
支付方式
order.buyer.buyerPhoneNo 传参格式
  • 中国香港:852-12****78,注意手机号总长度是 8 位(不包含前缀 852-)。
  • 中国大陆:86-137****5678,注意手机号总长度是 11 位(不包含前缀 86-)。
62-8569****7288,手机号 8 开头且手机号长度不超过 12 位(不包括前缀 62-)。
首次支付时传入 order.buyer.buyerPhoneNo 可自动回填买家支付方式账号至支付页面,避免手动输入操作。以下是传入和未传入的体验对比图:
传入支付方式登录账号
当传入支付方式账号时,买家进入授权支付流程或选择单笔支付。
授权并支付
开启 Enable One-Click Payment 按钮,首次支付完成授权即可开启免密支付,后续交易方便快捷。
单笔支付
关闭 Enable One-Click Payment 按钮,跳转至支付方式侧进行单笔支付。
未传入支付方式登录账号
当未传入支付方式账号时, 页面将引导买家跳转至支付方式侧进行授权。
以下是首次支付和后续支付两种不同场景集成代码示例:
首次支付
调用 pay(令牌支付) 接口示例:
@PostMapping("/v1/payments/pay")
public ResponseEntity<ApiResponse> pay(@RequestBody PaymentVO payment) {
  AmsPayRequest request = new AmsPayRequest();
  request.setProductCode(ProductCodeType.AGREEMENT_PAYMENT);

  // 替换为您的 paymentRequestId
  String paymentRequestId = UUID.randomUUID().toString();
  request.setPaymentRequestId(paymentRequestId);

  // 转换金额单位(实际使用中,金额应在服务端计算)
  // 详情请参考: https://docs.antom.com/ac/ref/cc
  long amountMinorLong = Money.of(
    CurrencyUnit.of(payment.currency),
    new BigDecimal(payment.amountValue)
  ).getAmountMinorLong();

  // 设置 paymentAmount
  Amount paymentAmount = Amount.builder()
    .currency(payment.currency)
    .value(String.valueOf(amountMinorLong))
    .build();
  request.setPaymentAmount(paymentAmount);

  // 设置 settlementStrategy
  // 替换为您现有的结算货币
  SettlementStrategy settlementStrategy = SettlementStrategy.builder()
    .settlementCurrency("USD")
    .build();
  request.setSettlementStrategy(settlementStrategy);

  // 设置 paymentMethod
  PaymentMethod paymentMethod = PaymentMethod.builder()
    .paymentMethodType(payment.paymentMethodType)
    .build();

  User loginUser = users.get(payment.getUserId());

  if (loginUser.getPaymentMethodTypeAccessToken().containsKey(payment.getPaymentMethodType())) {
    // 买家已授权,使用 token 走代扣
    String accessToken = loginUser
      .getPaymentMethodTypeAccessToken()
      .get(payment.getPaymentMethodType());
    paymentMethod.setPaymentMethodId(accessToken);
  } else {
    // 买家未授权,设置 agreementInfo 走签约流程
    String authState = UUID.randomUUID().toString();
    AgreementInfo agreementInfo = AgreementInfo.builder().authState(authState).build();
    request.setAgreementInfo(agreementInfo);

    // 保存与 authState 对应的 paymentMethodType
    authStatePayment.put(authState, payment);
  }
  request.setPaymentMethod(paymentMethod);

  // 设置 env(环境信息,用于风控)
  Env env = Env.builder()
    .osType(payment.getOsType())
    .terminalType(payment.getTerminalType())
    .deviceId(payment.getDeviceId())
    .clientIp(payment.getClientIp())
    .deviceTokenId(payment.getDeviceTokenId())
    .build();
  request.setEnv(env);

  // 设置 goods(商品明细)
  List<Goods> goodsList = payment
    .getGoodsList()
    .stream()
    .map(g ->
      Goods.builder()
        .referenceGoodsId(g.getReferenceGoodsId())
        .goodsName(g.getGoodsName())
        .quantity(g.getQuantity())
        .price(Amount.builder().currency(payment.currency).value(g.getPriceValue()).build())
        .build()
    )
    .collect(Collectors.toList());

  // 设置 shipping(物流信息)
  Shipping shipping = Shipping.builder()
    .shippingName(
      ShippingName.builder()
        .firstName(payment.getShippingFirstName())
        .lastName(payment.getShippingLastName())
        .build()
    )
    .shippingAddress(
      ShippingAddress.builder()
        .region(payment.getShippingRegion())
        .state(payment.getShippingState())
        .city(payment.getShippingCity())
        .address1(payment.getShippingAddress1())
        .address2(payment.getShippingAddress2())
        .zipCode(payment.getShippingZipCode())
        .build()
    )
    .shippingCarrier(payment.getShippingCarrier())
    .shippingPhoneNo(payment.getShippingPhoneNo())
    .build();

  // 设置 buyer(买家信息)
  Buyer buyer = Buyer.builder()
    .referenceBuyerId(loginUser.getReferenceBuyerId())
    .buyerName(
      BuyerName.builder()
        .firstName(loginUser.getFirstName())
        .lastName(loginUser.getLastName())
        .build()
    )
    .buyerPhoneNo(loginUser.getPhoneNumber())
    .buyerEmail(loginUser.getEmail())
    .build();

  // 替换为您的 orderId
  String orderId = UUID.randomUUID().toString();

  // 设置 order(订单信息,含商品明细、物流、买家)
  Amount orderAmount = Amount.builder()
    .currency(payment.currency)
    .value(String.valueOf(amountMinorLong))
    .build();
  Order order = Order.builder()
    .referenceOrderId(orderId)
    .orderDescription(payment.getOrderDescription())
    .orderAmount(orderAmount)
    .goods(goodsList)
    .shipping(shipping)
    .buyer(buyer)
    .build();
  request.setOrder(order);

  // 替换为您的通知 url
  // 或配置您的通知 url: https://dashboard.antom.com/global-payments/developers/iNotify
  request.setPaymentNotifyUrl("https://merchant.com/notify/payment-result");

  // 替换为您的跳转 url
  request.setPaymentRedirectUrl(
    "https://merchant.com/payment/result?paymentRequestId=" + paymentRequestId
  );

  AmsPayResponse amsPayResponse;
  try {
    long startTime = System.currentTimeMillis();
    System.out.println("pay request: " + JSON.toJSONString(request));
    amsPayResponse = CLIENT.execute(request, AmsPayResponse.class);
    System.out.println("pay response: " + JSON.toJSONString(amsPayResponse));
    System.out.println("pay request cost time: " + (System.currentTimeMillis() - startTime) + "ms");
  } catch (AlipayApiException e) {
    return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
  }
  return ResponseEntity.ok()
    .body(new ApiResponse(paymentRequestId, payment.getUserId(), amsPayResponse));
}
请求报文示例:
{
  "order": {
    "orderAmount": {
      "currency": "HKD",
      "value": 100
    },
    "referenceOrderId": "ORD_2024040512345",
    "orderDescription": "iPhone 15 Pro Monthly Subscription",
    "goods": [
      {
        "referenceGoodsId": "G_001",
        "goodsName": "iPhone 15 Pro",
        "quantity": 1,
        "price": {
          "currency": "HKD",
          "value": 100
        }
      }
    ],
    "shipping": {
      "shippingName": {
        "firstName": "John",
        "lastName": "Doe"
      },
      "shippingAddress": {
        "region": "US",
        "state": "CA",
        "city": "San Francisco",
        "address1": "123 Tech Street",
        "address2": "Apt 4B",
        "zipCode": "94107"
      },
      "shippingCarrier": "FedEx",
      "shippingPhoneNo": "+1-415-555-1234"
    },
    "buyer": {
      "referenceBuyerId": "BUYER_88118999",
      "buyerName": {
        "firstName": "John",
        "lastName": "Doe"
      },
      "buyerPhoneNo": "66622222",
      "buyerEmail": "john.doe@example.com"
    }
  },
  "env": {
    "osType": "IOS",
    "terminalType": "APP",
    "deviceId": "deviceIdxxxxxxx",
    "clientIp": "192.168.111.111",
    "deviceTokenId": "deviceTokenIdxxxxxxxx"
  },
  "paymentRequestId": "PAYMENT_20251110121228651_AUTO",
  "paymentAmount": {
    "currency": "HKD",
    "value": 100
  },
  "settlementStrategy": {
    "settlementCurrency": "USD"
  },
  "paymentMethod": {
    "paymentMethodType": "ALIPAY_HK"
  },
  "paymentNotifyUrl": "https://merchant.com/notify/payment-result",
  "paymentRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_114.html",
  "productCode": "AGREEMENT_PAYMENT",
  "agreementInfo": {
    "authState": "sign_no_xxxxx111111x01001"
  }
}
响应报文示例:
{
    "actualPaymentAmount": {
        "currency": "HKD",
        "value": "100"
    },
    "normalUrl": "https://checkout.antom.com/easysafepay/1.39.0/pages/api-portal/index.html?paymentMethodCategoryType=WALLET&sessionData=vxA9kkY8yysEoUhFyy%2BEvM17vV72yntAcqJGeMF1PETOU9fJtoSUls3s0vdS1YouYbWEl8gHHEaWPO0Xh%2FT%2BJg%3D%3D%26%26SG%26%26188&locale=en-US&productScene=EASY_PAY&productSceneVersion=2.0",
    "paymentActionForm": "{"method":"GET","paymentActionFormType":"RedirectActionForm","redirectUrl":"https://checkout.antom.com/easysafepay/1.39.0/pages/api-portal/index.html?paymentMethodCategoryType=WALLET&sessionData=vxA9kkY8yysEoUhFyy%2BEvM17vV72yntAcqJGeMF1PETOU9fJtoSUls3s0vdS1YouYbWEl8gHHEaWPO0Xh%2FT%2BJg%3D%3D%26%26SG%26%26188&locale=en-US&productScene=EASY_PAY&productSceneVersion=2.0"}",
    "paymentAmount": {
        "currency": "HKD",
        "value": "100"
    },
    "paymentCreateTime": "2025-11-10T00:35:03-08:00",
    "paymentId": "20251110194010900000188350227845338",
    "paymentRequestId": "PAYMENT_20251110163502455_AUTO",
    "redirectActionForm": {
        "method": "GET",
        "redirectUrl": "https://checkout.antom.com/easysafepay/1.39.0/pages/api-portal/index.html?paymentMethodCategoryType=WALLET&sessionData=vxA9kkY8yysEoUhFyy%2BEvM17vV72yntAcqJGeMF1PETOU9fJtoSUls3s0vdS1YouYbWEl8gHHEaWPO0Xh%2FT%2BJg%3D%3D%26%26SG%26%26188&locale=en-US&productScene=EASY_PAY&productSceneVersion=2.0"
    },
    "result": {
        "resultCode": "PAYMENT_IN_PROCESS",
        "resultMessage": "payment in process",
        "resultStatus": "U"
    }
}
请根据返回的 result.resultStatus 参数值执行下一步操作:
result.resultStatus
信息
下一步操作
S
表示请求成功。
获取 applinkUrl/normalUrl/schemeUrl 其中 1 个或多个支付推进链接,返回的 URL 说明请参见如何正确使用支付推进链接文档。
F
表示请求失败。
关闭当前交易或重新更换 authState 和 paymentRequestId 后再次下单。
U
表示由于未知原因请求失败。
  • 若返回 PAYMENT_IN_PROCESS 结果码,获取任意一个链接 (applinkUrl/normalUrl/schemeUrl) 并打开收银页面。返回的 URL 说明请参见支付推进链接文档。
  • 若返回其他结果码,关闭当前交易或重新更换 paymentRequestId 后再次下单。
注意:若您未收到响应,可能是网络超时导致,请关闭当前交易或重新更换 authState 和 paymentRequestId 后再次下单。
后续支付
调用 pay(令牌支付) 接口示例:
@PostMapping("/v1/payments/pay")
public ResponseEntity<ApiResponse> pay(@RequestBody PaymentVO payment) {
  AmsPayRequest request = new AmsPayRequest();
  request.setProductCode(ProductCodeType.AGREEMENT_PAYMENT);

  // 替换为您的 paymentRequestId
  String paymentRequestId = UUID.randomUUID().toString();
  request.setPaymentRequestId(paymentRequestId);

  // 转换金额单位(实际使用中,金额应在服务端计算)
  // 详情请参考: https://docs.antom.com/ac/ref/cc
  long amountMinorLong = Money.of(
    CurrencyUnit.of(payment.currency),
    new BigDecimal(payment.amountValue)
  ).getAmountMinorLong();

  // 设置 paymentAmount
  Amount paymentAmount = Amount.builder()
    .currency(payment.currency)
    .value(String.valueOf(amountMinorLong))
    .build();
  request.setPaymentAmount(paymentAmount);

  // 设置 settlementStrategy
  // 替换为您现有的结算货币
  SettlementStrategy settlementStrategy = SettlementStrategy.builder()
    .settlementCurrency("USD")
    .build();
  request.setSettlementStrategy(settlementStrategy);

  // 设置 paymentMethod(代扣场景:使用已有的 paymentMethodId)
  User loginUser = users.get(payment.getUserId());
  String accessToken = loginUser
    .getPaymentMethodTypeAccessToken()
    .get(payment.getPaymentMethodType());

  PaymentMethodMetadata metadata = PaymentMethodMetadata.builder()
    .recurringType("SCHEDULED") // 用户不参与扣款时传入 SCHEDULED,用户参与场景不需要传入
    .build();
  PaymentMethod paymentMethod = PaymentMethod.builder()
    .paymentMethodType(payment.paymentMethodType)
    .paymentMethodId(accessToken)
    .paymentMethodMetadata(metadata)
    .build();
  request.setPaymentMethod(paymentMethod);

  // 设置 env(环境信息,用于风控)
  Env env = Env.builder()
    .osType(payment.getOsType())
    .terminalType(payment.getTerminalType())
    .deviceId(payment.getDeviceId())
    .clientIp(payment.getClientIp())
    .deviceTokenId(payment.getDeviceTokenId())
    .build();
  request.setEnv(env);

  // 设置 goods(商品明细)
  List<Goods> goodsList = payment
    .getGoodsList()
    .stream()
    .map(g ->
      Goods.builder()
        .referenceGoodsId(g.getReferenceGoodsId())
        .goodsName(g.getGoodsName())
        .quantity(g.getQuantity())
        .price(Amount.builder().currency(payment.currency).value(g.getPriceValue()).build())
        .build()
    )
    .collect(Collectors.toList());

  // 设置 shipping(物流信息)
  Shipping shipping = Shipping.builder()
    .shippingAddress(
      ShippingAddress.builder()
        .region(payment.getShippingRegion())
        .state(payment.getShippingState())
        .city(payment.getShippingCity())
        .address1(payment.getShippingAddress1())
        .address2(payment.getShippingAddress2())
        .zipCode(payment.getShippingZipCode())
        .build()
    )
    .build();

  // 设置 buyer(买家信息)
  Buyer buyer = Buyer.builder()
    .referenceBuyerId(payment.getReferenceBuyerId())
    .buyerName(
      BuyerName.builder()
        .firstName(payment.getBuyerFirstName())
        .lastName(payment.getBuyerLastName())
        .build()
    )
    .buyerPhoneNo(payment.getBuyerPhoneNo())
    .buyerEmail(payment.getBuyerEmail())
    .build();

  // 替换为您的 orderId
  String orderId = UUID.randomUUID().toString();

  // 设置 order(订单信息,含商品明细、物流、买家)
  Amount orderAmount = Amount.builder()
    .currency(payment.currency)
    .value(String.valueOf(amountMinorLong))
    .build();
  Order order = Order.builder()
    .referenceOrderId(orderId)
    .orderDescription(payment.getOrderDescription())
    .orderAmount(orderAmount)
    .goods(goodsList)
    .shipping(shipping)
    .buyer(buyer)
    .build();
  request.setOrder(order);

  // 替换为您的通知 url
  // 或配置您的通知 url: https://dashboard.antom.com/global-payments/developers/iNotify
  request.setPaymentNotifyUrl("https://kademo.intlalipay.cn/payments/notifySuccess");

  // 替换为您的跳转 url
  request.setPaymentRedirectUrl("https://kademo.intlalipay.cn/melitigo/Test_114.html");

  AmsPayResponse amsPayResponse;
  try {
    long startTime = System.currentTimeMillis();
    System.out.println("pay request: " + JSON.toJSONString(request));
    amsPayResponse = CLIENT.execute(request, AmsPayResponse.class);
    System.out.println("pay response: " + JSON.toJSONString(amsPayResponse));
    System.out.println("pay request cost time: " + (System.currentTimeMillis() - startTime) + "ms");

    // 代扣场景:支付结果同步返回
    // resultStatus=S 表示支付成功,无需跳转收银台
    if ("S".equals(amsPayResponse.getResult().getResultStatus())) {
      System.out.println(
        "Payment SUCCESS, paymentId: " +
        amsPayResponse.getPaymentId() +
        ", paymentTime: " +
        amsPayResponse.getPaymentTime()
      );
    }
  } catch (AlipayApiException e) {
    return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
  }
  return ResponseEntity.ok()
    .body(new ApiResponse(paymentRequestId, payment.getUserId(), amsPayResponse));
}
请求报文示例:
{
  "order": {
    "orderAmount": {
      "currency": "HKD",
      "value": 100
    },
    "referenceOrderId": "ORD_2024040512345",
    "orderDescription": "iPhone 15 Pro Monthly Subscription",
    "goods": [
      {
        "referenceGoodsId": "G_001",
        "goodsName": "iPhone 15 Pro",
        "quantity": 1,
        "price": {
          "currency": "HKD",
          "value": 100
        }
      }
    ],
    "shipping": {
      "shippingAddress": {
        "region": "US",
        "state": "CA",
        "city": "San Francisco",
        "address1": "123 Tech Street",
        "address2": "Apt 4B",
        "zipCode": "94107"
      }
    },
    "buyer": {
      "referenceBuyerId": "BUYER_88118999",
      "buyerName": {
        "firstName": "John",
        "lastName": "Doe"
      },
      "buyerPhoneNo": "66622222",
      "buyerEmail": "john.doe@example.com"
    }
  },
  "env": {
    "osType": "IOS",
    "terminalType": "APP",
    "deviceId": "deviceIdxxxxxxx",
    "clientIp": "192.168.111.111",
    "deviceTokenId": "deviceTokenIdxxxxxxxx"
  },
  "paymentMethod": {
    "paymentMethodType": "ALIPAY_HK",
    "paymentMethodId": "xxxxxxxx",
    "paymentMethodMetadata": {
      "recurringType": "SCHEDULED" //买家不参与的情况下需要传入,买家参与场景不需要传入
    }
  },
  "settlementStrategy": {
    "settlementCurrency": "USD"
  },
  "paymentNotifyUrl": "https://kademo.intlalipay.cn/payments/notifySuccess",
  "paymentRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_114.html",
  "paymentRequestId": "PAY_20251110143957765",
  "productCode": "AGREEMENT_PAYMENT"
}
响应报文示例:
{
  "actualPaymentAmount": {
    "currency": "HKD",
    "value": "100"
  },
  "paymentAmount": {
    "currency": "HKD",
    "value": "100"
  },
  "paymentCreateTime": "2025-11-05T23:03:16-08:00",
  "paymentId": "202511061940108001001888********",
  "paymentRequestId": "PAYMENT_20251106150314003_AUTO",
  "paymentTime": "2025-11-05T23:03:18-08:00",
  "pspCustomerInfo": {
    "pspCustomerId": "208812211210000",
    "pspName": "ALIPAY_HK"
  },
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
请根据返回的 result.resultStatus 参数的值执行下一步操作:
result.resultStatus
信息
下一步操作
S
表示支付成功。
无需进一步操作。
F
表示支付失败。
您可以根据 resultCode 进行相关处理。
U
请根据返回的事件码进行下一步处理。
  • 返回 PAYMENT_IN_PROCESS事件码并返回跳转链接:跳转到支付推进链接 normalUrl 上。
  • 返回其他事件码:通过轮询 inquiryPayment 接口主动查询交易状态或等待 notifyPayment 来获取交易结果。强烈建议您同时接入这两个接口,以便更快的获取支付结果以及避免因其中一个接口出现问题导致未获取到对应支付结果。
注意:若您未收到响应,可能是网络超时导致,请保持 paymentRequestId 不变重新调用接口以解决问题。如果问题未解决,请联系 Antom 技术支持。
常见问题
问:请求参数的值可以使用中文字符吗?
答:为了避免某些支付方式的不兼容,不要在请求的参数中使用中文字符。
​
问:如何设置接收支付通知的链接?
答:在 pay(令牌支付) 接口中指定参数 paymentNotifyUrl,以接收支付结果的异步通知(notifyPayment),或者在 Antom Dashboard 中配置接收链接。如果请求和 Antom Dashboard 中都指定了链接,请求中指定的值优先。
​
问:paymentAmount 和 orderAmount 的区别是什么?
答:paymentAmount 是指支付金额,orderAmount 是指订单金额。实际支付金额以 paymentAmount 为准。

步骤 2:获取跳转支付推进链接

商户服务端拿到 Antom 返回的支付推进链接后,将该地址传递给前端,由商户前端跳转至支付方式页面。
以下为商户前端加载支付推进链接的示例代码:
Web
if (URL != null) {
  window.open(URL, "_blank");
}
WAP
window.location.href = URL;
iOS
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0) {
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:Url] options:@{} completionHandler:nil];
}else{ 
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:Url]];
}
Android
try {
  Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(URL));
  intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  // use the startActivity function to redirect to the wallet app
  startActivity(intent);
} catch (Exception e) {
  e.printStackTrace();
}
注意:示例代码里的 URL 是指步骤 1 返回 applinkUrl、schemeUrl、normalUrl。关于如何使用这些 URL,请参见跳转链接使用最佳实践文档。
下图为支付方式收银台页面的效果图:
首次支付
后续支付
在某些场景下,风控可能会要求买家进行 OTP 核身。

步骤 3:获取授权和支付结果

回跳支付结果页面

当买家在支付完成后,会回跳到您在 pay(令牌支付) 接口里指定的 paymentRedirectUrl。
注意:并不是所有情况都支持回跳,例如买家操作或者网络原因无法回跳。

获取授权和支付结果

首次支付将返回授权及支付结果,后续支付仅返回支付结果。以下是常见场景:
类型
常见场景
获取到的异步通知情况
处理建议
首次支付
买家成功授权和支付。
授权成功,支付成功。
  • 若收到支付异步通知,则推进到对应状态。
  • 若收到授权成功异步通知,则在商户侧维护好买家和令牌的映射关系。
  • 若在商户订单关闭时未收到任何通知,您可以调用 cancel 接口将支付订单关闭。
    注意:调用 cancel 接口仅关闭支付订单,不影响授权,如果您收到授权成功的通知,建议您进行下一步操作。
买家授权成功,但是因为余额不足等原因支付失败。
授权成功,支付失败。
买家未授权或授权失败,但是支付成功。
授权无异步通知,支付成功。
买家未授权或授权失败,同时因为余额不足等原因支付失败。
授权无异步通知,支付失败。
买家未授权或授权失败,同时也未提交支付。
授权和支付均无异步通知。
后续支付
买家成功支付。
支付成功。
  • 若收到支付异步通知,则推进到对应状态。
  • 若在商户订单关闭时未收到任何通知,您可以调用 cancel 接口将订单关闭。
买家因余额不足等原因支付失败。
支付失败。
获取授权结果
首次支付签约成功后,Antom 会通过 notifyAuthorization 接口给您发送授权异步通知。
  1. 配置接收异步授权通知的 webhook URL:按照 Antom Dashboard > 开发者 > 通知地址路径,为 alipay.ams.authorizations.notify 接口增加通知地址。具体操作请参阅通知地址。
以下是异步授权通知请求的代码示例:
{
  "accessToken": "28288803001319861727421828000Cv96OFlYoi17100****",
  "accessTokenExpiryTime": 2145916817000,
  "authState": "36a38e87-0453-495e-ad17-b46553b918da",
  "authorizationNotifyType": "TOKEN_CREATED",
  "userLoginId": "852-91****67",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
根据授权结果通知请求中 result.resultStatus 的值(仅返回 S)进行处理。
S:表示授权成功,并返回以下参数:
参数名
说明
accessToken
由 Antom 返回的支付令牌,用于后续免密支付。
注意:是否会返回免密支付的令牌依赖于支付方式的能力或买家是否选择开通免密,并不是每笔支付都会返回支付令牌。
accessTokenExpiryTime
accessToken 的有效期。
请以下面支付令牌有效期表中的时间为准,当过了有效期后,您需要重新引导买家签约授权。
authState
发起授权而分配的专属ID。该参数的值用于验证是否与 pay(令牌支付) 请求中指定的 authState 值一致。
authorizationNotifyType
仅返回 TOKEN_CREATED,表示买家在商户客户端成功发起快捷支付的授权。
userLoginId
买家在注册支付方式中时使用的登录 ID,该参数已经脱敏。您可以存储该账号用于后续支付时展示。
注意:授权完成后是否返回 userLoginId,取决于支付方式自身能力,因此并非所有支付方式都会返回该参数。
下表为各支付方式的令牌有效期:
支付方式
支付令牌有效期
92 年
100 年
100 年
100 年
PayPay Smart Payment
首次签约有效期为一年,若一年内有支付成功的交易,则自该交易成功之日起顺延一年。
100 年
100 年
无 token 返回,商户侧不需要维护。
  1. Antom 发送的通知结果由 Antom 加签,故建议您验证签名以确认通知由 Antom 发送。参考以下代码示例对授权通知进行验签:
@PostMapping("/receiveAuthNotify")
@ResponseBody
public Result receiveAuthNotify(HttpServletRequest request, @RequestBody String notifyBody) {
  // 从 HTTP 请求中获取必要参数
  String requestUri = request.getRequestURI();
  String requestMethod = request.getMethod();

  // 从请求头中获取必要参数
  String requestTime = request.getHeader("request-time");
  String clientId = request.getHeader("client-id");
  String signature = request.getHeader("signature");

  try {
    // 验证通知签名
    boolean verifyResult = WebhookTool.checkSignature(
      requestUri,
      requestMethod,
      clientId,
      requestTime,
      signature,
      notifyBody,
      ANTOM_PUBLIC_KEY
    );
    if (!verifyResult) {
      throw new RuntimeException("Invalid notify signature");
    }

    // 反序列化通知体
    AlipayAuthNotify authNotify = JSON.parseObject(notifyBody, AlipayAuthNotify.class);

    if (
      authNotify != null &&
      "SUCCESS".equals(authNotify.getResult().getResultCode()) &&
      "TOKEN_CREATED".equals(authNotify.getAuthorizationNotifyType())
    ) {
      // 保存买家 PaymentMethodType 与 accessToken 的对应关系
      PaymentVO payment = authStatePayment.get(authNotify.getAuthState());
      User user = users.get(payment.getUserId());
      user
        .getPaymentMethodTypeAccessToken()
        .put(payment.getPaymentMethodType(), authNotify.getAccessToken());
      return Result.builder()
        .resultCode("SUCCESS")
        .resultMessage("success.")
        .resultStatus(ResultStatusType.S)
        .build();
    }
    // 其他类型的通知
  } catch (Exception e) {
    return Result.builder()
      .resultCode("FAIL")
      .resultMessage("fail.")
      .resultStatus(ResultStatusType.F)
      .build();
  }

  return Result.builder()
    .resultCode("SYSTEM_ERROR")
    .resultMessage("system error.")
    .resultStatus(ResultStatusType.F)
    .build();
}
  1. 收到通知后,您无需对响应通知结果做加签处理,但是对于每个通知请求均需按以下固定格式响应,与授权成功与否无关。
{
  "result": {
    "resultCode": "SUCCESS",
    "resultStatus": "S",
    "resultMessage": "success"
  }
}
获取支付结果
首次支付或后续支付完成后,可通过以下方式获取支付结果:
  • 接收异步通知:接收 Antom 服务端发送的支付结果
  • 查询支付结果:调用 inquiryPayment 接口获取支付状态
接收异步通知
  1. 设置接收通知的 Webhook URL:
完成支付或支付失败时,Antom 会向您设置的 webhook URL 发送异步通知,您可以选择以下两种方法中的一种来设置接收通知的 webhook URL:
  • 订单级通知配置:通过 pay(令牌支付)接口请求中的 paymentNotifyUrl 参数为每笔订单指定独立的通知 URL。
  • 商户级通知配置:登陆 Antom Dashboard > 开发者 > 通知地址,为 alipay.ams.payments.payNotify 接口增加通知地址。具体操作请参阅通知地址。
注意:如果以上两种方式您都配置了通知地址,则优先以接口设置为准。
以下是支付结果异步通知请求的代码示例:
{
  "actualPaymentAmount": {
    "currency": "HKD",
    "value": "98080"
  },
  "customsDeclarationAmount": {},
  "notifyType": "PAYMENT_RESULT",
  "paymentAmount": {
    "currency": "HKD",
    "value": "98080"
  },
  "paymentCreateTime": "2024-09-27T00:23:36-07:00",
  "paymentId": "202409271940108001001881E0211235544",
  "paymentRequestId": "bc93d19e-e1f6-4b68-b6b1-3d6ddc2a792a",
  "paymentTime": "2024-09-27T00:23:46-07:00",
  "pspCustomerInfo": {
    "pspCustomerId": "20881221121****",
    "pspName": "ALIPAY_HK"
  },
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
下表展示了支付结果的异步通知中 result.resultStatus 参数可能返回的值,请您根据指引进行处理
result.resultStatus
信息
后续操作
S
支付成功。
可从中获取以下参数信息:
  • paymentrequestld:用于查询、取消和对账的支付请求 ID。
  • paymentld:表示由 Antom 生成的支付订单 ID,用于退款和对账。
  • paymentAmount:表示支付币种和金额。
F
支付失败。
建议引导买家重新下单。
  1. Antom 发送的通知结果由 Antom 加签,故建议您验证签名以确认通知由 Antom 发送。参考以下代码示例对支付通知进行验签:
/**
 * 接收通知
 *
 * @param request    请求
 * @param notifyBody 通知体
 * @return Result
 */
@PostMapping("/receiveNotify")
@ResponseBody
public Result receiveNotify(HttpServletRequest request, @RequestBody String notifyBody) {
  // 从 HTTP 请求中获取必要参数
  String requestUri = request.getRequestURI();
  String requestMethod = request.getMethod();

  // 从请求头中获取必要参数
  String requestTime = request.getHeader("request-time");
  String clientId = request.getHeader("client-id");
  String signature = request.getHeader("signature");

  try {
    // 验证通知签名
    boolean verifyResult = WebhookTool.checkSignature(
      requestUri,
      requestMethod,
      clientId,
      requestTime,
      signature,
      notifyBody,
      ANTOM_PUBLIC_KEY
    );
    if (!verifyResult) {
      throw new RuntimeException("Invalid notify signature");
    }
    // 反序列化通知体
    JSONObject jsonObject = JSON.parseObject(notifyBody);
    String notifyType = (String) jsonObject.get("notifyType");
    if ("PAYMENT_RESULT".equals(notifyType)) {
      AlipayPayResultNotify paymentNotify = jsonObject.toJavaObject(AlipayPayResultNotify.class);
      if (paymentNotify != null && "SUCCESS".equals(paymentNotify.getResult().getResultCode())) {
        // 处理您的业务逻辑
        // 例如:将支付信息与买家关系存入数据库
        System.out.println("receive payment notify: " + JSON.toJSONString(paymentNotify));
        return Result.builder()
          .resultCode("SUCCESS")
          .resultMessage("success.")
          .resultStatus(ResultStatusType.S)
          .build();
      }
    }
    // 其他类型的通知
  } catch (Exception e) {
    // 处理错误情况
    return Result.builder()
      .resultCode("FAIL")
      .resultMessage("fail.")
      .resultStatus(ResultStatusType.F)
      .build();
  }
  return Result.builder()
    .resultCode("SYSTEM_ERROR")
    .resultMessage("system error.")
    .resultStatus(ResultStatusType.F)
    .build();
}
  1. 收到通知后,您无需对响应通知结果做加签处理,但是对于每个通知请求均需按以下固定格式响应,与订单支付成功与否无关。
{
  "result": {
    "resultCode": "SUCCESS",
    "resultStatus": "S",
    "resultMessage": "success"
  }
}
查询支付结果
Antom 提供 inquiryPayment 接口,支持主动获取订单支付状态,您可以在支付后发起轮询或发起定时任务查询。
以下代码展示了如何调用 inquiryPayment 接口:
public static void inquiryPayment() {
  AlipayPayQueryRequest alipayPayQueryRequest = new AlipayPayQueryRequest();

  // 替换为您的 paymentRequestId
  alipayPayQueryRequest.setPaymentRequestId("yourPaymentRequestId");

  AlipayPayQueryResponse alipayPayQueryResponse = null;
  try {
    alipayPayQueryResponse = CLIENT.execute(alipayPayQueryRequest);
  } catch (AlipayApiException e) {
    String errorMsg = e.getMessage();
    // 处理错误情况
  }
}
以下是请求报文的示例:
{
  "paymentRequestId": "bc93d19e-e1f6-4b68-b6b1-3d6ddc2a****"
}
以下是响应报文的示例:
{
  "actualPaymentAmount": {
    "currency": "USD",
    "value": "1"
  },
  "customsDeclarationAmount": {
    "currency": "CNY",
    "value": "7"
  },
  "paymentAmount": {
    "currency": "USD",
    "value": "1"
  },
  "paymentId": "20250305194010800100188690281017336",
  "paymentMethodType": "ALIPAY_CN",
  "paymentRedirectUrl": "https://checkout.antom.com/checkout-page/pages/payment/index.html?sessionData=%2BCUim8L0KviXagaygm9xBL5jZ%2F75w6gAX1nn8pcuFuGkIsMoHtD6U88YSyMrMJvorbwnBg5uQv8e6pyvIpjDQQ%3D%3D%26%26SG%26%26188%26%26eyJleHRlbmRJbmZvIjoie1wiT1BFTl9NVUxUSV9QQVlNRU5UX0FCSUxJVFlcIjpcInRydWVcIixcImxvY2FsZVwiOlwiZW5fVVNcIixcImRpc3BsYXlBbnRvbUxvZ29cIjpcInRydWVcIn0iLCJwYXltZW50U2Vzc2lvbkNvbmZpZyI6eyJwYXltZW50TWV0aG9kQ2F0ZWdvcnlUeXBlIjoiQUxMIiwicHJvZHVjdFNjZW5lIjoiQ0hFQ0tPVVRfUEFZTUVOVCIsInByb2R1Y3RTY2VuZVZlcnNpb24iOiIxLjAifSwic2VjdXJpdHlDb25maWciOnsiYXBwSWQiOiIiLCJhcHBOYW1lIjoiT25lQWNjb3VudCIsImJpelRva2VuIjoiNlRjZGJyMnJGM3JQWXg0aGtWckhxYnZqIiwiZ2F0ZXdheSI6Imh0dHBzOi8vaW1ncy1zZWEuYWxpcGF5LmNvbS9tZ3cuaHRtIiwiaDVnYXRld2F5IjoiaHR0cHM6Ly9vcGVuLXNlYS1nbG9iYWwuYWxpcGF5LmNvbS9hcGkvb3Blbi9yaXNrX2NsaWVudCIsIndvcmtTcGFjZUlkIjoiIn0sInNraXBSZW5kZXJQYXltZW50TWV0aG9kIjpmYWxzZX0%3D",
  "paymentRequestId": "PAYMENT_20250305220039086_AUTO",
  "paymentResultCode": "SUCCESS",
  "paymentResultMessage": "success.",
  "paymentStatus": "SUCCESS",
  "paymentTime": "2025-03-05T06:02:34-08:00",
  "pspCustomerInfo": {
    "pspName": "ALIPAY_CN"
  },
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
请根据响应中 paymentStatus 参数的值进行处理,具体返回值请参阅 inquiryPayment 接口文档。
常见问题
问:支付通知何时发送?
答:这取决于支付是否完成:如果支付成功完成,Antom 通常会在 3 到 5 秒内发送异步通知。
​
问:授权失败是否有异步通知发送?
答:只有授权成功才会有异步通知发送,授权失败不会返回异步通知
​
问:异步通知会被重新发送吗?
答:是的,对于以下情况,异步通知将在 24 小时内自动重新发送:
  • 如果由于网络原因没有收到异步通知;
  • 如果您收到 Antom 的异步通知,但您没有按照返回收到确认信息的示例代码格式进行响应。
通知可以重发最多 8 次,或者直到收到正确的响应以终止传递。发送间隔如下:0 分钟,2 分钟,10 分钟,10 分钟,1 小时,2 小时,6 小时,15 小时。
​
问:授权通知和支付结果通知是分开的,授权通知一定是比支付结果通先收到吗?
答:由于网络稳定性不可控,可能会出现授权通知比支付结果通知晚到的情况。
​
问:是否支持授权查询接口?
答:目前暂未支持该能力。
​
问:在响应异步通知时,我需要添加数字签名吗?
答:如果您收到 Antom 的异步通知,您需要按照返回收到确认信息的示例代码格式返回响应,但不需要对响应进行签名。

支付后集成

取消授权

授权完成后,买家可通过商户侧或支付方式侧取消授权。取消后,原授权令牌立即失效且不可再用于支付。详情请参阅取消授权。

取消交易

订单支持在时效窗口内(截至 T+1 日 00:15 GMT+8)通过 cancel 接口终止交易。详情请参阅取消交易。

退款

Antom 退款规则及操作流程,请参阅退款。

账单

交易完成后,请使用 Antom 财务报告进行对账。结算规则及对账操作请参阅对账。

最佳实践

Antom 为您提供以下最佳实践方案,请参阅最佳实践了解详情:
  • 智能风控服务
  • 处理回跳结果
  • 商户侧主动关单
  • 支付失败重试