托管卡订阅支付
订阅支付是一种周期性自动扣款解决方案,可以帮助您完成周期性自动收款。仅需一次授权即可绑定支付账户享受持续的订阅服务,且支持动态调整订阅配置(如修改周期/金额、取消续订或终止服务等)。整个流程既便捷高效,又安全可靠。
本文为您介绍如何通过托管模式集成银行卡支付方式。通过托管模式集成银行卡支付,您可以将支付信息采集环节交由 Antom 处理。由于敏感的持卡人数据不经过您的服务器,此模式可帮助您免除 PCI-DSS 的合规负担,无需您自行构建符合 PCI-DSS 标准的支付环境,您也无需获取 PCI 合规资质。
订阅支付体验
以下为首次授权和后续扣款的用户体验:
注意:订阅支付需要绑定卡资产时,首笔交易需要买家发起并通过 3DS 验证流程以完成身份核验。
PC 端:
Mobile 端:
订阅生命周期
以下图片分别展示了整个订阅周期、订阅创建以及周期扣款的流程:
下图展示了整个订阅生命周期,包括创建订阅、签约绑定支付方式、完成首次扣款,以及在必要时发起退款等环节,旨在保障订阅的正常生效与费用处理的安全透明:
集成准备
在您开始集成前,请阅读集成指南及接口概述文档,了解服务端接口的集成步骤及调用接口的注意事项,并确保已完成以下预配置:
- 已获得 client ID。
- 已完成密钥配置。
- 已完成异步通知接收地址的配置。
- 集成服务端 SDK 资源包,并完成接口库安装及请求示例初始化。具体操作请参阅服务端 SDK。
集成步骤
开始集成,请按照以下步骤操作:
- 添加支付方式列表
- 创建订阅支付请求
- 跳转至 Antom 卡信息收集页面(normalUrl)
- 授权结果通知
- 请款并获取请款通知
- 获取订阅通知
步骤 1:添加支付方式列表
在买家下单页面的支付方式列表中,展示本次需要集成的卡品牌标识和名称,供买家根据自身需求和偏好选择。
注意:支付方式列表页面需要由您自行实现。
步骤 2:创建订阅支付请求
您可跳转到 Antom 卡信息收集页面来收集买家的支付信息(如卡号、有效期等)、订阅信息(如扣款金额,周期)、订单详情,设备及支付金额等信息,并调用 pay(单笔支付)接口来创建授权订阅支付请求:
创建授权订阅支付请求包含以下关键参数:
类型 | 参数 | 是否必传 | 描述 |
基础字段 | paymentRequestId | 是 | 授权支付请求单号,每次都需要唯一。 |
paymentAmount.currency | 是 | 支付币种。 | |
paymentAmount.value | 是 | 支付金额。按币种的最小单位设置,除 JPY、KRW 为元,其他均为分。 | |
settlementStrategy.settlementCurrency | 是 | 结算币种。 | |
paymentMethod.paymentMethodType | 是 | 支付方式枚举值,卡支付场景下的值为 | |
paymentFactor.isAuthorization | 是 | 表示支付场景是否为授权场景。卡支付场景下固定传 | |
paymentFactor.captureMode | 否 | 请款模式。默认由 Antom 替商户完成请款。如对首笔创建订阅交易需要设置为由您自行发起请款,可将该字段设置为 | |
productCode | 是 | 产品码,在此场景中,此字段固定传 | |
paymentRedirectUrl | 是 | 商户端支付结果页。需传入 HTTPS 地址,您根据支付结果进行动态渲染。 | |
paymentNotifyUrl | 否 | 授权支付结果通知地址,需传入 HTTPS 地址。此字段可通过接口传递,也可通过 Antom Dashboard 设置为固定值。若两者都设置,则接口传递的值优先。 | |
设备字段 | env.terminalType | 是 | 指定买家发起交易的端类型:
|
env.clientIp | 是 | 买家的 IP 地址。 | |
订单字段 | order.orderAmount | 是 | 订单金额。 |
order.referenceOrderId | 是 | 商户端订单号。 | |
order.orderDescription | 是 | 商户端订单描述。 | |
order.buyer | 是 | 商户端买家信息。至少需要提供以下三者其中一个信息:
| |
订阅字段 | subscriptionInfo.subscriptionDescription | 是 | 订阅描述。 |
subscriptionInfo.subscriptionStartTime | 是 | 订阅关系生效时间,格式类似 2019-11-27T12:01:01+08:00,+08:00 代表东八区 | |
subscriptionInfo.subscriptionNotifyUrl | 是 | 订阅关系通知接收地址,需传入 HTTPS 地址。 | |
subscriptionInfo.trials | 否 | 订阅的试用信息列表。若您提供的订阅服务包含试用或折扣优惠,可通过此参数指定。 | |
subscriptionInfo.periodRule | 是 | 订阅周期,支持 | |
卡支付信息参数 | paymentMethod.paymentMethodMetaData. is3DSAuthentication | 是 | 您需要根据当前交易的风险和拒付情况,决定交易是否进行 3DS 认证。有效值为:
|
以上参数是创建订阅支付请求的基本参数,完整参数和特定支付方式的额外要求请参考 pay(单笔支付)。
以下示例代码展示了如何调用 pay(单笔支付)接口:
public static void pay() {
AlipayPayRequest alipayPayRequest = new AlipayPayRequest();
// 设置订阅信息
SubscriptionInfo subscriptionInfo = new SubscriptionInfo();
subscriptionInfo.setSubscriptionDescription("TEST_SUBSCRIPTION");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
subscriptionInfo.setSubscriptionStartTime(ZonedDateTime.now().format(formatter));
subscriptionInfo.setSubscriptionEndTime(ZonedDateTime.now().plusYears(1).format(formatter));
subscriptionInfo.setSubscriptionNotifyUrl("https://your.example.com/subscriptionNotify");
// 设置订阅周期规则
PeriodRule periodRule = new PeriodRule();
periodRule.setPeriodType("YEAR");
periodRule.setPeriodCount(1);
subscriptionInfo.setPeriodRule(periodRule);
alipayPayRequest.setSubscriptionInfo(subscriptionInfo);
// 设置订单信息
String rng = UUID.randomUUID().toString();
Amount amount = Amount.builder().currency("SGD").value("5200").build();
Order order = new Order();
order.setOrderAmount(amount);
order.setOrderDescription("TEST_ORDER_" + rng);
order.setReferenceOrderId("ORDER_" + rng);
Buyer buyer = new Buyer();
// 设置订单描述
order.setOrderDescription("Sample subscription order");
// 替换为您的 orderId
order.setReferenceOrderId("ORDER_" + rng);
// 设置买家信息
buyer.setBuyerEmail("buyer@example.com");
buyer.setBuyerPhoneNo("123456789");
buyer.setReferenceBuyerId("BUYER_" + rng);
order.setBuyer(buyer);
alipayPayRequest.setOrder(order);
// 设置环境信息
Env env = new Env();
env.setTerminalType(TerminalType.WEB);
env.setClientIp("112.80.248.78");
alipayPayRequest.setEnv(env);
alipayPayRequest.setPaymentAmount(amount);
// 设置支付方式
PaymentMethod paymentMethod = new PaymentMethod();
paymentMethod.setPaymentMethodType("CARD");
// 设置支付方式扩展信息
Map<String, Object> metaData = new HashMap<>();
metaData.put("is3DSAuthentication", "true");
paymentMethod.setPaymentMethodMetaData(metaData);
alipayPayRequest.setPaymentMethod(paymentMethod);
// 设置结算币种
SettlementStrategy settlementStrategy = new SettlementStrategy();
settlementStrategy.setSettlementCurrency("SGD");
alipayPayRequest.setSettlementStrategy(settlementStrategy);
// 设置授权请款模式
PaymentFactor paymentFactor = new PaymentFactor();
paymentFactor.setIsAuthorization(true);
alipayPayRequest.setPaymentFactor(paymentFactor);
// 替换为您的通知地址
alipayPayRequest.setPaymentNotifyUrl("https://www.your-notify.example.com/payments/notify");
// 替换为您的跳转 url
alipayPayRequest.setPaymentRedirectUrl("https://www.your-merchant.example.com/redirect");
// 替换为您的 paymentRequestId
alipayPayRequest.setPaymentRequestId("PAY_XXXXXX" + rng);
// 设置产品码
alipayPayRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
// 设置请求路径
alipayPayRequest.setPath(PAY_PATH);
// 支付
AlipayPayResponse alipayPayResponse = null;
try {
alipayPayResponse = CLIENT.execute(alipayPayRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// 处理错误信息
}
}以下为请求报文示例:
{
"env": {
"clientIp": "112.*.*.*",
"terminalType": "WEB"
},
"order": {
"buyer": {
"buyerEmail": "buy***@example.com",
"buyerPhoneNo": "123456789",
"referenceBuyerId": "BUYER_eeae1497-8f54-4359-977e-3b5e858335af"
},
"orderAmount": {
"currency": "SGD",
"value": "5200"
},
"orderDescription": "Sample subscription order",
"referenceOrderId": "ORDER_eeae1497-8f54-4359-977e-3b5e858335af"
},
"paymentAmount": {
"currency": "SGD",
"value": "5200"
},
"paymentFactor": {
"isAuthorization": true
},
"paymentMethod": {
"paymentMethodMetaData": {
"is3DSAuthentication": "true"
},
"paymentMethodType": "CARD"
},
"paymentNotifyUrl": "https://www.your-notify.example.com/payments/notify",
"paymentRedirectUrl": "https://www.your-merchant.example.com/redirect",
"paymentRequestId": "PAY_XXXXXXeeae1497-8f54-4359-977e-3b5e858335af",
"productCode": "CASHIER_PAYMENT",
"settlementStrategy": {
"settlementCurrency": "SGD"
},
"subscriptionInfo": {
"periodRule": {
"periodCount": 1,
"periodType": "YEAR"
},
"subscriptionDescription": "TEST_SUBSCRIPTION",
"subscriptionEndTime": "2027-03-12T09:59:38+08:00",
"subscriptionNotifyUrl": "http://localhost:8443/payment/receiveSubscriptionNotify",
"subscriptionStartTime": "2026-03-12T09:59:38+08:00"
}
}以下代码展示了一个响应的示例,其中包含以下关键参数:
- result.resultStatus:判断授权状态。
- normalUrl:为 Antom 的卡信息收集页面。
{
"normalUrl": "https://sandbox.example.com/checkout/page?sessionData=SESSION_SAMPLE_ABC123",
"paymentActionForm": "{\"method\":\"GET\",\"paymentActionFormType\":\"RedirectActionForm\",\"redirectUrl\":\"https://sandbox.example.com/checkout/page?sessionData=SESSION_SAMPLE_ABC123\"}",
"paymentAmount": {
"currency": "SGD",
"value": "5200"
},
"paymentCreateTime": "2026-03-11T18:59:40-07:00",
"paymentId": "202603121940109000001888F0284122695",
"paymentRequestId": "PAY_XXXXXXeeae1497-8f54-4359-977e-3b5e858335af",
"paymentResultInfo": {},
"redirectActionForm": {
"method": "GET",
"redirectUrl": "https://sandbox.example.com/checkout/page?sessionData=SESSION_SAMPLE_ABC123"
},
"result": {
"resultCode": "PAYMENT_IN_PROCESS",
"resultMessage": "payment in process",
"resultStatus": "U"
}
}下表展示了响应代码中 result.resultStatus 字段可能返回的值,请您根据指引进行处理:
result.resultStatus | 信息 | 后续操作 |
| 授权支付失败。 | 关闭当前交易或重新更换 paymentRequestId 再次下单。 |
| 授权支付进行中。 |
|
注意:如果您未收到响应报文,可能是网络超时所致。您可关闭当前交易或更换 paymentRequestId 重新下单。
常见问题
问:首笔交易是否一定要强制 3D 验证?
答:首笔交易是买家参与的交易,需要进行身份验证,用于保障后续买家不在场的周期性扣费的安全。因此对于首笔交易的身份验证有如下要求:
- 通过 Antom 完成 3D 验证:买家选择卡支付,设置 paymentMethodType 为
CARD,均需要完成 3DS 交易,以完成买家身份验证。可以在 pay(单笔支付)接口请求中设置参数 is3DSAuthentication 的值为true,通过 Antom 3DS 实现。
步骤 3:跳转至 Antom 卡信息收集页面(normalUrl)
商户服务端拿到 Antom 返回的卡信息收集页面地址(normalUrl )后,将该地址传递给前端,由商户前端跳转至 Antom 卡信息收集页面。
以下为商户前端加载 normalUrl 的示例代码:
if (serverResponse.normalUrl != null) {
window.open(serverResponse.normalUrl, '_blank');
}以下图片展示了 Web 和 App 端重定向至卡信息采集页面(normalUrl)的用户体验:
常见问题
问:如何处理不同的支付体验?
答:通过 API 集成接入卡支付返回的 normalUrl 均为 H5 链接,对于 WEB 和 WAP 直接跳转即可,对于 APP 建议您通过 WebView 形式加载 normalUrl,提升用户体验。
问:paymentRedirectUrl 在传参上有些什么注意点?
答:默认设置为 HTTPS 地址,同时 URL 中的特殊字符能进行编码处理,否则会支付异常。
问:支付结果页内容如何展示?
答:您需要通过在 pay(单笔支付)接口中指定 paymentRedirectUrl 字段来提供一个 HTTPS 地址。该地址用于在商户端显示支付结果。在支付成功和支付失败的情况下,可能都有入口可以从支付方式端回跳到商户页面。因此,请勿将 paymentRedirectUrl 固定写成“订阅创建成功页面”,而是以服务端返回的结果为准,避免引起买家误解。
问:回跳商户结果页是否代表订阅创建成功?
答:不能仅凭回跳商户页面来判断订阅创建是否成功,具体有以下三种情况:
- 买家支付成功后,可能因网络等原因导致未能回跳至商户页。
- 即使买家未完成支付,也可能通过支付方式端的入口回跳至商户页面。
- 即使买家完成支付,也可能因为请款失败而导致订阅关系没有生效。
步骤 4:授权结果通知
无论授权成功或失败,Antom 都会使用 notifyPayment(订阅)接口将支付结果发送给您。请按以下步骤获取授权支付结果通知:
- 设置接收通知的 webhook URL:在 pay(单笔支付)接口请求的 paymentNotifyUrl 参数设置和 Antom Dashboard 配置。
以下为异步通知请求体的代码示例:
{
"notifyType": "PAYMENT_RESULT",
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
},
"paymentRequestId": "2020010123456789XXXX",
"paymentId": "2020010123456789XXXX",
"paymentAmount": {
"value": "8000",
"currency": "EUR"
},
"paymentCreateTime": "2020-01-01T12:01:00+08:30",
"paymentTime": "2020-01-01T12:01:01+08:30"
}- 异步通知验签。
当您收到 Antom 的异步通知,您需要按照返回收到确认信息的格式返回响应,但无需做加签处理。
您需要按照以下方法对 Antom 发送的通知进行验签:
/**
* 接收支付通知
*
* @param request request
* @param notifyBody notify body
* @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("Invalid notify signature");
}
// 反序列化通知报文体
AlipaySubscriptionPayNotify paymentNotify = JSON.parseObject(notifyBody, AlipaySubscriptionPayNotify.class);
if (paymentNotify != null && "SUCCESS".equals(paymentNotify.getResult().getResultCode())) {
// 处理你的业务逻辑
// 例如:通过 subscriptionRequestId 与用户 ID 的关系保存用户的支付信息。
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();
}- 响应通知结果。无论订单是否支付成功,每个通知请求均需按以下固定格式响应。否则,Antom 会重新发送异步通知。
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}步骤 5:请款并获取请款通知
注意:只有授权支付成功才会触发请款。
授权支付成功后,Antom 默认自动为您请款,也支持您手动发起请款。同时,Antom 会使用 notifyCapture(单笔支付)将请款结果通知发送给您,您也可以通过主动查询来获取请款结果。您需要根据请款结果来决定是否发货,具体操作请参阅请款。
步骤 6:获取订阅通知
订阅关系生效后,Antom 会为您发送以下通知:
首期订阅通知
Antom 将通过 HTTPS 向您在接口或 Antom Dashboard 中配置的 Webhook 推送以下事件通知:
通知类型 | 接口 | 请求报文信息 |
订阅状态通知 | 订阅关系生效后,Antom 会使用 notifySubscription 接口将订阅结果通知发送给您。 |
|
当期扣款结果通知 | 在订阅支付成功开通或续期成功后,Antom 会使用 notifyPayment(订阅)接口将本期订阅扣款结果发送给您。 | 请求报文 notifyType 的值为 |
请按以下步骤获取订阅状态通知:
- 设置接收通知的 webhook URL:通过 pay(单笔支付)接口的 subscriptionInfo.subscriptionNotifyUrl 参数设置。以下是两种订阅状态的通知示例:
- 当 subscriptionNotificationType 的值为
CREATE时,请根据 subscriptionStatus 的值判断订阅关系:
ACTIVE:表示订阅关系生效。TERMINATED:表示订阅关系失效。
{
"periodRule": {
"periodCount": 1,
"periodType": "MONTH"
},
"subscriptionEndTime": "2074-02-20T01:16:17-08:00",
"subscriptionId": "2024091******000000050000010226",
"subscriptionNotificationType": "CREATE",
"subscriptionRequestId": "SUBSCRIPTION_20244******165oo009851_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 的异步通知,您需要按照返回收到确认信息的格式返回响应,但无需做加签处理。
您需要按照以下方法对 Antom 发送的通知进行验签:
/**
* receive subscription notify
*
* @param request request
* @param notifyBody notify body
* @return Result
*/
@PostMapping("/receiveSubscriptionNotify")
@ResponseBody
public Result receiveSubscriptionNotify(HttpServletRequest request, @RequestBody String notifyBody) {
// retrieve the required parameters from http request
String requestUri = request.getRequestURI();
String requestMethod = request.getMethod();
// retrieve the required parameters from request header
String requestTime = request.getHeader("request-time");
String clientId = request.getHeader("client-id");
String signature = request.getHeader("signature");
try {
// verify the signature of notification
boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId,
requestTime, signature, notifyBody, ANTOM_PUBLIC_KEY);
if (!verifyResult) {
throw new RuntimeException("Invalid notify signature");
}
// deserialize the notification body
AlipaySubscriptionNotify subscriptionNotify = JSON.parseObject(notifyBody, AlipaySubscriptionNotify.class);
if (subscriptionNotify != null && SubscriptionNotificationType.CREATE.equals(subscriptionNotify.getSubscriptionNotificationType())) {
// handle your own business logic.
// e.g. The subscription information of the user is saved through the relationship between the subscriptionRequestId and the user 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"
}
}常见问题
问: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的状态通知给您,表明订阅开通失败。
问:订阅超时时间是多久?
答:针对卡支付类支付方式,默认为 7 天超时时间,您也可以通过 subscriptionExpiryTime 字段来指定超时时间。
问:订阅当期扣款结果通知和授权支付通知、请款通知有什么区别?
答:授权支付阶段通知中包含 3DS 等相关的信息;请款通知则体现最终的支付结果,建议以此通知作为发货依据;订阅当期支付结果通知中包含了订阅周期信息,包含当期的开始,结束时间及期数等。
问:订阅的首次绑定支付支持商户自行发起请款吗?
答:支持,需要在 pay(单笔支付)接口中将字段 paymentFactor.captureMode 的值设置为
MANUAL,然后在收到授权支付成功的异步通知后,自行发起 capture(单笔支付)调用。在此场景下,需保障请款成功才算首次绑定支付成功,Antom 才会生成后续的周期扣款计划。
订阅续期通知
当订阅创建成功并建立有效关系后,Antom 系统将会根据您配置的订阅规则,自动发起续订扣款,并通过 Webhook 推送相应的支付结果通知,实现周期性扣费。触发续订扣款的时间和规则如下:
- 触发时间:续订扣款将在下一个订阅周期起始日的前 24 小时自动触发。您可以依据上一周期支付结果通知中的 periodEndTime 字段,向前推 24 小时以判断下一周期扣款的发起时间。
- 周期规则:续费周期及扣款频率将按照订阅时设定的 periodRule 执行,例如按日、按月、按季度或按年扣款。
首期扣款时间 首期 (paymentTime = periodStartTime) | 订阅周期 | 下期扣款时间 (paymentTime) | 下期生效时间 (periodStartTime) |
2024-09-25T20:10:17+08:00 | 设置订阅周期为 3 天,需要传入以下参数:
| 2024-09-27T20:20:04+08:00 | 2024-09-28T20:10:17+08:00 |
2024-09-25T20:10:17+08:00 | 设置订阅周期为 1 周,需要传入以下参数:
| 2024-10-01T20:10:17+08:00 | 2024-10-02T20:10:17+08:00 |
2024-09-25T20:10:17+08:00 | 设置订阅周期为 1 个月,需要传入以下参数:
| 2024-10-24T20:10:17+08:00 | 2024-10-25T20:10:17+08:00 |
2024-09-25T20:10:17+08:00 | 设置订阅周期为 1 年,需要传入以下参数:
| 2025-09-24T20:10:17+08:00 | 2025-09-25T20:10:17+08:00 |
异步通知通常分为以下场景:
常见场景 | 首次绑定支付 | 后续周期扣款 |
授权支付结果通知 | 有通知,告知授权结果和 3DS 认证结果。 | 有通知,告知授权结果和 3DS 认证结果。 |
请款通知 | 授权成功则有通知,请款结果为发货依据。 | 授权成功则有通知,请款结果为发货依据。 |
订阅状态通知 | 有通知,告知订阅创建结果。 | 无通知。 |
当期扣费结果通知 | 有通知,告知本期扣费状态、金额和有效期。 | 有通知,告知每期扣费状态、金额和有效期 |
以下为各场景异步通知的示例代码:
{
"notifyType": "PAYMENT_RESULT",
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
},
"paymentRequestId": "2020010123456789XXXX",
"paymentId": "2020010123456789XXXX",
"paymentAmount": {
"value": "8000",
"currency": "EUR"
},
"paymentCreateTime": "2020-01-01T12:01:00+08:30",
"paymentTime": "2020-01-01T12:01:01+08:30"
}常见问题
问:若扣款失败会导致订阅关系失效吗?
答:创建订阅的首期扣款如果失败,订阅关系将不会生效;若订阅关系已生效但后续的周期扣款失败(如余额不足),订阅状态仍保持有效;若未主动取消订阅,Antom 将会在下一期继续周期扣款。
问:扣款失败会发送当期扣款通知吗,会重试吗?
答:扣款失败会发送扣款失败通知;卡支付的订阅支付场景下,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 与首期合约关联。针对卡支付的周期扣款, Antom 还会额外发送授权结果通知和请款结果通知,这两个通知可以根据 paymentId 关联到周期扣款通知中的 paymentId 并最终关联上首期合约的 subscriptionId。
问:针对卡支付,如果首次创建订阅关系时选择由商户自行请款,即字段 paymentFactor.captureMode 的值为
MANUAL,那后续的自动续费会如何处理?答:后续自动续费均由 Antom 发起,无需商户侧参与发起请款,即均默认 paymentFactor.captureMode 的值为
AUTOMATIC。
订阅后操作
完成订阅后,您可对交易进行以下操作:
订阅试用
Antom 提供订阅试用功能,帮助买家在正式购买订阅计划前,以免费或优惠价格在限定时间内体验产品或服务。详情请参阅订阅试用文档。
终止订阅
终止订阅功能允许买家在不需要继续使用相关服务时,随时取消当前订阅。详情请参阅终止订阅文档。
取消交易
对于支付成功后的订单,如买家在当天内申请取消订单或退款,您可以通过 Antom 提供的取消交易能力将订单状态取消或解冻。此外,对于尚未完成支付的订单,您也可以直接进行取消,具体的集成方案见取消交易文档。
退款
对于已支付成功的订单,如您需向买家发起退款,Antom 提供以下两种方式。
- 由您的运营人员直接在 Antom Dashboard 平台上进行人工退款。
- 通过 API 方式接入 refund 接口发起退款。
Antom 的退款能力如下:
- 支持全额退款。
- 支持部分多次退款,多次退款的总金额需小于等于请款金额。
具体的集成方案见退款文档。
更多内容
测试卡
使用测试银行卡确保您的集成已准备好投入生产。想要了解更多关于下载测试钱包的信息,请参阅测试资源。
最佳实践
为了提高集成效率,Antom 为您提供以下最佳实践方案: