APM 订阅支付

订阅支付是一种周期性自动扣款解决方案,可以帮助您完成周期性自动收款。仅需一次授权即可绑定支付账户享受持续的订阅服务,且支持动态调整订阅配置(如修改周期/金额、取消续订或终止服务等)。整个流程既便捷高效,又安全可靠。
本文主要针对 APM 类支付方式通过 API 方式集成进行阐述。不同支付方式的集成策略各异,其优缺点直接影响开发成本与用户体验。要做出最适合您业务的技术决策,请参阅场景适配指引以深入了解各集成方案的特性与适用场景。

用户体验

首次绑定
后续扣款

交互流程

以下为订阅周期、订阅创建以及接收扣款通知的流程示意。
订阅周期
订阅创建
接收扣款通知

集成准备

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

集成步骤

开始集成,请按照以下步骤操作:
  1. 添加支付方式列表
  2. 创建订阅
  3. 跳转授权绑定链接
  4. 接收订阅结果异步通知
  5. 接收订阅续期异步通知

步骤 1:添加支付方式列表
客户端

订阅场景下,买家进入支付方式选择页,需展示本次需要集成的支付方式标识和名称,供买家根据自身需求和偏好选择。请联系 Antom 技术支持以获取各支付方式的标识和名称。
注意:支付方式列表页面需要由您自行实现。

步骤 2:创建订阅
服务端

调用 create 接口,您需要采集买家的支付方式、订阅周期、每期金额、订单信息等提交订阅创建请求。
创建订阅包含以下关键参数:
以下代码为调用 create 接口发起请求的代码示例:
public static void createSubscription() {
  AlipaySubscriptionCreateRequest alipaySubscriptionCreateRequest = new AlipaySubscriptionCreateRequest();

  // 替换为你自己的 subscriptionRequestId。
  // 你可以保存 subscriptionRequestId 与买家 ID 的对应关系,方便后续信息查询。
  String subscriptionRequestId = UUID.randomUUID().toString();
  alipaySubscriptionCreateRequest.setSubscriptionRequestId(subscriptionRequestId);
  alipaySubscriptionCreateRequest.setSubscriptionDescription("Subscription Description");

  // 设置订阅的开始时间和结束时间,你可能需要考虑时区因素。
  // 如果开始时间早于授权时间,则订阅立即生效。
  // 如果开始时间晚于授权时间,则在授权成功后进行支付,这种情况属于预售。
  // 详情请参考:<a href="https://docs.antom.com/ac/subscriptionpay/activation#uiqBb">示例</a>
  DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
  alipaySubscriptionCreateRequest.setSubscriptionStartTime(ZonedDateTime.now().format(formatter));
  alipaySubscriptionCreateRequest.setSubscriptionEndTime(ZonedDateTime.now().plusYears(3).format(formatter));

  // 设置周期规则(periodRule)
  PeriodRule periodRule = PeriodRule.builder().periodCount(1).periodType("MONTH").build();
  alipaySubscriptionCreateRequest.setPeriodRule(periodRule);

  // 设置支付方式(paymentMethod)
  PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType("ALIPAY_HK").build();
  alipaySubscriptionCreateRequest.setPaymentMethod(paymentMethod);

  // 转换金额单位(实际情况中应在你的服务器端计算金额)。
  // 详情请参考:<a href="https://docs.antom.com/ac/ref/cc">Amount 对象的使用规则</a>
  Amount amount = Amount.builder().currency("HKD").value("1688").build();

  // 设置支付金额
  alipaySubscriptionCreateRequest.setPaymentAmount(amount);

  // 设置订单信息
  OrderInfo orderInfo = OrderInfo.builder().orderAmount(amount).build();
  alipaySubscriptionCreateRequest.setOrderInfo(orderInfo);

  // 设置结算策略
  // 替换为你实际使用的结算币种
  SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
  alipaySubscriptionCreateRequest.setSettlementStrategy(settlementStrategy);

  // 设置环境信息(env info)
  Env env = Env.builder().terminalType(TerminalType.APP).build();
  env.setOsType(OsType.ANDROID);

  alipaySubscriptionCreateRequest.setEnv(env);

  // 替换为你自己的通知回调地址。
  // 你也可以在此处或控制台配置通知 URL:<a href="https://dashboard.antom.com/global-payments/developers/iNotify">通知 URL</a>
  alipaySubscriptionCreateRequest.setPaymentNotificationUrl("http://www.yourNotifyUrl.com/subscriptions/receivePaymentNotify");
  alipaySubscriptionCreateRequest.setSubscriptionNotificationUrl("http://www.yourNotifyUrl.com/subscriptions/receiveSubscriptionNotify");

  // 替换为你自己的重定向地址(redirect url)
  alipaySubscriptionCreateRequest.setSubscriptionRedirectUrl("http://www.yourRedirectUrl.com?subscriptionRequestId=" + subscriptionRequestId);

  AlipaySubscriptionCreateResponse alipaySubscriptionCreateResponse;
      try {
          alipaySubscriptionCreateResponse = CLIENT.execute(alipaySubscriptionCreateRequest);
      } catch (AlipayApiException e) {
          String errorMsg = e.getMessage();
          // 处理错误情况
      }
  }
以下为请求报文示例:
{
"env": {
  "osType": "ANDROID",
  "terminalType": "APP"
},
"orderInfo": {
  "orderAmount": {
    "currency": "HKD",
    "value": "1688"
  }
},
"paymentAmount": {
  "currency": "HKD",
  "value": "1688"
},
"paymentMethod": {
  "paymentMethodType": "ALIPAY_HK"
},
"paymentNotificationUrl": "http://www.yourNotifyUrl.com/subscriptions/receivePaymentNotify",
"periodRule": {
  "periodCount": 1,
  "periodType": "MONTH"
},
"settlementStrategy": {
  "settlementCurrency": "USD"
},
"subscriptionDescription": "Subscription Description",
"subscriptionEndTime": "2029-03-11T17:48:07+08:00",
"subscriptionNotificationUrl": "http://www.yourNotifyUrl.com/subscriptions/receiveSubscriptionNotify",
"subscriptionRedirectUrl": "http://www.yourRedirectUrl.com?subscriptionRequestId=5e5932ac-ed92-461a-9e3f-e1b4ac08fb0e",
"subscriptionRequestId": "5e5932ac-ed92-461a-9e3f-e1b4ac08fb0e",
"subscriptionStartTime": "2026-03-11T17:48:07+08:00"
}
响应代码中涉及以下关键参数:
以下为响应报文示例:
{
  "appIdentifier": "com.iap.linker_portal",
  "applinkUrl": "https://psp.ac.alipay.com/page/simulation-wallet/acwallet/signContract.html?scopes=AGREEMENT_PAY%2CUSER_LOGIN_ID&bizContent=%7B%22acquirerId%22%3A%22102218800000000000A%22%2C%22authClientDisplayName%22%3A%222188120314639523%40alitest.com%22%2C%22authClientId%22%3A%2221881200300645I9%22%2C%22authClientName%22%3A%222188120314639523%40alitest.com%22%2C%22authRedirectUrl%22%3A%22https%3A%2F%2Fg.alipayplus.com%2Fpage%2Fac-auth-payment%2Fresult%2Fmobile%2Findex.html%3FloadMode%3D2%26callbackType%3DCommon%26terminalType%3DAPP%26referenceAgreementId%3D2026031119214000100500031242021%26authRequestId%3D2026031119091305000370002050791%26pspId%3D102216000000000000A%26clientId%3DT_4GGO000000000001%22%2C%22authState%22%3A%22188bmljL2ZDWEZ4MnowK3dYVVdQVElPS0lpSFQ0b21xRkdSVWxkTStlaXAzOEh1VEVpaFRJS3M3Y290T0Zma0h6Ng%22%2C%22customerBelongsTo%22%3A%22ALIPAY_HK%22%2C%22osType%22%3A%22ANDROID%22%2C%22passThroughInfo%22%3A%22%7B%5C%22referenceMerchantId%5C%22%3A%5C%2221881200300645I9%5C%22%7D%22%2C%22pspId%22%3A%22102216000000000000A%22%2C%22referenceAgreementId%22%3A%222026031119214000100500031242021%22%2C%22referenceMerchantId%22%3A%2221881200300645I9%22%2C%22scopes%22%3A%5B%22AGREEMENT_PAY%22%2C%22USER_LOGIN_ID%22%5D%2C%22terminalType%22%3A%22APP%22%7D&source=AlipayConnect&needCallback=false",
  "normalUrl": "https://g.alipayplus.com/page/aplus-linker/acwallet/authorization.html?url=alipayconnect%3A%2F%2Fplatformapi%2Facwallet%2FsignContract&scopes=AGREEMENT_PAY%2CUSER_LOGIN_ID&bizContent=%7B%22acquirerId%22%3A%22102218800000000000A%22%2C%22authClientDisplayName%22%3A%222188120314639523%40alitest.com%22%2C%22authClientId%22%3A%2221881200300645I9%22%2C%22authClientName%22%3A%222188120314639523%40alitest.com%22%2C%22authRedirectUrl%22%3A%22https%3A%2F%2Fg.alipayplus.com%2Fpage%2Fac-auth-payment%2Fresult%2Fmobile%2Findex.html%3FloadMode%3D2%26callbackType%3DCommon%26terminalType%3DAPP%26referenceAgreementId%3D2026031119214000100500031242021%26authRequestId%3D2026031119091305000370002050791%26pspId%3D102216000000000000A%26clientId%3DT_4GGO000000000001%22%2C%22authState%22%3A%22188bmljL2ZDWEZ4MnowK3dYVVdQVElPS0lpSFQ0b21xRkdSVWxkTStlaXAzOEh1VEVpaFRJS3M3Y290T0Zma0h6Ng%22%2C%22customerBelongsTo%22%3A%22ALIPAY_HK%22%2C%22osType%22%3A%22ANDROID%22%2C%22passThroughInfo%22%3A%22%7B%5C%22referenceMerchantId%5C%22%3A%5C%2221881200300645I9%5C%22%7D%22%2C%22pspId%22%3A%22102216000000000000A%22%2C%22referenceAgreementId%22%3A%222026031119214000100500031242021%22%2C%22referenceMerchantId%22%3A%2221881200300645I9%22%2C%22scopes%22%3A%5B%22AGREEMENT_PAY%22%2C%22USER_LOGIN_ID%22%5D%2C%22terminalType%22%3A%22APP%22%7D&source=AlipayConnect&needCallback=false",
  "result": {
      "resultCode": "SUCCESS",
      "resultMessage": "success.",
      "resultStatus": "S"
  }
}
下表展示了响应代码中 result.resultStatus 参数可能返回的值,请您根据指引进行处理:
注意:如果您未收到响应报文,可能是网络超时所致,您可以关闭订阅或发起原单重试。
常见问题
问:如何确认响应代码中需要消费的链接类型?
答:不同支付方式在不同端类型下,Antom 可能会返回以下三种链接中的一种或多种:normalUrlapplinkUrl schemeUrl。商户服务端需将这些链接传递给商户前端,可以选择任选一种链接进行跳转消费。

问:如何设置 terminalType
答:terminalType 的有效值为:
  • 如果买家在 PC 端发起交易,需要将 terminalType 指定为
    WEB
  • 如果买家在移动浏览器上发起交易,需要将 terminalType 指定为
    WAP
    。添加 osType 参数,并根据买家的手机填写相应的系统参数
    ANDROID
    IOS
  • 如果买家在应用内发起交易,需要将 terminalType 指定为
    APP

步骤 3:跳转授权绑定链接
客户端

商户服务端拿到 Antom 返回的授权绑定链接后,将该地址传递给前端,由商户前端跳转至支付方式页面。不同类型的推进链接如下表所示:
请参阅支付推进链接了解更多内容。
以下为商户前端加载推进链接的示例代码:
Web
WAP
iOS
Android
下图展示支付方式收银台页面的效果:
不同支付方式在不同终端会返回不同的支付推进链接,Antom 基于您传入的 paymentMethod terminalType 决策返回不同的支付推进链接。下表列举了不同终端返回的支付推进链接类型及其用户体验。关于具体的不同支付方式返回的支付推进链接内容,请参阅支付方式返回链接了解更多详情。
常见问题
问:subscriptionRedirectUrl 在传参上需要注意什么?
答:默认设置为 HTTPS 地址,同时 URL 中的特殊字符不能进行编码处理,否则会支付异常。

问:支付结果页内容如何展示?
答:您需要在 create 接口中指定 subscriptionRedirectUrl 参数来提供一个 HTTPS 地址。该地址用于在商户端显示支付结果。
  • 授权成功和授权失败的情况下,可能都有入口可以从支付方式端回跳到商户页面。因此,请勿将 subscriptionRedirectUrl 固定为授权成功页面,而是以服务端返回的结果为准,避免引起买家误解。
  • 如果商户从应用程序端发起交易,subscriptionRedirectUrl 需设置为商户应用程序的 scheme 地址。

问:回跳商户结果页是否代表订阅关系生效?
答:不能仅凭回跳商户页面来判断授权是否成功,具体有以下三种情况:
  • 买家授权成功后,可能因网络等原因导致未能回跳至商户页。
  • 即使买家未完成授权,也可能通过支付方式端的入口回跳至商户页面。
  • 即使买家完成授权认证,也可能因为首期扣款失败导致订阅关系没有生效。

步骤 4:接收首期订阅异步通知
服务端

Antom 会根据 APM 交易的授权结果和扣费结果的状态来推送异步通知:
订阅状态通知
当期扣款结果通知
  1. 响应通知结果。响应通知时,无论交易支付成功与否,均需按以下固定格式响应,且无需做加签处理。
{
"result": {
  "resultCode": "SUCCESS",
  "resultStatus": "S",
  "resultMessage": "success"
}
}
常见问题
问:异步通知会被重新发送吗?
答:是的,对于以下情况,异步通知会在 24 小时内自动重新发送:
  • 如果由于网络原因未收到异步通知。
  • 如果您收到来自 Antom 的异步通知,但您没有按照处理通知的示例代码格式对通知做出响应。
通知最多可以重发 8 次,或者直到收到正确的响应以终止发送。发送间隔如下:0 分钟、2 分钟、10 分钟、10 分钟、1 小时、2 小时、6 小时和15 小时。

问:在响应异步通知时,我需要加签吗?
答:如果您收到来自 Antom 的异步通知,您需要按照处理通知的示例代码格式返回响应,但不需要对响应进行签名。

问:收到支付结果通知后是否需要验签?
答: 需要。为确保回调请求确实由 Antom 发送,在验签时需要进行验证。在拼装待验签的报文时,必须按照以下标准顺序处理:
<http-method> <http-uri> <client-id>.<request-time>.<request-body>
。请注意拼装
request-body
时应直接取其原始值,而不要解析成 JSON 后再拼装。

问:若首次支付失败,订阅关系会生效吗?
答:当订阅开通的首次扣款失败时,订阅关系将不会生效,Antom 系统会通过 Webhook 推送 subscriptionStatus =
TERMINATED
的状态通知给商户,表明订阅开通失败。

问:订阅超时时间是多久?
答:针对 APM 类支付方式,默认为 80 分钟超时时间,您也可以通过 subscriptionExpiryTime 来指定超时时间。

问:如果订阅创建失败,是否会有首期扣费结果通知?
答:此场景分为两种情况:
  • 如果买家授权成功但是首期扣费失败,则会发送订阅关系创建失败的通知和首期扣费失败通知;
  • 如果买家授权失败,则仅有订阅关系创建失败的通知

步骤 5:接收订阅续期异步通知
服务端

当订阅创建成功并建立有效关系后,Antom 系统将会根据您配置的订阅规则,自动发起续订扣款,并通过 notifyPayment 接口发送相应的支付结果通知,实现周期性扣费。
  • 触发时间:续订扣款将在下一个订阅周期起始日的前 24 小时自动触发。您可以依据上一周期支付结果通知中的 periodEndTime 参数,向前推 24 小时以判断下一周期扣款的发起时间。
  • 周期规则:续费周期及扣款频率将按照订阅时设定的 periodRule 执行,例如按日、按月、按季度或按年扣款。如下表述:
异步通知通常分为以下场景:
订阅当期扣款结果通知示例:
{
"paymentAmount": {
	"currency": "PHP",
	"value": "100"
},
"notifyType": "PAYMENT_RESULT",
"paymentCreateTime": "2024-09-17T23:10:48-07:00",
"paymentId": "20240918194010******88060246428030",
"paymentTime": "2024-09-17T23:10:50-07:00",
"periodEndTime": "2024-10-19T22:15:17-07:00",
"periodStartTime": "2024-09-19T22:15:17-07:00",
"phaseNo": "2",
"result": {
	"resultCode": "SUCCESS",
	"resultMessage": "success",
	"resultStatus": "S"
},
"subscriptionId": "2024091819000000******050000010807",
"subscriptionRequestId": "SUBSCRIPTION_20244jj09yyy5oo0hhh1_AUTO"
}
关键参数说明:
  • notifyType:通知类型,值为
    PAYMENT_RESULT
  • phaseNo:订阅当期的期数。
常见问题
问:若扣款失败会导致订阅关系失效吗?
答:创建订阅的首期扣款如果失败,订阅关系将不会生效;若订阅关系已生效但后续的周期扣款失败(如余额不足),订阅状态仍保持有效;若未主动取消订阅,Antom 将会在下一期继续扣款。

问:扣款失败会发送当期扣款通知吗,会重试吗?
答:扣款失败会发送扣款失败通知;APM 的订阅支付场景下,Antom 会发起多次重试。

问:假如订阅周期为 1 个月,首期扣款是 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 提供订阅试用功能,帮助买家在正式购买订阅计划前,以免费或优惠价格在限定时间内体验产品或服务。详情请参阅订阅试用文档。

终止订阅
服务端

终止订阅功能允许买家在不需要继续使用相关服务时,随时取消当前订阅。详情请参阅终止订阅文档。

取消订单
服务端

对于支付成功后的订单,如买家在当天内申请取消订单或退款,您可以通过 Antom 提供的取消订单能力将订单状态取消或解冻。此外,对于尚未完成支付的订单,您也可以直接进行取消,具体的集成方案见取消交易文档。

退款
服务端

对于已支付成功的订单,如您需向买家发起退款,Antom 提供以下两种方式。
  • 由您的运营人员直接在 Antom Dashboard 平台上进行人工退款。
  • 通过 API 方式接入 refund 接口发起退款。具体的集成方案见退款文档。

更多内容

测试钱包

下载测试钱包应用程序来模拟支付。想要了解更多关于下载测试钱包的信息,请参阅下载测试钱包

最佳实践

为了提高集成效率,Antom 为您提供以下最佳实践方案: