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

# 傳送卡片給他人

> 產生託管虛擬卡連結、觀察收件者領取並管理連結生命週期——在沙盒中端到端完成。

本快速入門將帶你走過完整的「傳送卡片」生命週期。你將建立一個 Staging 應用程式、鑄造具範圍的 Bearer 權杖、選擇卡片方案、擷取已注資的消費帳戶、產生託管虛擬卡連結、體驗收件者啟用流程、驗證核發，然後停用未使用的連結。

完成後，你將成功執行所有公開的「傳送卡片」操作：

* `generateVCShareLinks`
* `getVCShareLinks`
* `deactivateVCShareLinks`

—全部在沙盒中進行，不會移動任何真實客戶資金。

<Info>
  **先決條件**

  * 一個 **Fluz 帳號**——你將在下方步驟 1–2 建立 Staging API 認證並鑄造具範圍的存取權杖。
  * 請將請求送至 **沙盒** GraphQL 端點。託管收件者連結使用標準的 Fluz 啟用體驗，但所有 API 操作皆使用你的 Staging 環境。
  * 你的帳號必須啟用 **Send Cards**（`send_virtual_cards_enabled`），否則每個「傳送卡片」操作都會回傳權限錯誤。
  * 本快速入門使用已注資的 **Spend Account** 作為資金來源。卡片在被**領取時**注資，而非在產生連結時。
</Info>

## 開始之前

除了鑄造權杖（步驟 2）以外，本指南中的每個請求都會使用你的 Bearer 存取權杖，發送至 Fluz GraphQL API。

<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 { offerId programName rewardValue } }"
    }'
  ```
</CodeGroup>

<Tip>
  以下每個 GraphQL 操作都使用此端點與你的 Bearer 權杖。唯一的例外是步驟 2，該步驟會透過 OAuth 服務以你的應用程式認證交換取得存取權杖。
</Tip>

## 完整流程

<Steps>
  <Step title="建立 Staging 應用程式" icon="user-plus">
    建立一個 Fluz 帳號，然後開啟開發者主控台並建立一個 **Staging** 應用程式。

    當你的應用程式建立後，你將取得：

    * `clientId`
    * `clientSecret`

    請將兩個值妥善保存。你的 `clientSecret` 只會顯示一次。

    若你尚未建立 Staging 應用程式，請參考[準備你的帳戶](/get-started/prepare-accounts)。
  </Step>

  <Step title="以具範圍的 Bearer 權杖交換你的認證" icon="key">
    將你的應用程式認證送至 OAuth 服務，以產生短期有效的使用者存取權杖。

    這個權杖將授權後續每一個「傳送卡片」操作。

    <CodeGroup>
      ```bash Mint access 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":[
              "CREATE_SHARE_LINK",
              "LIST_PAYMENT"
            ]
          }
      }'
      ```

      ```json Response theme={null}
      {
        "data": {
          "generateUserAccessToken": {
            "accessToken": "eyJhbGciOi...",
            "expiresIn": 3600,
            "scopes": [
              "CREATE_SHARE_LINK",
              "LIST_PAYMENT"
            ]
          }
        }
      }
      ```
    </CodeGroup>

    儲存回傳的 `accessToken`。

    你將以以下方式使用它：

    ```http theme={null}
    Authorization: Bearer <YOUR_USER_ACCESS_TOKEN>
    ```

    用於後續每個請求。

    <Info>
      `CREATE_SHARE_LINK` 會授權所有「傳送卡片」操作。

      本快速入門也要求 `LIST_PAYMENT`，以便你擷取用於資助託管卡片的 Spend Account。
    </Info>

    <Warning>
      **切勿在瀏覽器或行動應用程式中暴露你的** `clientSecret`。\*\*

      請在伺服端產生 Bearer 權杖，並僅將存取權杖轉發給你的用戶端。
    </Warning>
  </Step>

  <Step title="擷取已注資的 Spend Account" icon="wallet">
    託管虛擬卡由你的其中一個 **Spend Accounts** 提供資金。

    與一般虛擬卡不同，**在產生連結時不會預留資金。**

    相反地，僅在收件者成功領取卡片時，所選的 Spend Account 才會被扣款。

    擷取你可用的 Spend Accounts。

    <CodeGroup>
      ```graphql Query theme={null}
      query GetSpendAccounts {
        getSpendAccounts {
          userCashBalanceId
          nickname
          availableBalance
          currency
        }
      }
      ```

      ```json Response theme={null}
      {
        "data": {
          "getSpendAccounts": [
            {
              "userCashBalanceId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
              "nickname": "Primary Spend Account",
              "availableBalance": 5000,
              "currency": "USD"
            }
          ]
        }
      }
      ```
    </CodeGroup>

    儲存 `userCashBalanceId`。

    你在產生託管卡片連結時會提供此值。

    <Note>
      所選的 Spend Account 必須屬於你的帳戶，且在**收件者領取卡片時**必須有足夠資金可用。若在領取時可用餘額不足，卡片核發將失敗。
    </Note>
  </Step>

  <Step title="選擇卡片方案" icon="layers">
    每張託管卡都是根據一個虛擬卡**優惠**所核發。

    該優惠決定了發卡方案、可用回饋，以及套用至每張產生卡片的限制。

    擷取你帳戶可用的優惠。

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

      ```json Response theme={null}
      {
        "data": {
          "getVirtualCardOffers": [
            {
              "offerId": "11111111-2222-3333-4444-555555555555",
              "programName": "Virtual Card",
              "rewardValue": "1.5%",
              "programLimits": {
                "dailyLimit": 500,
                "weeklyLimit": 2000,
                "monthlyLimit": 5000
              }
            }
          ]
        }
      }
      ```
    </CodeGroup>

    儲存你想要核發之方案的 `offerId`。

    <Info>
      **所選優惠必須：**

      * 為啟用狀態
      * 已啟用分享功能

      若因優惠不符合「傳送卡片」資格而導致產生失敗，請與你的 Fluz 代表確認哪些優惠已啟用託管分享。
    </Info>
  </Step>

  <Step title="產生兩個託管卡片連結" icon="link">
    你現在可以建立託管「傳送卡片」連結了。

    每個產生的連結代表**一張未來的虛擬卡**。

    此階段：

    * 尚未核發任何卡片。
    * 尚未提領任何資金。
    * 每個連結都以 `PENDING` 狀態開始。

    僅在收件者**領取連結**時，所選的 Spend Account 才會被扣款。

    在本快速入門中，我們將產生**兩個**連結：

    * **連結 A** —— 你將以收件者身分領取它。
    * **連結 B** —— 你將保留未領取，以便稍後撤銷。

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

      ```json Variables theme={null}
      {
        "input": {
          "cardLimit": 25,
          "offerId": "<OFFER_ID>",
          "quantity": 2,
          "daysUntilExpiration": 14,
          "shareMethod": "GENERATE_URL",
          "userCashBalanceId": "<USER_CASH_BALANCE_ID>"
        }
      }
      ```

      ```json Response theme={null}
      {
        "data": {
          "generateVCShareLinks": {
            "shareLinks": [
              "https://fluz.app/virtual-prepaid-card/3f8ac...c1",
              "https://fluz.app/virtual-prepaid-card/9b2dd...77"
            ]
          }
        }
      }
      ```
    </CodeGroup>

    回應會為每張產生的卡片回傳一個託管啟用 URL。

    請儲存兩個 URL。

    我們將分別稱為：

    * **連結 A**
    * **連結 B**

    在本快速入門的其餘部分都會用到它們。

    ### 瞭解產生設定

    <ParamField body="cardLimit" type="Int" required>
      每張卡在被領取時載入的金額。

      每張產生的卡片都會有自身獨立的限額。
    </ParamField>

    <ParamField body="offerId" type="UUID" required>
      要核發的託管虛擬卡方案。

      該優惠必須為啟用狀態，且已啟用「傳送卡片」。
    </ParamField>

    <ParamField body="quantity" type="Int" required>
      要產生的託管連結數量。

      每個請求的數量都會建立一個分享請求與一個託管 URL。
    </ParamField>

    <ParamField body="shareMethod" type="ShareMethodType" required>
      控制收件者如何收到其連結。

      * `GENERATE_URL` 回傳託管 URL 供你自行發送。
      * `EMAIL` 會自動以電子郵件寄送給收件者。
      * `PHONE_NUMBER` 會以 SMS 簡訊寄送給收件者。
    </ParamField>

    <ParamField body="userCashBalanceId" type="UUID" required>
      為每張產生卡片提供資金的 Spend Account。

      雖然此欄位在 GraphQL 結構中看似選填，但實務上為必填。
    </ParamField>

    <ParamField body="daysUntilExpiration" type="Int">
      收件者可用來領取託管連結的時間長度。

      若省略，則使用方案預設值。

      所得到的到期日也將成為已核發卡片的鎖定日期。
    </ParamField>

    <Accordion title="改用 Email 或 SMS 投遞卡片" icon="mail">
      若你不想自行分送託管 URL，Fluz 可將每位收件者的啟用連結直接寄送給他們。

      ### 電子郵件

      ```json theme={null}
      {
        "input": {
          "cardLimit": 25,
          "offerId": "<OFFER_ID>",
          "quantity": 2,
          "shareMethod": "EMAIL",
          "recipientListEmail": [
            "alice@example.com",
            "bob@example.com"
          ],
          "userCashBalanceId": "<USER_CASH_BALANCE_ID>"
        }
      }
      ```

      ### SMS 簡訊

      ```json theme={null}
      {
        "input": {
          "cardLimit": 25,
          "offerId": "<OFFER_ID>",
          "quantity": 2,
          "shareMethod": "PHONE_NUMBER",
          "recipientListPhone": [
            "+18883606660",
            "+18885551234"
          ],
          "userCashBalanceId": "<USER_CASH_BALANCE_ID>"
        }
      }
      ```

      收件者清單長度**必須與** `quantity` **完全相等**。

      若不相符，驗證將失敗且**不會建立任何連結**。

      電話號碼必須：

      * 包含國碼
      * 不含空白
      * 以字串提供

      範例：

      ```text theme={null}
      +18883606660
      ```
    </Accordion>

    <Warning>
      **產生託管連結不會預留資金。**

      若在收件者領取卡片時，所選的 Spend Account 可用餘額不足，卡片核發將失敗。
    </Warning>

    <Info>
      **產生回應刻意只回傳託管 URL。**

      它**不會**回傳：

      * `shareRequestBatchId`
      * `shareRequestDisplayId`

      你將在下一步中擷取它們。
    </Info>
  </Step>

  <Step title="擷取已產生的分享請求" icon="list-checks">
    雖然你已經擁有託管 URL，但通常你也會需要底層的分享請求記錄。

    其中包含：

    * 生命週期狀態
    * 批次識別碼
    * 顯示 ID
    * 已核發的虛擬卡 ID
    * 到期資訊

    在產生後立即擷取你尚未處理的分享請求。

    <CodeGroup>
      ```graphql Query theme={null}
      query GetVCShareLinks($input: GetVCShareLinksInput!) {
        getVCShareLinks(input: $input) {
          shareRequestBatchId
          shareRequestDisplayId
          shareObjectStatus
          linkExpirationDate
          virtualCardId
          linkUrl
        }
      }
      ```

      ```json Variables theme={null}
      {
        "input": {
          "shareObjectStatuses": [
            "PENDING"
          ]
        }
      }
      ```

      ```json Response theme={null}
      {
        "data": {
          "getVCShareLinks": [
            {
              "shareRequestBatchId": "BATCH123",
              "shareRequestDisplayId": "SR-000001",
              "shareObjectStatus": "PENDING",
              "virtualCardId": null,
              "linkExpirationDate": "2026-08-01T00:00:00Z",
              "linkUrl": "https://fluz.app/virtual-prepaid-card/3f8ac...c1"
            },
            {
              "shareRequestBatchId": "BATCH123",
              "shareRequestDisplayId": "SR-000002",
              "shareObjectStatus": "PENDING",
              "virtualCardId": null,
              "linkExpirationDate": "2026-08-01T00:00:00Z",
              "linkUrl": "https://fluz.app/virtual-prepaid-card/9b2dd...77"
            }
          ]
        }
      }
      ```
    </CodeGroup>

    將每個回傳的 `linkUrl` 與產生時回傳的 URL 對應起來。

    請儲存：

    * 共用的 `shareRequestBatchId`
    * 兩個 `shareRequestDisplayId` 值

    你稍後將使用它們來停用未使用的連結。

    此時兩個連結應為：

    ```text theme={null}
    Status: PENDING
    Virtual Card ID: null
    ```

    這確認了：

    * 連結已成功建立
    * 尚無收件者領取
    * 尚未核發任何虛擬卡
  </Step>

  <Step title="以收件者身分領取其中一個連結" icon="smartphone">
    在瀏覽器中開啟**連結 A**。

    這正是你的收件者所看到的體驗。

    託管流程引導收件者完成卡片啟用，而不需要任何 API 串接。

    在啟用過程中，收件者會：

    1. 開啟託管啟用頁面。
    2. 登入或建立 Fluz 帳號。
    3. 完成身分驗證。
    4. 完成雙重驗證。
    5. 若尚未留存，新增帳單地址。
    6. 建立卡片 PIN 碼。
    7. 取得其託管虛擬卡。

    僅在最後一步之後，Fluz 才會：

    * 核發虛擬卡
    * 由你的 Spend Account 注資
    * 指派給收件者

    收件者成為**僅該卡片**的授權持有人。

    他們**不會**取得以下權限：

    * 你的 Fluz 帳號
    * 你的 Spend Accounts
    * 你的餘額
    * 任何其他已產生的卡片

    一旦核發，收件者即可：

    * 檢視卡片
    * 線上消費
    * 加入 Apple Pay 或 Google Wallet（於支援地區）
    * 檢視後續交易

    <Info>
      **請保持連結 B 不動。**

      我們將在下一節示範如何撤銷連結。
    </Info>
  </Step>

  <Step title="驗證卡片已核發" icon="badge-check">
    在收件者領取**連結 A**之後，再次擷取分享請求。

    這次你會看到已領取的連結從 `PENDING` 轉為 `ISSUED`。

    <CodeGroup>
      ```graphql Query theme={null}
      query GetVCShareLinks($input: GetVCShareLinksInput!) {
        getVCShareLinks(input: $input) {
          shareRequestDisplayId
          shareObjectStatus
          virtualCardId
          linkUrl
        }
      }
      ```

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

      ```json Response theme={null}
      {
        "data": {
          "getVCShareLinks": [
            {
              "shareRequestDisplayId": "SR-000001",
              "shareObjectStatus": "ISSUED",
              "virtualCardId": "c8dbe6d8-2f2f-4c90-8d7e-15ef5b06e387",
              "linkUrl": "https://fluz.app/virtual-prepaid-card/3f8ac...c1"
            },
            {
              "shareRequestDisplayId": "SR-000002",
              "shareObjectStatus": "PENDING",
              "virtualCardId": null,
              "linkUrl": "https://fluz.app/virtual-prepaid-card/9b2dd...77"
            }
          ]
        }
      }
      ```
    </CodeGroup>

    你的兩個連結現在應處於不同的生命週期狀態。

    | 連結       | 預期狀態      | 意義                 |
    | -------- | --------- | ------------------ |
    | **連結 A** | `ISSUED`  | 收件者已成功領取卡片且已建立虛擬卡。 |
    | **連結 B** | `PENDING` | 該連結尚未被領取。          |

    出現 `virtualCardId` 表示卡片核發已成功完成。

    <Accordion title="瞭解「傳送卡片」狀態" icon="info">
      每個託管「傳送卡片」都會經歷四種生命週期狀態之一。

      | 狀態        | 意義                  |
      | --------- | ------------------- |
      | `PENDING` | 託管連結已產生，但尚未被領取。     |
      | `ISSUED`  | 收件者已成功領取連結並取得虛擬卡。   |
      | `USED`    | 已核發的卡片至少完成一筆交易。     |
      | `EXPIRED` | 託管連結自然到期，或在被領取前被停用。 |

      只有 `PENDING` 狀態的連結可以被停用。

      一旦卡片達到 `ISSUED`，停用原始連結**不會**撤銷該卡片。
    </Accordion>
  </Step>

  <Step title="停用未使用的連結" icon="lock">
    假設第二位收件者不再需要卡片，或是不小心產生了一批連結。

    你可以使用以下任一方式撤銷任何**未被領取**的託管連結：

    * `shareRequestBatchIds`
    * `shareRequestDisplayIds`

    在本快速入門中，我們將使用其顯示 ID 僅停用**連結 B**。

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

      ```json Variables theme={null}
      {
        "input": {
          "shareRequestDisplayIds": [
            "SR-000002"
          ]
        }
      }
      ```

      ```json Response theme={null}
      {
        "data": {
          "deactivateVCShareLinks": "1 share requests successfully deactivated!"
        }
      }
      ```
    </CodeGroup>

    停用會立即阻止該託管連結被領取。

    若之後收件者開啟該連結，他們將看到到期或已撤銷的體驗，而非啟用流程。

    <Warning>
      停用僅影響**未被領取**的連結。

      若收件者已領取卡片（`ISSUED` 或 `USED`），則無法再透過託管連結撤銷。

      若要停止已核發卡片的消費，請使用適當的虛擬卡生命週期控制，例如[鎖定虛擬卡](/features/lock-virtual-card)。
    </Warning>
  </Step>

  <Step title="確認最終生命週期" icon="clipboard-check">
    最後再擷取一次分享請求。

    <CodeGroup>
      ```graphql Query theme={null}
      query GetVCShareLinks($input: GetVCShareLinksInput!) {
        getVCShareLinks(input: $input) {
          shareRequestDisplayId
          shareObjectStatus
          virtualCardId
        }
      }
      ```

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

      ```json Response theme={null}
      {
        "data": {
          "getVCShareLinks": [
            {
              "shareRequestDisplayId": "SR-000001",
              "shareObjectStatus": "ISSUED",
              "virtualCardId": "c8dbe6d8-2f2f-4c90-8d7e-15ef5b06e387"
            },
            {
              "shareRequestDisplayId": "SR-000002",
              "shareObjectStatus": "EXPIRED",
              "virtualCardId": null
            }
          ]
        }
      }
      ```
    </CodeGroup>

    你現在已經演練完整的「傳送卡片」生命週期。

    | 連結       | 最終狀態      | 結果             |
    | -------- | --------- | -------------- |
    | **連結 A** | `ISSUED`  | 已成功被領取並核發給收件者。 |
    | **連結 B** | `EXPIRED` | 已在被領取前成功撤銷。    |

    至此，你已成功使用三個公開的「傳送卡片」操作：

    * ✅ `generateVCShareLinks`
    * ✅ `getVCShareLinks`
    * ✅ `deactivateVCShareLinks`
  </Step>
</Steps>

## 大功告成 🎉

你已完成完整的託管「傳送卡片」生命週期——從產生、收件者啟用、生命週期追蹤到連結撤銷。

在此過程中你：

* 產生託管虛擬卡連結。
* 選擇用於資助收件者卡片的 Spend Account。
* 擷取並追蹤分享請求記錄。
* 以收件者身分領取一張託管卡。
* 驗證從 `PENDING` 轉為 `ISSUED` 的狀態變化。
* 撤銷未使用的託管連結。
* 確認最終的 `EXPIRED` 狀態。

接下來你可以探索更多進階的「傳送卡片」工作流程。

<CardGroup cols={2}>
  <Card title="Send Cards 概觀" icon="send" href="/features/send-cards">
    收件者體驗、方案規則、生命週期狀態與完整錯誤參考。
  </Card>

  <Card title="產生分享連結" icon="link" href="/features/generate-share-links">
    每個「傳送卡片」操作的詳細 API 參考。
  </Card>

  <Card title="取得 Spend Accounts" icon="wallet" href="/features/get-spend-accounts">
    擷取並管理用於資助託管卡片的 Spend Accounts。
  </Card>

  <Card title="管理虛擬卡" icon="credit-card" href="/features/lock-virtual-card">
    在卡片核發給收件者後進行鎖定與管理。
  </Card>
</CardGroup>

<Note>
  **想了解更多？**

  請聯絡 [support@fluz.app](mailto:support@fluz.app) 與我們的專家交流或申請示範。
</Note>
