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

# 数字钱包推送开通（Push Provisioning）

使用 `getCardProvisioningUrl` 查询来铸造一个短且一次性使用的 URL——当终端用户在手机上打开该链接时，会在设备上启动 Fluz，并将指定优惠的虚拟卡添加到 Apple Pay（iOS）或 Google Pay（Android）。

你可以通过任意方式传递该 URL：二维码、短信、电子邮件，或应用内按钮。随后 Fluz 将处理钱包开通流程。

## 何时使用

在任何你通常会把虚拟卡交给用户、并希望他们能在手机的钱包中一键添加而无需输入卡号的场景。典型流程：

* 为用户创建卡片优惠后，在屏幕上展示一个二维码。
* 通过短信或电子邮件将 URL 发送给持卡人。
* 在你的移动应用中嵌入一个“添加到 Apple Pay / Google Pay”按钮。

<Info>
  **先决条件：** 终端用户的 OAuth 访问令牌，且包含 `CREATE_VIRTUALCARD` 范围，以及为该用户创建的虚拟卡优惠（通过现有的优惠 API 创建）。
</Info>

<Warning>
  此查询不接受基本认证（`client_id` / `client_secret`）——必须使用用户上下文的持有者令牌（bearer token）。
</Warning>

## 查询

```graphql theme={null}
query ProvisionCard($offerId: String!) {
  getCardProvisioningUrl(input: { offerId: $offerId, platform: IOS }) {
    url
    expiresAt
  }
}
```

### 输入

| 字段         | 类型                     | 必填 | 说明                                                   |
| ---------- | ---------------------- | -- | ---------------------------------------------------- |
| `offerId`  | `String!` (UUIDv4)     | 是  | 要开通的钱包的虚拟卡优惠。必须处于激活状态、符合代币化资格，并且可被该用户的账户访问。          |
| `platform` | `ProvisioningPlatform` | 否  | 关于用户将在哪打开 URL 的提示。默认为 `IOS`。见下文——这并不会将 URL 限制在某个平台上。 |

#### `ProvisioningPlatform`

返回的 URL 具备平台感知能力：iOS 用户会自动获得 App Clip 体验，Android 用户会自动获得 Fluz 应用深链。`platform` 仅影响当 URL 在 iOS 或 Android 设备之外的地方（如桌面浏览器）被打开时的行为。

| 值         | 桌面 / 未知设备回退行为      |
| --------- | ------------------ |
| `IOS`（默认） | Apple App Clip 启动器 |
| `ANDROID` | Fluz Android 深链    |
| `OTHER`   | Fluz Web 应用        |

选择与你预期 URL 将被打开位置最匹配的值。如不确定，保持 `IOS` 即可。

### 输出

| 字段          | 类型        | 说明                                      |
| ----------- | --------- | --------------------------------------- |
| `url`       | `String!` | 要传递给用户的短链接。一次性使用。                       |
| `expiresAt` | `String!` | ISO-8601 时间戳。该 URL 在此时间后失效（≈ 创建后 5 分钟）。 |

## 示例

### 请求

```bash theme={null}
curl -X POST https://api.fluz.app/api/v1/graphql \
  -H "Authorization: Bearer <user_access_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query($id:String!){ getCardProvisioningUrl(input:{ offerId:$id, platform:IOS }){ url expiresAt } }",
    "variables": { "id": "11111111-2222-3333-4444-555555555555" }
  }'
```

### 响应

```json theme={null}
{
  "data": {
    "getCardProvisioningUrl": {
      "url": "https://fluz.app.link/abc123XYZ",
      "expiresAt": "2026-05-26T17:42:11.000Z"
    }
  }
}
```

## 如何投递 URL

该 URL 是不透明的且不包含敏感数据——可安全地用于二维码、短信、电子邮件或应用内 UI。常见模式：

* **屏幕二维码** —— 从 `url` 生成二维码并展示；用户用手机相机扫描。
* **短信 / 电子邮件** —— 将链接直接发送到用户的手机或收件箱。
* **应用内深链** —— 在你的移动应用中接入一个按钮来打开 `url`。

无论通过何种投递渠道，用户都必须在移动设备上打开该 URL——钱包开通流程会在手机上进行。

## 有效期与重新签发

* 每次调用都会返回一个全新的、一次性使用的 URL。
* URL 在 `expiresAt` 前有效（≈ 5 分钟）。
* 如果用户未及时操作，只需再次调用 `getCardProvisioningUrl` 来铸造一个新的链接。没有单独的“刷新”端点。

## 错误处理

所有错误都会以 Fluz 标准 GraphQL 错误格式返回，错误名称位于 `extensions.code` 中。

| 代码                                            | 含义                          | 处理措施                |
| --------------------------------------------- | --------------------------- | ------------------- |
| `Arguments.INVALID`                           | `offerId` 不是有效的 UUID。       | 在你的端校验输入。           |
| `VirtualCard.OFFER_NOT_FOUND`                 | 优惠不存在或已失效。                  | 确认优惠 ID；如有需要创建新的优惠。 |
| `VirtualCard.OFFER_NOT_ACCESSIBLE`            | 该用户的账户无权使用此优惠（活动访问权限）。      | 向用户展示通用的“不可用”消息。    |
| `VirtualCard.OFFER_NOT_AVAILABLE`             | 该优惠已被兑换为一张不再活跃的卡。           | 不要用同一优惠重试；创建一个新的优惠。 |
| `VirtualCard.OFFER_NOT_TOKENIZATION_ELIGIBLE` | 该优惠的卡计划不支持钱包开通。             | 不要为此卡计划提供“添加到钱包”。   |
| `Auth.USER_REVOKED_DEVELOPER_ACCESS`          | 用户已撤销对你应用的 OAuth 访问。        | 引导用户重新完成 OAuth 授权。  |
| `Auth.INVALID_SCOPE`                          | 令牌不包含 `CREATE_VIRTUALCARD`。 | 在 OAuth 流程中请求该范围。   |
| `Generic.EXTERNAL_SERVICE_ERROR`              | 下游临时性问题。                    | 重试——该调用可安全重试。       |

## 常见问题

<AccordionGroup>
  <Accordion title="URL 是否包含卡号？">
    不包含。该 URL 仅携带短期有效的不透明查找 ID。一旦用户打开链接，凭据会在设备上安全交换。
  </Accordion>

  <Accordion title="同一个 URL 能重复使用吗？">
    不能。它是一次性使用。每次需要触发此流程时都应生成一个新的链接。
  </Accordion>

  <Accordion title="如果用户在桌面端怎么办？">
    他们会根据你选择的 `platform` 落到相应的回退（App Clip 启动器、Android 深链或 Fluz Web 应用）。要完成钱包开通，最终仍需在移动设备上打开该 URL。
  </Accordion>

  <Accordion title="iOS 和 Android 需要区别处理吗？">
    不需要。相同的 URL 适用于两者——Fluz 会自动按设备类型路由。
  </Accordion>
</AccordionGroup>

## 后续步骤

<CardGroup cols={2}>
  <Card title="发送卡片" icon="send" href="/features/send-cards">
    通过电子邮件、短信或分享链接分发虚拟卡。
  </Card>

  <Card title="设置虚拟卡 PIN" icon="key-round" href="/set-virtual-card-pin">
    在需要线下输入 PIN 的交易前，为符合条件的卡设置 PIN。
  </Card>
</CardGroup>
