Skip to main content
通过 Fluz 发行的卡片完成的一笔消费并非单一事件。它是在商户、卡组织与 Fluz 之间展开的一段对话,可能持续数秒、数小时,甚至数周——在结束前会在你这边生成多条记录。 本页解释各阶段会发生什么、每个阶段会产出哪些 Fluz 记录与 webhook,以及那些容易让天真集成算错账的地方。
本页涵盖开放式卡交易(open-loop)——在卡组织网络上由 Fluz 发行的虚拟卡的消费。礼品卡购买、充值、提现和钱包转账不走此生命周期;它们在各自轨道上结算。参见 交易总览 获取承载所有记录的统一总账。

三个阶段

结算是跟随清算、由网络按自身节奏运行的银行间流程。Fluz 将清算与结算表示为一个事件——当一笔交易在 Fluz 上被清算,你应将其视为最终结果。

一笔消费,多条记录

单笔消费可能产生一次授权、一次或多次清算,并可能出现撤销或退款。Fluz 通过三个查询以不同视角暴露这些信息: 三笔消费及各自留下的记录:
退款是一条新记录,而不是对旧记录的编辑。退款以独立的 REFUND 交易到达。原始的 PURCHASE 记录不会发生任何改变——金额保持不变。如果你的系统在退款到达时去减少原始采购金额,你会把这笔贷记计算两次。请在记录层面对账;永远不要修改原记录。

单报文与双报文流程

网络发送多少报文取决于商户和交易类型。两种流程都很常见,你的集成必须同时支持。

单报文

网络发送一条同时完成授权与清算的消息。常见于 PIN 借记、ATM 取款与交通场景。不存在挂账窗口——交易几乎立即最终确定。

双报文

网络先发送授权,商户随后提交清算——通常当夜,但酒店、租车和旅行场景可达数日。两者之间的间隔即挂账窗口,也是大多数对账错误的来源。
清算金额可能与授权金额不同。 小费、加油站、货币兑换和分批发货都会导致清算金额高于或低于最初的预占。以清算金额为准,切勿将授权金额视为最终金额。

资金所在位置

从账户视角看同一生命周期:

Fluz 在各阶段记录了什么

两个数据源,两套状态词汇。
  • getVirtualCardTransactions 返回如 PROCESSING 与 CLEARED 的 transactionStatus。
  • getTransactions 返回 PENDING 与 SETTLED 的 status。
它们从两个角度描述同一生命周期。不要编写在两个位置都期待同一词汇表的代码。→ GraphQL API 如何工作
被拒不是交易。 被拒授权不会进入账户总账,因此在任何状态下都不会出现在 getTransactions 中。通过 getDeclinedTransactions 查询,并在拒绝码中读取原因。

授权(Authorization)

当网络请求 Fluz 批准一笔扣款时,Fluz 会根据卡片、账户以及卡片背后的资金对请求进行评估。这一切在一秒内完成,因为网络会超时。
  • 卡片为 ACTIVE——未被锁定、未过期、未到达 lockDate,亦未被一次性规则消费
  • 金额在卡片 spendLimit 与其 spendLimitDuration 范围内
  • 若卡片发行于品牌锁定计划,商户需与卡片的品牌锁匹配
  • 账户持有人已通过身份验证
  • 卡片背后的资金来源可覆盖该金额
  • 银行计划自身限额未被超出
卡片本身不持有余额。它会在授权时,按发卡配置的资金栈进行扣划:
  1. userCashBalanceId 指定的消费账户,或账户默认
  2. 预付(礼品卡)余额,除非 usePrepaymentBalance: false
  3. 奖励余额,除非 useRewardsBalance: false
  4. 当 primaryFundingSource 为 BANK_ACCOUNT 时的外部银行账户
若授权金额超出上述来源可覆盖的范围,即便卡片的 spendLimit 更高也会被拒。→ 管理虚拟卡资金来源
网络请求一个金额;Fluz 记录批准的金额。部分批准情况下两者不同,实际预占的是批准金额。请从 Fluz 记录读取金额,不要假设与商户请求一致。
被拒授权会向商户返回响应码,并在 Fluz 侧生成 declineReason 与 declineCategory。最常见原因包括超出消费限额、卡片被锁、卡片背后资金不足、品牌锁定卡用于错误商户、以及 CVV 或 AVS 不匹配。→ 拒绝码

非采购类授权

预占资金

获批授权会减少卡片可继续消费的额度,但不会把钱移出账户。清算到来前:
  • 卡片的 remainingBalance 反映该预占
  • 总账记录处于 PENDING
  • expectedClearedDate 告知你何时再查看
若清算从未到来,预占不会永远保留——网络的过期规则会释放它,资金回到卡片可用余额。大多数授权大约一周内过期;旅行与住宿的预占时间更长。确切窗口由网络与商户决定,而非 Fluz。

撤销(Reversals)

撤销是在清算之前取消授权。预占被释放,资金回到卡片。撤销可以是全额或部分。 常见原因:
  • 商户放弃了交易,或终端超时
  • 商品缺货,或持卡人在发货前取消
  • 发送了重复授权
  • 授权在未清算的情况下过期
清算之后的“撤销”其实是退款。一旦交易已清算,不再有可释放的预占。之后退回的资金以贷记形式到达——独立的 REFUND 记录——并应按此处理。是否存在匹配的清算记录,是区分两种情形的分界线。

清算与结算

清算是商户提交最终金额,通常作为隔夜批处理的一部分。Fluz 使用网络参考标识符将其匹配到未结的授权,并最终入账该记录。 需面向现实编写逻辑:
  • 金额会变化。 小费、加油、外汇与分批发货都会改变数值。
  • 可能存在多次清算。 一次分批发货会针对一个授权分次清算,且到达顺序可能错乱。
  • 清算可能在无授权的情况下到达。 在某些场景下网络允许商户强制入账——离线终端、机上消费、交通聚合计费。Fluz 会监测这些,但你的总账必须接受“直接已清算、没有挂账阶段”的采购。
  • 匹配并非保证成功。 罕见情况下,清算上的标识符与其所属授权不一致,清算会以独立记录出现。
不要仅凭网络参考标识符对账。 它们不保证在交易生命周期内保持一致,且跨网络不稳定。请在你创建订单时,将 Fluz 的 record_id 与 reference_id 存入你的系统。→ 与自有系统对账

退款(Refunds)

商户退回金额会通过网络以贷记返回。Fluz 会在卡片数据中将其记录为 REFUND,并在总账中记为一笔贷记。它可能先以授权到达后再清算,或直接以清算到达。 两种会打破天真匹配的情形:
  • 未关联退款。 网络可能在不引用原采购或使用不同标识的情况下发送贷记。它会作为独立的贷记到达,无法与原采购建立关联。
  • 打包退款。 多笔不同原采购的退款可能共享网络标识并被聚合到达。
基于上述,不要假设退款与采购是一一对应。将退款作为针对卡片的独立贷记对账,并以余额为最终真实来源。

外币

以其他货币进行的消费会以 USD 清算,同时在记录中保留原始金额: 这三个字段要么同时返回、要么同时为 null。换汇发生在清算阶段,因此外币授权与其清算在 USD 计价上常常不同,即便商户实际收取的金额一致。

常见消息序列

除了两条“快乐路径”,以下序列也值得纳入测试覆盖。

围绕生命周期进行构建

1

将挂账与已清算视为不同事物

切勿把挂账授权当作已完成采购展示,且切勿将授权与清算相加汇总。若需一个数值,请汇总已清算记录,并将预占单独展示。
2

订阅三种交易事件

TRANSACTION_CREATE、TRANSACTION_UPDATE 与 TRANSACTION_DECLINE。仅监听创建事件的集成会让每笔交易永远停留在授权金额。→ Webhooks
3

基于 updatedGte 同步,而非 createdGte

一条以 PENDING 创建、随后清算的记录会改变其“更新时间戳”,而非“创建时间戳”。按创建时间同步会悄然漏掉所有结算。
4

从快照对账余额

每条总账记录都携带每个余额的事后状态。请读取这些字段,而非自行累加金额——它们已包含费用、返现与未结预占。
5

使处理器具备幂等性

Webhook 会重试,且清算可能乱序到达。以 Fluz 记录标识符作为键,并让重放成为空操作。

测试该生命周期

预发卡(staging cards)是真实卡片记录,但不接入真实网络,因此通过注入交易而非刷卡来驱动。你可以演练授权、单独清算、拒绝、撤销、退款与零元探测——每种都会产生与生产环境一致的记录与 webhook。 → 模拟虚拟卡交易

后续步骤

交易总览

统一总账——记录包含哪些字段以及如何对账。

获取虚拟卡交易

卡级活动、过滤器、外汇字段与分页。

获取被拒交易

从未成为交易的授权。

拒绝码

全部拒绝原因与类别,以及应对措施。

模拟虚拟卡交易

在预发卡上进行测试消费并观察完整生命周期。

Webhooks

订阅交易事件、验证签名、处理重试。