@alipay/alipay-aipay 1.0.2 → 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.d.ts.map +1 -1
- package/dist/commands/install.js +71 -22
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/prepare-tools.d.ts.map +1 -1
- package/dist/commands/prepare-tools.js +16 -4
- package/dist/commands/prepare-tools.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +9 -9
- package/dist/commands/update.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/alipay-cli.d.ts +6 -0
- package/dist/utils/alipay-cli.d.ts.map +1 -1
- package/dist/utils/alipay-cli.js +38 -22
- package/dist/utils/alipay-cli.js.map +1 -1
- package/dist/utils/file.d.ts +9 -2
- package/dist/utils/file.d.ts.map +1 -1
- package/dist/utils/file.js +33 -3
- package/dist/utils/file.js.map +1 -1
- package/dist/utils/gpg.d.ts.map +1 -1
- package/dist/utils/gpg.js +97 -53
- package/dist/utils/gpg.js.map +1 -1
- package/dist/utils/jq.d.ts.map +1 -1
- package/dist/utils/jq.js +6 -9
- package/dist/utils/jq.js.map +1 -1
- package/dist/utils/npm.d.ts.map +1 -1
- package/dist/utils/npm.js +2 -6
- package/dist/utils/npm.js.map +1 -1
- package/dist/utils/shell.d.ts +15 -2
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +216 -12
- package/dist/utils/shell.js.map +1 -1
- package/package.json +3 -4
- package/skill/SKILL.md +77 -11
- package/skill/VERSION +1 -0
- package/skill/references/integration/flow.md +154 -136
- 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 +77 -48
- package/skill/references/integration/modules/sandbox/alipay-sandbox-tool.md +8 -5
- package/skill/references/integration/modules/sandbox/sandbox-setup-guide.md +157 -117
- package/skill/references/integration/modules/scripts/local_402_sandbox_pay.py +35 -4
- package/skill/references/normal/alipay-cli-env.md +13 -11
- package/skill/references/normal/self-update.md +59 -0
- package/skill/references/onboarding/flow.md +202 -282
- package/skill/references/onboarding/modules/app-release.md +91 -35
- package/skill/references/onboarding/modules/authorization.md +49 -22
- package/skill/references/onboarding/modules/error-handling.md +19 -14
- package/skill/references/onboarding/modules/product-sign.md +23 -20
- package/skill/references/onboarding/modules/scripts/app.sh +139 -40
- package/skill/references/onboarding/modules/scripts/auth.sh +183 -101
- 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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# 产品签约模块
|
|
2
2
|
|
|
3
3
|
> 本文档定义产品签约的完整流程、参数规范和状态判断逻辑。
|
|
4
|
-
> 被引用文档:`
|
|
4
|
+
> 被引用文档:`onboarding/flow.md` → Step 3.1 签约查询 + Step 5.1 签约提交
|
|
5
5
|
> 本文档位于 `references/onboarding/modules/`,文中的 `scripts/...` 路径相对本目录;从技能包根目录执行时对应 `references/onboarding/modules/scripts/...`。
|
|
6
6
|
|
|
7
7
|
---
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
本模块采用 `ar-sign.apply` **外部直调 / 静态参数模式**:由 `scripts/ar_sign_apply.sh` 基于当前已确认的产品类型、MCC 和资料字段直接构造 `businessProperty` 后提交申请。它不走 `previewFormView` 动态 schema 收集循环,因此只覆盖本文档明确列出的字段和产品。
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
**使用条件:** Step 3.1 始终使用本模块的签约状态查询规则;只有查询结果为 `NOT_SIGNED` 时,才使用本模块的签约申请提交规则。`SIGNED_EFFECTIVE`、`SIGN_SUBMITTED`、查询失败或其他状态均禁止提交签约申请。
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
| 返回结果 | 状态判定 | 说明 |
|
|
43
43
|
|----------|----------|------|
|
|
44
44
|
| `resultObj.arInfoList` 为空数组 `[]` | `NOT_SIGNED` | 未签约 |
|
|
45
|
-
| `resultObj.arInfoList` 不为空,且存在 `arStatus` 为 `"02"` 的记录 | `SIGNED_EFFECTIVE` |
|
|
46
|
-
| `resultObj.arInfoList` 不为空,且存在 `arStatus` 为 `"01"` 的记录 | `SIGN_SUBMITTED` |
|
|
45
|
+
| `resultObj.arInfoList` 不为空,且存在 `arStatus` 为 `"02"` 的记录 | `SIGNED_EFFECTIVE` | 签约已生效,跳过签约材料采集,仍在 Step 4 处理应用/服务决策 |
|
|
46
|
+
| `resultObj.arInfoList` 不为空,且存在 `arStatus` 为 `"01"` 的记录 | `SIGN_SUBMITTED` | 已提交签约(待生效),跳过签约材料和重复签约提交,仍在 Step 4 处理应用/服务决策 |
|
|
47
47
|
|
|
48
48
|
### 判断逻辑
|
|
49
49
|
|
|
@@ -53,22 +53,22 @@
|
|
|
53
53
|
|
|
54
54
|
| 签约状态 | 产品类型 | FLOW 信号 | 后续流程 |
|
|
55
55
|
|----------|----------|-----------|----------|
|
|
56
|
-
| `NOT_SIGNED` | 网站支付 | `FLOW:PC_WEB_NOT_SIGNED` | 进入 Step 4
|
|
57
|
-
| `NOT_SIGNED` | APP支付 | `FLOW:APP_NOT_SIGNED` | 进入 Step 4
|
|
58
|
-
| `NOT_SIGNED` | 按量付费 | `FLOW:AI_PAY_NOT_SIGNED` |
|
|
59
|
-
| `SIGNED_EFFECTIVE` | 网站支付 | `FLOW:PC_WEB_SIGNED` |
|
|
60
|
-
| `SIGNED_EFFECTIVE` | APP支付 | `FLOW:APP_SIGNED` |
|
|
61
|
-
| `SIGNED_EFFECTIVE` | 按量付费 | `FLOW:AI_PAY_SIGNED` |
|
|
62
|
-
| `SIGN_SUBMITTED` | 网站支付 | `FLOW:PC_WEB_SIGNED` |
|
|
63
|
-
| `SIGN_SUBMITTED` | APP支付 | `FLOW:APP_SIGNED` |
|
|
64
|
-
| `SIGN_SUBMITTED` | 按量付费 | `FLOW:AI_PAY_SIGNED` |
|
|
65
|
-
|
|
66
|
-
**⚠️
|
|
56
|
+
| `NOT_SIGNED` | 网站支付 | `FLOW:PC_WEB_NOT_SIGNED` | 进入 Step 4 一次性资料与资源决策(3张网站截图 + 应用决策/条件资料)→ Step 5 签约 + 应用发布 |
|
|
57
|
+
| `NOT_SIGNED` | APP支付 | `FLOW:APP_NOT_SIGNED` | 进入 Step 4 一次性资料与资源决策(APP名称 + 3张APP界面截图 + 应用决策/条件资料)→ Step 5 签约 + 应用发布 |
|
|
58
|
+
| `NOT_SIGNED` | 按量付费 | `FLOW:AI_PAY_NOT_SIGNED` | Step 4 无需收集页面图片,但一次完成服务/应用决策和条件资料;再进入 Step 5.1 签约 |
|
|
59
|
+
| `SIGNED_EFFECTIVE` | 网站支付 | `FLOW:PC_WEB_SIGNED` | Step 4 完成应用决策后,跳过签约提交并执行应用发布 |
|
|
60
|
+
| `SIGNED_EFFECTIVE` | APP支付 | `FLOW:APP_SIGNED` | Step 4 完成应用决策后,跳过签约提交并执行应用发布 |
|
|
61
|
+
| `SIGNED_EFFECTIVE` | 按量付费 | `FLOW:AI_PAY_SIGNED` | Step 4 完成服务/应用决策后,跳过签约提交并执行服务注册 + 应用发布 |
|
|
62
|
+
| `SIGN_SUBMITTED` | 网站支付 | `FLOW:PC_WEB_SIGNED` | Step 4 完成应用决策后,跳过重复签约提交并执行应用发布 |
|
|
63
|
+
| `SIGN_SUBMITTED` | APP支付 | `FLOW:APP_SIGNED` | Step 4 完成应用决策后,跳过重复签约提交并执行应用发布 |
|
|
64
|
+
| `SIGN_SUBMITTED` | 按量付费 | `FLOW:AI_PAY_SIGNED` | Step 4 完成服务/应用决策后,跳过重复签约提交并执行服务注册 + 应用发布 |
|
|
65
|
+
|
|
66
|
+
**⚠️ 按量付费无需签约材料:**
|
|
67
67
|
```
|
|
68
68
|
✅ 网站支付未签约:需先采集 3 张网站截图,再进入 Step 5 签约
|
|
69
69
|
✅ APP支付未签约:需先采集 APP 名称和 3 张APP界面截图,再进入 Step 5 签约
|
|
70
|
-
✅ 按量付费
|
|
71
|
-
|
|
70
|
+
✅ 按量付费 未签约:Step 4 无需签约页面图片,但前置完成服务/应用决策和条件资料;Step 5 仍先提交签约
|
|
71
|
+
✅ 按量付费在 Step 4 基于已查询的服务候选,一次收集新建/修改分支的完整五项服务资料;Step 5.2 才执行写操作
|
|
72
72
|
```
|
|
73
73
|
|
|
74
74
|
**按量付费签约后的必要后续动作:**
|
|
@@ -188,8 +188,8 @@ bash scripts/ar_sign_apply.sh --product apppay --sales-code "I108030000100004131
|
|
|
188
188
|
| `mccCode` | Step 2 方案规划 | 运行时变量,格式 `Axxxx_Bxxxx`,不持久化到状态文件 |
|
|
189
189
|
| `channelCode` | 固定值 | `"B_SK_SH_RPC"` |
|
|
190
190
|
| `orderType` | 固定值 | `"NEW_SIGN"` |
|
|
191
|
-
| `screenshot` | Step 4
|
|
192
|
-
| `appName` | Step 4
|
|
191
|
+
| `screenshot` | Step 4 一次性资料与资源决策 | **仅未签约的网站支付/APP支付需要**(3个上传后的图片引用值),按量付费无需此项 |
|
|
192
|
+
| `appName` | Step 4 一次性资料与资源决策 | **仅未签约的 APP支付需要**;脚本参数仍为 `--app-name`,提交到 MCP 时映射为 `nativeAppDTO.name` |
|
|
193
193
|
| `appStatus` | 固定值 | **仅APP支付需要**,本次固定为 `OFFLINE` |
|
|
194
194
|
|
|
195
195
|
### 按量付费接入产物映射
|
|
@@ -209,8 +209,11 @@ bash scripts/ar_sign_apply.sh --product apppay --sales-code "I108030000100004131
|
|
|
209
209
|
✅ 网站支付未签约 → 需要 3 张网站截图(首页、商品页、支付页)
|
|
210
210
|
✅ APP支付未签约 → 需要 APP 名称和 3 张APP界面截图(首页、商品页、支付页),签约状态固定按 OFFLINE 提交
|
|
211
211
|
✅ 按量付费 未签约 → 无需截图,直接签约
|
|
212
|
+
✅ 网站支付/APP支付缺少支付页或支付能力 → 不提交签约;先进入/回到集成流程完成实现,再回来上传图片
|
|
213
|
+
✅ 网站支付/APP支付页面和支付能力已存在、仅缺三张页面图片 → 保留在 onboarding Step 4 收集和上传,不进入集成流程
|
|
212
214
|
❌ 禁止:按量付费 签约时传入 screenshot 字段
|
|
213
215
|
❌ 禁止:网站支付/APP支付 签约时省略 screenshot 字段
|
|
216
|
+
❌ 禁止:将“支付页”自行改口为“支付成功页”或要求用户提供文档未定义的页面
|
|
214
217
|
❌ 禁止:APP支付签约 MCP payload 中使用 webAppDTO、appDTO、appName、appType、placeType=APP、placeType=ONLINE_WEBAPP、placeType=ONLINE_NATIVEAPP 或 appType=PC_WEB
|
|
215
218
|
```
|
|
216
219
|
|
|
@@ -226,7 +229,7 @@ bash scripts/ar_sign_apply.sh --product apppay --sales-code "I108030000100004131
|
|
|
226
229
|
|
|
227
230
|
> ⚠️ **签约提交成功后,无需等待签约审核通过,应立即继续推进后续步骤。**
|
|
228
231
|
|
|
229
|
-
签约申请提交后,后端会异步审核,`arStatus` 为 `"01"
|
|
232
|
+
签约申请提交后,后端会异步审核,`arStatus` 为 `"01"`(已提交待生效)。应用创建和服务注册不依赖签约审核通过,可以继续推进。为减少用户交互,应用/服务列表查询及分支资料采集可在签约提交前完成;当前流程仍先提交签约,成功后才执行服务或应用写操作。
|
|
230
233
|
|
|
231
234
|
### FLOW 信号
|
|
232
235
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#=============================================================================
|
|
3
3
|
# 脚本名称: app.sh
|
|
4
4
|
# 功能描述: 应用发布全流程 - 查询/复用 + 创建 + 公钥设置 + 提交审核
|
|
5
|
-
# 调用位置: Step 5.3 应用发布
|
|
5
|
+
# 调用位置: list 用于 Step 3.1 前置资源查询;其他命令用于 Step 5.3 应用发布
|
|
6
6
|
# 调用前置: 脚本通过 error_handler.sh 间接初始化 DEV_TOOL_NAME
|
|
7
7
|
# list/create 可传 --application-type,未传时按 --product-type/--sales-code 或兼容环境变量推断
|
|
8
8
|
# 用法:
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
# app audit <appId> - 提交应用审核
|
|
14
14
|
# app reuse <appId> - 复用已有应用(查询安全密钥)
|
|
15
15
|
# 返回值:
|
|
16
|
-
# list: FLOW:CREATE_NEW | FLOW:SELECT | FLOW:ERROR
|
|
17
|
-
# create:
|
|
16
|
+
# list: FLOW:CREATE_NEW | FLOW:SELECT | FLOW:PENDING_APPLICATIONS | FLOW:ERROR
|
|
17
|
+
# create: 成功输出 APP_ID=xxx;失败 exit 1,返回结构异常时同时输出 FLOW:ERROR
|
|
18
18
|
# key: 输出 confirmPageUrl
|
|
19
19
|
# audit: 输出审核结果
|
|
20
20
|
# reuse: FLOW:REUSE_SUCCESS | FLOW:REUSE_NO_KEY | FLOW:ERROR
|
|
@@ -31,7 +31,6 @@ else
|
|
|
31
31
|
fi
|
|
32
32
|
|
|
33
33
|
require_command jq || exit 1
|
|
34
|
-
require_command alipay-cli || exit 1
|
|
35
34
|
|
|
36
35
|
parse_app_context_args() {
|
|
37
36
|
while [[ $# -gt 0 ]]; do
|
|
@@ -261,36 +260,54 @@ extract_application_status() {
|
|
|
261
260
|
'
|
|
262
261
|
}
|
|
263
262
|
|
|
264
|
-
|
|
263
|
+
extract_rsa2_application_key_info() {
|
|
265
264
|
echo "$SECURITY_BUSINESS" | jq -c '
|
|
266
265
|
(
|
|
267
|
-
(.resultObj.
|
|
266
|
+
(.resultObj.securityConfigList // []) +
|
|
268
267
|
(.resultObj.securityKeys // []) +
|
|
269
|
-
(.data.
|
|
270
|
-
(.data.securityKeys // [])
|
|
271
|
-
|
|
268
|
+
(.data.securityConfigList // []) +
|
|
269
|
+
(.data.securityKeys // []) +
|
|
270
|
+
(.resultObj.alipayKeyList // []) +
|
|
271
|
+
(.data.alipayKeyList // [])
|
|
272
|
+
) |
|
|
273
|
+
map(select(
|
|
274
|
+
.signType == "RSA2" and
|
|
275
|
+
(
|
|
276
|
+
((.partnerPublicKey // "") != "") or
|
|
277
|
+
((.certInfoDTO | type) == "object" and ((.certInfoDTO.publicKey // "") != ""))
|
|
278
|
+
)
|
|
279
|
+
)) |
|
|
280
|
+
.[0] // {}
|
|
272
281
|
'
|
|
273
282
|
}
|
|
274
283
|
|
|
275
|
-
|
|
284
|
+
extract_rsa2_alipay_key_info() {
|
|
276
285
|
echo "$SECURITY_BUSINESS" | jq -c '
|
|
277
286
|
(
|
|
278
|
-
(.resultObj.
|
|
279
|
-
(.data.
|
|
280
|
-
|
|
287
|
+
(.resultObj.alipayKeyList // []) +
|
|
288
|
+
(.data.alipayKeyList // []) +
|
|
289
|
+
(.resultObj.securityKeys // []) +
|
|
290
|
+
(.data.securityKeys // [])
|
|
291
|
+
) |
|
|
292
|
+
map(select(.signType == "RSA2" and ((.alipayPublicKey // "") != ""))) |
|
|
293
|
+
.[0] // {}
|
|
281
294
|
'
|
|
282
295
|
}
|
|
283
296
|
|
|
297
|
+
extract_alipay_public_key() {
|
|
298
|
+
local RSA2_KEY_INFO="$1"
|
|
299
|
+
echo "$RSA2_KEY_INFO" | jq -r '.alipayPublicKey // empty'
|
|
300
|
+
}
|
|
301
|
+
|
|
284
302
|
is_rsa2_application_key_ready() {
|
|
285
303
|
local RSA2_KEY_INFO="$1"
|
|
286
|
-
local RSA2_SECURITY_CONFIG="$2"
|
|
287
304
|
|
|
288
305
|
echo "$RSA2_KEY_INFO" | jq -e '
|
|
289
|
-
((.
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
306
|
+
((.partnerPublicKey // "") != "") or
|
|
307
|
+
(
|
|
308
|
+
(.certInfoDTO | type) == "object" and
|
|
309
|
+
((.certInfoDTO.publicKey // "") != "")
|
|
310
|
+
)
|
|
294
311
|
' >/dev/null 2>&1
|
|
295
312
|
}
|
|
296
313
|
|
|
@@ -342,10 +359,9 @@ ensure_rsa2_application_key_ready() {
|
|
|
342
359
|
while [ "$ATTEMPT" -le "$MAX_ATTEMPTS" ]; do
|
|
343
360
|
query_security_key "$APP_ID" "$PUBLIC_KEY" || return 1
|
|
344
361
|
|
|
345
|
-
RSA2_KEY_INFO=$(
|
|
346
|
-
RSA2_SECURITY_CONFIG=$(extract_rsa2_security_config)
|
|
362
|
+
RSA2_KEY_INFO=$(extract_rsa2_application_key_info)
|
|
347
363
|
|
|
348
|
-
if is_rsa2_application_key_ready "$RSA2_KEY_INFO"
|
|
364
|
+
if is_rsa2_application_key_ready "$RSA2_KEY_INFO"; then
|
|
349
365
|
return 0
|
|
350
366
|
fi
|
|
351
367
|
|
|
@@ -361,30 +377,35 @@ ensure_rsa2_application_key_ready() {
|
|
|
361
377
|
return 1
|
|
362
378
|
}
|
|
363
379
|
|
|
364
|
-
|
|
380
|
+
verify_key_and_export_alipay_public_key() {
|
|
365
381
|
local APP_ID="$1"
|
|
366
382
|
|
|
367
383
|
query_security_key "$APP_ID" || return 1
|
|
368
384
|
|
|
369
|
-
RSA2_KEY_INFO=$(
|
|
370
|
-
|
|
371
|
-
ALIPAY_PUBLIC_KEY=$(
|
|
385
|
+
RSA2_KEY_INFO=$(extract_rsa2_application_key_info)
|
|
386
|
+
RSA2_ALIPAY_KEY_INFO=$(extract_rsa2_alipay_key_info)
|
|
387
|
+
ALIPAY_PUBLIC_KEY=$(extract_alipay_public_key "$RSA2_ALIPAY_KEY_INFO")
|
|
372
388
|
|
|
373
|
-
if ! is_rsa2_application_key_ready "$RSA2_KEY_INFO"
|
|
389
|
+
if ! is_rsa2_application_key_ready "$RSA2_KEY_INFO"; then
|
|
374
390
|
echo "❌ 应用公钥尚未确认,禁止提交应用审核"
|
|
375
391
|
return 1
|
|
376
392
|
fi
|
|
377
393
|
|
|
378
394
|
if [ -z "$ALIPAY_PUBLIC_KEY" ]; then
|
|
379
|
-
echo "❌
|
|
395
|
+
echo "❌ 已确认应用公钥生效,但未获取到 RSA2 支付宝公钥,禁止提交应用审核"
|
|
380
396
|
return 1
|
|
381
397
|
fi
|
|
382
398
|
|
|
383
399
|
if write_alipay_public_key "$APP_ID" "$ALIPAY_PUBLIC_KEY"; then
|
|
384
400
|
echo "✅ 已确认应用公钥并导出支付宝公钥"
|
|
385
401
|
echo "支付宝公钥保存路径: ~/.config/${APP_ID}-alipayPublicKey.keytext"
|
|
402
|
+
echo "ALIPAY_PUBLIC_KEY_EXPORT_STATUS=EXPORTED"
|
|
386
403
|
echo "ALIPAY_PUBLIC_KEY_FILE=~/.config/${APP_ID}-alipayPublicKey.keytext"
|
|
404
|
+
else
|
|
405
|
+
echo "ALIPAY_PUBLIC_KEY_EXPORT_STATUS=MANUAL_CONFIGURATION_REQUIRED"
|
|
387
406
|
fi
|
|
407
|
+
|
|
408
|
+
return 0
|
|
388
409
|
}
|
|
389
410
|
|
|
390
411
|
# ─── app list: 查询已有应用 ──────────────────────────────────────────────────
|
|
@@ -422,7 +443,7 @@ app_list() {
|
|
|
422
443
|
elif (.resultObj | type) == "array" then
|
|
423
444
|
.resultObj
|
|
424
445
|
else
|
|
425
|
-
|
|
446
|
+
null
|
|
426
447
|
end
|
|
427
448
|
' 2>/dev/null)
|
|
428
449
|
if [ -z "$APP_LIST" ] || ! echo "$APP_LIST" | jq -e 'type == "array"' >/dev/null 2>&1; then
|
|
@@ -433,17 +454,32 @@ app_list() {
|
|
|
433
454
|
APP_COUNT=$(echo "$APP_LIST" | jq 'length')
|
|
434
455
|
|
|
435
456
|
if [ "$APP_COUNT" -eq 0 ]; then
|
|
436
|
-
echo "📋 暂无 ${APP_APPLICATION_TYPE}
|
|
457
|
+
echo "📋 暂无 ${APP_APPLICATION_TYPE} 应用;记录新建候选分支,等待 Step 4 统一决策"
|
|
437
458
|
echo "FLOW:CREATE_NEW"
|
|
438
459
|
else
|
|
439
460
|
# 实际返回的状态字段值是 "ON_LINE"(带下划线)
|
|
440
461
|
ONLINE_APPS=$(echo "$APP_LIST" | jq -r '[.[] | select(.status == "ON_LINE")]')
|
|
462
|
+
NON_ONLINE_APPS=$(echo "$APP_LIST" | jq -r '[.[] | select(.status != "ON_LINE")]')
|
|
441
463
|
ONLINE_COUNT=$(echo "$ONLINE_APPS" | jq 'length')
|
|
464
|
+
NON_ONLINE_COUNT=$(echo "$NON_ONLINE_APPS" | jq 'length')
|
|
442
465
|
ONLINE_COUNT=${ONLINE_COUNT:-0}
|
|
466
|
+
NON_ONLINE_COUNT=${NON_ONLINE_COUNT:-0}
|
|
443
467
|
|
|
444
468
|
if [ "$ONLINE_COUNT" -eq 0 ]; then
|
|
445
|
-
echo "📋
|
|
446
|
-
echo "
|
|
469
|
+
echo "📋 当前已有以下尚未上线的 ${APP_APPLICATION_TYPE} 应用:"
|
|
470
|
+
echo ""
|
|
471
|
+
echo "| 应用ID | 应用名称 | 实际状态 |"
|
|
472
|
+
echo "|--------|----------|----------|"
|
|
473
|
+
for i in $(seq 0 $((NON_ONLINE_COUNT-1))); do
|
|
474
|
+
APP=$(echo "$NON_ONLINE_APPS" | jq ".[$i]")
|
|
475
|
+
APP_ID=$(echo "$APP" | jq -r '.appId // "未知"')
|
|
476
|
+
APP_NAME=$(echo "$APP" | jq -r '.appName // "未知"')
|
|
477
|
+
APP_STATUS=$(echo "$APP" | jq -r '.status // "未知"')
|
|
478
|
+
echo "| $APP_ID | $APP_NAME | $APP_STATUS |"
|
|
479
|
+
done
|
|
480
|
+
echo ""
|
|
481
|
+
echo "以上应用当前不可复用。请等待应用上线,或在了解现有应用状态后明确选择新建。"
|
|
482
|
+
echo "FLOW:PENDING_APPLICATIONS"
|
|
447
483
|
else
|
|
448
484
|
echo "📋 发现您已有以下上线 ${APP_APPLICATION_TYPE} 应用:"
|
|
449
485
|
echo ""
|
|
@@ -457,6 +493,23 @@ app_list() {
|
|
|
457
493
|
echo "| $((i+1)) | $APP_ID | $APP_NAME | 已上线 |"
|
|
458
494
|
done
|
|
459
495
|
|
|
496
|
+
if [ "$NON_ONLINE_COUNT" -gt 0 ]; then
|
|
497
|
+
echo ""
|
|
498
|
+
echo "另有以下尚未上线的同类型应用,当前不可复用:"
|
|
499
|
+
echo ""
|
|
500
|
+
echo "| 应用ID | 应用名称 | 实际状态 |"
|
|
501
|
+
echo "|--------|----------|----------|"
|
|
502
|
+
for i in $(seq 0 $((NON_ONLINE_COUNT-1))); do
|
|
503
|
+
APP=$(echo "$NON_ONLINE_APPS" | jq ".[$i]")
|
|
504
|
+
APP_ID=$(echo "$APP" | jq -r '.appId // "未知"')
|
|
505
|
+
APP_NAME=$(echo "$APP" | jq -r '.appName // "未知"')
|
|
506
|
+
APP_STATUS=$(echo "$APP" | jq -r '.status // "未知"')
|
|
507
|
+
echo "| $APP_ID | $APP_NAME | $APP_STATUS |"
|
|
508
|
+
done
|
|
509
|
+
echo ""
|
|
510
|
+
echo "新建前请结合以上状态避免重复创建。"
|
|
511
|
+
fi
|
|
512
|
+
|
|
460
513
|
echo ""
|
|
461
514
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
462
515
|
echo " 请选择操作:"
|
|
@@ -499,6 +552,11 @@ app_create() {
|
|
|
499
552
|
|
|
500
553
|
if [ "$SUCCESS" = "true" ]; then
|
|
501
554
|
APP_ID=$(echo "$BUSINESS" | jq -r '.resultObj.appId // .data.appId // empty')
|
|
555
|
+
if [ -z "$APP_ID" ]; then
|
|
556
|
+
echo "❌ 应用创建返回成功,但未解析到 appId,禁止进入公钥设置流程"
|
|
557
|
+
echo "FLOW:ERROR"
|
|
558
|
+
exit 1
|
|
559
|
+
fi
|
|
502
560
|
echo "✅ 应用创建成功"
|
|
503
561
|
echo "APPLICATION_TYPE=$APP_APPLICATION_TYPE"
|
|
504
562
|
echo "APP_ID=$APP_ID"
|
|
@@ -511,6 +569,12 @@ app_create() {
|
|
|
511
569
|
|
|
512
570
|
# ─── app key: 设置应用公钥 ───────────────────────────────────────────────────
|
|
513
571
|
app_key() {
|
|
572
|
+
if [ "$#" -ne 2 ] || [[ "${1:-}" == --* ]]; then
|
|
573
|
+
echo "❌ 参数格式错误:key 使用位置参数 <appId> <publicKey>,不支持 --app-id 等未定义选项"
|
|
574
|
+
echo "用法: bash app.sh key <appId> <publicKey>"
|
|
575
|
+
exit 1
|
|
576
|
+
fi
|
|
577
|
+
|
|
514
578
|
APP_ID="$1"
|
|
515
579
|
PUBLIC_KEY="$2"
|
|
516
580
|
|
|
@@ -546,7 +610,8 @@ app_key() {
|
|
|
546
610
|
echo ""
|
|
547
611
|
echo "请点击以下链接确认公钥设置:"
|
|
548
612
|
echo ""
|
|
549
|
-
echo "
|
|
613
|
+
echo "提示:无法跳链时,请复制下方链接到网页浏览器打开。"
|
|
614
|
+
echo "[点击确认公钥设置]($CONFIRM_PAGE_URL)"
|
|
550
615
|
echo ""
|
|
551
616
|
echo "链接有效期为10分钟。"
|
|
552
617
|
echo ""
|
|
@@ -564,6 +629,12 @@ app_key() {
|
|
|
564
629
|
|
|
565
630
|
# ─── app audit: 提交应用审核 ─────────────────────────────────────────────────
|
|
566
631
|
app_audit() {
|
|
632
|
+
if [ "$#" -ne 1 ] || [[ "${1:-}" == --* ]]; then
|
|
633
|
+
echo "❌ 参数格式错误:audit 使用位置参数 <appId>,不支持 --app-id 等未定义选项"
|
|
634
|
+
echo "用法: bash app.sh audit <appId>"
|
|
635
|
+
exit 1
|
|
636
|
+
fi
|
|
637
|
+
|
|
567
638
|
APP_ID="$1"
|
|
568
639
|
|
|
569
640
|
if [ -z "$APP_ID" ]; then
|
|
@@ -572,7 +643,7 @@ app_audit() {
|
|
|
572
643
|
exit 1
|
|
573
644
|
fi
|
|
574
645
|
|
|
575
|
-
|
|
646
|
+
verify_key_and_export_alipay_public_key "$APP_ID" || exit 1
|
|
576
647
|
|
|
577
648
|
REQUEST_JSON=$(jq -n --arg appId "$APP_ID" '{request:{appId:$appId}}')
|
|
578
649
|
|
|
@@ -602,6 +673,12 @@ app_audit() {
|
|
|
602
673
|
|
|
603
674
|
# ─── app verify-key: 确认应用公钥已设置 ─────────────────────────────────────
|
|
604
675
|
app_verify_key() {
|
|
676
|
+
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ] || [[ "${1:-}" == --* ]]; then
|
|
677
|
+
echo "❌ 参数格式错误:verify-key 使用位置参数 <appId> [publicKey],不支持 --app-id 等未定义选项"
|
|
678
|
+
echo "用法: bash app.sh verify-key <appId> [publicKey]"
|
|
679
|
+
exit 1
|
|
680
|
+
fi
|
|
681
|
+
|
|
605
682
|
APP_ID="$1"
|
|
606
683
|
PUBLIC_KEY="${2:-}"
|
|
607
684
|
|
|
@@ -623,6 +700,12 @@ app_verify_key() {
|
|
|
623
700
|
|
|
624
701
|
# ─── app reuse: 复用已有应用(查询安全密钥) ──────────────────────────────────
|
|
625
702
|
app_reuse() {
|
|
703
|
+
if [ "$#" -ne 1 ] || [[ "${1:-}" == --* ]]; then
|
|
704
|
+
echo "❌ 参数格式错误:reuse 使用位置参数 <appId>,不支持 --app-id 等未定义选项"
|
|
705
|
+
echo "用法: bash app.sh reuse <appId>"
|
|
706
|
+
exit 1
|
|
707
|
+
fi
|
|
708
|
+
|
|
626
709
|
APP_ID="$1"
|
|
627
710
|
|
|
628
711
|
if [ -z "$APP_ID" ]; then
|
|
@@ -644,20 +727,29 @@ app_reuse() {
|
|
|
644
727
|
fi
|
|
645
728
|
|
|
646
729
|
if query_security_key "$APP_ID"; then
|
|
647
|
-
RSA2_KEY_INFO=$(
|
|
648
|
-
|
|
730
|
+
RSA2_KEY_INFO=$(extract_rsa2_application_key_info)
|
|
731
|
+
RSA2_ALIPAY_KEY_INFO=$(extract_rsa2_alipay_key_info)
|
|
732
|
+
ALIPAY_PUBLIC_KEY=$(extract_alipay_public_key "$RSA2_ALIPAY_KEY_INFO")
|
|
649
733
|
|
|
650
|
-
if
|
|
734
|
+
if ! is_rsa2_application_key_ready "$RSA2_KEY_INFO"; then
|
|
735
|
+
echo "⚠️ 未确认到已生效的 RSA2 应用公钥"
|
|
736
|
+
echo "FLOW:REUSE_NO_KEY"
|
|
737
|
+
exit 1
|
|
738
|
+
elif [ -n "$ALIPAY_PUBLIC_KEY" ]; then
|
|
651
739
|
if write_alipay_public_key "$APP_ID" "$ALIPAY_PUBLIC_KEY"; then
|
|
652
740
|
echo "✅ 已获取支付宝公钥"
|
|
653
741
|
echo "支付宝公钥保存路径: ~/.config/${APP_ID}-alipayPublicKey.keytext"
|
|
742
|
+
echo "ALIPAY_PUBLIC_KEY_EXPORT_STATUS=EXPORTED"
|
|
654
743
|
echo "ALIPAY_PUBLIC_KEY_FILE=~/.config/${APP_ID}-alipayPublicKey.keytext"
|
|
744
|
+
else
|
|
745
|
+
echo "ALIPAY_PUBLIC_KEY_EXPORT_STATUS=MANUAL_CONFIGURATION_REQUIRED"
|
|
655
746
|
fi
|
|
656
747
|
echo "APP_ID=$APP_ID"
|
|
657
748
|
echo "FLOW:REUSE_SUCCESS"
|
|
658
749
|
else
|
|
659
|
-
echo "
|
|
660
|
-
echo "FLOW:
|
|
750
|
+
echo "❌ 已确认应用公钥生效,但未获取到 RSA2 支付宝公钥"
|
|
751
|
+
echo "FLOW:ERROR"
|
|
752
|
+
exit 1
|
|
661
753
|
fi
|
|
662
754
|
else
|
|
663
755
|
echo "FLOW:ERROR"
|
|
@@ -666,7 +758,14 @@ app_reuse() {
|
|
|
666
758
|
}
|
|
667
759
|
|
|
668
760
|
# ─── 入口分发 ────────────────────────────────────────────────────────────────
|
|
669
|
-
|
|
761
|
+
APP_COMMAND="${1:-}"
|
|
762
|
+
case "$APP_COMMAND" in
|
|
763
|
+
list|create|key|verify-key|audit|reuse)
|
|
764
|
+
require_command alipay-cli || exit 1
|
|
765
|
+
;;
|
|
766
|
+
esac
|
|
767
|
+
|
|
768
|
+
case "$APP_COMMAND" in
|
|
670
769
|
list)
|
|
671
770
|
shift
|
|
672
771
|
app_list "$@"
|