Didit 如何路由交易
当 Didit 客户发起转账时,Didit 会严格按优先级顺序尝试以下通道,并使用第一个能够联系到您的通道:
上表涵盖 Didit 客户发出的转账。当您向 Didit 客户发送转账时,Didit 只能通过以下两种方式接收:一是作为
TRP 转账查询,但须待 Didit 的公共 TRP 主机上线(该主机目前尚未响应,参见 TRP endpoints);二是在结算后作为 Sunrise 登记。目前,没有任何网络通道或邮件通道能将入站转账投递给 Didit 客户。
网络通道(GTR、TRUST、VERIFYVASP、SYGNA)依赖发送方一侧的会员资格运行。目前,这必须是 Didit 客户自己已连接的会员资格:Didit 尚未在这些网络中持有任何平台会员资格,目前正以服务提供方身份办理入驻。GTR 默认不包含在内,且四个网络均适用相同的会员资格要求。发送方应检查 获取 Travel Rule 设置中的 networks 对象:didit 表示 Didit 的会员资格在该网络中以其自身参与方身份承载该应用,own 表示已连接的客户会员资格,off 表示已禁用平台路由,unavailable 表示该应用目前无法通过该网络发送。在 Didit 持有平台会员资格之前,任何网络都不会显示 didit。启用 Travel Rule 并不会激活网络会员资格。各网络目前可触达的范围,参见 Travel Rule 网络。
如果您已接入上述网络之一,且 Didit 客户在该网络中持有自己的会员资格,请将您的网络标识符分享给对方,转账即可通过您已在运营的网络到达您处。
通过 SYGNA 时,您的许可答复将完成或拒绝该转账:Didit 每 5 分钟轮询一次转账状态,同时还会为每个许可请求注册 https://trp.didit.me/sygna/callbacks/permission/{token}/ 作为回调地址,该令牌专为该转账生成。该回调位于 Didit 的公共 TRP 主机上,而该主机目前尚不提供服务。permission_status 为 ACCEPTED 时,发送方的转账将变为 COMPLETED;为 REJECTED 时,转账将变为 COUNTERPARTY_VASP_GENERAL_DECLINE;当 reject_code 为 BVRC007(收款人姓名不匹配)时,转账将变为 COUNTERPARTY_MISMATCHED_DATA。回调需要您的签名:若签名无效或缺失,它将返回 401 及 {"status": "INVALID_SIGNATURE"};对于未知令牌返回 404;对于已应用的决定则再次返回 200。
若双方没有任何共享会员资格,应规划使用 TRP:向 Didit 客户分享您的 Travel Address,其转账即可到达您的 TRP endpoint。您在查询响应中给出的答复会立即完成或拒绝该转账;您之后提交到 Didit 回调的答复,则需要 Didit 的公共 TRP 主机,而该主机目前尚未上线。
当所有通道都无法识别您时,Didit 会再执行一个解析步骤:区块链分析归因。目标钱包会与区块链分析数据进行匹配;若该钱包被归因于您的交易所或托管服务,Didit 会将您的名称记录到其 VASP 目录中,并使用该名称重新尝试这些通道。这意味着,即使发送方只提供了地址,您仍可能被识别。归因转账只有在您的目录条目包含路由时才会自动路由到您:即已验证的 TRP endpoint、网络列表,或合规联系人(参见进入 Didit VASP 目录)。
因此,完整的解析链依次为:先是证明了对该钱包拥有控制权的 Didit 客户(INTERNAL),以及发送方为其存储的 Travel Address;然后是协议和网络通道;最后是区块链分析。
Travel Address
每个启用了 Travel Rule 的 Didit VASP 都有一个 Travel Address。它是一个以ta 开头的紧凑字符串,编码了其专属 TRP 转账查询端点的 URL。
Didit 客户可以在其 Travel Rule 设置中查看自己的 Travel Address,并将其分享给交易对手。当 Didit 客户向您提供其 Travel Address 时,您就已掌握通过 TRP 与其联系所需的全部信息。
编码遵循 TRP Travel Address 约定:
- 去掉
ta前缀。 - 对剩余部分进行 Base58Check 解码(使用比特币字母表,校验和采用双重 SHA256)。
- 解码后的字节即为去掉协议部分的查询 URL;在其前面加上
https://。 - 该 URL 始终带有查询参数对
t=i(类型:查询)。
{profile_uuid} 用于标识托管 VASP 档案。请将转账查询 POST 到该 URL,并先通过对应的身份 endpoint验证您正在通信的对象。
第二种是按钱包的 Travel Address,它指向 Didit 客户的某一个钱包(即其地址簿中的 receiving_travel_address),因此您的查询无需通过账号或账户持有人姓名进行匹配,即可直接到达该钱包。当该钱包被删除,或被记录为属于其他 VASP 后,此地址将返回 404。
TRP endpoints
Didit 在基础 URLhttps://trp.didit.me 上使用 TRP API 版本 3.2.1。
所有 endpoint 均通过 HTTPS 交换 JSON。
两个 TRP 请求头很重要:
api-version- 您使用的 TRP 协议版本,例如3.2.1。 在询问和两个回调上必填。request-identifier- 您为该请求分配的唯一 ID,会在响应头中回显。 在询问和两个回调上必填。
400。
Didit 的每个响应都带有 api-version: 3.2.1,并回显您的 request-identifier。
GET /identity
返回平台运营方的身份。 不需要任何请求头。GET /trp/identity//
返回您即将进行交换的特定 VASP 的身份,可用于在发送个人身份信息(PII)前核验名称和 LEI。 Didit 在发起交换时会反向执行同样的核验:如果端点返回的身份与预期的 LEI 或名称不符,交换将被中止。404。
POST /trp/inquiries//
提交转账询问:您是汇款方 VASP,Didit 客户是收款方 VASP。
在此通道上,资产通过 DTI 标识,且一个 DTI 对应单一区块链上的一种代币。
Didit 目前将
BTC(4H95J0R2X)、ETH(X9J9K872S)和 USDC 映射到九个网络,并会随时间推移添加更多资产。
完整列表请参阅 TRP 资产标识符。
Didit 无法识别其 DTI 的询问仍会被接受,并以该 DTI 作为资产代码展示给收款方 VASP。
返回 200 表示询问已被接受处理;400 表示缺少 TRP 请求头或请求体无效;404 表示配置文件(或按钱包地址指定的钱包)未知或已禁用;422 表示请求使用了 TRP 扩展。Didit 不支持任何扩展,因此包含 api-extensions 请求头或请求体中含 extensions 键的请求会被拒绝。
使用相同的 request-identifier 重新发送是幂等的:会复用原始询问,而不会重复创建。
随后,Didit 在客户的应用中创建入账转账,并根据客户的钱包地址簿和策略进行处理。
匹配收款方的方式依次为:按某个钱包的 Travel Address 所指定的钱包;否则按 IVMS101.beneficiary.accountNumber 中的第一个钱包地址;如果没有钱包地址,则按 beneficiaryPersons[0].naturalPerson 的姓名与客户已验证的钱包条目进行匹配。
当 Didit 能够立即给出结果时,200 响应会包含该结果:
{"approved": {"address": "...", "callback": "..."}}表示询问已被自动批准。Didit 不会再将该批准结果发送到您的callback。{"rejected": "NOT_ENOUGH_COUNTERPARTY_DATA: inquiry carries no beneficiary identification"}表示询问既未指明收款方也未指明钱包地址,因此请务必同时包含两者。{"version": "3.2.1"}表示决定正在等待 Didit 客户处理。随后,处理结果会以 POST 请求的形式发送到您的callbackURL,内容为下面两种正文之一。
originatingVASP 中您的 VASP 名称,就是 Didit 客户所看到的该转账的汇款方 VASP。
Didit 不为您发送的询问设置期限,Didit 客户取消询问时也不会向您发送拒绝通知,因此请自行设置超时。
收到批准并在链上广播转账后,请向您获得的 approved.callback URL 发送 POST 请求,以结束此次交换:
{ "canceled": "reason" }。
txid 会将收款方一侧的转账状态变为 FINISHED;canceled 会将其变为 CANCELLED。
两个回调在处理完成后返回 204;对于未知令牌或不再等待该回调的转账,返回 404;对于既不包含这两个回调字段中任何一个的请求体,返回 400。
处理 Didit 发来的询问
当 Didit 客户通过 TRP 向您发起转账时,Didit 会:- 请求您询问 URL 主机根路径下的
/identity(https://{your-host}/identity),并核对返回的名称和 LEI 是否与客户预期一致。当路由来自 Didit 目录时,您的/identity必须返回该目录条目的 LEI。 - 向您的询问 URL 发送 POST 请求,请求体结构与上文相同,包含
asset.dti、以基本单位表示且为 JSON 数字的amount、callback以及IVMS101payload。
2xx 响应才视为已送达。3xx 会被拒绝,因为 Didit 不跟随重定向;其他任何响应都会记录在客户的转账时间线上,并附上您的状态码,例如 refused by counterparty (HTTP 403): ...。
两个请求都携带两个 TRP 请求头,且 Didit 不会跟随这些请求的 HTTP 重定向,因此请直接提供 /identity 和询问 URL。
如果 /identity 无法访问、未返回 LEI、在客户提供了 LEI 时返回了不同的 LEI,或返回的名称不匹配,Didit 会在发送询问前停止,客户的转账将转为 COUNTERPARTY_VASP_NOT_REACHABLE。
如果随后的询问 POST 失败,或您的 endpoint 以 4xx 或 5xx 状态码响应,转账同样会转为 COUNTERPARTY_VASP_NOT_REACHABLE。
该询问中的 callback 指向 Didit 的解析 endpoint(/trp/callbacks/resolution/{token}/)。
请通过 POST 发送 Didit 所用的相同解析请求体进行响应:批准时发送 { "approved": { "address": "...", "callback": "..." } }(您的 callback 是 Didit 发送链上确认的地址),拒绝时发送 { "rejected": "reason" }。
同时需携带两个 TRP 请求头。
Didit 处理完成后返回 204;转账已不再等待解析时返回 404;批准请求缺少 address,或 callback 不是 Didit 可以调用的公网 http(s) URL 时,返回 400。
批准后,Didit 一侧转为 COMPLETED;客户报告链上哈希后,Didit 会向您提供的确认回调地址发送 { "txid": "..." }。如果转账先被取消,则发送 { "canceled": "reason" }。
回调令牌是为单次用途、不可猜测的密钥,并按转账分别生成。请将完整的回调 URL 视为机密信息。另请注意,只有在转账仍在等待解析时,解析请求才会被接受。
邮件取件
如果没有任何协议通道能够联系到您,且 Didit 客户提供了您的合规邮箱,Didit 会改用邮件方式:您的合规联系人会收到一封邮件,其中注明发起方 VASP,并附有一次性安全取件链接。 无需账户、API 密钥或集成,链接中的令牌即为身份验证凭据。 打开链接后会显示待处理的信息交换;托管页面为您调用的底层 API 是公开的:amount 为存储的原始十进制数,因此完整保留 18 位小数。
decision 可为 accept 或 decline。选择接受时,请提供您记录中的收款人姓名,以便发起方一侧进行姓名匹配;或者将您完整的 IVMS 101 响应作为 ivms_response 发送,此时以其中的收款人姓名为准。
选择拒绝时,您可以提供 decline_reason(data_mismatch、not_our_customer、wallet_not_hosted、sanctions、risk_appetite、jurisdiction、insufficient_data 或 other),以及最多 512 个字符的 decline_detail;选择 other 时必须填写。
如果接受时未提供 beneficiary_name,而发送方提供了收款人姓名(且发送方未关闭姓名匹配),则该记录会被标记为数据不匹配。
响应为最终的 {"status": "..."}:姓名匹配时为 COMPLETED,不匹配时为 COUNTERPARTY_MISMATCHED_DATA,拒绝后为 COUNTERPARTY_VASP_GENERAL_DECLINE。
您只能响应一次,且仅限转账等待您响应期间。若在您已响应之后、转账被取消之后或确认截止时间之后提交,两个 endpoint 都会返回 410;未知令牌返回 404。
请求页面会显示发送方共享的汇款方字段,以及您所在司法辖区语言的 IVMS 101 ivms_request。在您尚未响应期间,系统会在截止时间前 72、24 和 6 小时分别提醒您。
Sunrise: 在信息交换之前已结算的转账
当转账在任何 Travel Rule 信息交换发生之前就已到达 Didit 客户的钱包(因为当时不存在共享通道)时,数据仍可在结算后送达。 请通过您常规的渠道将 Travel Rule payload 发送给 Didit 客户(即您的收款交易对手),并请其进行登记:客户调用POST /v3/travel-rule/inbound/,附上充值的链、txid、地址、金额、币种以及您的汇款人数据。
在该 payload 中,请将您的 VASP 身份信息(名称、LEI 和 Travel Address)作为 originating_vasp 包含在内,以便 Didit 客户的转账记录能显示是谁发出了这笔充值。
该信息仅保存在该笔转账上,不会创建或更改您的目录条目。
LEI 必须是有效的 20 位 LEI,Travel Address 也必须有效,否则登记会被拒绝。
进入 Didit VASP 目录
Didit 维护一份 VASP 目录,客户的出站路由会查询该目录。 目录条目来自以下来源:- ESMA 加密资产服务提供商临时 MiCA 注册库,每周读取一次:包括您的名称、LEI,以及若您已在该库中列明,则为您的所属成员国。
- 公开的 TRISA 目录,每周读取一次:您的身份信息、所在国家/地区,以及您的 TRISA 登记信息。
- 全球 LEI 注册库,用于补充您的 LEI、其他法定名称和所在国家/地区。
- 区块链分析归因:当目标钱包被归属到您的交易所或托管服务时,Didit 会新增或匹配您的条目,并将归因名称保留为别名。
- Didit 工作人员负责整理条目,包括其已核实的路由标识符和网络登记信息、合规联系人、别名,以及品牌与其所属实体的对应关系。
originating_vasp 或转账中的 Travel Address)仅保留在该客户的转账中,绝不会更改您的条目。
您发送给 Didit 客户的转账查询同样不会创建或更新您的条目。
当您的条目包含已验证的 TRP endpoint、发送方可用的网络登记信息,或用于邮件备用通道的合规联系人时,条目即可将转账路由至您。
您自有域名下的合规邮箱地址,若通过其响应链接回复请求,即成为所有 Didit 客户均可使用的联系人。
在您的条目包含路由信息之前,Didit 客户只能通过每笔转账传递的字段联系您:您的 Travel Address、您的网络标识符(counterparty_gtr_vasp_code、counterparty_trust_membership_id、counterparty_verifyvasp_id 或 counterparty_sygna_vasp_code),或您的合规邮箱(counterparty_vasp_email)。
要想现在就能被联系到,请将您的 Travel Address、网络标识符或合规邮箱提供给与您合作的 Didit 客户。
交易对手 VASP 检查清单
- 您已经运行 TRP:请将您的 Travel Address 和 LEI 提供给 Didit 客户。其
BTC、ETH和USDC转账会以标准 TRP 查询的形式到达您的 endpoint。请在查询响应中直接作答;若要稍后作答,则需要 Didit 的公共 TRP 主机,而该主机尚未上线。 - 您使用 GTR、TRUST 或 VerifyVASP:请提供您的网络标识符。当 Didit 客户在该网络中拥有自己的会员资格时,转账将通过该网络到达。Didit 会从网络中读取您的 GTR 或 VerifyVASP 应答,但不会读取 TRUST 应答,因此当通过 TRUST 的交换需要完成时,还需同时发布 TRP endpoint。Travel Rule 网络说明了何时会有所变化。
- 您使用 Sygna Bridge:请提供您的 Sygna VASP 代码。当 Didit 客户拥有自己的 Sygna 会员资格时,Didit 通过轮询读取到您的许可应答后,即可完成或拒绝该转账。
- 您尚无协议通道:请向 Didit 客户提供一个有人监控的合规邮箱。您将收到取件链接,并可通过托管页面作答,无需任何集成。
- 转账已经完成结算:请通过 Didit 客户使用 Sunrise 登记提交数据。
- 您还希望向 Didit VASP 发起转账:请从对方的 Didit Travel Rule 设置中获取其 Travel Address,待 Didit 的公共 TRP 主机上线后,再调用 POST /trp/inquiries。
后续步骤
Travel Rule
面向客户的产品:生命周期、设置、通道,以及 /v3/ API。
钱包所有权组件
当钱包为自托管时,如何收集收款方侧的所有权证明。
Sunrise 登记
为已在链上完成结算的入金登记 Travel Rule 数据。
Webhook
Didit 客户如何在其一侧观察每一次交换状态的变化。