mcpField
S
sumsub-integrate-id-connect

sumsub-integrate-id-connect

github.com/sumsub开发71.0k 次安装4 周前更新
代码仓库

关于 sumsub-integrate-id-connect

用于集成 Sumsub ID Connect 的开发技能,面向需要在应用中请求并接收已验证身份信息的团队。它强调先确认 Sumsub 端配置并通过预检,再编写前后端 OIDC 流程。

主要功能

  1. 01核对集成前置条件
  2. 02预检工作区与验证等级
  3. 03引导 OIDC 授权与 PKCE
  4. 04编排令牌交换和身份复用

适用场景

  1. 01在应用中加入 Sumsub ID 验证入口
  2. 02验证 OIDC 客户端与回调地址配置
  3. 03接收授权结果并交换令牌
  4. 04将 Sumsub ID 身份复用为申请人

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/sumsub/agent-skills --skill sumsub-integrate-id-connect

安装后在 Claude Code 中输入/sumsub-integrate-id-connect确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

examples/
express-callback.js
oidc-button.html
oidc-modal.html
oidc-redirect.html
references/
scopes-and-claims.md
scripts/
preflight.sh

详细介绍

Sumsub — ID Connect 集成

端到端嵌入“通过 Sumsub ID 验证”OIDC 流程 — 前提条件 → 预检 → 按钮 → 后端交换 → 同意 → 工作区中的申请人。

⚠️ 仅限沙盒令牌

接入时不要使用生产环境的 App Token / 密钥。务必从 https://cockpit.sumsub.com/checkus/home?sbx=true 获取一对沙盒令牌 — Connect Sumsub to your AI agent -> Build & configure -> Generate token。令牌和密钥只会在创建时显示一次;关闭对话框前请复制二者。预检会通过 sbx: 前缀检查强制执行此要求。

更深入的身份验证机制:sumsub-api-auth。

⛔ 操作顺序 — 不要先搭建应用

这是本技能中最重要的一条规则。在下面两个关卡都通过之前,不要编写任何前端或后端代码,不要创建演示项目,也不要搭建任何内容。客户端的 Sumsub 设置(阶段 0a)必须手动完成,你无法代劳 — 在它尚未完成时就开始写代码,只会得到一个无法验证身份、无法重定向且无法复用的应用。务必遵循以下顺序:

  1. 逐项向用户确认阶段 0a 的前提条件。 不要假设任何项目已经完成。逐项询问用户是否已完成;如果没有,停止并告知他们具体的手动操作步骤和操作位置(支持邮件模板、Dev Space → OIDC Settings 注册、App Token 创建页面、级别创建交接)。这些操作只能在 Sumsub 控制面板或通过支持团队完成 — 没有对应的公共 API,因此你无法代用户完成。等待所有项目都得到确认后再继续。
  2. 运行阶段 0b 预检,并要求退出码为 0。 只有确认前提条件后,才能运行 scripts/preflight.sh。解决所有 FAIL(必要时返回阶段 0a)。只要有任何 FAIL,就不要继续。
  3. 现在才能开始构建。 两个关卡都通过后,继续阶段 1,搭建前端和后端。

如果用户在关卡通过前说“直接搭建演示”,请简要说明为什么现在还无法运行,并先带他们完成缺失的前提条件。代码是最后一步,不是第一步。

什么是 ID Connect(以及它不是什么)

Sumsub ID Connect 允许企业从最终用户的 Sumsub ID 账户请求特定的已验证身份声明 — 年龄、姓名、国籍、电子邮件、居住国家/地区、真人身份。Sumsub 托管整个面向用户的流程:登录、创建账户(如有需要)、电子邮件 OTP、任何尚未完成的验证步骤,以及针对每位接收者的同意页面。你的应用会收到签名的 OIDC 令牌作为结果;此外,还可以通过 Reusable KYC 在工作区中生成申请人。

这不是 WebSDK。WebSDK 会在你的页面内运行完整的 KYC 信息采集流程;ID Connect 则将整个用户体验交由 Sumsub 处理。

生命周期一览

 ┌──────────────────────────────┐
 │ Stage 0a Preconditions check │  manual setup on Sumsub side
 │ Stage 0b scripts/preflight.sh │  automated validation
 └──────────────┬───────────────┘
                │ clientId, levelName, allowlist
 ┌──────────────▼───────────────┐
 │ Stage 1: Frontend "Verify…"  │  authorize redirect with PKCE
 │   button                      │
 └──────────────┬───────────────┘
                │ onSuccess({ code, state })
 ┌──────────────▼───────────────┐
 │ Stage 2: code → access_token  │  POST id.sumsub.com/api/snsId/oauth/token
 │   (client_secret_basic)       │
 └──────────────┬───────────────┘
                │ access_token
 ┌──────────────▼───────────────┐
 │ Stage 3a: → share token       │  POST /resources/accessTokens/sumsubIdShareToken
 └──────────────┬───────────────┘
                │ sharingAllowed?
        ┌───────┴────────┐
        │ false           │
        ▼                ▼ true
 ┌──────────────────┐ ┌──────────────────────────────┐
 │ Stage 3b:        │ │ Stage 4: reuse/preview +     │
 │ shareLink        │ │   reuse/commit               │
 │ redirect + retry │ │ → applicant in your workspace │
 └────────┬─────────┘ └──────────────────────────────┘
          │
          └──────► back to Stage 3a (retry — now sharingAllowed: true)

端点

METHODURLAuthStage
(浏览器重定向)https://id.sumsub.com/api/snsId/oauth/authorize无1
GEThttps://id.sumsub.com/.well-known/openid-configuration无0b
GEThttps://id.sumsub.com/.well-known/jwks.json无(id_token 验证)
POSThttps://id.sumsub.com/api/snsId/oauth/tokenclient_secret_basic2
POSThttps://api.sumsub.com/resources/accessTokens/sumsubIdShareTokenApp Token + HMAC3a
POSThttps://api.sumsub.com/resources/snsId/oauth/shareLinkApp Token + HMAC + Bearer3b
GEThttps://api.sumsub.com/resources/api/reusableIdentity/reuse/previewApp Token + HMAC4
POSThttps://api.sumsub.com/resources/api/reusableIdentity/reuseApp Token + HMAC4

“Enable Sumsub ID Connect”开关、OIDC 客户端注册(client_secret + redirect_uri 允许列表)以及共享合作伙伴注册,只能通过 Sumsub 控制面板 UI 完成 — 没有对应的公共 API。

阶段 0a — 前置条件检查清单

开始编写代码或执行预检前,Sumsub 端必须已具备以下条件。每一项都对应下方的一项检查,若未满足则会导致运行时失败。

  • Sumsub 支持团队已为你的工作区启用 ID Connect。 这不能自行在界面中切换——支持团队启用之前,无法创建 OIDC 客户端,预检会报告 connect_token: ID Connect not enabled for this workspace。请先联系你的客户成功经理(CSM)或 [email protected],并等待确认。模板:

    ```
    Subject: 为 clientId <YOUR_CLIENT_ID> 启用 Sumsub ID Connect(sandbox)
    
    Hi Sumsub team,
    
    Please enable Sumsub ID Connect for our workspace.
    
      Environment:         sandbox
      clientId:            <YOUR_CLIENT_ID>          (Dashboard top-left)
      Intended scopes:     openid, share, name        (adjust as needed)
      Intended recipients: self                       (or list partner clientIds)
      Use case:            <one-line description of where the button will live>
    
    Once enabled we'll register the OIDC client + redirect URIs in
    Dev Space → OIDC Settings.
    
    Thanks
    ```
    
  • App Token 和 secret(sandbox)。 通过 https://cockpit.sumsub.com/checkus/home?sbx=true,依次选择 Connect Sumsub to your AI agent -> Build & configure -> Generate token 生成。创建时这两个值只显示一次。→ 导出为 SUMSUB_APP_TOKEN / SUMSUB_SECRET_KEY。

  • 已在 Dashboard → Dev Space → OIDC Settings 注册 OIDC 客户端。 记录以下三项: - client_id(公开信息——会放在浏览器中;在常见的接收方为自己的场景下,作为共享令牌的 forClientId) - client_secret(创建时只显示一次;如果丢失,必须重新生成,这会使现有集成失效)。Stage 2 的 code→token 交换需要此项——只能保存在服务端。 - 已填写两个回调地址的 redirect_uri 允许列表(Sumsub 会逐字节匹配——尾部斜杠、大小写、端口和查询参数都会影响匹配): - 你的 authorize 回调(例如 https://yourapp.com/auth/callback) - 你的 shareLink 回调(例如 https://yourapp.com/share-complete) Sumsub 会将浏览器重定向回这些 URL,并要求使用公开的 HTTPS 地址——单独的 http://localhost:3000 无法用于本地测试。若要在自己的机器上开发,请使用公开的 HTTPS 隧道(ngrok)暴露本地服务,并将该地址加入允许列表——参见下文的使用 ngrok 进行本地开发。

  • 此工作区中至少存在一个验证级别。 记录 levelName。如果没有,请先移交给 sumsub-create-level——没有验证级别,Stage 4 就无法创建申请人。

  • 至少有一个包含已验证数据的 Sumsub ID 账户用于端到端测试。仅有电子邮件的账户(未完成 KYC)会导致 Stage 4 失败,并返回 errorCode 10521 reusable-kyc-inactive-sumsub-id-account——参见 Stage 4 末尾的错误表。

阶段 0b — 预检

scripts/preflight.sh 会通过机器验证可在不生成 OIDC 代码或创建申请人的情况下探测的前置条件。它不会修改任何内容。

SUMSUB_APP_TOKEN=sbx:... SUMSUB_SECRET_KEY=... \
  bash scripts/preflight.sh

检查项(彼此独立——一项失败不会中止其他检查):

检查项验证内容
connect_tokenApp-Token HMAC 签名已被接受,且此工作区已启用 ID Connect——通过已知错误代码探测端点,并预期返回 401 Invalid code(若返回 404 invalid clientId,则表示未启用 ID Connect)。这是连通性/权限探测,不是阶段 2 的交换路由。
oidc_discoveryhttps://id.sumsub.com/.well-known/openid-configuration 返回有效的 OIDC 发现文档
levels此工作区中至少存在一个验证级别

全部 PASS 或 PASS+WARN 时退出码为 0,任何 FAIL 时退出码为 10。开始阶段 1 前,请解决所有 FAIL。

使用 ngrok 进行本地开发

ID Connect 无法针对 http://localhost 进行测试。Sumsub 会在授权流程(阶段 1)和 shareLink 同意流程(阶段 3b)之后,将浏览器重定向回你的 redirect_uri,并要求该 URL 必须是公开的 HTTPS URL,且与 OIDC 客户端 redirect_uri 允许列表中的条目逐字节完全一致。裸 localhost URL 既不公开也不是 HTTPS,因此重定向会失败。进行本地开发时,请使用 ngrok 在本地服务器前建立一个公开的 HTTPS 隧道,并将该来源添加到允许列表。

  1. 在本地启动后端(示例监听 PORT=3000):

    PORT=3000 node examples/express-callback.js
    
  2. 建立到该端口的隧道。 建议使用保留(静态)域名,这样 URL 在重启后仍然有效——免费的随机 ngrok URL 每次启动都会变化,因此每次都得重新编辑允许列表:

    ngrok http 3000 --domain=your-reserved-name.ngrok-free.app
    # or, ephemeral URL (changes each restart): ngrok http 3000
    

    ngrok 会打印一个转发 URL,例如 https://your-reserved-name.ngrok-free.app。

  3. 在 ngrok 来源处将两个回调都添加到允许列表:进入 Dashboard → Dev Space → OIDC Settings(沙盒工作区)——逐字节保持一致,包括末尾的斜杠:

    https://your-reserved-name.ngrok-free.app/
    https://your-reserved-name.ngrok-free.app/share-complete
    
  4. 让应用使用公开 URL,而不是 localhost。 浏览器的 redirect_uri 和服务端的 shareLink redirectUri 必须基于 同一个公开来源,因此请设置 PUBLIC_BASE_URL 并重启:

    PUBLIC_BASE_URL=https://your-reserved-name.ngrok-free.app \
      PORT=3000 node examples/express-callback.js
    

    然后在浏览器中打开 ngrok URL(而不是 localhost:3000),这样它发送的 redirect_uri 才会与允许列表匹配。

⚠️ 每次 URL 变更都要重新注册。 如果使用临时 ngrok URL,每次 ngrok 重启时都必须更新允许列表条目和 PUBLIC_BASE_URL。使用保留域名可避免这种反复操作。

ngrok 的免费插页(“You are about to visit…”)只影响 API/XHR 调用,不影响顶层浏览器导航,因此不会阻止 OIDC 重定向。使用保留域名或付费套餐可完全移除此插页。

阶段 1 — 前端:按钮

⛔ 关卡。 在阶段 0a 的前置条件全部经用户确认,且阶段 0b 预检以 0 退出之前,不要开始此阶段。如果这两项都尚未完成,请返回——参见上文“操作顺序”。这是第一个需要编写代码的阶段;在此之前,你必须先验证所有设置。

架构 — 哪些由你负责,哪些由 Sumsub 负责

Sumsub 提供:OIDC 服务(id.sumsub.com)、HMAC API(api.sumsub.com),以及可选的 @sumsub/id-connect JS 库,用于挂载按钮。

集成的前后两部分都由你编写:

  • 前端(本阶段)— 带按钮的页面。生成 PKCE,启动到 id.sumsub.com 的 OIDC 重定向,在回调中接收 ?code=,并向你自己的后端 POST { code, codeVerifier }。
  • 后端(阶段 2-4)— 前端向其发送 POST 请求的 HTTP 端点。使用你的 App Token + 密钥为 Sumsub API 调用签名(这些凭据绝不能传到浏览器),协调 code → access_token → share token → reuse 流程,并返回已物化的申请人信息。

前后两部分通过一个路由名称关联 — 示例中为 POST /api/sumsub/id-connect/exchange;请根据你的路由配置进行重命名。匹配的参考实现: examples/oidc-button.html(前端)+ examples/express-callback.js(后端)。 后端是一个精简的流程协调器(约 180 行 Node/Express);可移植到你选择的技术栈 — 无论使用何种语言,线协议格式都相同。

⚠️ onSuccess 不是验证信号。 它仅表示用户已完成 OIDC 授权步骤,且 Sumsub 已签发授权码。 实际验证结果来自阶段 4 — /reuse 响应中的 applicant.review.reviewStatus(如果你的接收方等级不运行额外检查,则会立即返回),或 applicantReviewed webhook(对于会在复用后运行检查的任何等级,该 webhook 都具有权威性)。 绝不要根据 onSuccess 触发来授予访问权限或解锁功能。

提供三种方案 — 默认使用 方法 1(createButton);其他方案适用于设计系统集成或无需打包器的场景。

方法 1 — 通过 @sumsub/id-connect 使用预构建按钮(推荐)
import { createButton } from '@sumsub/id-connect';

// PKCE helpers (S256 — full versions in examples/oidc-button.html).
const b64url = (buf) => btoa(String.fromCharCode(...new Uint8Array(buf)))
  .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
const sha256 = (s) => crypto.subtle.digest('SHA-256', new TextEncoder().encode(s));

// Generate the PKCE pair yourself, store the verifier under YOUR key — Stage 2
// on the backend needs that verifier to exchange the code for an access token.
const verifier  = b64url(crypto.getRandomValues(new Uint8Array(32)));
const challenge = b64url(await sha256(verifier));
sessionStorage.setItem('myapp.pkce.verifier', verifier);

createButton({
  clientId:      '<your-client-id>',
  permissions:   ['openid', 'share', 'name'],
  container:     document.getElementById('button-container'),
  codeChallenge: challenge,                            // library uses YOUR challenge — skips its own PKCE gen
  loginHint:     '[email protected]',                   // optional, prefills the email field
  onSuccess: async ({ code, state }) => {
    const v = sessionStorage.getItem('myapp.pkce.verifier');
    await fetch('/api/sumsub/id-connect/exchange', {
      method:  'POST',
      headers: { 'Content-Type': 'application/json' },
      body:    JSON.stringify({ code, codeVerifier: v, redirectUri: location.href }),
    });
  },
  onError: (err) => console.error('sumsub-id-connect error', err),
});

为何自行生成 PKCE:阶段 2 的令牌交换需要 verifier。如果让库生成,你就需要依赖库内部的 sessionStorage 键(每个次要版本都未记录其文档),才能在 onSuccess 中读回它。传入自己的 codeChallenge,就能将 verifier 存储在由你掌控的键下。方法 2 和 3 也可使用相同模式。

可运行示例:examples/oidc-button.html。

方法 2 — 使用自己的触发元素 + 库模态框

使用同一个库,但由你掌控触发元素;库通过 openModal({...}) 在叠加层中打开流程。如果你的设计系统已有自己的按钮,请使用此方案。

可运行示例:examples/oidc-modal.html。

方法 3 — 原始 OIDC 重定向(不使用库)

直接导航到 OIDC 授权端点,页面中不加载 Sumsub 脚本。当 CSP 禁止第三方脚本、你所处环境仅支持 SSR,或你需要跨多个提供方维护通用 OIDC 客户端时,可使用此方案。

GET https://id.sumsub.com/api/snsId/oauth/authorize
  ?client_id=<your-client-id>
  &response_type=code
  &redirect_uri=<allowlisted URI>
  &scope=openid+share+name
  &state=<random CSRF nonce>
  &code_challenge=<base64url(SHA256(code_verifier))>
  &code_challenge_method=S256
  &login_hint=<optional email>

你需要生成 code_verifier(43–128 个字符,URL 安全),推导出 code_challenge = base64url(SHA256(verifier)),存储 verifier(sessionStorage),并在回调后将其转发给后端。Sumsub 只接受 code_challenge_method=S256(不接受 plain),且 redirect_uri 必须与允许列表逐字节完全一致。

可运行示例:examples/oidc-redirect.html。

选择作用域

默认值为 ['openid', 'share', 'name']。仅当下游逻辑确实会读取 email、profile 或 offline_access(刷新令牌)时才添加 — 额外作用域会在面向用户的流程中触发额外检查。完整表格: references/scopes-and-claims.md。

阶段 2 — 后端:代码 → access_token

在 OIDC 令牌端点上交换授权码。该代码来自浏览器授权流程,因此对应的是标准 OIDC 令牌端点——使用 OIDC client_secret(client_secret_basic)进行身份验证,而不是 HMAC。

POST https://id.sumsub.com/api/snsId/oauth/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(<client_id>:<client_secret>)

grant_type=authorization_code
&code=<the code your frontend got>
&redirect_uri=<exact-match URI from Stage 1 — byte-for-byte>
&code_verifier=<PKCE verifier matched to the code_challenge from Stage 1>

响应(有效期为 24 小时的 access_token):

{
  "access_token":  "snd-id-con-a-...",
  "refresh_token": "snd-id-con-r-...",   // only with `offline_access`
  "token_type":    "Bearer",
  "expires_in":    86400,
  "id_token":      "eyJhbGc..."           // only with `openid` — RS256-signed
}

之后通过 grant_type: "refresh_token" 刷新;刷新时请求的 scope 不能超过用户同意时授予的范围。

client_secret 必须保留在服务器端——绝不能放进浏览器资源包中。交换方式是 client_secret_basic / client_secret_post;不要使用 HMAC 签名。(Stage 3a/4 中仍会使用 App-Token + HMAC 身份验证来处理 share token 和 reuse 调用。)

注意事项
  • Invalid code 401 有三个常见原因:PKCE 不匹配(verifier 的哈希值与授权时发送的 challenge 不一致)、代码已使用(代码只能使用一次;刷新回调页面会导致重复触发),或代码已过期(有效期很短——请立即交换)。
  • redirect_uri 必须与 Stage 1 逐字节完全一致——尾随斜杠、大小写、端口和查询参数都必须匹配,否则交换会失败。
  • id_token 验证——使用成熟的库(jose、pyjwt、jjwt),根据 .well-known/openid-configuration 中的 jwks_uri 进行验证。绝不要信任未经验证的 JWT 内容。

阶段 3 — 后端:access_token → share token + 同意

创建一个限定接收方(forClientId)的 share token。务必实现同意回退流程(Stage 3b)——只要用户尚未授权与该特定 forClientId 共享,就会返回 sharingAllowed: false。在常见的自有接收方场景中,通常会在 Stage 1 的同意页面上一次点击授予这两项同意;但如果生产代码只处理 sharingAllowed: true,那么用户重新进入流程或接收方配置发生变化时,流程首次就会失败。

阶段 3a — 创建 share token
POST https://api.sumsub.com/resources/accessTokens/sumsubIdShareToken
{
  "sumsubIdConnectToken": "<access_token from Stage 2>",
  "forClientId":          "<recipient clientId>",
  "ttlInSecs":            1800
}

forClientId:

  • 自有接收方(常见情况):你自己的工作区 clientId,可在 Dashboard 左上角查看。
  • 第三方接收方:合作伙伴的 clientId(必须预先在 Dashboard 中注册为合作伙伴)。

响应:

{
  "token":          "_act-snsId-...",
  "forClientId":    "<echoed>",
  "sharingAllowed": true    // or false → continue to Stage 3b
}
阶段 3b — 合作伙伴同意 shareLink

如果 sharingAllowed: false,创建同意链接并重定向用户:

POST https://api.sumsub.com/resources/snsId/oauth/shareLink
Authorization: Bearer <access_token from Stage 2>
X-App-Token + X-App-Access-Ts + X-App-Access-Sig

{
  "redirectUri": "<your shareLink callback URL — must be in the allowlist>",
  "forClientId": "<same recipient clientId>",
  "displayMode": "page",
  "state":       "<csrf-or-correlation-id>"
}

响应:{ "link": "https://id.sumsub.com/share/<id>" }——5 分钟后过期。

在服务器端按 state 保存 access_token(演示项目可以使用内存 Map;生产环境请使用 Redis / 加密 Cookie / 会话表)。将用户重定向到 link。用户同意后,Sumsub 会将用户重定向回 redirectUri,并附带 ?token=<JWT>——这是一个经过 RS256 签名的 JWT,其载荷中包含 state(以及 sharingAllowed: true 和 forClientId)。

⚠️ state 位于 JWT 载荷中,而不是顶层的 ?state= 查询参数中。 解码 token JWT 以读取 state(首先根据 jwks_uri 验证其签名),然后通过该 state 查找已保存的 access_token。再次调用 Stage 3a——此时 share token 会返回 sharingAllowed: true。解码后的载荷结构: { iss, sub, aud, iat, exp, sharingAllowed, state, forClientId }。

完整的参考实现: examples/express-callback.js(使用以 state 为键的内存 pendingShare Map,以及 /share-complete 处理器)。

阶段 4 — 创建申请人

获得可用的 share token 后,在你的工作区中创建申请人。务必先预览。

预览(无副作用)
GET https://api.sumsub.com/resources/api/reusableIdentity/reuse/preview
  ?shareToken=<token>
  &levelName=<your-level>
  &userId=<externalUserId>

返回与 /reuse 将创建的相同 ApplicantPublicDto 结构——可用于在提交前显示兼容性错误。

提交(创建申请人)
POST https://api.sumsub.com/resources/api/reusableIdentity/reuse
  ?shareToken=<token>
  &levelName=<your-level>
  &userId=<externalUserId>

userId 是 Sumsub 存储在申请人记录中的 externalUserId——每个真实用户对应一个稳定的标识,对用户不透明,并与您的身份验证系统关联。规则与 WebSDK 相同。

Reuse 错误代码

所有 400 响应均包含 errorCode(整数)和 errorName(kebab-case), 适合用于代码分支。401 表示通用的令牌有效性问题——不包含 errorCode, 只有 description。

HTTP / errorCodename原因操作
401 / —Token is invalid共享令牌已过期(超出 TTL)、已使用或格式错误通过第 3a 阶段重新生成 — 使用仍有效的 access_token 再次调用 /sumsubIdShareToken
400 / 10501not-in-partners-listforClientId 未注册为工作区的共享合作伙伴在 Dashboard 中将接收方添加为合作伙伴(仅限 Sumsub UI — 无公开 API)
400 / 10502invalid-partner-id从共享令牌中提取的合作伙伴 ID 无效重新检查 forClientId;针对真实合作伙伴重新生成共享令牌
400 / 10503invalid-share-token共享令牌格式错误或已过期通过第 3a 阶段重新生成
400 / 10504non-suitable-share-token共享令牌不适用于在指定 levelName 下重复使用(范围不匹配)使用匹配的范围重新生成共享令牌,然后针对同一等级重试
400 / 10505reusable-kyc-disabled此工作区已禁用 Reusable KYC联系 Sumsub 支持,为工作区启用 Reusable KYC
400 / 10506reusable-kyc-not-reusable通用回退 — 数据提供方不符合重复使用资格,且未匹配到更具体的原因在 Dashboard 中检查数据提供方;选择其他数据提供方,或回退到 WebSDK
400 / 10507reusable-kyc-not-approved-applicant数据提供方申请人尚未处于已批准状态(待处理/已拒绝/暂停处理)等待数据提供方的 KYC 获批;使用状态为已批准的数据提供方
400 / 10508reusable-kyc-not-active-applicant数据提供方申请人处于非活动状态(已停用/已封锁)使用其他数据提供方 — 重新激活需由 Sumsub 处理
400 / 10509reusable-kyc-not-kyc-moderation-type数据提供方的源审核类型不适合重复使用数据提供方需要通过标准 KYC 审核;专用流程无法重复使用
400 / 10510reusable-kyc-not-selfie-or-identity-doc数据提供方缺少必需的自拍照或身份证明文件选择不需要该文件集的等级,或让数据提供方重新验证
400 / 10511reusable-kyc-not-selfie-liveness接收方等级要求活体检测;数据提供方的自拍照未通过活体检测拍摄使用 SELFIE 上未设置 videoRequired: passiveLiveness 的等级,或让数据提供方通过活体检测重新验证
400 / 10512reusable-kyc-not-req-doc-overlap数据提供方与接收方等级要求的文件类型没有交集选择所需文件属于数据提供方文件子集的接收方等级
400 / 10513reusable-kyc-not-compatible-doc-type接收方等级要求的数据提供方未提供的文件类型使用要求较低的等级,或回退到 WebSDK 以完整采集资料
400 / 10514reusable-kyc-not-actual-poi-date数据提供方的身份证明(POI)已过期,不适合重复使用数据提供方必须重新提交最新 POI,或放宽接收方等级的 POI 时效窗口
400 / 10515reusable-kyc-not-actual-poa-date数据提供方的地址证明(POA)已过期,不适合重复使用数据提供方必须重新提交最新 POA,或放宽接收方等级的 POA 时效窗口
400 / 10516reusable-kyc-not-acceptable-age数据提供方不符合接收方等级的年龄标准无法恢复 — 需要更换用户
400 / 10517reusable-kyc-incompatible-capture-settings数据提供方与接收方之间的采集设置(文件上传与实时摄像头等)不匹配将接收方等级的 captureParams 调整为与数据提供方使用的设置一致,或让数据提供方重新采集
400 / 10518reusable-kyc-email-mismatch数据提供方的电子邮件与接收方申请人已有的电子邮件不匹配解决申请人重复冲突 — 使用不同的 externalUserId,或使电子邮件保持一致
400 / 10519reusable-kyc-phone-mismatch数据提供方的电话号码与接收方申请人已有的电话号码不匹配与 10518 相同 — 解决冲突
400 / 10521reusable-kyc-inactive-sumsub-id-account数据提供方的 Sumsub ID 账户没有存储的文件(仅有电子邮件,从未完成 KYC)数据提供方必须先在 id.sumsub.com 完成完整 KYC;测试时请使用 Sumsub 提供的已验证测试账户
当申请人被创建后,applicantReviewed Webhook 是验证结果的权威信号,请按 WebSDK 的相同方式接入。有关 Webhook 的资料,请参阅
sumsub-integrate-websdk;有关沙盒 Webhook 订阅设置,请参阅
sumsub-manage-webhooks。

上线检查清单

当用户表示“我们准备好上线了”时:

  • Sumsub 支持团队已为生产环境的 clientId 启用 Sumsub ID Connect(与沙盒环境分开)。
  • 生产环境的 redirectUri(authorize 和 shareLink 回调)已加入生产工作区 Dashboard 的允许列表。
  • 后端令牌交换端点已设为需要身份验证(只有经过身份验证的用户才能兑换为其本人签发的代码)。
  • 已根据生产环境的 JWKS 验证 id_token 签名。
  • externalUserId 对每个真实用户都保持稳定(不是邮箱,也不是显示名称)。
  • 在调用 /reuse 前先调用 /reuse/preview,让兼容性错误以 UX 问题的形式呈现,而不是产生 4xx 噪声。
  • 已实现并测试第 3b 阶段的 shareLink 工作流——不要发布只处理 sharingAllowed: true 的代码。
  • shareLink 回调使用的内存状态已替换为真实的会话存储(Redis / 加密 Cookie / DB)。
  • App Token、密钥和 OIDC client_secret 已存入生产环境的密钥存储,不在代码库中,也不在浏览器包中。
  • 刷新令牌(如有使用)仅在服务端存储、静态加密,并采用单租户模式。

另请参阅

评论

支持 Markdown