|
|
@@ -8,14 +8,13 @@
|
|
|
* @version
|
|
|
*/
|
|
|
|
|
|
-const crypto = require('crypto');
|
|
|
const jwt = require('jsonwebtoken');
|
|
|
const axios = require('axios');
|
|
|
const weappConfig = require('../const/weapp');
|
|
|
|
|
|
module.exports = app => {
|
|
|
class Weappchat extends app.BaseService {
|
|
|
- async login(data) {
|
|
|
+ async accountlogin(data) {
|
|
|
const { code, account, password } = data;
|
|
|
const projectData = await this.ctx.service.project.getProjectByCode(
|
|
|
code.trim()
|
|
|
@@ -23,24 +22,37 @@ module.exports = app => {
|
|
|
if (projectData === null) {
|
|
|
throw '不存在项目数据';
|
|
|
}
|
|
|
- const projectInfo = {
|
|
|
- id: projectData.id,
|
|
|
- name: projectData.name,
|
|
|
- code: projectData.code,
|
|
|
- userAccount: projectData.user_account,
|
|
|
- };
|
|
|
- const projectService = this.ctx.service.projectAccount;
|
|
|
- const accountData = await projectService.db.get(projectService.tableName, {
|
|
|
- account: data.account,
|
|
|
- projectId: projectInfo.id,
|
|
|
+ const projectAccount = await this.ctx.service.projectAccount.getDataByCondition({
|
|
|
+ account,
|
|
|
+ project_id: projectData.id,
|
|
|
enable: 1,
|
|
|
});
|
|
|
- if (!accountData) {
|
|
|
+ if (!projectAccount) {
|
|
|
throw '账号不存在或未启用';
|
|
|
}
|
|
|
- // const encryptPassword = crypto.createHmac('sha1', data.account.trim()).update('!*#)385'+).digest().toString('base64');
|
|
|
+ // 验证密码
|
|
|
+ const isPasswordValid = await this.ctx.service.projectAccount.loginAndMigrate(projectAccount, password.trim());
|
|
|
+ if (!isPasswordValid) {
|
|
|
+ throw '帐号或密码错误';
|
|
|
+ }
|
|
|
+ const accessToken = jwt.sign(
|
|
|
+ { accountId: projectAccount.id, type: 'access' },
|
|
|
+ weappConfig.jwtSecret,
|
|
|
+ { expiresIn: weappConfig.accessTokenExpiresIn }
|
|
|
+ );
|
|
|
+
|
|
|
+ const refreshToken = jwt.sign(
|
|
|
+ { accountId: projectAccount.id, type: 'refresh' },
|
|
|
+ weappConfig.jwtSecret,
|
|
|
+ { expiresIn: weappConfig.refreshTokenExpiresIn }
|
|
|
+ );
|
|
|
+ // 3. 存入 Redis:pid 对应最新 refreshToken
|
|
|
+ const key = `user:${projectAccount.id}:refresh_token`;
|
|
|
+ await app.redis.set(key, refreshToken, 'EX', weappConfig.redisExpire);
|
|
|
+ return { accessToken, refreshToken };
|
|
|
}
|
|
|
- // 微信小程序登录
|
|
|
+
|
|
|
+ // 微信快捷登录
|
|
|
async weappLogin(code) {
|
|
|
try {
|
|
|
const wxRes = await axios.get('https://api.weixin.qq.com/sns/jscode2session', {
|
|
|
@@ -52,28 +64,87 @@ module.exports = app => {
|
|
|
},
|
|
|
});
|
|
|
|
|
|
- const { openid, session_key, errcode } = wxRes.data;
|
|
|
- if (errcode || !openid) throw '微信登录失败';
|
|
|
+ const { openid, errcode } = wxRes.data;
|
|
|
+ console.log('openid', openid);
|
|
|
+
|
|
|
+ if (errcode || !openid) throw '微信授权登录失败';
|
|
|
+
|
|
|
+ const paList = await this.ctx.service.projectAccount.getAllDataByCondition({ where: { wx_openid: openid } });
|
|
|
+ const pidList = this.ctx.app._.uniq(this.ctx.app._.map(paList, 'project_id'));
|
|
|
+ const pList = [];
|
|
|
+ for (const p of pidList) {
|
|
|
+ const project = await this.ctx.service.project.getDataById(p);
|
|
|
+ if (project) {
|
|
|
+ pList.push({ code: project.code, name: project.name });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (pList.length === 0) {
|
|
|
+ throw '该微信号未绑定任何项目';
|
|
|
+ }
|
|
|
+
|
|
|
// 2. 生成 access_token + refresh_token
|
|
|
- const accessToken = app.jwt.sign(
|
|
|
- { openid, type: 'access' },
|
|
|
+ const accessToken = jwt.sign(
|
|
|
+ { accountId: openid, type: 'access' },
|
|
|
weappConfig.jwtSecret,
|
|
|
{ expiresIn: weappConfig.accessTokenExpiresIn }
|
|
|
);
|
|
|
|
|
|
- const refreshToken = app.jwt.sign(
|
|
|
- { openid, type: 'refresh' },
|
|
|
+ const refreshToken = jwt.sign(
|
|
|
+ { accountId: openid, type: 'refresh' },
|
|
|
weappConfig.jwtSecret,
|
|
|
{ expiresIn: weappConfig.refreshTokenExpiresIn }
|
|
|
);
|
|
|
- // 3. 存入 Redis:openid 对应最新 refreshToken
|
|
|
+ // 3. 存入 Redis:pid 对应最新 refreshToken
|
|
|
const key = `user:${openid}:refresh_token`;
|
|
|
await app.redis.set(key, refreshToken, 'EX', weappConfig.redisExpire);
|
|
|
- return { accessToken, refreshToken };
|
|
|
+ return { accessToken, refreshToken, pList };
|
|
|
} catch (error) {
|
|
|
- throw '微信登录失败';
|
|
|
+ throw error.toString();
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // 其他手机号验证码登陆
|
|
|
+ async mobileLogin(data) {
|
|
|
+ // 1. 根据手机号查询账号
|
|
|
+ const projectAccount = await this.ctx.service.projectAccount.getDataByCondition({ auth_mobile: data.mobile });
|
|
|
+ if (!projectAccount) {
|
|
|
+ throw '手机号未绑定';
|
|
|
+ }
|
|
|
+ const cacheKey = 'smsCode:' + projectAccount.id;
|
|
|
+ const cacheCode = await this.cache.get(cacheKey);
|
|
|
+
|
|
|
+ if (!cacheCode || cacheCode !== (data.captcha + projectAccount.auth_mobile)) {
|
|
|
+ throw '验证码错误或已过期';
|
|
|
+ }
|
|
|
+ const accessToken = jwt.sign(
|
|
|
+ { accountId: projectAccount.id, type: 'access' },
|
|
|
+ weappConfig.jwtSecret,
|
|
|
+ { expiresIn: weappConfig.accessTokenExpiresIn }
|
|
|
+ );
|
|
|
+
|
|
|
+ const refreshToken = jwt.sign(
|
|
|
+ { accountId: projectAccount.id, type: 'refresh' },
|
|
|
+ weappConfig.jwtSecret,
|
|
|
+ { expiresIn: weappConfig.refreshTokenExpiresIn }
|
|
|
+ );
|
|
|
+ // 3. 存入 Redis:pid 对应最新 refreshToken
|
|
|
+ const key = `user:${projectAccount.id}:refresh_token`;
|
|
|
+ await app.redis.set(key, refreshToken, 'EX', weappConfig.redisExpire);
|
|
|
+ return { accessToken, refreshToken };
|
|
|
+ }
|
|
|
+
|
|
|
+ async sendCaptcha(mobile) {
|
|
|
+ const projectAccount = await this.ctx.service.projectAccount.getDataByCondition({ auth_mobile: mobile });
|
|
|
+ if (!projectAccount) {
|
|
|
+ throw '手机号未绑定';
|
|
|
+ }
|
|
|
+
|
|
|
+ const result = await this.ctx.service.projectAccount.setSMSCode(projectAccount.id, mobile);
|
|
|
+ if (!result) {
|
|
|
+ throw '验证码发送失败';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 刷新 access token
|
|
|
* @param {string} refreshToken - 刷新 token
|
|
|
@@ -85,16 +156,22 @@ module.exports = app => {
|
|
|
if (decoded.type !== 'refresh') {
|
|
|
throw 'token 类型错误';
|
|
|
}
|
|
|
- const { openid } = decoded;
|
|
|
+ const { accountId } = decoded;
|
|
|
// 2. 校验 Redis 中是否存在(防止篡改/过期/被踢)
|
|
|
- const redisKey = `user:${openid}:refresh_token`;
|
|
|
+ const redisKey = `user:${accountId}:refresh_token`;
|
|
|
const redisRefreshToken = await app.redis.get(redisKey);
|
|
|
if (!redisRefreshToken || redisRefreshToken !== refreshToken) {
|
|
|
throw 'refresh_token 无效或已过期';
|
|
|
}
|
|
|
- const newAccessToken = app.jwt.sign({ openid, type: 'access' }, weappConfig.jwtSecret, { expiresIn: weappConfig.accessTokenExpiresIn });
|
|
|
+ const newAccessToken = jwt.sign({ accountId, type: 'access' }, weappConfig.jwtSecret, { expiresIn: weappConfig.accessTokenExpiresIn });
|
|
|
return newAccessToken;
|
|
|
}
|
|
|
+
|
|
|
+ // 获取用户信息以及参与的标段等
|
|
|
+ async getUserInfo() {
|
|
|
+ const accountInfo = this.ctx.accountInfo;
|
|
|
+
|
|
|
+ }
|
|
|
}
|
|
|
return Weappchat;
|
|
|
};
|