PAYATHON 2026

Authorize.net API:有无订阅的客户滞纳金处理

技术老齐

结论

可以。Authorize.Net 可以使用 Customer Information Manager(CIM)中保存的 customerProfileId 和 paymentProfileId 发起一次性扣款。家长是否参加 recurring billing subscription,不影响学校收取滞纳金或未结余额。

Authorize.Net 没有专门用于处理“滞纳金”或“余额账户”的 API。滞纳金的计算、账龄、减免和余额分配都要由学校自己的业务系统管理。系统确定应收金额后,再通过 createTransactionRequest 提交普通交易。

推荐的处理方式

订阅扣款和额外费用可以分开处理:

  1. 学校系统记录学费、已付款、滞纳金和未结余额。
  2. 账单到期后,根据业务规则计算应收金额。
  3. 找到对应的 customerProfileId 和 paymentProfileId。
  4. 使用 authCaptureTransaction 发起一次性扣款。
  5. 根据交易响应更新本地账单状态。
  6. 查询后续结算结果,并处理失败、撤销或退款。

已加入订阅的客户可以继续使用同一个 payment profile 支付额外费用。一次性滞纳金通常不适合通过临时修改订阅金额来收取,因为修改可能影响后续账期,还可能导致重复收费。

未加入订阅的客户也按相同方式处理,前提是已经创建 customer profile 和 payment profile。如果客户还没有保存付款方式,需要先通过符合 PCI 要求的页面或令牌化流程收集付款信息,然后创建 payment profile。

发起一次性扣款

以下 XML 示例使用已有的 payment profile 收取 25.00。其中,description 仅用于说明交易内容,Authorize.Net 不会据此计算或管理滞纳金。

<?xml version="1.0" encoding="utf-8"?>
<createTransactionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
  <merchantAuthentication>
    <name>YOUR_API_LOGIN_ID</name>
    <transactionKey>YOUR_TRANSACTION_KEY</transactionKey>
  </merchantAuthentication>

  <refId>late-fee-2026-001</refId>

  <transactionRequest>
    <transactionType>authCaptureTransaction</transactionType>
    <amount>25.00</amount>

    <profile>
      <customerProfileId>123456789</customerProfileId>
      <paymentProfile>
        <paymentProfileId>987654321</paymentProfileId>
      </paymentProfile>
    </profile>

    <order>
      <invoiceNumber>INV-2026-001</invoiceNumber>
      <description>Late fee for overdue tuition</description>
    </order>
  </transactionRequest>
</createTransactionRequest>

Sandbox 请求示例:

curl 'https://apitest.authorize.net/xml/v1/request.api' \
  -H 'Content-Type: application/xml' \
  --data-binary @request.xml

生产环境端点为:

https://api.authorize.net/xml/v1/request.api

API 凭据不能写入前端代码,也不要提交到版本库。

如何取得付款档案

系统已保存相关 ID 时,可以直接使用。尚未保存时,可调用以下接口:

  • getCustomerProfileRequest:获取客户档案及其 payment profiles。
  • getCustomerPaymentProfileRequest:获取指定的 payment profile。
  • getSubscriptionRequest:核对现有订阅信息。

这些接口用于读取档案或订阅信息,不会发起扣款。收费需要通过 createTransactionRequest 完成。

一个客户可能有多个 payment profiles。可以让客户预先指定默认付款方式,也可以由学校系统保存每张账单对应的 paymentProfileId。不能因为某条记录排在接口返回结果的第一位,就直接用它扣款。

未结余额如何处理

假设账单如下:

原学费余额:500.00
滞纳金:25.00
本次应收:525.00

可以提交一笔 525.00 的交易,也可以把学费和滞纳金拆成两笔。Authorize.Net 只处理提交的金额,不会识别这笔款项在学校账务系统中的分配方式。

合并成一笔交易通常更方便对账,也能减少交易手续费以及多次扣款引发的争议。如果学校需要分别撤销、退款,或将款项计入不同的会计科目,可以拆分交易,同时要做好重复提交控制。

客户只支付部分余额时,可以按实际付款金额创建交易,剩余金额继续记录在学校自己的应收账款系统中。

处理交易响应

处理响应时,不能只看 HTTP 状态码。还应检查:

  • 顶层 messages.resultCode
  • transactionResponse.responseCode
  • transactionResponse.transId
  • transactionResponse.errors
  • AVS 或 CVV 响应,如业务和商户配置需要

responseCode 为 1 通常表示交易已获批准。系统还应保存 transId,并通过后续查询或 webhook 跟踪结算结果。交易获得授权时,资金尚未完成最终结算。

交易被拒绝后,不要将账单标记为已支付。系统应记录拒绝信息,并以合适的方式通知付款人更新付款方式。

实现时需要注意

防止重复扣款

refId 可用于关联业务记录,但不能充当完整的幂等机制。学校系统应为每笔应收款建立唯一的收费记录,同时保存提交状态和 transId。发生网络超时后,先核对原交易是否成功,再决定是否重试。

保留订阅原有职责

订阅适合收取固定的周期性费用。滞纳金、补缴款和临时调整可以作为独立的一次性交易处理。只有需要永久调整后续每期金额时,才使用订阅更新接口。

客户授权与合规

保存付款方式不代表商户可以随时追加扣款。学校应取得适当授权,并在协议中说明滞纳金标准、扣款时间和通知方式。具体要求取决于所在地法律、卡组织规则、收单机构和商户账户配置,必要时应请支付服务商或法律顾问确认。

不要依赖 Authorize.Net 保存账务余额

Customer Profile 用于保存客户及付款方式,subscription 用于保存周期扣款计划。以下数据仍需由学校自行保存:

  • 每张账单的原始金额
  • 到期日期和滞纳金规则
  • 已付及未付金额
  • 交易与账单的对应关系
  • 减免、退款、拒付和冲正记录

学校的账单系统负责计算应收款并记账,Authorize.Net 负责完成实际支付。

备注:内容仅供参考。