第三方账号授权
本 Skill 有两条相互隔离的链路:天翼账号的显式扫码登录,以及瑞幸咖啡第三方授权。轻喜到家的授权管理当前在 Skill 层暂时隐藏:不要查询、展示或执行轻喜绑定、授权、详情、解绑、取消及登录续接;用户明确提出时,说明“轻喜授权管理暂不可用”。授权列表只显示瑞幸咖啡,不依据服务端返回的其它平台扩展列表,也不要把天翼扫码当成第三方扫码。
详细规则按需阅读:
- A2UI 授权卡片与用户交互:场景、固定字段、按钮、旧卡片点击和降级规则。
- 使用流程:业务路由、状态表、参数示例及完成流程生命周期。
- 结果契约:公共结果、手机号安全投影、幂等和登录交付边界。
- 错误处理:失败、重试、自动重认证和 HTTP 排查。
- 运行态与维护:文件、ctei、签名和两条登录链路的隔离。
- 退出登录:仅处理天翼账号退出和重新登录。
瑞幸授权与显示边界
Skill 当前只支持 luckin(瑞幸咖啡)的第三方授权管理。所有授权查询必须显式使用 --platform-code luckin;绑定、详情、解绑、取消和重试也必须使用 luckin。不得调用 qingxi,不得续接轻喜授权的旧 pending,也不得把其它平台放进授权列表。用户要求轻喜授权管理时,直接说明“轻喜授权管理暂不可用”,不调用授权命令。
卡片品牌、协议、隐私政策和 logo 一律读取瑞幸 query 的 cardConfigs.luckin,配置缺失时不自行编造素材。缺少绑定卡片必填链接时用文字明确确认授权。轻喜平台契约仅保留作内部维护参考,不属于当前 Skill 可调用或展示的能力。
先判断用户意图
当前用户消息优先于旧流程中的模糊文本。品牌和操作必须同时明确;裸“确定”“同意”“重试”不是一律拒绝:当前上下文中恰好只有一个未过期、完整且明确指向当前品牌操作的流程时可以承接,否则追问“要确认绑定,还是取消授权?”等具体意图。
| 用户意图 | 操作或下一步 |
|---|---|
| 查询授权、查看我的授权 | query --platform-code luckin 后按瑞幸结果展示 auth_manage_list |
| 管理轻喜到家授权 | 说明“轻喜授权管理暂不可用”,不调用授权命令 |
| 绑定瑞幸咖啡、去授权绑定瑞幸咖啡 | 先建立本次意图的 ID/主 trace,再用相同标识查最新 query,未绑定才进入绑定确认 |
确认授权绑定瑞幸咖啡 |
仅在当前绑定确认上下文中执行 authorize |
暂不授权瑞幸咖啡 |
未绑定的当前绑定流程带匹配的 requestId/traceId 执行 cancel --platform-code luckin --authorization-request-id <绑定ID> --trace-id <绑定主traceId>,随后展示暂不授权结果 |
列表入口 取消瑞幸咖啡的授权 |
先查最新状态,再创建或复用独立解绑确认流程 |
确认取消瑞幸咖啡的授权 |
仅在当前解绑确认上下文中执行确认解绑 |
暂不取消瑞幸咖啡的授权 |
取消当前解绑确认,保留授权 |
重试绑定瑞幸咖啡 / 取消授权失败卡片中的 取消瑞幸咖啡的授权 |
只有当前有效的已确认失败流程才复用原标识重试 |
登录天翼账号 / 已登录 |
走显式 AST 登录入口及其安全用户投影 |
重新登录天翼账号 |
user_message → ast_relogin,清理后重新扫码 |
退出登录、退出天翼账号、注销登录 |
ast_logout;保留第三方授权关系 |
“退出登录”不能映射为 cancel、query 或 unbind;“取消授权”不能映射为天翼账号退出。“取消”没有唯一上下文时先澄清。退出和重新登录的用户文案只使用 ast_logout/ast_relogin 的安全投影,规则见 退出登录。
命令入口
以本文件所在目录为 Skill 根目录,使用随包发布的 scripts/authorization_cli.py。先运行离线检查,之后只执行与用户意图对应的命令,不因检查自动查询:
cd /absolute/path/to/third-party-account-authorization-v1
python3 scripts/authorization_cli.py check
check 不读取认证材料、不访问网络,也不证明服务可用;发布包应包含 query、authorize、detail、unbind、cancel、ast_login_start、ast_login_status、ast_logout、ast_relogin 和 user_message。缺少所需操作时提示更新 Skill 包,不能用 cancel 冒充退出或解绑。
运行时要求 Python 3.10+ 和 cryptography。依赖缺失时使用宿主提供的 Python 环境或独立虚拟环境安装;不要改用手写 curl、临时 Python HTTP 请求或其它登录 Skill。
默认地址为 https://open.e.189.cn/api/agent。第三方路由固定为 /ast/third-account/bindings/{query|authorize|detail|unbind},均为 POST JSON;AST 使用 /ast/login/start、/ast/login/status/{ticket},旧 /ast/login/qrcode 仅为兼容客户端保留,本 Skill 不调用。只有部署配置明确给出地址时才为所有命令统一加 --base-url <已确认地址>,不要猜测路径、域名或协议。
授权管理命令只允许瑞幸;查询时必须显式使用 --platform-code luckin:
| 场景 | 命令 |
|---|---|
| 查询瑞幸授权状态 | python3 scripts/authorization_cli.py query --platform-code luckin |
| 绑定意图内查询瑞幸状态 | 同一命令附带 --authorization-request-id <绑定ID> --trace-id <绑定主traceId>;解绑入口查询不预设解绑 ID |
| 明确确认绑定 | python3 scripts/authorization_cli.py authorize --platform-code luckin --authorization-request-id <绑定上下文ID> --trace-id <绑定主traceId> |
| 绑定/解绑失败卡片重试 | 使用卡片给出的对应重试文本;调用时复用原 operation、authorizationRequestId 和主 traceId |
| 创建解绑确认 | 最新 query 为 BOUND 后执行 python3 scripts/authorization_cli.py unbind --platform-code luckin,不传预设解绑 requestId/traceId;使用返回 BIND_CONFIRM_REQUIRED 中的两个实际标识 |
| 明确确认解绑 | python3 scripts/authorization_cli.py unbind --platform-code luckin --confirmed --authorization-request-id <解绑pending的ID> --trace-id <解绑主traceId> |
| 暂停当前流程 | python3 scripts/authorization_cli.py cancel --platform-code luckin --authorization-request-id <当前流程ID> --trace-id <当前流程主traceId> |
| 自动登录完成后续接 | python3 scripts/authorization_cli.py ast_login_status |
绑定意图在第一次 query 前由客户端/Skill 生成并保存,query、登录续接和 authorize 一路复用;解绑入口先做不带预设解绑标识的只读 query,确认仍为 BOUND 后调用不带 requestId/traceId 的 unbind --platform-code luckin,由该调用创建或返回独立 pending 及其实际两个标识。后续确认、取消和失败重试只能使用该 pending 返回的 authorizationRequestId/traceId,绑定与解绑 ID 不得混用。命令输出是机器 JSON,退出码 0 只代表命令完成;按 status 和当前上下文路由,不能把原始 JSON 直接贴给用户。
瑞幸业务流程
以下授权流程只适用于瑞幸咖啡,始终使用 platformCode=luckin 和服务端 cardConfigs.luckin。
- 查询时始终使用
query --platform-code luckin,不查询全平台映射。只有BOUND或NOT_BOUND才能展示只含瑞幸单项的授权管理列表,其他状态不伪造列表。 - 用户要求绑定瑞幸时先建立绑定意图、
authorizationRequestId和主traceId,再用相同标识查询最新状态。若已绑定,停止绑定并展示brand_auth_already_bound;若未绑定,在 Skill 交互上下文保存确认信息,然后展示brand_auth_binding。query 不创建 Python 绑定确认 pending。 - 只有当前绑定上下文收到精确的
确认授权绑定瑞幸咖啡,或在唯一有效上下文中收到语义等价且明确指向当前品牌绑定的确认,才调用authorize。收到精确的暂不授权瑞幸咖啡时,只取消当前匹配的绑定上下文并展示brand_auth_skip;不发授权请求。 authorize返回BOUND后展示brand_auth_success;只有最新 query 或服务端明确已绑定状态才展示brand_auth_already_bound,普通冲突/失败不能当作已绑定;失败则展示brand_auth_fail,其重试文本只在流程仍有效且确已确认时可直接重试。授权成功结果按既有结果定义交付,不展示工具原始 JSON,也不重复调用授权副作用。- 瑞幸列表中的解绑入口必须先查最新状态。只有 query 返回
BOUND时才调用不带预设 ID 的unbind(platformCode=luckin, confirmed=false),使用其返回的实际 pending 两个标识后展示brand_revoke_auth;未授权或 query 失败时不发送解绑请求,刷新或按状态文字说明。确认解绑前不能调用有副作用的解绑请求。 - 解绑确认成功返回
NOT_BOUND后调用brand_revoke_success;返回BIND_FAILED后调用brand_revoke_fail。两个结果卡片只传固定brand_name,按钮参数使用卡片默认值;卡片失败时再降级为文字。结果卡片的“去授权”进入新的绑定流程,失败卡片的“取消授权”只在当前失败解绑上下文中重试;用户查询绑定状态时再调用query展示auth_manage_list。暂不解绑只用文字说明“已保留瑞幸咖啡的授权”,不触发解绑或其它副作用。
旧卡片或迟到消息必须先查最新状态。具体分支、完成流程失效和失败重试规则见 A2UI 卡片 与 使用流程:完成的绑定/解绑流程不能因旧 requestId 命中幂等账本而重放;只有未过期、上下文完整、已确认且失败的同一流程可复用原标识重试。若旧绑定卡片与当前 AST 登录 pending 或解绑 pending 的 requestId/traceId 不匹配,不能调用无参数 cancel 清理其它流程;query 返回 AST_LOGIN_REQUIRED、BINDING 或其它失败时也不能当作 NOT_BOUND 出暂不授权结果。
A2UI 调用总则
所有授权卡片只使用唯一工具:
scm__scene_card_map({ scene_id, apiData })
运行时先确认工具存在。每次卡片调用前先向用户给出一句安全文字引导,再调用工具;工具返回通过宿主的卡片通道交付,不展示原始 JSON,不手写 a2ui://,不改写按钮文字,不因渲染失败重做业务请求。工具缺失、调用失败或必要字段缺失时使用安全文字降级;只要用户随后给出当前品牌和操作都明确的确认,仍按相同流程执行,不能借降级扩大授权范围。
开放场景只有 auth_manage_list、brand_auth_binding、brand_auth_success、brand_auth_fail、brand_auth_already_bound、brand_auth_skip、brand_revoke_auth、brand_revoke_success 和 brand_revoke_fail。brand_auth_qr_bind 本期不开放;不要使用其它未定义场景名。完整 apiData 字段及服务端平台展示配置见 A2UI 卡片。
天翼登录隔离
显式 ast_login_start/status 只负责天翼认证和显式 loginData 置换;扫码二维码、登录链接及其话术只能称为天翼账号登录。其成功结果按 login_success.json 契约交付,不能当作第三方授权成功。
query、authorize、detail、unbind 在实际发第三方请求前独立读取并校验 ctei、AST session、Agent identity 和私钥;不读取 login_success.json,不调用 loginData 置换。第三方自动 AST 重认证只保存 session、identity、private key,随后恢复原业务;不把 loginData、AST token、二维码原文放入 pending、公共结果、卡片或用户话术。/ast/login/start 成功必须同时返回登录链接和二维码,缺少任一字段都按登录启动失败处理,不能创建只有链接的登录 pending,也不能改走第三方扫码场景。
一次业务意图建立的主 traceId、平台和操作在登录续接、恢复及有效重试中保持不变;新意图才生成新标识。ctei、pending、敏感材料、结果投影和错误处理的维护细节分别见 运行态与维护、结果契约 和 错误处理。
用户可见内容只包含安全文字、脱敏手机号、协议链接、卡片或登录二维码图片/链接。缺少脱敏手机号时不得填“未知”、示例号码或其它占位值;绑定卡片不完整时改用安全文字说明展示信息暂不可用。