Widget 用户会话列表
发布状态 · 2026-09-14
用户会话列表、消息摘要和未读数已部署至 api.open4x.com 与 widget.open4x.com,生产数据库已升级至 0054。商户仍需完成自己的身份授权、Session 接口和业务验收;本次功能发布不代表 SLA、DPA 或商业生产验收已完成。SDK 仍通过确认版本的交付包提供,不代表公共 npm 包已发布。
Widget 2.3.7 起,用户可查看本人获授权的个人咨询和订单客服会话,不要求每一条都曾在 Widget 中打开。原有有效绑定继续使用;没有绑定的普通客服会话按活动 customer 身份列出,唯一客服接收人时首次打开自动建立绑定,多接收人需商户明确配置。已撤销绑定不自动恢复。详见统一 Session和用户分组。
图片与文件是独立扩展,开通条件见聊天图片与文件。列表 Token 不能直接上传附件。
两种接入方式
如需后端决定个人、客服或管理员身份,前端仍使用同一个 Widget,见统一 Session 接入。
| 方式 | 用途 |
|---|---|
| Widget 内置列表 | 商户签发用户列表 Token,Widget 自动获取列表、分页和切换 |
| 商户自有列表 | 商户后端调用列表 API,自行展示页面;进入会话仍需业务授权及短期 Session |
这里的用户是商户网站的用户,不是 Open4X Console 账号。列表不复用租户管理员 Inbox API,也不需要给用户 conversation:supervise。
1. 网站后端签发列表 Token
网站实现自己的 POST /api/open4x/customer-session。校验登录、CSRF/来源、速率限制,从服务端登录态取得 external_user_id,然后调用:
POST /v1/conversations/customer-session
Authorization: Bearer <服务端 Bridge Key>
Content-Type: application/json
{"external_user_id":"site-a:user-123","ttl_seconds":1800}需要 conversation:read 和 conversation:write,TTL 为 900–3600 秒。响应:
{"data":{"session_token":"<用户列表短期JWT>","expires_in":1800}}只把此短期 Token 返回给当前用户,设置 Cache-Control: no-store,不记录 Token。它不是 Bridge Key,也不是某一会话的聊天 Token。网站退出或切换账号时必须调用 Widget destroy(),重新登录后签发新 Token。
同一租户的不同网站应给用户 ID 加稳定站点前缀。必须与之前创建 Widget Session 时的 external_user_id 完全一致,不能每次随机生成。
2. Widget 自动显示“我的会话”
沿用本地交付的 React 组件,只将 Session 地址指向上一步:
<Open4XSupportWidget
sessionUrl="/api/open4x/customer-session"
widgetUrl="https://widget.open4x.com"
gatewayUrl="https://api.open4x.com"
autoOpen
/>以上为本功能已部署的正式域名。staging 使用配套交付地址,不与生产数据混用。组件仍来自已确认的 SDK 交付包,不保证公共 npm 发布。
Widget 按 Token 类型选择列表或单会话。列表支持加载、空状态、失败重试、分页、返回列表、Token 过期提示;选择会话后重新挂载单会话界面,避免旧消息混入下一会话。列表 Token 仅保留在内存,Loader 使用 URL fragment 而不是查询参数传递 Token。不要把含 Token 的完整浏览器地址分享到聊天或截图。
服务器端 SDK 新增 createCustomerSession、listCustomerConversations;Fetch 框架可使用 createOpen4XCustomerSessionHandler。其 resolve(request) 必须完成商户登录、CSRF 和业务校验,返回可信身份或 null,不能照抄浏览器提供的用户 ID。
3. API 合同
可选左侧栏与入口未读提醒(已发布)
已于 2026-09-16 部署至正式 Widget 和 Gateway。使用本地 SDK 的商户需同步更新 SDK 类型与组件;自托管 Widget 的商户需升级静态资源。 使用用户列表 Token 时,宽度超过 620px 会显示左侧会话列表和右侧原有聊天组件;手机与小窗口在列表和聊天之间切换。 showConversationList 默认 true。2.3.7 起设为 false 时隐藏侧栏和返回列表按钮;conversationId 可指定默认会话,没有默认会话时打开最新一条。这只是布局,不改变凭证权限。重新配置为 true 可恢复列表入口。
<script src="https://widget.open4x.com/widget.js"
data-lazy="true"
data-show-conversation-list="true"
data-show-unread-badge="true"></script>从网站后端取得短期列表 Token 后初始化,也可随时修改:
Open4XWidget.init(customerSessionToken, {
gatewayUrl: 'https://api.open4x.com',
showConversationList: true,
showUnreadBadge: true
});
Open4XWidget.configure({ showConversationList: false });
const unread = Open4XWidget.getUnreadCount();React 组件支持同名属性;自定义标签支持 show-conversation-list="false" 和 show-unread-badge="false"。 右下角角标默认开启,超过 99 显示 99+。它统计当前用户全部可访问会话,不只是列表第一页,也不会因为打开窗口就归零。 页面可见且在线时,每 30 秒查询一次;页面隐藏/离线时暂停网络请求,错误时退避,401/403 或 Token 到期时停止,退出/切换账号清除旧计数和请求。 关闭角标同时关闭 Loader 的未读轮询。这里只保证用户列表 Token 的跨会话汇总,单会话 Token 不会获得其他会话权限,也不自动启用该汇总。
GET /v1/apps/bot/widget/conversations/unread
Authorization: Bearer <用户列表Token>{"data":{"unread_count":12}}响应 Cache-Control: no-store;不返回正文、不修改已读记录,不接受浏览器覆盖用户身份。此查询不分页,排除自己发送的消息、内部备注、发给其他人的消息及已撤销会话。沿用 Widget 限流,不承诺即时推送或无限调用。
商户服务端查询
GET /v1/conversations/customer-conversations?external_user_id=site-a%3Auser-123&limit=20
Authorization: Bearer <服务端 Bridge Key>需要 conversation:read,只能从商户服务端使用。Bridge Key 可以查询该租户的不同网站用户,因此商户必须在后端固定为当前登录身份,不能提供任意用户查询代理。
Widget 或自有浏览器 UI 查询
GET /v1/apps/bot/widget/conversations?limit=20
Authorization: Bearer <用户列表Token>{
"data": [{"id":"conv_example","conversation_type":"general_support","status":"open","created_at":"2026-09-14 00:00:00","unread_count":1,"last_message":{"id":"msg_example","text":"您好,您的问题已收到。","created_at":"2026-09-14 01:00:00","sender_role":"support_agent"}}],
"pagination": {"has_more":false,"next_cursor":null}
}limit 为 1–100,默认 20。下一页原样传响应的 next_cursor 作为 cursor,不要自行拼接游标。不能通过查询参数改变 Token 中的用户身份。
客服分组扩展 已于 2026-09-16 发布到生产,新增 context_type/context_id,并改为按本人最新可见公开消息时间降序,无消息使用创建时间,同时间按 ID 升序。其他环境请单独确认版本。新消息到来后应刷新第一页,分页不是固定快照。
恢复原聊天
POST /v1/apps/bot/widget/conversations/conv_example/session
Authorization: Bearer <用户列表Token>无请求体。返回 data.conversation_id、data.session_token、data.expires_in。这里返回的是单会话聊天 Token,其有效期不超过列表 Token。复用原有 Chat ID 和服务端收件人,不重新创建会话、不自动恢复被撤销的权限,也不改变已关闭工单的业务状态。
通用错误:400 参数错误;401 Token/签发 Key 失效;403 类型或 Scope 不符;404 会话不存在或不再可访问;409 原收件人为空或失效,需商户重新配置;429 限流。失败时不要扩大权限重试。沿用平台 request_id 和错误规范。
权限和限制
消息摘要与已读
last_message 是该用户最后一条可见消息,按消息序号确定,文本最多前 200 个 Unicode 字符;无可见消息时为 null。这是文本摘录,不是 AI 摘要,无模型调用费。前端必须作为文本渲染,不能作为 HTML。
unread_count 仅统计其他参与者发出的、当前用户可见且尚无已读记录的消息。自己的消息、内部备注和发给其他人的私聊不计数。状态按用户的参与者外部 ID 持久化,可跨设备共享。用户多个身份的会话按实际恢复的活动 Widget 参与者计算。
进入会话或查询历史本身不会清空未读。Widget 在页面可见且消息进入可视区域后批量上报;自有 UI 使用单会话聊天 Token(不是列表 Token 或 Key)调用:
POST /v1/apps/bot/widget/read
Authorization: Bearer <单会话聊天Token>
Content-Type: application/json
{"message_ids":["msg_example"]}每次 1–50 个消息 ID,返回 {"data":{"acknowledged":true}}。不可见、不存在或其他会话的 ID 被忽略,不披露匹配数量。重复提交安全;只标记提交的可见消息,不推进“全部已读”游标,因此尚未加载的旧消息和同时到达的新消息仍保持未读。收件人权限已撤销时拒绝请求。
返回列表或刷新时从服务器重新获取计数;不会仅靠前端乐观归零。429 按 Retry-After 重试,失败期间可能暂时保留未读。接口使用原有已读回执表,无需新增数据库迁移。
- 仅列出已存在的 Widget Chat,并且活动渠道记录中的外部用户 ID 匹配。仅作为参与者加入但从未创建 Widget Session 的会话不会出现,旧版无参与者绑定的 Bot Chat 不包含在内。
- 当前参与者必须是活动的
customer或creator,租户、渠道、Chat、参与者和删除状态都会复查。 - 停用/移除参与者、撤销 Chat、停用渠道或安排会话删除后不可恢复;签发 Key 过期、吊销或丢失 Scope 后,列表及派生聊天令牌失效。
- 未新增单独撤销某个列表 JWT 的接口。退出时清除客户端,令牌到期自动失效;紧急撤销使用 Key 或对应 Chat/参与者权限。Key 撤销会影响使用同一 Key 的其他用户。
- 列表返回会话 ID、类型、状态、创建时间,以及用户可见的消息摘录、未读数;不返回内部备注、其他人的私聊、订单元数据、客户姓名和附件内容。
- 如果商户业务权限发生变化,需同步撤销 Open4X 参与者或 Chat;Open4X 无法自行推断订单授权已失效。
- AI 关闭不影响本功能。浏览器接口使用已有 Widget 限流,商户服务端接口使用实际 Key 配额;不承诺无限调用。
分步 AI 提示词
让 AI 接入用户会话列表
请在当前网站接入 Open4X Widget 用户会话列表,保留指定订单的单会话入口。
先读 https://docs.open4x.com/zh/guide/customer-conversation-list 和 https://docs.open4x.com/openapi/open4x.openapi.json,确认本功能已在目标环境部署;未部署只做 mock,不假定生产可用。
在商户后端实现 /api/open4x/customer-session,校验现有登录、CSRF/Origin 和限流;从服务端取得带站点前缀的稳定用户 ID,与原 Widget Session 身份一致。使用服务端 Bridge Key 调用 /v1/conversations/customer-session,只返回短期列表 Token,响应 no-store。密钥不要进前端或日志。
把本地交付的 Open4XSupportWidget 的 sessionUrl 指向此接口。用户退出或切换账号先 destroy,取消旧请求后重新签发。不要直接把管理员 Inbox 接口开放给浏览器。
测试列表、分页、返回及切换后历史恢复、两用户隔离、内部信息不泄露、参与者/渠道/Key 撤销、空列表和过期。原单会话入口也要测试。列表不会自动创建新会话,创建咨询仍走原来的业务入口。
交付代码、配置位置、测试证据和未验证项。不索要完整 Key,不自动发布生产或发送真实消息。