@alipay/alipay-aipay 1.6.0-beta → 1.6.0-beta.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 +1 -1
- package/skill/VERSION +1 -1
- package/skill/references/integration/flow.md +22 -11
- package/skill/references/integration/modules/code-examples/csharp/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.cs +12 -8
- package/skill/references/integration/modules/code-examples/java/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +3 -2
- package/skill/references/integration/modules/code-examples/nodejs/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.js +15 -6
- package/skill/references/integration/modules/code-examples/php/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.php +36 -19
- package/skill/references/integration/modules/code-examples/python/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.py +9 -9
- package/skill/references/integration/modules/sandbox/alipay-sandbox-tool.md +4 -1
- package/skill/references/integration/modules/scripts/sandbox_config.sh +3 -2
- package/skill/references/normal/alipay-cli-env.md +2 -2
- package/skill/references/normal/full-process-routing.md +11 -5
- package/skill/references/normal/json/customer-messages.json +1 -1
- package/skill/references/normal/scripts/common.sh +21 -0
- package/skill/references/normal/scripts/integration_message_runner.mjs +63 -18
- package/skill/references/normal/scripts/onboarding_message_runner.mjs +4 -0
- package/skill/references/onboarding/flow.md +5 -5
- package/skill/references/onboarding/modules/scripts/auth.sh +1 -1
- package/skill/references/onboarding/modules/scripts/upload_screenshots.sh +4 -4
- package/skill/references/onboarding/modules/service-registration.md +1 -1
- package/skill/references/runtime-entry.md +2 -2
package/package.json
CHANGED
package/skill/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.6.0-beta
|
|
1
|
+
1.6.0-beta.1
|
|
@@ -85,15 +85,23 @@
|
|
|
85
85
|
|
|
86
86
|
### 目标项目执行上下文
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
步骤 1 前先确定唯一项目根和服务端语言,所有项目检测、安装、写入、启动和校验都以该目录为 workdir。保留原始 `PROJECT_INPUT`;新项目含名称或位置时由 Agent 解析 `TARGET_PROJECT_PATH`,runner 只校验,不解析原话或把整句当目录;纯默认新建才使用安全默认目录。复用项目未知时先定位候选,“当前项目/当前目录”仅在 runner 识别为项目根时接受。所有路径经统一 runtime 的 `resolve-project`/`locate-projects` 取得规范化事实;Skill 自有文件仍从当前 Skill 目录读取。禁止改用方便的其他项目或把临时产物算作目标项目产物。
|
|
89
89
|
|
|
90
90
|
- `full_process`:步骤 1 前置准备先继承 `../normal/full-process-routing.md` 已选定的项目来源、规范化项目路径和服务端语言,此时代码开发启动方案尚未展示,不得要求目标产品或代码状态;产品确定、项目扫描并完成唯一方案展示后,进入步骤 2 时继承同一摘要中的目标产品、项目选择分类、目标产品集成状态、其他支付产品、语言和框架。两个阶段都不得重新猜测或静默改选项目。
|
|
91
91
|
- `integration_only`:优先从当前可访问业务项目确定根目录;当前目录不是可识别项目根、存在多个候选或用户要求其他/新项目时,先让用户选定并确认规范化路径,不得自行选择或扫描上层大目录。当前目录内已选定的现有项目分类为 `CURRENT_PROJECT`,用户指定的其他现有路径分类为 `OTHER_PROJECT`;本轮按下条规则初始化成功的新项目在完成步骤 1 后分类为 `PREPARED_NEW_PROJECT`。该分类只用于本轮检查器输入,不持久化。
|
|
92
92
|
- 已有项目:进入任何写操作前确认目标路径可读、在当前 Agent 权限范围内可写、包含可识别项目根标记,且仍对应用户选定的业务项目;需要环境文件权限时按当前权限机制申请,无法取得权限、路径失效或实际项目不符时停止,要求用户提供可访问路径或重新选择项目。完整保留项目结构、已有文件和其他支付能力,只对当前目标产品需要的位置做可审查的局部修改,禁止先删除文件再重建。
|
|
93
|
-
-
|
|
93
|
+
- 新项目:含名称或位置时,Agent 唯一解析绝对 `TARGET_PROJECT_PATH` 并执行第一条命令,`PROJECT_INPUT` 仍传原话;纯默认新建执行第二条。runner 不从自然语言推导路径,只调用 `prepare-new`;应传而未传 `--target-path` 时保持未解析,禁止原话目录或默认回退。默认目录为用户目录下 `alipay-aipay-projects/pay-demo`,非空占用则加安全后缀。仅退出码 0 且唯一 JSON 满足 `projectSelection/projectOrigin=NEW_PROJECT`、`projectOriginLabel=本轮新建项目`、`preparationStatus=READY` 才继续,并确认目标或最近已有父目录可写。路径非空、预检/权限失败时保留内容并改选空或不存在目录,禁止清空或覆盖。服务端语言缺失才补问;框架使用下方 runner。创建命令只来自用户指定方式、已有模板/项目或本轮已读官方文档,禁用覆盖选项和臆造脚手架。初始化并完成步骤 1 后本轮转为 `PREPARED_NEW_PROJECT`,重入按现有项目重扫。
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message resolve-project --project-input "$PROJECT_INPUT" --target-path "$TARGET_PROJECT_PATH" --base-path "$USER_WORKSPACE_ROOT" --intent new
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message resolve-project --project-input "$PROJECT_INPUT" --base-path "$USER_WORKSPACE_ROOT" --intent new
|
|
101
|
+
```
|
|
94
102
|
- 项目准备失败时停留在步骤 1 前置准备,输出实际错误和待补条件;不得进入沙箱准备。目标项目准备成功后记录实际根目录,步骤 1、步骤 3 的沙箱配置和后续代码必须落入该项目;沙箱配置不得降级写入系统临时目录、Agent 原始工作目录或其他项目。
|
|
95
103
|
|
|
96
|
-
|
|
104
|
+
**项目选择保护规则**:当前目录已有项目时只允许保留并新增能力、在新子目录创建或使用其他路径,不展示清空/删除。明确新建产物必须保留原话并使用 `--intent new`,不得因当前目录有项目而改为复用。`full_process` 在取得 `NEW_PROJECT` 路径、技术栈和初始化结果前留在主编排;`integration_only` 在路径可安全创建前不准备沙箱或开发。确认精确空/不存在路径前不得写文件。
|
|
97
105
|
|
|
98
106
|
**启动前上下文补问**:缺少项目位置或服务端语言时,必须从本 flow 所在目录执行下列标准消息,一次补齐;只缺少新项目精确位置时仍使用上方 `integration.project_path.required`。框架缺失本身不触发补问。禁止使用 AskUserQuestion、request_user_input、宿主超时默认值、Agent 自创选项或自由话术替代;用户未明确补齐前不得创建目录、初始化项目、安装依赖或修改文件。
|
|
99
107
|
|
|
@@ -162,7 +170,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message win
|
|
|
162
170
|
资料校验通过后必须建立适用的版本控制忽略和访问保护。该例外只适用于当前沙箱资料;生产环境应用私钥和密码禁止提供给 Agent。Agent 不得在回复、摘要或普通日志中复述收到的值。
|
|
163
171
|
|
|
164
172
|
5. Unix/macOS/Linux 的 `ensure` 只依据同一目标项目的 `.alipay-sandbox.json` 当前事实分流:文件不存在时执行既有 `create`;文件存在或为符号链接时执行既有 `verify` 安全路径。已存在配置不得再次调用 `createAnonymousSandbox`、不得覆盖,也不得因为中断重来要求用户删除配置;无效、不安全或被 Git 跟踪时不得使用,脚本按待配置终态统一输出后继续代码开发。
|
|
165
|
-
6. 只有 Unix/macOS/Linux 创建分支会调用冻结的 `alipay-anonymous-sandbox.createAnonymousSandbox`、`{"request":{"appType":"PUBLICAPP"}}`、`PLATFORM` 环境变量和 `result.content[0].text -> success -> data`
|
|
173
|
+
6. 只有 Unix/macOS/Linux 创建分支会调用冻结的 `alipay-anonymous-sandbox.createAnonymousSandbox`、`{"request":{"appType":"PUBLICAPP"}}`、`PLATFORM`、`PLATFORM_ID`、`ALIPAYCLI_BIZ_INFO` 环境变量和 `result.content[0].text -> success -> data` 解包逻辑;`ALIPAYCLI_BIZ_INFO` 固定标识当前调用方 Skill 及当前生效版本,禁止传入 `PRODUCT`。Windows 不调用该方法或 `sandbox_config.sh`。
|
|
166
174
|
7. Unix/macOS/Linux 只接受以下互斥最终结果和一个临时恢复结果;待配置不算成功:
|
|
167
175
|
- `READY`:退出码为 0;唯一带 `ALIPAY_AIPAY_INTERNAL:` 前缀的 `SANDBOX_ENSURE_ACTION=CREATED|VERIFIED`、`SANDBOX_CONFIG_PATH=<同一目标项目绝对路径>/.alipay-sandbox.json` 和 `FLOW:SANDBOX_CONFIG_READY` 内部事实。
|
|
168
176
|
- `CREATE_PENDING`:退出码为 0;脚本 stdout 已渲染唯一 `sandbox.configuration.pending/CREATE` 正文;唯一带 `ALIPAY_AIPAY_INTERNAL:` 前缀的 `SANDBOX_PENDING_PATH=<同一目标项目绝对路径>/.alipay-sandbox.json` 和 `FLOW:SANDBOX_CONFIG_PENDING_CREATE` 内部事实;不得出现 READY 标记。
|
|
@@ -198,7 +206,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message win
|
|
|
198
206
|
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message start-confirm --product-type "$PRODUCT_TYPE" --product-name "$PRODUCT_NAME" --project-path "$PROJECT_PATH" --project-selection "$PROJECT_SELECTION" --language "$SERVER_LANGUAGE" --framework "$FRAMEWORK" --framework-source "$FRAMEWORK_SOURCE"
|
|
199
207
|
```
|
|
200
208
|
|
|
201
|
-
runner 失败时不得展示手写方案或进入步骤 3。成功时必须同时取得唯一 `ALIPAY_AIPAY_INTERNAL:PROJECT_CONFIRM_RECEIPT=<receipt>` 和 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=integration.start.confirm`;缺失、重复或不可解析都视为失败。stdout 是步骤 2
|
|
209
|
+
runner 失败时不得展示手写方案或进入步骤 3。成功时必须同时取得唯一 `ALIPAY_AIPAY_INTERNAL:PROJECT_CONFIRM_RECEIPT=<receipt>` 和 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=integration.start.confirm`;缺失、重复或不可解析都视为失败。stdout 是步骤 2 唯一对客消息;命令后的下一个动作必须把 stdout 作为可见进行中消息原文送达,不得作为最终答复结束当前回合,送达前禁止调用工具。命令面板、折叠输出、内部思考或“已渲染/已展示”说明都不能替代交付;禁止添加 `<...>` 标签、“已输出完整方案”“服务声明已打印”、重复摘要或任何前后缀。送达后同一回合立即执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" flow integration development --product-type "$PRODUCT_TYPE" --project-confirm-receipt "$PROJECT_CONFIRM_RECEIPT"`,不得总结、询问或等待回复。loader 返回 `PROJECT_CONFIRMATION=VALID` 才能进入步骤 3;返回 `STALE` 时 stdout 已重新渲染当前标准方案并给出新 receipt,必须先原文可见送达,再使用新 receipt 立即重试一次;连续变化说明项目事实不稳定,停在步骤 2 核对,不要求用户输入确认口令。
|
|
202
210
|
|
|
203
211
|
- `full_process`:`../normal/full-process-routing.md` 已使用同一个 `integration.start.confirm`,在同一方案中绑定检查器产生的项目来源、代码状态和其他产品,以及产品、项目路径、语言/框架和服务声明;消息送达后已经直接通过 receipt 进入本步骤,禁止再次渲染或要求确认。该消息不展示步骤清单,也不缩减执行范围;后续仍必须按当前产品完成本 flow 的全部适用接口、完成条件和 checklist。任一方案字段变化时必须返回完整接入 router 重新扫描、渲染并自动校验新的单条方案。该方案仍禁止提前展示 MCC、授权范围、产品开通材料或 onboarding 待办。
|
|
204
212
|
|
|
@@ -548,7 +556,14 @@ stdout 必须为空,stderr 只接受唯一可解析的 `ALIPAY_AIPAY_INTERNAL:
|
|
|
548
556
|
|
|
549
557
|
仅在已通过、只剩人工待验证或无法继续修复时渲染一次最终结论。
|
|
550
558
|
|
|
551
|
-
对客结论统一使用 `integration.checklist.result
|
|
559
|
+
对客结论统一使用 `integration.checklist.result`;整体结论、失败/部分通过项和人工待验证项必须来自最终一轮 checklist 实际证据。首次调用前先按以下完整契约确定参数,禁止自由改写枚举:
|
|
560
|
+
|
|
561
|
+
- `variant` 固定映射 `aipay=AIPAY`、`webpay=WEBPAY`、`apppay=APPPAY`;`overallResult` 只允许“通过、部分通过、未通过”。
|
|
562
|
+
- `failedItems` 与 `manualItems` 是包含确定下一步的受控单行值,没有对应项目时传“无”。`sandboxConfigState` 直接复用本轮脚本终态,只允许 `READY|CREATE_PENDING|VERIFY_PENDING`;`blockingDefectState` 中,除沙箱配置及其直接依赖外存在代码、安全或必要依据缺口时传 `PRESENT`,否则传 `NONE`。待配置时 `failedItems` 必须列出沙箱配置及依赖动作未完成;恢复口令只由步骤 1/3 已发送的 `sandbox.configuration.pending` 正文提供。
|
|
563
|
+
- `executionMode` 在 `integration_only` 固定为“仅代码开发”,此时 `nextFlowReminder` 固定为“正式上线前还需完成支付产品-产品开通。”。`full_process` 固定为“完整接入”:`READY` 且整体“通过”时提醒“代码开发校验通过后将自动进入支付产品-产品开通;未通过时停留在代码开发。”;沙箱待配置、整体“部分通过”且 `blockingDefectState=NONE` 时提醒“沙箱配置尚未完成,但不阻塞本轮继续支付产品-产品开通;完成配置后再进行沙箱测试。”;`READY`、整体“部分通过”、`failedItems=无` 且仅有人工待验证项时提醒“代码开发自动校验已完成,仍有人工待验证项;本轮继续产品开通。”,并把 `manualItems` 原样带入 Onboarding Step 6。其他阻断结果停在 Integration。
|
|
564
|
+
- 只有 `AIPAY` 传 `sandboxResult`:步骤 6 实际端到端联调通过时固定为“AI 按量付费沙箱服务端联调通过”,未运行、待配置或未通过时固定为“AI 按量付费沙箱服务端联调未通过”。只有 `WEBPAY` 传 `webpayExperienceResult`:按步骤 6 实际证据从“已提供浏览器付款入口和操作指引,实际付款及结果验证仍以用户完成情况为准”“未提供浏览器付款入口或完整操作指引,需先补齐”“已提供浏览器付款入口和操作指引;用户已完成一笔沙箱付款,结果只按实际核验证据记录”中选择。`APPPAY` 不传这两个参数。
|
|
565
|
+
|
|
566
|
+
必须从本 flow 所在目录执行当前产品对应单行 runner;runner stdout 是唯一对客正文,必须把 stdout 原文作为当前回复正文发给用户:
|
|
552
567
|
|
|
553
568
|
<!-- ALIPAY_AIPAY_PRODUCT:aipay:START -->
|
|
554
569
|
```bash
|
|
@@ -566,13 +581,9 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message che
|
|
|
566
581
|
```
|
|
567
582
|
<!-- ALIPAY_AIPAY_PRODUCT:END -->
|
|
568
583
|
|
|
569
|
-
`failedItems` 与 `manualItems` 必须在各自受控单行值中包含对应的确定下一步;没有对应项目时明确传入“无”。`sandboxConfigState` 必须直接复用本轮脚本终态,只允许 `READY|CREATE_PENDING|VERIFY_PENDING`。`blockingDefectState` 来自同一最终 checklist:除沙箱配置及其直接依赖动作外,存在任一代码、安全或必要依据缺口时必须为 `PRESENT`,否则为 `NONE`。待配置时 `failedItems` 必须包含沙箱配置及其依赖动作未完成;恢复口令已由步骤 1/3 选定并发送的唯一 `sandbox.configuration.pending` 正文输出,checklist runner 不生成也不重复该消息。
|
|
570
|
-
|
|
571
584
|
同一次代码开发流程只渲染一次最终 checklist 结果;renderer stdout 是本次默认收口的唯一对客正文,禁止在前后追加风险说明、通过项摘要、执行说明、衔接提醒或第二份待办。
|
|
572
585
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
只有 `AIPAY` 传入 `sandboxResult`,且只能复用步骤 6 的实际服务端联调证据;`WEBPAY` 必须按步骤 6 的实际证据传入消息目录登记的 `webpayExperienceResult` 枚举,区分已提供、未提供和用户已完成一笔体验,不得自由改写。这些字段只用于 renderer 校验最终结论,不在 checklist 对客结果中重复展示。APP 支付未来沙箱测试对客引导的维护 TODO 只保留在消息目录对应变体,不得渲染给用户;补充时必须同步本 flow、`modules/checklist.md` 和测试。
|
|
586
|
+
这些产品专属字段只用于 renderer 校验最终结论,不在 checklist 对客结果中重复展示。APP 支付未来沙箱测试对客引导的维护 TODO 只保留在消息目录对应变体,不得渲染给用户;补充时必须同步本 flow、`modules/checklist.md` 和测试。
|
|
576
587
|
|
|
577
588
|
**完成语义**:只有步骤 1-8 的适用完成条件均满足且 `sandboxConfigState=READY` 后,才可声明支付产品-代码开发完成。沙箱待配置但代码实现与其余检查通过时只能输出“部分通过”,不得改写为完成;存在其他未通过项时输出“未通过”;若配置已就绪且仅剩无法自动验证项,输出“部分通过”并登记人工待验证项,不得改写为完成或生产就绪。
|
|
578
589
|
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
*
|
|
14
14
|
* 依赖安装:
|
|
15
15
|
* dotnet add package AlipaySDKNet.Standard
|
|
16
|
-
* dotnet add package Microsoft.AspNetCore.App
|
|
17
16
|
*/
|
|
18
17
|
|
|
19
18
|
using System;
|
|
@@ -351,9 +350,10 @@ namespace A2MPaymentDemo
|
|
|
351
350
|
tradeNo = protocol.GetProperty("trade_no").GetString();
|
|
352
351
|
}
|
|
353
352
|
|
|
354
|
-
if (root.TryGetProperty("method", out var method)
|
|
353
|
+
if (root.TryGetProperty("method", out var method)
|
|
354
|
+
&& method.TryGetProperty("client_session", out var clientSessionValue))
|
|
355
355
|
{
|
|
356
|
-
clientSession =
|
|
356
|
+
clientSession = clientSessionValue.GetString();
|
|
357
357
|
}
|
|
358
358
|
}
|
|
359
359
|
|
|
@@ -379,12 +379,16 @@ namespace A2MPaymentDemo
|
|
|
379
379
|
|
|
380
380
|
// 2. 调用支付宝 API 验证支付凭证
|
|
381
381
|
var request = new AlipayAipayAgentPaymentVerifyRequest();
|
|
382
|
-
|
|
382
|
+
var verifyBizContent = new Dictionary<string, string>
|
|
383
383
|
{
|
|
384
|
-
payment_proof = paymentProofValue,
|
|
385
|
-
trade_no = tradeNo
|
|
386
|
-
|
|
387
|
-
|
|
384
|
+
["payment_proof"] = paymentProofValue,
|
|
385
|
+
["trade_no"] = tradeNo
|
|
386
|
+
};
|
|
387
|
+
if (!string.IsNullOrWhiteSpace(clientSession))
|
|
388
|
+
{
|
|
389
|
+
verifyBizContent["client_session"] = clientSession;
|
|
390
|
+
}
|
|
391
|
+
request.BizContent = JsonSerializer.Serialize(verifyBizContent);
|
|
388
392
|
|
|
389
393
|
var verifyResponse = AlipayClient.Execute(request);
|
|
390
394
|
|
|
@@ -29,7 +29,8 @@ public class AlipayTradeQuery {
|
|
|
29
29
|
|
|
30
30
|
if (response.isSuccess()) {
|
|
31
31
|
String businessState;
|
|
32
|
-
|
|
32
|
+
String tradeStatus = response.getTradeStatus();
|
|
33
|
+
switch (tradeStatus == null ? "" : tradeStatus) {
|
|
33
34
|
case "TRADE_SUCCESS":
|
|
34
35
|
case "TRADE_FINISHED":
|
|
35
36
|
businessState = "PAID";
|
|
@@ -44,7 +45,7 @@ public class AlipayTradeQuery {
|
|
|
44
45
|
businessState = "UNKNOWN";
|
|
45
46
|
}
|
|
46
47
|
System.out.println("业务状态: " + businessState + ", 支付宝状态: "
|
|
47
|
-
+
|
|
48
|
+
+ tradeStatus + ", 订单金额: " + response.getTotalAmount());
|
|
48
49
|
} else {
|
|
49
50
|
System.out.println("调用失败: " + response.getSubCode() + " - " + response.getSubMsg());
|
|
50
51
|
}
|
|
@@ -161,6 +161,12 @@ function normalizeAmount(value) {
|
|
|
161
161
|
return `${BigInt(match[1]).toString()}.${(match[2] || '').padEnd(2, '0')}`;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
+
function amountsEqual(left, right) {
|
|
165
|
+
const leftAmount = normalizeAmount(left);
|
|
166
|
+
const rightAmount = normalizeAmount(right);
|
|
167
|
+
return leftAmount !== null && rightAmount !== null && leftAmount === rightAmount;
|
|
168
|
+
}
|
|
169
|
+
|
|
164
170
|
function isExactSandboxMode() {
|
|
165
171
|
return CONFIG.alipay.gateway === 'https://openapi-sandbox.dl.alipaydev.com/gateway.do'
|
|
166
172
|
&& CONFIG.alipay.serviceId === 'api_mock_service_id';
|
|
@@ -301,12 +307,15 @@ async function verifyPaymentAndDeliverResource(req, res, paymentProof) {
|
|
|
301
307
|
return createPaymentRequiredResponse(req, res);
|
|
302
308
|
}
|
|
303
309
|
|
|
310
|
+
const verifyBizContent = {
|
|
311
|
+
payment_proof: paymentProofValue,
|
|
312
|
+
trade_no: tradeNo
|
|
313
|
+
};
|
|
314
|
+
if (clientSession) {
|
|
315
|
+
verifyBizContent.client_session = clientSession;
|
|
316
|
+
}
|
|
304
317
|
const verifyResponse = await alipaySdk.exec('alipay.aipay.agent.payment.verify', {
|
|
305
|
-
bizContent:
|
|
306
|
-
payment_proof: paymentProofValue,
|
|
307
|
-
trade_no: tradeNo,
|
|
308
|
-
client_session: clientSession
|
|
309
|
-
}
|
|
318
|
+
bizContent: verifyBizContent
|
|
310
319
|
});
|
|
311
320
|
|
|
312
321
|
// SDK 可能返回嵌套响应,也可能直接返回业务字段。
|
|
@@ -351,7 +360,7 @@ async function verifyPaymentAndDeliverResource(req, res, paymentProof) {
|
|
|
351
360
|
return createPaymentRequiredResponse(req, res);
|
|
352
361
|
}
|
|
353
362
|
|
|
354
|
-
const amountMatches = order &&
|
|
363
|
+
const amountMatches = order && amountsEqual(order.amount, verifyAmount);
|
|
355
364
|
const resourceMatches = order && order.resourceId === resourceIdVerified && resourceIdVerified === CONFIG.resource.path;
|
|
356
365
|
const fulfillmentInProgress = order && ['PENDING_CONFIRM', 'FULFILLED'].includes(order.fulfillStatus);
|
|
357
366
|
const orderUsable = order
|
|
@@ -97,42 +97,51 @@ function loadAlipayConfig() {
|
|
|
97
97
|
$privateKey = firstNonBlank(
|
|
98
98
|
getenv('ALIPAY_AIPAY_PRIVATE_KEY'),
|
|
99
99
|
$sandboxApp['appPrivatePkcsKey'] ?? null,
|
|
100
|
-
$sandbox['appPrivatePkcsKey'] ?? null
|
|
101
|
-
'<APP_PRIVATE_KEY>'
|
|
100
|
+
$sandbox['appPrivatePkcsKey'] ?? null
|
|
102
101
|
);
|
|
103
102
|
|
|
104
|
-
|
|
103
|
+
$gateway = firstNonBlank(
|
|
104
|
+
getenv('ALIPAY_AIPAY_GATEWAY'),
|
|
105
|
+
getenv('ALIPAY_GATEWAY'),
|
|
106
|
+
$sandbox['gateway'] ?? null,
|
|
107
|
+
'https://openapi-sandbox.dl.alipaydev.com/gateway.do'
|
|
108
|
+
);
|
|
109
|
+
$serviceId = firstNonBlank(
|
|
110
|
+
getenv('ALIPAY_AIPAY_SERVICE_ID'),
|
|
111
|
+
$gateway === 'https://openapi-sandbox.dl.alipaydev.com/gateway.do' ? 'api_mock_service_id' : null
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
$config = [
|
|
105
115
|
'appId' => firstNonBlank(
|
|
106
116
|
getenv('ALIPAY_AIPAY_APP_ID'),
|
|
107
117
|
$sandboxApp['appId'] ?? null,
|
|
108
|
-
$sandbox['appId'] ?? null
|
|
109
|
-
'<APP_ID>'
|
|
118
|
+
$sandbox['appId'] ?? null
|
|
110
119
|
),
|
|
111
120
|
'privateKey' => $privateKey, // PHP 使用 PKCS#1 格式应用私钥
|
|
112
121
|
'alipayPublicKey' => firstNonBlank(
|
|
113
122
|
getenv('ALIPAY_AIPAY_PUBLIC_KEY'),
|
|
114
123
|
$sandboxApp['alipayPublicKey'] ?? null,
|
|
115
|
-
$sandbox['alipayPublicKey'] ?? null
|
|
116
|
-
'<ALIPAY_PUBLIC_KEY>'
|
|
124
|
+
$sandbox['alipayPublicKey'] ?? null
|
|
117
125
|
),
|
|
118
126
|
// 默认用于本 Skill 的快速沙箱联调;生产部署时设置 ALIPAY_AIPAY_GATEWAY=https://openapi.alipay.com/gateway.do
|
|
119
|
-
'gateway' =>
|
|
120
|
-
getenv('ALIPAY_AIPAY_GATEWAY'),
|
|
121
|
-
getenv('ALIPAY_GATEWAY'),
|
|
122
|
-
$sandbox['gateway'] ?? null,
|
|
123
|
-
'https://openapi-sandbox.dl.alipaydev.com/gateway.do'
|
|
124
|
-
),
|
|
127
|
+
'gateway' => $gateway,
|
|
125
128
|
'sellerId' => firstNonBlank(
|
|
126
129
|
getenv('ALIPAY_AIPAY_SELLER_ID'),
|
|
127
130
|
$sandboxApp['pid'] ?? null,
|
|
128
131
|
$sandboxApp['uid'] ?? null,
|
|
129
|
-
$sandbox['sellerId'] ?? null
|
|
130
|
-
'<SELLER_ID_2088>'
|
|
132
|
+
$sandbox['sellerId'] ?? null
|
|
131
133
|
), // 商户 PID(2088 格式)
|
|
132
134
|
'sellerName' => firstNonBlank(getenv('ALIPAY_AIPAY_SELLER_NAME'), '测试商户'),
|
|
133
|
-
'serviceId' =>
|
|
135
|
+
'serviceId' => $serviceId, // 仅固定沙箱网关可默认 api_mock_service_id;上线前替换为真实 serviceId
|
|
134
136
|
'merchantPrivateKey' => $privateKey // 用于商家账单签名
|
|
135
137
|
];
|
|
138
|
+
|
|
139
|
+
foreach (['appId', 'privateKey', 'alipayPublicKey', 'sellerId', 'serviceId'] as $requiredField) {
|
|
140
|
+
if ($config[$requiredField] === '') {
|
|
141
|
+
throw new RuntimeException("支付宝配置缺失:{$requiredField}");
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return $config;
|
|
136
145
|
}
|
|
137
146
|
|
|
138
147
|
define('ALIPAY_CONFIG', loadAlipayConfig());
|
|
@@ -254,6 +263,12 @@ function normalizeAmount($value) {
|
|
|
254
263
|
return ($integer === '' ? '0' : $integer) . '.' . str_pad($fraction, 2, '0');
|
|
255
264
|
}
|
|
256
265
|
|
|
266
|
+
function amountsEqual($left, $right) {
|
|
267
|
+
$leftAmount = normalizeAmount($left);
|
|
268
|
+
$rightAmount = normalizeAmount($right);
|
|
269
|
+
return $leftAmount !== null && $rightAmount !== null && $leftAmount === $rightAmount;
|
|
270
|
+
}
|
|
271
|
+
|
|
257
272
|
function isExactSandboxMode() {
|
|
258
273
|
return ALIPAY_CONFIG['gateway'] === 'https://openapi-sandbox.dl.alipaydev.com/gateway.do'
|
|
259
274
|
&& ALIPAY_CONFIG['serviceId'] === 'api_mock_service_id';
|
|
@@ -427,9 +442,11 @@ function verifyPaymentAndDeliverResource($paymentProof) {
|
|
|
427
442
|
|
|
428
443
|
$model = [
|
|
429
444
|
'payment_proof' => $paymentProofValue,
|
|
430
|
-
'trade_no' => $tradeNo
|
|
431
|
-
'client_session' => $clientSession
|
|
445
|
+
'trade_no' => $tradeNo
|
|
432
446
|
];
|
|
447
|
+
if ($clientSession !== null && trim((string)$clientSession) !== '') {
|
|
448
|
+
$model['client_session'] = $clientSession;
|
|
449
|
+
}
|
|
433
450
|
|
|
434
451
|
$request->setBizContent(json_encode($model, JSON_UNESCAPED_UNICODE));
|
|
435
452
|
$responseResult = $alipayClient->execute($request);
|
|
@@ -465,7 +482,7 @@ function verifyPaymentAndDeliverResource($paymentProof) {
|
|
|
465
482
|
createPaymentRequiredResponse();
|
|
466
483
|
}
|
|
467
484
|
|
|
468
|
-
$amountMatches = $order &&
|
|
485
|
+
$amountMatches = $order && amountsEqual($order['amount'], $verifyAmount);
|
|
469
486
|
$resourceMatches = $order
|
|
470
487
|
&& $order['resourceId'] === $resourceIdVerified
|
|
471
488
|
&& $resourceIdVerified === RESOURCE_CONFIG['path'];
|
|
@@ -168,6 +168,12 @@ def normalize_amount(value):
|
|
|
168
168
|
return f'{Decimal(text):.2f}'
|
|
169
169
|
|
|
170
170
|
|
|
171
|
+
def amounts_equal(left, right):
|
|
172
|
+
left_amount = normalize_amount(left)
|
|
173
|
+
right_amount = normalize_amount(right)
|
|
174
|
+
return left_amount is not None and right_amount is not None and left_amount == right_amount
|
|
175
|
+
|
|
176
|
+
|
|
171
177
|
def is_future(value):
|
|
172
178
|
try:
|
|
173
179
|
return datetime.fromisoformat(value).timestamp() > time.time()
|
|
@@ -344,16 +350,10 @@ def verify_payment_and_deliver_resource(payment_proof):
|
|
|
344
350
|
model = AlipayAipayAgentPaymentVerifyModel()
|
|
345
351
|
model.payment_proof = payment_proof_value
|
|
346
352
|
model.trade_no = trade_no
|
|
347
|
-
|
|
353
|
+
if client_session:
|
|
354
|
+
model.client_session = client_session
|
|
348
355
|
verify_request.biz_model = model
|
|
349
356
|
|
|
350
|
-
# 如果 SDK 版本支持直接使用 dict,也可以用 biz_content(备选方案)
|
|
351
|
-
# verify_request.biz_content = json.dumps({
|
|
352
|
-
# 'payment_proof': payment_proof_value,
|
|
353
|
-
# 'trade_no': trade_no,
|
|
354
|
-
# 'client_session': client_session
|
|
355
|
-
# }, ensure_ascii=False)
|
|
356
|
-
|
|
357
357
|
verify_response_content = alipay_client.execute(verify_request)
|
|
358
358
|
verify_response = json.loads(verify_response_content)
|
|
359
359
|
|
|
@@ -392,7 +392,7 @@ def verify_payment_and_deliver_resource(payment_proof):
|
|
|
392
392
|
print(f"支付凭证无效或已过期:outTradeNo={verify_out_trade_no}")
|
|
393
393
|
return create_payment_required_response()
|
|
394
394
|
|
|
395
|
-
amount_matches = order and
|
|
395
|
+
amount_matches = order and amounts_equal(order.get('amount'), verify_amount)
|
|
396
396
|
resource_matches = (
|
|
397
397
|
order
|
|
398
398
|
and order.get('resource_id') == resource_id_verified
|
|
@@ -18,11 +18,12 @@ which alipay-cli 2>/dev/null && alipay-cli version
|
|
|
18
18
|
|
|
19
19
|
**重要:工具返回的 `data` 只是候选沙箱配置;必须先按 `sandbox-setup-guide.md` 完成字段完整性校验,校验通过后再写入正式本地配置文件。创建阶段不对客输出字段核对表、独立校验结论或沙箱环境摘要表;代码开发完成并通过配置后置校验后,才按该指南输出一张沙箱环境摘要表。该结果不代表沙箱支付测试通过。privateKey、publicKey 等密钥字段不得展开。**
|
|
20
20
|
|
|
21
|
-
`createAnonymousSandbox` 的 MCP 请求体只有业务入参 `request.appType`,当前固定为 `PUBLICAPP`。`PLATFORM` 和 `
|
|
21
|
+
`createAnonymousSandbox` 的 MCP 请求体只有业务入参 `request.appType`,当前固定为 `PUBLICAPP`。`PLATFORM`、`PLATFORM_ID` 和 `ALIPAYCLI_BIZ_INFO` 是 alipay-cli 上下文环境变量,禁止写入 `--data` 的 JSON。匿名沙箱创建不依赖本轮最终选择的支付产品,因此不得为了创建沙箱先编造或强行确认 `PRODUCT`。
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
24
|
PLATFORM="<PLATFORM>" \
|
|
25
25
|
PLATFORM_ID="<run_id>" \
|
|
26
|
+
ALIPAYCLI_BIZ_INFO='{"skill":"alipay-aipay","skill_version":"v<当前 VERSION>"}' \
|
|
26
27
|
alipay-cli mcp call alipay-anonymous-sandbox.createAnonymousSandbox \
|
|
27
28
|
--data '{"request":{"appType":"PUBLICAPP"}}' \
|
|
28
29
|
--json
|
|
@@ -40,6 +41,7 @@ alipay-cli mcp call alipay-anonymous-sandbox.createAnonymousSandbox \
|
|
|
40
41
|
|------|------|----------|
|
|
41
42
|
| `PLATFORM` | AI 编程工具识别结果 | 参考通用脚本 `../../../normal/scripts/detect_dev_tool.sh` 识别当前工具后使用其输出值;缺失时使用 `unknown`。例如 Codex 环境检测结果为 `codex` |
|
|
42
43
|
| `PLATFORM_ID` | 当前流程 `run_id` | 由 `sandbox_config.sh` 通过 `common.sh` 从当前流程 run context 读取,遥测开启或关闭都不影响该值;若宿主提供 `COZE_PROJECT_ID`、`MEOO_PROJECT_ID`,或 `MIAODA` 环境下的 `VITE_APP_ID`/`PLATFORM_ID`,新建 run 时优先以该项目 ID 为 `run_id`;缺失时不阻断沙箱创建 |
|
|
44
|
+
| `ALIPAYCLI_BIZ_INFO` | 当前生效 Skill 的 `VERSION` | 由 `common.sh` 动态生成 JSON:`{"skill":"alipay-aipay","skill_version":"v<当前 VERSION>"}`;`skill` 固定,版本统一带 `v` 前缀,禁止由 Agent 手写或沿用外部同名值 |
|
|
43
45
|
| `PRODUCT` | 不再传入 | 该 MCP 方法当前不需要产品上下文;不得把产品名写入 `--data` 或 CLI 环境变量 |
|
|
44
46
|
|
|
45
47
|
**Codex 环境示例:**
|
|
@@ -47,6 +49,7 @@ alipay-cli mcp call alipay-anonymous-sandbox.createAnonymousSandbox \
|
|
|
47
49
|
```bash
|
|
48
50
|
PLATFORM=codex \
|
|
49
51
|
PLATFORM_ID=<run_id> \
|
|
52
|
+
ALIPAYCLI_BIZ_INFO='{"skill":"alipay-aipay","skill_version":"v<当前 VERSION>"}' \
|
|
50
53
|
alipay-cli mcp call alipay-anonymous-sandbox.createAnonymousSandbox \
|
|
51
54
|
--data '{"request":{"appType":"PUBLICAPP"}}' \
|
|
52
55
|
--json
|
|
@@ -242,6 +242,7 @@ if [ "$MODE" = "create" ]; then
|
|
|
242
242
|
ensure_gitignore_protection || { echo "SANDBOX_ERROR:无法为沙箱配置建立 Git 忽略保护" >&2; exit 1; }
|
|
243
243
|
PLATFORM=$(bash "$DETECTOR") || PLATFORM="unknown"
|
|
244
244
|
init_platform_id
|
|
245
|
+
init_alipay_cli_biz_info || { echo "SANDBOX_ERROR:无法初始化 alipay-cli 业务上报信息" >&2; exit 1; }
|
|
245
246
|
if ! require_alipay_cli_local_state_access; then
|
|
246
247
|
emit_control "SANDBOX_LOCAL_FS_PERMISSION_MODE=CREATE"
|
|
247
248
|
emit_control "CLI_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION"
|
|
@@ -249,7 +250,7 @@ if [ "$MODE" = "create" ]; then
|
|
|
249
250
|
fi
|
|
250
251
|
attempt=1
|
|
251
252
|
while true; do
|
|
252
|
-
raw=$(env -u PRODUCT PLATFORM="$PLATFORM" PLATFORM_ID="${PLATFORM_ID:-}" alipay-cli mcp call alipay-anonymous-sandbox.createAnonymousSandbox --data '{"request":{"appType":"PUBLICAPP"}}' --json 2>&1)
|
|
253
|
+
raw=$(env -u PRODUCT PLATFORM="$PLATFORM" PLATFORM_ID="${PLATFORM_ID:-}" ALIPAYCLI_BIZ_INFO="$ALIPAYCLI_BIZ_INFO" alipay-cli mcp call alipay-anonymous-sandbox.createAnonymousSandbox --data '{"request":{"appType":"PUBLICAPP"}}' --json 2>&1)
|
|
253
254
|
rc=$?
|
|
254
255
|
if alipay_cli_has_local_state_permission_error "$raw"; then
|
|
255
256
|
echo "SANDBOX_ERROR:快速沙箱创建结果不明,禁止自动重复创建" >&2
|
|
@@ -274,7 +275,7 @@ if [ "$MODE" = "create" ]; then
|
|
|
274
275
|
fi
|
|
275
276
|
if [ "$(echo "$business" | jq -r '.success // false')" != "true" ] && echo "$business" | jq -r '.msg // .resultMsg // ""' | grep -q '证书密钥'; then
|
|
276
277
|
sleep 2
|
|
277
|
-
raw=$(env -u PRODUCT PLATFORM="$PLATFORM" PLATFORM_ID="${PLATFORM_ID:-}" alipay-cli mcp call alipay-anonymous-sandbox.createAnonymousSandbox --data '{"request":{"appType":"PUBLICAPP"}}' --json 2>&1)
|
|
278
|
+
raw=$(env -u PRODUCT PLATFORM="$PLATFORM" PLATFORM_ID="${PLATFORM_ID:-}" ALIPAYCLI_BIZ_INFO="$ALIPAYCLI_BIZ_INFO" alipay-cli mcp call alipay-anonymous-sandbox.createAnonymousSandbox --data '{"request":{"appType":"PUBLICAPP"}}' --json 2>&1)
|
|
278
279
|
rc=$?
|
|
279
280
|
if alipay_cli_has_local_state_permission_error "$raw"; then
|
|
280
281
|
echo "SANDBOX_ERROR:快速沙箱创建结果不明,禁止自动重复创建" >&2
|
|
@@ -130,12 +130,12 @@ source ~/.bashrc # Linux/bash
|
|
|
130
130
|
|
|
131
131
|
> ⚠️ **强制规范:检测结果仅供内部使用,禁止向用户输出!**
|
|
132
132
|
|
|
133
|
-
AI 工具由 `scripts/detect_dev_tool.sh` 检测;`init_alipay_cli_context` 设置 `DEV_TOOL_NAME`、`PLATFORM
|
|
133
|
+
AI 工具由 `scripts/detect_dev_tool.sh` 检测;`init_alipay_cli_context` 设置 `DEV_TOOL_NAME`、`PLATFORM`,把当前 `run_id` 作为 `PLATFORM_ID`(不受遥测开关影响),并从当前生效 Skill 的 `VERSION` 动态生成 `ALIPAYCLI_BIZ_INFO={"skill":"alipay-aipay","skill_version":"v<当前 VERSION>"}`。所有携带 `PLATFORM` 的 Skill 业务 CLI 调用均携带该 JSON,外部同名值会被覆盖;`alipay-cli version` 等不携带 `PLATFORM` 的安装和环境探测不注入该变量。产品确认后,Onboarding 还严格映射 `aipay|webpay|apppay` 为 `PRODUCT=AIPAY|WEBPAY|APPPAY`,其环境检查、登录、查询、写入和上传均携带该值,但 `PRODUCT` 和 `ALIPAYCLI_BIZ_INFO` 都不写入 MCP JSON;Integration 产品确定前的环境检查和快速沙箱不传 `PRODUCT`。新建 run 优先采用宿主 `COZE_PROJECT_ID`、`MEOO_PROJECT_ID` 或 MIAODA 的 `VITE_APP_ID`/`PLATFORM_ID`,并复用为 `PLATFORM_ID`。
|
|
134
134
|
|
|
135
135
|
```
|
|
136
136
|
❌ 禁止:向用户输出"环境检查完成,检测到您正在使用 Claude Code 环境"等检测结果
|
|
137
137
|
❌ 禁止:向用户透出任何关于 AI 编程工具检测的信息
|
|
138
|
-
✅ 正确:检测结果仅供内部使用,只用于脚本设置 `PLATFORM`;`PLATFORM_ID` 由脚本从当前 `run_id`
|
|
138
|
+
✅ 正确:检测结果仅供内部使用,只用于脚本设置 `PLATFORM`;`PLATFORM_ID` 由脚本从当前 `run_id` 派生,`ALIPAYCLI_BIZ_INFO` 由当前 Skill 版本派生,Onboarding 的 `PRODUCT` 由已确认产品映射
|
|
139
139
|
✅ 正确:静默完成检测,直接进入下一步流程
|
|
140
140
|
```
|
|
141
141
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
目标项目和技术栈确定后执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" flow integration entry`,只加载当前入口阶段并按步骤 1/2 准备及展示方案;代码开发满足衔接条件后执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" flow onboarding entry`。禁止整读两个 flow。所有 Skill 自有运行时动作只用当前 Skill 绝对路径下的统一入口单命令执行,不前置 `cd`、不拼接管道;用户项目命令仍以已确认项目根为 workdir。
|
|
6
6
|
|
|
7
|
-
其他 Skill 相对命令以 `references/normal/` 为 workdir
|
|
7
|
+
其他 Skill 相对命令以 `references/normal/` 为 workdir。保留原始 `PROJECT_INPUT`;明确新建产物固定用 `--intent new`,含名称或位置时由 Agent 解析绝对 `TARGET_PROJECT_PATH`,runner 只校验安全与目录状态;纯默认新建才省略。复用须选定项目根,未知位置先定位候选;“当前目录”仅在 runner 识别为项目根时接受。后续只用解析后的绝对路径。
|
|
8
8
|
|
|
9
9
|
## 边界
|
|
10
10
|
|
|
@@ -16,17 +16,23 @@
|
|
|
16
16
|
|
|
17
17
|
项目来源互斥:`CURRENT_PROJECT` 为当前目录内项目根,`OTHER_PROJECT` 为用户以绝对路径提供的目录外项目;未选定/不可访问/不可识别则为 `PROJECT_UNRESOLVED`,禁止凭描述生成状态。
|
|
18
18
|
|
|
19
|
-
`NEW_PROJECT`
|
|
19
|
+
`NEW_PROJECT` 只用于初始化前。含名称或位置时执行:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message resolve-project --project-input "$PROJECT_INPUT" --target-path "$TARGET_PROJECT_PATH" --base-path "$USER_WORKSPACE_ROOT" --intent new
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
纯默认新建时执行:
|
|
20
26
|
|
|
21
27
|
```bash
|
|
22
28
|
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message resolve-project --project-input "$PROJECT_INPUT" --base-path "$USER_WORKSPACE_ROOT" --intent new
|
|
23
29
|
```
|
|
24
30
|
|
|
25
|
-
|
|
31
|
+
第二条命令使用用户目录下 `alipay-aipay-projects/pay-demo`,非空占用则加安全后缀;其他自然语言请求缺 `--target-path` 时保持未解析,不得把原话当目录名或改用默认目录。只有 `preparationStatus=READY` 才继续;框架由 Integration 的 `framework-resolve` 按语言默认或用户明确值初始化,其他结果不得清空/覆盖。初始化且沙箱终态确定后单向成为本轮 `PREPARED_NEW_PROJECT`;不持久化,重入重扫。`NEW_PROJECT` 不扫描代码。
|
|
26
32
|
|
|
27
33
|
### 固定检查器与 runner 终态协议
|
|
28
34
|
|
|
29
|
-
- `resolve-project --intent new` 只接受退出码 0、唯一 JSON
|
|
35
|
+
- `resolve-project --intent new` 只接受退出码 0、唯一 JSON、绝对 `projectPath`、`projectSelection/projectOrigin=NEW_PROJECT`、`projectOriginLabel=本轮新建项目` 和 `preparationStatus=READY`;否则保持 `PROJECT_UNRESOLVED`。
|
|
30
36
|
- `resolve-project --intent existing` 只接受退出码 0、唯一 JSON、规范化绝对路径、`CURRENT_PROJECT|OTHER_PROJECT` 和 `EXISTING_PROJECT/现有项目`。相对路径限 `--base-path` 内,目录外由用户提供绝对路径;失败不得以描述/cwd 代替。
|
|
31
37
|
- `locate-projects` 用于未知位置/多候选,缺省搜索词为 `当前目录`。stdout 是唯一候选消息;选择后仍执行 `resolve-project --intent existing`。
|
|
32
38
|
- `start-confirm` 内部只执行一次项目扫描,校验后将同一对象交给 renderer;失败为 `STATUS_UNKNOWN`。禁止改写命令、另跑扫描、抽取代码,或追加 `find`、`ls`、`stat`、额外 `jq` 和临时脚本复核同一结果。
|
|
@@ -60,7 +66,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message con
|
|
|
60
66
|
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message locate-projects --base-path "$USER_WORKSPACE_ROOT" --search-input "$SEARCH_INPUT" --format message
|
|
61
67
|
```
|
|
62
68
|
|
|
63
|
-
字段齐备后执行唯一 runner;禁止拆开执行项目扫描、`jq` 或 renderer,也不得附加解析。runner stdout
|
|
69
|
+
字段齐备后执行唯一 runner;禁止拆开执行项目扫描、`jq` 或 renderer,也不得附加解析。runner stdout 是本动作唯一对客消息;只有取得唯一 `CUSTOMER_MESSAGE_DELIVERY_REQUIRED=integration.start.confirm` 才能继续。命令后的下一个动作必须把 stdout 作为可见进行中消息原文送达,不得作为最终答复结束当前回合,送达前禁止调用工具;送达后同一回合立即使用同一次 runner receipt 进入 development loader,不得总结、询问或等待回复。方案事实变化时重新扫描并输出,不使用确认口令;静态扫描只决定进入验证,不证明完成。
|
|
64
70
|
|
|
65
71
|
```bash
|
|
66
72
|
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message start-confirm --product-type "$PRODUCT_TYPE" --product-name "$PRODUCT_NAME" --project-path "$PROJECT_PATH" --project-selection "$PROJECT_SELECTION" --language "$SERVER_LANGUAGE" --framework "$FRAMEWORK" --framework-source "$FRAMEWORK_SOURCE"
|