feat: 完善微信登录

This commit is contained in:
2026-05-27 00:12:45 +08:00
parent d1147713f8
commit 716a55744e
14 changed files with 160 additions and 256 deletions
+2 -1
View File
@@ -5,6 +5,7 @@ import { ScheduleModule } from '@nestjs/schedule';
import databaseConfig from './config/database.config';
import jwtConfig from './config/jwt.config';
import redisConfig from './config/redis.config';
import wechatConfig from './config/wechat.config';
import { ScheduleModule as TaskScheduleModule } from './schedule/schedule.module';
// 新的模块结构 - 按端分类
@@ -20,7 +21,7 @@ import { WebsiteModule } from './modules/website/website.module';
TaskScheduleModule,
ConfigModule.forRoot({
isGlobal: true,
load: [databaseConfig, jwtConfig, redisConfig],
load: [databaseConfig, jwtConfig, redisConfig, wechatConfig],
envFilePath: ['.env.local', '.env'],
}),
TypeOrmModule.forRootAsync({
+6
View File
@@ -0,0 +1,6 @@
import { registerAs } from '@nestjs/config';
export default registerAs('wechat', () => ({
appId: process.env.WECHAT_APPID,
appSecret: process.env.WECHAT_SECRET,
}));
@@ -239,18 +239,7 @@ export class AuthService {
session_key: string;
unionid?: string;
}> {
// 开发模式:返回模拟数据
const isDev = process.env.NODE_ENV === 'development';
if (isDev) {
this.logger.log(`[DEV] 模拟微信登录: code=${code}`);
return {
openid: `dev_openid_${Date.now()}`,
session_key: 'dev_session_key_1234567890abcdef',
unionid: `dev_unionid_${Date.now()}`,
};
}
// 生产模式:调用微信API
// 调用微信API
const appId = this.configService.get<string>('wechat.appId');
const appSecret = this.configService.get<string>('wechat.appSecret');
@@ -261,12 +250,17 @@ export class AuthService {
const url = `https://api.weixin.qq.com/sns/jscode2session?appid=${appId}&secret=${appSecret}&js_code=${code}&grant_type=authorization_code`;
try {
this.logger.log(`调用微信API: appId=${appId}, code=${code.substring(0, 10)}...`);
const response = await fetch(url);
const data = await response.json();
this.logger.log(`微信API响应: ${JSON.stringify(data)}`);
if (data.errcode) {
this.logger.error(`微信API错误: ${data.errmsg}`);
throw new BadRequestException('微信授权失败');
const errorMsg = this.getWechatErrorMessage(data.errcode, data.errmsg);
this.logger.error(`微信API错误 [${data.errcode}]: ${errorMsg}`);
this.logger.error(`微信API错误 data : ${data}`);
throw new BadRequestException(errorMsg);
}
return {
@@ -275,29 +269,35 @@ export class AuthService {
unionid: data.unionid,
};
} catch (error) {
if (error instanceof BadRequestException) {
throw error;
}
this.logger.error('调用微信API失败', error);
throw new BadRequestException('微信授权失败');
throw new BadRequestException('微信授权失败,请重试');
}
}
private getWechatErrorMessage(errcode: number, errmsg: string): string {
const errorMap: Record<number, string> = {
40029: '微信登录code无效,请重新授权',
45011: '微信登录频率限制,请稍后再试',
40163: 'code已被使用,请重新授权',
};
if (errcode === -1) {
return '微信系统繁忙,请稍后再试';
}
return errorMap[errcode] || `微信授权失败: ${errmsg}`;
}
private decryptWechatData(
encryptedData: string,
iv: string,
sessionKey: string,
): any {
try {
// 开发模式:返回模拟数据
const isDev = process.env.NODE_ENV === 'development';
if (isDev) {
this.logger.log('[DEV] 模拟解密微信手机号');
return {
phoneNumber: '13800138000',
purePhoneNumber: '13800138000',
countryCode: '86',
};
}
// 生产模式:解密数据
// 解密数据
const sessionKeyBuffer = Buffer.from(sessionKey, 'base64');
const encryptedDataBuffer = Buffer.from(encryptedData, 'base64');
const ivBuffer = Buffer.from(iv, 'base64');