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

# Secure Elements 概觀

> 在你的頁面中直接嵌入由 Fluz 代管的框架，向使用者顯示其自身的虛擬卡詳細資訊，同時卡片資料永不觸及你的伺服器或頁面上的 JavaScript。

<Warning>
  **僅限 Staging，且僅提供揭示功能。** Secure Elements 正在積極開發中。
  本頁與 [Card Reveal](/build-a-platform/card-reveal)
  頁面目前皆連線至 Fluz 的 staging 環境 — 生產環境主機尚未確認。本節僅文件化 **Card Reveal** 能力；實體卡收集（代碼化）尚未涵蓋。
</Warning>

## Secure Elements 是什麼

Secure Elements 是一個 JavaScript SDK，`@fluz/secure-elements`，可將由 Fluz 代管、相互隔離的框架直接掛載進你頁面上的容器元素中。該框架負責渲染卡片資料；你的頁面與伺服器只會持有一個短效、不透明的權杖，用於授權單一次的特定動作。

這是展示使用者自身卡片詳細資訊的第三種方式，與你已具備的兩種方式並列：

| 路徑                                                                                                    | 卡片資料可讀取的位置                | 需求條件                                                                                       |
| :---------------------------------------------------------------------------------------------------- | :------------------------ | :----------------------------------------------------------------------------------------- |
| [`revealVirtualCardByVirtualCardId`](/api-reference/mutations/reveal-virtual-card-by-virtual-card-id) | 你的自有伺服器，在 API 回應中         | `PCI_COMPLIANCE` — 僅授予已證明符合 PCI DSS 規範的開發者，且由 Fluz 管理的 scope。（個人/私人應用程式可豁免。）               |
| [Embedded Widget](/developers/widgets)                                                                | Fluz 代管的模態框，全螢幕覆蓋你的頁面     | 除了 OAuth 授權外無需其他條件 — Fluz 擁有整個介面，包含揭示流程。                                                   |
| **Secure Elements Card Reveal**                                                                       | 由 Fluz 代管的框架，內嵌於你自有版面配置之中 | 以你現有的 OAuth access token 鑄造的 client token。無需 `PCI_COMPLIANCE` 授權 — 你的頁面不會接收資料，因此不在其合規範圍之內。 |

<Note>
  若你已經在所有情境下使用 [Embedded Widget](/developers/widgets)，就不需要這個工具。Secure Elements 適用於無頭或 API 駆動的整合，仍需向使用者顯示 PAN、到期日與 CVV，但不想開啟完整小工具模態框，或不打算追求 `PCI_COMPLIANCE`。
</Note>

## 運作方式

```
Your backend  →  mint client token  →  Your frontend  →  SDK mounts Fluz frame  →  callback with result
```

<Steps>
  <Step title="你的後端鑄造 client token" icon="server">
    將你現有的 [Fluz OAuth access
    token](/build-a-platform/oauth-applications-overview) 交換成短效的
    **client token**，其範圍限於單次揭示。
  </Step>

  <Step title="你的前端掛載框架" icon="app-window">
    將 client token 交給 `@fluz/secure-elements`，它會把 Fluz 代管的框架掛載到你提供的容器中 — 直接內嵌於頁面，而非模態框。
  </Step>

  <Step title="SDK 透過回呼回報結果" icon="reply">
    你的頁面永不讀取原始卡片資料。它只能接收成功、錯誤或掛載事件。
  </Step>
</Steps>

## 先決條件

* 你的應用程式已向 Fluz 註冊，且在你的 access token 上啟用了 `CREATE_VIRTUALCARD` scope。
* 你擁有狀態為 `ACTIVE`、且屬於欲揭示之帳戶的虛擬卡 id，將在鑄造 client token 時一併傳入。

<Warning>
  **在動手寫任何程式碼前，請先請 Fluz 將你的來源網域加入允許清單。** 若頁面來源未事先獲 Fluz 核准，框架將拒絕渲染 — 目前沒有自助開關，若延後處理可能會卡關。

  請寄信至 [partnerships@fluz.app](mailto:partnerships@fluz.app)（或聯繫你的客戶經理，如有）並提供你的**應用程式名稱或 ID**，以及需要核准的每個**來源網域** — 包含每個你用於開發的 `http://localhost:PORT`、以及 staging 與 production 網域。Fluz 會在後端加入允許清單；完成後你這端無需額外設定。
</Warning>

## 環境

| 環境         | 基底 URL                            |
| :--------- | :-------------------------------- |
| Staging    | `https://staging.secure.fluz.app` |
| Production | `https://secure.fluz.app`         |

<Note>
  在 Fluz 與處理方的整合完成前，Staging 的揭示目前會回傳模擬結果。請使用 staging 以端到端驗證你的整合 — 生產可用性將另行確認。
</Note>

`frameHostOrigin` 在 `createCardViewer` 中為選填 — 省略時預設為生產環境（`https://secure.fluz.app`）。若要指向 staging，請明確傳入。僅接受上述兩個精確的來源；傳入其他值會在呼叫 `createCardViewer` 時立即擲出 `FluzElementsError`（`error.code === "INVALID_FRAME_HOST_ORIGIN"`），在任何框架掛載前就中止。

## 載入 SDK

`@fluz/secure-elements` 不會發佈到 npm — 請以 `<script>` 標籤從 Fluz 的 CDN 載入瀏覽器全域（IIFE）版本。它會暴露一個 `FluzSecureElements` 全域：

```html theme={null}
<script src="https://secure-cdn-staging.fluz.app/secure-elements/v0.1.0/index.global.js"></script>
<script>
  const { createCardViewer } = FluzSecureElements;

  const viewer = createCardViewer({
    /* ... */
  });
</script>
```

本頁與 [Card Reveal](/build-a-platform/card-reveal) 上的每個程式碼範例皆假設你已載入上述的 script 並從 `FluzSecureElements` 解構所需成員。

每次發佈都會提供不可變的鎖定版本路徑（`.../v0.1.0/index.global.js`）以及一個浮動的 `.../latest/index.global.js`，永遠指向最新版本。除原型外，請鎖定至特定版本 — `latest` 可能在未通知的情況下變動。

<Info>
  目前僅 staging 的 CDN 主機上線（`secure-cdn-staging.fluz.app`）。
  生產環境的託管將與生產 API 可用性一併確認。
</Info>

## 鑄造 client token

你的後端使用你已透過標準 [OAuth 授權流程](/client-facing-o-auth-grant-flow) 取得的 Fluz OAuth access token 呼叫此端點。**切勿將該 access token 傳至瀏覽器** — 僅將此端點回傳的 `clientToken` / `loadToken` 配對提供給前端。

```text theme={null}
POST {baseUrl}/v1/client-token
Authorization: Bearer <your Fluz OAuth access token>
Content-Type: application/json

{
  "purpose": "reveal",
  "virtualCardId": "<uuid>"
}
```

```json theme={null}
{ "clientToken": "<token>", "loadToken": "<token>", "expiresIn": 300 }
```

成功鑄造會回傳 `201`。兩個權杖皆是單一用途且短效 — 每次揭示都需鑄造一組新配對。`clientToken` 用於授權實際的揭示（有效期為 `expiresIn` 秒，預設 300）；`loadToken` 的範圍更嚴格（60 秒），因為它會出現在 URL 中 — 參見 [Card Reveal](/build-a-platform/card-reveal) 的說明 — 且除了載入框架外，將在其他情境被拒絕。直接將兩者傳入 `createCardViewer`，並切勿自行將 `clientToken` 放入 URL — SDK 已幫你避免這點。

<Accordion title="錯誤回應">
  | 狀態碼 | 錯誤                         | 意義                                            |
  | :-- | :------------------------- | :-------------------------------------------- |
  | 400 | `invalid_purpose`          | 缺少或無效的 `purpose`                              |
  | 400 | `virtual_card_id_required` | 針對揭示權杖缺少 `virtualCardId`                      |
  | 401 | `unauthorized`             | 缺少 access token                               |
  | 401 | `invalid_token`            | access token 驗證失敗（格式錯誤、逾期、簽章不正確）              |
  | 403 | `insufficient_scope`       | access token 缺少所需的 scope                      |
  | 403 | `app_not_registered`       | 你的應用程式尚未註冊 — 請聯絡 Fluz                         |
  | 403 | `forbidden`                | 找不到卡片，或該卡片不屬於此使用者                             |
  | 429 | `rate_limited`             | 此使用者的 client-token 請求過多 — 參閱 `Retry-After` 標頭 |
  | 500 | `internal_error`           | 非預期的伺服器錯誤                                     |
</Accordion>

## 欄位樣式設定

`createCardViewer` 可接受選填的 `style` 物件，將套用於其掛載的每個欄位：

```js theme={null}
const viewer = createCardViewer({
  clientToken,
  loadToken,
  frameHostOrigin: "https://staging.secure.fluz.app",
  style: {
    color: "#1a1a1a",
    fontSize: "16px",
    fontWeight: "600",
    fontFamily: "Inter",
  },
});
```

`style` 會在任何內容傳至框架前先行驗證。若某個值不符合以下文件規範，`await viewer.mount(...)` 會以 `FluzElementsError`（`error.code === "INVALID_STYLE"`）拒絕 — 若你本身允許可配置的樣式輸入，請以 try/catch 包覆 `mount()` 呼叫。

| 屬性           | 可接受值                                                                |
| :----------- | :------------------------------------------------------------------ |
| `color`      | 十六進位色碼（`#1a1a1a` 或 `#111`）、`rgb(r, g, b)`，或 CSS 命名色彩（`"slategray"`） |
| `fontSize`   | 以 `px`、`pt`、`em`、或 `rem` 結尾的數值（例如 `"16px"`）                         |
| `fontWeight` | `"normal"`、`"bold"`，或 `"100"` 到 `"900"` 的 100 倍數                    |
| `fontFamily` | 精確的系統字型名稱或 Google Font 家族名稱 — 見下方說明                                 |

`fontFamily` 必須與以下兩個允許清單之一**完全、區分大小寫地匹配**：

* **系統字型** — 常見的作業系統/安全網頁字型（`system-ui`、`-apple-system`、`Helvetica Neue`、`Arial`、`Georgia`、`Menlo`，以及通用關鍵字 `monospace` / `serif` / `sans-serif` 等）。這些會立即渲染，無需網路請求。
* **Google Fonts** — 任何來自 Google Fonts 目錄的家族（`"Roboto"`、`"Inter"`、`"IBM Plex Mono"` 等），須與 Google 所列之名稱完全相同。SDK 會替你載入字型 — 你不需要 `<link>` 標籤或 `@font-face` 規則。

<Note>
  Google Font 會在欄位掛載之後取用，而非事先打包，因此在冷快取的短暫時間內，欄位會先以瀏覽器的後備字型渲染，再切換為你設定的字型。系統字型則不會有此延遲。
</Note>

若你想自行驗證字型選擇或建立字型挑選器，兩份清單皆有匯出：

```js theme={null}
const { SYSTEM_FONTS, GOOGLE_FONTS, isAllowedFontFamily } = FluzSecureElements;

isAllowedFontFamily("Roboto"); // true
isAllowedFontFamily("roboto"); // false -- exact, case-sensitive match required
```

## 內容安全政策（CSP）

若你的頁面設定了 CSP，請允許你所使用的框架主機：

```text theme={null}
frame-src https://staging.secure.fluz.app;  # or https://secure.fluz.app in production
```

## 安全模型

* 你的 OAuth access token 永不離開你的伺服器。
* 前端持有的 client token 是不透明且單一用途 — 它不攜帶任何卡片資料，且無法重播至其他卡片或動作。
* 卡片資料只會在 Fluz 代管的框架內可讀，並與你頁面自身的 JavaScript 隔離。每個設定的欄位都會以獨立的沙箱（`allow-scripts allow-same-origin allow-forms`）、`referrerPolicy="no-referrer"` 的 iframe 掛載 — SDK 絕不會把卡片資料放在其外的 DOM 中。
* 框架僅會在你已事先向 Fluz 登記的來源網域中渲染。

## 下一步

<CardGroup cols={2}>
  <Card title="卡片揭示" icon="eye" href="/build-a-platform/card-reveal">
    建立卡片檢視器、掛載它，並控制要揭示的欄位。
  </Card>

  {" "}

  <Card title="即時示範" icon="play" href="https://demo.secure.fluz.app/">
    觀看在 staging 上執行的卡片檢視器，包含完整揭示、僅揭示 CVV，以及遮罩模式。
  </Card>

  {" "}

  <Card title="範例整合" icon="github" href="https://github.com/fluz-app/secure-elements-examples">
    可執行的純 HTML 與 React 範例，皆呼叫真實的 staging 基礎設施。
  </Card>

  <Card title="OAuth 應用程式" icon="handshake" href="/build-a-platform/oauth-applications-overview">
    如何取得你要用來交換 client token 的 access token。
  </Card>
</CardGroup>
