@alipay/alipay-aipay 1.2.2 → 1.5.0
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 +5 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +13 -12
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/uninstall.d.ts.map +1 -1
- package/dist/commands/uninstall.js +17 -9
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +5 -5
- package/dist/commands/update.js.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/utils/config.d.ts +5 -3
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +34 -12
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/file.d.ts +8 -0
- package/dist/utils/file.d.ts.map +1 -1
- package/dist/utils/file.js +161 -9
- package/dist/utils/file.js.map +1 -1
- package/dist/utils/jq.d.ts.map +1 -1
- package/dist/utils/jq.js +8 -0
- package/dist/utils/jq.js.map +1 -1
- package/package.json +9 -5
- package/skill/SKILL.md +15 -169
- package/skill/VERSION +1 -1
- package/skill/references/integration/flow.md +388 -291
- package/skill/references/integration/modules/alipay-sdk-reminder.md +5 -3
- package/skill/references/integration/modules/checklist.md +54 -32
- package/skill/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/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 +8 -4
- package/skill/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 +6 -2
- package/skill/references/integration/modules/code-examples/csharp/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.cs +3 -1
- package/skill/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/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 +4 -1
- package/skill/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 +5 -2
- package/skill/references/integration/modules/code-examples/java/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemoController.java +3 -1
- package/skill/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/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 +16 -10
- package/skill/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 +10 -4
- package/skill/references/integration/modules/code-examples/nodejs/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.js +2 -1
- package/skill/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/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 +4 -1
- package/skill/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 +5 -2
- package/skill/references/integration/modules/code-examples/php/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.php +2 -1
- package/skill/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/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 +4 -1
- package/skill/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 +5 -1
- package/skill/references/integration/modules/code-examples/python/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.py +4 -2
- package/skill/references/integration/modules/interface-contract/aipay-interface-contract.md +52 -0
- package/skill/references/integration/modules/interface-contract/apppay-interface-contract.md +45 -0
- package/skill/references/integration/modules/interface-contract/common-trade-contract.md +42 -0
- package/skill/references/integration/modules/interface-contract/notify-url-contract.md +68 -0
- package/skill/references/integration/modules/interface-contract/webpay-interface-contract.md +44 -0
- package/skill/references/integration/modules/interface-guide.md +38 -71
- package/skill/references/integration/modules/product-decision.md +18 -35
- package/skill/references/integration/modules/sandbox/a2m-sandbox-test.md +62 -94
- package/skill/references/integration/modules/sandbox/alipay-sandbox-tool.md +43 -40
- package/skill/references/integration/modules/sandbox/sandbox-setup-guide.md +93 -114
- package/skill/references/integration/modules/scripts/local_402_sandbox_pay.py +358 -148
- package/skill/references/integration/modules/scripts/sandbox_config.sh +299 -0
- package/skill/references/integration/modules/troubleshooting-flow.md +28 -0
- package/skill/references/normal/alipay-cli-env.md +15 -5
- package/skill/references/normal/full-process-routing.md +82 -0
- package/skill/references/normal/json/customer-messages.json +942 -0
- package/skill/references/normal/json/policy-rules.json +179 -0
- package/skill/references/normal/rejection-guide.md +12 -7
- package/skill/references/normal/scripts/alipay_cli_env.mjs +33 -0
- package/skill/references/normal/scripts/alipay_cli_env.sh +55 -0
- package/skill/references/normal/scripts/common.sh +151 -0
- package/skill/references/normal/scripts/detect_dev_tool.sh +5 -1
- package/skill/references/normal/scripts/flow_loader.mjs +241 -0
- package/skill/references/normal/scripts/integration_context_runner.mjs +166 -0
- package/skill/references/normal/scripts/integration_message_runner.mjs +1023 -0
- package/skill/references/normal/scripts/interaction_reply.mjs +133 -0
- package/skill/references/normal/scripts/onboarding_discovery_runner.mjs +224 -0
- package/skill/references/normal/scripts/onboarding_message_runner.mjs +451 -0
- package/skill/references/normal/scripts/onboarding_recovery_runner.mjs +96 -0
- package/skill/references/normal/scripts/open_official_url.sh +82 -0
- package/skill/references/normal/scripts/platform_compat.mjs +39 -0
- package/skill/references/normal/scripts/project_route_inspector.sh +132 -0
- package/skill/references/normal/scripts/python_script_runner.mjs +56 -0
- package/skill/references/normal/scripts/render_customer_message.mjs +1288 -0
- package/skill/references/normal/scripts/self_update.mjs +160 -0
- package/skill/references/normal/scripts/telemetry.mjs +1327 -0
- package/skill/references/normal/self-update.md +18 -51
- package/skill/references/normal/telemetry.md +26 -0
- package/skill/references/onboarding/flow.md +421 -309
- package/skill/references/onboarding/modules/app-release.md +44 -438
- package/skill/references/onboarding/modules/authorization.md +25 -281
- package/skill/references/onboarding/modules/error-handling.md +31 -237
- package/skill/references/onboarding/modules/product-sign.md +25 -294
- package/skill/references/onboarding/modules/scripts/app.sh +445 -169
- package/skill/references/onboarding/modules/scripts/ar_sign_apply.sh +47 -28
- package/skill/references/onboarding/modules/scripts/auth.sh +484 -167
- package/skill/references/onboarding/modules/scripts/download_key_tool.sh +157 -0
- package/skill/references/onboarding/modules/scripts/error_handler.sh +101 -130
- package/skill/references/onboarding/modules/scripts/network_retry.sh +96 -0
- package/skill/references/onboarding/modules/scripts/query_sign_status.sh +20 -71
- package/skill/references/onboarding/modules/scripts/service.sh +154 -89
- package/skill/references/onboarding/modules/scripts/sign_status_parser.sh +58 -0
- package/skill/references/onboarding/modules/scripts/upload_screenshots.sh +34 -20
- package/skill/references/onboarding/modules/service-registration.md +20 -317
- package/skill/references/runtime-entry.md +63 -0
|
@@ -3,15 +3,19 @@
|
|
|
3
3
|
# 脚本名称: auth.sh
|
|
4
4
|
# 功能描述: 登录授权全流程 - 检查状态 + 执行登录 + 授权确认 + scope/MCC 校验 + 重新授权
|
|
5
5
|
# 调用位置: Step 3 登录授权
|
|
6
|
-
# 调用前置: 脚本通过 error_handler.sh 间接初始化 DEV_TOOL_NAME;必要时可用 DEV_TOOL_NAME 环境变量覆盖
|
|
6
|
+
# 调用前置: 脚本通过 error_handler.sh 间接初始化 DEV_TOOL_NAME/PLATFORM_ID;必要时可用 DEV_TOOL_NAME 环境变量覆盖
|
|
7
7
|
# 用法:
|
|
8
|
-
# auth init --scope <scope> --sales-code <code> --mcc-code <code>
|
|
8
|
+
# auth init --defer-open --scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>
|
|
9
|
+
# auth open [--scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>]
|
|
9
10
|
# auth confirm [--scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>]
|
|
10
|
-
# auth
|
|
11
|
+
# auth wait [--scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>]
|
|
12
|
+
# auth mismatch --defer-open [--scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>]
|
|
11
13
|
# 返回值:
|
|
12
|
-
# init: AUTH_FLOW:SKIP | AUTH_FLOW:
|
|
13
|
-
#
|
|
14
|
-
#
|
|
14
|
+
# init: AUTH_FLOW:SKIP | AUTH_FLOW:READY_TO_OPEN | AUTH_FLOW:SCOPE_MISMATCH | AUTH_FLOW:MCC_MISMATCH | AUTH_FLOW:RETRY_WITH_NETWORK | AUTH_FLOW:FAILED
|
|
15
|
+
# wait: AUTH_FLOW:AUTH_SUCCESS | AUTH_FLOW:PENDING | AUTH_FLOW:EXPIRED | AUTH_FLOW:SCOPE_MISMATCH | AUTH_FLOW:MCC_MISMATCH | AUTH_FLOW:CONTEXT_MISMATCH | AUTH_FLOW:RETRY_WITH_NETWORK | AUTH_FLOW:FAILED
|
|
16
|
+
# confirm: AUTH_FLOW:AUTH_SUCCESS | AUTH_FLOW:PENDING | AUTH_FLOW:EXPIRED | AUTH_FLOW:SCOPE_MISMATCH | AUTH_FLOW:MCC_MISMATCH | AUTH_FLOW:CONTEXT_MISMATCH | AUTH_FLOW:RETRY_WITH_NETWORK | AUTH_FLOW:FAILED
|
|
17
|
+
# mismatch: logout 可确认成功后调用 auth init 重新生成授权链接;上下文冲突时输出 AUTH_FLOW:CONTEXT_MISMATCH 且不 logout;无法确认 CLI 结果时输出 AUTH_FLOW:RETRY_WITH_NETWORK
|
|
18
|
+
# stdout: 仅登记对客正文;AUTH_FLOW/状态/查询复用标记写入 stderr
|
|
15
19
|
#=============================================================================
|
|
16
20
|
|
|
17
21
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -23,22 +27,113 @@ else
|
|
|
23
27
|
echo "❌ 缺少错误处理脚本: ${SCRIPT_DIR}/error_handler.sh"
|
|
24
28
|
exit 1
|
|
25
29
|
fi
|
|
30
|
+
source "${SCRIPT_DIR}/network_retry.sh"
|
|
31
|
+
source "${SCRIPT_DIR}/sign_status_parser.sh"
|
|
32
|
+
RENDERER="${SCRIPT_DIR}/../../../normal/scripts/render_customer_message.mjs"
|
|
26
33
|
|
|
27
34
|
require_command jq || exit 1
|
|
28
35
|
require_command alipay-cli || exit 1
|
|
36
|
+
require_command node || exit 1
|
|
29
37
|
require_command mktemp || exit 1
|
|
38
|
+
umask 077
|
|
30
39
|
|
|
31
40
|
# ─── 授权状态文件(用于独立执行 confirm/mismatch 时兜底恢复非敏感参数)────
|
|
32
41
|
AUTH_STATE_OWNER="$(id -u 2>/dev/null || printf '%s' "${USER:-unknown}" | tr -c 'A-Za-z0-9_-' '_')"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
42
|
+
AUTH_STATE_BASE="${TMPDIR:-/tmp}"
|
|
43
|
+
AUTH_STATE_BASE="${AUTH_STATE_BASE%/}"
|
|
44
|
+
if [ -n "${ALIPAY_AUTH_STATE_FILE:-}" ]; then
|
|
45
|
+
AUTH_STATE_FILE="$ALIPAY_AUTH_STATE_FILE"
|
|
46
|
+
AUTH_STATE_DIR="$(dirname "$AUTH_STATE_FILE")"
|
|
47
|
+
AUTH_STATE_DIR_MANAGED=false
|
|
48
|
+
else
|
|
49
|
+
AUTH_STATE_DIR="${AUTH_STATE_BASE}/alipay-aipay-auth-${AUTH_STATE_OWNER}"
|
|
50
|
+
AUTH_STATE_FILE="${AUTH_STATE_DIR}/state.json"
|
|
51
|
+
AUTH_STATE_DIR_MANAGED=true
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
secure_mode() {
|
|
55
|
+
local target="$1" expected="$2" mode
|
|
56
|
+
if mode=$(stat -f '%Lp' "$target" 2>/dev/null); then
|
|
57
|
+
:
|
|
58
|
+
elif mode=$(stat -c '%a' "$target" 2>/dev/null); then
|
|
59
|
+
:
|
|
60
|
+
else
|
|
61
|
+
return 1
|
|
62
|
+
fi
|
|
63
|
+
[ "$mode" = "$expected" ]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
prepare_auth_state_dir() {
|
|
67
|
+
if [ "$AUTH_STATE_DIR_MANAGED" = true ]; then
|
|
68
|
+
if [ -L "$AUTH_STATE_DIR" ] || { [ -e "$AUTH_STATE_DIR" ] && [ ! -d "$AUTH_STATE_DIR" ]; }; then
|
|
69
|
+
echo "❌ 授权临时目录不安全,已停止" >&2
|
|
70
|
+
return 1
|
|
71
|
+
fi
|
|
72
|
+
mkdir -p "$AUTH_STATE_DIR" || return 1
|
|
73
|
+
chmod 700 "$AUTH_STATE_DIR" 2>/dev/null || return 1
|
|
74
|
+
secure_mode "$AUTH_STATE_DIR" 700 || return 1
|
|
75
|
+
else
|
|
76
|
+
[ -d "$AUTH_STATE_DIR" ] && [ ! -L "$AUTH_STATE_DIR" ] || {
|
|
77
|
+
echo "❌ 指定的授权状态目录不可用或不安全,已停止" >&2
|
|
78
|
+
return 1
|
|
79
|
+
}
|
|
80
|
+
fi
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
validate_auth_state_file() {
|
|
84
|
+
[ -f "$AUTH_STATE_FILE" ] && [ ! -L "$AUTH_STATE_FILE" ] || return 1
|
|
85
|
+
chmod 600 "$AUTH_STATE_FILE" 2>/dev/null || return 1
|
|
86
|
+
secure_mode "$AUTH_STATE_FILE" 600
|
|
87
|
+
}
|
|
36
88
|
|
|
37
89
|
cleanup_auth_state() {
|
|
38
90
|
rm -f "$AUTH_STATE_FILE"
|
|
39
91
|
}
|
|
40
92
|
|
|
93
|
+
reset_auth_state_for_init() {
|
|
94
|
+
local field current saved
|
|
95
|
+
AUTH_INIT_CONTEXT_MISMATCH_TYPE=""
|
|
96
|
+
[ -e "$AUTH_STATE_FILE" ] || [ -L "$AUTH_STATE_FILE" ] || return 0
|
|
97
|
+
if ! prepare_auth_state_dir || ! validate_auth_state_file; then
|
|
98
|
+
echo "❌ 授权状态文件不可用或不安全,已停止"
|
|
99
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
100
|
+
return 1
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
# 新上下文通过机器校验后才读取旧状态;只记录差异类型,不复用旧 deviceCode。
|
|
104
|
+
if jq -e 'type == "object"' "$AUTH_STATE_FILE" >/dev/null 2>&1; then
|
|
105
|
+
for field in salesCode scope productName mccCode mccName; do
|
|
106
|
+
case "$field" in
|
|
107
|
+
salesCode) current="$SALES_CODE" ;;
|
|
108
|
+
scope) current="$SCOPE" ;;
|
|
109
|
+
productName) current="$PRODUCT_NAME" ;;
|
|
110
|
+
mccCode) current="$MCC_CODE" ;;
|
|
111
|
+
mccName) current="$MCC_NAME" ;;
|
|
112
|
+
esac
|
|
113
|
+
saved=$(jq -r --arg field "$field" '.[$field] // ""' "$AUTH_STATE_FILE")
|
|
114
|
+
if [ "$current" != "$saved" ]; then
|
|
115
|
+
case "$field" in
|
|
116
|
+
salesCode|scope|productName) AUTH_INIT_CONTEXT_MISMATCH_TYPE="SCOPE_MISMATCH" ;;
|
|
117
|
+
*) [ -n "$AUTH_INIT_CONTEXT_MISMATCH_TYPE" ] || AUTH_INIT_CONTEXT_MISMATCH_TYPE="MCC_MISMATCH" ;;
|
|
118
|
+
esac
|
|
119
|
+
fi
|
|
120
|
+
done
|
|
121
|
+
else
|
|
122
|
+
# 无法证明旧状态属于当前产品上下文时,已有登录也必须重新授权。
|
|
123
|
+
AUTH_INIT_CONTEXT_MISMATCH_TYPE="SCOPE_MISMATCH"
|
|
124
|
+
fi
|
|
125
|
+
cleanup_auth_state
|
|
126
|
+
}
|
|
127
|
+
|
|
41
128
|
save_auth_state() {
|
|
129
|
+
local temp_state
|
|
130
|
+
prepare_auth_state_dir || return 1
|
|
131
|
+
if [ -L "$AUTH_STATE_FILE" ] || { [ -e "$AUTH_STATE_FILE" ] && [ ! -f "$AUTH_STATE_FILE" ]; }; then
|
|
132
|
+
echo "❌ 授权状态路径不是安全的普通文件,已停止" >&2
|
|
133
|
+
return 1
|
|
134
|
+
fi
|
|
135
|
+
temp_state=$(mktemp "${AUTH_STATE_DIR}/.auth-state.XXXXXX") || return 1
|
|
136
|
+
chmod 600 "$temp_state" 2>/dev/null || { rm -f "$temp_state"; return 1; }
|
|
42
137
|
jq -n \
|
|
43
138
|
--arg salesCode "$SALES_CODE" \
|
|
44
139
|
--arg mccCode "$MCC_CODE" \
|
|
@@ -46,19 +141,26 @@ save_auth_state() {
|
|
|
46
141
|
--arg productName "${PRODUCT_NAME:-}" \
|
|
47
142
|
--arg mccName "${MCC_NAME:-}" \
|
|
48
143
|
--arg deviceCode "${DEVICE_CODE:-}" \
|
|
144
|
+
--arg authorizationUrl "${BROWSER_URL:-}" \
|
|
49
145
|
'{
|
|
50
146
|
salesCode: $salesCode,
|
|
51
147
|
mccCode: $mccCode,
|
|
52
148
|
scope: $scope,
|
|
53
149
|
productName: $productName,
|
|
54
150
|
mccName: $mccName,
|
|
55
|
-
deviceCode: $deviceCode
|
|
56
|
-
|
|
57
|
-
|
|
151
|
+
deviceCode: $deviceCode,
|
|
152
|
+
authorizationUrl: $authorizationUrl
|
|
153
|
+
}' > "$temp_state" || { rm -f "$temp_state"; return 1; }
|
|
154
|
+
mv "$temp_state" "$AUTH_STATE_FILE" || { rm -f "$temp_state"; return 1; }
|
|
155
|
+
validate_auth_state_file || {
|
|
156
|
+
cleanup_auth_state
|
|
157
|
+
echo "❌ 无法确认授权状态文件权限为 0600,已停止" >&2
|
|
158
|
+
return 1
|
|
159
|
+
}
|
|
58
160
|
}
|
|
59
161
|
|
|
60
162
|
load_auth_state() {
|
|
61
|
-
if
|
|
163
|
+
if ! validate_auth_state_file; then
|
|
62
164
|
echo "❌ 缺少授权上下文(请传入 --sales-code/--mcc-code,或先执行 auth.sh init)"
|
|
63
165
|
return 1
|
|
64
166
|
fi
|
|
@@ -75,6 +177,33 @@ load_auth_state() {
|
|
|
75
177
|
[ -n "${MCC_NAME:-}" ] || MCC_NAME=$(jq -r '.mccName // ""' "$AUTH_STATE_FILE")
|
|
76
178
|
}
|
|
77
179
|
|
|
180
|
+
verify_context_against_auth_state() {
|
|
181
|
+
local field current saved
|
|
182
|
+
[ -e "$AUTH_STATE_FILE" ] || [ -L "$AUTH_STATE_FILE" ] || return 0
|
|
183
|
+
if ! validate_auth_state_file; then
|
|
184
|
+
echo "❌ 授权状态文件不可用或不安全,已停止"
|
|
185
|
+
return 1
|
|
186
|
+
fi
|
|
187
|
+
if ! jq -e . "$AUTH_STATE_FILE" >/dev/null 2>&1; then
|
|
188
|
+
echo "❌ 授权状态文件不是合法 JSON: $AUTH_STATE_FILE"
|
|
189
|
+
return 1
|
|
190
|
+
fi
|
|
191
|
+
for field in salesCode mccCode scope productName mccName; do
|
|
192
|
+
case "$field" in
|
|
193
|
+
salesCode) current="$SALES_CODE" ;;
|
|
194
|
+
mccCode) current="$MCC_CODE" ;;
|
|
195
|
+
scope) current="$SCOPE" ;;
|
|
196
|
+
productName) current="$PRODUCT_NAME" ;;
|
|
197
|
+
mccName) current="$MCC_NAME" ;;
|
|
198
|
+
esac
|
|
199
|
+
saved=$(jq -r --arg field "$field" '.[$field] // ""' "$AUTH_STATE_FILE")
|
|
200
|
+
if [ -n "$current" ] && [ -n "$saved" ] && [ "$current" != "$saved" ]; then
|
|
201
|
+
emit_control "AUTH_FLOW:CONTEXT_MISMATCH"
|
|
202
|
+
return 1
|
|
203
|
+
fi
|
|
204
|
+
done
|
|
205
|
+
}
|
|
206
|
+
|
|
78
207
|
parse_auth_context_args() {
|
|
79
208
|
while [[ $# -gt 0 ]]; do
|
|
80
209
|
case $1 in
|
|
@@ -109,13 +238,17 @@ restore_auth_context_or_state() {
|
|
|
109
238
|
parse_auth_context_args "$@" || return 1
|
|
110
239
|
fi
|
|
111
240
|
|
|
112
|
-
|
|
241
|
+
verify_context_against_auth_state || return 1
|
|
242
|
+
if [ -e "$AUTH_STATE_FILE" ] || [ -L "$AUTH_STATE_FILE" ]; then
|
|
243
|
+
load_auth_state || return 1
|
|
244
|
+
elif [ -z "$SALES_CODE" ] || [ -z "$MCC_CODE" ] || [ -z "$PRODUCT_NAME" ] || [ -z "$MCC_NAME" ]; then
|
|
113
245
|
load_auth_state || return 1
|
|
114
246
|
fi
|
|
115
247
|
|
|
116
248
|
if [ -z "$SCOPE" ]; then
|
|
117
249
|
SCOPE=$(get_scope "$SALES_CODE")
|
|
118
250
|
fi
|
|
251
|
+
validate_auth_context || return 1
|
|
119
252
|
}
|
|
120
253
|
|
|
121
254
|
# ─── 共用:根据 salesCode 获取 scope ─────────────────────────────────────────
|
|
@@ -128,27 +261,97 @@ get_scope() {
|
|
|
128
261
|
esac
|
|
129
262
|
}
|
|
130
263
|
|
|
264
|
+
validate_auth_context() {
|
|
265
|
+
local context_json
|
|
266
|
+
context_json=$(jq -n \
|
|
267
|
+
--arg productName "$PRODUCT_NAME" \
|
|
268
|
+
--arg salesCode "$SALES_CODE" \
|
|
269
|
+
--arg scope "$SCOPE" \
|
|
270
|
+
--arg mccCode "$MCC_CODE" \
|
|
271
|
+
--arg mccName "$MCC_NAME" \
|
|
272
|
+
'{productName:$productName,salesCode:$salesCode,scope:$scope,mccCode:$mccCode,mccName:$mccName}') || return 1
|
|
273
|
+
if ! printf '%s' "$context_json" | node "$RENDERER" --validate-authorization-context >/dev/null; then
|
|
274
|
+
echo "❌ 授权上下文校验失败:产品、产品码、scope 或 MCC 不匹配当前固定规则"
|
|
275
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
276
|
+
return 1
|
|
277
|
+
fi
|
|
278
|
+
init_alipay_cli_product_from_sales_code "$SALES_CODE" || {
|
|
279
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
280
|
+
return 1
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
build_authorization_url() {
|
|
285
|
+
local input_json platform_value
|
|
286
|
+
platform_value="${DEV_TOOL_NAME:-}"
|
|
287
|
+
[ "$platform_value" = "unknown" ] && platform_value=""
|
|
288
|
+
input_json=$(jq -n \
|
|
289
|
+
--arg productName "$PRODUCT_NAME" \
|
|
290
|
+
--arg salesCode "$SALES_CODE" \
|
|
291
|
+
--arg scope "$SCOPE" \
|
|
292
|
+
--arg mccCode "$MCC_CODE" \
|
|
293
|
+
--arg mccName "$MCC_NAME" \
|
|
294
|
+
--arg deviceCode "$DEVICE_CODE" \
|
|
295
|
+
--arg platform "$platform_value" \
|
|
296
|
+
'{productName:$productName,salesCode:$salesCode,scope:$scope,mccCode:$mccCode,mccName:$mccName,deviceCode:$deviceCode,platform:$platform}') || return 1
|
|
297
|
+
printf '%s' "$input_json" | node "$RENDERER" --build-authorization-url
|
|
298
|
+
}
|
|
299
|
+
|
|
131
300
|
extract_json_payload() {
|
|
132
301
|
local raw="$1"
|
|
133
|
-
local
|
|
302
|
+
local analysis status
|
|
303
|
+
analysis=$(extract_unique_json "$raw") || return 1
|
|
304
|
+
status=$(printf '%s' "$analysis" | jq -r '.status // "none"' 2>/dev/null)
|
|
305
|
+
[ "$status" = "ok" ] || return 1
|
|
306
|
+
printf '%s' "$analysis" | jq -ce '.value | select(type == "object")' 2>/dev/null
|
|
307
|
+
}
|
|
134
308
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
309
|
+
auth_cli_environment_failure() {
|
|
310
|
+
local action="$1"
|
|
311
|
+
echo "❌ ${action} 未能在当前 Agent 执行环境取得可确认结果,已停止。"
|
|
312
|
+
echo "📋 这通常表示当前执行环境缺少联网权限、CLI wrapper 混入输出,或 stdout/stderr 无法唯一解析。"
|
|
313
|
+
echo "📋 这不代表支付宝业务失败,也不能据此判断用户本机 logout/login 失败。"
|
|
314
|
+
echo "📋 Agent 应申请可联网权限后重试同一条 auth.sh 命令;不要要求用户手动 logout/login 代替本轮事实。"
|
|
315
|
+
emit_control "AUTH_FLOW:RETRY_WITH_NETWORK"
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
wait_for_effective_whoami() {
|
|
319
|
+
local action="$1"
|
|
320
|
+
local max_attempts=3
|
|
321
|
+
local interval_seconds=2
|
|
322
|
+
local attempt=1
|
|
323
|
+
local logged_in is_expired
|
|
324
|
+
|
|
325
|
+
AUTH_WHOAMI_RESULT=""
|
|
326
|
+
if [ "${ALIPAY_AIPAY_TEST_MODE:-0}" = "1" ] && [[ "${AUTH_WHOAMI_RECHECK_INTERVAL_SECONDS:-}" =~ ^[0-9]+$ ]]; then
|
|
327
|
+
interval_seconds="$AUTH_WHOAMI_RECHECK_INTERVAL_SECONDS"
|
|
138
328
|
fi
|
|
139
329
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
330
|
+
while [ "$attempt" -le "$max_attempts" ]; do
|
|
331
|
+
AUTH_WHOAMI_RESULT=$(run_json_command "alipay-cli whoami --json" alipay-cli whoami --json) || {
|
|
332
|
+
auth_cli_environment_failure "$action"
|
|
333
|
+
return 1
|
|
334
|
+
}
|
|
335
|
+
if ! handle_error "$AUTH_WHOAMI_RESULT"; then
|
|
336
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
337
|
+
return 1
|
|
338
|
+
fi
|
|
339
|
+
|
|
340
|
+
logged_in=$(echo "$AUTH_WHOAMI_RESULT" | jq -r '.data.logged_in // false')
|
|
341
|
+
is_expired=$(echo "$AUTH_WHOAMI_RESULT" | jq -r '.data.is_expired // false')
|
|
342
|
+
if [ "$logged_in" = "true" ] && [ "$is_expired" != "true" ]; then
|
|
146
343
|
return 0
|
|
147
344
|
fi
|
|
148
|
-
|
|
345
|
+
|
|
346
|
+
emit_control "AUTH_WHOAMI_RECHECK=${attempt}/${max_attempts}"
|
|
347
|
+
if [ "$attempt" -lt "$max_attempts" ]; then
|
|
348
|
+
sleep "$interval_seconds"
|
|
349
|
+
fi
|
|
350
|
+
attempt=$((attempt + 1))
|
|
149
351
|
done
|
|
150
352
|
|
|
151
|
-
|
|
353
|
+
emit_control "AUTH_WHOAMI_NOT_EFFECTIVE"
|
|
354
|
+
return 2
|
|
152
355
|
}
|
|
153
356
|
|
|
154
357
|
run_json_command() {
|
|
@@ -157,7 +360,7 @@ run_json_command() {
|
|
|
157
360
|
local stderr_file stdout stderr_output combined_output exit_code json_payload
|
|
158
361
|
|
|
159
362
|
stderr_file="$(mktemp "${TMPDIR:-/tmp}/alipay_auth_stderr.XXXXXX")" || return 1
|
|
160
|
-
stdout=$(PLATFORM="${DEV_TOOL_NAME}" "$@" 2>"$stderr_file")
|
|
363
|
+
stdout=$(PLATFORM="${DEV_TOOL_NAME}" PLATFORM_ID="${PLATFORM_ID:-}" PRODUCT="${PRODUCT:-}" "$@" 2>"$stderr_file")
|
|
161
364
|
exit_code=$?
|
|
162
365
|
stderr_output=$(cat "$stderr_file")
|
|
163
366
|
|
|
@@ -180,16 +383,7 @@ run_json_command() {
|
|
|
180
383
|
return 0
|
|
181
384
|
fi
|
|
182
385
|
|
|
183
|
-
echo "❌ ${label}
|
|
184
|
-
echo "📋 退出码: ${exit_code}" >&2
|
|
185
|
-
if [ -n "$stderr_output" ]; then
|
|
186
|
-
echo "📋 错误输出:" >&2
|
|
187
|
-
printf '%s\n' "$stderr_output" >&2
|
|
188
|
-
fi
|
|
189
|
-
if [ -n "$stdout" ]; then
|
|
190
|
-
echo "📋 标准输出:" >&2
|
|
191
|
-
printf '%s\n' "$stdout" >&2
|
|
192
|
-
fi
|
|
386
|
+
echo "❌ ${label} 未返回可唯一解析的合法 JSON(退出码: ${exit_code});原始输出已隐藏,请申请联网权限后重试同一条 auth.sh 命令" >&2
|
|
193
387
|
rm -f "$stderr_file"
|
|
194
388
|
return 1
|
|
195
389
|
}
|
|
@@ -199,26 +393,27 @@ run_json_command() {
|
|
|
199
393
|
validate_current_authorization() {
|
|
200
394
|
local whoami_result="${1:-}"
|
|
201
395
|
local logged_in is_expired granted_scope required_scope
|
|
202
|
-
local scope_match mcc_verify_result mcc_verify_unwrapped mcc_match
|
|
396
|
+
local scope_match mcc_verify_result mcc_verify_unwrapped mcc_match mcc_raw retry_rc
|
|
203
397
|
local mcc_error_type mcc_error_code mcc_success
|
|
204
|
-
local
|
|
205
|
-
local
|
|
398
|
+
local mismatch_type sign_status_output
|
|
399
|
+
local granted_scope_item required_scope_item required_scope_found
|
|
400
|
+
local -a granted_scope_items required_scope_items
|
|
206
401
|
|
|
207
402
|
if [ -z "$SALES_CODE" ] || [ -z "$MCC_CODE" ]; then
|
|
208
403
|
echo "❌ 缺少授权校验参数"
|
|
209
|
-
|
|
404
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
210
405
|
return 1
|
|
211
406
|
fi
|
|
212
407
|
|
|
213
408
|
if [ -z "$whoami_result" ]; then
|
|
214
409
|
whoami_result=$(run_json_command "alipay-cli whoami --json" alipay-cli whoami --json) || {
|
|
215
|
-
|
|
410
|
+
auth_cli_environment_failure "登录状态复核"
|
|
216
411
|
return 1
|
|
217
412
|
}
|
|
218
413
|
fi
|
|
219
414
|
|
|
220
415
|
if ! handle_error "$whoami_result"; then
|
|
221
|
-
|
|
416
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
222
417
|
return 1
|
|
223
418
|
fi
|
|
224
419
|
|
|
@@ -226,40 +421,52 @@ validate_current_authorization() {
|
|
|
226
421
|
is_expired=$(echo "$whoami_result" | jq -r '.data.is_expired // false')
|
|
227
422
|
if [ "$logged_in" != "true" ] || [ "$is_expired" = "true" ]; then
|
|
228
423
|
echo "❌ 当前登录状态无效或已过期"
|
|
229
|
-
|
|
424
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
230
425
|
return 1
|
|
231
426
|
fi
|
|
232
427
|
|
|
233
428
|
granted_scope=$(echo "$whoami_result" | jq -r '.data.scope // empty')
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
"
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
echo "AUTH_FLOW:FAILED"
|
|
241
|
-
return 1
|
|
242
|
-
;;
|
|
243
|
-
esac
|
|
429
|
+
required_scope=$(get_scope "$SALES_CODE")
|
|
430
|
+
if [ -z "$required_scope" ] || [ "$SCOPE" != "$required_scope" ]; then
|
|
431
|
+
echo "❌ 当前产品的固定 scope 上下文无效"
|
|
432
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
433
|
+
return 1
|
|
434
|
+
fi
|
|
244
435
|
|
|
245
|
-
scope_match="
|
|
436
|
+
scope_match="true"
|
|
246
437
|
IFS=',' read -r -a granted_scope_items <<< "$granted_scope"
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
438
|
+
IFS=',' read -r -a required_scope_items <<< "$required_scope"
|
|
439
|
+
for required_scope_item in "${required_scope_items[@]}"; do
|
|
440
|
+
required_scope_found="false"
|
|
441
|
+
for granted_scope_item in "${granted_scope_items[@]}"; do
|
|
442
|
+
granted_scope_item="${granted_scope_item#"${granted_scope_item%%[![:space:]]*}"}"
|
|
443
|
+
granted_scope_item="${granted_scope_item%"${granted_scope_item##*[![:space:]]}"}"
|
|
444
|
+
if [ "$granted_scope_item" = "$required_scope_item" ]; then
|
|
445
|
+
required_scope_found="true"
|
|
446
|
+
break
|
|
447
|
+
fi
|
|
448
|
+
done
|
|
449
|
+
if [ "$required_scope_found" != "true" ]; then
|
|
450
|
+
scope_match="false"
|
|
252
451
|
break
|
|
253
452
|
fi
|
|
254
453
|
done
|
|
255
454
|
|
|
256
455
|
mcc_match="true"
|
|
257
456
|
if [ "$scope_match" = "true" ]; then
|
|
258
|
-
|
|
259
|
-
|
|
457
|
+
export PLATFORM="${DEV_TOOL_NAME}" PLATFORM_ID="${PLATFORM_ID:-}"
|
|
458
|
+
run_network_retry mcc_raw read authorization_mcc_check -- alipay-cli mcp call ar-query.queryArInfosBySalesProd \
|
|
260
459
|
-d "{\"request\":{\"salesProductCodes\":[\"${SALES_CODE}\"]},\"ctx\":{}}" \
|
|
261
|
-
--json
|
|
262
|
-
|
|
460
|
+
--json
|
|
461
|
+
retry_rc=$?
|
|
462
|
+
if [ "$retry_rc" -ne 0 ]; then
|
|
463
|
+
echo "❌ 授权 MCC 校验因网络或服务异常在自动重试两次后仍未恢复"
|
|
464
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
465
|
+
return 1
|
|
466
|
+
fi
|
|
467
|
+
mcc_verify_result=$(extract_json_payload "$mcc_raw") || {
|
|
468
|
+
echo "❌ alipay-cli mcp call ar-query.queryArInfosBySalesProd 未返回合法 JSON"
|
|
469
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
263
470
|
return 1
|
|
264
471
|
}
|
|
265
472
|
|
|
@@ -269,7 +476,7 @@ validate_current_authorization() {
|
|
|
269
476
|
mcc_match="false"
|
|
270
477
|
elif [ "$mcc_error_type" != "SUCCESS" ]; then
|
|
271
478
|
echo "❌ MCC 校验失败"
|
|
272
|
-
|
|
479
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
273
480
|
return 1
|
|
274
481
|
fi
|
|
275
482
|
|
|
@@ -282,37 +489,32 @@ validate_current_authorization() {
|
|
|
282
489
|
elif echo "$mcc_verify_unwrapped" | grep -qi "mccCode.*is not auth"; then
|
|
283
490
|
mcc_match="false"
|
|
284
491
|
fi
|
|
492
|
+
|
|
493
|
+
# 同一请求也是 Step 3.1 的签约查询;仅在完整结构可由共享解析器证明时输出可复用事实。
|
|
494
|
+
if [ "$mcc_match" = "true" ] && sign_status_output=$(emit_sign_status_from_business "$mcc_verify_unwrapped" "$SALES_CODE" 2>/dev/null); then
|
|
495
|
+
printf '%s\n' "$sign_status_output" \
|
|
496
|
+
| while IFS= read -r marker; do emit_control "$marker"; done
|
|
497
|
+
emit_control "AUTH_SIGN_QUERY_REUSABLE=true"
|
|
498
|
+
fi
|
|
285
499
|
fi
|
|
286
500
|
|
|
287
501
|
if [ "$scope_match" = "true" ] && [ "$mcc_match" = "true" ]; then
|
|
288
|
-
|
|
502
|
+
emit_control "✅ 授权范围校验通过(scope + MCC 授权有效性)"
|
|
289
503
|
return 0
|
|
290
504
|
fi
|
|
291
505
|
|
|
292
|
-
echo ""
|
|
293
|
-
echo "⚠️ 授权范围不满足"
|
|
294
506
|
if [ "$scope_match" != "true" ]; then
|
|
295
|
-
|
|
296
|
-
echo "🤖 需要权限: $required_scope"
|
|
297
|
-
echo "🤖 已授权 scope: $granted_scope"
|
|
298
|
-
fi
|
|
299
|
-
if [ "$mcc_match" != "true" ]; then
|
|
300
|
-
echo "📋 原因:经营类目未授权"
|
|
301
|
-
echo "🤖 当前类目: $MCC_CODE"
|
|
302
|
-
fi
|
|
303
|
-
|
|
304
|
-
echo ""
|
|
305
|
-
echo "📋 必须通过 auth.sh mismatch 退出当前登录并重新授权"
|
|
306
|
-
if [ "$scope_match" != "true" ]; then
|
|
307
|
-
echo "AUTH_FLOW:SCOPE_MISMATCH"
|
|
507
|
+
mismatch_type="SCOPE_MISMATCH"
|
|
308
508
|
else
|
|
309
|
-
|
|
509
|
+
mismatch_type="MCC_MISMATCH"
|
|
310
510
|
fi
|
|
511
|
+
emit_control "AUTH_FLOW:${mismatch_type}"
|
|
311
512
|
return 1
|
|
312
513
|
}
|
|
313
514
|
|
|
314
515
|
# ─── auth init: 检查登录状态 + 执行登录 + 构建授权链接 + 输出授权信息 ────────
|
|
315
516
|
auth_init() {
|
|
517
|
+
local DEFER_OPEN=false
|
|
316
518
|
SCOPE=""
|
|
317
519
|
SALES_CODE=""
|
|
318
520
|
MCC_CODE=""
|
|
@@ -321,6 +523,8 @@ auth_init() {
|
|
|
321
523
|
|
|
322
524
|
while [[ $# -gt 0 ]]; do
|
|
323
525
|
case $1 in
|
|
526
|
+
--defer-open)
|
|
527
|
+
DEFER_OPEN=true; shift ;;
|
|
324
528
|
--scope)
|
|
325
529
|
[ $# -ge 2 ] || { echo "❌ 缺少参数值: $1"; exit 1; }
|
|
326
530
|
SCOPE="$2"; shift 2 ;;
|
|
@@ -340,40 +544,57 @@ auth_init() {
|
|
|
340
544
|
esac
|
|
341
545
|
done
|
|
342
546
|
|
|
343
|
-
if [ -z "$SCOPE" ] || [ -z "$SALES_CODE" ] || [ -z "$MCC_CODE" ]; then
|
|
547
|
+
if [ -z "$SCOPE" ] || [ -z "$SALES_CODE" ] || [ -z "$MCC_CODE" ] || [ -z "$PRODUCT_NAME" ] || [ -z "$MCC_NAME" ]; then
|
|
344
548
|
echo "❌ 缺少必填参数"
|
|
345
|
-
echo "用法: bash auth.sh init --scope <scope> --sales-code <code> --mcc-code <code>
|
|
549
|
+
echo "用法: bash auth.sh init --defer-open --scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>"
|
|
346
550
|
exit 1
|
|
347
551
|
fi
|
|
552
|
+
if [ "$DEFER_OPEN" != true ]; then
|
|
553
|
+
echo "❌ 参数格式错误:auth init 必须使用 --defer-open,确保先展示授权说明和链接,再自动打开页面"
|
|
554
|
+
echo "用法: bash auth.sh init --defer-open --scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>"
|
|
555
|
+
exit 1
|
|
556
|
+
fi
|
|
557
|
+
validate_auth_context || return 1
|
|
558
|
+
emit_stage_metric_async "onboarding.auth.start" "$PRODUCT_NAME"
|
|
559
|
+
# 新 init 表示按已确认上下文重建授权链路;只在机器校验通过后替换旧短时状态。
|
|
560
|
+
reset_auth_state_for_init || return 1
|
|
348
561
|
|
|
349
562
|
# Step 1: 检查登录状态
|
|
350
563
|
CHECK_RESULT=$(run_json_command "alipay-cli whoami --json" alipay-cli whoami --json) || {
|
|
351
|
-
|
|
564
|
+
auth_cli_environment_failure "登录状态检查"
|
|
352
565
|
return 1
|
|
353
566
|
}
|
|
354
567
|
if ! handle_error "$CHECK_RESULT"; then
|
|
355
|
-
|
|
568
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
356
569
|
return 1
|
|
357
570
|
fi
|
|
358
571
|
LOGGED_IN=$(echo "$CHECK_RESULT" | jq -r '.data.logged_in // false')
|
|
359
572
|
IS_EXPIRED=$(echo "$CHECK_RESULT" | jq -r '.data.is_expired // false')
|
|
360
573
|
|
|
361
574
|
if [ "$LOGGED_IN" = "true" ] && [ "$IS_EXPIRED" = "false" ]; then
|
|
575
|
+
if [ -n "$AUTH_INIT_CONTEXT_MISMATCH_TYPE" ]; then
|
|
576
|
+
# 后端查询没有权威 MCC 字段,旧状态变化时不能把现有登录误判为当前上下文已授权。
|
|
577
|
+
DEVICE_CODE=""
|
|
578
|
+
BROWSER_URL=""
|
|
579
|
+
save_auth_state || return 1
|
|
580
|
+
emit_control "AUTH_FLOW:${AUTH_INIT_CONTEXT_MISMATCH_TYPE}"
|
|
581
|
+
return 1
|
|
582
|
+
fi
|
|
362
583
|
validate_current_authorization "$CHECK_RESULT" || return 1
|
|
363
584
|
DEVICE_CODE=""
|
|
364
|
-
save_auth_state
|
|
365
|
-
|
|
366
|
-
|
|
585
|
+
save_auth_state || return 1
|
|
586
|
+
emit_control "✅ 当前登录及授权范围有效,可继续后续流程"
|
|
587
|
+
emit_control "AUTH_FLOW:SKIP"
|
|
367
588
|
return 0
|
|
368
589
|
fi
|
|
369
590
|
|
|
370
591
|
# Step 2: 执行登录
|
|
371
592
|
LOGIN_RESULT=$(run_json_command "alipay-cli login --non-interactive --scope" alipay-cli login --non-interactive --scope "$SCOPE" --json) || {
|
|
372
|
-
|
|
593
|
+
auth_cli_environment_failure "授权登录发起"
|
|
373
594
|
return 1
|
|
374
595
|
}
|
|
375
596
|
if ! handle_error "$LOGIN_RESULT"; then
|
|
376
|
-
|
|
597
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
377
598
|
return 1
|
|
378
599
|
fi
|
|
379
600
|
LOGIN_STATUS=$(echo "$LOGIN_RESULT" | jq -r '.data.status // ""')
|
|
@@ -381,9 +602,9 @@ auth_init() {
|
|
|
381
602
|
if [ "$LOGIN_STATUS" = "already_logged_in" ]; then
|
|
382
603
|
validate_current_authorization || return 1
|
|
383
604
|
DEVICE_CODE=""
|
|
384
|
-
save_auth_state
|
|
385
|
-
|
|
386
|
-
|
|
605
|
+
save_auth_state || return 1
|
|
606
|
+
emit_control "✅ 当前登录及授权范围有效,可继续后续流程"
|
|
607
|
+
emit_control "AUTH_FLOW:SKIP"
|
|
387
608
|
return 0
|
|
388
609
|
fi
|
|
389
610
|
|
|
@@ -396,30 +617,21 @@ auth_init() {
|
|
|
396
617
|
# Step 4: 参数校验
|
|
397
618
|
if [ -z "$DEVICE_CODE" ] || [ -z "$SALES_CODE" ] || [ -z "$MCC_CODE" ]; then
|
|
398
619
|
echo "❌ 授权链接参数不完整,无法生成授权链接"
|
|
399
|
-
echo "📋 deviceCode
|
|
400
|
-
echo "📋 productCode
|
|
401
|
-
echo "📋 mccCode
|
|
620
|
+
[ -n "$DEVICE_CODE" ] || echo "📋 缺少字段: deviceCode"
|
|
621
|
+
[ -n "$SALES_CODE" ] || echo "📋 缺少字段: productCode"
|
|
622
|
+
[ -n "$MCC_CODE" ] || echo "📋 缺少字段: mccCode"
|
|
402
623
|
exit 1
|
|
403
624
|
fi
|
|
404
625
|
|
|
405
|
-
# Step 5:
|
|
406
|
-
BROWSER_URL
|
|
407
|
-
if [ -n "${DEV_TOOL_NAME:-}" ] && [ "$DEV_TOOL_NAME" != "unknown" ]; then
|
|
408
|
-
AUTH_PLATFORM=$(jq -nr --arg value "$DEV_TOOL_NAME" '$value|@uri')
|
|
409
|
-
BROWSER_URL="${BROWSER_URL}&platform=${AUTH_PLATFORM}"
|
|
410
|
-
fi
|
|
411
|
-
if [[ "$BROWSER_URL" != https://aipay.alipay.com/cli-auth\?* ]] ||
|
|
412
|
-
[[ "$BROWSER_URL" != *"deviceCode=${DEVICE_CODE}"* ]] ||
|
|
413
|
-
[[ "$BROWSER_URL" != *"productCode=${SALES_CODE}"* ]] ||
|
|
414
|
-
[[ "$BROWSER_URL" != *"mccCode=${MCC_CODE}"* ]] ||
|
|
415
|
-
[[ "$BROWSER_URL" == *"opengw.alipay.com/oauth/device"* ]]; then
|
|
626
|
+
# Step 5: 由统一校验器编码、构建并逐字段校验授权链接。
|
|
627
|
+
BROWSER_URL=$(build_authorization_url) || {
|
|
416
628
|
echo "❌ 授权链接构建失败,缺少必要参数或误用了 CLI verification_url,已停止。"
|
|
417
629
|
echo "📋 正确格式: https://aipay.alipay.com/cli-auth?deviceCode=...&productCode=...&mccCode=..."
|
|
418
|
-
|
|
419
|
-
|
|
630
|
+
return 1
|
|
631
|
+
}
|
|
420
632
|
|
|
421
633
|
# Step 6: 保存参数到状态文件(供 confirm/mismatch 使用)
|
|
422
|
-
save_auth_state
|
|
634
|
+
save_auth_state || return 1
|
|
423
635
|
|
|
424
636
|
# Step 7: 有效期转换(对非数字做防护)
|
|
425
637
|
if [[ "$EXPIRES_IN" =~ ^[0-9]+$ ]] && [ "$EXPIRES_IN" -ge 60 ]; then
|
|
@@ -431,35 +643,56 @@ auth_init() {
|
|
|
431
643
|
EXPIRES_DISPLAY="10 分钟"
|
|
432
644
|
fi
|
|
433
645
|
|
|
434
|
-
# Step 8:
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
echo "| 经营类目 | ${MCC_NAME:-${MCC_CODE}} (${MCC_CODE}) |"
|
|
444
|
-
if [ -n "$VERIFICATION_CODE" ]; then
|
|
445
|
-
echo "| 确认码 | ${VERIFICATION_CODE} |"
|
|
446
|
-
else
|
|
447
|
-
echo "| 确认码 | (请查看支付宝授权页面) |"
|
|
646
|
+
# Step 8: 由统一目录渲染授权信息;独立 open 动作在消息发出后打开。
|
|
647
|
+
DISPLAY_CODE="${VERIFICATION_CODE:-(请查看支付宝授权页面)}"
|
|
648
|
+
MESSAGE_INPUT=$(printf '%s\n' "$PRODUCT_NAME" "$DEVICE_CODE" "$MCC_CODE" "$MCC_NAME" "$DISPLAY_CODE" "$EXPIRES_DISPLAY" "$BROWSER_URL" | jq -Rs '
|
|
649
|
+
split("\n") as $v | {productName:$v[0],deviceCode:$v[1],mccCode:$v[2],mccName:$v[3],verificationCode:$v[4],expiresDisplay:$v[5],officialUrl:$v[6]}
|
|
650
|
+
')
|
|
651
|
+
if ! printf '%s' "$MESSAGE_INPUT" | ALIPAY_AIPAY_RENDERER_MANAGED_CALLER=auth.sh node "$RENDERER" auth.page --variant READY; then
|
|
652
|
+
cleanup_auth_state
|
|
653
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
654
|
+
exit 1
|
|
448
655
|
fi
|
|
449
|
-
echo "| 授权链接有效期 | ${EXPIRES_DISPLAY} |"
|
|
450
|
-
echo ""
|
|
451
|
-
echo "⚠️ 安全提示:请核对授权页面显示的确认码是否与上方一致,如不一致,请勿授权,立即停止操作!"
|
|
452
656
|
echo ""
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
657
|
+
emit_control "AUTH_FLOW:READY_TO_OPEN"
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
auth_open() {
|
|
661
|
+
local saved_device saved_url validate_input open_status open_helper
|
|
662
|
+
|
|
663
|
+
restore_auth_context_or_state "$@" || exit 1
|
|
664
|
+
saved_device=$(jq -r '.deviceCode // ""' "$AUTH_STATE_FILE")
|
|
665
|
+
saved_url=$(jq -r '.authorizationUrl // ""' "$AUTH_STATE_FILE")
|
|
666
|
+
if [ -z "$saved_device" ] || [ -z "$saved_url" ]; then
|
|
667
|
+
echo "❌ 缺少待打开的授权页面上下文,请重新执行 auth.sh init --defer-open"
|
|
668
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
669
|
+
return 1
|
|
670
|
+
fi
|
|
671
|
+
|
|
672
|
+
validate_input=$(jq -n \
|
|
673
|
+
--arg productName "$PRODUCT_NAME" \
|
|
674
|
+
--arg salesCode "$SALES_CODE" \
|
|
675
|
+
--arg scope "$SCOPE" \
|
|
676
|
+
--arg mccCode "$MCC_CODE" \
|
|
677
|
+
--arg mccName "$MCC_NAME" \
|
|
678
|
+
--arg deviceCode "$saved_device" \
|
|
679
|
+
--arg officialUrl "$saved_url" \
|
|
680
|
+
'{productName:$productName,salesCode:$salesCode,scope:$scope,mccCode:$mccCode,mccName:$mccName,deviceCode:$deviceCode,officialUrl:$officialUrl}') || return 1
|
|
681
|
+
if ! printf '%s' "$validate_input" | node "$RENDERER" --validate-authorization-context >/dev/null; then
|
|
682
|
+
echo "❌ 授权页面上下文校验失败,已停止打开"
|
|
683
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
684
|
+
return 1
|
|
685
|
+
fi
|
|
686
|
+
|
|
687
|
+
open_helper="${SCRIPT_DIR}/../../../normal/scripts/open_official_url.sh"
|
|
688
|
+
open_status=$(printf '%s\n' "$saved_url" | bash "$open_helper" authorization)
|
|
689
|
+
case "$open_status" in OPENED|OPEN_FAILED|GUI_UNAVAILABLE|LINK_ONLY) ;; *) open_status="OPEN_FAILED" ;; esac
|
|
690
|
+
emit_control "AUTH_OPEN:${open_status}"
|
|
459
691
|
}
|
|
460
692
|
|
|
461
|
-
# ─── auth confirm: 授权确认 + scope 校验 + MCC
|
|
693
|
+
# ─── auth confirm: 授权确认 + scope 校验 + MCC 授权有效性校验 ────────────────
|
|
462
694
|
auth_confirm() {
|
|
695
|
+
AUTH_CONFIRM_RESULT=""
|
|
463
696
|
# 优先使用显式传入的非敏感上下文;未传时再从状态文件兜底恢复。
|
|
464
697
|
restore_auth_context_or_state "$@" || exit 1
|
|
465
698
|
|
|
@@ -474,51 +707,126 @@ auth_confirm() {
|
|
|
474
707
|
|
|
475
708
|
# Step 1: 执行授权确认
|
|
476
709
|
LOGIN_COMPLETE_RESULT=$(run_json_command "alipay-cli login --complete --json" alipay-cli login --complete --json) || {
|
|
477
|
-
|
|
710
|
+
auth_cli_environment_failure "授权完成确认"
|
|
478
711
|
return 1
|
|
479
712
|
}
|
|
480
713
|
|
|
481
714
|
# Step 2: 判断授权结果
|
|
482
|
-
# alipay-cli login --complete
|
|
715
|
+
# alipay-cli login --complete: success=true/logged_in 表示可进入 whoami 门禁;
|
|
716
|
+
# authorization_pending/auth_expired 可能出现在 .error.code、.data.error.code 或 status 中。
|
|
483
717
|
OUTER_SUCCESS=$(echo "$LOGIN_COMPLETE_RESULT" | jq -r '.success // false')
|
|
484
718
|
DATA_STATUS=$(echo "$LOGIN_COMPLETE_RESULT" | jq -r '.data.status // ""')
|
|
485
|
-
ERROR_CODE=$(echo "$LOGIN_COMPLETE_RESULT" | jq -r '.data.error.code // ""')
|
|
486
|
-
|
|
487
|
-
if [ "$
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
719
|
+
ERROR_CODE=$(echo "$LOGIN_COMPLETE_RESULT" | jq -r '.error.code // .data.error.code // ""')
|
|
720
|
+
|
|
721
|
+
if [ "$ERROR_CODE" = "authorization_pending" ] || [ "$DATA_STATUS" = "authorization_pending" ] || [ "$DATA_STATUS" = "pending" ]; then
|
|
722
|
+
AUTH_CONFIRM_RESULT="PENDING"
|
|
723
|
+
if [ "${AUTH_POLLING:-false}" != "true" ]; then
|
|
724
|
+
if ! printf '%s' '{}' | ALIPAY_AIPAY_RENDERER_MANAGED_CALLER=auth.sh node "$RENDERER" auth.pending --variant DEFAULT; then
|
|
725
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
726
|
+
return 1
|
|
727
|
+
fi
|
|
728
|
+
emit_control "AUTH_FLOW:PENDING"
|
|
729
|
+
fi
|
|
492
730
|
return 0
|
|
493
|
-
elif [ "$ERROR_CODE" = "auth_expired" ]; then
|
|
494
|
-
|
|
731
|
+
elif [ "$ERROR_CODE" = "auth_expired" ] || [ "$DATA_STATUS" = "auth_expired" ] || [ "$DATA_STATUS" = "expired" ]; then
|
|
732
|
+
AUTH_CONFIRM_RESULT="EXPIRED"
|
|
495
733
|
cleanup_auth_state
|
|
496
|
-
|
|
734
|
+
if ! printf '%s' '{}' | ALIPAY_AIPAY_RENDERER_MANAGED_CALLER=auth.sh node "$RENDERER" auth.expired --variant DEFAULT; then
|
|
735
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
736
|
+
return 1
|
|
737
|
+
fi
|
|
738
|
+
emit_control "AUTH_FLOW:EXPIRED"
|
|
497
739
|
return 0
|
|
740
|
+
elif [ "$OUTER_SUCCESS" = "true" ] || [ "$DATA_STATUS" = "logged_in" ] || [ "$DATA_STATUS" = "already_logged_in" ] || [ "$DATA_STATUS" = "completed" ]; then
|
|
741
|
+
:
|
|
498
742
|
else
|
|
499
743
|
if handle_error "$LOGIN_COMPLETE_RESULT"; then
|
|
500
744
|
echo "❌ 授权确认失败:返回结果未包含可识别的完成状态"
|
|
501
745
|
fi
|
|
502
746
|
cleanup_auth_state
|
|
503
|
-
|
|
747
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
504
748
|
return 1
|
|
505
749
|
fi
|
|
506
750
|
|
|
507
|
-
# Step 3: 复用 init 的 scope + MCC
|
|
508
|
-
|
|
509
|
-
|
|
751
|
+
# Step 3: 复用 init 的 scope + MCC 授权有效性校验
|
|
752
|
+
wait_for_effective_whoami "授权后登录状态复核"
|
|
753
|
+
whoami_rc=$?
|
|
754
|
+
if [ "$whoami_rc" -eq 2 ]; then
|
|
755
|
+
AUTH_CONFIRM_RESULT="PENDING"
|
|
756
|
+
if [ "${AUTH_POLLING:-false}" != "true" ]; then
|
|
757
|
+
if ! printf '%s' '{}' | ALIPAY_AIPAY_RENDERER_MANAGED_CALLER=auth.sh node "$RENDERER" auth.pending --variant DEFAULT; then
|
|
758
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
759
|
+
return 1
|
|
760
|
+
fi
|
|
761
|
+
emit_control "AUTH_FLOW:PENDING"
|
|
762
|
+
fi
|
|
763
|
+
return 0
|
|
764
|
+
elif [ "$whoami_rc" -ne 0 ]; then
|
|
510
765
|
return 1
|
|
511
|
-
|
|
512
|
-
validate_current_authorization "$
|
|
766
|
+
fi
|
|
767
|
+
validate_current_authorization "$AUTH_WHOAMI_RESULT" || return 1
|
|
513
768
|
cleanup_auth_state
|
|
514
|
-
|
|
769
|
+
AUTH_CONFIRM_RESULT="AUTH_SUCCESS"
|
|
770
|
+
emit_control "✅ 授权确认成功(本机 CLI 登录态、scope 与 MCC 授权有效性均已通过)"
|
|
771
|
+
emit_control "AUTH_FLOW:AUTH_SUCCESS"
|
|
515
772
|
return 0
|
|
516
773
|
}
|
|
517
774
|
|
|
775
|
+
# ─── auth wait: 授权页打开后有限轮询确认状态 ────────────────────────────────
|
|
776
|
+
auth_wait() {
|
|
777
|
+
local attempt=1
|
|
778
|
+
local max_attempts=12
|
|
779
|
+
local interval_seconds=5
|
|
780
|
+
|
|
781
|
+
if [ "${ALIPAY_AIPAY_TEST_MODE:-0}" = "1" ] && [[ "${AUTH_CONFIRM_POLL_INTERVAL_SECONDS:-}" =~ ^[0-9]+$ ]]; then
|
|
782
|
+
interval_seconds="$AUTH_CONFIRM_POLL_INTERVAL_SECONDS"
|
|
783
|
+
fi
|
|
784
|
+
|
|
785
|
+
while [ "$attempt" -le "$max_attempts" ]; do
|
|
786
|
+
AUTH_POLLING=true
|
|
787
|
+
if ! auth_confirm "$@"; then
|
|
788
|
+
AUTH_POLLING=false
|
|
789
|
+
return 1
|
|
790
|
+
fi
|
|
791
|
+
AUTH_POLLING=false
|
|
792
|
+
|
|
793
|
+
case "$AUTH_CONFIRM_RESULT" in
|
|
794
|
+
AUTH_SUCCESS|EXPIRED)
|
|
795
|
+
return 0
|
|
796
|
+
;;
|
|
797
|
+
PENDING)
|
|
798
|
+
emit_control "AUTH_POLL_PENDING=${attempt}/${max_attempts}"
|
|
799
|
+
if [ "$attempt" -eq "$max_attempts" ]; then
|
|
800
|
+
if ! printf '%s' '{}' | ALIPAY_AIPAY_RENDERER_MANAGED_CALLER=auth.sh node "$RENDERER" auth.pending --variant DEFAULT; then
|
|
801
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
802
|
+
return 1
|
|
803
|
+
fi
|
|
804
|
+
emit_control "AUTH_FLOW:PENDING"
|
|
805
|
+
return 0
|
|
806
|
+
fi
|
|
807
|
+
sleep "$interval_seconds"
|
|
808
|
+
;;
|
|
809
|
+
*)
|
|
810
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
811
|
+
return 1
|
|
812
|
+
;;
|
|
813
|
+
esac
|
|
814
|
+
attempt=$((attempt + 1))
|
|
815
|
+
done
|
|
816
|
+
}
|
|
817
|
+
|
|
518
818
|
# ─── auth mismatch: 授权范围不满足 → logout → 重新授权 ──────────────────────
|
|
519
819
|
auth_mismatch() {
|
|
520
820
|
local logout_result logout_error_type
|
|
521
821
|
|
|
822
|
+
if [ "${1:-}" = "--defer-open" ]; then
|
|
823
|
+
shift
|
|
824
|
+
else
|
|
825
|
+
echo "❌ 参数格式错误:auth mismatch 必须使用 --defer-open,确保重新授权时先展示说明和链接,再自动打开页面"
|
|
826
|
+
echo "用法: bash auth.sh mismatch --defer-open [--scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>]"
|
|
827
|
+
return 1
|
|
828
|
+
fi
|
|
829
|
+
|
|
522
830
|
# 优先使用显式传入的非敏感上下文;未传时再从状态文件兜底恢复。
|
|
523
831
|
restore_auth_context_or_state "$@" || exit 1
|
|
524
832
|
|
|
@@ -535,26 +843,25 @@ auth_mismatch() {
|
|
|
535
843
|
fi
|
|
536
844
|
|
|
537
845
|
# Step 2: mismatch 是授权不匹配恢复路径中唯一执行 logout 的入口。
|
|
538
|
-
|
|
846
|
+
if ! printf '%s' '{}' | ALIPAY_AIPAY_RENDERER_MANAGED_CALLER=auth.sh node "$RENDERER" auth.mismatch --variant DEFAULT; then
|
|
847
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
848
|
+
return 1
|
|
849
|
+
fi
|
|
539
850
|
logout_result=$(run_json_command "alipay-cli logout --json" alipay-cli logout --json) || {
|
|
540
|
-
|
|
541
|
-
echo "AUTH_FLOW:FAILED"
|
|
851
|
+
auth_cli_environment_failure "退出当前登录"
|
|
542
852
|
return 1
|
|
543
853
|
}
|
|
544
854
|
logout_error_type=$(detect_error "$logout_result")
|
|
545
855
|
if [ "$logout_error_type" != "SUCCESS" ]; then
|
|
546
856
|
echo "❌ 退出当前登录失败,已停止重新授权"
|
|
547
|
-
|
|
857
|
+
emit_control "AUTH_FLOW:FAILED"
|
|
548
858
|
return 1
|
|
549
859
|
fi
|
|
550
|
-
echo "✅ 已退出当前登录"
|
|
551
|
-
|
|
552
|
-
# Step 3: 调用 auth init 执行登录 + 构建授权链接 + 输出授权信息
|
|
553
|
-
# DEV_TOOL_NAME 已 export,子进程可继承
|
|
554
|
-
echo "📋 请重新扫码授权,新的授权将包含正确的权限范围"
|
|
555
|
-
echo ""
|
|
556
860
|
|
|
861
|
+
# Step 3: 调用 auth init 执行登录 + 构建授权链接 + 输出唯一授权消息。
|
|
862
|
+
# DEV_TOOL_NAME 已 export,子进程可继承。
|
|
557
863
|
auth_init \
|
|
864
|
+
--defer-open \
|
|
558
865
|
--scope "$SCOPE" \
|
|
559
866
|
--sales-code "$SALES_CODE" \
|
|
560
867
|
--mcc-code "$MCC_CODE" \
|
|
@@ -572,16 +879,26 @@ case "${1:-}" in
|
|
|
572
879
|
shift
|
|
573
880
|
auth_confirm "$@"
|
|
574
881
|
;;
|
|
882
|
+
open)
|
|
883
|
+
shift
|
|
884
|
+
auth_open "$@"
|
|
885
|
+
;;
|
|
886
|
+
wait)
|
|
887
|
+
shift
|
|
888
|
+
auth_wait "$@"
|
|
889
|
+
;;
|
|
575
890
|
mismatch)
|
|
576
891
|
shift
|
|
577
892
|
auth_mismatch "$@"
|
|
578
893
|
;;
|
|
579
894
|
*)
|
|
580
|
-
echo "用法: bash auth.sh <init|confirm|mismatch> [参数...]"
|
|
895
|
+
echo "用法: bash auth.sh <init|open|wait|confirm|mismatch> [参数...]"
|
|
581
896
|
echo ""
|
|
582
|
-
echo " auth init --scope <scope> --sales-code <code> --mcc-code <code>
|
|
897
|
+
echo " auth init --defer-open --scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>"
|
|
898
|
+
echo " auth open [--scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>]"
|
|
899
|
+
echo " auth wait [--scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>]"
|
|
583
900
|
echo " auth confirm [--scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>]"
|
|
584
|
-
echo " auth mismatch [--scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>]"
|
|
901
|
+
echo " auth mismatch --defer-open [--scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>]"
|
|
585
902
|
exit 1
|
|
586
903
|
;;
|
|
587
904
|
esac
|