> ## 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.

# 概览

> 从你的平台生成托管的虚拟卡链接（“open-loop” 发送卡）。你调用一个 API 来铸造一个或多个链接，然后以你喜欢的任何方式将这些链接交付给收件人——通过电子邮件、短信，或直接返回原始 URL 以嵌入你自己的流程。当收件人打开链接时，他们将进入一个由 Fluz 托管的页面，完成身份验证，并领取一张由你的账户资助的单次充值虚拟卡。

<Info>
  **先决条件：** 一个携带 `CREATE_SHARE_LINK` 范围的 Bearer 访问令牌。Basic auth 会被拒绝。联系你的销售代表以启用访问。参见 [Authentication](/concepts/authentication)。
</Info>

<Note>
  **什么是“托管”/“open-loop”。** *托管* 链接指向由 Fluz 托管的激活页面。*Open-loop* 表示生成的虚拟卡是网络卡（Visa/Mastercard 风格），可在许多商户处使用，但需遵循你项目的规则——而不是单品牌的封闭式礼品卡。
</Note>

![托管虚拟卡](https://test.fluz.app/wp-content/uploads/2026/04/ol-mock.png)

## 工作原理

<Steps>
  <Step title="你生成链接">
    使用 `generateVCShareLinks` 调用并传入优惠、卡片限额、数量、资金来源以及投递方式。每个链接代表一张卡及其独立限额，资金来自你指定的消费账户。
  </Step>

  <Step title="Fluz 为每个链接创建一个分享请求">
    每个链接对应一个分享请求（`PENDING`）和一个托管 URL。
  </Step>

  <Step title="链接被投递">
    使用 `GENERATE_URL` 时，你会拿到 URL 自行分发。使用 `EMAIL` 或 `PHONE_NUMBER` 时，Fluz 会为你向每位收件人发送一个链接。
  </Step>

  <Step title="收件人激活并领取卡片">
    收件人打开链接，通过一次性验证码验证手机号并设置卡片 PIN——无需下载 App、无需密码。卡片限额会在领取时从你的消费账户中划拨，而不是在生成链接时划拨。随后，收件人可以查看卡片详情、在线消费，并一键将卡片添加到 Apple Pay 或 Google Pay。
  </Step>
</Steps>

收件人仅成为该虚拟卡对象的授权用户——他们无法访问你的账户、余额或任何其他卡片。

查看收件人实际体验：[桌面流程](https://test.fluz.app/wp-content/uploads/2026/04/Web-Share-V6.mp4) · [移动流程](https://test.fluz.app/wp-content/uploads/2026/04/Mob-Share-F.mp4)。

![发送卡片流程图](https://files.readme.io/c19029bfeaca196f7eadc2f020ab56f2aad893261f561307bec543e700f0d74b-diagram.svg)

## 可用性与范围

| 功能            | 状态            |
| ------------- | ------------- |
| 单次充值虚拟卡       | ✅ 支持          |
| 一次性/可重复充值卡    | ❌ 不支持         |
| 通过 API 生成链接   | ✅ 支持          |
| 通过 CSV 导入生成链接 | ❌ 即将推出        |
| 托管的**礼品卡**链接  | ❌ 不在范围内（仅虚拟卡） |

卡片分享链接对象类型为 `VIRTUAL_CARD`，卡片类型为 `SINGLE_LOAD`。

<Warning>
  **礼品卡：** 尽管更广义的计划涵盖“虚拟卡**与**礼品卡”，但目前没有托管的礼品卡领取流程。礼品卡余额仅作为托管虚拟卡的\_潜在资金来源\_出现在此处（规划中，尚未启用）。请仅针对虚拟卡进行文档编写与开发。
</Warning>

## 操作参考

共有三个公开操作，均受 `CREATE_SHARE_LINK` 范围控制：

| 操作                       | 类型       | 目的             |
| ------------------------ | -------- | -------------- |
| `generateVCShareLinks`   | Mutation | 创建一个或多个托管虚拟卡链接 |
| `getVCShareLinks`        | Query    | 列出/查看先前生成的链接   |
| `deactivateVCShareLinks` | Mutation | 停用（过期）你生成的链接   |

所有发送卡片操作均在 Fluz GraphQL API 上，端点为 `POST https://<your-fluz-api-host>/api/v1/graphql`，并带有 `Authorization: Bearer <access_token>` 头。令牌必须携带 `CREATE_SHARE_LINK` 范围——否则每个操作都会返回 *"Missing permissions! Please contact your sales rep to get access to generate VC share links."*

## generateVCShareLinks

创建 `quantity` 个分享请求，并为每个请求返回一个托管链接。

```graphql theme={null}
mutation GenerateVCShareLinks($input: GenerateVCShareLinksInput!) {
  generateVCShareLinks(input: $input) {
    shareLinks
  }
}
```

### 输入字段

| 字段                    | 类型                 | 必填  | 说明                                                                                        |
| --------------------- | ------------------ | --- | ----------------------------------------------------------------------------------------- |
| `cardLimit`           | `Int!`             | 是   | 每张卡的消费限额（亦为充值金额），以整货币单位计。必须为整数且 ≥ 项目最小值。                                                  |
| `offerId`             | `String!`          | 是   | 卡片关联的商户优惠的 UUID v4。该优惠必须处于激活状态，且其商户必须可分享。                                                 |
| `quantity`            | `Int!`             | 是   | 要生成的链接数量。每个单位都会创建一个独立的托管 URL。                                                             |
| `shareMethod`         | `ShareMethodType!` | 是   | 链接的投递方式：`GENERATE_URL`、`EMAIL` 或 `PHONE_NUMBER`。                                          |
| `userCashBalanceId`   | `UUID`             | 是\* | 为卡片提供资金的消费账户。*在架构中标记为可选，但实际上必填——省略会导致校验失败。*                                               |
| `daysUntilExpiration` | `Int`              | 否   | 链接到期的天数。最少 1 天。若省略，默认为项目默认值（30 天）。**该日期也将成为卡片的锁定/冻结日期**——参见 [到期与冻结](#expiration--freeze)。 |
| `recipientListEmail`  | `[String]`         | 条件  | 当 `shareMethod = EMAIL` 时必填且非空。长度必须与 `quantity` 相等。否则必须为空。                                |
| `recipientListPhone`  | `[String]`         | 条件  | 当 `shareMethod = PHONE_NUMBER` 时必填且非空。长度必须与 `quantity` 相等。否则必须为空。                         |

<Note>
  **资金来源。** 目前唯一支持的资金来源是**消费账户**（`userCashBalanceId`），并且必须属于你（发送方）的账户。其他资金来源（银行账户、银行卡、预付/奖励余额）尚未开放。
</Note>

### 投递方式（`shareMethod`）

| 值              | 行为                       | 收件人列表                                      |
| -------------- | ------------------------ | ------------------------------------------ |
| `GENERATE_URL` | Fluz 在响应中返回托管 URL。你自行分发。 | 两个列表都必须为空/省略。                              |
| `EMAIL`        | Fluz 向每位收件人发送电子邮件链接。     | 需要 `recipientListEmail`；长度必须等于 `quantity`。 |
| `PHONE_NUMBER` | Fluz 向每位收件人发送短信链接。       | 需要 `recipientListPhone`；长度必须等于 `quantity`。 |

### 校验规则

* `cardLimit` 必须为整数，且至少为项目最小值。
* `offerId` 必须为 **激活** 优惠的有效 UUID v4，且其**商户可分享**。
* `quantity` 必须为整数。
* 当以 `EMAIL` 或 `PHONE_NUMBER` 投递时，相应的收件人列表长度**必须等于** `quantity`。不匹配会返回清晰错误，且**不会**创建任何记录。
* 只能提供一个资金来源。`userCashBalanceId` 必须为发送方账户所拥有的有效 UUID v4。
* 非法卡片类型或畸形输入会返回清晰错误，且不会创建记录。

### 示例

<CodeGroup>
  ```json Generate URLs theme={null}
  {
    "input": {
      "cardLimit": 25,
      "offerId": "11111111-2222-3333-4444-555555555555",
      "daysUntilExpiration": 30,
      "quantity": 3,
      "shareMethod": "GENERATE_URL",
      "userCashBalanceId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
    }
  }
  ```

  ```json Email theme={null}
  {
    "input": {
      "cardLimit": 25,
      "offerId": "11111111-2222-3333-4444-555555555555",
      "daysUntilExpiration": 30,
      "quantity": 2,
      "shareMethod": "EMAIL",
      "recipientListEmail": ["recipient1@example.com", "recipient2@example.com"],
      "userCashBalanceId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
    }
  }
  ```

  ```json SMS theme={null}
  {
    "input": {
      "cardLimit": 25,
      "offerId": "11111111-2222-3333-4444-555555555555",
      "daysUntilExpiration": 30,
      "quantity": 2,
      "shareMethod": "PHONE_NUMBER",
      "recipientListPhone": ["+12125550101", "+12125550102"],
      "userCashBalanceId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
    }
  }
  ```
</CodeGroup>

### 响应

```json theme={null}
{
  "data": {
    "generateVCShareLinks": {
      "shareLinks": [
        "https://fluz.app/virtual-prepaid-card/3f8a...c1",
        "https://fluz.app/virtual-prepaid-card/9b2d...77",
        "https://fluz.app/virtual-prepaid-card/0c41...e3"
      ]
    }
  }
}
```

`shareLinks` 是一个托管 URL 数组，每个对应 `quantity` 中的一条，形式为 `https://fluz.app/virtual-prepaid-card/{share_request_id}`。

<Tip>
  响应仅返回 URL。若要获取你刚创建链接的**批次 ID**和**显示 ID**（用于列表与停用），请使用 `getVCShareLinks` 并按状态过滤。
</Tip>

## getVCShareLinks

列出先前生成的分享链接，以便你查看状态、收件人、到期时间及已发卡片。

```graphql theme={null}
query GetVCShareLinks($input: GetVCShareLinksInput!) {
  getVCShareLinks(input: $input) {
    senderAppId
    shareRequestBatchId
    shareRequestDisplayId
    shareObjectStatus
    recipientPhone
    recipientEmail
    linkExpirationDate
    virtualCardId
    linkUrl
    shareRequestDetails {
      cardLimit
      offerId
      daysUntilExpiration
      quantity
      shareMethod
      recipientListEmail
      recipientListPhone
      userCashBalanceId
    }
  }
}
```

### 输入字段

| 字段                       | 类型                    | 说明                                         |
| ------------------------ | --------------------- | ------------------------------------------ |
| `shareObjectStatuses`    | `[ShareObjectStatus]` | 按状态过滤：`PENDING`、`ISSUED`、`USED`、`EXPIRED`。 |
| `shareRequestBatchIds`   | `[String]`            | 仅返回这些批次中的链接。                               |
| `shareRequestDisplayIds` | `[String]`            | 仅返回具有这些显示 ID 的链接。                          |

<Tip>
  **推荐流程。** 第一次调用时，只按 `shareObjectStatuses` 过滤。响应会给出 `shareRequestBatchId` 和 `shareRequestDisplayId`；在后续调用（以及停用时）使用这些值进行精确过滤。
</Tip>

### 响应字段（`GeneratedShareLink`）

| 字段                      | 类型                    | 说明                                     |
| ----------------------- | --------------------- | -------------------------------------- |
| `senderAppId`           | `String`              | 生成链接的应用/开发者应用。                         |
| `shareRequestBatchId`   | `String`              | 在一次调用中生成的所有链接共享的批次标识符。                 |
| `shareRequestDisplayId` | `String`              | 便于识别的人性化单链接标识符。                        |
| `shareObjectStatus`     | `ShareObjectStatus`   | `PENDING`、`ISSUED`、`USED` 或 `EXPIRED`。 |
| `recipientEmail`        | `String`              | 若通过电子邮件投递，则为收件人邮箱。                     |
| `recipientPhone`        | `String`              | 若通过短信投递，则为收件人手机号。                      |
| `linkExpirationDate`    | `DateTime`            | 链接到期/卡片冻结时间。                           |
| `virtualCardId`         | `String`              | 领取后发放的虚拟卡 ID。                          |
| `linkUrl`               | `String`              | 链接的托管 URL。                             |
| `shareRequestDetails`   | `ShareRequestDetails` | 原始配置（卡限额、优惠、数量、投递、资金）。                 |

### 示例

<CodeGroup>
  ```json By status theme={null}
  { "input": { "shareObjectStatuses": ["PENDING", "ISSUED"] } }
  ```

  ```json By batch theme={null}
  { "input": { "shareRequestBatchIds": ["ABC123", "XYZ789"] } }
  ```

  ```json By display ID theme={null}
  { "input": { "shareRequestDisplayIds": ["SR-000001", "SR-000002"] } }
  ```
</CodeGroup>

## deactivateVCShareLinks

停用（使过期）你生成的链接——例如，若误发送了某批次，或你需要撤销未被领取的链接。停用后的链接状态将设为 `EXPIRED`；未领取的链接将无法再被领取。

```graphql theme={null}
mutation DeactivateVCShareLinks($input: DeactivateVCShareLinksInput!) {
  deactivateVCShareLinks(input: $input)
}
```

### 输入字段

| 字段                       | 类型         | 说明                |
| ------------------------ | ---------- | ----------------- |
| `shareRequestBatchIds`   | `[String]` | 停用这些批次中的所有链接。     |
| `shareRequestDisplayIds` | `[String]` | 仅停用具有这些显示 ID 的链接。 |

批次 ID 可通过 `getVCShareLinks` 获取。

```json theme={null}
{ "input": { "shareRequestBatchIds": ["ABC123"] } }
```

返回一段可读性确认字符串，例如 `"3 share requests successfully deactivated!"`。

<Warning>
  如果收件人已**领取**某个链接（状态为 `ISSUED`/`USED`），停用链接不会回收已发放的卡片。要停止已发卡片的消费，请使用相应的卡片生命周期/冻结控制。
</Warning>

## 收件人体验

当收件人打开一个托管链接（`https://fluz.app/virtual-prepaid-card/{share_request_id}`）时：

<Steps>
  <Step title="落地与登录">
    收件人会看到带有发送方品牌的激活页面。他们通过 Fluz 认证门户登录（新用户在此完成注册）。
  </Step>

  <Step title="双重验证">
    初次加载时，已有用户将进入 2FA 页面。必须完成 2FA 后才能查看或领取卡片。
  </Step>

  <Step title="账单地址（如需）">
    如果收件人尚未保存账单地址，将会提示添加。*在线购物需要账单地址。*
  </Step>

  <Step title="PIN（若尚未发卡）">
    在发卡之前，收件人需要设置 PIN。
  </Step>

  <Step title="发卡与领取">
    将创建一张单次充值虚拟卡并分配给收件人，资金来自发送方账户，锁定日期等于链接的到期日期。
  </Step>

  <Step title="使用卡片">
    领取后，收件人可查看卡片详情、交易明细，并（在支持的场景下）将卡片添加到移动钱包。
  </Step>
</Steps>

<Note>
  **已被领取？** 如果同一用户打开他们已领取的链接，会显示其卡片详情。若\_不同\_用户打开已被他人领取的链接，在完成 2FA 后将看到拒绝访问状态。
</Note>

## 到期与冻结

链接的到期日期有双重作用：

* **链接到期**——在此日期之后，**未领取**的链接将无法再被领取。
* **卡片冻结/锁定日期**——对于**已发放**的卡片，这是锁定日期（当日结束）。过后卡片将被冻结，无法消费。
* **卡片有效期** 与冻结日期所在月的月末对齐（例如，冻结日期为 2026/6/15，则卡片有效期为 2026/6/30）。

在生成时通过 `daysUntilExpiration` 设置此窗口。若省略，则使用项目默认（30 天）。该日期会展示给收件人（通常作为“有效至”日期）。

## 需向收件人传达的项目规则

以下是托管（open-loop）虚拟卡的项目级规则。请与你的 Fluz 代表确认**你的**项目的具体值——其中若干为合作方协商项。

| 规则       | 默认值             | 备注                          |
| -------- | --------------- | --------------------------- |
| 账户每日消费限额 | **\$250,000/日** | 部分合作方有自定义限额。                |
| 餐厅交易缓冲   | **25%**         | 所有项目均适用 25% 缓冲（用于餐厅小费/预授权）。 |
| 受限商户/类别  | 项目特定            | 某些商户类别受限。                   |
| 资金来源     | 发送方的消费账户        | 卡片在领取时从发送方账户划拨资金。           |

**收件人客服支持：** 1-888-360-6660 · [humans@fluz.app](mailto:humans@fluz.app)

<Note>
  完整的面向合作方参考资料（术语、带截图的收件人流程、资金说明、受限类别及支持）见 **Partner Guide — Hosted URL Virtual Cards**。请向你的 Fluz 联系人索取你项目的最新版本。
</Note>

## 状态与错误参考

### 分享对象状态

| 状态        | 含义               |
| --------- | ---------------- |
| `PENDING` | 已生成链接，尚未领取。      |
| `ISSUED`  | 收件人已领取链接；已发放虚拟卡。 |
| `USED`    | 已发放的卡片已被使用。      |
| `EXPIRED` | 链接已到期或被停用；不可再领取。 |

### 面向收件人的链接错误

| 条件            | 收件人看到的内容                          |
| ------------- | --------------------------------- |
| 在领取前链接已到期     | “Expired before issued”——链接已无法领取。 |
| 发送方提前停用了链接    | “Frozen by sender”——链接在到期前被撤销。    |
| 领取后卡片锁定日期已过   | “Expired after issued”——卡片已冻结。    |
| 不同用户打开已被领取的链接 | “Access denied”。                  |

### 常见 API 错误

| 原因                                         | 结果               |
| ------------------------------------------ | ---------------- |
| 缺失/无效的 Bearer 令牌或缺少 `CREATE_SHARE_LINK` 范围 | 请求被拒绝（未授权）。      |
| 收件人列表长度 ≠ `quantity`                       | 明确的校验错误；不创建任何记录。 |
| 非激活优惠、不可分享商户或无效的 `offerId`                 | 校验错误；不创建任何记录。    |
| 缺失/无效的 `userCashBalanceId`，或提供了多个资金来源      | 校验错误；不创建任何记录。    |

## 备注与限制

* **返回的 URL 是托管目的地而非短链接。** 内部会通过短链接服务包装，但 API 返回的是规范的托管 URL（`/virtual-prepaid-card/{share_request_id}`）。请按原样分发该 URL。
* 尽管架构标注为可选，但 `userCashBalanceId` 实际上是必填项。
* **隐藏/内部字段不属于该 API。** 对象类型和卡片类型是固定的（`VIRTUAL_CARD` / `SINGLE_LOAD`），其他资金来源字段尚未启用；请勿发送。
* **不支持礼品卡托管链接。** 此 API 仅用于虚拟卡。

## 下一步

<CardGroup cols={2}>
  <Card title="创建批量订单" icon="layers" href="/features/create-bulk-order">
    一次性发放多张卡以便程序化分发。
  </Card>
</CardGroup>
