> ## 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 的而不是供应商的，并且在三个礼品卡连接器中都相同。在切换前请阅读此页面。

## 认证与账户范围

每个连接器都使用带有你的 Fluz API 密钥的 HTTP Basic 认证：

```text theme={null}
Authorization: Basic <FLUZ-API-Key>
```

一个密钥只针对一个 Fluz 账户签发。使用该密钥下的每笔订单都由该账户出资，且所有读取都限定在该账户范围内。

你的供应商用于在子账户间路由的字段（例如 Tango 的 `accountIdentifier`）在此处不会选择子账户。如果你运营多个账户，请为每个账户申请一个密钥。

## 订单状态值

订单上的 `status` 字段（InComm 上为 `OrderStatus`）携带的是 Fluz 的值，而不是你的供应商的：

| 状态            | 含义       |
| :------------ | :------- |
| `PENDING`     | 已接受，尚未开始 |
| `IN_PROGRESS` | 正在履约     |
| `COMPLETED`   | 已履约，凭证可用 |
| `FAILED`      | 未履约      |
| `CANCELED`    | 履约前已取消   |

<Callout icon="⚠️">
  你的供应商状态字符串不会沿用。针对供应商值编写的检查，例如 `status === "COMPLETE"`，将不会匹配 `COMPLETED`。在切换前请更新每一个状态比较。
</Callout>

## 时序

**Tango Card 和 InComm** 同步创建订单，始终执行至完成。调用在购买完成前不会返回，这可能需要长达 150 秒，因此请将客户端的读取超时设置在此之上。

**Runa** 默认是异步的。`POST /v2/order` 会立即返回 `202` 和一个引用 ID，你随后再读取该订单。发送 `X-Execution-Mode: sync` 可阻塞至购买完成并接收完整结果，就像 Tango 和 InComm 那样。

## 读取订单

一笔订单在购买完成后才能被读取。在此之前读取引用 ID 会返回错误而不是待处理状态，因此请将新创建的异步订单上的错误视为仍在处理中，并稍后再读。

列表端点会在单个响应中返回该账户最近的 100 笔订单，按从新到旧排序。

## 错误响应

错误使用 Fluz 的封装，而不是你的供应商错误架构：

```json theme={null}
{ "error": "<message>" }
```

| 代码    | 何时返回                                               |
| :---- | :------------------------------------------------- |
| `401` | 缺失或无效的凭证                                           |
| `429` | 触发速率限制。响应体为 `{ "message": "Rate limit exceeded" }` |
| `500` | 其他所有失败，包括被连接器拒绝的请求                                 |

被拒绝的请求和服务器故障都会返回 `500`。请读取 `error` 消息以区分：拒绝表示请求需要更改，故障则可以安全重试。

## 速率限制

每个 API 密钥和每个源 IP 均为每秒 20 个请求。超过任一限制都会阻断该密钥或该 IP 10 秒，因此在收到 `429` 后请至少退避这么久。

密钥级别的限额是共享的，因此多个主机共用一个密钥会共享同一额度。

## 余额

余额读取会报告你的 API 密钥所属 Fluz 账户的可用余额。Tango 将其返回为 `currentBalance`，Runa 为 `balance`；InComm 会返回 `availableBalance` 和 `prepaidBalance`，后者单独覆盖礼品卡余额。

余额读取始终限定在你的密钥所属账户，因此你供应商余额调用中的区分符不会进一步缩小范围：Tango 的 `:accountId`、InComm 的 `:programId` 和 Runa 的 `?currency=` 会被接受以兼容你现有的请求结构。

需注意一项行为：带任意查询字符串的余额调用返回单个对象，而不带查询字符串的调用返回一个包含一个元素的数组。如果你的客户端对响应调用 `.map()`，请不要携带查询字符串。

## 品牌代码

三个连接器都会针对同一个 Fluz 目录解析品牌代码，无论它们位于哪个字段：Tango 的 `utid`、InComm 的 `Sku`、Runa 的 `items[].products.value`。你供应商的产品代码不会沿用，且 Fluz 不识别的代码会返回错误。

<Callout icon="⚠️">
  在切换前请将你的完整品牌列表与 Fluz 目录完成映射。解析到错误 Fluz 商品的代码会在没有错误的情况下发放错误的卡。
</Callout>

## 请求约束

连接器接受你的供应商请求结构，但某些值是固定的。违反以下任一约束的请求会被拒绝。

| 连接器        | 约束                                                                      |
| :--------- | :---------------------------------------------------------------------- |
| Tango Card | `sendEmail` 必须存在且设为 `false`                                             |
| Runa       | `payment_method` 必须为 `{ "type": "ACCOUNT_BALANCE", "currency": "USD" }` |
| Runa       | `products.type` 必须为 `SINGLE`                                            |
| Runa       | `items[]` 中的每一项必须完全相同。混合购物篮会被拒绝。请为每种不同的商品分别发送一笔订单                       |
| InComm     | `Recipients[]` 中必须且只能有一项                                                |
| InComm     | `Products[]` 中必须且只能有一项                                                  |
| InComm     | `DeliverEmail` 不得为 `true`                                               |

Fluz 直接在订单响应中返回礼品卡凭证，这也是上述邮件标志必须关闭的原因：收件人的投递仍由你控制。
