@alipay/alipay-aipay 1.7.9 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/skill/SKILL.md +34 -3
- package/skill/VERSION +1 -1
- package/skill/references/integration/flow.md +2 -0
- package/skill/references/integration/modules/checklist.md +4 -2
- package/skill/references/integration/modules/code-examples/csharp/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +3 -1
- package/skill/references/integration/modules/code-examples/java/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemoController.md +3 -1
- package/skill/references/integration/modules/code-examples/nodejs/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +6 -2
- package/skill/references/integration/modules/code-examples/php/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +3 -1
- package/skill/references/integration/modules/code-examples/python/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +8 -3
- package/skill/references/integration/modules/interface-contract/aipay-interface-contract.md +3 -1
- package/skill/references/integration/modules/interface-contract/apppay-interface-contract.md +3 -3
- package/skill/references/integration/modules/interface-contract/common-trade-contract.md +8 -8
- package/skill/references/integration/modules/interface-contract/notify-url-contract.md +7 -7
- package/skill/references/integration/modules/interface-contract/webpay-interface-contract.md +2 -2
- package/skill/references/integration/modules/sandbox/a2m-sandbox-test.md +4 -4
- package/skill/references/normal/conversation-telemetry.md +103 -0
- package/skill/references/normal/json/customer-messages.json +1 -1
- package/skill/references/normal/scripts/conversation_consent.mjs +76 -0
- package/skill/references/normal/scripts/conversation_telemetry.mjs +200 -0
- package/skill/references/normal/scripts/render_customer_message.mjs +2 -0
- package/skill/references/normal/scripts/runtime.mjs +1 -0
- package/skill/references/normal/scripts/telemetry.mjs +618 -74
- package/skill/references/runtime-entry.md +7 -1
- package/skill-pre/VERSION +1 -1
- package/skill-pre/references/integration/flow.md +7 -3
- package/skill-pre/references/integration/modules/checklist.md +4 -2
- package/skill-pre/references/integration/modules/code-examples/csharp/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +3 -1
- package/skill-pre/references/integration/modules/code-examples/java/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemoController.md +3 -1
- package/skill-pre/references/integration/modules/code-examples/nodejs/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +6 -2
- package/skill-pre/references/integration/modules/code-examples/php/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +3 -1
- package/skill-pre/references/integration/modules/code-examples/python/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +8 -3
- package/skill-pre/references/integration/modules/interface-contract/aipay-interface-contract.md +3 -1
- package/skill-pre/references/integration/modules/interface-contract/apppay-interface-contract.md +3 -3
- package/skill-pre/references/integration/modules/interface-contract/common-trade-contract.md +8 -8
- package/skill-pre/references/integration/modules/interface-contract/notify-url-contract.md +7 -7
- package/skill-pre/references/integration/modules/interface-contract/webpay-interface-contract.md +2 -2
- package/skill-pre/references/integration/modules/sandbox/a2m-sandbox-test.md +4 -4
- package/skill-pre/references/integration/modules/sandbox/sandbox-setup-guide.md +2 -2
- package/skill-pre/references/normal/conversation-telemetry.md +9 -9
- package/skill-pre/references/normal/full-process-routing.md +2 -2
- package/skill-pre/references/normal/scripts/conversation_telemetry.mjs +113 -18
- package/skill-pre/references/normal/scripts/telemetry.mjs +243 -32
- package/skill-pre/references/normal/windows-environment.md +4 -4
- package/skill-pre/references/runtime-entry.md +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alipay/alipay-aipay",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "支付宝 AI 付接入 Skill 安装包 - 优先安装 Agent Skill,并在 macOS/Linux 后台准备用户级 CLI 工具",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"typescript": "^5.3.3"
|
|
56
56
|
},
|
|
57
57
|
"alipayAipayChannels": {
|
|
58
|
-
"stable": "1.7.
|
|
59
|
-
"pre": "1.
|
|
58
|
+
"stable": "1.7.7",
|
|
59
|
+
"pre": "1.8.0-pre"
|
|
60
60
|
}
|
|
61
61
|
}
|
package/skill/SKILL.md
CHANGED
|
@@ -7,7 +7,7 @@ description: >-
|
|
|
7
7
|
|
|
8
8
|
# 支付宝 AI 付接入 Skill 启动器
|
|
9
9
|
|
|
10
|
-
本文件只负责在加载业务规则前确定本轮实际使用的 Skill 版本、完成 Windows
|
|
10
|
+
本文件只负责在加载业务规则前确定本轮实际使用的 Skill 版本、完成 Windows 渠道选择和会话采集选择,并刷新本机 `alipay-cli`。禁止在完成下列启动协议前读取 `references/runtime-entry.md`、任一 flow、模块或业务脚本;Windows 渠道提示和采集说明仅由下述固定 runtime 入口读取消息目录。声明展示和明确同意前,不得采集、缓存或上传会话正文。
|
|
11
11
|
|
|
12
12
|
## 前置启动协议
|
|
13
13
|
|
|
@@ -67,7 +67,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" channel-offer show
|
|
|
67
67
|
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" channel-offer decide --reply "<USER_REPLY>"
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
仅唯一 `ALIPAY_AIPAY_INTERNAL:CHANNEL_OFFER=PRE` 可进入内测安装;`STABLE`
|
|
70
|
+
仅唯一 `ALIPAY_AIPAY_INTERNAL:CHANNEL_OFFER=PRE` 可进入内测安装;`STABLE` 表示继续本正式版,记录已处理并进入下方会话采集选择。`UNDECIDED` 表示用户在提问或表达不确定,先回答或澄清,仍等待明确选择;不能把业务催促、泛泛的“继续/OK/1”或通用 `reply confirm` 当作内测授权。任一错误或 marker 不唯一时停止渠道切换,禁止安装。用户以后明确提出切换时,可重新进行这一选择,不受已处理事实限制。
|
|
71
71
|
|
|
72
72
|
`PRE` 后先执行固定只读预检,确认 npm latest 的预发渠道已包含 Windows 改造版;本地当前工作区或尚未发布的版本不能代替线上事实:
|
|
73
73
|
|
|
@@ -91,7 +91,38 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" channel-offer available
|
|
|
91
91
|
- `INSTALL_TIMEOUT` 或其他安装失败:状态未知,不自动再次写入;说明失败并提供恢复后重试或继续正式版的选择。用户确认安装进程已结束、故障已处理后最多重试一次,不并发启动安装器。
|
|
92
92
|
- `VERIFY_FAILED`、成功 marker 缺失/冲突或安装目录无法读取:不宣称已切换,不加载旧版替代;说明安装结果未通过核验,修复后最多重新安装一次并完整复核。耗尽预算仍保留可用正式版,等待用户选择修复环境或继续正式版,不自动转站点、不重新展示推荐循环。
|
|
93
93
|
|
|
94
|
-
上述安装重试始终使用已保存、原先判为 `PRE`
|
|
94
|
+
上述安装重试始终使用已保存、原先判为 `PRE` 的同一条完整回复;用户后来拒绝或切回正式版则立即取消重试。选择继续正式版时记录已处理并进入下方会话采集选择,保留原任务,不要求重复描述需求。此选择发生在正式版 telemetry 启动前,不为渠道提示或预发安装创建正式版 run。
|
|
95
|
+
|
|
96
|
+
## 会话采集选择
|
|
97
|
+
|
|
98
|
+
Windows 渠道选择和采集授权是两个独立选择。非 Windows 或确定继续正式版后才进入本节;切换内测版则只执行其已有内测声明。不得将此前 Windows 安装确认、“继续正式版”或历史业务确认当作本声明的回复。
|
|
99
|
+
|
|
100
|
+
已确定继续正式版后、任何 CLI 刷新、会话解析或业务入口加载前,必须先执行以下固定声明动作;此前仅允许完成上述必要的 Windows Node 准备、自更新检查及 Windows 渠道选择与对应的安装核验、恢复动作,不得采集、缓存或上传会话正文:
|
|
101
|
+
|
|
102
|
+
```text
|
|
103
|
+
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" conversation notice
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
命令必须成功、stdout 非空且只有一个 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=conversation.notice`。下一 Agent 动作必须把 stdout 按原文完整作为独立可见消息发送给用户;禁止概括、改写、删减、只留工具面板、合并业务方案或在送达前继续工具调用。完整送达后记录当前对话中与规范化 Skill 路径绑定的 `ALIPAY_AIPAY_CONVERSATION_NOTICE_DELIVERED=true`,立即结束当前回合并等待用户确认;有效选择前禁止刷新 CLI、读取业务入口、识别根意图或执行任何业务动作。失败或 marker 缺失/重复时停止启动,不能跳过声明。首次加载正式版,或声明已确认事实无法确认时必须重新展示并等待确认。声明送达和确认事实都不落盘。此声明只维护在当前正式版消息目录。
|
|
107
|
+
|
|
108
|
+
收到声明后的首条用户回复时,先从宿主明确身份确定 `AGENT_PLATFORM`(无法确认时用 `unknown`),执行一次以下只读命令取得稳定 `SESSION_ID`;同一对话已有可靠的该值时直接复用,不重新生成。该身份同时用于采集选择、对话采集和后续业务命令,不使用另一份随机 `CONVERSATION_SESSION_ID`。
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" telemetry resolve-session --agent-platform "<AGENT_PLATFORM>"
|
|
112
|
+
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" conversation consent --reply "<USER_REPLY>" --input-id "<USER_INPUT_ID>" --agent-platform "<AGENT_PLATFORM>" --session-id "<SESSION_ID>"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
两条命令分别执行;`USER_REPLY` 为当前回复原文,`USER_INPUT_ID` 为当前宿主对话全程唯一的非内容型幂等键,同一回复重试复用,不同回复使用新键,不随业务 run 重置,不得借用此前业务确认。必须把完整原文交给 conversation consent 专用解析器,不截取关键词或由 Agent 改写为“确认”。`确认`、`同意`、`确认采集`、`同意采集`、`允许收集我的会话内容` 等明确同意表达认可采集;`仅使用服务`、`不要采集会话`、`不同意采集` 等明确拒绝采集表达表示继续服务但不采集。允许首尾空白、常见句末标点及独立选项的【】外框;规则以脚本完整声明匹配为准,不使用通用业务确认解析器。`确认,但不同意采集` 按拒绝处理;同时明确同意和拒绝采集、疑问、条件、转述、未识别组合及 `行吧`、`1`、`OK`、`继续` 等含糊表达均要求澄清。用户未回复或明确不愿继续使用时不执行后续业务。
|
|
116
|
+
|
|
117
|
+
`CONVERSATION_DECISION=UNCONFIRMED` 时,命令同时输出 `conversation.consent.clarify` 对客正文及唯一对应的 `CUSTOMER_MESSAGE_DELIVERY_REQUIRED`。下一条可见回复原文完整包含该澄清消息,结束回合,等待用户重新选择;不得启动业务、创建采集或改写已有选择。用户询问声明含义时可在该回复中先解释,再原文交付澄清消息,不能把问题当作授权;用户明确取消使用时停止,不要求其继续选择。用户在此阶段明确要求切换内测版时,按上方渠道选择执行;切换后走内测版声明,不把安装确认或正式版采集选择自动当作内测声明的确认。
|
|
118
|
+
|
|
119
|
+
- `CONVERSATION_DECISION=CONFIRMED` 或 `SERVICE_ONLY`:可记录与当前路径和版本绑定的 `ALIPAY_AIPAY_CONVERSATION_NOTICE_CONFIRMED=true` 并继续业务。此声明确认事实仍只保留当前对话上下文。
|
|
120
|
+
- 仅 `CONVERSATION_CONSENT=GRANTED` 且没有本轮采集失败事实时,先读取 `references/normal/conversation-telemetry.md`,按其中的补采规则执行:以触发本 Skill 的那条用户消息(沿用其原始输入幂等键)为第一条消息执行 `start-conversation`;取得 `CONVERSATION_ID` 后,按原始顺序用 `conversation-message` 依次补采授权前的其余消息(采集说明、澄清往来等助手收口消息带 `--final true`),最后补采本次同意回复。授权前内容因上下文压缩等原因无法可靠取得时,从可可靠取得的最早消息开始,禁止伪造。已 ACTIVE 时沿用 `CONVERSATION_ID`,不重复初始化、不重复采集。
|
|
121
|
+
- `CONVERSATION_CONSENT=DENIED|DISABLED|UNAVAILABLE`:当前对话停止传入会话正文,不调用采集或自动补建入口,业务照常继续;状态保存失败也按不采集处理,不宣称已保存选择。运行时的启动和消息入口还会校验持久化授权,未同意或已拒绝均不能采集。
|
|
122
|
+
|
|
123
|
+
`仅使用服务` 及等价明确拒绝的选择按宿主会话 hash 独立保存,不随业务 run 结束、再次引用 Skill 或自更新清除。用户之后明确要求重新同意采集时,重新展示本声明并等待新的 `同意采集` 或明确同意采集的等价回复,再执行同一 consent 命令;不得把普通业务确认当成重新授权。用户中途要求停止采集时,立即执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" telemetry opt-out --input-id "<USER_INPUT_ID>" --session-id "<SESSION_ID>" --agent-platform "<AGENT_PLATFORM>"`(有 ID 时附加 `--conversation-id "<CONVERSATION_ID>"`),停止传入后续正文;只有 `CONVERSATION_CONSENT=DENIED` 才可宣称选择已保存,失败不阻断业务。
|
|
124
|
+
|
|
125
|
+
同一对话中确认事实、路径和当前正式版本均未变化时,材料回复、恢复、再次引用和子流程衔接不重复展示声明。路径或版本变化、上下文压缩导致确认事实不可用时重新展示并等待选择,但不得清除原有采集拒绝状态。会话身份无法可靠恢复时重新展示声明并取得选择,绝不根据旧确认事实自动授权新的会话身份。
|
|
95
126
|
|
|
96
127
|
仅确定继续正式版后,若当前上下文没有与规范化 `SKILL_DIR`、合法 `VERSION` 绑定的 `ALIPAY_AIPAY_CLI_REFRESHED=true`,必须刷新一次 `alipay-cli`;不得因自更新已检查而跳过。仅唯一终态 `READY` 可在当前对话上下文记录该成功事实、路径和版本,不写缓存或业务状态;三者仍可用且一致时,后续根触发、确认、补材料、候选选择、恢复、中断继续和 Full Process 衔接均不重复刷新。
|
|
97
128
|
|
package/skill/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.7.
|
|
1
|
+
1.7.7
|
|
@@ -541,6 +541,8 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message saf
|
|
|
541
541
|
|
|
542
542
|
> 详细校验清单已附在当前阶段 bundle 的“当前产品适用校验清单”。
|
|
543
543
|
|
|
544
|
+
**验收阶段边界**:本轮代码开发按沙箱集成验收;checklist 第七节中尚未开通产品或尚未取得、切换生产实值的检查,记为当前阶段不适用并保留上线前待办,不计入失败项或人工待验证项,不单独阻止 Onboarding。仍须检查生产配置加载边界、环境隔离和所有适用代码/安全控制;已发现的实现缺陷、泄露或环境混用仍是阻断缺口。不得为完成本轮检查索取生产私钥、提前改用生产配置或宣称生产就绪。
|
|
545
|
+
|
|
544
546
|
**校验完整性要求**:内部必须覆盖当前 bundle 中适用于目标产品的密钥与安全、异步通知、接口覆盖、支付结果处理、按量付费专项、退款、上线前和结果输出章节,不得只检查上方三个摘要项。通过时默认对客只输出通过结论和下一步;部分通过或未通过时只输出实际未完成项、人工待验证项和下一步。步骤 5/6 已展示的沙箱配置、联调或付款体验结论不在 checklist 结果中重复。通过项与不适用项无需逐行展开,用户要求明细时再输出完整逐项结果。精简输出不得导致任何适用校验被跳过。
|
|
545
547
|
|
|
546
548
|
先汇总 checklist 证据;本轮可修复时先修复、重检,不渲染中间结果。项目快照变化会使旧 `CHECKLIST_SCOPE_RECEIPT` 失效,必须重新加载本阶段并重跑受影响检查。
|
|
@@ -80,11 +80,11 @@
|
|
|
80
80
|
| Payment-Proof 验证 | 收到 `Payment-Proof` 后必须调用 `alipay.aipay.agent.payment.verify` | 验证成功只代表支付宝凭证有效,不代表本地订单已完成校验 |
|
|
81
81
|
| 本地订单匹配 | 验付成功后必须查询本地订单并校验状态 | 防止凭证有效但商户订单不存在、过期或状态异常 |
|
|
82
82
|
| 资源防串 | 必须校验本地订单的 `resource_id` 与验付结果/请求资源一致 | 防止用户通过篡改资源标识获取其他资源 |
|
|
83
|
-
| 金额一致性 |
|
|
83
|
+
| 金额一致性 | 商家服务端必须校验本地持久化订单金额与 `Payment-Needed` 账单金额和服务定价一致;验付返回非空金额时必须与本地订单匹配。仅精确沙箱模式(沙箱 SDK 网关且 `serviceId=api_mock_service_id`)缺金额时允许使用本地订单金额继续判断;生产缺金额必须拒绝交付 | 按本地接口契约核对商家代码;自动联调脚本不直接比较验付金额与本地订单金额,通过结果不能替代此项审查 |
|
|
84
84
|
| 幂等履约 | 同一订单重复携带 `Payment-Proof` 时不得重复发放资源 | 应返回历史履约结果或可重试确认结果 |
|
|
85
85
|
| 履约确认 | 资源生成后必须调用 `alipay.aipay.agent.fulfillment.confirm` | 确认成功后再标记订单 `FULFILLED` 并返回成功交付 |
|
|
86
86
|
| 自动联调成功证据 | 必须同时具备 HTTP 200、非空 `resource_id` / `resourceId`、非空 `content`、无明确业务失败,以及当前五语言示例有效的 `Payment-Validation` | 204、空体、空对象、`VERIFY_FAILED`、履约失败或异常响应头均不得判为通过 |
|
|
87
|
-
| 敏感过程产物 | 单次联调的临时目录/文件权限不得宽于 `0700/0600`,命令结束时立即清理 | 禁止打印 Payment-Proof 或 Payment-Validation
|
|
87
|
+
| 敏感过程产物 | 单次联调的临时目录/文件权限不得宽于 `0700/0600`,命令结束时立即清理 | 禁止打印 Payment-Proof 或 Payment-Validation 原始值;失败或中断后按 flow 的执行 guard 判定,不得无变化重跑或自动重放结果未知的请求 |
|
|
88
88
|
| 沙箱 serviceId | 沙箱联调的 `serviceId` 固定为 `api_mock_service_id` | 不向用户索要正式 `serviceId`,不使用其他占位符 |
|
|
89
89
|
| 沙箱空字段边界 | 沙箱联调中字段为空可用于排查定位,生产环境关键字段为空必须按异常处理 | 不得把沙箱容错逻辑直接迁移成生产跳过校验 |
|
|
90
90
|
| 生产实现完整性 | 订单持久化、本地订单匹配、金额一致性、资源防串、幂等履约、待确认状态和确认失败重试均已实际实现 | 任一关键控制仍为 TODO、注释、内存演示或伪代码时只能判定沙箱演示可测试,不得判定生产就绪 |
|
|
@@ -107,6 +107,8 @@
|
|
|
107
107
|
<!-- ALIPAY_AIPAY_CHECKLIST_PRODUCTS:aipay,webpay,apppay -->
|
|
108
108
|
## 七、上线前校验
|
|
109
109
|
|
|
110
|
+
本节区分当前代码开发验收与生产上线验收。沙箱代码开发阶段检查生产配置加载边界、沙箱/生产隔离及适用安全控制;尚未开通产品、尚未取得生产 APPID/密钥/真实 serviceId 或尚未切换生产网关,记录为上线前待办,相应生产实值检查记为“当前阶段不适用”,不计入 `failedItems`、`manualItems` 或 `blockingDefectState`,不单独阻止继续 Onboarding。沿用既有上线提醒交付这些要求,不索取生产私钥、不提前切换配置。代码缺陷、密钥泄露、环境混用等安全问题仍须修复;已有生产配置也须检查其适用保护。实际生产上线验收必须满足本节全部适用项,否则不得宣称生产就绪。
|
|
111
|
+
|
|
110
112
|
| 校验项 | 校验要求 | 说明 |
|
|
111
113
|
|----------|----------|----------|
|
|
112
114
|
| 网关地址切换 | 五语言 A2M 示例默认沙箱网关为 `https://openapi-sandbox.dl.alipaydev.com/gateway.do`;上线时显式切换为 `https://openapi.alipay.com/gateway.do` | 禁止把生产网关复制进沙箱运行配置 |
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
以下代码展示严格验付和幂等履约的完整控制流。生成项目代码时,请按当前项目结构拆分并绑定真实持久化实现。
|
|
4
4
|
|
|
5
|
+
金额校验由商家服务端执行:验付返回非空金额时必须与本地持久化订单匹配;仅 SDK 网关严格为 `https://openapi-sandbox.dl.alipaydev.com/gateway.do` 且 `serviceId=api_mock_service_id` 的精确沙箱模式下,验付缺少金额才允许使用本地订单金额继续判断。生产缺少金额必须拒绝交付。自动沙箱联调脚本不直接比较这两个金额,脚本通过不能代替商家代码校验。
|
|
6
|
+
|
|
5
7
|
```csharp
|
|
6
8
|
/*
|
|
7
9
|
* A2M 智能收产品接入示例 - C# 版本
|
|
8
10
|
*
|
|
9
11
|
* 本示例展示 A2M 核心协议、严格验付和幂等履约流程。
|
|
10
12
|
* 必须通过 ConfigureOrderRepository 绑定项目真实持久化实现;端口未绑定时明确失败,
|
|
11
|
-
*
|
|
13
|
+
* 不使用内存订单或固定资源;生产环境不使用验付字段缺失兜底。
|
|
12
14
|
*
|
|
13
15
|
* 本文件演示 A2M 核心协议调用流程:
|
|
14
16
|
* 1. 返回 402 Payment-Needed Header
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
以下代码展示严格验付和幂等履约的完整控制流。生成项目代码时,请按当前项目结构拆分并绑定真实持久化实现。
|
|
4
4
|
|
|
5
|
+
金额校验由商家服务端执行:验付返回非空金额时必须与本地持久化订单匹配;仅 SDK 网关严格为 `https://openapi-sandbox.dl.alipaydev.com/gateway.do` 且 `serviceId=api_mock_service_id` 的精确沙箱模式下,验付缺少金额才允许使用本地订单金额继续判断。生产缺少金额必须拒绝交付。自动沙箱联调脚本不直接比较这两个金额,脚本通过不能代替商家代码校验。
|
|
6
|
+
|
|
5
7
|
```java
|
|
6
8
|
/*
|
|
7
9
|
* Copyright (C) 2015-2026 Ant Group
|
|
@@ -21,7 +23,7 @@
|
|
|
21
23
|
/*
|
|
22
24
|
* 本示例展示 A2M 核心协议、严格验付和幂等履约流程。
|
|
23
25
|
* 必须通过 OrderRepository 绑定项目真实持久化实现;端口未绑定时明确失败,
|
|
24
|
-
*
|
|
26
|
+
* 不使用内存订单或固定资源;生产环境不使用验付字段缺失兜底。
|
|
25
27
|
*/
|
|
26
28
|
package com.alipay.aipayweb.demo;
|
|
27
29
|
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
以下代码展示严格验付和幂等履约的完整控制流。生成项目代码时,请按当前项目结构拆分并绑定真实持久化实现。
|
|
4
4
|
|
|
5
|
+
金额校验由商家服务端执行:验付返回非空金额时必须与本地持久化订单匹配;仅 SDK 网关严格为 `https://openapi-sandbox.dl.alipaydev.com/gateway.do` 且 `serviceId=api_mock_service_id` 的精确沙箱模式下,验付缺少金额才允许使用本地订单金额继续判断。生产缺少金额必须拒绝交付。自动沙箱联调脚本不直接比较这两个金额,脚本通过不能代替商家代码校验。
|
|
6
|
+
|
|
5
7
|
```javascript
|
|
6
8
|
/**
|
|
7
9
|
* A2M 智能收产品接入示例 - Node.js 版本
|
|
8
10
|
*
|
|
9
11
|
* 本示例展示 A2M 核心协议、严格验付和幂等履约流程。
|
|
10
12
|
* 必须通过 configureOrderRepository 绑定项目真实持久化实现;
|
|
11
|
-
*
|
|
13
|
+
* 端口未绑定时明确失败,不使用内存订单或固定资源;生产环境不使用验付字段缺失兜底。
|
|
12
14
|
*
|
|
13
15
|
* 本文件演示 A2M 核心协议调用流程:
|
|
14
16
|
* 1. 返回 402 Payment-Needed Header
|
|
@@ -161,6 +163,7 @@ function base64UrlDecode(str) {
|
|
|
161
163
|
}
|
|
162
164
|
|
|
163
165
|
function normalizeAmount(value) {
|
|
166
|
+
if (typeof value !== 'string' && typeof value !== 'number') return null;
|
|
164
167
|
const match = /^(\d+)(?:\.(\d{1,2}))?$/.exec(String(value ?? '').trim());
|
|
165
168
|
if (!match) return null;
|
|
166
169
|
return `${BigInt(match[1]).toString()}.${(match[2] || '').padEnd(2, '0')}`;
|
|
@@ -345,7 +348,8 @@ async function verifyPaymentAndDeliverResource(req, res, paymentProof) {
|
|
|
345
348
|
const order = verifyOutTradeNo ? await repository.findByOutTradeNo(verifyOutTradeNo) : null;
|
|
346
349
|
const sandboxMode = isExactSandboxMode();
|
|
347
350
|
const verifyTradeNo = returnedTradeNo || (sandboxMode ? tradeNo : '');
|
|
348
|
-
const
|
|
351
|
+
const amountMissing = returnedAmount === undefined || returnedAmount === null || returnedAmount === '';
|
|
352
|
+
const verifyAmount = amountMissing && sandboxMode && order ? order.amount : returnedAmount;
|
|
349
353
|
const resourceIdVerified = returnedResourceId || (sandboxMode && order ? order.resourceId : '');
|
|
350
354
|
|
|
351
355
|
if (process.env.A2M_DEBUG === 'true') {
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
以下代码展示严格验付和幂等履约的完整控制流。生成项目代码时,请按当前项目结构拆分并绑定真实持久化实现。
|
|
4
4
|
|
|
5
|
+
金额校验由商家服务端执行:验付返回非空金额时必须与本地持久化订单匹配;仅 SDK 网关严格为 `https://openapi-sandbox.dl.alipaydev.com/gateway.do` 且 `serviceId=api_mock_service_id` 的精确沙箱模式下,验付缺少金额才允许使用本地订单金额继续判断。生产缺少金额必须拒绝交付。自动沙箱联调脚本不直接比较这两个金额,脚本通过不能代替商家代码校验。
|
|
6
|
+
|
|
5
7
|
```php
|
|
6
8
|
<?php
|
|
7
9
|
/**
|
|
@@ -9,7 +11,7 @@
|
|
|
9
11
|
*
|
|
10
12
|
* 本示例展示 A2M 核心协议、严格验付和幂等履约流程。
|
|
11
13
|
* 必须通过 configureOrderRepository 绑定项目真实持久化实现;
|
|
12
|
-
*
|
|
14
|
+
* 端口未绑定时明确失败,不使用内存订单或固定资源;生产环境不使用验付字段缺失兜底。
|
|
13
15
|
* 订单快照将支付状态映射为 PENDING_PAYMENT/PAID,
|
|
14
16
|
* 将履约状态映射为 UNFULFILLED/PENDING_CONFIRM/FULFILLED。
|
|
15
17
|
*
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
以下代码展示严格验付和幂等履约的完整控制流。生成项目代码时,请按当前项目结构拆分并绑定真实持久化实现。
|
|
4
4
|
|
|
5
|
+
金额校验由商家服务端执行:验付返回非空金额时必须与本地持久化订单匹配;仅 SDK 网关严格为 `https://openapi-sandbox.dl.alipaydev.com/gateway.do` 且 `serviceId=api_mock_service_id` 的精确沙箱模式下,验付缺少金额才允许使用本地订单金额继续判断。生产缺少金额必须拒绝交付。自动沙箱联调脚本不直接比较这两个金额,脚本通过不能代替商家代码校验。
|
|
6
|
+
|
|
5
7
|
```python
|
|
6
8
|
#!/usr/bin/env python3
|
|
7
9
|
# -*- coding: utf-8 -*-
|
|
@@ -10,7 +12,7 @@ A2M 智能收产品接入示例 - Python 版本
|
|
|
10
12
|
|
|
11
13
|
本示例展示 A2M 核心协议、严格验付和幂等履约流程。
|
|
12
14
|
必须通过 configure_order_repository 绑定项目真实持久化实现;
|
|
13
|
-
|
|
15
|
+
端口未绑定时明确失败,不使用内存订单或固定资源;生产环境不使用验付字段缺失兜底。
|
|
14
16
|
|
|
15
17
|
本文件演示 A2M 核心协议调用流程:
|
|
16
18
|
1. 返回 402 Payment-Needed Header
|
|
@@ -167,7 +169,9 @@ def base64url_decode(data):
|
|
|
167
169
|
|
|
168
170
|
|
|
169
171
|
def normalize_amount(value):
|
|
170
|
-
|
|
172
|
+
if isinstance(value, bool) or not isinstance(value, (str, int, float, Decimal)):
|
|
173
|
+
return None
|
|
174
|
+
text = str(value).strip()
|
|
171
175
|
if not re.fullmatch(r'\d+(?:\.\d{1,2})?', text):
|
|
172
176
|
return None
|
|
173
177
|
return f'{Decimal(text):.2f}'
|
|
@@ -381,7 +385,8 @@ def verify_payment_and_deliver_resource(payment_proof):
|
|
|
381
385
|
order = repository.find_by_out_trade_no(verify_out_trade_no) if verify_out_trade_no else None
|
|
382
386
|
sandbox_mode = is_exact_sandbox_mode()
|
|
383
387
|
verify_trade_no = returned_trade_no or (trade_no if sandbox_mode else '')
|
|
384
|
-
|
|
388
|
+
amount_missing = returned_amount is None or returned_amount == ''
|
|
389
|
+
verify_amount = order.get('amount') if amount_missing and sandbox_mode and order else returned_amount
|
|
385
390
|
resource_id_verified = returned_resource_id or (order.get('resource_id') if sandbox_mode and order else '')
|
|
386
391
|
|
|
387
392
|
print(f"支付凭证验证成功:tradeNo={verify_trade_no}, outTradeNo={verify_out_trade_no}")
|
|
@@ -39,7 +39,7 @@ AI 按量付费只实现 HTTP 402、`Payment-Needed`、`Payment-Proof`、`alipay
|
|
|
39
39
|
验付成功不能只看 SDK 调用成功,还必须同时校验:
|
|
40
40
|
|
|
41
41
|
- `active=true`。
|
|
42
|
-
-
|
|
42
|
+
- 返回非空 `amount` 时,必须与本地持久化订单金额一致;金额不匹配或格式非法时拒绝交付。仅在精确沙箱模式(SDK 网关严格为 `https://openapi-sandbox.dl.alipaydev.com/gateway.do` 且 `serviceId=api_mock_service_id`)下,验付响应缺少金额时允许使用本地持久化订单金额继续判断;生产环境缺少金额必须拒绝交付,不能使用该回退。
|
|
43
43
|
- 返回 `out_trade_no` 等于本地订单号。
|
|
44
44
|
- 返回 `resource_id` 等于当前请求资源。
|
|
45
45
|
- `trade_no` 未被重复履约。
|
|
@@ -47,6 +47,8 @@ AI 按量付费只实现 HTTP 402、`Payment-Needed`、`Payment-Proof`、`alipay
|
|
|
47
47
|
|
|
48
48
|
任一校验失败时返回 402,让智能体重新支付;不得返回资源。
|
|
49
49
|
|
|
50
|
+
上述金额判断由商家服务端实现。自动沙箱联调脚本从商家返回的 `Payment-Needed` 读取并传递金额,不直接比较验付响应金额与本地订单金额;脚本通过不能替代商家金额校验的代码审查。
|
|
51
|
+
|
|
50
52
|
## 履约确认
|
|
51
53
|
|
|
52
54
|
资源生成后调用 `alipay.aipay.agent.fulfillment.confirm`,业务入参只有 `trade_no`。必须在履约确认成功后再把订单标记为最终完成。确认失败时允许同一 `Payment-Proof` 重试确认,避免资源已生成但平台未记录履约。
|
package/skill/references/integration/modules/interface-contract/apppay-interface-contract.md
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
sourceUrl:
|
|
6
6
|
|
|
7
|
-
- <https://aipay.alipay.com/docs/mobile-app-pay/app-pay-integration-guide-new.md>
|
|
8
|
-
- <https://aipay.alipay.com/docs/mobile-app-pay/ai-app-pay/alipay-trade-app-pay.md>
|
|
9
|
-
- <https://aipay.alipay.com/docs/mobile-app-pay/ai-app-pay/sync-result.md>
|
|
7
|
+
- <https://aipay.alipay.com/docs/vibe-pay/mobile-app-pay/app-pay-integration-guide-new.md>
|
|
8
|
+
- <https://aipay.alipay.com/docs/vibe-pay/mobile-app-pay/ai-app-pay/alipay-trade-app-pay.md>
|
|
9
|
+
- <https://aipay.alipay.com/docs/vibe-pay/mobile-app-pay/ai-app-pay/sync-result.md>
|
|
10
10
|
|
|
11
11
|
## 默认范围
|
|
12
12
|
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
sourceUrl:
|
|
6
6
|
|
|
7
|
-
- <https://aipay.alipay.com/docs/ai-web-app-payment-qianyi/api-list/alipay-trade-query.md>
|
|
8
|
-
- <https://aipay.alipay.com/docs/ai-web-app-payment-qianyi/api-list/alipay-trade-refund.md>
|
|
9
|
-
- <https://aipay.alipay.com/docs/ai-web-app-payment-qianyi/api-list/alipay-trade-fastpay-refund-query.md>
|
|
10
|
-
- <https://aipay.alipay.com/docs/ai-web-app-payment-qianyi/api-list/alipay-trade-close.md>
|
|
11
|
-
- <https://aipay.alipay.com/docs/mobile-app-pay/ai-app-pay/alipay-trade-query.md>
|
|
12
|
-
- <https://aipay.alipay.com/docs/mobile-app-pay/ai-app-pay/alipay-trade-refund.md>
|
|
13
|
-
- <https://aipay.alipay.com/docs/mobile-app-pay/ai-app-pay/alipay-trade-fastpay-refund-query.md>
|
|
14
|
-
- <https://aipay.alipay.com/docs/mobile-app-pay/ai-app-pay/alipay-trade-close.md>
|
|
7
|
+
- <https://aipay.alipay.com/docs/vibe-pay/ai-web-app-payment-qianyi/api-list/alipay-trade-query.md>
|
|
8
|
+
- <https://aipay.alipay.com/docs/vibe-pay/ai-web-app-payment-qianyi/api-list/alipay-trade-refund.md>
|
|
9
|
+
- <https://aipay.alipay.com/docs/vibe-pay/ai-web-app-payment-qianyi/api-list/alipay-trade-fastpay-refund-query.md>
|
|
10
|
+
- <https://aipay.alipay.com/docs/vibe-pay/ai-web-app-payment-qianyi/api-list/alipay-trade-close.md>
|
|
11
|
+
- <https://aipay.alipay.com/docs/vibe-pay/mobile-app-pay/ai-app-pay/alipay-trade-query.md>
|
|
12
|
+
- <https://aipay.alipay.com/docs/vibe-pay/mobile-app-pay/ai-app-pay/alipay-trade-refund.md>
|
|
13
|
+
- <https://aipay.alipay.com/docs/vibe-pay/mobile-app-pay/ai-app-pay/alipay-trade-fastpay-refund-query.md>
|
|
14
|
+
- <https://aipay.alipay.com/docs/vibe-pay/mobile-app-pay/ai-app-pay/alipay-trade-close.md>
|
|
15
15
|
|
|
16
16
|
网页应用付款和移动应用收款的查询、退款、退款查询、关闭文档当前内容一致,本 Skill 本地维护一份通用契约。
|
|
17
17
|
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
sourceUrl:
|
|
6
6
|
|
|
7
|
-
- <https://aipay.alipay.com/docs/ai-web-app-payment-qianyi/api-list/async-notify-verify.md>
|
|
8
|
-
- <https://aipay.alipay.com/docs/mobile-app-pay/ai-app-pay/async-notify-verify.md>
|
|
7
|
+
- <https://aipay.alipay.com/docs/vibe-pay/ai-web-app-payment-qianyi/api-list/async-notify-verify.md>
|
|
8
|
+
- <https://aipay.alipay.com/docs/vibe-pay/mobile-app-pay/ai-app-pay/async-notify-verify.md>
|
|
9
9
|
|
|
10
10
|
当前两份官方文档内容一致。运行时默认读取本文和当前语言 `1-通用接口/异步通知处理代码示例.md`;在线文档只在 fallback 条件下读取。
|
|
11
11
|
|
|
@@ -59,10 +59,10 @@ sourceUrl:
|
|
|
59
59
|
|
|
60
60
|
| 语言 | 示例 |
|
|
61
61
|
| --- | --- |
|
|
62
|
-
| Java |
|
|
63
|
-
| Python |
|
|
64
|
-
| Node.js |
|
|
65
|
-
| PHP |
|
|
66
|
-
| C# |
|
|
62
|
+
| Java | `../code-examples/java/1-通用接口/异步通知处理代码示例.md` |
|
|
63
|
+
| Python | `../code-examples/python/1-通用接口/异步通知处理代码示例.md` |
|
|
64
|
+
| Node.js | `../code-examples/nodejs/1-通用接口/异步通知处理代码示例.md` |
|
|
65
|
+
| PHP | `../code-examples/php/1-通用接口/异步通知处理代码示例.md` |
|
|
66
|
+
| C# | `../code-examples/csharp/1-通用接口/异步通知处理代码示例.md` |
|
|
67
67
|
|
|
68
68
|
Java 官方示例明确使用 `AlipaySignature.rsaCheckV1`。Node.js 示例给出 `checkNotifySignV2(params)` 的落地形态,但 Agent 落地前必须先读取目标项目 `alipay-sdk` 的 package.json 和类型定义,确认当前版本确实暴露该 API。Python、PHP、C# 示例使用项目内支付宝 SDK 验签适配器表示验签边界;适配器必须封装当前项目实际 SDK API,禁止临时手写不确定的 RSA 验签实现。
|
package/skill/references/integration/modules/interface-contract/webpay-interface-contract.md
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
sourceUrl:
|
|
6
6
|
|
|
7
|
-
- <https://aipay.alipay.com/docs/ai-web-app-payment-qianyi/ai-web-app-payment-integration-guide.md>
|
|
8
|
-
- <https://aipay.alipay.com/docs/ai-web-app-payment-qianyi/api-list/alipay-trade-page-pay.md>
|
|
7
|
+
- <https://aipay.alipay.com/docs/vibe-pay/ai-web-app-payment-qianyi/ai-web-app-payment-integration-guide.md>
|
|
8
|
+
- <https://aipay.alipay.com/docs/vibe-pay/ai-web-app-payment-qianyi/api-list/alipay-trade-page-pay.md>
|
|
9
9
|
|
|
10
10
|
## 默认范围
|
|
11
11
|
|
|
@@ -123,7 +123,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" a2m run --url "$SERVICE
|
|
|
123
123
|
8. 生成浏览器付款链接
|
|
124
124
|
9. 使用同一过程产物构建 Payment-Proof 并重试原始服务
|
|
125
125
|
10. 仅在 HTTP 200、非空且可归属的资源、无明确业务失败,并且当前示例要求的 `Payment-Validation` 校验通过时输出服务端联调成功
|
|
126
|
-
11.
|
|
126
|
+
11. 命令结束前清理敏感过程产物,不保存跨轮恢复状态;失败或中断后必须重新按执行 guard 判定,不得直接重跑
|
|
127
127
|
|
|
128
128
|
**脚本输出**:
|
|
129
129
|
- Payment-Needed 获取结果(终端不输出原始值)
|
|
@@ -134,7 +134,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" a2m run --url "$SERVICE
|
|
|
134
134
|
- Payment-Proof 重试后的服务响应与测试结论;`Payment-Validation` 原始值不在终端输出
|
|
135
135
|
|
|
136
136
|
**错误处理**:
|
|
137
|
-
- 沙箱化 Agent
|
|
137
|
+
- 沙箱化 Agent 环境执行本脚本时,首次执行即申请可联网权限;权限恢复只允许原样重试可确认尚未发出的命令。命令可能已发出时仍按执行 guard 处理,不以网络恢复为由重放结果未知的请求
|
|
138
138
|
- 如果未找到 `Payment-Needed` 响应头,确认服务端是否实现了 402 协议
|
|
139
139
|
- 如果收银接口返回 `PARAM_INVALID: protocol.sellerSignature不能为空`,回到预检步骤检查 `protocol.seller_signature` 是否为空、缺失或仍是占位符
|
|
140
140
|
- 如果 `pay_before` 相关参数报错,检查是否使用 ISO 8601 带时区格式
|
|
@@ -142,7 +142,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" a2m run --url "$SERVICE
|
|
|
142
142
|
|
|
143
143
|
### 第三步:连续验证 Payment-Proof 重试
|
|
144
144
|
|
|
145
|
-
标准流程只使用第二步命令中的 `--auto-complete`。脚本生成付款链接后,在同一次进程内继续构建 Payment-Proof
|
|
145
|
+
标准流程只使用第二步命令中的 `--auto-complete`。脚本生成付款链接后,在同一次进程内继续构建 Payment-Proof、重试原始服务并输出结果;进程中断后按执行 guard 处理,结果未知时不得自动重新执行完整联调。
|
|
146
146
|
|
|
147
147
|
**脚本执行步骤**:
|
|
148
148
|
1. 读取过程产物目录中的 `state.json`
|
|
@@ -154,7 +154,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" a2m run --url "$SERVICE
|
|
|
154
154
|
**Payment-Proof 处理约束**:
|
|
155
155
|
- `trade_no` 必须使用前面沙箱收银接口返回并写入 `state.json` 的交易号;不得改用商户侧 `out_trade_no` 或重新生成。
|
|
156
156
|
- `payment_proof`、`client_session` 和最终请求头由脚本按沙箱联调约定自动处理;Agent 不得手工拼接、改写或向用户展开其原始值和内部处理规则。
|
|
157
|
-
-
|
|
157
|
+
- 进程中断后,不得以过程产物缺失或已清理推定请求未发出;`UNKNOWN_PREVIOUS_EXECUTION` 固定记录结果未知,禁止自动重跑。明确业务失败、服务实现失败或脚本已输出失败结论时,禁止立即重复执行同一联调命令;输入未变化时按 `BLOCK_UNCHANGED` 停止;只有代码、配置、URL、方法或 POST body 实际变化且 guard 返回新 `RUN` 时,才允许重新发起完整联调,禁止复用旧过程产物。
|
|
158
158
|
|
|
159
159
|
Payment-Proof 参考结构:
|
|
160
160
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# 对话采集:开始、持续与结束
|
|
2
|
+
|
|
3
|
+
## 开关与范围
|
|
4
|
+
|
|
5
|
+
对话遥测环境开关默认可用,实际采集必须先取得当前宿主会话的明确同意,可用独立开关 `ALIPAY_AIPAY_CONVERSATION_TELEMETRY=0|false|off|no` 关闭;未设置或为其他值时保持开启。该开关只关闭对话采集,不影响阶段遥测。默认 code 见下方上报字段表。可用 `ALIPAY_AIPAY_CONVERSATION_CODE` 覆盖(1–16 位数字,不得与阶段遥测 code 数值相同);显式空值、非法值或与阶段遥测 code 数值相同时停用对话入口,不影响阶段遥测。全局 `ALIPAY_AIPAY_TELEMETRY=0|false|off|no` 时,两类遥测均关闭,对话采集入口不采集、不读写、不发送;用户主动拒绝仍保存最小隐私选择,明确拒绝的例外见下一段。每条保留 d1~d5,c1 为 conversation_id,c2 仅含 sequence、role、content。正文过滤凭证、个人信息及原流程禁止记录的公钥和临时 URL,不设置采集文本或消息 JSON 的人为长度上限,不截断正文;本地缓存沿用阶段遥测的现有规则。阶段遥测原有 run 创建/关闭、计数和进度不变。
|
|
6
|
+
|
|
7
|
+
明确的用户拒绝属于隐私选择:即使遥测环境开关当前关闭,conversation consent 的“仅使用服务”和 telemetry opt-out 仍保存最小拒绝状态并关闭已有采集,防止开关恢复后旧授权复活;这不采集正文、不生成事件或发起上传。环境开关关闭时的同意不写授权,恢复开关后仍需有效的明确同意。
|
|
8
|
+
|
|
9
|
+
## 开始:声明后的明确同意
|
|
10
|
+
|
|
11
|
+
声明选择由 conversation consent 专用解析器处理完整原文:`确认`、`同意`、`同意采集`、`确认采集` 等明确授权与 `仅使用服务`、`不要采集会话` 等明确拒绝分别复用原有同意/拒绝存储路径。`行吧`、`1` 等含糊回复、疑问、条件和相互冲突的采集选择只输出澄清,不改变授权或开始采集;Agent 不得自行将用户原文改写为授权词。
|
|
12
|
+
|
|
13
|
+
启动器先完整交付采集说明并等待用户选择。只有 `conversation consent` 返回 `CONVERSATION_CONSENT=GRANTED`,才允许创建/复用会话并采集;未回复、选择“仅使用服务”、环境开关关闭或授权保存失败时均不采集。授权状态只保存宿主会话 hash、选择、授权随机 ID 和回复幂等 hash,不保存回复正文。普通业务确认、start-run、再次引用 Skill 或自更新均不能修改拒绝状态;恢复采集必须重新展示声明并取得新的明确同意。
|
|
14
|
+
|
|
15
|
+
`SESSION_ID` 复用启动器处理声明选择时一次取得的稳定身份,后续采集和业务 runtime 命令均显式携带同一个值。宿主无身份时,启动器的 resolve-session 生成一次随机身份并沿用,不能为对话与业务分别生成。无法恢复身份时重新展示声明并取得选择,不能继承旧会话同意。上传的 `conversation_id` 仍由运行时生成独立随机 UUID,不等于 SESSION_ID 或业务 RUN_ID。
|
|
16
|
+
|
|
17
|
+
首次采集以触发 Skill 的那条用户消息为起点。用户同意采集时,按原始顺序补采授权前的完整对话:触发消息为第一条(sequence=1),随后依次是采集说明、澄清往来(如有)和同意回复,每条只采集一次,不重复采集。授权前的助手收口消息(声明、澄清)与正常轮次一样带 `--final true` 采集;其 `MESSAGE_ID` 由对应用户消息的幂等键确定性派生(如 `<触发幂等键>#notice`、`<澄清回复幂等键>#clarify`),同一对话内不得与其他消息重复。授权前内容无法可靠取得(如上下文压缩)时,从可可靠取得的最早消息开始,禁止伪造。`MESSAGE_ID` 使用消息的稳定非内容型身份,同一消息重试复用。`SANITIZED_MESSAGE_JSON` 是 `{"role":"user","content":"脱敏后的消息","has_attachments":false}`;过滤凭证、个人信息及原流程禁止记录的公钥和临时 URL,保留其余文字及格式。原文不得拼入命令或普通临时文件,使用结构化参数安全传递脱敏 JSON。无文字附件用空文本和 true;不读取附件、OCR 或文件名。运行时兼容 `{"text":"..."}`,其余非法结构静默拒绝。
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" telemetry start-conversation --session-id "<SESSION_ID>" --message-id "$MESSAGE_ID" --message-json "$SANITIZED_MESSAGE_JSON" --agent-platform "<AGENT_PLATFORM>"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
从唯一 `ALIPAY_AIPAY_INTERNAL:CONVERSATION_ID=<uuid>` 保存标识。已 ACTIVE 时沿用原 ID;正常结束后再次明确唤起且授权仍有效时可建立新 ID。`start-run` 只在已获同意时兜底,不改变阶段 run 的计数或生命周期。采集失败时继续业务,不宣称成功。
|
|
24
|
+
|
|
25
|
+
用户选择“仅使用服务”时由 conversation consent 保存拒绝;中途明确停止采集时,在采集该消息之前执行:
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" telemetry opt-out --session-id "<SESSION_ID>" --input-id "$MESSAGE_ID" --conversation-id "$CONVERSATION_ID" --agent-platform "<AGENT_PLATFORM>"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
尚无 conversation_id 时省略该参数,仍可按 SESSION_ID 保存拒绝。出现 `CONVERSATION_CONSENT=DENIED` 表示已保存拒绝并禁止后续采集;失败时调用方也立即停止传入正文,业务继续,不假报保存成功。正常 `end-conversation` 不等于 opt-out,不修改同意状态。重新同意使用新的授权 ID,旧 conversation 不能复活。
|
|
32
|
+
|
|
33
|
+
对话状态使用 schema_ver=3,持有 ACTIVE/CLOSED 与创建时的 consent_id;业务 run state 不保存采集选择、对话序号或正文。会话选择、创建、消息写入和关闭使用同一宿主会话锁,不与业务 run 的锁混用。
|
|
34
|
+
|
|
35
|
+
## 持续:从同意到结束的可见对话
|
|
36
|
+
|
|
37
|
+
当前授权仍有效且采集 ACTIVE 时,以对话轮次为单位只采集每轮的头和尾:头是本轮用户消息,逐条采集当前宿主会话内的所有用户消息;尾是本轮的阻塞对客消息与最终收口助手回复;不按是否与支付或 Skill 业务相关筛选。包括澄清、补材料和临时切换话题的用户消息;同一轮内的过程说明、进行中回复、阶段性助手回复、工具结果和轮内送达的非阻塞登记对客消息(如方案、摘要、checklist 结果)一律跳过;切换话题本身不等于取消或退出。
|
|
38
|
+
|
|
39
|
+
助手侧采集对象按 Skill 既有阻塞/非阻塞概念判定,不另设分类:凡阻塞对客消息(送达后本轮即停止、等待用户回复:上下文补问、MCC/应用/服务候选选择、材料收集、阻塞确认、授权或公钥页 pending 等)一律采集;每轮最终收口回复一律采集。阻塞消息通常同时就是本轮收口回复,按一条采集,不重复。两类都适用下方"先采集、后发送"规则:带 `--final true` 的 `conversation-message` 是送达前必须执行的采集动作(任务结束时仅允许再执行下文的 end-conversation),业务交付屏障"送达前禁止调用工具"不排除本条采集,采集内容是最终正文仅替换凭证、个人信息及原流程禁止记录的公钥和临时 URL后的版本,不改写其他内容。正文不含 system、隐藏推理或工具输出;不能把工具 stdout 当已送达的回复。已有业务计数窗口内,先执行原有 count-user-input,再采集;窗口外采集对话不补计 counter,所有交付屏障和原计数顺序优先。后续消息执行:
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" telemetry conversation-message --session-id "<SESSION_ID>" --conversation-id "$CONVERSATION_ID" --message-id "$MESSAGE_ID" --message-json "$SANITIZED_MESSAGE_JSON" --agent-platform "<AGENT_PLATFORM>"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
用户暂时离开、等待补材料或审核、澄清、遇到报错或中间阶段完成都不结束采集;之后在同一宿主对话继续时沿用原 conversation_id。自更新后保留当前标识,后续命令使用新版同一路径。产品已明确时,初始化和后续消息命令可追加 `--product-type aipay|webpay|apppay`;未知则省略,d5=UNKNOWN。不读取或关联业务 run;首次授权前的补采只在上述明确同意后按原始顺序执行,后续持续采集不回填遗漏消息。
|
|
46
|
+
|
|
47
|
+
助手最终收口回复固定采用先采集、后发送:Agent 组织好本轮最终收口回复后,先执行上述 `conversation-message` 并追加 `--final true`,`--message-json` 的 content 必须是随后发送正文的脱敏版本,仅允许替换凭证、个人信息及原流程禁止记录的公钥和临时 URL;执行采集后发送原定回复。禁止先发送后采集、发送后补采或在脱敏之外改写采集内容。assistant 角色缺少 `--final true` 时运行时静默丢弃该条记录,过程回复不得调用 conversation-message。采集成功时 stderr 产生唯一 `ALIPAY_AIPAY_INTERNAL:CONVERSATION_MESSAGE_RECORDED=<sequence>` 内部事实行;未出现该 marker 视为采集失败,遥测失败静默、不阻断 Skill,仍正常发送回复。
|
|
48
|
+
|
|
49
|
+
MESSAGE_ID 可复用用户消息的 USER_INPUT_ID;本地按 conversation_id+role+message_id 的 hash 幂等分配 sequence,消息身份本身不上报。调用方按消息在当前会话中出现的顺序依次采集:收到用户消息后,在适用的原计数动作之后采集;最终收口回复按上述先采集后发送规则采集。不得先采集后出现的消息,再补采前面的消息。sequence 在采集时分配,从 1 开始,在同一 conversation 内加锁递增,产品变化不重置;同一消息重试和已入队消息补传均保留原序号,不重新编号。消费端按 conversation_id+sequence 去重并按 sequence 排序,不依赖网络到达先后。该序号仍表示采集顺序,不能自动纠正漏采后补采的原始位置;不上传原始消息时间。
|
|
50
|
+
|
|
51
|
+
## 结束:任务完成、取消或退出
|
|
52
|
+
|
|
53
|
+
正常流程以应用发布完成为采集结束点;仅提交审核或仍有阻塞步骤不算发布完成。用户选择的任务本来不包含应用发布(例如仅代码开发,或仅产品开通且不涉及发布)时,以该任务按对应 flow 的完成条件实际完成为结束点,不扩展任务范围。每轮助手回复说完、业务报错或输出阶段性结果本身都不是结束条件。
|
|
54
|
+
|
|
55
|
+
达到上述完成条件后,最终结果回复同样按先采集、后发送处理:先通过 conversation-message(`--final true`)完成本地状态写入和 outbox 入队,尝试记录后执行以下结束命令,再发送最终回复;任一遥测动作失败仍正常交付,不等待网络:
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" telemetry end-conversation --session-id "<SESSION_ID>" --conversation-id "$CONVERSATION_ID" --agent-platform "<AGENT_PLATFORM>"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
用户明确取消或退出 Skill 时,先采集该用户消息及本次结束回复(如有,`--final true`),再执行同一结束命令,结束回复在结束命令返回后才发送;不等待新的用户确认。结束命令在独立 conversation 锁内将当前采集置为 CLOSED,成功时 stderr 产生唯一 `ALIPAY_AIPAY_INTERNAL:CONVERSATION_CLOSED=true` 内部事实行,不发送额外结束事件,不增加序号或修改业务 run。重复结束幂等,结束后旧 ID 拒绝新消息;不因普通后续聊天自动调用 start-conversation。再次明确唤起 Skill 才开始新的采集。
|
|
62
|
+
|
|
63
|
+
用户一直未返回时,采集停留在已取得的消息,不推定任务完成或取消,不因沉默设置自动结束计时器,也不额外生成结束上报。
|
|
64
|
+
|
|
65
|
+
用户明确切换为预发版 `alipay-aipay-pre` 时,视为退出正式版,按上述结束顺序关闭当前正式版 conversation,并停止正式版采集动作;不得把预发版后续对话自动纳入旧正式版采集。预发版按自身启动器展示声明并确认采集选择,不继承正式版授权。仅暂时切换话题不适用此规则。以后再次明确唤起正式版时,按正式版启动器检查当前声明事实与授权,再决定是否创建新的 conversation。
|
|
66
|
+
|
|
67
|
+
业务 summary 事件本身不触发关闭,以免漏掉尚未送达的最终回复,也避免 full_process 的中间 summary 提前结束采集。关闭仅停止接收新消息,此前在有效授权下已入队的消息继续按原机制补传,不等网络成功才关闭。
|
|
68
|
+
|
|
69
|
+
## 失败与宿主执行限制
|
|
70
|
+
|
|
71
|
+
遥测失败静默,不阻断 Skill。调用方在结束边界记录当前采集已结束并停止传入消息,不能因记录或关闭失败而继续采集无关聊天。结束命令失败可对旧 ID 重试,不以 start-conversation 代替结束重试。
|
|
72
|
+
|
|
73
|
+
最终收口回复采集和结束命令都在回复发送前执行,不再依赖宿主在最终回复送达后提供执行机会。采集成功但回复被宿主中断、截断或未送达时,该条记录保留在 conversation 中,属于可接受偏差,不补发、不删除;采集失败或未授权时仍正常发送回复,不得以采集成功为业务交付条件。
|
|
74
|
+
|
|
75
|
+
## 上报字段
|
|
76
|
+
|
|
77
|
+
复用 collect.alipay.com/yuyan/ 的 syncLog 通道与匿名机器维度,conversation 本地事件使用 schema_ver=5,阶段仍为 schema_ver=2。每条保留 d1~d5,沿用现有取值规则;d3 的模型归一化和 unknown 规则见 [阶段遥测说明](telemetry.md#stage-快照),不依赖查询阶段遥测记录才获取维度。产品由明确的当前上下文传入,未知为 UNKNOWN。对话传输字段如下:
|
|
78
|
+
|
|
79
|
+
| 字段 | 消息事件 |
|
|
80
|
+
|---|---|
|
|
81
|
+
| code | 独立 code(默认 1008) |
|
|
82
|
+
| msg | alipay_aipay_skill_conversation |
|
|
83
|
+
| d1/d2/d3/d4/d5 | 系统、宿主、模型、Skill 版本、产品(可 UNKNOWN) |
|
|
84
|
+
| c1 | conversation_id |
|
|
85
|
+
| c2 | JSON 字符串,只含 sequence、role、content(脱敏正文) |
|
|
86
|
+
|
|
87
|
+
对话不携带 event_id、run_id 或 root_intent,也不生成关联记录。消费端用 c1 与 c2.sequence 组成唯一键;event_id 不再单独生成。附件和脱敏版本标志只保留在本地事件,不进入 c2;保留旧本地 schema 的 truncated 字段,新消息固定为 false。对话不上传 c3/c4,采集时间仅保留在本地事件供队列处理;统计时间窗口使用平台接收时间,补传会计入接收时段。stage 的 event_id、c1=run_id 和 c4 原白名单保持不变。模块入口为 startConversation({sessionId}, env)、recordConversationMessage(message, {conversationId, messageId, productType?}, env)、endConversation(conversationId, env)。
|
|
88
|
+
|
|
89
|
+
## 脱敏、本地缓存与共用发送
|
|
90
|
+
|
|
91
|
+
调用方对凭证、个人信息及原流程禁止记录的公钥和临时 URL 做语义脱敏,保留字段名、周围说明、代码结构及非敏感参数。凭证包括私钥、密码、访问 Token、API Secret/Key、授权码、验证码、认证 Cookie 或支付认证凭证;个人信息包括姓名、手机号、邮箱、身份证号、银行卡号及个人地址。自由叙述中的姓名、住址等由调用方按语义判断,脚本不能保证覆盖任意表达。
|
|
92
|
+
|
|
93
|
+
脚本在落盘和构造请求前再次过滤私钥和公钥 PEM、可解析的无头单行或换行 Base64 密钥、公钥字段、deviceCode/keyConfirmToken 字段、Bearer/Basic 认证值、完整 Cookie 值、带前缀的凭证字段、明确标注的个人信息字段,以及可识别的邮箱、手机号和身份证格式。原流程限制为当次调用使用的应用公钥不得进入采集队列;授权、公钥确认等临时 URL 整条移除,URL 规则复用当前渠道 policy-rules.json 的 temporaryUrlAllowlist,含 deviceCode/keyConfirmToken(含编码后的参数名)的其他 URL 也整条移除。URL 规则不可读时保守移除全部 URL,不阻断启动或自更新。普通帮助链接、路径、代码结构、应用 ID、服务 ID、MCC 编码、价格和业务状态继续保留;其中嵌入的凭证或个人信息仍遮盖敏感值。格式匹配仍可能误判或漏判,不能声称完全匿名。
|
|
94
|
+
|
|
95
|
+
采集脱敏后的完整正文,不主动截断或摘要。
|
|
96
|
+
|
|
97
|
+
独立 conversation state 只保存随机 ID、会话 hash、去重 hash、消息序号、待确认消息的序号/去重 hash/时间戳、创建时授权 ID 和 ACTIVE/CLOSED 状态;正文仅进入当前用户的 outbox。Unix/macOS/Linux 使用 `0600` 文件模式,Windows 仅检查目录实际可写,不声称已经配置 ACL。对话事件使用 .conversation 后缀保存 JSON,让只识别 .json 的旧版 worker 跳过。对话正文和解析错误不进入 stdout/stderr。code 入队时固定,后续改配置不重标旧事件。升级前未取得明确同意的旧 conversation 队列不补传;worker 只发送具有创建时授权 ID 的会话消息,后续同意不得追认旧消息。
|
|
98
|
+
|
|
99
|
+
对话上报请求最多等待 10 秒(包括 DNS、连接和响应正文等待),每个后台 worker 最多运行 60 秒。同一渠道、同一 outbox 只允许一个后台 worker 执行上传;上传者记录包含开始及失效时间,有效期最多 70 秒(60 秒运行上限及 10 秒退出余量),旧版记录按文件修改时间计算同样的上限。仅在记录有效且进程仍存活时阻止重复启动,过期记录不会因进程号被其他程序复用而永久阻塞;并发启动时由队列锁决定唯一上传者。失效记录对应的 PID 若仍存活,其占用中的记录保留原有 claim TTL 恢复规则,不提前抢占其他活跃发送。每批成功后重新检查队列,继续处理上传期间新增的消息;前台启动上传只尝试取得队列锁,不等待;后台释放退出锁后再检查队列,接手退出窗口内新增的消息。到期前已有成功上传且仍有积压时,释放当前记录后交给新的限时 worker;失败或首条请求持续无响应时不循环拉起新进程。授权保存、采集和结束命令不等待会话锁,锁忙时静默失败并继续业务;过期锁按原规则恢复后只重试一次。成功采集完成本地状态记录和入队即返回,后台启动锁忙时保留队列,不在前台等待锁或网络结果。超时或失败保留未发送记录,worker 到期退出时释放自己占用的记录;异常退出后,后续 worker 检查原进程已结束便恢复其占用记录并重试。前台 flush-outbox 跳过对话记录,避免补传引入前台等待。后台启动失败时保留队列,后续触发时再尝试,不保证最终送达。本地状态写入和入队仍需要少量执行时间。
|
|
100
|
+
|
|
101
|
+
除上述对话上报的超时与后台发送规则外,上传、claim 恢复、补传和队列保留/清理规则沿用 [telemetry.md 的“进度与上传”](telemetry.md#进度与上传)。对话消息先在会话状态中私有保存待确认序号、去重 hash 与事件时间戳,成功入队后再提交正式序号和去重记录;待确认标记不含正文,不代表采集成功。入队失败不推进正式序号、不输出成功回执,目录恢复后可重试同一消息。状态提交失败时尝试清理本次队列记录。异常退出后,下一次采集或后台上传在同一会话锁内核对待确认标记与队列:已入队则恢复原序号及去重,未入队则清除标记;核对或保存失败时停止本次采集/发送,不占用或重复分配序号。后台仍跳过尚未提交且无法恢复的记录。采集成功仅表示本地入队和状态提交成功,不表示已上传。失败时停止继续传入正文,Skill 业务继续运行。
|
|
102
|
+
|
|
103
|
+
正式版默认遥测根目录为系统临时目录下 `alipay-aipay-telemetry`,预发版使用其下的 `pre` 子目录;两渠道的 run、outbox、上传状态及采集授权隔离;手动设置目录/文件覆盖变量时须自行按渠道分开,不能指向同一状态位置。阶段与对话队列各自保留最多 1000 条及 7 天;对话数量不挤占阶段配额。后台先处理阶段队列,再发送对话;对话写入/启动/上传失败均不改写阶段上传状态,前台联网补传判定只统计阶段队列。对话入队外壳采用 schema_ver=2,固定采集时的 platform,跨宿主补传不改变 d2;旧 schema_ver=1 外壳仍兼容。
|