@alipay/alipay-aipay 1.1.0 → 1.2.2
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/dist/commands/install.js +1 -1
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/update.js +1 -1
- package/dist/commands/update.js.map +1 -1
- package/dist/utils/alipay-cli.js +4 -4
- package/dist/utils/alipay-cli.js.map +1 -1
- package/package.json +3 -4
- package/skill/SKILL.md +75 -12
- package/skill/VERSION +1 -1
- package/skill/references/integration/flow.md +150 -108
- package/skill/references/integration/modules/alipay-sdk-reminder.md +29 -13
- package/skill/references/integration/modules/checklist.md +49 -19
- package/skill/references/integration/modules/code-examples/csharp/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +3 -3
- package/skill/references/integration/modules/code-examples/csharp/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.cs +27 -13
- package/skill/references/integration/modules/code-examples/java/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +3 -3
- package/skill/references/integration/modules/code-examples/java/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemoController.java +31 -12
- package/skill/references/integration/modules/code-examples/nodejs/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +5 -4
- package/skill/references/integration/modules/code-examples/nodejs/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.js +69 -37
- package/skill/references/integration/modules/code-examples/php/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +3 -3
- package/skill/references/integration/modules/code-examples/php/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.php +38 -17
- package/skill/references/integration/modules/code-examples/python/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +3 -3
- package/skill/references/integration/modules/code-examples/python/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.py +31 -18
- package/skill/references/integration/modules/interface-guide.md +7 -3
- package/skill/references/integration/modules/sandbox/a2m-sandbox-test.md +76 -54
- package/skill/references/integration/modules/sandbox/alipay-sandbox-tool.md +3 -3
- package/skill/references/integration/modules/sandbox/sandbox-setup-guide.md +80 -24
- package/skill/references/integration/modules/scripts/local_402_sandbox_pay.py +35 -4
- package/skill/references/normal/alipay-cli-env.md +2 -2
- package/skill/references/normal/self-update.md +2 -2
- package/skill/references/onboarding/flow.md +193 -297
- package/skill/references/onboarding/modules/app-release.md +91 -35
- package/skill/references/onboarding/modules/authorization.md +19 -13
- package/skill/references/onboarding/modules/error-handling.md +19 -14
- package/skill/references/onboarding/modules/product-sign.md +22 -21
- package/skill/references/onboarding/modules/scripts/app.sh +139 -40
- package/skill/references/onboarding/modules/scripts/auth.sh +168 -99
- package/skill/references/onboarding/modules/scripts/error_handler.sh +148 -18
- package/skill/references/onboarding/modules/scripts/query_sign_status.sh +17 -11
- package/skill/references/onboarding/modules/scripts/service.sh +208 -37
- package/skill/references/onboarding/modules/scripts/upload_screenshots.sh +1 -1
- package/skill/references/onboarding/modules/service-registration.md +72 -29
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
#=============================================================================
|
|
3
3
|
# 脚本名称: service.sh
|
|
4
4
|
# 功能描述: 服务市场注册 - 查询已有服务 + 创建/修改服务
|
|
5
|
-
# 调用位置: Step 5.2 服务市场注册
|
|
5
|
+
# 调用位置: list 用于 Step 3.1 前置资源查询;save/validate 用于 Step 5.2 服务市场注册
|
|
6
6
|
# 调用前置: 脚本通过 error_handler.sh 间接初始化 DEV_TOOL_NAME;必要时可用 DEV_TOOL_NAME 环境变量覆盖
|
|
7
7
|
# 用法:
|
|
8
8
|
# service list - 查询已有服务列表
|
|
9
9
|
# service save --name <n> --desc <d> --url <u> --pricing <p> --schema <json> [--service-id <id>]
|
|
10
10
|
# service validate --name <n> --desc <d> --url <u> --pricing <p> --schema <json>
|
|
11
11
|
# 返回值:
|
|
12
|
-
# list:
|
|
12
|
+
# list: 输出服务列表 + FLOW:CREATE_NEW | FLOW:SELECT
|
|
13
13
|
# save: 输出 ✅/❌ + serviceId(无 FLOW 标记,由 Agent 根据退出码判断)
|
|
14
14
|
# validate: 输出 ✅/❌ + 校验详情(退出码 0=通过, 1=失败)
|
|
15
15
|
#=============================================================================
|
|
@@ -29,9 +29,18 @@ require_command alipay-cli || exit 1
|
|
|
29
29
|
require_command awk || exit 1
|
|
30
30
|
|
|
31
31
|
# ─── service list: 查询已有服务 ──────────────────────────────────────────────
|
|
32
|
-
|
|
32
|
+
fetch_service_page() {
|
|
33
|
+
local OFFSET="$1"
|
|
34
|
+
local LIMIT="$2"
|
|
35
|
+
local REQUEST_JSON RESULT BUSINESS BUSINESS_CODE BUSINESS_MESSAGE
|
|
36
|
+
|
|
37
|
+
REQUEST_JSON=$(jq -n \
|
|
38
|
+
--argjson limit "$LIMIT" \
|
|
39
|
+
--argjson offset "$OFFSET" \
|
|
40
|
+
'{request:{limit:$limit,offset:$offset}}')
|
|
41
|
+
|
|
33
42
|
RESULT=$(export PLATFORM=${DEV_TOOL_NAME} && alipay-cli mcp call a2a-pay-service.discoverBazaarServicesForMcp \
|
|
34
|
-
-d
|
|
43
|
+
-d "$REQUEST_JSON" \
|
|
35
44
|
--json 2>/dev/null)
|
|
36
45
|
|
|
37
46
|
if ! handle_error "$RESULT"; then
|
|
@@ -39,9 +48,116 @@ fetch_service_list() {
|
|
|
39
48
|
fi
|
|
40
49
|
|
|
41
50
|
BUSINESS=$(unwrap_mcp "$RESULT")
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
51
|
+
|
|
52
|
+
BUSINESS_CODE=$(echo "$BUSINESS" | jq -r 'if has("code") then (.code | tostring) else "" end' 2>/dev/null)
|
|
53
|
+
if [ -n "$BUSINESS_CODE" ] && [ "$BUSINESS_CODE" != "10000" ]; then
|
|
54
|
+
BUSINESS_MESSAGE=$(echo "$BUSINESS" | jq -r '
|
|
55
|
+
.subMsg // .data.subMsg // .msg // .data.msg // "未知错误"
|
|
56
|
+
' 2>/dev/null)
|
|
57
|
+
echo "❌ 查询服务列表失败: ${BUSINESS_CODE} / ${BUSINESS_MESSAGE}"
|
|
58
|
+
return 1
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
PAGE_FORMAT=$(echo "$BUSINESS" | jq -r '
|
|
62
|
+
if ((.code | tostring) == "10000") and
|
|
63
|
+
((.data | type) == "object") and
|
|
64
|
+
((.data.items | type) == "array") and
|
|
65
|
+
((.data.pagination | type) == "object") and
|
|
66
|
+
((.data.pagination.total | type) == "number") and
|
|
67
|
+
(.data.pagination.total >= 0) and
|
|
68
|
+
((.data.pagination.total | floor) == .data.pagination.total) and
|
|
69
|
+
((.data.pagination.offset | type) == "number") and
|
|
70
|
+
(.data.pagination.offset >= 0) and
|
|
71
|
+
((.data.pagination.offset | floor) == .data.pagination.offset) then
|
|
72
|
+
"current"
|
|
73
|
+
elif (.success == true) and
|
|
74
|
+
((.resultObj | type) == "object") and
|
|
75
|
+
((.resultObj.serviceList | type) == "array") then
|
|
76
|
+
"legacy"
|
|
77
|
+
else
|
|
78
|
+
"invalid"
|
|
79
|
+
end
|
|
80
|
+
' 2>/dev/null)
|
|
81
|
+
|
|
82
|
+
case "$PAGE_FORMAT" in
|
|
83
|
+
current)
|
|
84
|
+
PAGE_ITEMS=$(echo "$BUSINESS" | jq -c '.data.items')
|
|
85
|
+
PAGE_TOTAL=$(echo "$BUSINESS" | jq -r '.data.pagination.total')
|
|
86
|
+
PAGE_OFFSET=$(echo "$BUSINESS" | jq -r '.data.pagination.offset')
|
|
87
|
+
;;
|
|
88
|
+
legacy)
|
|
89
|
+
PAGE_ITEMS=$(echo "$BUSINESS" | jq -c '.resultObj.serviceList')
|
|
90
|
+
PAGE_TOTAL=$(echo "$PAGE_ITEMS" | jq 'length')
|
|
91
|
+
PAGE_OFFSET=0
|
|
92
|
+
;;
|
|
93
|
+
*)
|
|
94
|
+
echo "❌ 服务列表返回结构异常,无法解析 data.items 或兼容的 resultObj.serviceList"
|
|
95
|
+
return 1
|
|
96
|
+
;;
|
|
97
|
+
esac
|
|
98
|
+
|
|
99
|
+
if [ -z "$PAGE_ITEMS" ] || ! echo "$PAGE_ITEMS" | jq -e 'type == "array"' >/dev/null 2>&1; then
|
|
100
|
+
echo "❌ 服务列表返回结构异常,列表字段不是数组"
|
|
101
|
+
return 1
|
|
102
|
+
fi
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
fetch_service_list() {
|
|
106
|
+
local LIMIT=20
|
|
107
|
+
local OFFSET=0
|
|
108
|
+
local EXPECTED_TOTAL=""
|
|
109
|
+
local PAGE_COUNT
|
|
110
|
+
|
|
111
|
+
SERVICE_LIST='[]'
|
|
112
|
+
|
|
113
|
+
while true; do
|
|
114
|
+
if ! fetch_service_page "$OFFSET" "$LIMIT"; then
|
|
115
|
+
return 1
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
if [ "$PAGE_FORMAT" = "legacy" ]; then
|
|
119
|
+
SERVICE_LIST="$PAGE_ITEMS"
|
|
120
|
+
break
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
if [ "$PAGE_OFFSET" -ne "$OFFSET" ]; then
|
|
124
|
+
echo "❌ 服务列表分页返回异常:期望 offset=${OFFSET},实际 offset=${PAGE_OFFSET}"
|
|
125
|
+
return 1
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
if [ -z "$EXPECTED_TOTAL" ]; then
|
|
129
|
+
EXPECTED_TOTAL="$PAGE_TOTAL"
|
|
130
|
+
elif [ "$PAGE_TOTAL" -ne "$EXPECTED_TOTAL" ]; then
|
|
131
|
+
echo "❌ 服务列表分页返回异常:分页过程中 total 发生变化"
|
|
132
|
+
return 1
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
SERVICE_LIST=$(jq -cn \
|
|
136
|
+
--argjson existing "$SERVICE_LIST" \
|
|
137
|
+
--argjson page "$PAGE_ITEMS" \
|
|
138
|
+
'$existing + $page')
|
|
139
|
+
SERVICE_COUNT=$(echo "$SERVICE_LIST" | jq 'length')
|
|
140
|
+
|
|
141
|
+
if [ "$SERVICE_COUNT" -gt "$EXPECTED_TOTAL" ]; then
|
|
142
|
+
echo "❌ 服务列表分页返回异常:已返回数量超过 total"
|
|
143
|
+
return 1
|
|
144
|
+
fi
|
|
145
|
+
if [ "$SERVICE_COUNT" -eq "$EXPECTED_TOTAL" ]; then
|
|
146
|
+
break
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
PAGE_COUNT=$(echo "$PAGE_ITEMS" | jq 'length')
|
|
150
|
+
if [ "$PAGE_COUNT" -eq 0 ]; then
|
|
151
|
+
echo "❌ 服务列表分页返回异常:尚有未返回数据但当前页为空"
|
|
152
|
+
return 1
|
|
153
|
+
fi
|
|
154
|
+
OFFSET="$SERVICE_COUNT"
|
|
155
|
+
done
|
|
156
|
+
|
|
157
|
+
if ! echo "$SERVICE_LIST" | jq -e '
|
|
158
|
+
all(.[]; ((.serviceId | type) == "string") and (.serviceId | length > 0))
|
|
159
|
+
' >/dev/null 2>&1; then
|
|
160
|
+
echo "❌ 服务列表返回结构异常:存在缺少 serviceId 的候选服务"
|
|
45
161
|
return 1
|
|
46
162
|
fi
|
|
47
163
|
|
|
@@ -54,14 +170,13 @@ service_list() {
|
|
|
54
170
|
fi
|
|
55
171
|
|
|
56
172
|
if [ "$SERVICE_COUNT" -eq 0 ] || [ "$SERVICE_LIST" = "[]" ] || [ -z "$SERVICE_LIST" ]; then
|
|
57
|
-
echo "📋
|
|
173
|
+
echo "📋 暂无已有服务;记录新建候选分支,等待 Step 4 统一决策"
|
|
58
174
|
echo "FLOW:CREATE_NEW"
|
|
59
175
|
else
|
|
60
|
-
# 输出服务列表
|
|
61
176
|
echo "📋 发现您已有以下服务:"
|
|
62
177
|
echo ""
|
|
63
|
-
echo "| 序号 | 服务ID | 服务名称 | 描述 | 价格 |
|
|
64
|
-
echo "
|
|
178
|
+
echo "| 序号 | 服务ID | 服务名称 | 描述 | 价格 | 实际状态 | 服务地址 |"
|
|
179
|
+
echo "|------|--------|----------|------|------|----------|----------|"
|
|
65
180
|
|
|
66
181
|
for i in $(seq 0 $((SERVICE_COUNT-1))); do
|
|
67
182
|
SERVICE=$(echo "$SERVICE_LIST" | jq ".[$i]")
|
|
@@ -69,11 +184,11 @@ service_list() {
|
|
|
69
184
|
SERVICE_NAME=$(echo "$SERVICE" | jq -r '.serviceName // "未知"')
|
|
70
185
|
SERVICE_DESC=$(echo "$SERVICE" | jq -r '.serviceDesc // "无描述"')
|
|
71
186
|
PRICING=$(echo "$SERVICE" | jq -r '.pricing // "未知"')
|
|
72
|
-
SERVICE_STATUS=$(echo "$SERVICE" | jq -r '.status // "未知"')
|
|
187
|
+
SERVICE_STATUS=$(echo "$SERVICE" | jq -r '.serviceStatus // .status // "未知"')
|
|
73
188
|
RESOURCE_URL=$(echo "$SERVICE" | jq -r '.resourceUrl // "未知"')
|
|
74
189
|
|
|
75
190
|
case "$SERVICE_STATUS" in
|
|
76
|
-
"
|
|
191
|
+
"ACTIVE") STATUS_CN="已上线" ;;
|
|
77
192
|
"PENDING") STATUS_CN="审核中" ;;
|
|
78
193
|
"REJECTED") STATUS_CN="审核拒绝" ;;
|
|
79
194
|
*) STATUS_CN="$SERVICE_STATUS" ;;
|
|
@@ -84,9 +199,9 @@ service_list() {
|
|
|
84
199
|
|
|
85
200
|
echo ""
|
|
86
201
|
echo "请选择:"
|
|
87
|
-
echo " •
|
|
202
|
+
echo " • 输入序号 (1-${SERVICE_COUNT}) 复用对应服务"
|
|
88
203
|
echo " • 输入\"新建\"创建新服务"
|
|
89
|
-
echo " • 输入\"
|
|
204
|
+
echo " • 输入\"修改 + serviceId\"修改已有服务"
|
|
90
205
|
echo "FLOW:SELECT"
|
|
91
206
|
fi
|
|
92
207
|
}
|
|
@@ -102,12 +217,24 @@ service_save() {
|
|
|
102
217
|
|
|
103
218
|
while [[ $# -gt 0 ]]; do
|
|
104
219
|
case $1 in
|
|
105
|
-
--service-id)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
--
|
|
109
|
-
|
|
110
|
-
|
|
220
|
+
--service-id)
|
|
221
|
+
[ $# -ge 2 ] || { echo "❌ 缺少参数值: $1"; exit 1; }
|
|
222
|
+
SERVICE_ID="$2"; shift 2 ;;
|
|
223
|
+
--name)
|
|
224
|
+
[ $# -ge 2 ] || { echo "❌ 缺少参数值: $1"; exit 1; }
|
|
225
|
+
SERVICE_NAME="$2"; shift 2 ;;
|
|
226
|
+
--desc)
|
|
227
|
+
[ $# -ge 2 ] || { echo "❌ 缺少参数值: $1"; exit 1; }
|
|
228
|
+
SERVICE_DESC="$2"; shift 2 ;;
|
|
229
|
+
--url)
|
|
230
|
+
[ $# -ge 2 ] || { echo "❌ 缺少参数值: $1"; exit 1; }
|
|
231
|
+
RESOURCE_URL="$2"; shift 2 ;;
|
|
232
|
+
--pricing)
|
|
233
|
+
[ $# -ge 2 ] || { echo "❌ 缺少参数值: $1"; exit 1; }
|
|
234
|
+
PRICING="$2"; shift 2 ;;
|
|
235
|
+
--schema)
|
|
236
|
+
[ $# -ge 2 ] || { echo "❌ 缺少参数值: $1"; exit 1; }
|
|
237
|
+
SCHEMA_URL="$2"; shift 2 ;;
|
|
111
238
|
*) echo "❌ 未知参数: $1"; exit 1 ;;
|
|
112
239
|
esac
|
|
113
240
|
done
|
|
@@ -162,26 +289,59 @@ service_save() {
|
|
|
162
289
|
exit 1
|
|
163
290
|
fi
|
|
164
291
|
|
|
165
|
-
# 解包 MCP
|
|
292
|
+
# 解包 MCP 信封后按当前协议解析,并兼容旧 success/resultObj 协议。
|
|
166
293
|
BUSINESS=$(unwrap_mcp "$RESULT")
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
294
|
+
SAVE_FORMAT=$(echo "$BUSINESS" | jq -r '
|
|
295
|
+
if ((.code | tostring) == "10000") and
|
|
296
|
+
((.data | type) == "object") and
|
|
297
|
+
(.data.success == true) then
|
|
298
|
+
"current"
|
|
299
|
+
elif (.success == true) and
|
|
300
|
+
((.resultObj | type) == "object") then
|
|
301
|
+
"legacy"
|
|
302
|
+
else
|
|
303
|
+
"invalid"
|
|
304
|
+
end
|
|
305
|
+
' 2>/dev/null)
|
|
306
|
+
|
|
307
|
+
if [ "$SAVE_FORMAT" = "current" ] || [ "$SAVE_FORMAT" = "legacy" ]; then
|
|
308
|
+
OPERATION="创建"
|
|
171
309
|
if [ -n "$SERVICE_ID" ]; then
|
|
172
310
|
OPERATION="修改"
|
|
173
311
|
fi
|
|
174
|
-
|
|
175
|
-
|
|
312
|
+
|
|
313
|
+
if [ "$SAVE_FORMAT" = "current" ]; then
|
|
314
|
+
NEW_SERVICE_ID=$(echo "$BUSINESS" | jq -r --arg fallback "${SERVICE_ID}" '
|
|
315
|
+
(.data.serviceId | select(type == "string" and length > 0)) // $fallback
|
|
316
|
+
')
|
|
317
|
+
else
|
|
318
|
+
NEW_SERVICE_ID=$(echo "$BUSINESS" | jq -r --arg fallback "${SERVICE_ID}" '
|
|
319
|
+
(.resultObj.serviceId | select(type == "string" and length > 0)) // $fallback
|
|
320
|
+
')
|
|
321
|
+
fi
|
|
322
|
+
|
|
323
|
+
if [ -z "$NEW_SERVICE_ID" ]; then
|
|
324
|
+
echo "❌ 服务创建返回成功,但未解析到 serviceId,禁止继续后续流程"
|
|
325
|
+
exit 1
|
|
326
|
+
fi
|
|
176
327
|
echo "✅ 服务${OPERATION}成功"
|
|
177
328
|
echo "📋 服务ID: $NEW_SERVICE_ID"
|
|
178
329
|
else
|
|
179
|
-
|
|
180
|
-
OPERATION="上架"
|
|
330
|
+
OPERATION="创建"
|
|
181
331
|
if [ -n "$SERVICE_ID" ]; then
|
|
182
332
|
OPERATION="修改"
|
|
183
333
|
fi
|
|
184
|
-
|
|
334
|
+
|
|
335
|
+
BUSINESS_CODE=$(echo "$BUSINESS" | jq -r 'if has("code") then (.code | tostring) else "" end' 2>/dev/null)
|
|
336
|
+
if [ -n "$BUSINESS_CODE" ] && [ "$BUSINESS_CODE" != "10000" ]; then
|
|
337
|
+
ERROR_MSG=$(echo "$BUSINESS" | jq -r '
|
|
338
|
+
.data.subMsg // .data.msg // .subMsg // .msg //
|
|
339
|
+
.error.message // .errorMessage // "未知错误"
|
|
340
|
+
' 2>/dev/null)
|
|
341
|
+
echo "❌ 服务${OPERATION}失败: ${BUSINESS_CODE} / ${ERROR_MSG:-未知错误}"
|
|
342
|
+
else
|
|
343
|
+
echo "❌ 服务${OPERATION}返回结构异常,无法确认操作结果"
|
|
344
|
+
fi
|
|
185
345
|
exit 1
|
|
186
346
|
fi
|
|
187
347
|
}
|
|
@@ -196,11 +356,21 @@ service_validate() {
|
|
|
196
356
|
|
|
197
357
|
while [[ $# -gt 0 ]]; do
|
|
198
358
|
case $1 in
|
|
199
|
-
--name)
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
--
|
|
203
|
-
|
|
359
|
+
--name)
|
|
360
|
+
[ $# -ge 2 ] || { echo "❌ 缺少参数值: $1"; exit 1; }
|
|
361
|
+
SERVICE_NAME="$2"; shift 2 ;;
|
|
362
|
+
--desc)
|
|
363
|
+
[ $# -ge 2 ] || { echo "❌ 缺少参数值: $1"; exit 1; }
|
|
364
|
+
SERVICE_DESC="$2"; shift 2 ;;
|
|
365
|
+
--url)
|
|
366
|
+
[ $# -ge 2 ] || { echo "❌ 缺少参数值: $1"; exit 1; }
|
|
367
|
+
RESOURCE_URL="$2"; shift 2 ;;
|
|
368
|
+
--pricing)
|
|
369
|
+
[ $# -ge 2 ] || { echo "❌ 缺少参数值: $1"; exit 1; }
|
|
370
|
+
PRICING="$2"; shift 2 ;;
|
|
371
|
+
--schema)
|
|
372
|
+
[ $# -ge 2 ] || { echo "❌ 缺少参数值: $1"; exit 1; }
|
|
373
|
+
SCHEMA_URL="$2"; shift 2 ;;
|
|
204
374
|
*) echo "❌ 未知参数: $1"; exit 1 ;;
|
|
205
375
|
esac
|
|
206
376
|
done
|
|
@@ -234,7 +404,8 @@ service_validate() {
|
|
|
234
404
|
exit 1
|
|
235
405
|
fi
|
|
236
406
|
|
|
237
|
-
# 5.
|
|
407
|
+
# 5. schemaUrl 在本流程中承载序列化后的 JSON 请求示例,不是 URL。
|
|
408
|
+
# CLI 接收原始 JSON;save 分支通过 jq --arg 将其安全写入字符串字段。
|
|
238
409
|
if [ -z "$SCHEMA_URL" ] || ! echo "$SCHEMA_URL" | jq . >/dev/null 2>&1; then
|
|
239
410
|
echo "❌ 请提供有效的 JSON 格式请求示例"
|
|
240
411
|
exit 1
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#=============================================================================
|
|
3
3
|
# 脚本名称: upload_screenshots.sh
|
|
4
4
|
# 功能描述: 并行上传截图文件并解析可用于签约的图片引用值
|
|
5
|
-
# 调用位置: Step 4
|
|
5
|
+
# 调用位置: Step 4 一次性资料与资源决策
|
|
6
6
|
# 调用前置: 脚本通过 error_handler.sh 间接初始化 DEV_TOOL_NAME;需传入3个文件路径
|
|
7
7
|
# 用法: bash upload_screenshots.sh "$HOME_IMG" "$SHOP_IMG" "$PAY_IMG"
|
|
8
8
|
# 返回值: 输出上传结果和图片引用值
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# 服务市场注册模块
|
|
2
2
|
|
|
3
3
|
> 本文档定义按量付费产品的服务市场上架流程。**仅按量付费产品需要服务市场注册**。
|
|
4
|
-
> 被引用文档:`
|
|
4
|
+
> 被引用文档:`onboarding/flow.md` → Step 3.1 服务查询 + Step 5.2 服务注册
|
|
5
5
|
> 本文档位于 `references/onboarding/modules/`,文中的 `scripts/...` 路径相对本目录;从技能包根目录执行时对应 `references/onboarding/modules/scripts/...`。
|
|
6
6
|
|
|
7
7
|
---
|
|
@@ -32,11 +32,11 @@
|
|
|
32
32
|
│ └─ 调用 discoverBazaarServicesForMcp │
|
|
33
33
|
│ │
|
|
34
34
|
│ Step 2: 判断服务列表 │
|
|
35
|
-
│ ├─
|
|
36
|
-
│ └─
|
|
35
|
+
│ ├─ data.items 为空 → 进入 Step 3 收集服务信息 │
|
|
36
|
+
│ └─ data.items 不为空 → 展示完整分页结果后进入 Step 3 决策 │
|
|
37
37
|
│ │
|
|
38
38
|
│ Step 3: 用户决策 │
|
|
39
|
-
│ ├─
|
|
39
|
+
│ ├─ 选择序号复用已有服务 → 跳过创建,完成 │
|
|
40
40
|
│ ├─ 选择"新建" → ⚠️ 检查服务数量,若 ≥ 20 则禁止创建 │
|
|
41
41
|
│ │ 若 < 20,收集 5 项服务信息,进入 Step 4 │
|
|
42
42
|
│ └─ 选择"修改" → 输入服务ID,收集所有服务信息,进入 Step 4 │
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
|
|
73
73
|
## Step 2: 根据查询结果执行不同分支
|
|
74
74
|
|
|
75
|
-
### 场景 A
|
|
75
|
+
### 场景 A:服务列表为空(无已有服务)
|
|
76
76
|
|
|
77
77
|
**此时必须进入 Step 3 收集服务信息并创建新服务。**
|
|
78
78
|
|
|
@@ -80,24 +80,24 @@
|
|
|
80
80
|
>
|
|
81
81
|
> ⚠️ 注意:服务数量上限为 20 个,`service.sh save` 在创建前会校验。
|
|
82
82
|
|
|
83
|
-
### 场景 B
|
|
83
|
+
### 场景 B:服务列表不为空(有已有服务)
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
**此时必须按接口返回结果展示服务及其实际状态,让用户选择复用、创建或修改。Skill 不额外按状态过滤复用候选。**
|
|
86
86
|
|
|
87
87
|
**输出格式:**
|
|
88
88
|
|
|
89
89
|
```markdown
|
|
90
90
|
📋 发现您已有以下服务:
|
|
91
91
|
|
|
92
|
-
| 序号 | 服务ID | 服务名称 | 描述 | 价格 |
|
|
93
|
-
|
|
94
|
-
| 1 | SVC001 | 天气查询 | 提供全球天气查询 | 0.01元/次 |
|
|
92
|
+
| 序号 | 服务ID | 服务名称 | 描述 | 价格 | 实际状态 | 服务地址 |
|
|
93
|
+
|------|--------|----------|------|------|----------|----------|
|
|
94
|
+
| 1 | SVC001 | 天气查询 | 提供全球天气查询 | 0.01元/次 | 已上线 | https://api.example.com/weather |
|
|
95
95
|
| 2 | SVC002 | AI助手 | 智能对话服务 | 0.05元/次 | 审核中 | https://api.example.com/ai |
|
|
96
96
|
|
|
97
97
|
请选择:
|
|
98
98
|
• 输入序号(1/2)复用对应服务
|
|
99
99
|
• 输入"新建"创建新服务
|
|
100
|
-
• 输入"修改"修改已有服务
|
|
100
|
+
• 输入"修改 + serviceId"修改已有服务
|
|
101
101
|
```
|
|
102
102
|
|
|
103
103
|
> 📎 表格渲染由 `scripts/service.sh list` 自动完成,无需手动拼接。Agent 直接展示脚本输出即可。
|
|
@@ -110,19 +110,21 @@ Agent 根据用户输入执行对应分支:
|
|
|
110
110
|
|----------|----------|
|
|
111
111
|
| 数字序号(1-$SERVICE_COUNT) | 复用对应服务 → 跳过创建,直接进入应用发布 |
|
|
112
112
|
| "新建" | 进入 Step 3 收集服务信息 → `bash scripts/service.sh save`(创建前自动校验数量 < 20) |
|
|
113
|
-
| "修改" |
|
|
113
|
+
| "修改 + serviceId" | 使用表格中展示的 serviceId → 进入 Step 3 收集**所有**字段 → `bash scripts/service.sh save --service-id <id>` |
|
|
114
114
|
|
|
115
115
|
> ⚠️ 服务数量上限 20 个,由 `service.sh save` 在创建前自动校验。
|
|
116
116
|
|
|
117
|
+
用户选择修改时可使用列表中展示的 `serviceId`。展示和记录接口返回的实际状态,不自行增加状态过滤、可用性结论或审核规则。
|
|
118
|
+
|
|
117
119
|
---
|
|
118
120
|
|
|
119
121
|
## Step 3: 收集服务信息(创建或修改服务时执行)
|
|
120
122
|
|
|
121
123
|
**⚠️ 在以下情况需执行此步骤:**
|
|
122
124
|
```
|
|
123
|
-
✅
|
|
125
|
+
✅ 服务列表为空(无已有服务)→ 创建新服务
|
|
124
126
|
✅ 用户选择"新建" → 创建新服务
|
|
125
|
-
✅ 用户选择"修改" →
|
|
127
|
+
✅ 用户选择"修改" → 修改已有服务(提供表格中的 serviceId)
|
|
126
128
|
```
|
|
127
129
|
|
|
128
130
|
**⚠️ 修改服务特别注意:**
|
|
@@ -141,11 +143,15 @@ Agent 根据用户输入执行对应分支:
|
|
|
141
143
|
2. 服务描述(1-500 字符):简要描述服务功能
|
|
142
144
|
3. 服务地址(URL):服务的 API 地址
|
|
143
145
|
4. 服务单价(元,最低 0.01):用户每次调用的费用
|
|
144
|
-
5. 请求示例(JSON):API
|
|
146
|
+
5. 请求示例(JSON):API 请求参数示例,提交时作为 `schemaUrl` 字符串传入
|
|
145
147
|
|
|
146
|
-
|
|
148
|
+
请在一条回复中一次性提供以上全部信息。修改服务时请同时提供表格中的 serviceId,不再单独增加一轮询问。
|
|
147
149
|
```
|
|
148
150
|
|
|
151
|
+
只补问缺失或校验失败的字段。已经通过校验的字段必须保留,不要求用户重新提交;修改服务仍必须最终获得全部五项字段,禁止只提交局部字段。
|
|
152
|
+
|
|
153
|
+
Agent 在当前任务中记录操作选择、serviceId 和五项服务资料。用户更正字段时只覆盖并重新校验该字段,其他未变化且已校验通过的字段继续复用;操作类型变化时清除不再适用的 serviceId 或创建资料。只补问缺失或校验失败字段,本模块的 `scripts/service.sh validate` 继续作为业务格式校验唯一来源。
|
|
154
|
+
|
|
149
155
|
### 入参校验规则
|
|
150
156
|
|
|
151
157
|
| 字段 | 说明 | 验证规则 | 错误提示 |
|
|
@@ -154,7 +160,9 @@ Agent 根据用户输入执行对应分支:
|
|
|
154
160
|
| `serviceDesc` | 服务描述 | 长度 1-500 字符 | 服务描述长度需在 1-500 字符之间 |
|
|
155
161
|
| `resourceUrl` | 服务地址 | 有效的 URL 格式(以 http:// 或 https:// 开头) | 请提供有效的 URL 地址 |
|
|
156
162
|
| `pricing` | 服务单价 | 必须 >= 0.01 元 | 服务单价最低为 0.01 元 |
|
|
157
|
-
| `schemaUrl` | 请求示例 | 有效的 JSON
|
|
163
|
+
| `schemaUrl` | 请求示例 | 有效的 JSON 格式;提交时序列化为字符串 | 请提供有效的 JSON 格式请求示例 |
|
|
164
|
+
|
|
165
|
+
> `schemaUrl` 是 MCP 入参字段名,本流程中承载的是序列化后的 JSON 请求示例,不是 URL。用户提供原始 JSON,例如 `{}`;`scripts/service.sh` 校验 JSON 后将其作为字符串写入 `request.schemaUrl`。禁止因为字段名含 `Url` 而要求用户提供网页地址。
|
|
158
166
|
|
|
159
167
|
### 校验脚本
|
|
160
168
|
|
|
@@ -186,20 +194,22 @@ bash scripts/service.sh validate --name "$SERVICE_NAME" --desc "$SERVICE_DES
|
|
|
186
194
|
### 成功输出格式
|
|
187
195
|
|
|
188
196
|
```markdown
|
|
189
|
-
✅
|
|
197
|
+
✅ 服务创建成功
|
|
190
198
|
|
|
191
199
|
| 项目 | 信息 |
|
|
192
200
|
|------|------|
|
|
201
|
+
| 服务ID | API_xxx |
|
|
193
202
|
| 服务名称 | 天气查询 |
|
|
194
203
|
| 服务描述 | 提供全球天气查询服务 |
|
|
195
204
|
| 服务地址 | https://api.example.com/weather |
|
|
196
205
|
| 服务单价 | 0.01 元/次 |
|
|
197
|
-
| 状态 | 审核中 |
|
|
198
206
|
```
|
|
199
207
|
|
|
208
|
+
`saveBazaarServiceForMcp` 的当前成功响应不包含服务状态。不得根据创建或修改成功推断为“审核中”“已上线”或其他状态。只有后续 `scripts/service.sh list` 只读查询成功并按 `serviceId` 匹配到该服务时,才能记录和展示实际状态;查询失败或尚未返回该服务时,将状态保留为“未取得”,不得因此重复执行 `save`。
|
|
209
|
+
|
|
200
210
|
### 按量付费集成产物
|
|
201
211
|
|
|
202
|
-
|
|
212
|
+
服务创建、修改或复用成功后,必须记录并向用户说明以下已取得字段:
|
|
203
213
|
|
|
204
214
|
| 字段 | 用途 |
|
|
205
215
|
|------|------|
|
|
@@ -207,7 +217,7 @@ bash scripts/service.sh validate --name "$SERVICE_NAME" --desc "$SERVICE_DES
|
|
|
207
217
|
| 服务名称 | 用于核对收银台展示和用户识别 |
|
|
208
218
|
| 服务地址 `resourceUrl` | 应与实际提供 402 服务的资源地址一致 |
|
|
209
219
|
| 服务单价 `pricing` | 应与 `Payment-Needed.protocol.amount` 的业务定价保持一致 |
|
|
210
|
-
| 服务状态 |
|
|
220
|
+
| 服务状态 | 仅在只读查询实际取得时记录,用于正式上线判断和后续排查 |
|
|
211
221
|
|
|
212
222
|
如果服务注册成功但未解析到 `serviceId`,不要继续宣称按量付费入驻完成;应提示用户重新查询服务列表或根据服务名称定位服务。
|
|
213
223
|
|
|
@@ -230,9 +240,17 @@ bash scripts/service.sh validate --name "$SERVICE_NAME" --desc "$SERVICE_DES
|
|
|
230
240
|
|
|
231
241
|
| 查询方式 | 参数 | 说明 |
|
|
232
242
|
|----------|------|------|
|
|
233
|
-
|
|
|
243
|
+
| 查询服务列表 | `{"request":{"limit":20,"offset":0}}` | 返回接口可见的服务列表;脚本按 `pagination.total` 自动翻页并完整展示实际状态,不按状态过滤候选 |
|
|
234
244
|
| 根据 serviceId 查询详情 | `{"request":{"keyword":"API_xxx"}}` | 返回指定服务的详细信息 |
|
|
235
245
|
|
|
246
|
+
**查询返回处理:**
|
|
247
|
+
|
|
248
|
+
- MCP 信封先通过共享 `unwrap_mcp` 解包 `content[0].text`。
|
|
249
|
+
- 当前成功协议以 `code="10000"` 判断,服务数组读取 `data.items`,分页读取 `data.pagination.limit/offset/total`。
|
|
250
|
+
- 当前服务状态字段读取 `serviceStatus`,兼容旧响应中的 `status`;`ACTIVE` 表示已上线,其他未定义映射的状态值原样展示,不推断业务含义。
|
|
251
|
+
- 脚本兼容旧成功协议中的 `success=true` 与 `resultObj.serviceList`,但不得用旧结构覆盖或猜测当前字段。
|
|
252
|
+
- 只有明确取得成功响应中的空数组,才能判定没有已有服务;业务失败、字段缺失、分页不完整或候选缺少 `serviceId` 均必须阻断,禁止输出 `FLOW:CREATE_NEW` 或 `FLOW:SELECT`。
|
|
253
|
+
|
|
236
254
|
**⚠️ saveBazaarServiceForMcp 创建/修改服务参数说明:**
|
|
237
255
|
|
|
238
256
|
| 场景 | 必传参数 | 说明 |
|
|
@@ -240,12 +258,35 @@ bash scripts/service.sh validate --name "$SERVICE_NAME" --desc "$SERVICE_DES
|
|
|
240
258
|
| 创建新服务 | serviceName, serviceDesc, resourceUrl, pricing, schemaUrl | 无需传入 serviceId |
|
|
241
259
|
| 修改已有服务 | **serviceId**, serviceName, serviceDesc, resourceUrl, pricing, schemaUrl | **必须传入 serviceId + 所有资料信息** |
|
|
242
260
|
|
|
261
|
+
**写入返回处理:**
|
|
262
|
+
|
|
263
|
+
- MCP 信封先通过共享 `unwrap_mcp` 解包 `content[0].text`。
|
|
264
|
+
- 当前成功协议必须同时满足 `code="10000"` 和 `data.success=true`,服务 ID 读取 `data.serviceId`。
|
|
265
|
+
- 脚本兼容旧成功协议中的 `success=true` 和 `resultObj.serviceId`;不得混用两套协议中的成功条件与服务 ID 路径。
|
|
266
|
+
- 创建成功但未解析到 `serviceId` 时必须阻断后续流程;修改成功未返回新 ID 时,继续使用本次请求中已经确认的原 `serviceId`。
|
|
267
|
+
- 业务失败优先展示 `data.subMsg` / `data.msg`,再读取顶层错误字段;响应结构不符合当前或兼容协议时不得宣称成功。
|
|
268
|
+
- 当前保存成功响应不包含服务状态;不得从 `success=true` 推断审核或上线状态。
|
|
269
|
+
|
|
270
|
+
其中 `schemaUrl` 按本模块约定传入序列化后的 JSON 请求示例。例如空请求示例的实际入参为:
|
|
271
|
+
|
|
272
|
+
```json
|
|
273
|
+
{
|
|
274
|
+
"request": {
|
|
275
|
+
"serviceName": "服务名称",
|
|
276
|
+
"serviceDesc": "服务描述",
|
|
277
|
+
"resourceUrl": "https://your-domain.com/callback",
|
|
278
|
+
"pricing": "0.6",
|
|
279
|
+
"schemaUrl": "{}"
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
243
284
|
### 正确调用示例
|
|
244
285
|
|
|
245
286
|
> 📎 所有 MCP 调用均有对应脚本:
|
|
246
287
|
|
|
247
288
|
```bash
|
|
248
|
-
# ✅
|
|
289
|
+
# ✅ 查询服务列表 → scripts/service.sh list
|
|
249
290
|
# ✅ 创建新服务 → scripts/service.sh save --name <name> --desc <desc> --url <url> --pricing <pricing> --schema <json>
|
|
250
291
|
# ✅ 修改已有服务 → scripts/service.sh save --service-id <id> --name <name> --desc <desc> --url <url> --pricing <pricing> --schema <json>
|
|
251
292
|
```
|
|
@@ -270,12 +311,14 @@ export PLATFORM=${DEV_TOOL_NAME} && alipay-cli mcp call a2a-pay-service.saveBaza
|
|
|
270
311
|
|
|
271
312
|
## 服务状态说明
|
|
272
313
|
|
|
314
|
+
当前列表响应优先读取 `serviceStatus`,旧响应兼容读取 `status`。下表以外的实际状态值必须原样展示;没有已验证依据时不得自行翻译、归类或推断是否可用。
|
|
315
|
+
|
|
273
316
|
| 状态 | 说明 | 处理方式 |
|
|
274
317
|
|------|------|----------|
|
|
275
|
-
| `DRAFT` | 草稿 |
|
|
276
|
-
| `PENDING` | 审核中 |
|
|
277
|
-
| `
|
|
278
|
-
| `REJECTED` | 审核拒绝 |
|
|
318
|
+
| `DRAFT` | 草稿 | 展示接口返回的实际状态,由用户决定后续操作 |
|
|
319
|
+
| `PENDING` | 审核中 | 展示接口返回的实际状态,由用户决定后续操作 |
|
|
320
|
+
| `ACTIVE` | 已上线 | 展示接口返回的实际状态,由用户决定后续操作 |
|
|
321
|
+
| `REJECTED` | 审核拒绝 | 展示接口返回的实际状态,由用户决定后续操作 |
|
|
279
322
|
|
|
280
323
|
---
|
|
281
324
|
|
|
@@ -283,8 +326,8 @@ export PLATFORM=${DEV_TOOL_NAME} && alipay-cli mcp call a2a-pay-service.saveBaza
|
|
|
283
326
|
|
|
284
327
|
```
|
|
285
328
|
❌ 禁止:未查询已有服务直接创建新服务
|
|
286
|
-
❌
|
|
287
|
-
❌
|
|
329
|
+
❌ 禁止:未在 Step 3.1 成功查询已有服务就要求用户决定新建/修改或提供服务资料
|
|
330
|
+
❌ 禁止:服务列表不为空时直接创建新服务(必须让用户选择)
|
|
288
331
|
❌ 禁止:用户选择复用已有服务后仍创建新服务
|
|
289
332
|
❌ 禁止:跳过服务信息校验直接提交
|
|
290
333
|
❌ 禁止:使用虚拟或自行推断的 MCP 方法
|