Payment Element 订阅支付
订阅支付是一种支持周期性自动扣款的支付解决方案,可帮助您轻松实现自动定期收款。买家仅需完成一次授权绑定,即可持续享受订阅服务,同时支持灵活调整订阅配置(如修改周期/金额、取消续订或终止服务)。整个流程安全可靠,操作便捷,兼顾效率与交易安全性。
Antom Payment Element 是基于 SDK 集成的支付组件,旨在为您打造完美无缝的支付体验,助力提升支付转化率。针对不同的终端类型,Antom 提供以下适配方案:
- Web/WAP 端:适用于浏览器及移动网页环境的 Web Element
- App 端(Android 及 iOS):专为商户自有移动应用设计的 Mobile Element
各端 Payment Element 支持的能力如下表所示:
Web/WAP
iOS
Android
用户体验
以下图片展示了集成 Payment Element 首次订阅和后续扣款的用户体验:
首次支付
APM 支付
卡支付
以下图片展示了买家使用 APM 支付的用户体验:

以下图片展示了买家使用卡支付的用户体验:

后续扣款
Antom 服务端将自动发起后续的周期扣款操作,商户服务端通过接收订阅续期扣费通知为买家续订订阅服务。该过程无页面交互。
订单生命周期
以下是不同支付方式的生命周期:
APM 支付
卡支付、Apple Pay、Google Pay
下图展示了 APM 支付的订阅生命周期,包括创建订阅、签约绑定支付方式、完成首次扣款,以及在必要时发起退款等环节,旨在保障订阅的正常生效与费用处理的安全透明:

下图展示了卡支付、Google Pay 和 Apple Pay 支付的订阅生命周期,包括创建订阅、签约绑定支付方式、完成首次扣款,以及在必要时发起退款等环节,旨在保障订阅的正常生效与费用处理的安全透明:


支付流程
以下图片展示了如何通过 Payment Element 集成订阅支付:
APM 支付
卡支付、Apple Pay、Google Pay
首次订阅
周期扣款


首次订阅
周期扣款


首次订阅
周期扣款
- 买家进入订阅商品页面并发起支付。
商户客户端收集买家订阅的相关信息。 - 创建支付会话请求。
调用 createPaymentSession(单笔支付)接口获取支付会话。您可以指定一个或多个支付方式类型,或不指定支付方式类型,以提交支付请求。 - 调用 Payment Element。
在客户端,通过支付会话调用 Payment Element。您可以选择由 Payment Element 或者您自行渲染支付方式,同时 Element 会根据支付方式的特性处理信息、收集支付要素、进行重定向、应用调用、二维码显示、验证等流程。当支付完成后,根据您的设置以及支付方式特性,您需要按照submitPayment().then()方法返回的结果处理跳转流程或者由系统自动回跳到您的支付结果页面。 - 获取支付或授权结果。
通过以下两种方法之一获取支付或授权结果:
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当支付成功或过期时,Antom 会使用 notifyPayment 接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询支付或授权状态。
注意:对于卡支付及部分 APM 支付方式(如 Google Pay、Apple Pay 和 Pay by Bank),这些支付方式采用的是授权-请款模式,以上步骤仅完成了授权部分,即买家使用银行卡完成支付,其资金处于冻结状态。为了将买家的冻结资金转至您的账户,您还需要集成请款步骤。请款成功的结果将作为您发货的依据。
- (可选)请款并获取请款结果。
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当请款完成时,Antom 会使用 notifyCapture(单笔支付)接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询请款状态。
- 获取订阅通知。
订阅关系生效后,Antom 会为您发送首期订阅通知及订阅续期通知。
- Antom 服务端向支付方式发起扣款。
- 获取支付或授权结果。
通过以下两种方法之一获取支付或授权结果:
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当支付成功或过期时,Antom 会使用 notifyPayment 接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询支付或授权状态。
注意:对于卡支付及部分 APM 支付方式(如 Google Pay、Apple Pay 和 Pay by Bank),这些支付方式采用的是授权-请款模式,以上步骤仅完成了授权部分,即买家使用银行卡完成支付,其资金处于冻结状态。为了将买家的冻结资金转至您的账户,您还需要集成请款步骤。请款成功的结果将作为您发货的依据。
- (可选)请款并获取请款结果。
周期扣款场景下,Antom 会自动为您处理资金请款。您可以通过以下两种方法之一获取请款结果:
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当请款完成时,Antom 会使用 notifyCapture(单笔支付)接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询请款状态。
- 获取订阅通知。
扣款成功或失败后,Antom 会为您发送订阅扣款通知。
集成准备
- 已获得 client ID。
- 已完成密钥配置。
- 已完成异步通知接收地址的配置。
- 集成 Antom 服务端 SDK 资源包,并完成接口库安装及请求示例初始化。具体操作请参阅服务端 SDK。
- 参阅 Web/WAP 端集成 SDK 资源包文档来集成客户端 SDK 资源包,并注意使用最新或不低于 1.46.0 版本的 SDK。
集成步骤
请按照以下步骤开始集成:
- 创建支付会话
- 调用 Payment Element
- 获取授权或支付结果
- (可选)请款
- 获取订阅通知
步骤 1:创建支付会话 服务端
传入订单信息以调用 createPaymentSession(单笔支付)接口来创建支付会话,获取唤起 Payment Element 的 paymentSessionData。您可选择由您自定义收银台的支付方式列表或由 Payment Element 为您渲染支付方式列表,并在调用 createPaymentSession(单笔支付)接口时传入相应的参数:
- 由您自行渲染支付方式列表:当您自行渲染支付方式列表时,您必须传入下表中列出的指定支付方式参数。请注意,对于部分支付方式(例如卡支付),您需要嵌入 Payment Element 渲染的支付要素组件。以下是提供卡支付选项时调用 createPaymentSession(单笔支付)接口的最佳时机:
- 如果 Payment Element 需要采集支付要素:在买家选择支付方式后调用 createPaymentSession(单笔支付)接口,并传入下表中列出的卡支付信息参数。
- 如果 Payment Element 不需要采集支付要素:在买家选择支付方式并提交支付后调用 createPaymentSession(单笔支付)接口。
- 由 Payment Element 渲染支付方式列表:当您使用 Payment Element 渲染的支付方式列表时,您只需传入下表中列出的基础参数。Payment Element 默认在收银台页面上渲染所有支持的支付方式,您也可以通过指定支付方式来选择您需要的支付方式。
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// 替换为您的 paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// 转换金额单位(实际应用中,金额应在您的服务器端计算)
// 详情请参考:<a href="https://docs.antom.com/ac/ref_zh-cn/cc">金额的使用规则</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// 设置金额
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// 设置支付策略
// 替换为您现有的结算货币
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("SGD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// 设置买家信息
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// 替换为您的 orderId
String orderId = UUID.randomUUID().toString();
// 设置订单信息
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// 替换为您的通知地址
// 或者在 Antom Dashboard 配置: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">通知地址</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("http://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// 替换为您的跳转地址
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"http://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
// 设置订阅信息
PeriodRule periodRule = PeriodRule.builder().periodCount(1).
periodType("MONTH").build();
List trials = new ArrayList<Trial>();
Trial trial = Trial.builder().
trialAmount(amount).
trialStartPeriod(1).
trialEndPeriod(2).
build();
trials.add(trial);
SubscriptionInfo subscriptionInfo = SubscriptionInfo.builder().
subscriptionDescription("Subscription description").
subscriptionStartTime("2026-03-11T09:48:17+08:00").
subscriptionEndTime("2026-11-21T09:48:17+08:00").
periodRule(periodRule).
trials(trials).
subscriptionNotifyUrl("https://your.example.com/subscriptionNotify").
subscriptionExpiryTime("2026-03-12T09:48:17+08:00").
build();
alipayPaymentSessionRequest.setSubscriptionInfo(subscriptionInfo);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment 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(), alipayPaymentSessionResponse));
}自行渲染支付方式列表
由 Payment Element 渲染支付方式列表
当您自行渲染支付方式列表时,需要通过指定单个支付方式集成。以下代码展示了一个请求报文的示例:
{
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "USD",
"value": "2900"
},
"orderDescription": "antom sdk testing order",
"referenceOrderId": "4b085ec4-9999-4296-8f00-479e929edb2c"
},
"paymentAmount": {
"currency": "USD",
"value": "2900"
},
"paymentNotifyUrl": "http://www.yourNotifyUrl.com/payment/receivePaymentNotify",
"paymentRedirectUrl": "http://google.com.my",
"paymentRequestId": "PAYMENT_20260313102551842_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT",
"settlementStrategy": {
"settlementCurrency": "USD"
},
"availablePaymentMethod": {
"paymentMethodTypeList": [
{
"paymentMethodType": "ALIPAY_CN" // 指定支付方式
},
{
"paymentMethodType": "TNG"
}
]
},
"subscriptionInfo": {
"periodRule": {
"periodCount": 1,
"periodType": "MONTH"
},
"subscriptionDescription": "Subscription description",
"subscriptionNotifyUrl": "https://your.example.com/subscriptionNotify",
"subscriptionStartTime": "2026-03-11T09:48:17+08:00"
}
}如果由 Payment Element 渲染收银台的支付方式列表,则会展示所有支付方式。以下代码展示了一个请求报文的示例:
{
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "SGD",
"value": "2900"
},
"orderDescription": "antom sdk testing order",
"referenceOrderId": "4b085ec4-9999-4296-8f00-479e929edb2c"
},
"paymentAmount": {
"currency": "SGD",
"value": "2900"
},
"paymentNotifyUrl": "http://www.yourNotifyUrl.com/payment/receivePaymentNotify",
"paymentRedirectUrl": "http://localhost:8080/index.html?paymentRequestId=7a6252b5-6d58-4033-882e-2eff7f262b35",
"paymentRequestId": "7a6252b5-6d58-4033-882e-2eff7f262b35",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT",
"settlementStrategy": {
"settlementCurrency": "SGD"
},
"subscriptionInfo": {
"periodRule": {
"periodCount": 1,
"periodType": "MONTH"
},
"subscriptionDescription": "Subscription description",
"subscriptionEndTime": "2026-11-21T09:48:17+08:00",
"subscriptionExpiryTime": "2026-03-12T09:48:17+08:00",
"subscriptionNotifyUrl": "https://your.example.com/subscriptionNotify",
"subscriptionStartTime": "2026-03-11T09:48:17+08:00",
"trials": [
{
"trialAmount": {
"$ref": "$.order.orderAmount"
},
"trialEndPeriod": 2,
"trialStartPeriod": 1
}
]
}
}以下代码展示了一个响应的示例,其中包含以下参数:
- result.resultStatus:createPaymentSession(单笔支付)接口的调用结果。
- paymentSessionData:将返回给前端的支付会话数据。
- paymentSessionExpiryTime:支付会话的过期时间。
{
"paymentSessionData": "WNoudiUNUDjHjx0oXddzWn0QrRHv52lrHFNMKc8/5uKSqNDklmQ7Nh4JGBNITqi3jgIASZkbpq15gIEQleY13A==&&SG&&188&&eyJhY3Rpb24iOnsibmVlZFZlcmlmeUFuZFJlc3VtZSI6ZmFsc2UsInNpZ25CdXR0b25EaXNwbGF5IjpmYWxzZSwic2tpcFNka1F1ZXJ5IjpmYWxzZSwidXNlclNpZ25BZ3JlZW1lbnQiOmZhbHNlfSwiY2xpZW50SWQiOiJTQU5EQk9YXzVZRVYxRzJaVjQzSzA3MjE3IiwiY29ubmVjdEZhY3RvciI6eyJlbmFibGVDb25uZWN0IjpmYWxzZX0sImVsaWdpYmxlRWFzeVBheU1hcmtldGluZyI6ZmFsc2UsImV4dGVuZEluZm8iOiJ7XCJPUEVOX01VTFRJX1BBWU1FTlRfQUJJTElUWVwiOlwidHJ1ZVwiLFwiZXhwcmVzc0NoZWNrb3V0XCI6XCJmYWxzZVwiLFwidmVyc2lvbk1hcFwiOlwie1xcXCJ3ZWJcXFwiOntcXFwiMS4xLjBcXFwiOntcXFwidGFyZ2V0V2ViVmVyaXNvblxcXCI6XFxcIjEuMS4wXFxcIn0sXFxcIjEuMi4wXFxcIjp7XFxcInRhcmdldFdlYlZlcmlzb25cXFwiOlxcXCIxLjIuMFxcXCJ9fSxcXFwiaU9TXFxcIjp7XFxcIjEuMS4wXFxcIjp7XFxcInRhcmdldFdlYlZlcmlzb25cXFwiOlxcXCIxLjEuMFxcXCJ9LFxcXCIxLjIuMFxcXCI6e1xcXCJ0YXJnZXRXZWJWZXJpc29uXFxcIjpcXFwiMS4yLjBcXFwifX0sXFxcIkFuZHJvaWRcXFwiOntcXFwiMS4xLjBcXFwiOntcXFwidGFyZ2V0V2ViVmVyaXNvblxcXCI6XFxcIjEuMS4wXFxcIn0sXFxcIjEuMi4wXFxcIjp7XFxcInRhcmdldFdlYlZlcmlzb25cXFwiOlxcXCIxLjIuMFxcXCJ9fX1cIn0iLCJuZWVkQWNjb3VudENvbmZpcm1QYWdlIjpmYWxzZSwicGF5bWVudFNlc3Npb25Db25maWciOnsicGF5bWVudE1ldGhvZENhdGVnb3J5VHlwZSI6IkFMTCIsInByb2R1Y3RTY2VuZSI6IkVMRU1FTlRfUEFZTUVOVCIsInByb2R1Y3RTY2VuZVZlcnNpb24iOiIxLjAifSwic2tpcFJlbmRlclBheW1lbnRNZXRob2QiOmZhbHNlfQ==",
"paymentSessionExpiryTime": "2026-03-12T15:24:24+08:00",
"paymentSessionId": "WNoudiUNUDjHjx0oXddzWn0QrRHv52lrHFNMKc8/5uIsshVVNylGbBzLF2n6JmoT",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}以下是创建支付会话响应中 result.resultStatus 可能返回的值,请您根据指引进行处理:
注意:如果您未收到响应报文,可能是网络超时所致。建议更换 paymentRequestId 重新调用接口。如果问题未解决,请联系 Antom 技术支持。
常见问题
问:请求参数的值可以使用中文字符吗?
答:为了避免特定支付方式的兼容性问题,请求中的参数请勿使用中文字符。
问:如何设置接收支付通知的地址?
答:在 createPaymentSession(单笔支付)接口的请求中指定 paymentNotifyUrl 参数,以接收支付结果的异步通知(notifyPayment),或者在 Antom Dashboard 中配置接收地址。如果请求和 Antom Dashboard 中都指定了地址,请求中的值优先。
问:返回的 paymentSessionData 是否需要处理后再传给客户端?
答:请勿对 paymentSessionData 进行任何处理,否则可能会导致调用 Payment Element 失败。
问:首笔交易是否必须进行 3DS 认证?
答:首笔交易为买家主动参与的交易,需完成身份验证,以保障后续周期性扣款(买家不在场)的安全性。具体要求如下:
答:首笔交易为买家主动参与的交易,需完成身份验证,以保障后续周期性扣款(买家不在场)的安全性。具体要求如下:
- 买家使用卡支付:无论由您还是 Antom 采集卡信息,均需完成 3DS 认证。您可以在 createPaymentSession(单笔支付)请求中设置 is3DSAuthentication 为 true以启用 Antom 3DS 认证。
- 买家使用 Google Pay 且由 Antom 解密:您需要设置 is3DSAuthentication 为 true以发起 3DS 交易完成身份验证。若解密后为 DPAN,系统将自动进入授权流程,无需买家二次核身。
- 买家使用 Apple Pay 且由 Antom 解密:您可以设置 is3DSAuthentication 为 false或不传递该参数,因为买家已经完成了 Apple 的核验流程。
步骤 2:调用 Payment Element 客户端
在您的客户端使用 paymentSessionData 调用 Payment Element,在买家提交支付后,Payment Element 会根据不同支付方式,负责展示二维码、跳转支付方式页面、3DS 认证、回跳商户结果页等流程。
根据您在步骤 1 中选择渲染支付方式列表的方式(由您自行渲染或由 Payment Element 渲染支付方式列表),以下是不同渲染方式的对比:
- 在服务端获取到 paymentSessionData 后,使用 类来创建 Payment Element 实例。以下是使用 CDN 或 npm 实例化 SDK 的示例代码:
CDN
npm
// 获取浏览器语言
let language = navigator.language || navigator.userLanguage;
language = language.replace("-", "_"); // 将 "-" 替换为 "_"
// 创建 Payment Element 实例
const elementPayment = new window.AMSElement({
environment: "sandbox",
locale: "en_US",
sessionData:sessionData
})import { AMSElement, ThemeType, PaymentElementLayout } from '@alipay/ams-checkout' // 包管理
// 获取浏览器语言
let language = navigator.language || navigator.userLanguage;
language = language.replace("-", "_"); // 将 "-" 替换为 "_"
// 创建 AMSElement 实例
const elementPayment = new AMSElement({
environment: "sandbox",
locale: "en_US",
sessionData:sessionData
})- 使用实例对象中的 方法来创建支付组件,如果需要嵌入组件则将组件嵌入到指定视图里。调用 方法前,您可以自行添加 loading 效果,并在 .then()方法中处理回调时关闭 loading 效果。若回调结果包含错误信息,请通过 error?.code 判断具体错误类型,并参阅回调函数事件码获取详细错误原因及处理建议。如果不存在错误信息,则表示 渲染成功。
注意:
let loading = false;
// 自定义外观
const appearance = {
theme: "default",
layout: { type: "Accordion" },
variables: {},
};
// 调用 mount 时先设置外部容器的 loading 状态
loading = true;
// 嵌入 document.querySelector("#payment-element") 这个节点中
elementPayment.mount(
{
type: 'payment',
appearance: appearance,
notRedirectAfterComplete: false,
},
'#payment-element',
).then(({ error }) => {
// 自行关闭外部容器的 loading 状态
loading = false;
// 消费错误信息,根据 error.code 处理异常
if (error && error?.code) {
// PARAM_INVALID: SDK 入参异常,建议检查集成代码
// UI_STATE_ERROR: mount 调用时机异常,建议检查集成代码
console.log(error.message);
if(error?.code === 'INITALIZE_API_TIMEOUT') {
// 支付信息查询接口超时,导致收银台渲染失败,建议引导买家重试
} else if(error?.code === 'INITALIZE_WEB_TIMEOUT'){
// 收银台静态资源加载超时,建议引导买家重试
} ...
return;
}
// mount 渲染成功,无需处理
})
- 买家点击您自定义的支付按钮后,您需调用 方法提交支付。调用 方法前,您可以自行添加 loading 效果,并在 .then()方法中处理回调时关闭 loading 效果。建议在买家点击支付按钮后展示 loading 状态,以避免其在短时间内重复提交。收到 Payment Element 返回的支付结果后,可根据实际结果引导买家重新发起支付或跳转至支付结果页。
- 若回调结果包含错误信息,您可根据 status 的值简化集成处理,具体操作请参考以下示例代码。您也可根据 error?.code 来进行精细化的异常处理,并参阅回调函数事件码获取详细错误原因及处理建议。
- 如不存在错误信息,请根据 status 的值进行后续操作。
let loading = false;
loading = true;
// 当买家点击支付按钮时:
elementPayment.submitPayment().then(({ error, status, userCanceled3D }) => {
// 自行关闭外部容器的 loading 状态
loading = false;
if (error) { // 先处理错误信息
const { code, message } = error;
if (userCanceled3D) {
// 买家主动关闭 3D 弹窗,建议从服务端轮询结果
}
if (status === 'PROCESSING') {
// 因网络异常或渠道不稳定导致状态未知. 建议从服务端轮询结果
} else {
// FAIL 失败
// 表单校验不通过,Payment Element 已提示买家,建议忽略
if (code === 'FORM_INVALID') {
return;
}
toast(message);
// 或根据 code 精细化定制体验
if (code ){
// xxx
}
}
return;
}
if (status === 'SUCCESS') {
// 成功 SUCCESS。部分场景 Payment Element 会有 toast 提示,建议直接跳转结果页
} else if(status === 'CANCELLED'){
// 订单已取消, 如无该场景可忽略
} else {
// 可添加监控
}
})
卸载 Payment Element
elementPayment.destroy();常见问题
问:是否可以在 PC 应用或移动应用中使用 Webview 集成 Web Element?
答:目前不支持。
步骤 3:获取授权或支付结果 服务端
在支付处理流程中,Antom 会根据不同的支付方式类型向您发送相应的结果通知。
- 对于卡支付、Google Pay 和 Apple Pay 场景,Antom 发送的是授权结果通知,告知您授权是否成功。只有授权成功后才会触发请款,请以请款结果作为发货依据。
- 对于 APM 支付场景,当支付成功或失败时 Antom 会向您发送支付结果通知。
您可以通过接收来自 Antom 的异步通知或主动查询来获取支付或授权结果。
接收异步通知
主动查询结果
1. 设置接收通知的 webhook URL
完成支付或支付失败时,Antom 会向您设置的 webhook URL 发送异步通知,您可以选择以下两种方法中的一种来设置接收通知的 webhook URL(若两者都设置,则以接口请求中指定的 URL 优先):
- 若您的每个订单都有单独的通知 URL,建议您在每笔请求中设置 webhook URL。您可以通过 createPaymentSession(单笔支付)接口请求的 paymentNotifyUrl 参数传入该笔订单的异步通知接收 URL。
- 若您的所有订单有统一的通知 URL,您可以在 Antom Dashboard > 开发者 > 通知地址 中设置 webhook URL。具体操作请参阅通知地址。
以下是异步通知请求体的代码示例:
卡支付、Apple Pay、Google Pay
APM 支付
{
"actualPaymentAmount": {
"currency": "SGD",
"value": "4200"
},
"cardInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe",
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "SGD",
"value": "4200"
},
"paymentMethodType": "CARD",
"paymentCreateTime": "2024-01-01T00:00:00+08:00",
"paymentId": "20240101123456789XXXX",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe", // 存储 cardToken 用于后续存卡支付使用
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentTime": "2024-01-01T00:01:00+08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}下表展示了支付结果的异步通知中 result.resultStatus 参数可能返回的值,请您根据指引进行处理:
{
"actualPaymentAmount": {
"currency": "HKD",
"value": "100"
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "HKD",
"value": "100"
},
"paymentCreateTime": "2025-02-04T22:11:19-08:00",
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "ALIPAY_HK",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
},
"paymentTime": "2025-02-04T22:14:25-08:00",
"pspCustomerInfo": {
"pspCustomerId": "216022003753XXXX",
"pspName": "ALIPAY_HK"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}下表展示了支付结果的异步通知中 result.resultStatus 参数可能返回的值,请您根据指引进行处理:
2. 异步通知验签
您需要按照以下方法对 Antom 发送的支付通知进行验签:
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.alipay.global.api.model.Result;
import com.alipay.global.api.model.ResultStatusType;
import com.alipay.global.api.response.AlipayResponse;
import com.alipay.global.api.tools.WebhookTool;
@RestController
public class PaymentNotifyHandleBySDK {
/**
* alipay public key, used to verify signature
*/
private static final String SERVER_PUBLIC_KEY = "";
/**
* payment result notify processor
* using <a href="https://spring.io">Spring Framework</a>
*
* @param request HttpServletRequest
* @param notifyBody notify body
* @return
*/
@PostMapping("/payNotify")
public Object payNotifyHandler(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");
Result result;
AlipayResponse response = new AlipayResponse();
try {
// 验签
boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId, requestTime, signature, notifyBody, SERVER_PUBLIC_KEY);
if (!verifyResult) {
throw new RuntimeException("Invalid notify signature");
}
// 反序列化通知体
// 根据通知结果更新订单状态
// 向服务器响应已接收通知
result = new Result("SUCCESS", "success", ResultStatusType.S);
} catch (Exception e) {
String errorMsg = e.getMessage();
// 处理错误情况
result = new Result("ERROR", errorMsg, ResultStatusType.F);
}
response.setResult(result);
return ResponseEntity.ok().body(response);
}
}无论订单是否支付成功,每个通知请求均需按以下固定格式响应。否则,Antom 会重新发送异步通知。
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}常见问题
问:什么时候会发送通知?
答:这取决于支付是否完成:
- 如果支付成功完成,Antom 通常会在 3 到 5 秒内发送异步通知。对于现金支付,通知可能会稍有延迟。
- 如果支付未完成,Antom 需要先关闭订单,然后发送异步通知。不同支付方式关闭订单所需的时间会有所不同,通常默认为 14 分钟。
问:Antom 会重新发送异步通知吗?
答:会。对于以下情况,异步通知将在 24 小时内自动重新发送:
- 由于网络原因未收到异步通知。
- 如果收到来自 Antom 的异步通知,但您没有按照返回收到确认信息的格式进行响应。
通知可以重发最多 8 次,或者直到收到正确的响应以终止传递。发送间隔如下:0 分钟,2 分钟,10 分钟,10 分钟,1 小时,2 小时,6 小时和15 小时。
问:在响应异步通知时,需要添加签名吗?
问:我在通知中需要使用哪些关键参数?
答:请注意以下关键参数:
- result:对于 APM 支付,其表示支付最终结果。对于 Google Pay、Apple Pay 和卡支付,则仅代表授权结果,需要进一步发起请款。
- paymentRequestId:用于咨询、取消和对账的支付请求 ID。
- paymentId:表示由 Antom 生成的支付订单 ID,用于退款和对账。
- paymentAmount:表示支付金额。
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": "paymentRequestId01"
}以下代码展示了响应报文的示例:
{
"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"
}
}答:请注意以下关键参数:
- result:仅表示本次 inquiryPayment 接口的调用结果。对于 APM 支付,订单的支付结果需要根据 paymentStatus 进行判断(SUCCESS成功/FAIL失败/PROCESSING处理中)。对于卡支付、Google Pay 和 Apple Pay,paymentStatus 仅代表授权结果,是否发货需要依赖请款结果决策。
- paymentAmount:用于核对支付金额。
- paymentId:表示由 Antom 生成的支付订单 ID,用于退款和对账。
(可选)步骤 4:请款 服务端
注意:卡支付及部分 APM 支付方式(如 Apple Pay、Google Pay 和 Pay by Bank)必须进行请款,且仅授权成功后才会触发请款。
授权成功后,Antom 默认自动为您请款,也支持您手动发起请款。同时,Antom 会使用 请款通知(单笔支付)将请款结果通知发送给您,您也可以通过主动查询来获取请款结果。您需要根据请款结果来决定是否发货,具体操作请参阅请款。
步骤 5:获取订阅通知 服务端
用户体验
以下图片展示了集成 Payment Element 首次订阅和后续扣款的用户体验:
首次支付
APM 支付
卡支付
以下图片展示了买家使用 APM 支付的用户体验:

以下图片展示了买家使用卡支付的用户体验:

后续扣款
Antom 服务端将自动发起后续的周期扣款操作,商户服务端通过接收订阅续期扣费通知为买家续订订阅服务。该过程无页面交互。
订单生命周期
以下是不同支付方式的生命周期:
APM 支付
卡支付、Apple Pay、Google Pay
下图展示了 APM 支付的订阅生命周期,包括创建订阅、签约绑定支付方式、完成首次扣款,以及在必要时发起退款等环节,旨在保障订阅的正常生效与费用处理的安全透明:

下图展示了卡支付、Google Pay 和 Apple Pay 支付的订阅生命周期,包括创建订阅、签约绑定支付方式、完成首次扣款,以及在必要时发起退款等环节,旨在保障订阅的正常生效与费用处理的安全透明:


支付流程
以下图片展示了如何通过 Payment Element 集成订阅支付:
APM 支付
卡支付、Apple Pay、Google Pay
首次订阅
周期扣款


首次订阅
周期扣款


首次订阅
周期扣款
- 买家进入订阅商品页面并发起支付。
商户客户端收集买家订阅的相关信息。 - 创建支付会话请求。
调用 createPaymentSession(单笔支付)接口获取支付会话。您可以指定一个或多个支付方式类型,或不指定支付方式类型,以提交支付请求。 - 调用 Payment Element。
在客户端,通过支付会话调用 Payment Element。您可以选择由 Payment Element 或者您自行渲染支付方式,同时 Element 会根据支付方式的特性处理信息、收集支付要素、进行重定向、应用调用、二维码显示、验证等流程。当支付完成后,根据您的设置以及支付方式特性,您需要按照onSubmitPayCallback:方法返回的结果处理跳转流程或者由系统自动回跳到您的支付结果页面。 - 获取支付或授权结果。
通过以下两种方法之一获取支付或授权结果:
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当支付成功或过期时,Antom 会使用 notifyPayment 接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询支付或授权状态。
注意:对于卡支付及部分 APM 支付方式(如 Apple Pay、Google Pay 和 Pay by Bank),这些支付方式采用的是授权-请款模式,以上步骤仅完成了授权部分,即买家使用银行卡完成支付,其资金处于冻结状态。为了将买家的冻结资金转至您的账户,您还需要集成请款步骤。请款成功的结果将作为您发货的依据。
- (可选)请款并获取请款结果。
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当请款完成时,Antom 会使用 notifyCapture(单笔支付)接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询请款状态。
- 获取订阅通知。
订阅关系生效后,Antom 会为您发送首期订阅通知及订阅续期通知。
- Antom 服务端向支付方式发起扣款。
- 获取支付或授权结果。
通过以下两种方法之一获取支付或授权结果:
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当支付成功或过期时,Antom 会使用 notifyPayment 接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询支付或授权状态。
注意:对于卡支付及部分 APM 支付方式(如 Google Pay、Apple Pay 和 Pay by Bank),这些支付方式采用的是授权-请款模式,以上步骤仅完成了授权部分,即买家使用银行卡完成支付,其资金处于冻结状态。为了将买家的冻结资金转至您的账户,您还需要集成请款步骤。请款成功的结果将作为您发货的依据。
- (可选)请款并获取请款结果。
周期扣款场景下,Antom 会自动为您处理资金请款。您可以通过以下两种方法之一获取请款结果:
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当请款完成时,Antom 会使用 notifyCapture(单笔支付)接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询请款状态。
- 获取订阅通知。
扣款成功或失败后,Antom 会为您发送订阅扣款通知。
集成准备
- 已获得 client ID。
- 已完成密钥配置。
- 已完成异步通知接收地址的配置。
- 集成 Antom 服务端 SDK 资源包,并完成接口库安装及请求示例初始化。具体操作请参阅服务端 SDK。
- 参阅 iOS 端集成 SDK 资源包文档来集成客户端 SDK 资源包,并注意使用最新或不低于 1.46.0 版本的 SDK。
集成步骤
请按照以下步骤开始集成:
- (可选)预加载 SDK
- 创建支付会话
- 调用 Payment Element
- 获取授权或支付结果
- (可选)请款
- 获取订阅通知
(可选)步骤 1:预加载 SDK 客户端
在创建支付会话前,强烈建议您预加载 SDK,以提升收银台页面的渲染速度,减少买家在支付过程中的等待时间。按照以下代码示例执行预加载操作:
[AMSPaymentElement.shared preload];步骤 2:创建支付会话 服务端
传入订单信息以调用 createPaymentSession(单笔支付)接口来创建支付会话,获取唤起 Payment Element 的 paymentSessionData。您可选择自行渲染支付方式列表或由 Payment Element 渲染支付方式列表。
- 由您自行渲染支付方式列表:当您自行渲染支付方式列表时,您必须传入下表中列出的指定支付方式参数。如果 Payment Element 需要采集支付要素,则需要传入下表中列出的卡支付信息参数。
- 由 Payment Element 渲染支付方式列表:当您使用 Payment Element 渲染的支付方式列表时,您只需传入下表中列出的基础参数。Payment Element 默认在收银台页面上渲染所有支持的支付方式,您也可以通过指定支付方式来选择您需要的支付方式。
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// 替换为您的 paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// 转换金额单位(实际应用中,金额应在您的服务器端计算)
// 详情请参考:<a href="https://docs.antom.com/ac/ref_zh-cn/cc">金额的使用规则</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// 设置金额
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// 设置支付策略
// 替换为您现有的结算货币
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("SGD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// 设置买家信息
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// 替换为您的 orderId
String orderId = UUID.randomUUID().toString();
// 设置订单信息
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// 替换为您的通知地址
// 或者在 Antom Dashboard 配置: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">通知地址</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("http://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// 替换为您的跳转地址
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"http://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
// 设置订阅信息
PeriodRule periodRule = PeriodRule.builder().periodCount(1).
periodType("MONTH").build();
List trials = new ArrayList<Trial>();
Trial trial = Trial.builder().
trialAmount(amount).
trialStartPeriod(1).
trialEndPeriod(2).
build();
trials.add(trial);
SubscriptionInfo subscriptionInfo = SubscriptionInfo.builder().
subscriptionDescription("Subscription description").
subscriptionStartTime("2026-03-11T09:48:17+08:00").
subscriptionEndTime("2026-11-21T09:48:17+08:00").
periodRule(periodRule).
trials(trials).
subscriptionNotifyUrl("https://your.example.com/subscriptionNotify").
subscriptionExpiryTime("2026-03-12T09:48:17+08:00").
build();
alipayPaymentSessionRequest.setSubscriptionInfo(subscriptionInfo);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment 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(), alipayPaymentSessionResponse));
}自行渲染支付方式列表
由 Payment Element 渲染支付方式列表
当您自行渲染支付方式列表时,需要通过指定单个支付方式集成。以下代码展示了一个请求报文的示例:
{
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "USD",
"value": "2900"
},
"orderDescription": "antom sdk testing order",
"referenceOrderId": "4b085ec4-9999-4296-8f00-479e929edb2c"
},
"paymentAmount": {
"currency": "USD",
"value": "2900"
},
"paymentNotifyUrl": "http://www.yourNotifyUrl.com/payment/receivePaymentNotify",
"paymentRedirectUrl": "http://google.com.my",
"paymentRequestId": "PAYMENT_20260313102551842_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT",
"settlementStrategy": {
"settlementCurrency": "USD"
},
"availablePaymentMethod": {
"paymentMethodTypeList": [
{
"paymentMethodType": "ALIPAY_CN" // 指定支付方式
},
{
"paymentMethodType": "TNG"
}
]
},
"subscriptionInfo": {
"periodRule": {
"periodCount": 1,
"periodType": "MONTH"
},
"subscriptionDescription": "Subscription description",
"subscriptionNotifyUrl": "https://your.example.com/subscriptionNotify",
"subscriptionStartTime": "2026-03-11T09:48:17+08:00"
}
}如果由 Payment Element 渲染收银台的支付方式列表,则会展示所有支付方式。以下代码展示了一个请求报文的示例:
{
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "SGD",
"value": "2900"
},
"orderDescription": "antom sdk testing order",
"referenceOrderId": "4b085ec4-9999-4296-8f00-479e929edb2c"
},
"paymentAmount": {
"currency": "SGD",
"value": "2900"
},
"paymentNotifyUrl": "http://www.yourNotifyUrl.com/payment/receivePaymentNotify",
"paymentRedirectUrl": "http://localhost:8080/index.html?paymentRequestId=7a6252b5-6d58-4033-882e-2eff7f262b35",
"paymentRequestId": "7a6252b5-6d58-4033-882e-2eff7f262b35",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT",
"settlementStrategy": {
"settlementCurrency": "SGD"
},
"subscriptionInfo": {
"periodRule": {
"periodCount": 1,
"periodType": "MONTH"
},
"subscriptionDescription": "Subscription description",
"subscriptionEndTime": "2026-11-21T09:48:17+08:00",
"subscriptionExpiryTime": "2026-03-12T09:48:17+08:00",
"subscriptionNotifyUrl": "https://your.example.com/subscriptionNotify",
"subscriptionStartTime": "2026-03-11T09:48:17+08:00",
"trials": [
{
"trialAmount": {
"$ref": "$.order.orderAmount"
},
"trialEndPeriod": 2,
"trialStartPeriod": 1
}
]
}
}以下代码展示了一个响应的示例,其中包含以下参数:
- result.resultStatus:createPaymentSession(单笔支付)接口的调用结果。
- paymentSessionData:将返回给前端的支付会话数据。
- paymentSessionExpiryTime:支付会话的过期时间。
{
"paymentSessionData": "WNoudiUNUDjHjx0oXddzWn0QrRHv52lrHFNMKc8/5uKSqNDklmQ7Nh4JGBNITqi3jgIASZkbpq15gIEQleY13A==&&SG&&188&&eyJhY3Rpb24iOnsibmVlZFZlcmlmeUFuZFJlc3VtZSI6ZmFsc2UsInNpZ25CdXR0b25EaXNwbGF5IjpmYWxzZSwic2tpcFNka1F1ZXJ5IjpmYWxzZSwidXNlclNpZ25BZ3JlZW1lbnQiOmZhbHNlfSwiY2xpZW50SWQiOiJTQU5EQk9YXzVZRVYxRzJaVjQzSzA3MjE3IiwiY29ubmVjdEZhY3RvciI6eyJlbmFibGVDb25uZWN0IjpmYWxzZX0sImVsaWdpYmxlRWFzeVBheU1hcmtldGluZyI6ZmFsc2UsImV4dGVuZEluZm8iOiJ7XCJPUEVOX01VTFRJX1BBWU1FTlRfQUJJTElUWVwiOlwidHJ1ZVwiLFwiZXhwcmVzc0NoZWNrb3V0XCI6XCJmYWxzZVwiLFwidmVyc2lvbk1hcFwiOlwie1xcXCJ3ZWJcXFwiOntcXFwiMS4xLjBcXFwiOntcXFwidGFyZ2V0V2ViVmVyaXNvblxcXCI6XFxcIjEuMS4wXFxcIn0sXFxcIjEuMi4wXFxcIjp7XFxcInRhcmdldFdlYlZlcmlzb25cXFwiOlxcXCIxLjIuMFxcXCJ9fSxcXFwiaU9TXFxcIjp7XFxcIjEuMS4wXFxcIjp7XFxcInRhcmdldFdlYlZlcmlzb25cXFwiOlxcXCIxLjEuMFxcXCJ9LFxcXCIxLjIuMFxcXCI6e1xcXCJ0YXJnZXRXZWJWZXJpc29uXFxcIjpcXFwiMS4yLjBcXFwifX0sXFxcIkFuZHJvaWRcXFwiOntcXFwiMS4xLjBcXFwiOntcXFwidGFyZ2V0V2ViVmVyaXNvblxcXCI6XFxcIjEuMS4wXFxcIn0sXFxcIjEuMi4wXFxcIjp7XFxcInRhcmdldFdlYlZlcmlzb25cXFwiOlxcXCIxLjIuMFxcXCJ9fX1cIn0iLCJuZWVkQWNjb3VudENvbmZpcm1QYWdlIjpmYWxzZSwicGF5bWVudFNlc3Npb25Db25maWciOnsicGF5bWVudE1ldGhvZENhdGVnb3J5VHlwZSI6IkFMTCIsInByb2R1Y3RTY2VuZSI6IkVMRU1FTlRfUEFZTUVOVCIsInByb2R1Y3RTY2VuZVZlcnNpb24iOiIxLjAifSwic2tpcFJlbmRlclBheW1lbnRNZXRob2QiOmZhbHNlfQ==",
"paymentSessionExpiryTime": "2026-03-12T15:24:24+08:00",
"paymentSessionId": "WNoudiUNUDjHjx0oXddzWn0QrRHv52lrHFNMKc8/5uIsshVVNylGbBzLF2n6JmoT",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}以下是创建支付会话响应中 result.resultStatus 可能返回的值,请您根据指引进行处理:
注意:如果您未收到响应报文,可能是网络超时所致。建议更换 paymentRequestId 重新调用接口。如果问题未解决,请联系 Antom 技术支持。
常见问题
问:请求参数的值可以使用中文字符吗?
答:为了避免特定支付方式的兼容性问题,请求中的参数请勿使用中文字符。
问:如何设置接收支付通知的地址?
答:在 createPaymentSession(单笔支付)接口的请求中指定 paymentNotifyUrl 参数,以接收支付结果的异步通知(notifyPayment),或者在 Antom Dashboard 中配置接收地址。如果请求和 Antom Dashboard 中都指定了地址,请求中的值优先。
问:返回的 paymentSessionData 是否需要处理后再传给客户端?
答:请勿对 paymentSessionData 进行任何处理,否则可能会导致调用 Payment Element 失败。
问:首笔交易是否必须进行 3DS 认证?
答:首笔交易为买家主动参与的交易,需完成身份验证,以保障后续周期性扣款(买家不在场)的安全性。具体要求如下:
答:首笔交易为买家主动参与的交易,需完成身份验证,以保障后续周期性扣款(买家不在场)的安全性。具体要求如下:
- 买家使用卡支付:无论由您还是 Antom 采集卡信息,均需完成 3DS 认证。您可以在 createPaymentSession(单笔支付)请求中设置 is3DSAuthentication 为 true以启用 Antom 3DS 认证。
- 买家使用 Google Pay 且由 Antom 解密:您需要设置 is3DSAuthentication 为 true以发起 3DS 交易完成身份验证。若解密后为 DPAN,系统将自动进入授权流程,无需买家二次核身。
- 买家使用 Apple Pay 且由 Antom 解密:您可以设置 is3DSAuthentication 为 false或不传递该参数,因为买家已经完成了 Apple 的核验流程。
步骤 3:调用 Payment Element 客户端
在您的客户端使用 paymentSessionData 调用 Payment Element,在买家提交支付后,Payment Element 会根据不同支付方式,负责展示二维码、跳转支付方式页面、3DS 认证、回跳商户结果页等流程。
- 在服务端获取到 paymentSessionData 后,使用 AMSPaymentElement类来创建 Payment Element 实例。
- 创建 AMSPaymentElementConfiguration 对象时,包括以下参数:
- 实现 AMSPaymentProtocol,用于处理后续流程中的相应事件,包含以下方法:
以下是使用
AMSPaymentElement
创建 Payment Element 实例的示例代码:#import <AMSComponent/AMSComponent-Swift.h>
// 创建一个 AMSPaymentElementConfiguration 对象
AMSPaymentElementConfiguration *componentConfig = [AMSPaymentElementConfiguration new];
componentConfig.locale = @"en_US";
NSString *appearance = @"{\n \"theme\": \"night\",\n \"layout\": {\n \"type\": \"Tabs\"\n },\n \"variables\": {\n \"content-quaternary\": \"#FFFF00\"\n }\n}";
// 设置沙箱环境。如果将其置空,则默认使用线上正式环境
NSDictionary *options = @{@"showLoading": @"true",
@"sandbox": @"true",
@"appearance": appearance
};
componentConfig.options = options;
// initConfiguration 用法
[[AMSPaymentElement shared] initConfiguration:componentConfig completion:^(AMSStatusResult * _Nonnull result) {
// 处理 initConfiguration 用法阶段错误事件
if (result.error) {
// 处理失败
if ([result.error.code isEqualToString:@"UI_STATE_ERROR"]) {
NSLog(@"integration code error, please check the integration code");
} else {
NSLog(@"unknown error, please contact support");
}
} else {
// 处理成功
}
}];
// 设置回调来监听收银台页面的支付事件
[AMSPaymentElement shared].paymentDelegate = self;
// 服务端调用 创建支付会话 接口以获取 paymentSessionData
#pragma AMSPaymentProtocol
// 回调事件码方式 处理 submitPay 阶段事件码
- (void)onSubmitPayCallback:(AMSStatusResult *)eventResult {
AMSStatusResultType statusType = eventResult.status;
AMSResultError *error = eventResult.error;
switch (statusType) {
case AMSStatusResultTypePROCESSING:
if (error && error.code) {
if ([@"PAYMENT_IN_PROCESS" isEqualToString:error.code]) {
NSLog(@"payment is in processing, please try polling the payment result from the server");
} else if ([@"USER_CANCELED" isEqualToString:error.code]) {
NSLog(@"user cancelled the payment process, please try invoke createComponent again");
} else if ([@"UNKNOWN_EXCEPTION" isEqualToString:error.code]) {
NSLog(@"unknown exception, please contact support");
} else if ([@"PAYMENT_RESULT_TIMEOUT" isEqualToString:error.code]) {
NSLog(@"get payment result timeout, please try polling the payment result from the server");
}
}
break;
case AMSStatusResultTypeCANCELLED:
// 继续执行下一 case
case AMSStatusResultTypeSUCCESS:
NSLog(@"payment cancelled or success, do nothing");
break;
case AMSStatusResultTypeFAIL:
if (error && error.code) {
if ([@"ORDER_IS_CANCELLED" isEqualToString:error.code]) {
NSLog(@"the merchant has proactively canceled the order, please check on your own.");
} else if ([@"ORDER_IS_CLOSED" isEqualToString:error.code]) {
NSLog(@"the order has timed out and is closed, please re-initiate payment using a new paymentRequestId.");
} else {
NSLog(@"unknown error, please contact support");
}
}
break;
default:
break;
}
}- 使用实例对象中的 createComponent函数来调用 Payment Element,包含以下方法:
// 回调事件码方式 createComponent 用法
[[AMSPaymentElement shared] createComponent:paymentSessionData completion:^(AMSStatusResult * _Nonnull result) {
if (result.error) {
// 处理失败
if ([result.error.code isEqualToString:@"UI_STATE_ERROR"]) {
NSLog(@"integration code error, please check the integration code");
} else if ([result.error.code isEqualToString:@"PARAM_INVALID"]) {
NSLog(@"session data invalid, please check the session data");
} else if ([result.error.code isEqualToString:@"INITIALIZE_WEB_TIMEOUT"]) {
NSLog(@"web app timeout, please invoke component again");
} else {
NSLog(@"unknown error, please contact support");
}
} else {
// 处理成功
}
}];
卸载 Payment Element
在以下情况下,调用
onDestory
方法来释放 SDK 组件资源:- 当买家切换视图离开结账页面时,释放在 createPaymentSession(单笔支付)接口中创建的组件资源。
- 当买家发起多笔支付,并且 initConfiguration中的参数发生改变时,释放之前 createPaymentSession(单笔支付)接口中创建的组件资源。
// 释放 SDK 组件资源
[[AMSPaymentElement shared] onDestroy];以下情况无需您调用
onDestroy
,SDK 会自动释放资源:- 当买家发起多笔支付,并且 AMSPaymentElementConfiguration中的参数未发生变更。SDK 会在支付结束后自行回收部分资源,以重置到createComponent之前的状态。
回跳商户页面
回跳商户页面及返回支付结果有以下情况,请您按照指引进行处理:
注意:
- 如果支付方式不支持在 SDK 内支付,支付结果不会通过 onSubmitPayCallback:函数返回。跳转到外部支付方式页面完成支付后,由支付方式决策是否自动回跳到您传入的 paymentRedirectUrl。
- onSubmitPayCallback:函数返回的支付结果仅用于客户端页面流转以及状态展示,最终的订单状态请通过步骤 4:获取授权或支付结果获取。
常见问题
问:paymentRedirectUrl 在传参上有什么注意点?
答:paymentRedirectUrl 必须设置为 HTTPS 地址,同时请勿对 URL 中的特殊字符进行编码,否则可能导致支付流程异常。
问:支付结果页内容如何展示?
答:按照以下建议进行展示:
- 您需在支付请求中通过 paymentRedirectUrl 字段传入 HTTPS 地址,用于在商户端展示支付结果。
- 若创建 Payment Element 实例时设置 notRedirectAfterComplete 为 true,且支付方式支持在 SDK 内完成支付,将通过submitPayment().then()返回支付结果,请根据响应中的{code , status}自行处理跳转逻辑。
- 无论订阅创建成功或失败,买家均可能从支付方式端返回商户页面。请勿将 paymentRedirectUrl 固定写为“创建订阅支付成功页面”,应根据服务端实际返回的结果为准,避免误导买家。
问:回跳商户结果页是否代表创建订阅支付成功?
答:不能仅凭回跳页面判断订阅是否创建成功,原因包括:
- 买家创建订阅支付成功后,可能因网络异常等原因未能回跳商户页面。
- 即使买家未完成创建订阅支付,也可能通过支付方式端入口回跳至商户页面。
- 即使买家完成创建订阅支付认证,若首期扣款失败,订阅关系也不会生效。
步骤 4:获取授权或支付结果 服务端
在支付处理流程中,Antom 会根据不同的支付方式类型向您发送相应的结果通知。
- 对于卡支付、Apple Pay 和 Google Pay 场景,Antom 发送的是授权结果通知,告知您授权是否成功。只有授权成功后才会触发请款,请以请款结果作为发货依据。
- 对于 APM 支付场景,当支付成功或失败时 Antom 会向您发送支付结果通知。
您可以通过接收来自 Antom 的异步通知或主动查询来获取支付或授权结果。
接收异步通知
主动查询结果
1. 设置接收通知的 webhook URL
完成支付或支付失败时,Antom 会向您设置的 webhook URL 发送异步通知,您可以选择以下两种方法中的一种来设置接收通知的 webhook URL(若两者都设置,则以接口请求中指定的 URL 优先):
- 若您的每个订单都有单独的通知 URL,建议您在每笔请求中设置 webhook URL。您可以通过 createPaymentSession(单笔支付)接口请求的 paymentNotifyUrl 参数传入该笔订单的异步通知接收 URL。
- 若您的所有订单有统一的通知 URL,您可以在 Antom Dashboard > 开发者 > 通知地址 中设置 webhook URL。具体操作请参阅通知地址。
以下是异步通知请求体的代码示例:
卡支付、Apple Pay、Google Pay
APM 支付
{
"actualPaymentAmount": {
"currency": "SGD",
"value": "4200"
},
"cardInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe",
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "SGD",
"value": "4200"
},
"paymentMethodType": "CARD",
"paymentCreateTime": "2024-01-01T00:00:00+08:00",
"paymentId": "20240101123456789XXXX",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe", // 存储 cardToken 用于后续存卡支付使用
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentTime": "2024-01-01T00:01:00+08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}下表展示了支付结果的异步通知中 result.resultStatus 参数可能返回的值,请您根据指引进行处理:
{
"actualPaymentAmount": {
"currency": "HKD",
"value": "100"
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "HKD",
"value": "100"
},
"paymentCreateTime": "2025-02-04T22:11:19-08:00",
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "ALIPAY_HK",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
},
"paymentTime": "2025-02-04T22:14:25-08:00",
"pspCustomerInfo": {
"pspCustomerId": "216022003753XXXX",
"pspName": "ALIPAY_HK"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}下表展示了支付结果的异步通知中 result.resultStatus 参数可能返回的值,请您根据指引进行处理:
2. 异步通知验签
您需要按照以下方法对 Antom 发送的支付通知进行验签:
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.alipay.global.api.model.Result;
import com.alipay.global.api.model.ResultStatusType;
import com.alipay.global.api.response.AlipayResponse;
import com.alipay.global.api.tools.WebhookTool;
@RestController
public class PaymentNotifyHandleBySDK {
/**
* alipay public key, used to verify signature
*/
private static final String SERVER_PUBLIC_KEY = "";
/**
* payment result notify processor
* using <a href="https://spring.io">Spring Framework</a>
*
* @param request HttpServletRequest
* @param notifyBody notify body
* @return
*/
@PostMapping("/payNotify")
public Object payNotifyHandler(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");
Result result;
AlipayResponse response = new AlipayResponse();
try {
// 验签
boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId, requestTime, signature, notifyBody, SERVER_PUBLIC_KEY);
if (!verifyResult) {
throw new RuntimeException("Invalid notify signature");
}
// 反序列化通知体
// 根据通知结果更新订单状态
// 向服务器响应已接收通知
result = new Result("SUCCESS", "success", ResultStatusType.S);
} catch (Exception e) {
String errorMsg = e.getMessage();
// 处理错误情况
result = new Result("ERROR", errorMsg, ResultStatusType.F);
}
response.setResult(result);
return ResponseEntity.ok().body(response);
}
}无论订单是否支付成功,每个通知请求均需按以下固定格式响应。否则,Antom 会重新发送异步通知。
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}常见问题
问:什么时候会发送通知?
答:这取决于支付是否完成:
- 如果支付成功完成,Antom 通常会在 3 到 5 秒内发送异步通知。对于现金支付,通知可能会稍有延迟。
- 如果支付未完成,Antom 需要先关闭订单,然后发送异步通知。不同支付方式关闭订单所需的时间会有所不同,通常默认为 14 分钟。
问:Antom 会重新发送异步通知吗?
答:会。对于以下情况,异步通知将在 24 小时内自动重新发送:
- 由于网络原因未收到异步通知。
- 如果收到来自 Antom 的异步通知,但您没有按照返回收到确认信息的格式进行响应。
通知可以重发最多 8 次,或者直到收到正确的响应以终止传递。发送间隔如下:0 分钟,2 分钟,10 分钟,10 分钟,1 小时,2 小时,6 小时和15 小时。
问:在响应异步通知时,需要添加签名吗?
问:我在通知中需要使用哪些关键参数?
答:请注意以下关键参数:
- result:对于 APM 支付,其表示支付最终结果。对于 Apple Pay、Google Pay 和卡支付,则仅代表授权结果,需要进一步发起请款。
- paymentRequestId:用于咨询、取消和对账的支付请求 ID。
- paymentId:表示由 Antom 生成的支付订单 ID,用于退款和对账。
- paymentAmount:表示支付金额。
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": "paymentRequestId01"
}以下代码展示了响应报文的示例:
{
"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"
}
}答:请注意以下关键参数:
- result:仅表示本次 inquiryPayment 接口的调用结果。对于 APM 支付,订单的支付结果需要根据 paymentStatus 进行判断(SUCCESS成功/FAIL失败/PROCESSING处理中)。对于卡支付、Apple Pay 和 Google Pay,paymentStatus 仅代表授权结果,是否发货需要依赖请款结果决策。
- paymentAmount:用于核对支付金额。
- paymentId:表示由 Antom 生成的支付订单 ID,用于退款和对账。
(可选)步骤 5:请款 服务端
注意:卡支付及部分 APM 支付方式(如 Apple Pay、Google Pay 和 Pay by Bank)必须进行请款,且仅授权成功后才会触发请款。
授权成功后,Antom 默认自动为您请款,也支持您手动发起请款。同时,Antom 会使用 请款通知(单笔支付)将请款结果通知发送给您,您也可以通过主动查询来获取请款结果。您需要根据请款结果来决定是否发货,具体操作请参阅请款。
步骤 6:获取订阅通知 服务端
用户体验
以下图片展示了集成 Payment Element 首次订阅和后续扣款的用户体验:
首次支付
APM 支付
卡支付
以下图片展示了买家使用 APM 支付的用户体验:

以下图片展示了买家使用卡支付的用户体验:

后续扣款
Antom 服务端将自动发起后续的周期扣款操作,商户服务端通过接收订阅续期扣费通知为买家续订订阅服务。该过程无页面交互。
订单生命周期
以下是不同支付方式的生命周期:
APM 支付
卡支付、Apple Pay、Google Pay
下图展示了 APM 支付的订阅生命周期,包括创建订阅、签约绑定支付方式、完成首次扣款,以及在必要时发起退款等环节,旨在保障订阅的正常生效与费用处理的安全透明:

下图展示了卡支付、Apple Pay 和 Google Pay 支付的订阅生命周期,包括创建订阅、签约绑定支付方式、完成首次扣款,以及在必要时发起退款等环节,旨在保障订阅的正常生效与费用处理的安全透明:


支付流程
以下图片展示了如何通过 Payment Element 集成订阅支付:
APM 支付
卡支付、Apple Pay、Google Pay
首次订阅
周期扣款


首次订阅
周期扣款


首次订阅
周期扣款
- 买家进入订阅商品页面并发起支付。
商户客户端收集买家订阅的相关信息。 - 创建支付会话请求。
调用 createPaymentSession(单笔支付)接口获取支付会话。您可以指定一个或多个支付方式类型,或不指定支付方式类型,以提交支付请求。 - 调用 Payment Element。
在客户端,通过支付会话调用 Payment Element。您可以选择由 Payment Element 或者您自行渲染支付方式,同时 Element 会根据支付方式的特性处理信息、收集支付要素、进行重定向、应用调用、二维码显示、验证等流程。当支付完成后,根据您的设置以及支付方式特性,您需要按照onSubmitPayCallback方法返回的结果处理跳转流程或者由系统自动回跳到您的支付结果页面。 - 获取支付或授权结果。
通过以下两种方法之一获取支付或授权结果:
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当支付成功或过期时,Antom 会使用 notifyPayment 接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询支付或授权状态。
注意:对于卡支付及部分 APM 支付方式(如 Apple Pay、Google Pay 和 Pay by Bank),这些支付方式采用的是授权-请款模式,以上步骤仅完成了授权部分,即买家使用银行卡完成支付,其资金处于冻结状态。为了将买家的冻结资金转至您的账户,您还需要集成请款步骤。请款成功的结果将作为您发货的依据。
- (可选)请款并获取请款结果。
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当请款完成时,Antom 会使用 notifyCapture(单笔支付)接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询请款状态。
- 获取订阅通知。
订阅关系生效后,Antom 会为您发送首期订阅通知及订阅续期通知。
集成准备
- 已获得 client ID。
- 已完成密钥配置。
- 已完成异步通知接收地址的配置。
- 集成 Antom 服务端 SDK 资源包,并完成接口库安装及请求示例初始化。具体操作请参阅服务端 SDK。
- 参阅 Android 端集成 SDK 资源包文档来集成客户端 SDK 资源包,并注意使用最新或不低于 1.46.0 版本的 SDK。
- Antom 服务端向支付方式发起扣款。
- 获取支付或授权结果。
通过以下两种方法之一获取支付或授权结果:
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当支付成功或过期时,Antom 会使用 notifyPayment 接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询支付或授权状态。
注意:对于卡支付及部分 APM 支付方式(如 Google Pay、Apple Pay 和 Pay by Bank),这些支付方式采用的是授权-请款模式,以上步骤仅完成了授权部分,即买家使用银行卡完成支付,其资金处于冻结状态。为了将买家的冻结资金转至您的账户,您还需要集成请款步骤。请款成功的结果将作为您发货的依据。
- (可选)请款并获取请款结果。
周期扣款场景下,Antom 会自动为您处理资金请款。您可以通过以下两种方法之一获取请款结果:
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当请款完成时,Antom 会使用 notifyCapture(单笔支付)接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询请款状态。
- 获取订阅通知。
扣款成功或失败后,Antom 会为您发送订阅扣款通知。
集成步骤
请按照以下步骤开始集成:
- (可选)预加载 SDK
- 创建支付会话
- 调用 Payment Element
- 获取授权或支付结果
- (可选)请款
- 获取订阅通知
(可选)步骤 1:预加载 SDK 客户端
在创建支付会话前,强烈建议您预加载 SDK,以提升收银台页面的渲染速度,减少买家在支付过程中的等待时间。按照以下代码示例执行预加载操作:
AMSPaymentElement.preload(getApplicationContext());步骤 2:创建支付会话 服务端
传入订单信息以调用 createPaymentSession(单笔支付)接口来创建支付会话,获取唤起 Payment Element 的 paymentSessionData。您可选择自行渲染支付方式列表或由 Payment Element 渲染支付方式列表。
- 自行渲染支付方式列表:当您自行渲染支付方式列表时,您必须传入下表中列出的指定支付方式参数。如果 Payment Element 需要采集支付要素,则需要传入下表中列出的卡支付信息参数。
- 由 Payment Element 渲染支付方式列表:当您使用 Payment Element 渲染的支付方式列表时,您只需传入下表中列出的基础参数。Payment Element 默认在收银台页面上渲染所有支持的支付方式,您也可以通过指定支付方式来选择您需要的支付方式。
- 由 Payment Element 渲染支付方式列表:当您使用 Payment Element 渲染的支付方式列表时,您只需传入下表中列出的基础参数。Payment Element 默认在收银台页面上渲染所有支持的支付方式,您也可以通过指定支付方式来选择您需要的支付方式。
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// 替换为您的 paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// 转换金额单位(实际应用中,金额应在您的服务器端计算)
// 详情请参考:<a href="https://docs.antom.com/ac/ref_zh-cn/cc">金额的使用规则</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// 设置金额
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// 设置支付策略
// 替换为您现有的结算货币
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("SGD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// 设置买家信息
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// 替换为您的 orderId
String orderId = UUID.randomUUID().toString();
// 设置订单信息
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// 替换为您的通知地址
// 或者在 Antom Dashboard 配置: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">通知地址</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("http://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// 替换为您的跳转地址
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"http://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
// 设置订阅信息
PeriodRule periodRule = PeriodRule.builder().periodCount(1).
periodType("MONTH").build();
List trials = new ArrayList<Trial>();
Trial trial = Trial.builder().
trialAmount(amount).
trialStartPeriod(1).
trialEndPeriod(2).
build();
trials.add(trial);
SubscriptionInfo subscriptionInfo = SubscriptionInfo.builder().
subscriptionDescription("Subscription description").
subscriptionStartTime("2026-03-11T09:48:17+08:00").
subscriptionEndTime("2026-11-21T09:48:17+08:00").
periodRule(periodRule).
trials(trials).
subscriptionNotifyUrl("https://your.example.com/subscriptionNotify").
subscriptionExpiryTime("2026-03-12T09:48:17+08:00").
build();
alipayPaymentSessionRequest.setSubscriptionInfo(subscriptionInfo);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment 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(), alipayPaymentSessionResponse));
}自行渲染支付方式列表
由 Payment Element 渲染支付方式列表
当您自行渲染支付方式列表时,需要通过指定单个支付方式集成。以下代码展示了一个请求报文的示例:
{
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "USD",
"value": "2900"
},
"orderDescription": "antom sdk testing order",
"referenceOrderId": "4b085ec4-9999-4296-8f00-479e929edb2c"
},
"paymentAmount": {
"currency": "USD",
"value": "2900"
},
"paymentNotifyUrl": "http://www.yourNotifyUrl.com/payment/receivePaymentNotify",
"paymentRedirectUrl": "http://google.com.my",
"paymentRequestId": "PAYMENT_20260313102551842_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT",
"settlementStrategy": {
"settlementCurrency": "USD"
},
"availablePaymentMethod": {
"paymentMethodTypeList": [
{
"paymentMethodType": "ALIPAY_CN" // 指定支付方式
},
{
"paymentMethodType": "TNG"
}
]
},
"subscriptionInfo": {
"periodRule": {
"periodCount": 1,
"periodType": "MONTH"
},
"subscriptionDescription": "Subscription description",
"subscriptionNotifyUrl": "https://your.example.com/subscriptionNotify",
"subscriptionStartTime": "2026-03-11T09:48:17+08:00"
}
}如果由 Payment Element 渲染收银台的支付方式列表,则会展示所有支付方式。以下代码展示了一个请求报文的示例:
{
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "SGD",
"value": "2900"
},
"orderDescription": "antom sdk testing order",
"referenceOrderId": "4b085ec4-9999-4296-8f00-479e929edb2c"
},
"paymentAmount": {
"currency": "SGD",
"value": "2900"
},
"paymentNotifyUrl": "http://www.yourNotifyUrl.com/payment/receivePaymentNotify",
"paymentRedirectUrl": "http://localhost:8080/index.html?paymentRequestId=7a6252b5-6d58-4033-882e-2eff7f262b35",
"paymentRequestId": "7a6252b5-6d58-4033-882e-2eff7f262b35",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT",
"settlementStrategy": {
"settlementCurrency": "SGD"
},
"subscriptionInfo": {
"periodRule": {
"periodCount": 1,
"periodType": "MONTH"
},
"subscriptionDescription": "Subscription description",
"subscriptionEndTime": "2026-11-21T09:48:17+08:00",
"subscriptionExpiryTime": "2026-03-12T09:48:17+08:00",
"subscriptionNotifyUrl": "https://your.example.com/subscriptionNotify",
"subscriptionStartTime": "2026-03-11T09:48:17+08:00",
"trials": [
{
"trialAmount": {
"$ref": "$.order.orderAmount"
},
"trialEndPeriod": 2,
"trialStartPeriod": 1
}
]
}
}以下代码展示了一个响应的示例,其中包含以下参数:
- result.resultStatus:createPaymentSession(单笔支付)接口的调用结果。
- paymentSessionData:将返回给前端的支付会话数据。
- paymentSessionExpiryTime:支付会话的过期时间。
{
"paymentSessionData": "WNoudiUNUDjHjx0oXddzWn0QrRHv52lrHFNMKc8/5uKSqNDklmQ7Nh4JGBNITqi3jgIASZkbpq15gIEQleY13A==&&SG&&188&&eyJhY3Rpb24iOnsibmVlZFZlcmlmeUFuZFJlc3VtZSI6ZmFsc2UsInNpZ25CdXR0b25EaXNwbGF5IjpmYWxzZSwic2tpcFNka1F1ZXJ5IjpmYWxzZSwidXNlclNpZ25BZ3JlZW1lbnQiOmZhbHNlfSwiY2xpZW50SWQiOiJTQU5EQk9YXzVZRVYxRzJaVjQzSzA3MjE3IiwiY29ubmVjdEZhY3RvciI6eyJlbmFibGVDb25uZWN0IjpmYWxzZX0sImVsaWdpYmxlRWFzeVBheU1hcmtldGluZyI6ZmFsc2UsImV4dGVuZEluZm8iOiJ7XCJPUEVOX01VTFRJX1BBWU1FTlRfQUJJTElUWVwiOlwidHJ1ZVwiLFwiZXhwcmVzc0NoZWNrb3V0XCI6XCJmYWxzZVwiLFwidmVyc2lvbk1hcFwiOlwie1xcXCJ3ZWJcXFwiOntcXFwiMS4xLjBcXFwiOntcXFwidGFyZ2V0V2ViVmVyaXNvblxcXCI6XFxcIjEuMS4wXFxcIn0sXFxcIjEuMi4wXFxcIjp7XFxcInRhcmdldFdlYlZlcmlzb25cXFwiOlxcXCIxLjIuMFxcXCJ9fSxcXFwiaU9TXFxcIjp7XFxcIjEuMS4wXFxcIjp7XFxcInRhcmdldFdlYlZlcmlzb25cXFwiOlxcXCIxLjEuMFxcXCJ9LFxcXCIxLjIuMFxcXCI6e1xcXCJ0YXJnZXRXZWJWZXJpc29uXFxcIjpcXFwiMS4yLjBcXFwifX0sXFxcIkFuZHJvaWRcXFwiOntcXFwiMS4xLjBcXFwiOntcXFwidGFyZ2V0V2ViVmVyaXNvblxcXCI6XFxcIjEuMS4wXFxcIn0sXFxcIjEuMi4wXFxcIjp7XFxcInRhcmdldFdlYlZlcmlzb25cXFwiOlxcXCIxLjIuMFxcXCJ9fX1cIn0iLCJuZWVkQWNjb3VudENvbmZpcm1QYWdlIjpmYWxzZSwicGF5bWVudFNlc3Npb25Db25maWciOnsicGF5bWVudE1ldGhvZENhdGVnb3J5VHlwZSI6IkFMTCIsInByb2R1Y3RTY2VuZSI6IkVMRU1FTlRfUEFZTUVOVCIsInByb2R1Y3RTY2VuZVZlcnNpb24iOiIxLjAifSwic2tpcFJlbmRlclBheW1lbnRNZXRob2QiOmZhbHNlfQ==",
"paymentSessionExpiryTime": "2026-03-12T15:24:24+08:00",
"paymentSessionId": "WNoudiUNUDjHjx0oXddzWn0QrRHv52lrHFNMKc8/5uIsshVVNylGbBzLF2n6JmoT",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}以下是创建支付会话响应中 result.resultStatus 可能返回的值,请您根据指引进行处理:
注意:如果您未收到响应报文,可能是网络超时所致。建议更换 paymentRequestId 重新调用接口。如果问题未解决,请联系 Antom 技术支持。
常见问题
问:请求参数的值可以使用中文字符吗?
答:为了避免特定支付方式的兼容性问题,请求中的参数请勿使用中文字符。
问:如何设置接收支付通知的地址?
答:在 createPaymentSession(单笔支付)接口的请求中指定 paymentNotifyUrl 参数,以接收支付结果的异步通知(notifyPayment),或者在 Antom Dashboard 中配置接收地址。如果请求和 Antom Dashboard 中都指定了地址,请求中的值优先。
问:返回的 paymentSessionData 是否需要处理后再传给客户端?
答:请勿对 paymentSessionData 进行任何处理,否则可能会导致调用 Payment Element 失败。
问:首笔交易是否必须进行 3DS 认证?
答:首笔交易为买家主动参与的交易,需完成身份验证,以保障后续周期性扣款(买家不在场)的安全性。具体要求如下:
答:首笔交易为买家主动参与的交易,需完成身份验证,以保障后续周期性扣款(买家不在场)的安全性。具体要求如下:
- 买家使用卡支付:无论由您还是 Antom 采集卡信息,均需完成 3DS 认证。您可以在 createPaymentSession(单笔支付)请求中设置 is3DSAuthentication 为 true以启用 Antom 3DS 认证。
- 买家使用 Google Pay 且由 Antom 解密:您需要设置 is3DSAuthentication 为 true以发起 3DS 交易完成身份验证。若解密后为 DPAN,系统将自动进入授权流程,无需买家二次核身。
- 买家使用 Apple Pay 且由 Antom 解密:您可以设置 is3DSAuthentication 为 false或不传递该参数,因为买家已经完成了 Apple 的核验流程。
步骤 3:调用 Payment Element 客户端
在您的客户端使用 paymentSessionData 调用 Payment Element,在买家提交支付后,Payment Element 会根据不同支付方式,负责展示二维码、跳转支付方式页面、3DS 认证、回跳商户结果页等流程。
- 在服务端获取到 paymentSessionData 后,使用 AMSPaymentElement类来创建 SDK 实例。
- 创建 AMSPaymentElementConfiguration 对象时,包括以下参数:
- 实现 OnCreateComponentListener,用于处理调用支付组件及拉起支付页面流程中的相关事件,包含以下方法:
- 实现 OnSubmitPayListener,用于处理发起支付过程中的相关事件,包含以下方法:
以下是使用
AMSPaymentElement
创建 SDK 实例的示例代码:AMSPaymentElementConfiguration configuration = new AMSPaymentElementConfiguration();
configuration.setLocale(new Locale("en", "US"));
configuration.setOption("showLoading", "true");
configuration.setOption("sandbox", "true");
configuration.setOption("notRedirectAfterComplete", "false");
String appearance = "{\"theme\":\"night\",\"layout\":{\"type\":\"accordion\"},\"variables\":{\"content-primary\":\"#ff5b4d\"}}";
configuration.setOption("appearance", appearance);
configuration.setOnCreateComponentListener(new OnCreateComponentListener() {
@Override
public void onCreateComponentCallback(AMSStatusResult statusResult) {
if (statusResult.getError() != null) {
switch (statusResult.getError().getCode()) {
case "UI_STATE_ERROR":
System.out.println("integration code error, please check the integration code");
break;
case "PARAM_INVALID":
System.out.println("session data invalid, please check the session data");
break;
case "INITIALIZE_WEB_TIMEOUT":
System.out.println("web app timeout, please invoke component again");
break;
default:
System.out.println("unknown error, please contact support");
break;
}
}
}
});
configuration.setOnSubmitPayListener(new OnSubmitPayListener() {
@Override
public void onSubmitPayCallback(AMSStatusResult statusResult) {
AMSStatus status = statusResult.getStatus();
AMSResultError error = statusResult.getError();
if (status == AMSStatus.PROCESSING) {
if (error != null && error.getCode() != null) {
if ("PAYMENT_IN_PROCESS".equals(error.getCode())) {
System.out.println("payment is in processing, please try polling the payment result from the server");
} else if ("USER_CANCELED".equals(error.getCode())){
System.out.println("user cancelled the payment process, please try invoke createComponent again");
} else if ("UNKNOWN_EXCEPTION".equals(error.getCode())) {
System.out.println("unknown exception, please contact support");
} else if ("PAYMENT_RESULT_TIMEOUT".equals(error.getCode())){
System.out.println("get payment result timeout, please try polling the payment result from the server");
}
}
} else if (status == AMSStatus.CANCELLED || status == AMSStatus.SUCCESS) {
System.out.println("payment cancelled or success, do nothing");
} else if (status == AMSStatus.FAIL) {
if (error != null && error.getCode() != null) {
if ("ORDER_IS_CANCELLED".equals(error.getCode())) {
System.out.println("the merchant has proactively canceled the order, please check on your own.");
} else if ("ORDER_IS_CLOSED".equals(error.getCode()) || "INQUIRY_PAYMENT_SESSION_FAILED".equals(error.getCode())){
System.out.println("the order has timed out and is closed, please re-initiate payment using a new paymentRequestId.");
} else {
System.out.println("unknown error, please contact support");
}
}
}
}
});
AMSPaymentElement amsPaymentElement = new AMSPaymentElement.Builder(this, (AMSPaymentElementConfiguration) configuration).build();
- 使用实例对象中的 createComponent函数来调用 Payment Element:
// 创建支付会话时获取的 paymentSessionData
String paymentSessionData = "exxxxe";
amsPaymentElement.createComponent(this, paymentSessionData);卸载 Payment Element
在以下情况下,调用
onDestory
方法来释放 SDK 组件资源:- 当买家切换视图离开结账页面时,释放在 createPaymentSession(单笔支付)接口中创建的组件资源。
- 当买家发起多笔支付,并且 AMSPaymentElementConfiguration中的参数发生改变时,释放之前 createPaymentSession(单笔支付)中创建的组件资源。
// 释放 SDK 组件资源
amsPaymentElement.onDestroy();以下情况无需您调用
onDestroy
,SDK 会自动释放资源(Android SDK 版本需不低于 1.33.0):- 当买家发起多笔支付,并且 AMSPaymentElementConfiguration中的参数未发生变更。SDK 会在支付结束后自行回收部分资源,以重置到createComponent之前的状态。
回跳商户页面
回跳商户页面及返回支付结果有以下情况,请您按照指引进行处理:
注意:
- 如果支付方式不支持在 SDK 内支付,支付结果不会通过 onSubmitPayCallback函数返回。跳转到外部支付方式页面完成支付后,由支付方式决策是否自动回跳到您传入的 paymentRedirectUrl。
- onSubmitPayCallback函数返回的支付结果仅用于客户端页面流转以及状态展示,最终的订单状态请通过步骤 4:获取授权或支付结果获取。
常见问题
问:paymentRedirectUrl 在传参上有什么注意点?
答:paymentRedirectUrl 必须设置为 HTTPS 地址,同时请勿对 URL 中的特殊字符进行编码,否则可能导致支付流程异常。
问:支付结果页内容如何展示?
答:按照以下建议进行展示:
- 您需在支付请求中通过 paymentRedirectUrl 字段传入 HTTPS 地址,用于在商户端展示支付结果。
- 若创建 Payment Element 实例时设置 notRedirectAfterComplete 为 true,且支付方式支持在 SDK 内完成支付,将通过submitPayment().then()返回支付结果,请根据响应中的{code , status}自行处理跳转逻辑。
- 无论订阅创建成功或失败,买家均可能从支付方式端返回商户页面。请勿将 paymentRedirectUrl 固定写为“创建订阅支付成功页面”,应根据服务端实际返回的结果为准,避免误导买家。
问:回跳商户结果页是否代表创建订阅支付成功?
答:不能仅凭回跳页面判断订阅是否创建成功,原因包括:
- 买家创建订阅支付成功后,可能因网络异常等原因未能回跳商户页面。
- 即使买家未完成创建订阅支付,也可能通过支付方式端入口回跳至商户页面。
- 即使买家完成创建订阅支付认证,若首期扣款失败,订阅关系也不会生效。
步骤 4:获取授权或支付结果 服务端
在支付处理流程中,Antom 会根据不同的支付方式类型向您发送相应的结果通知。
- 对于卡支付、Apple Pay 和 Google Pay 场景,Antom 发送的是授权结果通知,告知您授权是否成功。只有授权成功后才会触发请款,请以请款结果作为发货依据。
- 对于 APM 支付场景,当支付成功或失败时 Antom 会向您发送支付结果通知。
您可以通过接收来自 Antom 的异步通知或主动查询来获取支付或授权结果。
接收异步通知
主动查询结果
1. 设置接收通知的 webhook URL
完成支付或支付失败时,Antom 会向您设置的 webhook URL 发送异步通知,您可以选择以下两种方法中的一种来设置接收通知的 webhook URL(若两者都设置,则以接口请求中指定的 URL 优先):
- 若您的每个订单都有单独的通知 URL,建议您在每笔请求中设置 webhook URL。您可以通过 createPaymentSession(单笔支付)接口请求的 paymentNotifyUrl 参数传入该笔订单的异步通知接收 URL。
- 若您的所有订单有统一的通知 URL,您可以在 Antom Dashboard > 开发者 > 通知地址 中设置 webhook URL。具体操作请参阅通知地址。
以下是异步通知请求体的代码示例:
卡支付、Apple Pay、Google Pay
APM 支付
{
"actualPaymentAmount": {
"currency": "SGD",
"value": "4200"
},
"cardInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe",
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "SGD",
"value": "4200"
},
"paymentMethodType": "CARD",
"paymentCreateTime": "2024-01-01T00:00:00+08:00",
"paymentId": "20240101123456789XXXX",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe", // 存储 cardToken 用于后续存卡支付使用
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentTime": "2024-01-01T00:01:00+08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}下表展示了支付结果的异步通知中 result.resultStatus 参数可能返回的值,请您根据指引进行处理:
{
"actualPaymentAmount": {
"currency": "HKD",
"value": "100"
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "HKD",
"value": "100"
},
"paymentCreateTime": "2025-02-04T22:11:19-08:00",
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "ALIPAY_HK",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
},
"paymentTime": "2025-02-04T22:14:25-08:00",
"pspCustomerInfo": {
"pspCustomerId": "216022003753XXXX",
"pspName": "ALIPAY_HK"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}下表展示了支付结果的异步通知中 result.resultStatus 参数可能返回的值,请您根据指引进行处理:
2. 异步通知验签
您需要按照以下方法对 Antom 发送的支付通知进行验签:
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.alipay.global.api.model.Result;
import com.alipay.global.api.model.ResultStatusType;
import com.alipay.global.api.response.AlipayResponse;
import com.alipay.global.api.tools.WebhookTool;
@RestController
public class PaymentNotifyHandleBySDK {
/**
* alipay public key, used to verify signature
*/
private static final String SERVER_PUBLIC_KEY = "";
/**
* payment result notify processor
* using <a href="https://spring.io">Spring Framework</a>
*
* @param request HttpServletRequest
* @param notifyBody notify body
* @return
*/
@PostMapping("/payNotify")
public Object payNotifyHandler(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");
Result result;
AlipayResponse response = new AlipayResponse();
try {
// 验签
boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId, requestTime, signature, notifyBody, SERVER_PUBLIC_KEY);
if (!verifyResult) {
throw new RuntimeException("Invalid notify signature");
}
// 反序列化通知体
// 根据通知结果更新订单状态
// 向服务器响应已接收通知
result = new Result("SUCCESS", "success", ResultStatusType.S);
} catch (Exception e) {
String errorMsg = e.getMessage();
// 处理错误情况
result = new Result("ERROR", errorMsg, ResultStatusType.F);
}
response.setResult(result);
return ResponseEntity.ok().body(response);
}
}无论订单是否支付成功,每个通知请求均需按以下固定格式响应。否则,Antom 会重新发送异步通知。
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}常见问题
问:什么时候会发送通知?
答:这取决于支付是否完成:
- 如果支付成功完成,Antom 通常会在 3 到 5 秒内发送异步通知。对于现金支付,通知可能会稍有延迟。
- 如果支付未完成,Antom 需要先关闭订单,然后发送异步通知。不同支付方式关闭订单所需的时间会有所不同,通常默认为 14 分钟。
问:Antom 会重新发送异步通知吗?
答:会。对于以下情况,异步通知将在 24 小时内自动重新发送:
- 由于网络原因未收到异步通知。
- 如果收到来自 Antom 的异步通知,但您没有按照返回收到确认信息的格式进行响应。
通知可以重发最多 8 次,或者直到收到正确的响应以终止传递。发送间隔如下:0 分钟,2 分钟,10 分钟,10 分钟,1 小时,2 小时,6 小时和15 小时。
问:在响应异步通知时,需要添加签名吗?
问:我在通知中需要使用哪些关键参数?
答:请注意以下关键参数:
- result:对于 APM 支付,其表示支付最终结果。对于 Apple Pay、Google Pay 和卡支付,则仅代表授权结果,需要进一步发起请款。
- paymentRequestId:用于咨询、取消和对账的支付请求 ID。
- paymentId:表示由 Antom 生成的支付订单 ID,用于退款和对账。
- paymentAmount:表示支付金额。
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": "paymentRequestId01"
}以下代码展示了响应报文的示例:
{
"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"
}
}答:请注意以下关键参数:
- result:仅表示本次 inquiryPayment 接口的调用结果。对于 APM 支付,订单的支付结果需要根据 paymentStatus 进行判断(SUCCESS成功/FAIL失败/PROCESSING处理中)。对于卡支付、Apple Pay 和 Google Pay,paymentStatus 仅代表授权结果,是否发货需要依赖请款结果决策。
- paymentAmount:用于核对支付金额。
- paymentId:表示由 Antom 生成的支付订单 ID,用于退款和对账。
(可选)步骤 5:请款 服务端
注意:卡支付及部分 APM 支付方式(如 Apple Pay、Google Pay 和 Pay by Bank)必须进行请款,且仅授权成功后才会触发请款。
授权成功后,Antom 默认自动为您请款,也支持您手动发起请款。同时,Antom 会使用 请款通知(单笔支付)将请款结果通知发送给您,您也可以通过主动查询来获取请款结果。您需要根据请款结果来决定是否发货,具体操作请参阅请款。
步骤 6:获取订阅通知 服务端
订阅关系生效后,Antom 会为您发送以下通知:
首期订阅通知
Antom 将通过 HTTPS 向您在接口或 Antom Dashboard 中配置的 Webhook 推送以下事件通知:
订阅状态通知
当期扣款结果通知
请按以下步骤获取订阅状态通知:
- 设置接收通知的 webhook URL:通过 createPaymentSession(单笔支付)接口的 subscriptionInfo.subscriptionNotifyUrl 参数设置。以下是两种订阅状态的通知示例:
- 当 subscriptionNotificationType 的值为 CREATE时,请根据 subscriptionStatus 的值判断订阅关系:
- ACTIVE:表示订阅关系生效。
- TERMINATED:表示订阅关系失效。
{
"periodRule": {
"periodCount": 1,
"periodType": "MONTH"
},
"subscriptionEndTime": "2074-02-20T01:16:17-08:00",
"subscriptionId": "20240914190000000000000050000010226",
"subscriptionNotificationType": "CREATE",
"subscriptionRequestId": "SUBSCRIPTION_202444091410165oo009851_AUTO",
"subscriptionStartTime": "2024-09-13T19:30:17-07:00",
"subscriptionStatus": "ACTIVE"
}- 当 subscriptionNotificationType 的值为 TERMINATE时,订阅关系失效。
{
"periodRule": {
"periodCount": 1,
"periodType": "WEEK"
},
"subscriptionId": "2025102619******00000160000671943",
"subscriptionLastUpdateTime": "2025-10-26T09:51:13-07:00",
"subscriptionNotificationType": "TERMINATE",
"subscriptionRequestId": "PR_en_****176",
"subscriptionStartTime": "2025-10-26T10:01:13-07:00",
"subscriptionStatus": "TERMINATED"
}- 异步通知验签。
您需要按照以下方法对 Antom 发送的通知进行验签:
/**
* 接收订阅通知
*
* @param request request
* @param notifyBody notify body
* @return Result
*/
@PostMapping("/receiveSubscriptionNotify")
@ResponseBody
public Result receiveSubscriptionNotify(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");
}
// 反序列化通知报文体
AlipaySubscriptionNotify subscriptionNotify = JSON.parseObject(notifyBody, AlipaySubscriptionNotify.class);
if (subscriptionNotify != null && SubscriptionNotificationType.CREATE.equals(subscriptionNotify.getSubscriptionNotificationType())) {
// 处理你的业务逻辑
// 例如:通过 subscriptionRequestId 与用户 ID 的关系保存用户的订阅信息。
System.out.println("receive subscription notify: " + JSON.toJSONString(subscriptionNotify));
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();
}- 响应通知结果。无论订单是否支付成功,每个通知请求均需按以下固定格式响应。否则,Antom 会重新发送异步通知。
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}请按以下步骤获取当期扣款结果通知:
- 设置接收通知的 webhook URL:在 createPaymentSession(单笔支付)接口请求的 paymentNotifyUrl 参数设置和 Antom Dashboard 配置。
以下为异步通知请求体的代码示例:
{
"paymentAmount": {
"currency": "USD",
"value": "1"
},
"notifyType": "PAYMENT_RESULT",
"paymentCreateTime": "2025-10-08T19:10:51-07:00",
"paymentId": "202510091940108001001889B0255128143",
"paymentTime": "2025-10-08T19:11:40-07:00",
"periodEndTime": "2025-08-02T19:15:29-07:00",
"periodStartTime": "2025-07-26T19:15:29-07:00",
"phaseNo": "1",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success",
"resultStatus": "S"
},
"subscriptionId": "202510091900000000000000E0000032897",
"subscriptionRequestId": "PAYMENT_20251009101050687_AUTO"
}关键参数说明:
- notifyType:通知类型,值为 PAYMENT_RESULT。
- phaseNo:订阅当期的期数。
- periodStartTime:本期订阅开始时间。
- periodEndTime:本期订阅结束时间。
- paymentAmount:每期周期扣款的金额。
- 异步通知验签。
您需要按照以下方法对 Antom 发送的通知进行验签:
/**
* 接收支付通知
*
* @param request HTTP 请求对象
* @param notifyBody 通知的请求体
* @return Result 返回结果
*/
@PostMapping("/receivePaymentNotify")
@ResponseBody
public Result receivePaymentNotify(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("通知签名无效");
}
// 反序列化通知报文体
AlipaySubscriptionPayNotify paymentNotify = JSON.parseObject(notifyBody, AlipaySubscriptionPayNotify.class);
if (paymentNotify != null && "SUCCESS".equals(paymentNotify.getResult().getResultCode())) {
// 处理你的业务逻辑
// 例如:通过 subscriptionRequestId 与用户 ID 的关系保存用户的支付信息。
System.out.println("接收到支付通知: " + 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();
}- 响应通知结果。无论订单是否支付成功,每个通知请求均需按以下固定格式响应。否则,Antom 会重新发送异步通知。
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}常见问题
问:Antom 会重新发送异步通知吗?
答:会。对于以下情况,异步通知将在 24 小时内自动重新发送:
- 由于网络原因未收到异步通知。
- 如果收到来自 Antom 的异步通知,但您没有按照返回收到确认信息的格式进行响应。
通知可以重发最多 8 次,或者直到收到正确的响应以终止传递。发送间隔如下:0 分钟,2 分钟,10 分钟,10 分钟,1 小时,2 小时,6 小时和 15 小时。
问:收到支付结果通知是否需要验签?
答:需要。通过验签 Antom 会发送保障回调请求给您,验签时请注意拼装待验签报文时需按标准处理:
<http-method> <http-uri> <client-id>.<request-time>.<request-body>
,特别是针对 <request-body>
需直接取值而非解析 JSON 后拼装。
问:若首次支付失败,订阅关系会生效吗?
答:当订阅开通的首次扣款失败时,订阅关系将不会生效,Antom 系统会通过 Webhook 推送 subscriptionStatus 为
TERMINATED
的状态通知给您,表明订阅开通失败。
问:订阅超时时间是多久?
答:针对 APM 类支付方式,默认为 30 分钟超时时间;针对卡支付类支付方式,默认为 7 天超时时间。
订阅续期通知
当订阅创建成功并建立有效关系后,Antom 系统将会根据您配置的订阅规则,自动发起续订扣款,并通过 Webhook 推送相应的支付结果通知,实现周期性扣费。触发续订扣款的时间和规则如下:
- 触发时间:续订扣款将在下一个订阅周期起始日的前 24 小时自动触发。您可以依据上一周期支付结果通知中的 periodEndTime 字段,向前推 24 小时以判断下一周期扣款的发起时间。
- 周期规则:续费周期及扣款频率将按照订阅时设定的 periodRule 执行,例如按日、按月、按季度或按年扣款。
卡支付、Google Pay 和 Apple Pay
APM 支付
卡支付、Apple Pay 和 Google Pay 支付场景下,异步通知通常分为以下场景:
以下为各场景异步通知的示例代码:
授权支付结果通知
请款通知
订阅结果通知
当期扣款结果通知
以下为授权支付结果通知请求体的示例代码:
{
"actualPaymentAmount": {
"currency": "USD",
"value": "1"
},
"cardInfo": {
"avsResultRaw": "U",
"cardBrand": "VISA",
"cardCategory": "CONSUMER",
"cardNo": "************0550",
"credentialTypeUsed": "PAN",
"cvvResultRaw": "M",
"funding": "PREPAID",
"issuingCountry": "MY",
"networkTransactionId": "202510090310009b937936376",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "mockCavv",
"challengeCancel": "",
"challenged": true,
"dsTransactionId": "cce18b6e-b55e-40ff-814c-619b45987636",
"eci": "02",
"threeDSOffered": true,
"threeDSVersion": "2.1.0",
"threeDStransactionStatusReason": ""
}
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "USD",
"value": "1"
},
"paymentCreateTime": "2025-10-08T19:11:20-07:00",
"paymentId": "202510091940108001001889B0255128143",
"paymentMethodType": "GOOGLEPAY",
"paymentRequestId": "PAYMENT_20251009101050687_AUTO",
"paymentResultInfo": {
"avsResultRaw": "U",
"cardBrand": "VISA",
"cardCategory": "CONSUMER",
"cardNo": "************0550",
"credentialTypeUsed": "PAN",
"cvvResultRaw": "M",
"funding": "PREPAID",
"issuingCountry": "MY",
"networkTransactionId": "202510090310009b937936376",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "mockCavv",
"challengeCancel": "",
"challenged": true,
"dsTransactionId": "cce18b6e-b55e-40ff-814c-619b45987636",
"eci": "02",
"threeDSOffered": true,
"threeDSVersion": "2.1.0",
"threeDStransactionStatusReason": ""
}
},
"paymentTime": "2025-10-08T19:11:38-07:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}以下为请款通知请求体的示例代码:
{
"captureAmount": {
"currency": "USD",
"value": "1"
},
"captureId": "202510091940108070001889B0280060023",
"captureRequestId": "PAYMENT_20251009101050687_AUTO",
"captureTime": "2025-10-08T19:11:40-07:00",
"notifyType": "CAPTURE_RESULT",
"paymentId": "202510091940108001001889B0255128143",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}无通知。
以下为当期扣款结果通知请求体的示例代码:
{
"paymentAmount": {
"currency": "USD",
"value": "1"
},
"notifyType": "PAYMENT_RESULT",
"paymentCreateTime": "2025-10-08T19:10:51-07:00",
"paymentId": "202510091940108001001889B0255128143",
"paymentTime": "2025-10-08T19:11:40-07:00",
"periodEndTime": "2025-08-02T19:15:29-07:00",
"periodStartTime": "2025-07-26T19:15:29-07:00",
"phaseNo": "1",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success",
"resultStatus": "S"
},
"subscriptionId": "202510091900000000000000E0000032897",
"subscriptionRequestId": "PAYMENT_20251009101050687_AUTO"
}关键参数说明:
- notifyType:通知类型,值为 PAYMENT_RESULT。
- phaseNo:订阅当期的期数。
- periodStartTime:本期订阅开始时间。
- periodEndTime:本期订阅结束时间。
- paymentAmount:每期周期扣款的金额。
APM 支付场景下,异步通知通常分为以下场景:
以下为各场景异步通知的示例代码:
支付结果通知
订阅状态通知
当期扣款结果通知
无通知。
无通知。
以下为当期扣款结果通知请求体的示例代码:
{
"paymentAmount": {
"currency": "USD",
"value": "1"
},
"notifyType": "PAYMENT_RESULT",
"paymentCreateTime": "2025-10-08T19:10:51-07:00",
"paymentId": "202510091940108001001889B0255128143",
"paymentTime": "2025-10-08T19:11:40-07:00",
"periodEndTime": "2025-08-02T19:15:29-07:00",
"periodStartTime": "2025-07-26T19:15:29-07:00",
"phaseNo": "1",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success",
"resultStatus": "S"
},
"subscriptionId": "202510091900000000000000E0000032897",
"subscriptionRequestId": "PAYMENT_20251009101050687_AUTO"
}关键参数说明:
- notifyType:通知类型,值为 PAYMENT_RESULT。
- phaseNo:订阅当期的期数。
- periodStartTime:本期订阅开始时间。
- periodEndTime:本期订阅结束时间。
- paymentAmount:每期周期扣款的金额。
常见问题
问:若扣款失败会导致订阅关系失效吗?
答:创建订阅的首期扣款如果失败,订阅关系将不会生效;若订阅关系已生效但后续的周期扣款失败(如余额不足),订阅状态仍保持有效;若未主动取消订阅,Antom 将会在下一期继续周期扣款。
问:扣款失败会发送当期扣款通知吗,会重试吗?
答:扣款失败会发送扣款失败通知。卡支付、Apple Pay 和 Google Pay 的订阅支付场景下,Antom 不会发起重试;APM 的订阅支付场景下,Antom 会发起多次重试。商户侧如需自行发起重试,可联系技术支持确定方案。
问:假如首期扣款是 2 月 28 日、3 月 31 日或 4 月 30 日这些月末时间点,那下一期的扣费时间怎么定义?
答:订阅的周期逻辑为按选定的日期来发起下一次扣款,如果下一个周期没有这个日期,则往前推到最后一天,例如:
- 首期 1.28,二期 2.28,三期 3.28,四期 4.28。
- 首期 1.31,二期 2.28,三期 3.31,四期 4.30。
- 首期 1.30,二期 2.28,三期 3.30,四期 4.30。
问:后续的周期扣款如何跟首期合约关联?
答:针对周期扣款通知,可以根据通知请求中的 subscriptionRequestId 或 subscriptionId 与首期合约关联。针对卡支付、Apple Pay 和 Google Pay 的周期扣款,Antom 还会额外发送授权结果通知和请款结果通知,这两个通知可以根据 paymentId 关联到周期扣款通知中的 paymentId 并最终关联上首期合约的 subscriptionId。
订阅后操作
完成订阅后,您可以进行以下操作:
查询订阅相关信息 服务端
订阅确认后,您可以查询以下订阅信息:
- 查询订阅列表:您可以通过 inquireSubscriptionList 接口查询符合特定筛选条件的订阅列表。
- 查询订阅详情:您可以使用 subscriptionId 调用 inquireSubscription 接口来获取订阅详情。
- 查询订阅交易信息:您可以使用 subscriptionId 调用 inquireSubscriptionPayment 接口来获取订阅交易的列表信息。
订阅试用 服务端
终止订阅 服务端
取消交易 服务端
退款 服务端
对于已支付成功的订单,如您需向买家发起退款,Antom 提供以下两种方式:
- 由您的运营人员直接在 Antom Dashboard 平台上进行人工退款。
- 通过调用 refund 接口发起退款。
Antom 的退款能力如下:
- 支持全额退款。
- 支持部分多次退款,多次退款的总金额需小于等于请款金额。
争议 服务端
对账 服务端
支付方式特性
本节内容为您阐述各类支付方式在支持特性方面的差异。
默认关单时间
注意:由于 Payment Element 订单默认有效期为 1 小时,实际关单时间需在支付方式原有默认时间基础上增加 1 小时。例如,若某支付方式默认关单时间为 14 分钟,则 Payment Element 订单的实际关单时间将为 1 小时 14 分钟。
集成要点
卡支付特性
Payment Element 支持以下卡支付特性,点击了解不同特性的具体信息及使用方法:
更多内容
Antom 还为您提供以下定制化内容:
- 自定义外观样式:Antom 提供了丰富的样式自定义能力,包含主题、布局以及 CSS 样式自定义功能。
- Google Pay:通过 Google Pay 服务,买家可以使用存储在其 Google 账户中的信用卡或借记卡来进行支付。使用 Payment Element,您无需另外集成 Google Pay 的 SDK,Payment Element 会为您加载 Google Pay,并可指定 Google Pay 为极速支付形式。
- Apple Pay:通过 Apple Pay 服务,买家可以使用存储在其 Apple Pay 账户中的信用卡或借记卡来进行支付。使用 Payment Element,您无需另外集成 Apple Pay 的 SDK,Payment Element 会为您加载 Apple Pay,并可指定 Apple Pay 为极速支付形式。
指定支付方式
您可以通过在 createPaymentSession(单笔支付)接口传入参数,指定在 Payment Element 上展示的支付方式、支付方式列表的排序,以及极速支付方式的展示。此功能为您带来以下优势:
- 根据您的业务地区过滤当地的支付方式
- 按照您的偏好对支付方式进行排序
- 可以将主流的支付方式如 Alipay、Apple Pay、Google Pay 以极速支付的形式展示(仅支持 App 端)
需要嵌入的支付方式
以下支付方式需要您嵌入支付要素采集组件: