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

# 注册并发送

> 使用 registerUser 预先注册收件人的身份与账单地址，然后使用 generateVCShareLinks（shareMethod: EXISTING_USER）生成绑定到该已知用户的托管虚拟卡链接。与标准流程不同，卡片会在生成链接时创建，而不是在认领时创建。

[标准托管链接流程](/features/open-loop-cards/send-open-loop-cards)将所有步骤留给收件人：你生成一个链接，Fluz 只有在收件人打开链接、完成验证并认领后才会创建虚拟卡。

对于你已识别的收件人，本流程将其反转。你使用 `registerUser` 自行注册收件人的身份与账单地址，然后使用 `generateVCShareLinks` 并设置 `shareMethod: EXISTING_USER` 生成分享链接。Fluz 会在生成时点**立即**创建虚拟卡，而不是等到认领时，并将其绑定到该唯一收件人。链接仍按照常规方式发送与认领；只有卡片创建提前。资金仍在认领时扣取，与标准流程相同——优先从 `userCashBalanceId` 扣取，如果启用了预付款或奖励余额且消费账户不足，则回退至你的预付款或奖励余额。

<Info>
  **何时选择此方式而非普通分享链接**

  * 你已明确知道收件人是谁（通过用户 ID），并希望在通知他们之前卡片已创建完毕并可用，而不是等待他们去认领。
  * 你需要硬性保证只有目标收件人才能查看该链接——而不是“第一个点击的人”。
  * 你要发送给一批已知收件人，并希望在收件人与卡片之间实现确定性的 1:1 映射。
</Info>

## 开始之前

你需要一个 Bearer 访问令牌。两个操作都不接受基本认证（Basic auth）。

| Operation              | Scope               | Also required                                |
| ---------------------- | ------------------- | -------------------------------------------- |
| `registerUser`         | —                   | 你的应用需启用注册权限                                  |
| `generateVCShareLinks` | `CREATE_SHARE_LINK` | 一个有效的虚拟卡 offer，一个用于出资的消费账户（可选启用预付款/奖励余额作为回退） |

<Warning>
  **用户注册默认不启用。** `registerUser` 是受限的变更操作——你的应用必须经 Fluz 明确批准后才能创建用户。**请联系你的 Fluz 销售代表或客户经理以启用此功能。** 来自未获批应用的调用会以 `AUTH-0022` 失败。

  如果收件人已拥有 Fluz 账户，你可以跳过注册，直接在 `generateVCShareLinks` 中使用其现有的 `recipientUserIds`。
</Warning>

参见[身份验证](/concepts/authentication)了解如何生成带作用域的令牌。

## 流程

<Steps>
  <Step title="注册收件人">
    使用收件人的个人信息、账单地址，以及其对持卡人协议的接受来调用 `registerUser`。

    ```graphql theme={null}
    mutation RegisterUser(
      $firstName: String!
      $lastName: String!
      $phoneNumber: String!
      $regionCode: String!
      $emailAddress: String!
      $dateOfBirth: String!
      $billingAddress: VirtualCardBillingAddressInput!
      $acceptCardholderAgreement: Boolean!
    ) {
      registerUser(
        firstName: $firstName
        lastName: $lastName
        phoneNumber: $phoneNumber
        regionCode: $regionCode
        emailAddress: $emailAddress
        dateOfBirth: $dateOfBirth
        billingAddress: $billingAddress
        acceptCardholderAgreement: $acceptCardholderAgreement
      ) {
        success
        userId
        accountId
        billingAddressId
        error {
          code
          message
        }
      }
    }
    ```

    ```json theme={null}
    {
      "firstName": "Ada",
      "lastName": "Lovelace",
      "phoneNumber": "5555555555",
      "regionCode": "US",
      "emailAddress": "ada.lovelace@example.com",
      "dateOfBirth": "1990-01-31",
      "billingAddress": {
        "streetAddressLine1": "456 Market St",
        "streetAddressLine2": "Suite 200",
        "country": "United States",
        "city": "San Francisco",
        "state": "CA",
        "postalCode": "94105"
      },
      "acceptCardholderAgreement": true
    }
    ```

    `acceptCardholderAgreement` 必须为 `true`——否则注册会被拒绝。注册失败将以 HTTP 200 返回并携带 `success: false`，而非出现在 GraphQL 的 `errors` 数组中；请务必检查 `success`。

    保存返回的 `userId`——你将在下一步将其传入 `generateVCShareLinks`。返回的 `accountId` 与 `billingAddressId` 在此流程中不需要。

    <Note>
      **此步骤不会创建卡片或持卡人协议。** 它只会创建用户记录、保存账单地址，并记录协议已被接受。虚拟卡及其与收件人的绑定会在下一步创建。
    </Note>

    <Note>
      **`AUTH-0026` 与 `AUTH-0027` 并非失败。** 它们表示该人已拥有 Fluz 账户——这很常见，因为 Fluz 账户并不限定于你的应用。跳过注册，直接使用其现有的用户 ID。
    </Note>

    完整参数参考：[registerUser](/api-reference/mutations/register-user)。
  </Step>

  <Step title="生成分享链接">
    使用 `shareMethod: EXISTING_USER` 调用 `generateVCShareLinks`，并将 `recipientUserIds` 设置为注册返回的用户 ID（或其他已知的 Fluz 用户 ID）。`recipientUserIds` 的长度必须等于 `quantity`。

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

    ```json theme={null}
    {
      "input": {
        "cardLimit": 100,
        "offerId": "09a9c8d1-9c4b-46fa-8a7a-508812a2a0d9",
        "daysUntilExpiration": 30,
        "quantity": 1,
        "shareMethod": "EXISTING_USER",
        "recipientUserIds": ["f1320ac4-52dc-4c67-9e80-24e506b18450"],
        "userCashBalanceId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
      }
    }
    ```

    对于多个收件人，请为每张卡传入一个用户 ID——顺序与生成的链接一一对应：

    ```json theme={null}
    {
      "input": {
        "cardLimit": 100,
        "offerId": "09a9c8d1-9c4b-46fa-8a7a-508812a2a0d9",
        "quantity": 3,
        "shareMethod": "EXISTING_USER",
        "recipientUserIds": [
          "f1320ac4-52dc-4c67-9e80-24e506b18450",
          "3f8a1c2d-4e5f-4a67-9a10-2b3c4d5e6f70",
          "9b2d0e11-77aa-4c3b-8f9e-1a2b3c4d5e6f"
        ],
        "userCashBalanceId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
      }
    }
    ```

    不要设置 `recipientListEmail` 和 `recipientListPhone`——对于该 `shareMethod`，收件人由 `recipientUserIds` 标识，且 Fluz 已为每位注册用户保存了联系方式。

    可选地将 `usePrepaymentBalance` 和/或 `useRewardsBalance` 设为 `true`，以便在认领时若 `userCashBalanceId` 余额不足，Fluz 可回退使用你的预付款或奖励余额：

    ```json With fallback funding theme={null}
    {
      "input": {
        "cardLimit": 100,
        "offerId": "09a9c8d1-9c4b-46fa-8a7a-508812a2a0d9",
        "quantity": 1,
        "shareMethod": "EXISTING_USER",
        "recipientUserIds": ["f1320ac4-52dc-4c67-9e80-24e506b18450"],
        "userCashBalanceId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
        "usePrepaymentBalance": true,
        "useRewardsBalance": true
      }
    }
    ```

    详情参见[资金来源](/features/open-loop-cards/send-open-loop-cards#input-fields)。
  </Step>

  <Step title="Fluz 创建卡片并分配链接">
    与标准流程不同，虚拟卡会在生成时点**立即**创建，而不是延后至认领。调用返回后，收件人会被分配到该卡及其链接。资金仍在认领时扣取，与标准流程相同——主要从 `userCashBalanceId` 扣取；若你设置了 `usePrepaymentBalance` / `useRewardsBalance` 且消费账户不足，则回退使用预付款或奖励余额。

    返回的每个链接都被锁定到其分配的收件人：只有该收件人的 Fluz 账户才能打开并认领。如果其他用户打开该 URL，他们在登录后会看到拒绝访问的状态，与任何已绑定的链接一致。
  </Step>

  <Step title="链接被投递">
    链接将与任何托管链接相同的方式发送给收件人——通过短信或电子邮件，使用 Fluz 为该用户备案的联系方式。之后收件人登录、完成 2FA，并进入其卡片页面。由于卡片已存在，认领时不会出现账单地址提示或等待发卡——此时进行资金扣取，与标准流程相同。
  </Step>
</Steps>

## 与标准流程的差异

|             | 标准（`GENERATE_URL` / `EMAIL` / `PHONE_NUMBER`）       | 本流程（`EXISTING_USER`）                  |
| ----------- | --------------------------------------------------- | ------------------------------------- |
| 收件人标识方式     | `recipientListEmail` / `recipientListPhone` 中的邮箱/电话 | `recipientUserIds` 中已知的 Fluz `userId` |
| 卡片创建时点      | 在收件人完成开户并认领时                                        | 在调用 `generateVCShareLinks` 时          |
| 卡片资金扣取      | 在认领时                                                | 在认领时（与标准流程相同）                         |
| 谁可以认领链接     | 若未被认领，则为第一个打开链接的人                                   | 仅分配的收件人——从链接创建那一刻起即强制执行               |
| 收件人认领时的开户流程 | 登录、2FA、账单地址（如需要）                                    | 登录、2FA——无账单地址提示，因为已在注册时收集             |
| 展示卡片        | 需要输入 PIN（或若尚未设置则创建 PIN）                             | 需要输入 PIN（或若尚未设置则创建 PIN）               |

标准流程参见[发送开放式卡](/features/open-loop-cards/send-open-loop-cards)，完整认领体验参见[收件人体验](/features/open-loop-cards/open-loop-cards-recipient-experience)。

## 注意事项与限制

* **`recipientUserIds` 必须指向已存在的 Fluz 用户。** 如果收件人尚未注册，请先使用 `registerUser` 注册（本流程），或使用标准托管链接流程让 Fluz 在认领时为其开户。
* **`recipientUserIds` 的长度必须等于 `quantity`。** 不匹配会返回校验错误且不创建任何记录。
* **卡片创建提前至生成时点——资金扣取则不变。** 当你调用 `generateVCShareLinks` 时会创建虚拟卡对象并完成收件人绑定，但资金仍在认领时扣取，与标准流程一致：先从 `userCashBalanceId` 扣取；若设置了 `usePrepaymentBalance` / `useRewardsBalance` 且消费账户不足，则回退使用你的预付款或奖励余额。
* **注册权限按应用与环境分别授予。** 在预发环境获得的权限不会自动延续到生产环境。参见[部署到生产](/deploying-to-production)。
* **切勿在预发环境注册真实用户。** 参见[预发 vs. 线上](/concepts/environments)。

## 下一步

<CardGroup cols={2}>
  <Card title="发送开放式卡" icon="link" href="/features/open-loop-cards/send-open-loop-cards">
    标准流程——生成链接并在认领时由 Fluz 发卡。
  </Card>

  {" "}

  <Card title="收件人体验" icon="user" href="/features/open-loop-cards/open-loop-cards-recipient-experience">
    收件人打开并认领托管链接时的所见即所得。
  </Card>

  <Card title="注册客户" icon="id-card" href="/user-registration">
    `registerUser` 的完整参考，包括错误处理与回退模式。
  </Card>
</CardGroup>
