PAYATHON 2026

如何修改 Authorize.Net recurring payment 的下次扣款日期?

支付小周

结论

Authorize.Net 的 Automated Recurring Billing(ARB)订阅一旦创建,就不能直接修改下一次扣款日期。paymentSchedule.startDate 和 paymentSchedule.interval 都不是可更新字段。

如果要把原订阅的后续扣款日改为 2018-06-04,通常需要:

  1. 取消现有的 ARB 订阅;
  2. 创建新订阅;
  3. 将新订阅的 paymentSchedule.startDate 设为目标日期。

处理步骤

1. 确认旧订阅是否已经产生当期交易

取消订阅前,先查询订阅状态和交易记录,确认下一笔扣款是否已经生成,以免:

  • 旧订阅已经扣款,新订阅又在同一周期重复扣款;
  • 取消旧订阅后留下计费空档;
  • 已产生但应退款的交易没有单独处理。

取消 ARB 订阅不会自动撤销或退还已经生成的交易。如需退款,必须通过交易 API 另行处理。

2. 取消旧订阅

ARB 取消请求的核心结构如下:

<?xml version="1.0" encoding="utf-8"?>
<ARBCancelSubscriptionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
    <merchantAuthentication>
        <name>API_LOGIN_ID</name>
        <transactionKey>TRANSACTION_KEY</transactionKey>
    </merchantAuthentication>
    <subscriptionId>OLD_SUBSCRIPTION_ID</subscriptionId>
</ARBCancelSubscriptionRequest>

使用 Authorize.Net-XML 时,可以通过相应的 ARB 客户端发送取消请求。不同版本的库可能使用不同的类名和方法签名,常见写法如下:

<?php

$arb = new AuthorizeNetARB($apiLoginId, $transactionKey);
$response = $arb->cancelSubscription($oldSubscriptionId);

if ($response->isOk()) {
    // 旧订阅已提交取消
} else {
    // 记录错误代码和错误消息
}

具体调用方式应以项目当前安装版本的方法定义为准。发送请求后,还要检查响应,不能仅凭示例认定取消成功。

3. 创建具有新开始日期的订阅

将新订阅的 startDate 设为首次自动扣款的目标日期。例如:

<?xml version="1.0" encoding="utf-8"?>
<ARBCreateSubscriptionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
    <merchantAuthentication>
        <name>API_LOGIN_ID</name>
        <transactionKey>TRANSACTION_KEY</transactionKey>
    </merchantAuthentication>

    <subscription>
        <name>Monthly Plan</name>

        <paymentSchedule>
            <interval>
                <length>1</length>
                <unit>months</unit>
            </interval>
            <startDate>2018-06-04</startDate>
            <totalOccurrences>9999</totalOccurrences>
            <trialOccurrences>0</trialOccurrences>
        </paymentSchedule>

        <amount>29.00</amount>

        <payment>
            <creditCard>
                <cardNumber>CARD_NUMBER</cardNumber>
                <expirationDate>YYYY-MM</expirationDate>
            </creditCard>
        </payment>

        <billTo>
            <firstName>John</firstName>
            <lastName>Smith</lastName>
        </billTo>
    </subscription>
</ARBCreateSubscriptionRequest>

startDate 采用 YYYY-MM-DD 格式。因此,2018-06-04 表示 2018 年 6 月 4 日,不是 2018 年 4 月 6 日。

创建成功后,保存响应中的新 subscriptionId,并在本地业务记录中关联新旧订阅。

为什么不能直接修改

ARB 更新接口主要用于修改订阅金额、付款信息和账单信息等内容。订阅创建后,计费计划中的以下字段通常不能更改:

  • paymentSchedule.startDate
  • paymentSchedule.interval.length
  • paymentSchedule.interval.unit

所以,即使业务需求只是推迟下一次扣款,也不能通过更新接口直接修改现有订阅的下一次执行日期。

注意事项

  • 不要先创建新订阅,再晚些时候取消旧订阅,否则两条订阅可能同时生效。
  • 取消后重新创建并不是原地修改。新订阅会获得新的 subscriptionId。
  • 新订阅的 totalOccurrences 应按剩余周期重新计算。如果业务使用约定值表示长期订阅,该值也要与现有业务逻辑一致。
  • 旧订阅的历史交易仍归属于旧 subscriptionId。报表和对账需要同时保留新旧两条订阅记录。
  • ARB 扣款由 Authorize.Net 的批处理系统执行,不能假定系统会在 startDate 当天的某个准确时刻立即扣款。
  • 即使只想临时延期一次,也需要取消并重建订阅。另一种做法是在自己的系统中管理扣款时间,到期后通过普通交易接口发起付款。
  • 不要在应用数据库或日志中明文保存信用卡数据。重新创建订阅时,应采用符合 PCI 要求的支付数据处理方式。
  • 在生产环境操作前,先在 Sandbox 中验证取消、重建、失败重试和重复提交的处理逻辑。

备注:内容仅供参考。