> ## 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 账户到一张已发行且可消费的虚拟卡。你将注册一个应用、铸造带作用域的访问令牌，然后浏览卡计划，创建为你的用例配置的卡片，展示其详细信息，并观察其交易——全部在沙盒环境中进行，不涉及真实资金流转。

<Info>
  **先决条件**

  * 一个 **Fluz 账户** —— 你将在下方步骤 1–2 中创建 Staging API 凭据并铸造一个访问令牌。
  * 请求将发送到 **沙盒** GraphQL 端点。此处不会对真实卡片扣款——参见 [Staging vs. Live Environment](/concepts/environments)。
  * 每个 mutation 都需要唯一的 `idempotencyKey`（客户端生成的 UUID），以确保请求只被处理一次——参见 [Idempotency](/concepts/idempotency)。
</Info>

## 开始之前

除铸造令牌（步骤 2）外，每次调用都是一个发往单一 GraphQL 端点的 `POST` 请求，使用你的 Bearer 令牌进行认证：

<CodeGroup>
  ```bash Endpoint & headers theme={null}
  POST https://transactional-graph.staging.fluzapp.com/api/v1/graphql

  Authorization: Bearer <YOUR_USER_ACCESS_TOKEN>
  Content-Type: application/json
  ```

  ```bash Example request (cURL) theme={null}
  curl -X POST https://transactional-graph.staging.fluzapp.com/api/v1/graphql \
    -H "Authorization: Bearer <YOUR_USER_ACCESS_TOKEN>" \
    -H "Content-Type: application/json" \
    -d '{
      "query": "query GetVirtualCardOffers { getVirtualCardOffers { offerId programName rewardValue } }"
    }'
  ```
</CodeGroup>

<Tip>
  Staging 附带了可直接发行的**测试卡计划**，且你的沙盒账户已预先添加了一张用于资金支持的测试银行卡。查看 [Test Merchants](/test-merchants) 和 [Test Bank Cards](/test-bank-cards) 以获取完整沙盒数据集。
</Tip>

## 全流程

<Steps>
  <Step title="注册并登记应用" icon="user-plus">
    在 [fluz.app](https://fluz.app) 创建一个 Fluz 账户，然后打开 [Developer Console](https://uni.staging.fluzapp.com/developers) 并创建一个新的 **Staging** 应用。当凭据出现时，复制你的 `clientId` 和 `clientSecret` —— secret 仅显示一次。

    完整演练：[准备你的账户](/get-started/prepare-accounts)。
  </Step>

  <Step title="用凭据换取访问令牌" icon="key">
    使用你的应用凭据铸造一个短时效、带作用域的用户访问令牌。该调用发送至 OAuth 服务；之后的每次调用都使用返回的令牌作为 Bearer 凭据。

    <CodeGroup>
      ```bash Mint token (cURL) theme={null}
          curl -X POST https://oauth-service.fluzapp.com/graphql \
            -H "Content-Type: application/json" \
            -d '{
              "query": "mutation ($clientId: String!, $clientSecret: String!, $scopes: [Scope!]!) { generateUserAccessToken(clientId: $clientId, clientSecret: $clientSecret, scopes: $scopes) { accessToken expiresIn scopes } }",
              "variables": {
                "clientId": "<APPLICATION_CLIENT_ID>",
                "clientSecret": "<APPLICATION_CLIENT_SECRET>",
                "scopes": ["MANAGE_PAYMENT", "CREATE_VIRTUALCARD", "EDIT_VIRTUALCARD", "REVEAL_VIRTUALCARD", "PCI_COMPLIANCE"]
              }
            }'
      ```

      ```json Response theme={null}
          {
            "data": {
              "generateUserAccessToken": {
                "accessToken": "eyJhbGciOi...",
                "expiresIn": 3600,
                "scopes": ["MANAGE_PAYMENT", "CREATE_VIRTUALCARD", "EDIT_VIRTUALCARD", "REVEAL_VIRTUALCARD", "PCI_COMPLIANCE"]
              }
            }
          }
      ```
    </CodeGroup>

    保存返回的 `accessToken`，并在下方每个请求中以 `Authorization: Bearer <accessToken>` 发送。令牌为短时效（`expiresIn` 为秒）——请在服务器端铸造，并在过期前刷新。完整细节：[API credentials](/get-started/api-credentials)。

    <Tip>
      作用域控制令牌能做什么——仅包含你的流程所需内容：`MANAGE_PAYMENT` 为你的余额注资，`CREATE_VIRTUALCARD` 浏览计划并发行卡，`REVEAL_VIRTUALCARD` + `PCI_COMPLIANCE` 展示卡并拉取其交易，`EDIT_VIRTUALCARD` 之后用于锁卡、解锁或编辑卡片。
    </Tip>

    <Warning>
      切勿在浏览器或移动端暴露 `clientSecret`。请在服务器端铸造令牌，并仅转发令牌。
    </Warning>
  </Step>

  <Step title="为你的 Fluz 余额注资" icon="wallet">
    虚拟卡在被使用时从你的账户扣资——默认从你的 **Fluz 余额**（`FLUZ_BALANCE`）中扣除。请确保有足够的可用余额覆盖你计划设置的消费限额。你可以通过两种方式注资：

    * **手动**，通过 [sandbox Fluz 网站](https://uni.staging.fluzapp.com/manage-money)。
    * **以编程方式**，通过 `depositCashBalance` mutation。

    <Accordion title="通过 API 入金（depositCashBalance）" icon="banknote-arrow-down">
      使用 `getWallet` 获取资金来源 ID，然后入金：

      ```graphql theme={null}
            mutation depositCashBalance($input: DepositCashBalanceInput!) {
              depositCashBalance(input: $input) {
                balances {
                  cashBalance { availableBalance totalBalance pendingBalance }
                }
              }
            }
      ```

      ```json theme={null}
            {
              "input": {
                "idempotencyKey": "0284be6f-1a69-44f7-9da0-5b5edaf45d19",
                "amount": 200.00,
                "depositType": "CASH_BALANCE",
                "bankCardId": "<YOUR_TEST_BANK_CARD_ID>"
              }
            }
      ```

      [礼品卡快速入门](/quickstart) 对该步骤进行了完整讲解，包括通过 `getWallet` 获取支付方式 ID。
    </Accordion>

    <Note>
      更倾向于从关联银行账户为卡片提供资金？在创建卡片（步骤 5）时设置 `primaryFundingSource: BANK_ACCOUNT` 并传入 `bankAccountId` —— 无需预存余额。
    </Note>
  </Step>

  <Step title="浏览卡计划并选择一个 offer" icon="layers">
    每张虚拟卡都是基于一个**卡计划**（一个 “offer”）发行的：该计划决定网络、发卡行、奖励比率，以及你的卡片必须遵守的消费限额。使用 `getVirtualCardOffers` 获取你的账户可用的计划。

    <CodeGroup>
      ```graphql Query theme={null}
          query GetVirtualCardOffers {
            getVirtualCardOffers {
              offerId
              programName
              bin
              bankName
              rewardValue
              programLimits {
                dailyLimit
                weeklyLimit
                monthlyLimit
              }
            }
          }
      ```

      ```json Response theme={null}
          {
            "data": {
              "getVirtualCardOffers": [
                {
                  "offerId": "ed669305-5e43-40a0-9a25-7a15ed174628",
                  "programName": "Virtual Card",
                  "bin": "543210",
                  "bankName": "Bank of Examples",
                  "rewardValue": "1.5%",
                  "programLimits": {
                    "dailyLimit": "500.00",
                    "weeklyLimit": "2000.00",
                    "monthlyLimit": "5000.00"
                  }
                }
              ]
            }
          }
      ```
    </CodeGroup>

    Offers 按 `rewardValue` 排序，最高返现的计划靠前。你可以用可选的 `input` 进行过滤——`cardType`（`DEBIT` / `PREPAID`）、`cardNetwork`（`MASTERCARD` / `VISA`），以及 `cardBrandLocked`。完整参考：[Get Virtual Card Offers](/features/get-card-offers)。

    在沙盒中，这些测试计划始终可用：

    | Offer ID                               | Program Name                                   | Reward Value |
    | -------------------------------------- | ---------------------------------------------- | ------------ |
    | `ed669305-5e43-40a0-9a25-7a15ed174628` | Virtual Card                                   | 1.5%         |
    | `b23630f6-8d91-43df-84aa-a541e7691197` | Virtual Card - Mastercard Prepaid              | 1.5%         |
    | `592c394e-26cc-44ac-a145-a5f81301fe77` | Brand Locked Virtual Card - Mastercard Prepaid | 1.5%         |

    <Info>
      保存你想要的 `offerId` 并注意其 `programLimits` —— 你在下一步设置的 `spendLimit` 必须落在该计划对所选周期的限额之内。
    </Info>
  </Step>

  <Step title="为你的用例创建并配置卡片" icon="credit-card">
    使用 `createVirtualCard` 发行卡片。输入中的设置决定了如何将一张通用卡变成一张针对性的卡片——选择与你的场景匹配的模式：

    <Tabs>
      <Tab title="一次性购买">
        一张只用于一笔交易的卡。将 `spendLimit` 设置为购买金额，并设置 `lockCardNextUse: true`，这样卡片在第一次授权成功后会自动锁定——之后任何扣款都会被拒绝。

        ```json Variables theme={null}
                {
                  "input": {
                    "idempotencyKey": "07df5653-43a8-4532-9881-3ab5857bbe12",
                    "offerId": "ed669305-5e43-40a0-9a25-7a15ed174628",
                    "spendLimit": 150.00,
                    "lockCardNextUse": true,
                    "cardNickname": "Vendor payment — Acme invoice #1042"
                  }
                }
        ```
      </Tab>

      <Tab title="按月上限的订阅">
        一张专用于某个周期性扣款的卡。`spendLimitDuration: MONTHLY` 会在每月重置限额，因此超出上限的涨价或重复扣款会被自动拒绝。

        ```json Variables theme={null}
                {
                  "input": {
                    "idempotencyKey": "07df5653-43a8-4532-9881-3ab5857bbe13",
                    "offerId": "ed669305-5e43-40a0-9a25-7a15ed174628",
                    "spendLimit": 29.99,
                    "spendLimitDuration": "MONTHLY",
                    "cardNickname": "SaaS — analytics subscription"
                  }
                }
        ```
      </Tab>

      <Tab title="有预算且有时间盒的卡">
        一张用于有明确结束日期的项目或差旅的卡。`lockDate` 会在当天冻结该卡（默认是创建后 47 个月），并且禁用 `usePrepaymentBalance` / `useRewardsBalance` 让其**仅**从指定的消费账户扣款——资金来源可预测、单一，便于清晰对账。

        ```json Variables theme={null}
                {
                  "input": {
                    "idempotencyKey": "07df5653-43a8-4532-9881-3ab5857bbe14",
                    "offerId": "ed669305-5e43-40a0-9a25-7a15ed174628",
                    "spendLimit": 2000.00,
                    "lockDate": "2026-09-30",
                    "userCashBalanceId": "<SPEND_ACCOUNT_ID>",
                    "usePrepaymentBalance": false,
                    "useRewardsBalance": false,
                    "cardNickname": "Q3 conference travel"
                  }
                }
        ```
      </Tab>
    </Tabs>

    以上三种都运行同一个 mutation：

    <CodeGroup>
      ```graphql Mutation theme={null}
          mutation createVirtualCard($input: CreateVirtualCardInput!) {
            createVirtualCard(input: $input) {
              virtualCardId
              cardholderName
              virtualCardLast4
              expiryMonth
              expiryYear
              status
              cardType
              initialAmount
              usedAmount
              createdAt
            }
          }
      ```

      ```json Sample response theme={null}
          {
            "data": {
              "createVirtualCard": {
                "virtualCardId": "07df5653-43a8-4532-9881-3ab5857bbe11",
                "cardholderName": "xyz789",
                "virtualCardLast4": "7890",
                "expiryMonth": "12",
                "expiryYear": "27",
                "status": "ACTIVE",
                "cardType": "MULTI_USE",
                "initialAmount": 150.00,
                "usedAmount": 0,
                "createdAt": "2026-07-09T10:00:00Z"
              }
            }
          }
      ```
    </CodeGroup>

    #### 设置一览

    <ParamField body="spendLimit" type="Float" required>
      该卡可被扣款的最高金额——你只会为实际使用的金额付费。必须在所选周期的计划限额内。
    </ParamField>

    <ParamField body="spendLimitDuration" default="LIFETIME" type="VirtualCardSpendLimitDuration">
      限额如何重置。`LIFETIME` 限制总花费；`DAILY` / `WEEKLY` / `MONTHLY` 使其成为滚动预算——适合订阅和团队配额。
    </ParamField>

    <ParamField body="lockCardNextUse" default="false" type="Boolean">
      在首次成功使用后锁定该卡——用于一次性供应商付款的“虚拟一次性卡”模式。
    </ParamField>

    <ParamField body="lockDate" default="创建后 47 个月" type="String">
      卡片冻结的 `yyyy-mm-dd` 日期。将卡片与项目、行程或合同期进行时间盒约束。
    </ParamField>

    <ParamField body="primaryFundingSource" default="FLUZ_BALANCE" type="VirtualCardFundingSource">
      消费从何处扣除。`FLUZ_BALANCE` 使用你的预存余额；`BANK_ACCOUNT` 从关联账户扣款（需要 `bankAccountId`）。
    </ParamField>

    <ParamField body="usePrepaymentBalance / useRewardsBalance" default="true" type="Boolean">
      默认情况下，卡片也可从预付（礼品卡）和奖励余额扣款。将两者设为 `false` 可实现仅现金卡，只从指定的 `userCashBalanceId` 扣款——最利于会计核对。
    </ParamField>

    <ParamField body="memo / transactionCategory" type="String">
      附加到生成交易上的可选费用元数据——类别在首次使用时创建。参见 [Add Expense Details](/features/add-expense-details)。
    </ParamField>

    <Note>
      **账单地址：** 如果你的账户未存档账单地址，请传入 `billingAddress`（或已保存的 `userAddressId`）。必须是真实、可投递的**美国**地址——不支持邮政信箱（PO Box）——否则创建会以 `VC-0025` 失败。参见 [Address Formatting Requirements](/concepts/address-formatting-requirements)。
    </Note>

    <Info>
      保留响应中的 `virtualCardId` —— 你将用它在下一步展示卡片信息。如果创建失败，请查看 [Virtual Card Error Codes](/features/virtual-card-error-codes)。
    </Info>
  </Step>

  <Step title="展示卡片详情" icon="eye">
    创建响应会刻意省略敏感信息。使用 `revealVirtualCardByVirtualCardId` 获取完整的 PAN、CVV 和有效期——这是你（或你的用户）在结账时输入或添加到移动钱包的信息。

    <CodeGroup>
      ```graphql Mutation theme={null}
          mutation RevealVirtualCard($virtualCardId: UUID!) {
            revealVirtualCardByVirtualCardId(virtualCardId: $virtualCardId) {
              cardNumber
              expiryMMYY
              cvv
              cardHolderName
              billingAddress {
                streetAddress
                postalCode
                city
                state
              }
            }
          }
      ```

      ```json Variables theme={null}
          {
            "virtualCardId": "07df5653-43a8-4532-9881-3ab5857bbe11"
          }
      ```
    </CodeGroup>

    需要 `REVEAL_VIRTUALCARD` 作用域。

    <Warning>
      响应包含明文的完整卡号和 CVV。将其视为敏感持卡人数据——仅通过 TLS 传输，切勿记录日志，并仅向授权用户展示。
    </Warning>

    <Tip>
      大多数线上收银不需要 PIN —— 但如果你的用例需要（或你希望支持闪付），请参见 [Set Virtual Card PIN](/set-virtual-card-pin) 和 [Digital Wallet Push Provisioning](/digital-wallet-push-provisioning)，一键将卡添加到 Apple Pay 或 Google Pay。
    </Tip>
  </Step>

  <Step title="消费，然后观察活动" icon="receipt">
    在卡网络受理的任何场景使用已展示的卡片信息，前提是满足你设置的限额。然后使用 `getVirtualCardTransactions` 拉取该卡的活动以确认扣款——同一查询也可用于消费看板、对账和拒付监控。

    <CodeGroup>
      ```graphql Query theme={null}
          query GetVirtualCardTransactions {
            getVirtualCardTransactions(
              input: {
                virtualCardIds: ["07df5653-43a8-4532-9881-3ab5857bbe11"]
                filters: { transactionTypes: [PURCHASE, REFUND, DECLINE] }
                paginate: { limit: 20, offset: 0 }
              }
            ) {
              virtualCardId
              transactions {
                transactionDate
                transactionType
                transactionStatus
                transactionAmount
                merchantName
                mcc
              }
            }
          }
      ```

      ```json Sample response theme={null}
          {
            "data": {
              "getVirtualCardTransactions": [
                {
                  "virtualCardId": "07df5653-43a8-4532-9881-3ab5857bbe11",
                  "transactions": [
                    {
                      "transactionDate": "2026-07-09T14:22:31Z",
                      "transactionType": "PURCHASE",
                      "transactionStatus": "CLEARED",
                      "transactionAmount": 42.17,
                      "merchantName": "ACME OFFICE SUPPLY",
                      "mcc": 5943
                    }
                  ]
                }
              ]
            }
          }
      ```
    </CodeGroup>

    需要 `PCI_COMPLIANCE` 和 `REVEAL_VIRTUALCARD` 作用域。省略 `virtualCardIds` 可拉取账户上所有卡片的活动，并按日期范围过滤以实现对账单式视图。完整参考：[Get Virtual Card Transactions](/features/get-virtual-card-transactions)。

    <Accordion title="用完卡了？将其锁定（lockVirtualCard）" icon="lock">
      具有 `lockCardNextUse` 或 `lockDate` 的卡会自处理。要按需锁定其他任意卡：

      ```graphql theme={null}
            mutation {
              lockVirtualCard(input: { virtualCardId: "07df5653-43a8-4532-9881-3ab5857bbe11" }) {
                virtualCardId
                locked
              }
            }
      ```

      需要 `EDIT_VIRTUALCARD` 作用域。锁定是可逆的——参见 [Unlock Virtual Card](/features/unlock-virtual-card)。
    </Accordion>
  </Step>
</Steps>

## 大功告成 🎉

你已经发行了一张为特定任务而建的虚拟卡——选择计划、设置消费控制、展示卡片信息，并跟踪其活动。接下来，深入探索：

<CardGroup cols={2}>
  <Card title="编辑、锁定与管理卡片" icon="pencil" href="/features/edit-virtual-card">
    修改已有卡片的限额、昵称和锁定日期。
  </Card>

  <Card title="数字钱包与 PIN" icon="smartphone" href="/digital-wallet-push-provisioning">
    将卡一键推送至 Apple Pay / Google Wallet 并设置 PIN。
  </Card>

  <Card title="批量发行" icon="layers" href="/features/create-bulk-order">
    在单个订单中创建多达 10,000 张卡片。
  </Card>

  <Card title="将卡片发送给他人" icon="send" href="/features/send-cards">
    通过链接、电子邮件或短信分发卡片给收件人。
  </Card>
</CardGroup>

<Note>
  **想了解更多？** 通过 [support@fluz.app](mailto:support@fluz.app) 联系我们，与专家交流或申请演示。
</Note>
