@alipay/alipay-aipay 1.7.0 → 1.7.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/README.md +30 -0
- package/dist/commands/install-current.js +15 -7
- package/dist/commands/install.js +20 -16
- package/dist/commands/uninstall.js +8 -3
- package/dist/commands/update.js +34 -16
- package/dist/index.js +10 -4
- package/dist/utils/channels.js +67 -0
- package/dist/utils/config.js +15 -11
- package/dist/utils/file.js +23 -10
- package/dist/utils/npm.js +19 -33
- package/package.json +8 -3
- package/skill/SKILL.md +2 -0
- package/skill/references/normal/json/release-channel.json +1 -0
- package/skill/references/normal/scripts/self_update.mjs +62 -17
- package/skill/references/normal/self-update.md +3 -1
- package/skill-pre/SKILL.md +65 -0
- package/skill-pre/VERSION +1 -0
- package/skill-pre/references/integration/flow.md +602 -0
- package/skill-pre/references/integration/modules/alipay-sdk-reminder.md +281 -0
- package/skill-pre/references/integration/modules/checklist.md +154 -0
- package/skill-pre/references/integration/modules/code-examples/csharp/1-/351/200/232/347/224/250/346/216/245/345/217/243//345/274/202/346/255/245/351/200/232/347/237/245/345/244/204/347/220/206/344/273/243/347/240/201/347/244/272/344/276/213.md +199 -0
- package/skill-pre/references/integration/modules/code-examples/csharp/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/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +68 -0
- package/skill-pre/references/integration/modules/code-examples/csharp/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 +83 -0
- package/skill-pre/references/integration/modules/code-examples/csharp/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/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +80 -0
- package/skill-pre/references/integration/modules/code-examples/csharp/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/351/200/200/346/254/276/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 +73 -0
- package/skill-pre/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 +62 -0
- package/skill-pre/references/integration/modules/code-examples/csharp/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +132 -0
- package/skill-pre/references/integration/modules/code-examples/csharp/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +640 -0
- package/skill-pre/references/integration/modules/code-examples/java/1-/351/200/232/347/224/250/346/216/245/345/217/243//345/274/202/346/255/245/351/200/232/347/237/245/345/244/204/347/220/206/344/273/243/347/240/201/347/244/272/344/276/213.md +184 -0
- package/skill-pre/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/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +72 -0
- package/skill-pre/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 +96 -0
- package/skill-pre/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/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +81 -0
- package/skill-pre/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/351/200/200/346/254/276/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 +77 -0
- package/skill-pre/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 +69 -0
- package/skill-pre/references/integration/modules/code-examples/java/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +138 -0
- package/skill-pre/references/integration/modules/code-examples/java/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemoController.md +623 -0
- package/skill-pre/references/integration/modules/code-examples/nodejs/1-/351/200/232/347/224/250/346/216/245/345/217/243//345/274/202/346/255/245/351/200/232/347/237/245/345/244/204/347/220/206/344/273/243/347/240/201/347/244/272/344/276/213.md +135 -0
- package/skill-pre/references/integration/modules/code-examples/nodejs/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/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +51 -0
- package/skill-pre/references/integration/modules/code-examples/nodejs/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 +63 -0
- package/skill-pre/references/integration/modules/code-examples/nodejs/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/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +59 -0
- package/skill-pre/references/integration/modules/code-examples/nodejs/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/351/200/200/346/254/276/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 +54 -0
- package/skill-pre/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 +84 -0
- package/skill-pre/references/integration/modules/code-examples/nodejs/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +71 -0
- package/skill-pre/references/integration/modules/code-examples/nodejs/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +498 -0
- package/skill-pre/references/integration/modules/code-examples/php/1-/351/200/232/347/224/250/346/216/245/345/217/243//345/274/202/346/255/245/351/200/232/347/237/245/345/244/204/347/220/206/344/273/243/347/240/201/347/244/272/344/276/213.md +157 -0
- package/skill-pre/references/integration/modules/code-examples/php/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/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +59 -0
- package/skill-pre/references/integration/modules/code-examples/php/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 +73 -0
- package/skill-pre/references/integration/modules/code-examples/php/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/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +69 -0
- package/skill-pre/references/integration/modules/code-examples/php/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/351/200/200/346/254/276/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 +65 -0
- package/skill-pre/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 +59 -0
- package/skill-pre/references/integration/modules/code-examples/php/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +110 -0
- package/skill-pre/references/integration/modules/code-examples/php/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +806 -0
- package/skill-pre/references/integration/modules/code-examples/python/1-/351/200/232/347/224/250/346/216/245/345/217/243//345/274/202/346/255/245/351/200/232/347/237/245/345/244/204/347/220/206/344/273/243/347/240/201/347/244/272/344/276/213.md +128 -0
- package/skill-pre/references/integration/modules/code-examples/python/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/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +57 -0
- package/skill-pre/references/integration/modules/code-examples/python/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 +70 -0
- package/skill-pre/references/integration/modules/code-examples/python/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/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +65 -0
- package/skill-pre/references/integration/modules/code-examples/python/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/351/200/200/346/254/276/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 +62 -0
- package/skill-pre/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 +51 -0
- package/skill-pre/references/integration/modules/code-examples/python/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +47 -0
- package/skill-pre/references/integration/modules/code-examples/python/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +541 -0
- package/skill-pre/references/integration/modules/interface-contract/aipay-interface-contract.md +52 -0
- package/skill-pre/references/integration/modules/interface-contract/apppay-interface-contract.md +45 -0
- package/skill-pre/references/integration/modules/interface-contract/common-trade-contract.md +42 -0
- package/skill-pre/references/integration/modules/interface-contract/notify-url-contract.md +68 -0
- package/skill-pre/references/integration/modules/interface-contract/webpay-interface-contract.md +44 -0
- package/skill-pre/references/integration/modules/interface-guide.md +61 -0
- package/skill-pre/references/integration/modules/product-decision.md +73 -0
- package/skill-pre/references/integration/modules/sandbox/a2m-sandbox-test.md +235 -0
- package/skill-pre/references/integration/modules/sandbox/alipay-sandbox-tool.md +142 -0
- package/skill-pre/references/integration/modules/sandbox/sandbox-setup-guide.md +239 -0
- package/skill-pre/references/integration/modules/scripts/local_402_sandbox_pay.py +900 -0
- package/skill-pre/references/integration/modules/scripts/sandbox_config.sh +347 -0
- package/skill-pre/references/integration/modules/troubleshooting-flow.md +28 -0
- package/skill-pre/references/normal/alipay-cli-env.md +169 -0
- package/skill-pre/references/normal/conversation-telemetry.md +101 -0
- package/skill-pre/references/normal/full-process-routing.md +92 -0
- package/skill-pre/references/normal/integration-worker.md +90 -0
- package/skill-pre/references/normal/json/customer-messages.json +1 -0
- package/skill-pre/references/normal/json/managed-jq-assets.json +1 -0
- package/skill-pre/references/normal/json/policy-rules.json +1 -0
- package/skill-pre/references/normal/json/release-channel.json +1 -0
- package/skill-pre/references/normal/rejection-guide.md +41 -0
- package/skill-pre/references/normal/scripts/agent_platform.mjs +43 -0
- package/skill-pre/references/normal/scripts/alipay_cli_env.mjs +34 -0
- package/skill-pre/references/normal/scripts/alipay_cli_env.sh +55 -0
- package/skill-pre/references/normal/scripts/alipay_cli_refresh.mjs +129 -0
- package/skill-pre/references/normal/scripts/auth_runtime_runner.mjs +60 -0
- package/skill-pre/references/normal/scripts/checklist_sections.mjs +43 -0
- package/skill-pre/references/normal/scripts/common.sh +365 -0
- package/skill-pre/references/normal/scripts/conversation_telemetry.mjs +105 -0
- package/skill-pre/references/normal/scripts/detect_dev_tool.sh +79 -0
- package/skill-pre/references/normal/scripts/flow_loader.mjs +237 -0
- package/skill-pre/references/normal/scripts/integration_context_runner.mjs +151 -0
- package/skill-pre/references/normal/scripts/integration_message_runner.mjs +1456 -0
- package/skill-pre/references/normal/scripts/interaction_reply.mjs +140 -0
- package/skill-pre/references/normal/scripts/managed_jq.mjs +215 -0
- package/skill-pre/references/normal/scripts/onboarding_discovery_runner.mjs +387 -0
- package/skill-pre/references/normal/scripts/onboarding_message_runner.mjs +1425 -0
- package/skill-pre/references/normal/scripts/onboarding_recovery_runner.mjs +100 -0
- package/skill-pre/references/normal/scripts/open_official_url.sh +205 -0
- package/skill-pre/references/normal/scripts/platform_compat.mjs +42 -0
- package/skill-pre/references/normal/scripts/preview_runtime.mjs +151 -0
- package/skill-pre/references/normal/scripts/project_route_inspector.sh +132 -0
- package/skill-pre/references/normal/scripts/python_script_runner.mjs +58 -0
- package/skill-pre/references/normal/scripts/render_customer_message.mjs +1792 -0
- package/skill-pre/references/normal/scripts/runtime.mjs +271 -0
- package/skill-pre/references/normal/scripts/self_update.mjs +376 -0
- package/skill-pre/references/normal/scripts/telemetry.mjs +2102 -0
- package/skill-pre/references/normal/self-update.md +7 -0
- package/skill-pre/references/normal/telemetry.md +70 -0
- package/skill-pre/references/onboarding/assets/keygen.html +927 -0
- package/skill-pre/references/onboarding/flow.md +607 -0
- package/skill-pre/references/onboarding/modules/app-release.md +90 -0
- package/skill-pre/references/onboarding/modules/authorization.md +43 -0
- package/skill-pre/references/onboarding/modules/error-handling.md +62 -0
- package/skill-pre/references/onboarding/modules/product-sign.md +49 -0
- package/skill-pre/references/onboarding/modules/scripts/app.sh +1485 -0
- package/skill-pre/references/onboarding/modules/scripts/ar_sign_apply.sh +331 -0
- package/skill-pre/references/onboarding/modules/scripts/auth.sh +1040 -0
- package/skill-pre/references/onboarding/modules/scripts/download_key_tool.sh +4 -0
- package/skill-pre/references/onboarding/modules/scripts/error_handler.sh +841 -0
- package/skill-pre/references/onboarding/modules/scripts/mcc.sh +1085 -0
- package/skill-pre/references/onboarding/modules/scripts/network_retry.sh +135 -0
- package/skill-pre/references/onboarding/modules/scripts/query_sign_status.sh +105 -0
- package/skill-pre/references/onboarding/modules/scripts/service.sh +528 -0
- package/skill-pre/references/onboarding/modules/scripts/sign_status_parser.sh +58 -0
- package/skill-pre/references/onboarding/modules/scripts/upload_screenshots.sh +208 -0
- package/skill-pre/references/onboarding/modules/scripts/upload_special_license.sh +195 -0
- package/skill-pre/references/onboarding/modules/service-registration.md +40 -0
- package/skill-pre/references/runtime-entry.md +99 -0
- package/dist/commands/install-current.d.ts +0 -4
- package/dist/commands/install-current.d.ts.map +0 -1
- package/dist/commands/install-current.js.map +0 -1
- package/dist/commands/install.d.ts +0 -10
- package/dist/commands/install.d.ts.map +0 -1
- package/dist/commands/install.js.map +0 -1
- package/dist/commands/prepare-tools.d.ts +0 -5
- package/dist/commands/prepare-tools.d.ts.map +0 -1
- package/dist/commands/prepare-tools.js.map +0 -1
- package/dist/commands/uninstall.d.ts +0 -10
- package/dist/commands/uninstall.d.ts.map +0 -1
- package/dist/commands/uninstall.js.map +0 -1
- package/dist/commands/update.d.ts +0 -10
- package/dist/commands/update.d.ts.map +0 -1
- package/dist/commands/update.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/types.d.ts +0 -42
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils/alipay-cli.d.ts +0 -20
- package/dist/utils/alipay-cli.d.ts.map +0 -1
- package/dist/utils/alipay-cli.js.map +0 -1
- package/dist/utils/config.d.ts +0 -52
- package/dist/utils/config.d.ts.map +0 -1
- package/dist/utils/config.js.map +0 -1
- package/dist/utils/file.d.ts +0 -77
- package/dist/utils/file.d.ts.map +0 -1
- package/dist/utils/file.js.map +0 -1
- package/dist/utils/jq.d.ts +0 -17
- package/dist/utils/jq.d.ts.map +0 -1
- package/dist/utils/jq.js.map +0 -1
- package/dist/utils/npm.d.ts +0 -17
- package/dist/utils/npm.d.ts.map +0 -1
- package/dist/utils/npm.js.map +0 -1
- package/dist/utils/shell.d.ts +0 -24
- package/dist/utils/shell.d.ts.map +0 -1
- package/dist/utils/shell.js.map +0 -1
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Sensitive sandbox fields are held in shell variables below; never inherit
|
|
4
|
+
# caller tracing into the parsing and persistence path.
|
|
5
|
+
set +x
|
|
6
|
+
set -u
|
|
7
|
+
|
|
8
|
+
MODE="${1:-}"
|
|
9
|
+
PRODUCT_TYPE=""
|
|
10
|
+
PROJECT_PATH=""
|
|
11
|
+
LANGUAGE=""
|
|
12
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
13
|
+
NORMAL_SCRIPTS="${SCRIPT_DIR}/../../../normal/scripts"
|
|
14
|
+
RENDERER="${NORMAL_SCRIPTS}/render_customer_message.mjs"
|
|
15
|
+
DETECTOR="${NORMAL_SCRIPTS}/detect_dev_tool.sh"
|
|
16
|
+
COMMON_SCRIPT="${NORMAL_SCRIPTS}/common.sh"
|
|
17
|
+
|
|
18
|
+
if [ -f "$COMMON_SCRIPT" ]; then
|
|
19
|
+
# shellcheck source=/dev/null
|
|
20
|
+
source "$COMMON_SCRIPT"
|
|
21
|
+
else
|
|
22
|
+
echo "SANDBOX_ERROR:缺少公共脚本 $COMMON_SCRIPT" >&2
|
|
23
|
+
exit 1
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
case "$MODE" in
|
|
27
|
+
create|verify|ensure|reverify)
|
|
28
|
+
if [ "${2:-}" = "aipay" ] || [ "${2:-}" = "webpay" ] || [ "${2:-}" = "apppay" ]; then
|
|
29
|
+
echo "SANDBOX_ERROR:${MODE} 不接受 productType 参数;用法 sandbox_config.sh ${MODE} <projectPath> <language>" >&2
|
|
30
|
+
exit 2
|
|
31
|
+
fi
|
|
32
|
+
PROJECT_PATH="${2:-}"
|
|
33
|
+
LANGUAGE="${3:-}"
|
|
34
|
+
;;
|
|
35
|
+
summary)
|
|
36
|
+
PRODUCT_TYPE="${2:-}"
|
|
37
|
+
PROJECT_PATH="${3:-}"
|
|
38
|
+
LANGUAGE="${4:-}"
|
|
39
|
+
;;
|
|
40
|
+
*)
|
|
41
|
+
echo "SANDBOX_ERROR:用法 sandbox_config.sh <ensure|reverify|create|verify> <projectPath> <language> 或 sandbox_config.sh summary <productType> <projectPath> <language>" >&2
|
|
42
|
+
exit 2
|
|
43
|
+
;;
|
|
44
|
+
esac
|
|
45
|
+
|
|
46
|
+
normalize_language() {
|
|
47
|
+
local value compact
|
|
48
|
+
value="${1:-}"
|
|
49
|
+
compact=$(printf '%s' "$value" | tr '[:upper:]' '[:lower:]' | sed 's/[ ._-]//g')
|
|
50
|
+
case "$compact" in
|
|
51
|
+
java) printf '%s\n' "Java" ;;
|
|
52
|
+
python|python3|py) printf '%s\n' "Python" ;;
|
|
53
|
+
nodejs|node|javascript|js) printf '%s\n' "Node.js" ;;
|
|
54
|
+
c#|csharp|dotnet|net) printf '%s\n' "C#" ;;
|
|
55
|
+
php) printf '%s\n' "PHP" ;;
|
|
56
|
+
*) return 1 ;;
|
|
57
|
+
esac
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
LANGUAGE="$(normalize_language "$LANGUAGE")" || {
|
|
61
|
+
echo "SANDBOX_ERROR:语言非法,仅支持 Java|Python|Node.js|C#|PHP;Node.js 请使用 Node.js 或 nodejs" >&2
|
|
62
|
+
exit 2
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
CONFIG_PATH="${PROJECT_PATH}/.alipay-sandbox.json"
|
|
66
|
+
GITIGNORE_PATH="${PROJECT_PATH}/.gitignore"
|
|
67
|
+
|
|
68
|
+
render_pending() {
|
|
69
|
+
printf '%s' '{}' | node "$RENDERER" sandbox.configuration.pending --variant "$PENDING_VARIANT" || {
|
|
70
|
+
echo "SANDBOX_ERROR:沙箱待配置消息渲染失败" >&2
|
|
71
|
+
return 1
|
|
72
|
+
}
|
|
73
|
+
emit_control "CUSTOMER_MESSAGE_DELIVERY_REQUIRED=sandbox.configuration.pending" || return 1
|
|
74
|
+
emit_control_field "SANDBOX_PENDING_PATH" "$CONFIG_PATH" || return 1
|
|
75
|
+
emit_control "$PENDING_MARKER"
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if [ "$MODE" = "summary" ]; then
|
|
79
|
+
case "$PRODUCT_TYPE" in aipay) PRODUCT_NAME="AI 按量付费" ;; webpay) PRODUCT_NAME="AI 网页应用收款" ;; apppay) PRODUCT_NAME="AI 移动应用收款" ;; *) echo "SANDBOX_ERROR:产品非法,仅支持 aipay|webpay|apppay" >&2; exit 2 ;; esac
|
|
80
|
+
fi
|
|
81
|
+
case "$PROJECT_PATH" in /*) ;; *) echo "SANDBOX_ERROR:项目路径必须为绝对路径" >&2; exit 2 ;; esac
|
|
82
|
+
[ -d "$PROJECT_PATH" ] && [ ! -L "$PROJECT_PATH" ] || { echo "SANDBOX_ERROR:项目目录不可访问或不安全" >&2; exit 2; }
|
|
83
|
+
detected=()
|
|
84
|
+
find "$PROJECT_PATH" -maxdepth 4 -type f \( -name pom.xml -o -name build.gradle -o -name build.gradle.kts \) -print -quit | grep -q . && detected+=(Java)
|
|
85
|
+
find "$PROJECT_PATH" -maxdepth 4 -type f -name package.json -print -quit | grep -q . && detected+=(Node.js)
|
|
86
|
+
find "$PROJECT_PATH" -maxdepth 4 -type f \( -name requirements.txt -o -name pyproject.toml \) -print -quit | grep -q . && detected+=(Python)
|
|
87
|
+
find "$PROJECT_PATH" -maxdepth 4 -type f -name '*.csproj' -print -quit | grep -q . && detected+=(C#)
|
|
88
|
+
find "$PROJECT_PATH" -maxdepth 4 -type f -name composer.json -print -quit | grep -q . && detected+=(PHP)
|
|
89
|
+
language_detected=false
|
|
90
|
+
for detected_language in "${detected[@]}"; do
|
|
91
|
+
[ "$detected_language" = "$LANGUAGE" ] && language_detected=true
|
|
92
|
+
done
|
|
93
|
+
[ "$language_detected" = true ] || { echo "SANDBOX_ERROR:未发现与已确认语言一致的项目构建标识" >&2; exit 2; }
|
|
94
|
+
|
|
95
|
+
if [ "$MODE" = "ensure" ] || [ "$MODE" = "reverify" ]; then
|
|
96
|
+
if [ "$MODE" = "reverify" ] || [ -e "$CONFIG_PATH" ] || [ -L "$CONFIG_PATH" ]; then
|
|
97
|
+
ENSURE_MODE="verify"
|
|
98
|
+
ENSURE_ACTION="VERIFIED"
|
|
99
|
+
PENDING_VARIANT="VERIFY"
|
|
100
|
+
PENDING_MARKER="FLOW:SANDBOX_CONFIG_PENDING_VERIFY"
|
|
101
|
+
else
|
|
102
|
+
ENSURE_MODE="create"
|
|
103
|
+
ENSURE_ACTION="CREATED"
|
|
104
|
+
PENDING_VARIANT="CREATE"
|
|
105
|
+
PENDING_MARKER="FLOW:SANDBOX_CONFIG_PENDING_CREATE"
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
attempt=1
|
|
109
|
+
while true; do
|
|
110
|
+
ensure_output=$(bash "$0" "$ENSURE_MODE" "$PROJECT_PATH" "$LANGUAGE" 2>&1)
|
|
111
|
+
ensure_rc=$?
|
|
112
|
+
if [ "$ensure_rc" -eq "$ALIPAY_CLI_LOCAL_STATE_PERMISSION_EXIT_CODE" ] &&
|
|
113
|
+
[ "$(printf '%s\n' "$ensure_output" | grep -Fxc 'ALIPAY_AIPAY_INTERNAL:SANDBOX_LOCAL_FS_PERMISSION_MODE=CREATE')" -eq 1 ] &&
|
|
114
|
+
[ "$(printf '%s\n' "$ensure_output" | grep -Fxc 'ALIPAY_AIPAY_INTERNAL:CLI_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION')" -eq 1 ]; then
|
|
115
|
+
render_pending || exit 1
|
|
116
|
+
emit_control "SANDBOX_LOCAL_FS_PERMISSION_MODE=CREATE"
|
|
117
|
+
emit_control "CLI_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION"
|
|
118
|
+
exit "$ALIPAY_CLI_LOCAL_STATE_PERMISSION_EXIT_CODE"
|
|
119
|
+
fi
|
|
120
|
+
if [ "$ensure_rc" -eq 0 ] &&
|
|
121
|
+
[ "$(printf '%s\n' "$ensure_output" | grep -Fxc "ALIPAY_AIPAY_INTERNAL:SANDBOX_CONFIG_PATH=$CONFIG_PATH")" -eq 1 ] &&
|
|
122
|
+
[ "$(printf '%s\n' "$ensure_output" | grep -Fxc 'ALIPAY_AIPAY_INTERNAL:FLOW:SANDBOX_CONFIG_READY')" -eq 1 ] &&
|
|
123
|
+
! printf '%s\n' "$ensure_output" | grep -q '^SANDBOX_ERROR:'; then
|
|
124
|
+
emit_control_field "SANDBOX_ENSURE_ACTION" "$ENSURE_ACTION" || exit 1
|
|
125
|
+
emit_control_field "SANDBOX_CONFIG_PATH" "$CONFIG_PATH" || exit 1
|
|
126
|
+
emit_control "FLOW:SANDBOX_CONFIG_READY"
|
|
127
|
+
emit_stage_metric "integration.create_sandbox"
|
|
128
|
+
exit 0
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
if [ "$attempt" -lt 3 ] && printf '%s\n' "$ensure_output" | grep -qE \
|
|
132
|
+
'SANDBOX_ERROR:(候选 data 缺少|配置缺少)当前语言或测试账号必含字段'; then
|
|
133
|
+
attempt=$((attempt + 1))
|
|
134
|
+
sleep 3
|
|
135
|
+
continue
|
|
136
|
+
fi
|
|
137
|
+
break
|
|
138
|
+
done
|
|
139
|
+
|
|
140
|
+
render_pending || exit 1
|
|
141
|
+
exit 0
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
extract_json_payload() {
|
|
145
|
+
local raw="$1" line_count span start end candidate normalized selected="" match_count=0
|
|
146
|
+
if normalized=$(printf '%s' "$raw" | jq -sce 'if length == 1 and (.[0] | type == "object") then .[0] else empty end' 2>/dev/null); then
|
|
147
|
+
printf '%s' "$normalized"
|
|
148
|
+
return 0
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
line_count=$(printf '%s\n' "$raw" | awk 'END { print NR }')
|
|
152
|
+
span="$line_count"
|
|
153
|
+
while [ "$span" -ge 1 ]; do
|
|
154
|
+
start=1
|
|
155
|
+
while [ $((start + span - 1)) -le "$line_count" ]; do
|
|
156
|
+
end=$((start + span - 1))
|
|
157
|
+
candidate=$(printf '%s\n' "$raw" | sed -n "${start},${end}p")
|
|
158
|
+
if normalized=$(printf '%s' "$candidate" | jq -sce 'if length == 1 and (.[0] | type == "object") then .[0] else empty end' 2>/dev/null) &&
|
|
159
|
+
printf '%s' "$normalized" | jq -e 'has("success") or ((.result.content[0].text? // .content[0].text?) | type == "string")' >/dev/null 2>&1; then
|
|
160
|
+
if [ "$normalized" != "$selected" ]; then
|
|
161
|
+
selected="$normalized"
|
|
162
|
+
match_count=$((match_count + 1))
|
|
163
|
+
fi
|
|
164
|
+
fi
|
|
165
|
+
start=$((start + 1))
|
|
166
|
+
done
|
|
167
|
+
span=$((span - 1))
|
|
168
|
+
done
|
|
169
|
+
[ "$match_count" -eq 1 ] || return 1
|
|
170
|
+
printf '%s' "$selected"
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
ensure_gitignore_protection() {
|
|
174
|
+
if [ -L "$GITIGNORE_PATH" ] || { [ -e "$GITIGNORE_PATH" ] && [ ! -f "$GITIGNORE_PATH" ]; }; then
|
|
175
|
+
echo "SANDBOX_ERROR:.gitignore 不是安全的普通文件" >&2
|
|
176
|
+
return 1
|
|
177
|
+
fi
|
|
178
|
+
if [ -f "$GITIGNORE_PATH" ] && grep -Fxq '/.alipay-sandbox.json' "$GITIGNORE_PATH"; then
|
|
179
|
+
return 0
|
|
180
|
+
fi
|
|
181
|
+
if [ -s "$GITIGNORE_PATH" ] && [ -n "$(tail -c 1 "$GITIGNORE_PATH" 2>/dev/null)" ]; then
|
|
182
|
+
printf '\n' >>"$GITIGNORE_PATH" || return 1
|
|
183
|
+
fi
|
|
184
|
+
printf '/.alipay-sandbox.json\n' >>"$GITIGNORE_PATH" || return 1
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
ensure_config_not_tracked() {
|
|
188
|
+
command -v git >/dev/null 2>&1 || return 0
|
|
189
|
+
git -C "$PROJECT_PATH" rev-parse --is-inside-work-tree >/dev/null 2>&1 || return 0
|
|
190
|
+
if git -C "$PROJECT_PATH" ls-files --error-unmatch -- '.alipay-sandbox.json' >/dev/null 2>&1; then
|
|
191
|
+
return 1
|
|
192
|
+
fi
|
|
193
|
+
return 0
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
ensure_config_permissions() {
|
|
197
|
+
local mode
|
|
198
|
+
chmod 600 "$CONFIG_PATH" 2>/dev/null || return 1
|
|
199
|
+
if mode=$(stat -f '%Lp' "$CONFIG_PATH" 2>/dev/null); then
|
|
200
|
+
:
|
|
201
|
+
elif mode=$(stat -c '%a' "$CONFIG_PATH" 2>/dev/null); then
|
|
202
|
+
:
|
|
203
|
+
else
|
|
204
|
+
return 1
|
|
205
|
+
fi
|
|
206
|
+
[ "$mode" = "600" ]
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
validate_data() {
|
|
210
|
+
local data="$1"
|
|
211
|
+
echo "$data" | jq -e --arg language "$LANGUAGE" '
|
|
212
|
+
(.appIds|type)=="array" and (.appIds|length)>0 and
|
|
213
|
+
(.appIds[0] as $app |
|
|
214
|
+
($app.appId|type)=="string" and ($app.appId|length)>0 and
|
|
215
|
+
($app.alipayPublicKey|type)=="string" and ($app.alipayPublicKey|length)>0 and
|
|
216
|
+
($app.appPublicKey|type)=="string" and ($app.appPublicKey|length)>0 and
|
|
217
|
+
(if $language=="Java" then ($app.appPrivateKey|type)=="string" and ($app.appPrivateKey|length)>0
|
|
218
|
+
else ($app.appPrivatePkcsKey|type)=="string" and ($app.appPrivatePkcsKey|length)>0 end) and
|
|
219
|
+
(.sandboxAccounts.partner.userId|type)=="string" and (.sandboxAccounts.partner.userId|length)>0 and
|
|
220
|
+
(.sandboxAccounts.user.userId|type)=="string" and (.sandboxAccounts.user.userId|length)>0 and
|
|
221
|
+
(.sandboxAccounts.user.email|type)=="string" and (.sandboxAccounts.user.email|length)>0 and
|
|
222
|
+
(.sandboxAccounts.user.logonPassword|type)=="string" and (.sandboxAccounts.user.logonPassword|length)>0 and
|
|
223
|
+
(.sandboxAccounts.user.payPassword|type)=="string" and (.sandboxAccounts.user.payPassword|length)>0
|
|
224
|
+
)
|
|
225
|
+
' >/dev/null 2>&1
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
render_summary() {
|
|
229
|
+
local data="$1" rows input
|
|
230
|
+
rows=$(echo "$data" | jq -r '
|
|
231
|
+
def safe: tostring|gsub("[|\\r\\n]";" ");
|
|
232
|
+
.appIds[0] as $app |
|
|
233
|
+
["| 沙箱支付宝应用ID(appID) | "+($app.appId|safe)+" |",
|
|
234
|
+
"| 沙箱买家测试账号 | "+(.sandboxAccounts.user.email|safe)+" |",
|
|
235
|
+
"| 沙箱买家登录密码 | "+(.sandboxAccounts.user.logonPassword|safe)+" |",
|
|
236
|
+
"| 沙箱买家支付密码 | "+(.sandboxAccounts.user.payPassword|safe)+" |"] | join("\n")
|
|
237
|
+
') || return 1
|
|
238
|
+
input=$(jq -cn --arg productName "$PRODUCT_NAME" --arg configPath "$CONFIG_PATH" --arg environmentRows "$rows" '{productName:$productName,configPath:$configPath,environmentRows:$environmentRows}') || return 1
|
|
239
|
+
printf '%s' "$input" | node "$RENDERER" sandbox.environment.summary --variant DEFAULT || return 1
|
|
240
|
+
printf '%s' '{}' | node "$RENDERER" sandbox.environment.reminder --variant DEFAULT || return 1
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
render_create_failure() {
|
|
244
|
+
local error_code trace_id
|
|
245
|
+
error_code=$(printf '%s' "$business" | jq -r '
|
|
246
|
+
if (.errorCode? | type) == "string" and (.errorCode | test("^[A-Za-z0-9_.:-]{1,80}$"))
|
|
247
|
+
then .errorCode else "UNKNOWN" end
|
|
248
|
+
' 2>/dev/null) || error_code="UNKNOWN"
|
|
249
|
+
trace_id=$(printf '%s' "$business" | jq -r '
|
|
250
|
+
if (.traceId? | type) == "string" and (.traceId | test("^[A-Za-z0-9_.:-]{1,128}$"))
|
|
251
|
+
then .traceId else "未返回" end
|
|
252
|
+
' 2>/dev/null) || trace_id="未返回"
|
|
253
|
+
printf 'SANDBOX_ERROR:%s traceId=%s\n' "$error_code" "$trace_id" >&2
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if [ "$MODE" = "create" ]; then
|
|
257
|
+
command -v alipay-cli >/dev/null 2>&1 || { echo "SANDBOX_ERROR:缺少 alipay-cli" >&2; exit 1; }
|
|
258
|
+
{ [ ! -e "$CONFIG_PATH" ] && [ ! -L "$CONFIG_PATH" ]; } || { echo "SANDBOX_ERROR:配置文件已存在或为不安全符号链接,禁止重复创建或覆盖" >&2; exit 1; }
|
|
259
|
+
ensure_config_not_tracked || { echo "SANDBOX_ERROR:沙箱配置路径已被 Git 跟踪,必须先从版本控制中移除" >&2; exit 1; }
|
|
260
|
+
ensure_gitignore_protection || { echo "SANDBOX_ERROR:无法为沙箱配置建立 Git 忽略保护" >&2; exit 1; }
|
|
261
|
+
PLATFORM=$(bash "$DETECTOR") || PLATFORM="unknown"
|
|
262
|
+
init_platform_id
|
|
263
|
+
init_alipay_cli_biz_info || { echo "SANDBOX_ERROR:无法初始化 alipay-cli 业务上报信息" >&2; exit 1; }
|
|
264
|
+
if ! require_alipay_cli_local_state_access; then
|
|
265
|
+
emit_control "SANDBOX_LOCAL_FS_PERMISSION_MODE=CREATE"
|
|
266
|
+
emit_control "CLI_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION"
|
|
267
|
+
exit "$ALIPAY_CLI_LOCAL_STATE_PERMISSION_EXIT_CODE"
|
|
268
|
+
fi
|
|
269
|
+
attempt=1
|
|
270
|
+
while true; do
|
|
271
|
+
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)
|
|
272
|
+
rc=$?
|
|
273
|
+
if alipay_cli_has_local_state_permission_error "$raw"; then
|
|
274
|
+
echo "SANDBOX_ERROR:快速沙箱创建结果不明,禁止自动重复创建" >&2
|
|
275
|
+
exit 1
|
|
276
|
+
fi
|
|
277
|
+
[ "$rc" -eq 0 ] && break
|
|
278
|
+
if printf '%s' "$raw" | grep -qiE '版本过旧|version.*old'; then break; fi
|
|
279
|
+
if [ "$attempt" -lt 3 ] && printf '%s' "$raw" | grep -qiE 'MCP_SERVICE_ERROR|SERVICE_UNSTABLE|timeout|timed out|connection|network|ECONN|socket|temporar'; then
|
|
280
|
+
attempt=$((attempt + 1))
|
|
281
|
+
sleep 3
|
|
282
|
+
continue
|
|
283
|
+
fi
|
|
284
|
+
break
|
|
285
|
+
done
|
|
286
|
+
[ "$rc" -eq 0 ] || { echo "SANDBOX_ERROR:快速沙箱 CLI 调用失败" >&2; exit 1; }
|
|
287
|
+
outer=$(extract_json_payload "$raw") || { echo "SANDBOX_ERROR:CLI 输出中未找到唯一合法 JSON 对象" >&2; exit 1; }
|
|
288
|
+
text=$(echo "$outer" | jq -r '.result.content[0].text // .content[0].text // empty')
|
|
289
|
+
if [ -n "$text" ]; then
|
|
290
|
+
business=$(printf '%s' "$text" | jq -c . 2>/dev/null) || { echo "SANDBOX_ERROR:content[0].text 不是合法 JSON" >&2; exit 1; }
|
|
291
|
+
else
|
|
292
|
+
business="$outer"
|
|
293
|
+
fi
|
|
294
|
+
if [ "$(echo "$business" | jq -r '.success // false')" != "true" ] && echo "$business" | jq -r '.msg // .resultMsg // ""' | grep -q '证书密钥'; then
|
|
295
|
+
sleep 2
|
|
296
|
+
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)
|
|
297
|
+
rc=$?
|
|
298
|
+
if alipay_cli_has_local_state_permission_error "$raw"; then
|
|
299
|
+
echo "SANDBOX_ERROR:快速沙箱创建结果不明,禁止自动重复创建" >&2
|
|
300
|
+
exit 1
|
|
301
|
+
fi
|
|
302
|
+
[ "$rc" -eq 0 ] || { echo "SANDBOX_ERROR:证书密钥临时错误重试后 CLI 调用失败" >&2; exit 1; }
|
|
303
|
+
outer=$(extract_json_payload "$raw") || { echo "SANDBOX_ERROR:重试输出中未找到唯一合法 JSON 对象" >&2; exit 1; }
|
|
304
|
+
text=$(echo "$outer" | jq -r '.result.content[0].text // .content[0].text // empty')
|
|
305
|
+
if [ -n "$text" ]; then business=$(printf '%s' "$text" | jq -c . 2>/dev/null) || { echo "SANDBOX_ERROR:重试 content[0].text 非法" >&2; exit 1; }; else business="$outer"; fi
|
|
306
|
+
fi
|
|
307
|
+
[ "$(echo "$business" | jq -r '.success // false')" = "true" ] || {
|
|
308
|
+
render_create_failure
|
|
309
|
+
exit 1
|
|
310
|
+
}
|
|
311
|
+
data=$(echo "$business" | jq -c '.data // null') || exit 1
|
|
312
|
+
validate_data "$data" || { echo "SANDBOX_ERROR:候选 data 缺少当前语言或测试账号必含字段" >&2; exit 1; }
|
|
313
|
+
temp=$(mktemp "${PROJECT_PATH}/.alipay-sandbox.XXXXXX") || exit 1
|
|
314
|
+
chmod 600 "$temp" 2>/dev/null || true
|
|
315
|
+
printf '%s\n' "$data" >"$temp" || { rm -f "$temp"; exit 1; }
|
|
316
|
+
mv "$temp" "$CONFIG_PATH" || { rm -f "$temp"; exit 1; }
|
|
317
|
+
ensure_config_permissions || { echo "SANDBOX_ERROR:无法确认配置权限为 0600" >&2; exit 1; }
|
|
318
|
+
elif [ "$MODE" = "verify" ]; then
|
|
319
|
+
[ -f "$CONFIG_PATH" ] && [ ! -L "$CONFIG_PATH" ] || { echo "SANDBOX_ERROR:配置文件不存在或不安全" >&2; exit 1; }
|
|
320
|
+
ensure_config_not_tracked || { echo "SANDBOX_ERROR:沙箱配置已被 Git 跟踪,必须先从版本控制中移除" >&2; exit 1; }
|
|
321
|
+
ensure_gitignore_protection || { echo "SANDBOX_ERROR:无法为沙箱配置建立 Git 忽略保护" >&2; exit 1; }
|
|
322
|
+
data=$(jq -c . "$CONFIG_PATH" 2>/dev/null) || { echo "SANDBOX_ERROR:配置不是合法 JSON" >&2; exit 1; }
|
|
323
|
+
validate_data "$data" || { echo "SANDBOX_ERROR:配置缺少当前语言或测试账号必含字段" >&2; exit 1; }
|
|
324
|
+
ensure_config_permissions || { echo "SANDBOX_ERROR:无法确认配置权限为 0600" >&2; exit 1; }
|
|
325
|
+
elif [ "$MODE" = "summary" ]; then
|
|
326
|
+
[ -f "$CONFIG_PATH" ] && [ ! -L "$CONFIG_PATH" ] || { echo "SANDBOX_ERROR:配置文件不存在或不安全" >&2; exit 1; }
|
|
327
|
+
ensure_config_not_tracked || { echo "SANDBOX_ERROR:沙箱配置已被 Git 跟踪,必须先从版本控制中移除" >&2; exit 1; }
|
|
328
|
+
ensure_gitignore_protection || { echo "SANDBOX_ERROR:无法为沙箱配置建立 Git 忽略保护" >&2; exit 1; }
|
|
329
|
+
data=$(jq -c . "$CONFIG_PATH" 2>/dev/null) || { echo "SANDBOX_ERROR:配置不是合法 JSON" >&2; exit 1; }
|
|
330
|
+
validate_data "$data" || { echo "SANDBOX_ERROR:配置缺少当前语言或测试账号必含字段" >&2; exit 1; }
|
|
331
|
+
ensure_config_permissions || { echo "SANDBOX_ERROR:无法确认配置权限为 0600" >&2; exit 1; }
|
|
332
|
+
else
|
|
333
|
+
echo "SANDBOX_ERROR:用法 sandbox_config.sh <ensure|reverify|create|verify> <projectPath> <language> 或 sandbox_config.sh summary <productType> <projectPath> <language>" >&2
|
|
334
|
+
exit 2
|
|
335
|
+
fi
|
|
336
|
+
|
|
337
|
+
if [ "$MODE" = "summary" ]; then
|
|
338
|
+
render_summary "$data" || exit 1
|
|
339
|
+
emit_control "CUSTOMER_MESSAGE_DELIVERY_REQUIRED=sandbox.environment.summary" || exit 1
|
|
340
|
+
emit_control_field "SANDBOX_CONFIG_PATH" "$CONFIG_PATH" || exit 1
|
|
341
|
+
emit_control "FLOW:SANDBOX_CONFIGURED"
|
|
342
|
+
exit 0
|
|
343
|
+
fi
|
|
344
|
+
|
|
345
|
+
emit_control_field "SANDBOX_CONFIG_PATH" "$CONFIG_PATH" || exit 1
|
|
346
|
+
emit_control "FLOW:SANDBOX_CONFIG_READY"
|
|
347
|
+
emit_stage_metric "integration.create_sandbox"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# 支付集成问题排查
|
|
2
|
+
|
|
3
|
+
仅在用户报告集成报错、错误码、问题、排查、调试或异常时读取。先确认当前支付产品;错误码查询还必须确认报错接口,缺少时暂停排查并请用户补充。
|
|
4
|
+
|
|
5
|
+
## 分流
|
|
6
|
+
|
|
7
|
+
1. `invalid-signature` 或验签失败:优先进入验签专项。
|
|
8
|
+
2. 有明确错误码:先查[公共错误码说明](https://ideservice.alipay.com/cms/site/02km9f),无匹配时再按已确认产品和接口查业务接口文档。
|
|
9
|
+
3. 无明确错误码:查当前产品常见问题文档。
|
|
10
|
+
|
|
11
|
+
| 产品 | 常见问题文档 |
|
|
12
|
+
|---|---|
|
|
13
|
+
| AI 按量付费 | [AI 按量付费常见问题](https://ideservice.alipay.com/cms/site/0j7uos) |
|
|
14
|
+
| AI 网页应用收款 | [AI 网页应用收款常见问题](https://ideservice.alipay.com/cms/site/0j3kh1) |
|
|
15
|
+
| AI 移动应用收款 | [AI 移动应用收款常见问题](https://ideservice.alipay.com/cms/site/0j3pih) |
|
|
16
|
+
|
|
17
|
+
没有确定依据时明确说明无法确认,禁止编造;引导用户查阅[支付宝开放平台](https://open.alipay.com?form=payskill)或咨询[支付宝技术支持](https://opensupport.alipay.com/support/intelligent-services?form=payskill)。
|
|
18
|
+
|
|
19
|
+
## 验签失败专项
|
|
20
|
+
|
|
21
|
+
严禁在没有实际请求证据时把 `invalid-signature`、`ERR_OSSL_UNSUPPORTED` 或验签失败归因于私钥格式,也不得添加 PEM 头尾或擅自转换密钥。按以下顺序核对:
|
|
22
|
+
|
|
23
|
+
1. 实际发送、参与签名和服务端验签的参数集是否完全一致。
|
|
24
|
+
2. 私钥字段是否正确:Java 使用 `appPrivateKey`,其他语言使用 `appPrivatePkcsKey`。
|
|
25
|
+
3. `signType` 是否为 `RSA2`。
|
|
26
|
+
4. 网关地址是否与当前环境一致。
|
|
27
|
+
|
|
28
|
+
线上环境确认公私钥不匹配时,建议用户登录支付宝开放平台重新上传应用公钥,并在应用配置中重新配置应用公私钥对。更完整原则见 `alipay-sdk-reminder.md` 的验签失败排查章节。
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Alipay CLI 环境准备
|
|
2
|
+
|
|
3
|
+
> 本文档定义 alipay-cli 的检测、安装、验证规范,供集成流程和签约流程统一引用。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. CLI 检测
|
|
8
|
+
|
|
9
|
+
### 1.0 对话首次成功刷新
|
|
10
|
+
|
|
11
|
+
本次 Agent 对话首次使用 `alipay-aipay` Skill 时,版本确定后按根 `SKILL.md` 执行一次:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" env refresh-alipay-cli
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
该动作把目标刷新到 `~/.local/bin`,不携带 `PLATFORM`、`PRODUCT` 或 `ALIPAYCLI_BIZ_INFO`。成功事实、内部 marker、重试预算和同对话复用均以根启动协议为准;失败不证明 CLI 可用,仍由本章检测和业务脚本按实际结果处理。
|
|
18
|
+
|
|
19
|
+
### 1.1 检测命令
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# 推荐:一步检测
|
|
23
|
+
which alipay-cli 2>/dev/null && alipay-cli version
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 1.2 检测时机
|
|
27
|
+
|
|
28
|
+
**必须在以下操作前执行 CLI 检测:**
|
|
29
|
+
- 执行 `whoami` 检查登录状态前
|
|
30
|
+
- 执行 `login` 登录授权前
|
|
31
|
+
- 执行任何 MCP 调用前
|
|
32
|
+
- 执行沙箱创建操作前
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 2. 沙箱化 Agent 网络权限规则
|
|
37
|
+
|
|
38
|
+
在存在网络沙箱或命令审批机制的 Agent 环境中,默认命令可能运行在无外网的受限沙箱内。`alipay-cli` 访问支付宝服务必须联网,若先在受限沙箱内执行,容易出现“网络连接失败”后再重试的差体验。
|
|
39
|
+
|
|
40
|
+
**应按联网命令处理的命令:**
|
|
41
|
+
- `alipay-cli login`、`alipay-cli whoami`、`alipay-cli logout`
|
|
42
|
+
- `alipay-cli mcp call ...`
|
|
43
|
+
- `alipay-cli file upload ...`
|
|
44
|
+
- `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" env refresh-alipay-cli`
|
|
45
|
+
- `export ALIPAY_CLI_BIN="$HOME/.local/bin" && curl -fsSL https://opengw.alipay.com/alipaycli/install | ALIPAY_CLI_SKIP_VERIFY=true bash`
|
|
46
|
+
- 按量付费沙箱测试中会访问用户服务或沙箱收银接口的 `local_402_sandbox_pay.py`
|
|
47
|
+
|
|
48
|
+
**执行要求:**
|
|
49
|
+
- 对已知需要联网的命令,如果当前 Agent 环境网络受限且支持显式授权,应首次执行即申请可联网权限,不要先在受限沙箱内试跑。
|
|
50
|
+
- 若命令已经因网络失败,重试时必须复用同一条命令并申请可联网权限;不要把该失败解释为用户网络故障。
|
|
51
|
+
- `auth.sh init|confirm|mismatch` 返回 `AUTH_FLOW:RETRY_WITH_NETWORK`:当前环境未取得可确认 CLI 结果;取联网权限后重试同一完整命令,不得解释为业务或 login/logout 失败,也不得改为用户手工操作。
|
|
52
|
+
- `auth.sh init|wait|confirm|mismatch` 返回 `AUTH_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION`:仅缺 CLI 状态目录权限。允许同一 runtime 命令访问 `$HOME/.alipay-cli/credentials`、`${XDG_DATA_HOME:-$HOME/.local/share}/alipay-cli/logs` 后原样重试一次;仅供 CLI 使用,Agent 禁止读取、列举、打印或复制已有内容,不改变其他脚本边界。
|
|
53
|
+
- 签约、服务、应用、截图上传及匿名沙箱创建等受控 runtime 动作同样属于“联网 + CLI 私有状态读写”命令。脚本在参数和上下文校验后、首次 `alipay-cli` 调用前,对上述两个目录执行私有随机文件的创建、固定内容写入、同目录 rename 和删除探测;同一 Shell 进程后续分页、轮询或写后核验不重复探测,不读取、列举或改动任何已有凭据和日志。
|
|
54
|
+
- 非 auth 动作在 CLI 调用前探测失败时只输出 `CLI_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION`,本次 CLI 调用次数为 0;允许当前同一 runtime 命令访问两个目录后原样重试一次。discovery 将其收口为唯一 `DISCOVERY_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION`。拒绝、不支持或重试仍命中同一 marker 时停止申请,按当前 flow 的既有分支失败或待配置边界继续,不新增业务确认或普通对客文案。
|
|
55
|
+
- CLI 已执行后才出现本地状态权限证据时,只读动作仍可按上述 marker 原样重试一次;写动作一律视为 `MAYBE_SENT`,只走现有查询核验或 `UNKNOWN`,不得输出本地权限重试 marker、不得重放原写请求。stdout 成功 JSON 与 stderr 本地权限强证据冲突时仍按本规则阻断。
|
|
56
|
+
- `app.sh reuse|verify-key|verify-key-and-audit|audit` 已取得 RSA2 支付宝公钥但 `${XDG_CONFIG_HOME:-$HOME/.config}` 探测失败时,返回 `APP_FLOW:RETRY_WITH_LOCAL_CONFIG_PERMISSION` 和 `ALIPAY_PUBLIC_KEY_EXPORT_STATUS=RETRY_WITH_LOCAL_CONFIG_PERMISSION`。仅允许同一 runtime 命令访问该目录后原样重试一次,用于写 `<appId>-alipayPublicKey.keytext`;Agent 禁止检查已有文件。仍失败按目录文案收口。
|
|
57
|
+
- 本地纯解析、文件检查、`bash -n`、`jq` 校验等不联网命令仍可在默认沙箱内执行。
|
|
58
|
+
|
|
59
|
+
**减少重复授权:**
|
|
60
|
+
- 优先使用 runtime 的 `auth|app|service` 动作,避免展开 `alipay-cli mcp call`。持久授权范围使用当前 Skill 绝对路径的稳定命令前缀,不得换副本。
|
|
61
|
+
- 不用 `DEV_TOOL_NAME=<tool>`、`PLATFORM=<tool>` 等环境变量前缀;公共初始化会设置。从业务入口的首条 bootstrap/start-run 起,Agent 依照入口协议随每条 runtime 命令追加 `--agent-platform "<AGENT_PLATFORM>" --session-id "<SESSION_ID>"`,作为当前命令的首选宿主名称;该值无效或为 `unknown` 时才回退自动识别。产品上下文用 `--sales-code`、`--mcc-code`、`--product-type` 等脚本参数。
|
|
62
|
+
- 只有脚本未覆盖的临时排查命令,才直接调用 `alipay-cli`;这类命令需要按具体前缀单独授权。
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 3. 前置依赖:用户级 jq
|
|
67
|
+
|
|
68
|
+
当前官方 alipay-cli 安装脚本直接下载对应平台二进制,不依赖 GPG/PGP。Skill 不检测、安装或记录 GPG,也不设置跳过 PGP 的环境变量;当前安装命令继续使用 `ALIPAY_CLI_SKIP_VERIFY=true`。
|
|
69
|
+
|
|
70
|
+
签约与 Unix/macOS/Linux 快速沙箱仍需 jq,手工验证命令为:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
jq --version
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
自动检测与恢复顺序固定如下:
|
|
77
|
+
|
|
78
|
+
1. `env check|integration-check` 先使用 PATH 中已有且能通过实际 filter 的 jq;受控 Shell 发现可执行的 `~/.local/bin/jq` 或 `~/.local/bin/alipay-cli` 时把该目录追加到 PATH,因此有效系统 jq 仍优先。若 PATH 前方 jq 能启动但无法执行实际 filter,而用户级 jq 验证通过,则当前受控 Shell 改用用户级 jq,避免恢复后仍被损坏的 PATH 项遮蔽。
|
|
79
|
+
2. 缺 jq 时,当前 flow 只执行一次 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" env prepare-jq --agent-platform "<AGENT_PLATFORM>" --session-id "<SESSION_ID>"`。该动作需要访问 GitHub,并需要对 `~/.local/bin` 创建、写入和 rename;宿主支持权限申请时,只为同一条受控命令取得这些权限,不新增业务确认。
|
|
80
|
+
3. macOS/Linux `x64|arm64` 只从固定官方 GitHub 资产下载 jq 1.7.1,在 60 秒总预算内校验固定 SHA-256,并于私有临时文件验证精确版本和实际 JSON filter 后,以 `0755` 原子写入 `~/.local/bin/jq`。成功后原样重跑环境检查。
|
|
81
|
+
4. `JQ_PREPARE=FAILED|UNSUPPORTED`,或返回 `READY` 后重跑环境检查仍缺 jq,表示 GitHub 下载、校验、执行或落盘链路未使 jq 可用。此时由 Agent 执行一个当前系统首选包管理器兜底:macOS 优先清华 Homebrew bottle 镜像,Debian/Ubuntu 使用 apt,CentOS/RHEL 使用 yum;执行后必须同时通过 `jq --version` 和环境检查的实际 filter 验证。macOS 首选镜像明确失败后,才按阿里云、中科大、直连顺序选择下一条,不并发、不回到 `prepare-jq` 循环。Linux 包管理器可能需要宿主系统权限,该权限只属于兜底安装,不改变 Skill 用户目录写入边界,也不构成业务确认。
|
|
82
|
+
|
|
83
|
+
首次 `npx ... install` 与 Skill 环境恢复复用同一个资产清单和安装器。首次安装缺 jq 时只启动 detached 后台任务,不等待下载结果;失败会清理探测/临时文件,不阻塞 Skill、不写系统目录、不请求 sudo。其他架构不自动下载,`--with-jq` 仅兼容旧命令。
|
|
84
|
+
|
|
85
|
+
以下是 GitHub 用户级安装失败后的 Agent/手工兜底命令;首次 `npx ... install` 和 detached 后台任务不得自动调用:
|
|
86
|
+
|
|
87
|
+
| 系统/来源 | 完整命令 |
|
|
88
|
+
|---|---|
|
|
89
|
+
| macOS 清华 bottle(首选) | `env HOMEBREW_BOTTLE_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles" HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1 brew install jq` |
|
|
90
|
+
| macOS 阿里云 bottle | `env HOMEBREW_BOTTLE_DOMAIN="https://mirrors.aliyun.com/homebrew-bottles" HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1 brew install jq` |
|
|
91
|
+
| macOS 中科大 bottle | `env HOMEBREW_BOTTLE_DOMAIN="https://mirrors.ustc.edu.cn/homebrew-bottles" HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1 brew install jq` |
|
|
92
|
+
| macOS 直连(最后) | `env HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1 brew install jq` |
|
|
93
|
+
| Linux (Debian/Ubuntu) | `sudo apt-get update && sudo apt-get install -y jq` |
|
|
94
|
+
| Linux (CentOS/RHEL) | `sudo yum install -y jq` |
|
|
95
|
+
|
|
96
|
+
Windows Integration 的 Node runner 路径只要求 Node,不以 Bash、jq 或 alipay-cli 阻断 Step 1;进入产品开通或既有 shell/CLI 脚本时仍按 flow 补齐依赖。其他系统和 Onboarding 的检查边界不变。
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 4. CLI 安装
|
|
101
|
+
|
|
102
|
+
### 4.1 自动安装
|
|
103
|
+
|
|
104
|
+
`npx -y @alipay/alipay-aipay@latest install` 的后台准备任务会把 alipay-cli 安装到用户目录 `~/.local/bin`,无需 sudo。正常 Skill 触发已通过 `env refresh-alipay-cli` 自动刷新到同一目标目录;手动兜底时使用:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
mkdir -p ~/.local/bin
|
|
108
|
+
export ALIPAY_CLI_BIN="$HOME/.local/bin" && curl -fsSL https://opengw.alipay.com/alipaycli/install | ALIPAY_CLI_SKIP_VERIFY=true bash
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 4.2 PATH 处理
|
|
112
|
+
|
|
113
|
+
如果安装成功后 `alipay-cli version` 仍提示 `command not found`,优先把 `~/.local/bin` 加入 PATH:
|
|
114
|
+
```bash
|
|
115
|
+
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
|
|
116
|
+
source ~/.zshrc
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
> ⚠️ 不要引导用户用 sudo 安装 alipay-cli 或修改系统目录权限。当前 Skill 的安装器通过 `ALIPAY_CLI_BIN="$HOME/.local/bin"` 规避 sudo;如用户环境无法写入 `~/.local/bin`,应让用户指定其他可写目录给 `ALIPAY_CLI_BIN`。
|
|
120
|
+
|
|
121
|
+
### 4.3 安装验证
|
|
122
|
+
|
|
123
|
+
安装后执行以下命令确认安装成功:
|
|
124
|
+
```bash
|
|
125
|
+
alipay-cli version
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
若提示 `command not found`,尝试以下方案:
|
|
129
|
+
```bash
|
|
130
|
+
# 方案一:刷新 PATH
|
|
131
|
+
source ~/.zshrc # macOS zsh
|
|
132
|
+
source ~/.bashrc # Linux/bash
|
|
133
|
+
|
|
134
|
+
# 方案二:使用绝对路径
|
|
135
|
+
~/.local/bin/alipay-cli version
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 5. 环境检测结果不透出规范
|
|
141
|
+
|
|
142
|
+
> ⚠️ **强制规范:检测结果仅供内部使用,禁止向用户输出!**
|
|
143
|
+
|
|
144
|
+
AI 工具由 `scripts/detect_dev_tool.sh` 检测;`init_alipay_cli_context` 设置 `DEV_TOOL_NAME`、`PLATFORM`,把当前 `run_id` 作为 `PLATFORM_ID`(不受遥测开关影响),并从当前生效 Skill 的 `VERSION` 和同源 `machineUserID` 动态生成 `ALIPAYCLI_BIZ_INFO={"skill":"alipay-aipay","skill_version":"v<当前 VERSION>","skill_user_id":"machine_<32位匿名机器哈希>"}`;极端环境无法取得合法 `machine_` 标识时只省略 `skill_user_id`,不写 `anonymous_uid` 且不阻断业务调用。所有携带 `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`。
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
❌ 禁止:向用户输出"环境检查完成,检测到您正在使用 Claude Code 环境"等检测结果
|
|
148
|
+
❌ 禁止:向用户透出任何关于 AI 编程工具检测的信息
|
|
149
|
+
✅ 正确:检测结果仅供内部使用,只用于脚本设置 `PLATFORM`;`PLATFORM_ID` 由脚本从当前 `run_id` 派生,`ALIPAYCLI_BIZ_INFO` 由当前 Skill 版本和匿名 `skill_user_id` 派生,Onboarding 的 `PRODUCT` 由已确认产品映射
|
|
150
|
+
✅ 正确:静默完成检测,直接进入下一步流程
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 5.1 页面打开与下载能力降级
|
|
154
|
+
|
|
155
|
+
- HTTPS 白名单通过后依次尝试 macOS `open`→`osascript open location`,或 Linux/Unix `xdg-open`→`gio open`→`sensible-browser`;Windows 保留 PowerShell。仅返回 `OPENED|OPEN_FAILED|GUI_UNAVAILABLE|LINK_ONLY`。
|
|
156
|
+
- 系统 opener 失败时,宿主内置浏览器可用则打开已校验、已交付的同一 URL 一次,不搜索、改写或自动操作;仍失败才提示手动打开/保留复制兜底,再有限轮询。不得安装工具或绕过审批;`OPEN_ERROR_KIND|OPEN_ERROR_CODE` 仅内部诊断,不算业务失败。
|
|
157
|
+
- 目标应用缺少用户已准备的应用公钥时,macOS/Windows 直接执行 onboarding 的 `download_key_tool.sh`,默认保存到用户 `Downloads` 目录并展示实际安装包路径;Linux、缺少 `curl`/`node`、目录不可用、下载源不可达或下载校验失败均回退 `https://opendocs.alipay.com/isv/02kipk`。脚本 stdout 直接输出标准对客文案,不输出 `DOWNLOADED`、`PATH=`、`DOWNLOAD_FAILED` 或 `DOWNLOAD_REASON` 机器标记。下载不安装、不启动、不生成密钥,Skill 不另询问是否下载。
|
|
158
|
+
- 页面打开和下载能力检测不改变 alipay-cli、MCP、业务确认或网络重试契约;宿主权限提示不是 Skill 业务确认。
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 6. 错误处理
|
|
163
|
+
|
|
164
|
+
| 错误场景 | 处理方式 |
|
|
165
|
+
|----------|----------|
|
|
166
|
+
| CLI 不存在 | 后台自动安装到 `~/.local/bin` |
|
|
167
|
+
| 安装目录不可写 | 提示设置 `ALIPAY_CLI_BIN` 到其他可写目录后手动安装 |
|
|
168
|
+
| 安装后找不到命令 | 提示将 `~/.local/bin` 加入 PATH 或使用绝对路径 |
|
|
169
|
+
| 版本过旧 | 提示更新 CLI |
|