1
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
2026-04-11 15:43:32 +08:00
parent f19e482c8f
commit 0981d6ee1b
78 changed files with 1102 additions and 8510 deletions

View File

@@ -15,6 +15,7 @@ export type WechatAuthService = {
buildAuthorizationUrl(params: {
callbackUrl: string;
state: string;
userAgent?: string | null;
}): string;
resolveCallbackProfile(params: {
code?: string | null;
@@ -22,12 +23,40 @@ export type WechatAuthService = {
}): Promise<WechatIdentityProfile>;
};
type WechatAuthorizationScene = 'desktop' | 'wechat_in_app';
const WECHAT_IN_APP_AUTHORIZE_ENDPOINT =
'https://open.weixin.qq.com/connect/oauth2/authorize';
function isWechatBrowser(userAgent?: string | null) {
return /MicroMessenger/iu.test(userAgent ?? '');
}
function isMobileBrowser(userAgent?: string | null) {
return /Android|iPhone|iPad|iPod|Mobile/iu.test(userAgent ?? '');
}
function resolveWechatAuthorizationScene(
userAgent?: string | null,
): WechatAuthorizationScene {
if (isWechatBrowser(userAgent)) {
return 'wechat_in_app';
}
if (isMobileBrowser(userAgent)) {
throw badRequest('当前浏览器请使用手机号登录,或在微信内打开后再使用微信登录');
}
return 'desktop';
}
class MockWechatAuthService implements WechatAuthService {
constructor(private readonly config: AppConfig['wechatAuth']) {}
buildAuthorizationUrl(params: {
callbackUrl: string;
state: string;
userAgent?: string | null;
}) {
const callbackUrl = new URL(params.callbackUrl);
callbackUrl.searchParams.set('mock_code', this.config.mockUserId);
@@ -64,12 +93,21 @@ class RealWechatAuthService implements WechatAuthService {
buildAuthorizationUrl(params: {
callbackUrl: string;
state: string;
userAgent?: string | null;
}) {
const url = new URL(this.config.authorizeEndpoint);
const scene = resolveWechatAuthorizationScene(params.userAgent);
const url = new URL(
scene === 'wechat_in_app'
? WECHAT_IN_APP_AUTHORIZE_ENDPOINT
: this.config.authorizeEndpoint,
);
url.searchParams.set('appid', this.config.appId);
url.searchParams.set('redirect_uri', params.callbackUrl);
url.searchParams.set('response_type', 'code');
url.searchParams.set('scope', 'snsapi_login');
url.searchParams.set(
'scope',
scene === 'wechat_in_app' ? 'snsapi_userinfo' : 'snsapi_login',
);
url.searchParams.set('state', params.state);
return `${url.toString()}#wechat_redirect`;
}