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

# 通过证件验证

> 请求一个托管的验证链接，发送给您的客户，让他们上传政府签发的身份证件和自拍照。

请求 IDV URL 是更高保证级别的 API 方法，也是当[向我们传递 SSN 信息](/verify-customers-by-ssn)未获批准时的回退方案。与其自行收集身份文件，不如从 Fluz 请求一个托管验证链接并交给您的客户。Fluz 将直接收集并筛查这些文件。

<Info>
  **先决条件**

  * 由 Fluz 在您的应用上启用 `VERIFY_KYC` scope。参见 [所需 scope](/user-kyc-verification#required-scope)。
  * 为正在验证的客户生成的[用户访问令牌](/recipes/generate-user-access-token)，其 scopes 中包含 `VERIFY_KYC`。
  * 已注册的 webhook 端点。**文档验证必须使用 webhook** —— 结果不会在 API 响应中提供。参见 [验证客户](/user-kyc-verification#set-up-a-webhook)。
</Info>

## 工作原理

<Steps>
  <Step title="您识别客户并请求链接">
    使用为该客户生成的用户访问令牌调用 `requestDocumentVerificationLink`。该令牌用于告知 Fluz 该次验证属于哪个客户。
  </Step>

  <Step title="Fluz 返回验证链接">
    响应包含 `verificationUrl` 和 `verificationId`。请存储 `verificationId` —— 之后您将用它来将最终的 webhook 与此请求进行对应。
  </Step>

  <Step title="您将链接发送给客户">
    通过适合您产品的方式发送：电子邮件、短信、推送通知，或应用内重定向。客户可随时完成验证。
  </Step>

  <Step title="您的客户上传他们的证件">
    在托管页面上，客户拍摄政府签发身份证件（驾照、护照、州身份证或军人证）的正反面，并拍摄自拍照用于生物特征比对。
  </Step>

  <Step title="Fluz 通知您结果">
    当客户完成后，Fluz 会对提交材料进行筛查，并将 `APPROVED` 或 `DECLINED` 的结果发送到您的 webhook 端点。
  </Step>
</Steps>

<Warning>
  验证链接仅对应一个客户的一次验证尝试。切勿在多个客户之间重复使用链接、将其记录在共享系统中，或将其暴露在非唯一读者可见的任何地方 —— 该链接可授予对身份提交会话的访问权限。
</Warning>

## 请求

| Field          | Type    | Required | Description                                    |
| :------------- | :------ | :------- | :--------------------------------------------- |
| `gaveConsent`  | Boolean | Yes      | 客户是否同意进行身份验证。必须为 `true`，否则请求将被拒绝。              |
| `prefillData`  | Boolean | Yes      | 是否使用 Fluz 已掌握的身份信息预填验证表单。为 `true` 时，您无需发送下列字段。 |
| `firstName`    | String  | No       | 客户的法定名。                                        |
| `lastName`     | String  | No       | 客户的法定姓。                                        |
| `streetLine1`  | String  | No       | 居住街道地址。                                        |
| `streetLine2`  | String  | No       | 公寓、套房或单元号。                                     |
| `city`         | String  | No       | 城市。                                            |
| `region`       | String  | No       | 州或地区。                                          |
| `postalCode`   | String  | No       | 邮政编码或 ZIP。                                     |
| `country`      | String  | No       | 国家，ISO 3166-1 alpha-2 格式。                      |
| `dateOfBirth`  | String  | No       | 出生日期，格式为 `YYYY-MM-DD`。                         |
| `emailAddress` | String  | No       | 客户的电子邮箱地址。                                     |
| `phoneNumber`  | String  | No       | 客户的 E.164 格式电话号码。                              |

<Note>
  在设置 `gaveConsent: true` 之前，您必须先采集并记录客户的同意。您传递的任何信息都将用于预填表单 —— 客户可在提交前查看并更正，因此请将这些字段视为便捷性输入，而非将被验证的最终值。
</Note>

<Warning>
  请注意与[SSN 验证](/verify-customers-by-ssn)的字段命名差异：此 mutation 使用 `region` 而另一个使用 `state`，并要求 `dateOfBirth` 为 `YYYY-MM-DD`（而非 `MM/DD/YYYY`）。
</Warning>

## 示例

```javascript theme={null}
import { GraphQLClient, gql } from 'graphql-request';

const API_URL = 'https://transactional-graph.fluzapp.com/api/v1/graphql';

const REQUEST_DOC_VERIFICATION = gql`
  mutation RequestDocumentVerificationLink($input: RequestDocumentVerificationLinkInput!) {
    requestDocumentVerificationLink(input: $input) {
      userId
      verificationType
      verificationId
      verificationUrl
      status
      message
    }
  }
`;

const client = new GraphQLClient(API_URL, {
  headers: {
    Authorization: `Bearer <<USER_ACCESS_TOKEN>>`,
    'Content-Type': 'application/json',
  },
});

const response = await client.request(REQUEST_DOC_VERIFICATION, {
  input: {
    gaveConsent: true,
    prefillData: true,
  },
});

console.log(response);
```

```json Response theme={null}
{
  "data": {
    "requestDocumentVerificationLink": {
      "userId": "eb910e93-5e39-4f53-99b9-0b033dd8e54b",
      "verificationType": "DOCUMENT_VERIFICATION",
      "verificationId": "idv_9MpDJC8aotDaxw",
      "verificationUrl": "https://verify.fluz.app/idv/idv_9MpDJC8aotDaxw?key=27f09ec042881c2c56945680c53108a4",
      "status": "OK",
      "message": "Verification link request successful"
    }
  }
}
```

<Note>
  此响应中的 `status`（`OK`）仅确认**链接已签发** —— 这并非验证决定。最终决定随后将通过 webhook 送达。
</Note>

<Card title="打开食谱" icon="code" horizontal href="/recipes/request-document-verification-link">
  此示例的可复制运行版本，可直接适配到您的集成中。
</Card>

## 响应字段

| Field              | Type   | Description                   |
| :----------------- | :----- | :---------------------------- |
| `userId`           | UUID   | 此次验证所属的 Fluz 客户。              |
| `verificationType` | String | 恒为 `DOCUMENT_VERIFICATION`。   |
| `verificationId`   | String | 此次验证尝试的标识符。请存储以便与 webhook 对应。 |
| `verificationUrl`  | String | 需要发送给客户的托管链接。                 |
| `status`           | String | 当链接成功签发时为 `OK`。               |
| `message`          | String | 人类可读的详细信息。                    |

## 客户所见

托管流程会为客户预填已知信息供其审核，然后要求他们：

1. 拍摄受支持的政府签发带照片身份证的正反面。
2. 拍摄一张自拍照，并与证件照片进行生物特征比对。

在返回决定之前，会对证件真伪、篡改情况以及生物特征匹配进行全面筛查。

## 接收结果

由于客户可能在您签发链接后较久才完成验证，结果会发送到您的 webhook 端点。将传入事件与您存储的 `verificationId` 匹配，然后据此处理：

* **`APPROVED`** —— 客户已通过验证。解锁相应功能。
* **`DECLINED`** —— 客户未通过验证。文档验证是升级路径的最终步骤；此处被拒通常需要人工审核，而非再次自动尝试。

每位客户的文档验证请求次数有限。当达到上限时，后续请求将返回 `ERROR`，并附带 `Exceeded document verification limit`。

## 测试

在 staging 环境中，您可以使用示例驾照和测试身份完成完整的文档流程。staging 中不强制执行证件真伪和其他安全特性，且您可以在反面拍摄中重复使用正面图像。参见 [测试 KYC 流程](/test-kyc-flows)。
