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

# OAuth 应用概览

> 你的应用如何获得代表 Fluz 用户账户操作的权限——涉及的凭证、权限模型、令牌生命周期，以及下一步该读哪一页。

## 这里为什么需要 OAuth

你的应用已经可以在**你自己的账户**上完成 Fluz API 提供的一切能力。你用 API key 铸造一个令牌就可以调用——参见 [Authentication](/concepts/authentication) 和 [API credentials](/get-started/api-credentials)。

当账户不属于你时，你就需要一个 OAuth 应用。

当你想在客户的钱包上开卡、从他们关联的银行账户扣款、读取他们的交易，或向他们付款时，你需要该用户的明确授权——并且需要一种 Fluz 可验证、可限定范围、可过期、可撤销的形式。这就是 OAuth 应用的作用：**为你的软件注册一个身份，加上一套同意机制，把用户的批准转换成你服务器可使用的令牌。**

<Info>
  一旦你持有了以客户为作用域的令牌，API 是完全一致的。用你自己的令牌调用 `createVirtualCard` 会在你的钱包上创建卡；用客户令牌进行同样的 mutation 会在他们的钱包上创建。OAuth 改变的是\_你操作的账户归属\_，而不是你能做什么。
</Info>

***

## 你是否需要一个？

<Tabs>
  <Tab title="不需要——只操作你自己的账户">
    你在**自己的 Fluz 账户**内发卡、购买礼品卡或划转资金：拨付引擎、批量制卡、内部消费工具、ERP 同步。

    使用你的应用 API key 直接调用 `generateUserAccessToken`。不需要 OAuth 应用、无需同意页、无需重定向。从这里开始：[API credentials](/get-started/api-credentials)。
  </Tab>

  <Tab title="需要——操作客户账户">
    你在构建一个平台，**你的用户拥有各自的 Fluz 账户**，而你代表他们执行操作。

    你需要一个 OAuth 应用，并且每位用户需要为你的应用授权一次范围。然后你将持有一个可刷新、以客户为作用域的令牌。从这里开始：[Create an OAuth App](/create-an-o-auth-app)，然后参见 [Build a platform](/build-a-platform)。
  </Tab>

  <Tab title="你已经有一个了">
    你在嵌入一个 [Fluz Widget](/developers/widgets)。

    Widget **本质上就是** 一个 OAuth 应用——只不过它自带一个托管的前端用于同意步骤，而无需你构建重定向流程。此页的凭证、范围和令牌机制同样适用。参见 [Configure App Widget](/developers/configure-app-widget)。
  </Tab>
</Tabs>

***

## 三组凭证，各司其职

本节最常见的困惑在于，一个 Fluz 应用携带不止一对凭证，而且它们不可互换。

| 凭证                                   | 存放位置               | 用途                                                                                                        | 会离开你的服务器吗？                           |
| :----------------------------------- | :----------------- | :-------------------------------------------------------------------------------------------------------- | :----------------------------------- |
| **API Key** / **API Secret**         | 你的应用的 Overview 选项卡 | 标识你的\_应用程序\_。在你自己的账户上铸造令牌（`Authorization: Basic <API_KEY>`），并签发 widget 的预批准交易令牌。                          | 永不                                   |
| **Client ID** / **Client Secret**    | 你的应用的 Overview 选项卡 | 在\_授权服务器\_前标识你的应用。用于 authorize URL，以及在交换或刷新代码时使用（`Authorization: Basic base64(client_id:client_secret)`）。 | Client ID 是公开的；secret 永不             |
| **Access Token** / **Refresh Token** | 按用户、按授权返回          | 以特定用户、特定范围在其账户上执行操作。                                                                                      | 以 `Authorization: Bearer <token>` 发送 |

<Warning>
  这里的每个 secret 都能铸造权限。泄露 `apiSecret` 将让他人以你的平台身份签署交易；泄露 `client_secret` 将让他人以你的应用身份交换代码。两者都应仅保存在服务器端，勿进浏览器打包、移动端二进制、或版本控制。
</Warning>

***

## 权限模型

Fluz 在两个层级上强制权限，一个应用的有效访问是这两者的**交集**。

<Steps>
  <Step title="应用级授权——上限">
    在你的应用 **Permissions** 选项卡中设置。这是你的应用在任何用户无关的前提下所能请求的最大范围。若你在 authorize URL 中包含了未在此处启用的 scope，将被静默忽略——请求不会报错，但该 scope 不会被授予。

    某些 scope 由 Fluz 管理而非自助选择。`PCI_COMPLIANCE` 仅在应用级授予，授予给已证明符合 PCI DSS 合规的开发者，且在生成令牌时无法请求。
  </Step>

  <Step title="用户级授权——下限">
    由终端用户在同意页上设置。他们会看到你请求的 scopes——以可读的顶层分组呈现，而非原始枚举值——并予以批准。任何他们拒绝的内容都不会被授予。
  </Step>

  <Step title="两者都必须有效">
    在 `generateUserAccessToken` 处验证，而非在调用时验证。两类授权都必须存在且未过期。因此被撤销或失效的授权会表现为**令牌生成失败**，而不是流程中途的权限错误——这通常是当一个之前正常的集成突然失效时首要检查之处。
  </Step>
</Steps>

按能力划分的 scopes：

| 区域   | Scopes                                                                              |
| :--- | :---------------------------------------------------------------------------------- |
| 资金来源 | `LIST_PAYMENT`, `MANAGE_PAYMENT`                                                    |
| 存取款  | `MAKE_DEPOSIT`, `MAKE_WITHDRAW`                                                     |
| 礼品卡  | `LIST_OFFERS`, `PURCHASE_GIFTCARD`, `REVEAL_GIFTCARD`, `LIST_PURCHASES`             |
| 虚拟卡  | `CREATE_VIRTUALCARD`, `EDIT_VIRTUALCARD`, `REVEAL_VIRTUALCARD`, `CREATE_SHARE_LINK` |
| 卡数据  | `PCI_COMPLIANCE`（应用级，Fluz 管理）                                                       |

使用 `getApplicationScopes` 读取当前已授予的内容。完整参考：[Application Scopes](/application-scopes)。

<Note>
  **少即是多。** 更短的同意页转化更高，更窄的令牌在泄露时风险更小。只请求当前流程所需的范围，需要更多时再铸造新令牌。
</Note>

***

## 全流程生命周期

下面每一步都有对应的深入页面。此处是地图；那些页面是领地。

<Steps>
  <Step title="创建应用">
    在开发者控制台选择 **Browse templates** 并添加 **OAuth Integration** 模板。为其命名、副标题、描述——这三项将出现在用户的同意页上，因此写给人看，而不是写给你的问题跟踪器。

    → [Create an OAuth App](/create-an-o-auth-app)
  </Step>

  <Step title="进行配置">
    在 **Permissions** 选项卡选择你的 scope 上限。在 **OAuth** 选项卡设置你的 **Redirect URIs**（公开、无查询参数、数量不限）以及 **Webhook URLs**（每个可选订阅特定事件；未选任何事件的 URL 作为兜底）。在 **Overview** 添加头像和标志——没有它们同意页会显得不完整。

    → [Configure OAuth App](/configure-o-auth-app)
  </Step>

  <Step title="引导用户授权">
    重定向到 `/authorize`，携带 `response_type=code`、你的 `client_id`、一个已注册的 `redirect_uri`、以空格分隔的 `scopes` 列表，以及可选的 `state` 值（将原样返回给你）。

    → [Client-facing OAuth grant flow](/client-facing-o-auth-grant-flow)
  </Step>

  <Step title="接收代码">
    获批后，Fluz 会重定向到你的 `redirect_uri`，附带 `code` 以及你原始的 `state`。若配置有误，重定向会带上描述不匹配项的错误消息。
  </Step>

  <Step title="用代码交换令牌">
    调用 `/token/exchange`，携带该 `code` 和**完全相同的 `redirect_uri`**，并使用 `Authorization: Basic base64(client_id:client_secret)` 进行认证。你将获得 `accessToken`、`refreshToken`、过期时间戳，以及确认的 scope 数组。

    → [Exchanging an OAuth authorization code](/exchanging-an-o-auth-authorization-code)
  </Step>

  <Step title="刷新，不要重提权限">
    使用 `refresh_token` 调用 `/token/refresh`，并使用相同的 Basic 认证头。访问令牌有意设置为短期有效——大约十分钟——而刷新令牌大约可维持一个月。请在后台静默刷新；仅当刷新令牌本身过期或授权被撤销时，再让用户走一遍同意流程。

    → [Refreshing an OAuth accessToken](/refresh-o-auth-access-token)
  </Step>

  <Step title="上线">
    预发布与生产是独立的环境，拥有独立的应用与凭证。两者不会互通——你需要在生产主机上重新注册应用、重配重定向 URI 和 webhook 端点。

    → [Deploying to Production](/deploying-to-production)
  </Step>
</Steps>

***

## 易踩的规则

在开始前值得内化，因为这些问题往往悄无声息或表现含糊。

<AccordionGroup>
  <Accordion title="Redirect URI 必须精确匹配——而且要匹配两次">
    你发往 `/authorize` 的 `redirect_uri` 必须已在应用上注册，而发往 `/token/exchange` 的必须与 `/authorize` 使用的那一个字节级完全一致。结尾斜杠、`http` 与 `https`、主机大小写都算差异。不要在 URI 本身注册查询参数——使用 `state` 承载上下文。
  </Accordion>

  <Accordion title="未启用的 scopes 会被忽略，而不是被拒绝">
    如果你请求了在 Permissions 选项卡上未勾选的 scope，授权请求仍会成功——该 scope 会被丢弃。始终读取交换响应中的 `scope` 数组，并以它为准，而不是你的请求。
  </Accordion>

  <Accordion title="授权码一次性且短时有效">
    立刻在服务器端交换且只交换一次。如果你的重定向处理器可能被重放——例如用户刷新回调页、或链接预取——确保第二次尝试不会破坏状态。
  </Accordion>

  <Accordion title="Basic 认证是对二者拼接做 base64，而不是分别编码">
    `Authorization: Basic <base64(client_id + ":" + client_secret)>`。对拼接后的字符串编码。交换步骤的大多数集成失败都在这里。
  </Accordion>

  <Accordion title="`state` 是你唯一的回传通道">
    重定向是一次全新的浏览器导航。如果你需要知道是哪个用户、哪个流程、或要返回哪个页面，把签名的或可在服务器端查询的引用放进 `state`。不要放敏感信息——它会经过用户浏览器。
  </Accordion>

  <Accordion title="令牌失败通常是授权失败">
    如果 `generateUserAccessToken` 开始对昨天还正常的用户失败，在检查你的代码之前，先确认应用级授权或用户级授权是否过期或被撤销。
  </Accordion>
</AccordionGroup>

***

## OAuth 应用与 widget 的区别

两者都是应用。都使用上述权限模型。区别在于由谁来构建同意界面。

|                      | OAuth 应用          | Widget           |
| :------------------- | :---------------- | :--------------- |
| 同意 UI                | 你构建重定向流程          | Fluz 在你的页面用模态框渲染 |
| 用户是否离开你的网站           | 会，前往 `/authorize` | 不会               |
| 敏感数据（PAN、SSN、证件、PIN） | 由你处理，你需要纳入合规范围    | 由 Fluz 采集并加密     |
| 注册与 KYC              | 你来构建，或通过 API      | 已包含在流程中          |
| 呈现控制力                | 完全可控              | 限于品牌化            |
| 到首个可用流程的耗时           | 数天                | 数小时              |

你可以混合使用：通过 API 完成用户注册与 KYC，然后仅为同意与敏感信息采集打开 widget。混合模式参见 [Embedded Widgets](/developers/widgets)。

***

## 下一步

<CardGroup cols={2}>
  <Card title="创建一个 OAuth 应用" icon="plus" href="/create-an-o-auth-app">
    从 OAuth Integration 模板注册你的应用。
  </Card>

  <Card title="配置 OAuth 应用" icon="sliders" href="/configure-o-auth-app">
    Scopes、重定向 URI、webhooks、品牌化。
  </Card>

  <Card title="面向客户端的授权流程" icon="user-check" href="/client-facing-o-auth-grant-flow">
    构建 authorize URL 并处理回调。
  </Card>

  <Card title="交换授权码" icon="arrow-left-right" href="/exchanging-an-o-auth-authorization-code">
    将 code 转换为 access token 与 refresh token。
  </Card>

  <Card title="刷新访问令牌" icon="refresh-cw" href="/refresh-o-auth-access-token">
    在不重新提示用户的情况下保持授权。
  </Card>

  <Card title="部署到生产环境" icon="rocket" href="/deploying-to-production">
    在生产主机上重新注册并上线。
  </Card>
</CardGroup>

<Info>
  正在构建一个让你的每位客户都拥有 Fluz 账户的平台？[Build a platform](/build-a-platform) 端到端讲解整个模式，并且 [API Features](/features) 上的每项能力在已连接账户上都可同样使用。
</Info>
