| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595 | 'use strict';/** * * * @author Ellisran * @date 2020/7/2 * @version */const moment = require('moment');// const Controller = require('egg').Controller;const crypto = require('crypto');const qywxCrypto = require('@wecom/crypto');const getRawBody = require('raw-body');const maintainConst = require('../const/maintain');const wxConst = require('../const/wechat_template.js');const smsTypeConst = require('../const/sms_type');const wxWork = require('../lib/wx_work');const { parseStringXml } = require('../lib/common');module.exports = app => {    class WechatController extends app.BaseController {        /**         * 接入微信         *         * @param {Object} ctx - egg全局页面         * @return {void}         */        async index(ctx) {            try {                const signature = ctx.query.signature;                const timestamp = ctx.query.timestamp;                const nonce = ctx.query.nonce;                const echostr = ctx.query.echostr;                const array = [ctx.app.config.wechatAll.token, timestamp, nonce];                array.sort();                const tempStr = array.join('');                const hashCode = crypto.createHash('sha1');                const resultCode = hashCode.update(tempStr, 'utf8').digest('hex');                if (resultCode === signature) {                    ctx.body = echostr;                    // res.send(echostr);                } else {                    throw '验证失败';                }            } catch (e) {                console.log(e);            }        }        /**         * 微信自动回复         *         * @param {Object} ctx - egg全局页面         * @return {void}         */        async replyMessage(ctx) {            const xml = ctx.request.body;            try {                const {                    createTime, msgType, toUserName, toFromName, event, msgContent,                } = await parseStringXml(xml);                let body = '';                if (msgType === 'text') {                    const reply_msg = '如有问题需要咨询,请电话联系0756-3850888;或添加企业QQ:800003850。';                    body = `            <xml>                <ToUserName><![CDATA[${toFromName}]]></ToUserName>                <FromUserName><![CDATA[${toUserName}]]></FromUserName>                <CreateTime>${createTime}</CreateTime>                <MsgType><![CDATA[text]]></MsgType>                <Content><![CDATA[${reply_msg}]]></Content>                <MediaId><![CDATA[media_id]]></MediaId>            </xml>        `;                }                ctx.body = body;            } catch (e) {                console.log(e);            }        }        /**         * 微信登录验证         *         * @param {Object} ctx - egg全局页面         * @return {void}         */        async oauth(ctx) {            const redirect_uri = ctx.query.redirect_uri;            const url = await app.wechat.oauth.getAuthorizeURL(redirect_uri, '', 'snsapi_userinfo');            ctx.redirect(url);        }        /**         * 绑定页面         *         * @param {Object} ctx - egg全局页面         * @return {void}         */        async bind(ctx) {            try {                const user = await app.wechat.oauth.getUser(ctx.session.wechatToken.openid);                const errorMessage = ctx.session.loginError;                // 显示完删除                ctx.session.loginError = null;                // 获取系统维护信息                const maintainData = await ctx.service.maintain.getDataById(1);                const renderData = {                    maintainData,                    maintainConst,                    errorMessage,                    user,                };                await ctx.render('wechat/bind.ejs', renderData);            } catch (e) {                const renderData = {                    status: 1,                    msg: e,                };                await ctx.render('wechat/tips.ejs', renderData);            }        }        async bindwx(ctx) {            try {                const result = await ctx.service.projectAccount.accountCheck(ctx.request.body);                if (!result) {                    throw '用户名或密码错误';                }                if (result === 2) {                    // 查找项目数据                    const projectData = await this.ctx.service.project.getProjectByCode(ctx.request.body.project.toString().trim());                    // 判断是否有设置停用提示,有则展示                    const msg = await ctx.service.projectStopmsg.getMsg(projectData.id);                    throw msg;                }                const accountData = result;                if (accountData.wx_openid || ctx.session.wechatToken.openid === accountData.wx_openid) {                    throw '该账号已经绑定过微信';                }                const wxAccountData = await ctx.service.projectAccount.getDataByCondition({ project_id: accountData.project_id, wx_openid: ctx.session.wechatToken.openid });                if (wxAccountData) {                    throw '该微信号已绑定过本项目账号';                }                const user = await app.wechat.api.getUser(ctx.session.wechatToken.openid);                if (user.subscribe === 0) {                    throw '先关注公众号才能绑定项目';                }                const result2 = await ctx.service.projectAccount.bindWx(accountData.id, ctx.session.wechatToken.openid, user.nickname, user.unionid);                if (!result2) {                    throw '绑定失败';                }                const projectData = await ctx.service.project.getDataById(accountData.project_id);                // 绑定成功通知                const templateId = 'JGJeWU2FT4syWKUE5haEf3iiqaRJ1XrsxY1PKixqLpw';                const url = '';                const msgData = {                    first: {                        value: '您好,纵横云计量与微信绑定成功。',                    },                    keyword1: {                        value: projectData.code,                    },                    keyword2: {                        value: accountData.account,                    },                    keyword3: {                        value: moment(new Date()).format('YYYY-MM-DD'),                    },                    remark: {                        value: '感谢您的使用。',                    },                };                await app.wechat.api.sendTemplate(ctx.session.wechatToken.openid, templateId, url, '', msgData);                const renderData = {                    status: 0,                    msg: '绑定成功',                };                await ctx.render('wechat/tips.ejs', renderData);            } catch (error) {                this.log(error);                ctx.session.loginError = error;                ctx.redirect('/wx/bind');            }        }        // 设置用户微信登录项目,跳转到对应wap页面        async url2wap(ctx) {            try {                if (!ctx.query.project || !ctx.query.url) {                    throw '参数有误';                }                const code = ctx.query.project;                // 查找项目数据                const projectData = await ctx.service.project.getProjectByCode(code.toString().trim());                if (projectData === null) {                    throw '不存在项目数据';                }                const pa = await ctx.service.projectAccount.getDataByCondition({ project_id: projectData.id, wx_openid: ctx.session.wechatToken.openid });                if (!pa) {                    throw '该微信号未绑定此项目';                }                if (pa.enable !== 1) {                    // 判断是否有设置停用提示,有则展示                    const msg = await ctx.service.projectStopmsg.getMsg(projectData.id);                    throw msg;                }                // 设置项目和用户session记录                const result = await ctx.service.projectAccount.accountLogin({ project: projectData, accountData: pa }, 3);                if (!result) {                    throw '登录出错';                }                ctx.redirect(ctx.query.url);            } catch (error) {                const renderData = {                    status: 1,                    msg: error,                };                await ctx.render('wechat/tips.ejs', renderData);            }        }        async project(ctx) {            try {                // const user = await app.wechat.oauth.getUser(ctx.session.wechatToken.openid);                const openid = ctx.session.wechatToken.openid;                // const openid = 'fasdfklahsdklf';                const paList = await ctx.service.projectAccount.getAllDataByCondition({ where: { wx_openid: openid } });                const pidList = ctx.app._.uniq(ctx.app._.map(paList, 'project_id'));                const pList = [];                const redirect_url = ctx.protocol + '://' + ctx.host + '/wap/dashboard';                for (const p of pidList) {                    const pro = await ctx.service.project.getDataById(p);                    pList.push(pro);                }                if (pList.length === 0) {                    throw '该微信号未绑定任何项目';                }                // 获取系统维护信息                const maintainData = await ctx.service.maintain.getDataById(1);                const renderData = {                    maintainData,                    maintainConst,                    // user,                    pList,                    redirect_url,                };                // ctx.body = renderData;                await ctx.render('wechat/project.ejs', renderData);            } catch (e) {                const renderData = {                    status: 1,                    msg: e,                };                await ctx.render('wechat/tips.ejs', renderData);            }        }        async oauthTxt(ctx) {            ctx.body = 't3MkWAMqplVxPjmr';        }        async testwx(ctx) {            try {                const sck = 'https://scn.ink/';                // 微信模板通知                const tender = {                    data: {                        name: 'XXX标段',                    },                    info: {                        deal_info: {                            buildName: 'XX项目',                        },                    },                };                ctx.tender = tender;                const stageInfo = await ctx.service.stage.getDataById(1704);                const shenpiUrl = await ctx.helper.urlToShort(ctx.protocol + '://' + ctx.host + '/wap/tender/1998/stage/' + stageInfo.order);                const wechatData = {                    wap_url: sck + shenpiUrl,                    qi: stageInfo.order,                    status: wxConst.status.success,                    tips: wxConst.tips.success,                    code: 'P1002',                };                // ctx.body = { tender, wechatData };                await ctx.helper.sendWechat(133, smsTypeConst.const.JL, smsTypeConst.judge.result.toString(), wxConst.template.stage, wechatData);                ctx.body = 'success';            } catch (error) {                console.log(error);                ctx.body = error;            }        }        // 企业微信功能        // 回调方法        async command(ctx) {            try {                const msg_signature = ctx.query.msg_signature;                const timestamp = ctx.query.timestamp;                const nonce = ctx.query.nonce;                const echostr = ctx.query.echostr;                const signature = qywxCrypto.getSignature(ctx.app.config.qywx.token, timestamp, nonce, echostr);                if (signature === msg_signature) {                    const aeskey = ctx.app.config.qywx.encodingAESKey;                    const { message } = qywxCrypto.decrypt(aeskey, echostr);                    ctx.body = message;                    // res.send(message);                } else {                    throw '验证失败';                }            } catch (e) {                console.log(e);            }        }        // 获取suite_ticket方法        async postCommand(ctx) {            try {                // ctx.req才能获取到rawbody                const wholeXML = await getRawBody(ctx.req, {                    length: ctx.headers['content-length'],                    limit: '1mb',                    encoding: 'utf-8',                });                const formatJson = await ctx.helper.parseXML(wholeXML);                const messageXML = qywxCrypto.decrypt(ctx.app.config.qywx.encodingAESKey, formatJson.Encrypt);                const callbackDataBody = await ctx.helper.parseXML(messageXML.message);                console.log('CallbackData', callbackDataBody);                const qywx = new wxWork(ctx);                switch (callbackDataBody.InfoType) {                    case 'suite_ticket':                        // 刷新                        console.log('SuiteTicket', callbackDataBody.SuiteTicket);                        await qywx.setSuiteTicket(callbackDataBody.SuiteTicket);                        // await app.redis.set('suite_ticket', callbackDataBody.SuiteTicket, 'EX', 1500);                        break;                    case 'reset_permanent_code':                    case 'create_auth':                        console.log('AuthCode', callbackDataBody.AuthCode);                        await qywx.savePermanentCode(callbackDataBody.AuthCode);                        qywx.setPermanentCode();// 不用马上执行,有执行就行                        break;                    case 'cancel_auth':                        // 企业管理员删除应用                        await ctx.service.wxWork.delCorp(callbackDataBody.AuthCorpId);                        break;                    default:                        break;                }                // 很重要,一定要返回 success 字符串                ctx.body = 'success';            } catch (e) {                console.log(e);            }        }        async oauthWxWorkTxt(ctx) {            ctx.body = 'CZwGPbI7BRGOBUX1';        }        /**         * 企业微信登录验证         *         * @param {Object} ctx - egg全局页面         * @return {void}         */        async workOauth(ctx) {            const corpid = ctx.params.corpid;            const redirect_uri = encodeURIComponent(ctx.query.redirect_uri);            const corpInfo = await ctx.service.wxWork.getDataByCondition({ corpid });            const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${corpid}&redirect_uri=${redirect_uri}&response_type=code&scope=snsapi_privateinfo&state=STATE&agentid=${corpInfo.agentid}#wechat_redirect`;            ctx.redirect(url);        }        async workBind(ctx) {            try {                const qywx = new wxWork(ctx);                const token = await qywx.getCorpAccessToken(ctx.params.corpid);                const user = await qywx.getCorpUser(token, ctx.query.code);                if (!user) {                    throw '获取企业用户信息失败';                }                const errorMessage = ctx.session.loginError;                // 显示完删除                ctx.session.loginError = null;                // 获取系统维护信息                const maintainData = await ctx.service.maintain.getDataById(1);                const renderData = {                    maintainData,                    maintainConst,                    errorMessage,                    user,                    corpid: ctx.params.corpid,                };                await ctx.render('wechat/work_bind.ejs', renderData);            } catch (error) {                console.log(error);                const renderData = {                    status: 1,                    msg: error,                };                await ctx.render('wechat/tips.ejs', renderData);            }        }        async workBindwx(ctx) {            const corpid = ctx.request.body.corpid ? ctx.request.body.corpid : null;            try {                const result = await ctx.service.projectAccount.accountCheck(ctx.request.body);                if (!result) {                    throw '用户名或密码错误';                }                if (result === 2) {                    // 查找项目数据                    const projectData = await this.ctx.service.project.getProjectByCode(ctx.request.body.project.toString().trim());                    // 判断是否有设置停用提示,有则展示                    const msg = await ctx.service.projectStopmsg.getMsg(projectData.id);                    throw msg;                }                const accountData = result;                const qywx_userid = ctx.request.body.userid;                if (!qywx_userid || !corpid) {                    throw '参数有误';                }                if (accountData.qywx_userid || qywx_userid === accountData.qywx_userid) {                    throw '该账号已经绑定过企业微信';                }                const wxAccountData = await ctx.service.projectAccount.getDataByCondition({ project_id: accountData.project_id, qywx_userid });                if (wxAccountData) {                    throw '该企业微信号已绑定过本项目其它账号';                }                const qywx = new wxWork(ctx);                const token = await qywx.getCorpAccessToken(corpid);                const user = await qywx.getCorpUserCommonData(token, qywx_userid, corpid);                if (!user) {                    throw '获取企业用户信息失败';                }                user.avatar = ctx.request.body.avatar !== undefined ? ctx.request.body.avatar : null;                user.gender = ctx.request.body.gender !== undefined ? ctx.request.body.gender : null;                const result2 = await ctx.service.projectAccount.bindWx4Work(accountData.id, corpid, qywx_userid, user);                if (!result2) {                    throw '绑定失败';                }                const projectData = await ctx.service.project.getDataById(accountData.project_id);                const desc = '您好,纵横云计量与企业微信绑定成功。';                const content = [                    {                        keyname: '项目编号',                        value: projectData.code,                    },                    {                        keyname: '账号',                        value: accountData.account,                    },                    {                        keyname: '绑定时间',                        value: moment(new Date()).format('YYYY-MM-DD'),                    },                    {                        keyname: '备注',                        value: '感谢您的使用。',                    },                ];                const url = ctx.protocol + '://' + ctx.host + `/wx/work/${corpid}/project`;                await qywx.sendTemplateCard([qywx_userid], corpid, '账号绑定成功通知', desc, content, url, '登录项目');                const renderData = {                    status: 0,                    msg: '绑定成功',                };                await ctx.render('wechat/tips.ejs', renderData);            } catch (error) {                this.log(error);                ctx.session.loginError = error;                const returnUrl = corpid ? `/wx/work/${corpid}/bind` : '/';                ctx.redirect(returnUrl);            }        }        // 设置用户企业微信登录项目,跳转到对应wap页面        async url2wap4work(ctx) {            try {                if (!ctx.query.project || !ctx.query.url) {                    throw '参数有误';                }                const code = ctx.query.project;                // 查找项目数据                const projectData = await ctx.service.project.getProjectByCode(code.toString().trim());                if (projectData === null) {                    throw '不存在项目数据';                }                const qywx = new wxWork(ctx);                const token = await qywx.getCorpAccessToken(ctx.params.corpid);                const user = await qywx.getCorpUser(token, ctx.query.code);                if (!user) {                    throw '获取企业用户信息失败';                }                const pa = await ctx.service.projectAccount.getDataByCondition({ project_id: projectData.id, qywx_userid: user.userid });                if (!pa) {                    throw '该企业微信号未绑定此项目';                }                if (pa.enable !== 1) {                    // 判断是否有设置停用提示,有则展示                    const msg = await ctx.service.projectStopmsg.getMsg(projectData.id);                    throw msg;                }                // 设置项目和用户session记录                const result = await ctx.service.projectAccount.accountLogin({ project: projectData, accountData: pa }, 3);                if (!result) {                    throw '登录出错';                }                ctx.redirect(ctx.query.url);            } catch (error) {                const renderData = {                    status: 1,                    msg: error,                };                await ctx.render('wechat/tips.ejs', renderData);            }        }        async workProject(ctx) {            try {                // const user = await app.wechat.oauth.getUser(ctx.session.wechatToken.openid);                const qywx = new wxWork(ctx);                const token = await qywx.getCorpAccessToken(ctx.params.corpid);                const user = await qywx.getCorpUser(token, ctx.query.code);                if (!user) {                    throw '获取企业用户信息失败';                }                const paList = await ctx.service.projectAccount.getAllDataByCondition({ where: { qywx_userid: user.userid } });                const pidList = ctx.app._.uniq(ctx.app._.map(paList, 'project_id'));                const pList = [];                const isWap = ctx.helper.isMobile(ctx.request.header['user-agent']) ? '/wap' : '';                const redirect_url = ctx.protocol + '://' + ctx.host + isWap + '/dashboard';                for (const p of pidList) {                    const pro = await ctx.service.project.getDataById(p);                    pList.push(pro);                }                if (pList.length === 0) {                    throw '该企业微信号未绑定任何项目';                }                // 获取系统维护信息                const maintainData = await ctx.service.maintain.getDataById(1);                const renderData = {                    maintainData,                    maintainConst,                    // user,                    pList,                    redirect_url,                    corpid: ctx.params.corpid,                };                // ctx.body = renderData;                await ctx.render('wechat/work_project.ejs', renderData);            } catch (e) {                const renderData = {                    status: 1,                    msg: e,                };                await ctx.render('wechat/tips.ejs', renderData);            }        }        async workTest(ctx) {            try {                // const user = await app.wechat.oauth.getUser(ctx.session.wechatToken.openid);                const qywx = new wxWork(ctx);                const result = await qywx.getUserList(ctx.params.corpid);                ctx.body = result;            } catch (e) {                const renderData = {                    status: 1,                    msg: e,                };                await ctx.render('wechat/tips.ejs', renderData);            }        }        async tips(ctx) {            const renderData = {                status: 0,                msg: ctx.query.msg,            };            await ctx.render('wechat/tips.ejs', renderData);        }    }    return WechatController;};
 |