From 7682bb2ae7cf699570fddd4d56aa6fb5908a92c6 Mon Sep 17 00:00:00 2001 From: Wang Zhuoxuan Date: Thu, 28 May 2026 23:43:21 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E8=9E=8D=E5=90=88=E8=AE=A4?= =?UTF-8?q?=E8=AF=81=20schemeCode=20=E6=8C=89=E5=B9=B3=E5=8F=B0=E6=8B=86?= =?UTF-8?q?=E5=88=86=E4=B8=BA=E7=8B=AC=E7=AB=8B=E7=8E=AF=E5=A2=83=E5=8F=98?= =?UTF-8?q?=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 不同端(Android/iOS/Harmony)在阿里云控制台使用不同的方案 Code, 单一 ALIYUN_FUSION_SCHEME_CODE 无法满足多端需求。改为按平台映射 三个独立环境变量,providers 端点也按平台精确判断可用性。 同步更新 API 文档:补充 fusion/token 请求参数表和 Harmony 平台支持。 --- .env.example | 4 +++- .env.prod.example | 9 +++++++++ docs/api-reference.md | 21 ++++++++++++++++++--- src/routes/auth.ts | 19 ++++++++++++++----- src/services/auth/fusion-auth-client.ts | 16 +++++++++++----- src/utils/config.ts | 4 +++- 6 files changed, 58 insertions(+), 15 deletions(-) diff --git a/.env.example b/.env.example index 12f8da4..a7c759f 100644 --- a/.env.example +++ b/.env.example @@ -27,7 +27,9 @@ OSS_REGION= # RAM 子用户需授予 AliyunDypnsFullAccess 权限 ALIYUN_ACCESS_KEY_ID= ALIYUN_ACCESS_KEY_SECRET= -ALIYUN_FUSION_SCHEME_CODE= +ALIYUN_FUSION_SCHEME_CODE_ANDROID= +ALIYUN_FUSION_SCHEME_CODE_IOS= +ALIYUN_FUSION_SCHEME_CODE_HARMONY= # Huawei IAP (Phase 1c) HUAWEI_IAP_URL= diff --git a/.env.prod.example b/.env.prod.example index 8c998d3..53ebe35 100644 --- a/.env.prod.example +++ b/.env.prod.example @@ -25,6 +25,15 @@ OSS_ACCESS_KEY_SECRET= OSS_BUCKET=duoqi-assets OSS_REGION=oss-cn-hangzhou +# Alibaba Cloud Fusion Auth +# 阿里云号码认证服务,用于手机号一键登录和短信验证码登录 +# RAM 子用户需授予 AliyunDypnsFullAccess 权限 +ALIYUN_ACCESS_KEY_ID= +ALIYUN_ACCESS_KEY_SECRET= +ALIYUN_FUSION_SCHEME_CODE_ANDROID= +ALIYUN_FUSION_SCHEME_CODE_IOS= +ALIYUN_FUSION_SCHEME_CODE_HARMONY= + # Huawei IAP HUAWEI_IAP_URL=https://subscr-drcn.iap.hicloud.com HUAWEI_MERCHANT_ID= diff --git a/docs/api-reference.md b/docs/api-reference.md index fda1db8..0731310 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -274,9 +274,24 @@ 认证:无 限流:10 次/分钟 -用途:获取阿里云融合认证 SDK 鉴权 Token。客户端在初始化 SDK 前调用此接口。 +用途:获取阿里云融合认证 SDK 鉴权 Token。客户端在初始化 SDK 前调用此接口。`schemeCode` 和 `durationSeconds` 由服务端配置,不暴露给客户端。 -请求:无请求体(schemeCode 从服务端配置读取)。 +请求: + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `platform` | `"Android"` \| `"iOS"` \| `"Harmony"` | 是 | 客户端平台 | +| `packageName` | string | Android 必填 | App 包名 | +| `packageSign` | string | Android 必填 | App 包签名(MD5,去冒号小写) | +| `bundleId` | string | iOS 必填 | App Bundle ID | + +```json +{ + "platform": "Android", + "packageName": "com.example.app", + "packageSign": "a1b2c3d4e5f6..." +} +``` 响应: @@ -297,7 +312,7 @@ "success": false, "data": null, "error": { - "code": "UNAUTHORIZED", + "code": "SERVICE_UNAVAILABLE", "message": "Fusion auth is not configured on the server" } } diff --git a/src/routes/auth.ts b/src/routes/auth.ts index 4f4e150..48481b4 100644 --- a/src/routes/auth.ts +++ b/src/routes/auth.ts @@ -37,7 +37,7 @@ const fusionVerifySchema = z.object({ }); const fusionTokenSchema = z.object({ - platform: z.enum(['Android', 'iOS']), + platform: z.enum(['Android', 'iOS', 'Harmony']), packageName: z.string().optional(), packageSign: z.string().optional(), bundleId: z.string().optional(), @@ -78,11 +78,20 @@ const PROVIDER_METADATA: Record = { + android: config.ALIYUN_FUSION_SCHEME_CODE_ANDROID, + ios: config.ALIYUN_FUSION_SCHEME_CODE_IOS, + harmony: config.ALIYUN_FUSION_SCHEME_CODE_HARMONY, + }; + return !!schemeCodeMap[platform]; + } case 'huawei': return !!(config.HUAWEI_CLIENT_ID && config.HUAWEI_CLIENT_SECRET); case 'apple': @@ -109,7 +118,7 @@ function buildProviderList(platform: Platform, dbToggles: Map): if (!PLATFORM_AVAILABILITY[id]?.includes(platform)) continue; const enabled = CREDENTIAL_PROVIDERS.has(id) - ? isCredentialConfigured(id) + ? isCredentialConfigured(id, platform) : DB_TOGGLE_PROVIDERS.has(id) ? (dbToggles.get(id) ?? false) : false; diff --git a/src/services/auth/fusion-auth-client.ts b/src/services/auth/fusion-auth-client.ts index 3ed7bde..a363ec8 100644 --- a/src/services/auth/fusion-auth-client.ts +++ b/src/services/auth/fusion-auth-client.ts @@ -29,11 +29,17 @@ function getClient() { return clientInstance; } -function requireSchemeCode(): string { - if (!config.ALIYUN_FUSION_SCHEME_CODE) { - throw new UnauthorizedError('Fusion auth scheme code is not configured'); +function requireSchemeCode(platform: string): string { + const schemeCodeMap: Record = { + Android: config.ALIYUN_FUSION_SCHEME_CODE_ANDROID, + iOS: config.ALIYUN_FUSION_SCHEME_CODE_IOS, + Harmony: config.ALIYUN_FUSION_SCHEME_CODE_HARMONY, + }; + const schemeCode = schemeCodeMap[platform]; + if (!schemeCode) { + throw new UnauthorizedError(`Fusion auth scheme code not configured for platform: ${platform}`); } - return config.ALIYUN_FUSION_SCHEME_CODE; + return schemeCode; } export async function getFusionAuthToken(options: { @@ -43,7 +49,7 @@ export async function getFusionAuthToken(options: { bundleId?: string; }): Promise { const client = getClient(); - const schemeCode = requireSchemeCode(); + const schemeCode = requireSchemeCode(options.platform); const request = new $Dypnsapi20170525.GetFusionAuthTokenRequest({ schemeCode, diff --git a/src/utils/config.ts b/src/utils/config.ts index 6d034bb..c05db4b 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -18,7 +18,9 @@ const envSchema = z.object({ APPLE_BUNDLE_ID: z.string().optional(), ALIYUN_ACCESS_KEY_ID: z.string().optional(), ALIYUN_ACCESS_KEY_SECRET: z.string().optional(), - ALIYUN_FUSION_SCHEME_CODE: z.string().optional(), + ALIYUN_FUSION_SCHEME_CODE_ANDROID: z.string().optional(), + ALIYUN_FUSION_SCHEME_CODE_IOS: z.string().optional(), + ALIYUN_FUSION_SCHEME_CODE_HARMONY: z.string().optional(), PORT: z.coerce.number().default(3000), NODE_ENV: z.enum(['development', 'production', 'test']).default('development'), LOG_LEVEL: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']).default('info'),