> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fluz.app/llms.txt
> Use this file to discover all available pages before exploring further.

# 概览

> 阅读商户目录，理解固定与可变优惠，购买礼品卡并进行揭示——完整的礼品卡流程，以及每一步该读的页面。

通过 Fluz 购买一张礼品卡分四步，每一步都有单独的页面。下面是导览。

<Steps>
  <Step title="查找优惠">
    拉取目录，或仅查询单一商户的最佳费率。→ [阅读目录](#reading-the-catalog)
  </Step>

  <Step title="确认可购金额">
    固定或可变，有现货或按需生成。→ [固定 vs. 可变](#fixed-vs-variable-offers)
  </Step>

  <Step title="购买">
    一次变更，一张卡，一个幂等键。→ [购买](#buying-a-card)
  </Step>

  <Step title="揭示">
    获取代码、PIN 或 URL，并正确渲染。→ [揭示](#revealing-the-card)
  </Step>
</Steps>

<Warning>
  **费率持续变化。** Fluz 持续重新定价以提供最佳可用优惠，且你的费率会针对你的账户定制。切勿缓存费率并在之后据此购买——在购买前应立即重新确认。
</Warning>

***

## 术语

本节主要用到五个术语，其中三个听起来相似。

| 术语                        | 含义                                                                             |
| :------------------------ | :----------------------------------------------------------------------------- |
| **Merchant（商户）**          | 品牌——如 Starbucks、Best Buy。具有 `merchantId` 与人类可读的 `slug`。                        |
| **Offer（优惠）**             | 来自该商户的一个可购买的具体方案，拥有独立的 `offerId`。一个商户可有多个优惠。                                   |
| **Offer rate（优惠费率）**      | 附加在优惠上的回报——返现、加成、可用面额、允许的支付方式。                                                 |
| **Denomination（面额）**      | 卡的面值。要么从预设列表中选择，要么是在某个范围内任意金额。                                                 |
| **Delivery format（交付格式）** | 卡如何到达：`URL`、`CODES`、`PIN_AS_CODE`、`PIN_WITH_URL` 或 `CODE_WITH_PREFIX`。决定你如何渲染。 |

两个标识符容易混淆：`merchantId` 标识品牌，`offeringMerchantId` 标识提供该笔交易的一方。你基于 `offerId` 或 `slug` 进行购买，绝不基于 `merchantId`。

***

## 阅读目录

三种入口，对应三类任务。

| 方法            | 查询                            | 适用场景                      |
| :------------ | :---------------------------- | :------------------------ |
| **完整目录**      | `getMerchants`                | 你要构建可浏览店面、同步本地目录，或在品牌间做对比 |
| **单一商户的最佳费率** | `getOfferQuote`               | 你已确定品牌与金额，只想要今日最佳费率       |
| **CSV 导出**    | Dashboard → **Stores** → 生成导出 | 分析、财务，或有人需要电子表格           |

将 `getMerchants` 过滤为礼品卡：`offerTypes: { giftCardOffer: true, cardLinkedOffer: false }`。卡联优惠会出现在目录中，但目前通过 API 仅可购买礼品卡与专属优惠。

<Note>
  **完整目录是缓存文件，每日刷新两次。** `getOfferQuote` 为实时。如果购买时的精确费率很重要——通常如此——请在购买前先报价，而不是相信今天早上的目录拉取。促销费率会反映在两者中，包括促销期间生成的 CSV 导出。
</Note>

两种查询都有限流，因此请分页获取完整目录，不要一次性请求。→ [获取目录](/get-catalog) · [获取礼品卡优惠](/get-gift-card-offers) · [获取最佳优惠](/get-best-offer)

### 专属优惠

费率会按账户定制。若你的账户有协商费率，它们会作为 `type: "EXCLUSIVE_RATE_OFFER"` 的优惠出现，并带有 `exclusiveRateId`。将该 ID 传给 `purchaseGiftCard` 可强制按该费率购买；若省略，Fluz 会选择最佳可用费率。

***

## 固定 vs. 可变优惠

这是最影响你的集成方式的区分，而且一个商户可以同时有两种。

<CardGroup cols={2}>
  <Card title="FIXED" icon="lock">
    该卡采用**预设面额**——$25, $50, \$100——你需按其原样购买。

    常由 Fluz 持有的**真实库存**背书，因此固定优惠通常具有**更优费率与更高购买限额**。

    库存有限，会耗尽。
  </Card>

  <Card title="VARIABLE" icon="sliders-horizontal">
    你可在**最小/最大范围内任意选择金额**，并实时生成卡片。

    无可耗尽的库存——几乎无限供应。

    通常**回报率低于**同品牌的固定优惠。
  </Card>
</CardGroup>

实际权衡：固定优惠回报更高但可能在处理中耗尽；可变优惠始终可用但回报更低。高批量下单通常先吃固定库存，再回退到可变。

### 在哪里读取可购买金额

由两个字段决定，其组合决定答案在哪个字段里。搞错会提交该优惠无法满足的金额。

| `denominationsType` | `hasStockInfo` | 可购买金额所在                               | 含义                                     |
| :------------------ | :------------- | :------------------------------------ | :------------------------------------- |
| `FIXED`             | `true`         | `stockInfo` → `StockInfoFixedType`    | 具体面额，带可计数的 `availableStock`            |
| `FIXED`             | `false`        | `offerRates.denominations`            | 预设面额，未公布库存约束                           |
| `VARIABLE`          | `true`         | `stockInfo` → `StockInfoVariableType` | `minDenomination`–`maxDenomination` 范围 |
| `VARIABLE`          | `false`        | `offerRates.denominations`            | 处于已公布范围内的任意金额                          |

<Warning>
  `stockInfo` 是一个**联合类型（union）**。你必须用针对两种形态的内联片段去查询，否则其中一种会拿不到结果：

  ```graphql theme={null}
  stockInfo {
    ... on StockInfoFixedType    { __typename denomination availableStock }
    ... on StockInfoVariableType { __typename description minDenomination maxDenomination }
  }
  ```

  即使你自以为知道会返回哪一种，也请始终包含两个片段。参见 [GraphQL API 的工作方式](/concepts/graphql)。
</Warning>

注意，“有库存信息”并不意味着“有可计数库存”。在可变优惠上，`stockInfo` 返回的是一个范围，而非数量。只有 `StockInfoFixedType` 携带可递减的 `availableStock` 数字。

填充 `stockInfo` 需要 Fluz 与供应商确认库存，供应商响应时间不一——因此请求它会让查询更慢。仅在你即将基于它采取行动时再请求。→ [获取有库存优惠的库存](/get-inventory)

***

## 购买礼品卡

一个变更：`purchaseGiftCard`。三个决策点。

### 1. 如何选择优惠

| 你传入                              | 行为                                |
| :------------------------------- | :-------------------------------- |
| `offerId`                        | **固定选择。** 购买该确切优惠。若已耗尽，调用失败——无回退。 |
| `merchantSlug`                   | **自动选择。** 购买该品牌的最佳可用费率，随库存变化自动回退。 |
| `merchantSlug` + `minRewardRate` | 带下限的自动选择。低于你的最低费率则失败。             |
| `exclusiveRateId`                | 强制使用特定的协商费率。                      |

固定选择给你费率的确定性；自动选择给你履约的确定性。`merchantSlug` + `minRewardRate` 是折中方案，也是自动化下单的常用默认值。

### 2. 如何支付

至少需要一个资金来源，你可以将 Fluz 余额与其他来源组合使用。

| 字段                                               | 作用                        |
| :----------------------------------------------- | :------------------------ |
| `balanceAmount`                                  | 从 Fluz 余额中支付的**金额**       |
| `userCashBalanceId`                              | 该余额来源于**哪个消费账户**          |
| `bankCardId` / `bankAccountId` / `paypalVaultId` | 外部资金来源                    |
| `defaultToBalance`                               | 其他方式失败时是否回退至余额。默认为 `true` |

<Warning>
  **若你的账户下有多个消费账户，请始终显式传入 `userCashBalanceId`。** 若省略，Fluz 会从标记为 `isDefault` 的账户扣款——该标记可能在你的代码不变的情况下发生变化，从而悄然改变资金来源。这是导致“余额不足”意外失败的最常见原因。

  在自动化流程中，也请设置 `defaultToBalance: false`，以便购买要么从你指定的账户扣款，要么干净地失败。
</Warning>

### 3. 幂等性

`idempotencyKey` 为必填，它决定重试与重复购买的区别。每张欲购的卡使用一个键，对同一张卡的每次重试都复用该键。→ [幂等性](/docs/idempotency-requests)

→ [购买礼品卡](/purchase-gift-card)

### 购买多张

**一次调用只购买一张卡**，基于一个优惠、一个费率。没有数量字段，也不能跨优惠混合。要十张卡，就发送十次调用，并使用十个不同的幂等键。

当你跑得比库存快时，结果取决于你如何选择优惠：

* **固定（`offerId`）**——一旦库存型优惠耗尽，其余调用失败。无自动回退。
* **自动选择（`merchantSlug`）**——其余调用会转向次优优惠，通常是费率更低的可变优惠，除非被 `minRewardRate` 阻止。

→ [批量购买](/purchase-in-bulk)

### 大批量下单

针对同一 Fluz 账户的购买会**顺序**处理。一次性发起大批量请求会造成调用互相排队，偶尔需数分钟才返回。

<Note>
  **客户端超时不等于取消。** 即使你不再等待，Fluz 仍会继续处理请求。将超时视为结果未知，而非失败。

  通过使用**相同**的 `idempotencyKey` 重试来确认结果——若原始购买已成功，重试会返回该结果，且不会重复扣款。为已尝试的购买换用新键，正是导致重复下单的方式。

  将客户端超时设置为约 1 分钟，分批次推进请求而非一股脑发出，并将大流量分散到多个账户。
</Note>

***

## 揭示礼品卡

购买后你会得到一个 `giftCardId`。兑换详情通过第二次调用获取。

<Steps>
  <Step title="获取礼品卡">
    若你刚完成购买并已持有 `giftCardId`，可跳过此步。否则 `getGiftCards` 会列出它们及 `purchaseId`、`purchaseDisplayId`、`purchaseValue`、`currentValue` 与 `status`——足以在不揭示每张卡的情况下对账。
  </Step>

  <Step title="揭示">
    `revealGiftCardByGiftCardId` 返回 `code`、`pin`、`url` 与 `termsAndConditions`。
  </Step>
</Steps>

三个常见坑：

* **不是每张卡都有这三个字段。** 有些商户仅发放无 PIN 的代码；有些只发放 URL。Fluz 原样透传商户提供的内容——请处理空值。
* **根据 `deliveryFormat` 与 `barcodeType` 渲染，** 且请从 `getGiftCards` 获取 `deliveryFormat`，而非商户当前优惠。优惠会变化；卡是在购买时的格式下发行的。`barcodeType` 为 `NONE`、`C128`、`PDF417` 或 `QRCODE`；当为 `NONE` 时，考虑显示 `faceplateUrl`。
* **详情可能不会即刻就绪。** 使用指数退避轮询——300ms 起步，倍增，上限三分钟——一旦详情返回即停止。

→ [查看礼品卡](/view-gift-card)

***

## 授权范围（Scopes）

| 范围                  | 用于                                |
| :------------------ | :-------------------------------- |
| `LIST_OFFERS`       | `getMerchants`、`getOfferQuote`    |
| `PURCHASE_GIFTCARD` | `purchaseGiftCard`                |
| `REVEAL_GIFTCARD`   | `revealGiftCardByGiftCardId`      |
| `LIST_PURCHASES`    | `getUserPurchases`、购买历史           |
| `LIST_PAYMENT`      | `getUserCashBalances`、`getWallet` |

请在应用的 **Permissions** 选项卡中启用后再开发。未启用却请求的范围会被静默丢弃。→ [配置 OAuth 应用](/configure-o-auth-app)

***

## 当出现失败

| 代码        | 含义                    |
| :-------- | :-------------------- |
| `GC-0002` | 购买金额或 Fluz Pay 金额不是正数 |
| `GC-0003` | 无法获取礼品卡记录             |
| `GC-0004` | 购买失败——请尝试其他支付方式       |
| `GC-0006` | 无法揭示礼品卡               |

完整列表：[礼品卡错误代码](/gift-card-error-codes)。

在为终端用户处理失败或超时购买的退款之前，**请使用相同的 `idempotencyKey` 重试或按 ID 查询该购买。** 超时请求经常已成功，且代码在购买被退款前始终可被揭示。

***

## 下一步

<CardGroup cols={2}>
  <Card title="获取目录" icon="list" href="/get-catalog">
    拉取商户及其优惠。
  </Card>

  <Card title="获取最佳优惠" icon="badge-percent" href="/get-best-offer">
    单一商户与金额的实时报价。
  </Card>

  <Card title="获取库存" icon="package" href="/get-inventory">
    固定、带库存优惠的库存信息。
  </Card>

  <Card title="购买礼品卡" icon="shopping-cart" href="/purchase-gift-card">
    完整的变更调用。
  </Card>

  <Card title="批量购买" icon="layers" href="/purchase-in-bulk">
    大批量下单与库存耗尽时的行为。
  </Card>

  <Card title="查看礼品卡" icon="eye" href="/view-gift-card">
    揭示代码、PIN 与 URL。
  </Card>
</CardGroup>
