'use strict'; const Service = require('egg').Service; const assert = require('assert'); const _ = require('lodash'); const { BusinessError, ErrorCode } = require('naf-core').Error; const { ObjectId } = require('mongoose').Types; const crypto = require('crypto'); // 云就业生成的公钥,用来加密退出登录的参数 const publicKey = `-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDafDeoNSNhqaj0dEK3bK/nXnGe7QdQHTegc49/jFHtbky3gZle0XKvbqPHv8d9eih89RJe3UOORUhBV6eRkvCLaf8lj+BgI0TyWDgjHg1jGi6MN+LZx9GKZ/Tq+TVPH3Fv/YPGcQADb4lELwSK3F6kRcm1duwcij0bnFhfTA999QIDAQAB -----END PUBLIC KEY-----`; // 双困生生成的私钥,用来解密登录的参数 const privateKey = `-----BEGIN ENCRYPTED PRIVATE KEY----- MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIDrmClOodJAACAggA MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBDFUSMr1yfAK9Lt9r4Idi5EBIIE 0JmkwwNWz+ya4IffVvzQS2fEbIRoAcxoBEKaZjLd2cCBQbE/0BODdlEWcJ7Z4Z3k 1NfDaqQToh+k9sE2C108q2jCETLiLPWodTMAMO0pVHBiiJeh2ZOoDxwyDWsyHYcA 6S7EhuQPOY7Fd8WKWeYcH1m8TLyL40fmWq0cseCoyvP1M0LRQ5OFKD7+uOYJBQhq 7pPwuJouorKMUHbxpribrOmr8fspfkglhP6+TZ7p7XzAs6e92mNz1SfiflmChoPH sqcJb0SJaHCdzblMT/yCF1Gm+h91gpU9L3sJUbivBtjFkX4LsE8DMs15dkPIbWHq YTJx+2QSOpGp6cK1D7LS8LInptHxI/UGRVYH3FLP1oUJuuFj+Wl7PKvOpZcc5uk1 u5tbHmUkhpJeklqsCWi6brQpPxiQAiCeiqMiTOQLlwiRNTT51waOqrvb60onDHAw bEWfb0FQ0o3kb1yEQd/qPTJXWPZ96WhM3/7VNGoEDKwCzv5m8G1JbO4ct79iPF5x Y7rx0uKJFPbekNACRmb9U0f3DpXm8hdgCKVKmbkgG2ZZnnmJg2lzmT72lwQfdcnv O6IjXVLoDLjAYqjGe6HXQchi5rBHgmoguyHP6nGJ67n50hQ+upecVyp7k7LvuXi/ jHF8/zJfDZaEvjf6CwkePYk9XbOnvyls+RWZM1ZwX4xbk6nbONzo71uRrI0E8sKS kWFCtvdbNJ//PaugrQNRMTs5z8Q3qMIyXRPXrxPFM/3lECaIEYvRrPyEYfdANqod JrMru+hbHvutTPhDuOgJ+RVgirwfZpxPQS5aHHXQu8bMps9DEL15i6xKOVX5lqvL lEL0YmqmRo7Idb9D+l0pyPAg9X1AwTziION/1cOPvWmjGVZqqaBv+jsMVlB+1o0o BrJBy9SEzw5ya7sYi1BCwO6k7qAsB1qSmnu8Gg/RXAIz6D9nJiJbB5kwusVQretn RqTj8ldBOgo+1la3hHzW8INTAVrlnmZjNMEGN4olYcJv6vHK9XTk7ruIkteJYD8Y 2jIFU3evsPTs4ugYxArEmzYsr1ZJR91aWf7naKcUlsap9k2zgHVw7Ks31D8T1OT3 mXQZdkY9hx+0kdh8iSYOkCSa237usV/TbYg12ncB8xSVsMQMNnEQHWIcgFUBeZoo KQ27ijLmy5YYx8KYDAm7UJZ3Z00OrFa1D5qjippXkrDKbBwM3SrDSSVBtfKMGxyi epF9hMBs6ecBBSIF9sZg0LHfMlbOIWyNLklHUtdBQ4+vavzbG1V66p0pB7HJp6rp YC3moNRhHXyUFpvkIis7gFQ4xdE6FMEJsrHeZQHuOzRIB4XlwiCiAIg+IDmnP0hd 8Sxv0drpFU+zjR2aMr4bfhYdBG35NE/xfOp+ba25yCWCilljCIj46+jD0E2UvSrw 9iDtf75OXF2njqaLwmnFtHyAOA54IcXi9Y3NaXUXFxmK9iif5UbKa/dR+8rmOCF2 cozCs4Ujribcpgs3cqjkVX0Z12B7YdCZM1Tpj7BgPOLjpi0h0s5wbP9QMm3yb2S2 SKteoIypVcUXdpPqSwXtsUOUSuj7MeNXW2mkmQsH+W/n2Zn5OxgFKZ0JZ4z/OHei hK1UFYPQ9BEBMzsJ2ttBLwak//hAMaUJDT8EKxEoBdqb -----END ENCRYPTED PRIVATE KEY-----`; class YunjiuyeService extends Service { // 检查用户是否和云就业有关联 // 没关联就直接重定向到关联页 // 有关联就直接去登录 async checkUserIsConnect({ code, org, type }) { assert(code, '缺少用户标识'); assert(org, '缺少机构'); const yjycModel = this.ctx.model.Yjyconnect; const result = await yjycModel.findOne({ ycode: code, yorg: org, ytype: type }).lean(); if (!result) return false; return result.suid; } /** * 用户与云就业关联 * @param {string} type 用户角色 * @param {string} mobile 电话 * @param {string} code 身份编码 * @param {string} org 云就业的组织机构编码 * @param {string} ytype 云就业角色类型 */ async userBind({ type, mobile, code, org, ytype }) { assert(mobile, '登录账户不能为空'); assert(type, '用户角色不能为空'); assert(ytype, '身份不能为空'); const userModel = this.ctx.model.User; let res = await userModel.findOne({ mobile, type }); if (!res) { const userData = { name: code, mobile, type, status: '1' }; // 没有账号,需要创建 // 中心端,直接创建中心端账号即可 // 教师,班主任,学校,对应创建数据,再形成用户数据 if (type === '0') { // 中心没什么需要处理的 userData.name = code; } else if (type === '1') { // 班主任,需要生成班主任数据 const obj = { name: code, mobile }; const res = await this.ctx.model.Headteacher.create(obj); if (res) userData.uid = ObjectId(res._id).toString(); } else if (type === '2') { // 学校管理员 const obj = { name: code }; const res = await this.ctx.model.School.create(obj); if (res) userData.uid = ObjectId(res._id).toString(); } else if (type === '3') { // 教师 const data = { name: code, phone: mobile }; const res = await this.ctx.model.Teacher.create(data); if (res) userData.uid = ObjectId(res._id).toString(); } res = await userModel.create(userData); } const yjycModel = this.ctx.model.Yjyconnect; const obj = { ycode: code, yorg: org, suid: ObjectId(res._id).toString(), ytype }; const isHas = await yjycModel.count({ suid: obj.suid }); if (process.env.NODE_ENV === 'development') { if (isHas > 0) return obj.suid; else { await yjycModel.create(obj); return obj.suid; } } else { if (isHas > 0) throw new BusinessError(ErrorCode.DATA_EXISTED, '账户已绑定,无需再次绑定'); await yjycModel.create(obj); return obj.suid; } } // 用户id获取用户信息,登录获取token返回 async userToken(id) { assert(id, '缺少双困生平台用户标识'); const userModel = this.ctx.model.User; const userService = this.ctx.service.login; const user = await userModel.findById(id); if (!user) throw new BusinessError(ErrorCode.USER_NOT_EXIST); const token = await userService.createJwt(user); return token; } async getBindInfo(suid) { const yjycModel = this.ctx.model.Yjyconnect; const info = await yjycModel.findOne({ suid }).lean(); if (!info) throw new BusinessError(ErrorCode.SERVICE_FAULT, '为找到与云就业绑定信息'); const data = { code: info.ycode, org: info.yorg }; return data; } async yLogout(params) { const domain = await this.app.redis.get('yjyDomain'); if (!domain) throw new BusinessError(ErrorCode.SERVICE_FAULT, '缺少登录时的域名'); const url = `${domain}?params=${params}`; return url; } // 检查用户是否登录.未登录就跳走 async checkYjyLogin(id) { if (!id) throw new BusinessError(ErrorCode.BADPARAM, '缺少参数'); const redis = this.app.redis; const key = this.app.config.yjyLoginKey; const loginTime = await redis.get(`${key}${id}`); if (loginTime) return true; } // 加密,使用云就业提供的公钥对数据进行加密,供退出登录加密参数使用 encryptData(data) { const enc = crypto.publicEncrypt( { key: publicKey, padding: crypto.constants.RSA_PKCS1_PADDING, }, Buffer.from(JSON.stringify(data)) ); return enc.toString('base64'); } // 解密,使用双困生提供的私钥对数据进行解密,供登录解析参数使用 decryptData(encstr) { // encstr = encodeURIComponent(encstr); const sb = Buffer.from(encstr, 'base64'); const dec = crypto.privateDecrypt( { key: privateKey, passphrase: 'sks_secret', padding: crypto.constants.RSA_PKCS1_PADDING, }, sb ); if (dec) return JSON.parse(dec.toString()); return false; } async getDomain(origin) { // 整个退出登录的地址 await this.app.redis.set('yjyDomain', origin); } } module.exports = YunjiuyeService;