chore: src/modules/user/service/login.ts

This commit is contained in:
2026-07-01 17:57:43 +08:00
parent c04839231b
commit 01be974465
+309
View File
@@ -0,0 +1,309 @@
import { Config, Inject, Provide } from '@midwayjs/core';
import { BaseService, CoolCommException } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Equal, Repository } from 'typeorm';
import { UserInfoEntity } from '../entity/info';
import { UserWxService } from './wx';
import * as jwt from 'jsonwebtoken';
import { UserWxEntity } from '../entity/wx';
import { BaseSysLoginService } from '../../base/service/sys/login';
import { UserSmsService } from './sms';
import { v1 as uuid } from 'uuid';
import * as md5 from 'md5';
import { PluginService } from '../../plugin/service/info';
/**
* 登录
*/
@Provide()
export class UserLoginService extends BaseService {
@InjectEntityModel(UserInfoEntity)
userInfoEntity: Repository<UserInfoEntity>;
@InjectEntityModel(UserWxEntity)
userWxEntity: Repository<UserWxEntity>;
@Inject()
userWxService: UserWxService;
@Config('module.user.jwt')
jwtConfig;
@Inject()
baseSysLoginService: BaseSysLoginService;
@Inject()
pluginService: PluginService;
@Inject()
userSmsService: UserSmsService;
/**
* 发送手机验证码
* @param phone
* @param captchaId
* @param code
*/
async smsCode(phone, captchaId, code) {
// 1、检查图片验证码 2、发送短信验证码
const check = await this.baseSysLoginService.captchaCheck(captchaId, code);
if (!check) {
throw new CoolCommException('图片验证码错误');
}
await this.userSmsService.sendSms(phone);
}
/**
* 手机验证码登录
* @param phone
* @param smsCode
*/
async phoneVerifyCode(phone, smsCode) {
// 1、检查短信验证码 2、登录
const check = await this.userSmsService.checkCode(phone, smsCode);
if (check) {
return await this.phone(phone);
} else {
throw new CoolCommException('验证码错误');
}
}
/**
* 小程序手机号登录
* @param code
* @param encryptedData
* @param iv
*/
async miniPhone(code, encryptedData, iv) {
const phone = await this.userWxService.miniPhone(code, encryptedData, iv);
if (phone) {
return await this.phone(phone);
} else {
throw new CoolCommException('获得手机号失败,请检查配置');
}
}
/**
* 手机号一键登录
* @param access_token
* @param openid
*/
async uniPhone(access_token, openid, appId) {
const instance: any = await this.pluginService.getInstance('uniphone');
const phone = await instance.getPhone(access_token, openid, appId);
if (phone) {
return await this.phone(phone);
} else {
throw new CoolCommException('获得手机号失败,请检查配置');
}
}
/**
* 手机登录
* @param phone
* @returns
*/
async phone(phone: string) {
let user: any = await this.userInfoEntity.findOneBy({
phone: Equal(phone),
});
if (!user) {
user = {
phone,
unionid: phone,
loginType: 2,
nickName: phone.replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2'),
};
await this.userInfoEntity.insert(user);
}
return this.token({ id: user.id });
}
/**
* 公众号登录
* @param code
*/
async mp(code: string) {
let wxUserInfo = await this.userWxService.mpUserInfo(code);
if (wxUserInfo) {
delete wxUserInfo.privilege;
wxUserInfo = await this.saveWxInfo(
{
openid: wxUserInfo.openid,
unionid: wxUserInfo.unionid,
avatarUrl: wxUserInfo.headimgurl,
nickName: wxUserInfo.nickname,
gender: wxUserInfo.sex,
city: wxUserInfo.city,
province: wxUserInfo.province,
country: wxUserInfo.country,
},
1
);
return this.wxLoginToken(wxUserInfo);
} else {
throw new Error('微信登录失败');
}
}
/**
* 微信APP授权登录
* @param code
*/
async wxApp(code: string) {
let wxUserInfo = await this.userWxService.appUserInfo(code);
if (wxUserInfo) {
delete wxUserInfo.privilege;
wxUserInfo = await this.saveWxInfo(
{
openid: wxUserInfo.openid,
unionid: wxUserInfo.unionid,
avatarUrl: wxUserInfo.headimgurl,
nickName: wxUserInfo.nickname,
gender: wxUserInfo.sex,
city: wxUserInfo.city,
province: wxUserInfo.province,
country: wxUserInfo.country,
},
1
);
return this.wxLoginToken(wxUserInfo);
} else {
throw new Error('微信登录失败');
}
}
/**
* 保存微信信息
* @param wxUserInfo
* @param type
* @returns
*/
async saveWxInfo(wxUserInfo, type) {
const find: any = { openid: wxUserInfo.openid };
let wxInfo: any = await this.userWxEntity.findOneBy(find);
if (wxInfo) {
wxUserInfo.id = wxInfo.id;
}
return this.userWxEntity.save({
...wxUserInfo,
type,
});
}
/**
* 小程序登录
* @param code
* @param encryptedData
* @param iv
*/
async mini(code, encryptedData, iv) {
let wxUserInfo = await this.userWxService.miniUserInfo(
code,
encryptedData,
iv
);
if (wxUserInfo) {
// 保存
wxUserInfo = await this.saveWxInfo(wxUserInfo, 0);
return await this.wxLoginToken(wxUserInfo);
}
}
/**
* 微信登录 获得token
* @param wxUserInfo 微信用户信息
* @returns
*/
async wxLoginToken(wxUserInfo) {
const unionid = wxUserInfo.unionid ? wxUserInfo.unionid : wxUserInfo.openid;
let userInfo: any = await this.userInfoEntity.findOneBy({ unionid });
if (!userInfo) {
const file = await this.pluginService.getInstance('upload');
const avatarUrl = await file.downAndUpload(
wxUserInfo.avatarUrl,
uuid() + '.png'
);
userInfo = {
unionid,
nickName: wxUserInfo.nickName,
avatarUrl,
gender: wxUserInfo.gender,
loginType: wxUserInfo.type,
};
await this.userInfoEntity.insert(userInfo);
}
return this.token({ id: userInfo.id });
}
/**
* 刷新token
* @param refreshToken
*/
async refreshToken(refreshToken) {
try {
const info = jwt.verify(refreshToken, this.jwtConfig.secret);
if (!info['isRefresh']) {
throw new CoolCommException('token类型非refreshToken');
}
const userInfo = await this.userInfoEntity.findOneBy({
id: info['id'],
});
return this.token({ id: userInfo.id });
} catch (e) {
throw new CoolCommException(
'刷新token失败,请检查refreshToken是否正确或过期'
);
}
}
/**
* 密码登录
* @param phone
* @param password
*/
async password(phone, password) {
const user = await this.userInfoEntity.findOneBy({ phone });
if (user && user.password == md5(password)) {
return this.token({
id: user.id,
});
} else {
throw new CoolCommException('账号或密码错误');
}
}
/**
* 获得token
* @param info
* @returns
*/
async token(info) {
const { expire, refreshExpire } = this.jwtConfig;
return {
expire,
token: await this.generateToken(info),
refreshExpire,
refreshToken: await this.generateToken(info, true),
};
}
/**
* 生成token
* @param tokenInfo 信息
* @param roleIds 角色集合
*/
async generateToken(info, isRefresh = false) {
const { expire, refreshExpire, secret } = this.jwtConfig;
const user = await this.userInfoEntity.findOneBy({ id: Equal(info.id) });
const tokenInfo = {
isRefresh,
...info,
tenantId: user?.tenantId,
};
return jwt.sign(tokenInfo, secret, {
expiresIn: isRefresh ? refreshExpire : expire,
});
}
}