跳转到主要内容
本页数据的权威来源是验证服务中的 serialize_catalog(),并通过 GET /v1/sandbox/scenarios/ 实时提供。service-didit-verification 仓库中的 docs/sandbox/SANDBOX_REFERENCE.md 是由 pipenv run python scripts/generate_sandbox_reference.py 生成的经过漂移测试的副本。本页内容与该参考文档保持一致。如果此处内容看起来过时,请始终以实时的目录接口为准。该目录接口需要身份验证:请像调用其他接口一样,通过 x-api-key 发送您的 API 密钥;如果您是在正在运行的会话内部读取,则可以使用会话令牌。
Didit 的沙盒相当于 Stripe 的测试卡或 Sumsub 的证件模板:它可以在不接触真实服务提供商、真实 PII 或您的余额的情况下,确定性地复现任意验证结果。

环境模型

沙盒是按应用划分的模式(ApplicationDetail.mode == SANDBOX),与 Stripe 测试模式的理念相同。当会话在沙盒应用下运行时:
  • 所有外部服务提供商(OCR、AML、人脸比对、活体检测、NFC、电话验证、邮箱验证、IP、地址证明、数据库核验、Document AI)都会被模拟,不会调用任何第三方。
  • 活体检测的运行方式与生产环境完全相同。 主动活体检测工作流会在沙盒中运行真实的主动采集,无论是托管流程还是通过原生 SDK 的 Web 跳转,都是如此,因此您可以测试终端用户将获得的真实体验。只有活体检测结果由场景或魔法值模拟,报告中记录的是您的工作流所配置的检测方式。
  • 自定义域名仅限生产环境使用。 沙盒应用无法添加自定义域名;沙盒会话始终运行在默认的托管验证域名上。
  • 会话从不计费,并且会跳过余额检查。
  • 每个应用每 24 小时最多可创建 500 个会话。
  • Webhook 会携带 "environment": "sandbox"(生产环境会话携带 "environment": "live")。
  • 托管流程会展示会话所处的环境,以便界面提醒用户不要上传真实的个人身份信息(PII)。
  • 结果永远不取决于像素内容。 提取的数据和状态均来自场景或魔法值。采集到的媒体本身(证件、自拍照、视频、地址证明文件)会像生产环境中的会话一样实际存储。

沙盒中的交易监控

沙盒是以会话为模型的:它模拟验证会话会调用的服务商。交易监控没有可以模拟的服务商,因此沙盒应用走另一条路径:交易会被存储,但针对它的任何判定、筛查、通知或计费都不会运行。 在沙盒应用上创建的交易会照常保存并返回,但不会发生以下任何情况:
  • 不执行规则评估。 rule_runs 为空,无论你的规则处于哪种模式。沙盒应用上的 ACTIVE 规则永远不会触发,因此交易保持 APPROVED,分数为 0,也不会触发警报或创建案件。
  • 不进行 AML / 钱包筛查。 即使在已启用监控的应用上发起加密货币交易,provider_results 也为空。
  • 不发送 Webhook。 沙盒交易不会投递 transaction.created 或 transaction.status.updated。
  • 不计费。 会记录一条单价为 0.0000 的用量事件,你的余额不变。
每个交易响应都包含 environment 字段("live" 或 "sandbox"),因此空的 rule_runs 永远不会产生歧义:"sandbox" 表示规则未被评估,而不是规则都未命中。Business Console 在交易的 Risk & decision 卡片中也是同样的含义,而不是只显示一句 “No rules evaluated”。
Travel Rule 是“什么都不运行”的唯一例外。 在启用了 Travel Rule 的应用上,沙盒中的 travelRule 交易仍会运行交换引擎:会创建转账记录,并使其依次经过各个状态。沙盒从不与 Didit 之外的任何人通信。其唯一的交易对手是内置于平台中的 Didit Test VASP:任何轨道(TRP、你已连接的网络成员资格、电子邮件或 INTERNAL)都不会把合规消息发送给真实的交易对手 VASP,跳过交易对手 VASP 归属筛查,取消交易也不会向交易对手发送任何内容。travel_rule.status.updated Webhook 会照常投递,并标记为 "environment": "sandbox"。出账:你提交的 travelRule 交易。系统先执行 threshold_amount 检查。在沙盒中,只有当你发送 transaction_details.amount_in_default_currency 时它才生效,因为沙盒不转换货币;否则沙盒中的每笔转账都会被视为超过阈值。未应答的转账会在 confirmation_timeout_hours 后过期,随后你的 timeout_outcome 适用于该交易。超过阈值后,自托管钱包检查照常适用:转给已声明的自托管钱包的转账会进入 UNCONFIRMED_OWNERSHIP,且不发送任何内容。你可以在沙盒中通过钱包所有权小组件完成该转账;当目标钱包已在你的钱包地址簿中时,也可以通过确认所有权完成。任何其他超过阈值的转账都会通过 TEST_VASP 轨道发送给 Didit Test VASP。它会在 Didit 内部对该转账作出响应,具体场景由你通过收款钱包或收款人姓名选择:转账可能完成、被拒绝、信息不匹配、进入 COUNTERPARTY_VASP_NOT_REACHABLE、过期(随后你的 timeout_outcome 适用于该交易),或等待钱包所有权。查看每个场景,请参阅在沙盒中测试 Travel Rule。入账:POST /v3/travel-rule/inbound/。登记从不通过轨道发送,因此登记本身没有任何模拟:沙盒会将存款与你的钱包地址簿进行比对,并同步结算,与正式环境完全一致。结果是真实的实际结果,而不是 AWAITING_COUNTERPARTY:ON_HOLD(地址簿中无匹配)、UNCONFIRMED_OWNERSHIP(匹配的条目未经所有权验证)、COUNTERPARTY_MISMATCHED_DATA(收款人姓名与钱包持有人不符),或 COMPLETED 后接 FINISHED(匹配到已验证的条目)。要改为接收来自 Didit Test VASP 的转账,请使用触发 Test VASP 入账转账,并指定你自己地址簿中的一个钱包。

Travel Rule 测试 VASP 场景

目录中的 travel_rule.scenarios 列出了以下出账场景。在沙盒应用上启用 Travel Rule 后,请在出账 travelRule 交易上设置下表中的收款人姓名。上文描述的阈值检查和已声明自托管钱包检查会先运行。 你也可以用收款钱包地址代替姓名来选择场景(两者都设置时以钱包为准)。未指定任何一项的转账会以 accept 完成。在沙盒中测试 Travel Rule 列出了每个场景的钱包及其确切结果。 入账测试 VASP 触发器 的 scenario 字段只接受 accept 和 name_mismatch。
如何在规则上线前进行测试。 使用回测:它会用你真实的交易历史重放规则,并报告 evaluated / matched / affected_entities,且不改变任何交易的状态。将其与正式应用上的 TEST 模式搭配使用:TEST 规则会对每笔新的正式交易进行评估,并记录它本会命中的内容,但不改变分数或状态。待规则的筛选效果看起来合适后,再切换到 ACTIVE。

如何在生产环境与沙盒之间切换

生产环境和沙盒是独立的应用,因此测试流量与生产数据绝不会混在一起。每个应用都有一个 mode,取值为 live 或 sandbox:
  • 使用沙盒模式应用的 API 密钥,可获得用于模拟的、不计费的、可模拟结果的会话。
  • 使用生产模式应用的 API 密钥,进行真实的验证。
sandbox_scenario 字段(用于会话创建请求和独立的 AML API)和模拟接口仅被沙盒应用接受;在生产应用上会被拒绝。

托管验证流程中的沙盒

在沙盒应用下创建的会话,会在托管验证流程中呈现额外的界面(即 POST /v3/session/ 返回的 url):
  • 卡片内沙盒横幅。 每个界面的卡片内都会显示一条横幅,文字为“仅限测试数据,无真实调用”,以便始终清楚地表明该会话从不调用真实服务商,也不会影响您的余额。采集到的媒体与任何会话一样会被存储,因此请使用示例证件和测试数据,而不要使用真实身份证件或个人信息。
  • 流程前场景选择器。 在开始采集之前,卡片内的选择器会引导用户选择一个测试结果:先选择结果,再选择该结果对应的触发器。确认后会调用 POST /v3/session/{session_id}/sandbox/arm/(见下文 流程开始前设置(或重新设置)会话),然后进入流程,并已应用该场景的魔法值。
  • 示例证件条。 文档上传/采集组件正下方直接显示一排沙盒示例证件(最多 3 个)。点击其中一个即可代替真实上传使用。
沙盒会话会存储真实采集的媒体:证件、自拍照、活体视频和地址证明文件,都会像生产会话一样被上传并保留。提取的数据(证件验证字段、人脸比对分数、活体检测结果等类似内容)以及会话结果本身(已通过 / 审核中 / 已拒绝),都由场景或魔法值模拟生成,绝不源自采集的媒体。Business Console 会在沙盒会话的提取数据部分标注一个模拟数据标签,方便审核人员一眼分辨会话中哪些部分是真实采集的,哪些部分由场景驱动。

场景

每个场景都是一组命名的魔法值。在创建会话时(或调用模拟接口时)将其标识符作为 sandbox_scenario 传入,即可复现对应结果。 review_* 场景的存在,是为了让你无需提供足以被拒绝的输入,即可测试人工审核的用户体验(控制台审核队列、In Review Webhook、审核员的通过/拒绝操作)。上述两个 kyb_* 场景设置的是 expected_details.registration_number,而不是 expected_details.first_name:它们仅适用于企业验证(KYB)会话。

魔法值

魔法值是一种特定输入,可使某个模拟功能输出特定风险。将输入字段设为魔法值(可直接设置,也可通过场景设置)即可触发该风险。

非证件查询与身份钱包

沙盒应用可以启用国家目录中的每一种身份钱包,包括在生产环境应用中不可用的钱包。 默认的 approve 场景模拟已验证的身份,无需登录外部钱包。 结果会存入会话,并按工作流的常规下一步继续。 沙盒不会验证真实的钱包凭证,模拟尝试也不收费。 查询请求仍会校验所填字段,并采用已配置的尝试次数上限,默认为一次。 请使用以下场景测试重试和回退规则: 钱包失败时,将按国家设置回退到证件拍摄或直接拒绝。 已完成的查询尝试会分别记录,因此在回退之前,允许的两次尝试会产生两条结果。 所有沙盒用量仍然免费。

银行验证账户核验

沙盒中的银行验证步骤在每个国家都提供两种方式,顺序与该步骤的设置一致,使用模拟服务,不涉及真实银行,也不产生费用。 默认顺序下,用户先进入银行登录,并选择 输入您的账户信息 来运行账户核验;将 bank_method_order 设置为 ["account_lookup", "open_banking"] 则从账户核验开始。 输入账户的末四位字符决定结果;各种结尾以及每种格式的有效账户,请参阅在沙盒中测试。 账户核验 API 根据相同的末四位返回相应的沙盒密钥。

示例证件

切勿在沙盒中上传真实身份证件。请改用内置的示例证件。
托管流程提供三份示例证件,每种证件类型一份: 在证件条中点击示例,即可代替真实采集使用它。提取的数据和会话结果始终来自所选场景或魔法值,因此任何示例都可用于任何场景。

测试示例身份与 expected_details

沙盒中的每份证件都由同一个固定身份伪造而成。 提取的值在每次会话中都相同,且从不由当前日期推算,因此你可以用它们预填 expected_details,并端到端地检查字段比对和警告处理。 传入以下值时,比对检查会通过;传入其他任何值时,对应的 *_MISMATCH_WITH_PROVIDED 警告会被有意触发。 所有示例证件共用以下日期: 其余身份信息取决于你使用的证件:
first_name 和 last_name 是例外:沙盒会把你在 expected_details 中发送的姓名回显到伪造的证件上,因此姓名比对可以通过任何姓名。 使用 SANDBOX_OCR_FULL_NAME_MISMATCH_WITH_PROVIDED 魔法值来测试姓名不匹配,使用 SANDBOX_OCR_DOB_MISMATCH_WITH_PROVIDED 来测试出生日期不匹配。
如果你的工作流将 documents_allowed 限制为排除巴西电子护照的国家或证件类型,沙盒会改为从第一个允许的国家伪造证件,因此 nationality、id_country 和证件名称都将跟随该国家。上述日期保持不变。

伪造证件不包含的信息

伪造证件是所允许国家和证件类型的通用模板,因此只有真实的国家签发证件才会提供的字段保持为空。其中对路由影响最大的是地区 / 美国州(kyc.region):沙盒中的美国驾照或身份证没有州信息,因此 Region equals IL 这类分支条件在沙盒中永远无法匹配。如果该节点的其他分支也不匹配,流程会走该节点的回退分支(即没有条件的分支)。这并不是审核,也不是分支失败,只是条件无从读取。缺失字段同样会使 not equals 和 not in 判定失败;关于缺失字段与空字符串的区别,请参阅分支条件如何读取会话数据。 要在沙盒中测试依赖州信息的流程,请从你可控的会话值而非证件出发来决定分支:
  • 创建会话时在 metadata 中发送州信息(例如 "metadata": {"credential_state": "IL"}),并基于 metadata.credential_state 分支。元数据在沙盒中的求值方式与生产环境完全相同。
  • 如果你还需要由证件证明州信息,请在生产流量中保留基于证件的 kyc.region 条件;在生产模式下,地区会从真实证件中读取。
路由的其他所有方面都与生产环境相同:工作流图、分支条件、metadata 和 expected_details 的值、操作节点与状态节点都会真实运行。沙盒本身不会强制将会话转入审核:只有工作流将其路由到审核时,沙盒会话才会进入审核中(即触发 review_* 场景、映射到审核操作的魔法值,或图中存在状态节点)。

OTP 验证码与邮件选择加入

  • 电话 OTP:沙盒电话验证接受任何格式正确的验证码(4 到 8 位数字,包括 123456)。格式错误的输入仍返回 400。
  • 邮箱 OTP:沙盒邮箱验证接受任何格式正确的验证码(包括 123456)。格式错误的输入仍返回 400。
默认情况下,沙盒会话不会发送邮件(包括审核提醒、状态变更、OTP、重新提交、新会话链接等)。如需仍然发送邮件,可对收件人地址使用以下任一选择加入模式:

控制沙盒结果:场景、魔法值、预设与模拟 endpoint

有五种方式可以控制沙盒结果。

1. 创建会话时设置 sandbox_scenario

在创建会话(POST /v3/session/)时设置场景 slug。创建流程会把该场景捆绑的魔法值展开到会话的输入字段中,使模拟的供应商通过真实的工作流管道输出预期结果。

2. 手动输入魔法值

自行设置各个输入字段(例如 expected_details.first_name = "SANDBOX_OCR_DOCUMENT_EXPIRED",或 user_email = "sandbox+aml_hit@didit.test")。完整的注册表见上方的魔法值表格。

3. 在流程开始前预设(或重新预设)会话

对已存在且尚未超过 Not Started 状态的会话,设置或替换预设场景。这是流程前场景选择器调用的接口,您也可以自行调用,以构建自定义选择器或测试工具:
200 响应:
  • 使用会话自身的 Session-Token 进行身份验证(即会话创建返回的 session_token),而不是应用 API 密钥:这是面向客户端的 endpoint。
  • 对未知场景 slug 返回 400;会话超过 Not Started 状态后同样返回 400,并附带消息 "Scenario can only be armed before the verification starts."。
  • 当 Session-Token 属于生产(非沙盒)应用,或与路径中的 session_id 不匹配时,返回 404。
  • 重新预设会替换之前的场景。 它只清除先前场景写入的魔法值,保留用户已手动输入的内容(邮箱、名字等)。例如:先预设 decline_phone_high_risk,再预设 approve,电话号码会恢复为未设置,但客户输入的邮箱在两次调用后都会保留。

4. 模拟接口

事后强制设置终态:
  • 控制台 / API 密钥(需要 write:sessions 权限;限定范围的 API 密钥需要会话的写入权限):POST /v3/session/{session_id}/simulate/
  • 托管流程(Session-Token 请求头):POST /v3/session/{session_id}/sandbox/simulate/
两者均适用于 KYC 和 KYB 沙盒会话。 生产(非沙盒)会话返回 404,Session-Token 与路径中的 session_id 不匹配时同样如此。 请求体中的每个字段都是可选的,但 new_status、scenario、risk 至少需要提供一个: send_webhooks: true 会发送真实状态变更所发送的完全相同的 Webhook:status.updated,以及该变更引起的 user.status.updated 和 user.data.updated 事件(若为企业会话,则为 business.status.updated 和 business.data.updated),发送给订阅这些事件的目标。 当 send_webhooks: false 时,状态仍会变更,但不会记录或发送任何 Webhook。 漏发 Webhook 的恢复机制永远不会重新发送该决定,控制台仍会实时更新。 会话的下一次状态变更将照常发送 Webhook。
200 响应:
  • status 为模拟设置的状态,previous_status 为会话之前的状态。
  • scenario 回显您提供的 slug,risk 为所应用的风险案件;若无则为 null。
  • send_webhooks 回显所应用的值。
  • 对未知的场景或风险、无法推导出 new_status、new_status 为其他任何值,以及会话已处于所请求状态(["The new status is the same as the current status."])时,返回 400。

5. 独立 AML API 上的 sandbox_scenario

后端 AML 筛查没有终端用户,也没有可预设的会话,因此场景 slug 需放在筛查请求本身中(POST /v3/aml/):
  • decline_aml_hit 返回一条符合生产格式的命中结果,并将筛查结论设为 Declined;review_aml_possible_match 则将其设为 In Review。未预设 AML 结果的场景会使筛查保持无命中。
  • 当 save_api_request: true(默认值)时,筛查会像使用正式密钥一样完整保存,因此返回的 request_id 可通过 GET /v3/session/{request_id}/decision/ 和 GET /v3/session/{request_id}/generate-pdf/ 查询。
  • 对未知场景 slug 返回 400;当 API 密钥属于生产应用时,同样返回 400。

sandbox_scenario 出现的位置

已预设的场景 slug(若未预设则为 null)会在部分接口中回显,其他接口则有意省略: 如果您的集成需要在服务端根据已预设的场景进行分支判断,请从 Webhook 信封或任一决策接口(v1 或 v3)读取该值。

用量与计费

沙盒用量会被记录,但绝不收费:
  • 每次模拟调用仍会记录一条用量事件(is_sandbox: true,单价为 0.0000),以便在调试时查看沙盒用量。但这些事件永远不会计入您的用量总计,永远不会从余额中扣除,也永远不会出现在发票上。
  • Business Console 的余额、充值和生产环境用量页面默认会过滤掉沙盒用量。充值用量接口接受 environment 参数(live 为默认值,sandbox 为沙盒),以便单独查看沙盒用量。这些查看操作始终为零成本,且不占用免费额度。
  • 邮箱验证和电话验证按请求而非按会话结果计费,而沙盒无法在 Webhook 层完全模拟这一计费方式。沙盒中的邮箱和电话验证检查仍会为每个请求记录一条用量事件,单价为 0.0000,与其他所有模拟功能相同。这是已知且已被接受的、与生产环境计费行为之间的差异,并非缺陷。
  • 数据库核验在沙盒中的响应结构有意不同于生产环境中按服务商区分的结构,因为沙盒中没有真实的服务商可供模拟。请将沙盒中的数据库核验 payload 视为结果(状态和警告代码)的替代,而非真实服务商响应的逐字节预览。
最后修改于 2026年11月7日