@@ -33,6 +33,18 @@ function isAliyunConfigMissing(config: AppConfig['smsAuth']) {
|
||||
return !config.accessKeyId || !config.accessKeySecret;
|
||||
}
|
||||
|
||||
function assertAliyunRequiredConfig(config: AppConfig['smsAuth']) {
|
||||
if (!config.signName.trim()) {
|
||||
throw new Error('ALIYUN_SMS_SIGN_NAME 未配置');
|
||||
}
|
||||
if (!config.templateCode.trim()) {
|
||||
throw new Error('ALIYUN_SMS_TEMPLATE_CODE 未配置');
|
||||
}
|
||||
if (!config.templateParamKey.trim()) {
|
||||
throw new Error('ALIYUN_SMS_TEMPLATE_PARAM_KEY 未配置');
|
||||
}
|
||||
}
|
||||
|
||||
function buildProviderErrorMessage(prefix: string, message: string) {
|
||||
const normalizedMessage = message.trim();
|
||||
return normalizedMessage ? `${prefix}:${normalizedMessage}` : prefix;
|
||||
@@ -48,6 +60,7 @@ class AliyunSmsVerificationService implements SmsVerificationService {
|
||||
if (isAliyunConfigMissing(config)) {
|
||||
throw new Error('ALIYUN_SMS_ACCESS_KEY_ID 或 ALIYUN_SMS_ACCESS_KEY_SECRET 未配置');
|
||||
}
|
||||
assertAliyunRequiredConfig(config);
|
||||
|
||||
const clientConfig = new OpenApiClient.Config({
|
||||
accessKeyId: config.accessKeyId,
|
||||
|
||||
@@ -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`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user