HTTP 响应已发出,但工作流仍在运行:让验证状态如实反映真相

先在免费沙盒中跑通流程,再准备生产接入。

统计选择在本站复用,可随时关闭;账号关联另行同意。

HTTP 响应已发出,但工作流仍在运行:让验证状态如实反映真相

n8n 的一个公开 issue 描述了这样一种情况:一个 webhook 工作流已经返回了成功的 HTML 响应,而它的执行(其中包含 PostgreSQL 节点)仍显示为运行中。我们无法诊断或修复这个厂商问题,也不代表任何受其影响的人。但它为构建身份引导流程的团队引出了一个相邻的问题:当 HTTP 层显示已完成,而背后的工作尚未结束时,你的应用应当如何看待一个验证会话?本文借助合成 fixture verification_delivery 回答这个问题,帮助你判断沙箱集成是否适合你的任务。

curl https://gridzen.ai/console/api/quickstart/trial \
  -H 'Content-Type: application/json' \
  -d '{"task": "identity_onboarding", "scenario": "success"}'

接入指南

问题与你的决策

200 响应只告诉发送方请求已被接收。它并不说明数据库写入已经提交、决策已经记录,或权限已经变更。如果回调处理器先返回响应、随后卡住,可能出现三种结果:会话状态可能过期,更新可能只完成了一部分,也可能收到重试的回调。你需要决定的是以什么作为事实来源。我们建议以带截止时间的持久化会话状态为准,而不是以 HTTP 结果或某个执行是否存在为准。卡住或缺失回调的会话绝不能变成批准。

fixture 实际实现了什么

可下载示例用 SQLite 存储会话和事件。create 步骤记录一个带截止时间的 pending 会话,默认截止时间为 60。event 步骤做四件事:拒绝任何非合成 fixture_callback 的输入,并抛出 PRODUCTION_SIGNATURE_VERIFIER_NOT_IMPLEMENTED;校验 tenant 与 subject 的绑定;在单个即时事务中按事件 ID 去重;对状态进行规范化。recover 步骤在截止时间过后将 pending、review 或 unknown 会话标记为 expired。该步骤在本地运行,不会轮询任何提供商。每次读取都返回 live_permission_changed: false。fixture 中授予的权限只是本地记录,并非业务权限。

假设场景演练

假设你的回调处理器很快返回了响应,但数据库步骤挂起了。你使用同一个 SQLite 文件重启服务。 创建会话返回 state simulated、位于 example.invalid 下的 hosted_link、link_executable false,以及 next send_real_provider_link_only_after_authorization。 一个带显式策略的合成 Approved 事件返回 status approved、deadline 60、permission_granted true 和 grant_count 1。 如果发送方重试同一事件,结果完全相同:grant_count 仍为 1。 随后的 Declined 更正返回 status declined 和 permission_granted false,grant_count 保持为 1。 在另一个始终没有收到回调的会话中,以 now=61 调用 recover,返回: - status expired - permission_granted false - grant_count 0 - next review_or_authorized_provider_refresh - provider_polled false

由你负责的失败处理

fixture 会报告两种错误:针对未知会话的事件抛出 BINDING_MISMATCH,读取未知会话抛出 SESSION_NOT_FOUND。应将两者视为需要排查的信号,而不是盲目重试的理由。以下是建议的应用设计,本示例并未实现: - 在确认响应之前先提交状态,或者只在事件以幂等方式持久化之后才确认。 - 对临近截止时间仍处于 pending 的会话发出告警。 - 使用有上限的重试。 - 将已过期的会话转入人工审核或经授权的状态刷新。 生产系统还需要针对具体提供商的签名校验,以及有上限的状态对账。fixture 未证明具备其中任何一项。

需要明确说明的限制

fixture 事件只接受合成回调,从不接受真实签名。recover 仅在本地将会话过期,从不联系提供商。合成授权不是真实的业务权限,而且在任何情况下 Approved 都不等于无条件权限。该指南还提供一个简短的匿名 HTTP 试用,它与可下载示例及其分支测试是两回事。测试通过只证明模拟的状态转换,不证明生产环境下能够成功。真实路由是否可用需要另行确认。

验收清单

- 复用同一数据库时,重启测试和超时恢复测试均通过。 - 重复事件不会改变 grant_count。 - Declined 更正会将 permission_granted 设为 false。 - 已过期会话显示 provider_polled false,并指向人工审核。 - 绑定未知的事件会被拒绝。 - 没有任何代码路径把 HTTP 200 或运行中的执行视为批准。 - 你自己的设计文档写明由谁执行授权刷新、由谁进行审核。

运行已检查的模拟示例

下载并解压 https://gridzen.ai/downloads/verification-delivery.zip,进入 verification_delivery,用 Python 3.10+ 运行。此本地示例不联网;独立身份实验请使用新的数据库。

python3 delivery.py identity --db /tmp/gridzen-article-fixture.sqlite

来源与范围

https://gridzen.ai/guides/missing-verification-webhook/ https://gridzen.ai/guides/current-capabilities/ 依据已检查的来源快照与本地模拟;建议的业务规则属于设计建议,不代表已证明的生产行为。内容使用 AI 辅助写作,并经过独立审稿。

另行体验三种沙盒结果 创建账号,继续项目接入

下载不等于运行成功;本地示例与在线沙盒分别测试。

接入你的应用

运行三种模拟结果 · 需要接入帮助

连接免费沙盒账号

号码基础有效性不证明持有权或送达,不提供短信验证码。业务放行由你的系统判断。