PAYATHON 2026

如何在 Square Connect API 中处理定期付款?

支付老李

结论

可以不发送 Square Invoice,直接完成周期性扣款。不过,旧版 Square Connect API 的 Checkout API 不能把订单定义为 recurring,也不能在 Checkout 请求中设置扣款日期或频率。

常见的实现流程如下:

  1. 首次付款时取得客户授权。
  2. 将银行卡保存为 card on file。
  3. 在自己的系统中记录订阅周期、下次扣款时间和订阅状态。
  4. 每个 billing period 到期后,由服务器调用支付接口扣款。

旧文档中的“支持 recurring payments”,通常是指商户可以使用已保存的银行卡发起后续扣款,并不代表 Checkout API 提供了完整的订阅调度功能。FAQ 和 API 文档看起来存在矛盾,往往是因为两者描述的功能层级不同,或者发布时间不同。

实现流程

1. 创建或识别客户

先在 Square 中创建 Customer,并在本地保存 Square 返回的 customer ID。不要只通过姓名或邮箱来关联客户。

2. 保存银行卡

使用 Square 提供的前端支付组件安全生成 card nonce/token,再由后端将银行卡关联到 Customer。

银行卡号、CVV 等原始卡片信息不应经过自己的服务器。一次性 nonce 也不能作为可重复使用的凭据。保存成功后,应使用 Square 返回的 card ID,或相应版本 API 提供的 card-on-file 标识。

保存银行卡前,还需要取得客户对后续周期性扣款的明确授权,并记录以下内容:

  • 扣款金额或金额计算方式
  • 扣款频率
  • 首次扣款日期
  • 取消方式
  • 金额变化时的通知规则

3. 在业务系统中保存订阅计划

Checkout API 不处理周期调度,因此需要在自己的数据库中记录类似信息:

{
  "customer_id": "CUSTOMER_ID",
  "card_id": "CARD_ID",
  "amount": 1999,
  "currency": "USD",
  "interval": "month",
  "next_billing_at": "2026-09-01T00:00:00Z",
  "status": "active"
}

interval、next_billing_at 和 status 是业务系统中的字段,并不表示 Checkout API 接受这些参数。

4. 到期时发起扣款

由定时任务、任务队列或账单服务查找已到期的订阅,再使用保存的卡片发起支付。

对于旧版 Transactions/Charge 风格的接口,请求结构大致如下:

curl -X POST \
  "https://connect.squareup.com/v2/locations/LOCATION_ID/transactions" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "idempotency_key": "subscription_123_period_2026_09",
    "amount_money": {
      "amount": 1999,
      "currency": "USD"
    },
    "card_nonce": "CUSTOMER_CARD_ID",
    "reference_id": "subscription_123"
  }'

这段代码展示的是旧版 Square Connect/Transactions API 的实现思路。具体字段能否继续使用,取决于账户采用的 API 版本。较新的 Square API 通常使用 Payments API,并通过 source_id 指定保存的 Card ID。例如:

const response = await squareClient.payments.create({
  sourceId: cardId,
  idempotencyKey: `subscription-${subscriptionId}-${billingPeriod}`,
  amountMoney: {
    amount: 1999n,
    currency: "USD"
  },
  customerId,
  referenceId: subscriptionId,
  note: "Monthly subscription payment"
});

SDK 的初始化方式、方法签名和金额类型可能随版本变化,具体应以项目锁定版本的官方文档为准。

为什么不能只使用 Checkout API

Checkout API 主要用于创建一次性的托管结账流程。即使首次订单通过 Checkout 完成,该订单也不会因此在未来自动重复执行。

周期性付款还需要处理以下问题:

  • 账单周期计算
  • 夏令时和月末日期
  • 扣款失败重试
  • 卡片失效或更换
  • 订阅暂停与取消
  • 金额变更
  • 重复任务和并发执行
  • 客户通知与退款

因此,不能通过重复提交同一个 Checkout 来实现周期扣款,也不能重复使用一次性支付 nonce。

更合适的现代方案

如果当前 Square 账户和所在地区支持 Subscriptions API,可以优先评估这一方案。对于标准订阅业务,它通常比自行调度 card-on-file 扣款更合适,可以管理计划、订阅、阶段和周期账单。

它能否完全替代自建账单逻辑,还要看具体需求,包括:

  • 所在国家或地区是否受支持
  • 订阅金额是否固定
  • 是否需要按使用量计费
  • 是否需要复杂的试用、升级或按比例计费
  • 是否需要关联现有订单系统

如果必须维护旧版 Square Connect 集成,采用“card on file + 每个 billing period 调用支付接口”的方式更符合该 API 的能力范围。

注意事项

  • 每次扣款都必须使用唯一且可重复计算的 idempotency_key,避免任务重试导致重复扣款。
  • 只有支付成功后才能推进 next_billing_at。支付失败时,应将订阅转入明确的重试或欠费状态。
  • 不要无限重试被拒绝的付款,需要区分临时错误和永久拒付。
  • 客户删除或更换银行卡后,需要同步更新订阅使用的 card ID。
  • 保存银行卡并不等于自动取得周期扣款授权。授权记录和用户取消机制需要单独处理。
  • API 文档中的 recurring payments 示例可能只是在说明如何通过 card on file 发起后续付款,不一定表示 Checkout API 支持声明式 recurring order。
  • Square Connect、Transactions API、Checkout API、Payments API 和 Subscriptions API 分属不同阶段或承担不同职责。实施前,需要确认项目实际使用的 API 和 SDK 版本。

备注:内容仅供参考。