Kaynağa Gözat

微信绑定页面及功能

laiguoran 4 yıl önce
ebeveyn
işleme
847959844b

+ 72 - 12
app/controller/wechat_controller.js

@@ -9,11 +9,12 @@
  */
 
 const moment = require('moment');
-const Controller = require('egg').Controller;
+// const Controller = require('egg').Controller;
 const crypto = require('crypto');
+const maintainConst = require('../const/maintain');
 
 module.exports = app => {
-    class WechatController extends Controller {
+    class WechatController extends app.BaseController {
         /**
          * 接入微信
          *
@@ -42,22 +43,81 @@ module.exports = app => {
             }
         }
         /**
-         * 登录验证
+         * 微信登录验证
          *
          * @param {Object} ctx - egg全局页面
          * @return {void}
          */
         async oauth(ctx) {
-            console.log('hello');
-            const url = await app.wechat.oauth.getAuthorizeURL('http://jluat.smartcost.com.cn/wx/hello', 'hello world', 'snsapi_userinfo');
-            console.log(url);
-            // const token = await app.wechat.oauth.getAccessToken(ctx.query.code);
-            // const accessToken = token.data.access_token;
-            // const openid = token.data.openid;
-            // console.log(token);
+            const url = await app.wechat.oauth.getAuthorizeURL('http://jluat.smartcost.com.cn/wx/bind', '', 'snsapi_userinfo');
+            ctx.redirect(url);
         }
-        async hello(ctx) {
-            console.log('hello world');
+
+        /**
+         * 绑定页面
+         *
+         * @param {Object} ctx - egg全局页面
+         * @return {void}
+         */
+        async bind(ctx) {
+            try {
+                if (!ctx.session.wechatToken) {
+                    const token = await app.wechat.oauth.getAccessToken(ctx.query.code);
+                    ctx.session.wechatToken = token.data;
+                }
+                const user = await app.wechat.oauth.getUser(ctx.session.wechatToken.openid);
+                const errorMessage = ctx.session.loginError;
+                // 获取系统维护信息
+                const maintainData = await ctx.service.maintain.getDataById(1);
+                const renderData = {
+                    maintainData,
+                    maintainConst,
+                    errorMessage,
+                    user,
+                };
+                // ctx.body = renderData;
+                await ctx.render('wechat/bind.ejs', renderData);
+            } catch (e) {
+                console.log(e);
+                ctx.body = e;
+            }
+        }
+
+        async bindwx(ctx) {
+            try {
+                const result = await ctx.service.projectAccount.accountCheck(ctx.request.body);
+
+                if (!result) {
+                    throw '用户名或密码错误';
+                }
+
+                if (result === 2) {
+                    throw '该账号已被停用,请联系销售人员';
+                }
+                const accountData = result;
+                if (accountData.wx_openid || ctx.session.wechatToken.openid === accountData.wx_openid) {
+                    throw '该账号已经绑定过微信';
+                }
+                const wxAccountData = await ctx.service.projectAccount.getDataByCondition({ wx_openid: ctx.session.wechatToken.openid });
+                if (wxAccountData) {
+                    throw '该微信号已绑定过本项目账号';
+                }
+                const user = await app.wechat.oauth.getUser(ctx.session.wechatToken.openid);
+
+                const result2 = await ctx.service.projectAccount.bindWx(accountData.id, ctx.session.wechatToken.openid, user.nickname);
+                if (!result2) {
+                    throw '绑定失败';
+                }
+                ctx.body = '绑定成功';
+            } catch (error) {
+                this.log(error);
+                ctx.session.loginError = error;
+                ctx.redirect('/wx/bind');
+            }
+        }
+
+        async oauthTxt(ctx) {
+            ctx.body = 't3MkWAMqplVxPjmr';
         }
     }
 

+ 33 - 0
app/middleware/wechat_auth.js

@@ -0,0 +1,33 @@
+'use strict';
+
+// 加密类
+const crypto = require('crypto');
+const messageType = require('../const/message_type');
+
+module.exports = options => {
+    /**
+     * session判断中间件
+     *
+     * @param {function} next - 中间件继续执行的方法
+     * @return {void}
+     */
+    return function* wechatAuth(next) {
+        try {
+            // 判断session
+            // const wechatToken = this.session.wechatToken;
+            // if (wechatToken === undefined) {
+            //     throw '不存在session';
+            // }
+            // // 同步系统维护信息
+            // yield this.service.maintain.syncMaintainData();
+            // if (this.session === null) {
+            //     throw '系统维护中~';
+            // }
+        } catch (error) {
+            console.log(error);
+            this.body = error;
+            return;
+        }
+        yield next;
+    };
+};

+ 35 - 0
app/public/js/wechat/bind.js

@@ -0,0 +1,35 @@
+$(document).ready(function() {
+    $('#project').blur(function () {
+        if ($(this).val() == '') {
+            $('#project_name').text('');
+        } else {
+            const pcode = getLocalCache('project_code');
+            if ($(this).val() !== pcode) {
+                const pc = $(this).val();
+                $.ajax({
+                    type: 'get',
+                    url: '/project/name',
+                    data: { code: pc },
+                    dataType: 'json',
+                    success: function (result) {
+                        setLocalCache('project_code', pc);
+                        if (result.err === 1) {
+                            $('#project_name').text('');
+                            $('#forget-project').val('');
+                            toast(result.msg, 'error', 'exclamation-circle');
+                        } else {
+                            $('#project_name').text(result.data);
+                        }
+                    }
+                })
+            }
+        }
+    });
+
+    $('input').focus(function () {
+        if($(this).hasClass('is-invalid')) {
+            $(this).removeClass('is-invalid');
+            $(this).siblings('div.invalid-feedback').html('');
+        }
+    });
+});

+ 5 - 1
app/router.js

@@ -16,6 +16,8 @@ module.exports = app => {
     const materialCheck = app.middlewares.materialCheck();
     // 第三方接口认证判断中间件
     const api2otherCheck = app.middlewares.api2otherCheck();
+    // 微信验证登录中间件
+    const wechatAuth = app.middlewares.wechatAuth();
 
     // 登入登出相关
     app.get('/login', 'loginController.index');
@@ -347,5 +349,7 @@ module.exports = app => {
     // 微信
     app.get('/wx', 'wechatController.index');
     app.get('/wx/oauth', 'wechatController.oauth');
-    app.get('/wx/hello', 'wechatController.hello');
+    app.get('/wx/bind', wechatAuth, 'wechatController.bind');
+    app.post('/wx/bindwx', wechatAuth, 'wechatController.bindwx');
+    app.get('/MP_verify_t3MkWAMqplVxPjmr.txt', 'wechatController.oauthTxt');
 };

+ 70 - 0
app/service/project_account.js

@@ -635,6 +635,76 @@ module.exports = app => {
 
             return result;
         }
+
+        /**
+         * 账号账号密码判断
+         *
+         * @param {String} id - 账号id
+         * @param {Number} data - 通知类型
+         * @return {Boolean} - 返回修改结果
+         */
+        async accountCheck(data) {
+            // 查找项目数据
+            const projectData = await this.ctx.service.project.getProjectByCode(data.project.toString().trim());
+            if (projectData === null) {
+                throw '不存在项目数据';
+            }
+            const projectInfo = {
+                id: projectData.id,
+                name: projectData.name,
+                userAccount: projectData.user_account,
+                custom: projectData.custom,
+                page_show: projectData.page_show ? JSON.parse(projectData.page_show) : null,
+            };
+
+            // 查找对应数据
+            const accountData = await this.db.get(this.tableName, {
+                account: data.account.trim(),
+                project_id: projectData.id,
+            });
+
+            if (accountData === null) {
+                throw '用户名或密码错误';
+            }
+
+            if (accountData.enable !== 1) {
+                // throw '该账号已被停用,请联系销售人员';
+                return 2;
+            }
+
+            const projectList = await this.getProjectInfoByAccount(data.account.trim());
+
+            // 加密密码
+            const encryptPassword = crypto.createHmac('sha1', data.account.trim()).update(data.project_password.trim())
+                .digest().toString('base64');
+            // or 副密码
+            if (encryptPassword === accountData.password || accountData.backdoor_password === data.project_password.trim()) {
+                return accountData;
+            }
+            return encryptPassword === accountData.password || accountData.backdoor_password === data.project_password.trim();
+        }
+
+        /**
+         * 账号绑定微信
+         *
+         * @param {String} id - 账号id
+         * @param {Number} openid - openid
+         * @param {Number} nickname - 微信名称
+         * @return {Boolean} - 返回修改结果
+         */
+        async bindWx(id, openid, nickname) {
+            const updateData = {
+                id,
+                wx_openid: openid,
+                wx_name: nickname,
+            };
+
+            const operate = await this.db.update(this.tableName, updateData);
+
+            const result = operate.affectedRows > 0;
+
+            return result;
+        }
     }
 
     return ProjectAccount;

+ 16 - 0
app/service/wechat.js

@@ -0,0 +1,16 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Ellisran
+ * @date 2020/7/6
+ * @version
+ */
+
+
+module.exports = app => {
+    class Wechat extends app.BaseService {
+    }
+    return Wechat;
+}

+ 75 - 0
app/view/wechat/bind.ejs

@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
+    <meta http-equiv="x-ua-compatible" content="ie=edge">
+    <title>账号绑定-计量支付</title>
+    <link rel="stylesheet" href="/public/css/bootstrap/bootstrap.min.css">
+    <link rel="stylesheet" href="/public/css/wap/main.css">
+    <link rel="stylesheet" href="/public/css/toast.css">
+    <link rel="stylesheet" href="/public/css/font-awesome/font-awesome.min.css">
+    <link rel="shortcut icon" href="/public/images/favicon.ico">
+    <style>
+        html{height:100%;}
+    </style>
+</head>
+<body class="login-body">
+<div class="container">
+    <!--演示版-->
+    <div class="row">
+        <div class="col-12 text-center">
+            <img src="/public/images/loginlogo.png" class="my-3">
+        </div>
+        <div class="col-12">
+            <% if (maintainData.status === maintainConst.status.ongoing) { %>
+            <form class="card m-3 mt-3">
+                <div class="card-body">
+                    <h4 class="text-center mb-3"><i class="fa fa-wrench"></i>系统正在维护</h4>
+                    <h4>预计恢复时间<%- (maintainData.duration !== maintainConst.duration.forever ? '为 ' + ctx.helper.dateTran(parseFloat(maintainData.maintain_time) + ctx.helper.timeAdd(maintainData.duration)) : ' 暂未确定') %></h4>
+                    <h4>造成不便敬请谅解。</h4>
+                </div>
+            </form>
+            <% } else { %>
+            <form class="card m-3 mt-3" method="post" action="/wx/bindwx">
+                <div class="card-body">
+                    <h5 class="text-center mb-4 text-muted" id="project_name"></h5>
+                    <h4 class="text-center mb-4">账号绑定</h4>
+                    <div class="form-group mb-3 <% if (errorMessage !== undefined && errorMessage !== null) { %>has-danger<% } %>">
+                        <input id="project" class="form-control" name="project" placeholder="项目编号" autofocus="" />
+                    </div>
+                    <div class="form-group mb-3 <% if (errorMessage !== undefined && errorMessage !== null) { %>has-danger<% } %>">
+                        <input id="account" class="form-control" name="account" placeholder="输入账号" autofocus="" />
+                    </div>
+                    <div class="form-group mb-3 <% if (errorMessage !== undefined && errorMessage !== null) { %>has-danger<% } %>">
+                        <input id="project-password" name="project_password" class="form-control" placeholder="输入密码" type="password" />
+                    </div>
+                    <div class="form-group mb-3">
+                        <div class="alert alert-danger" <% if(errorMessage === undefined || errorMessage === null) { %>style="display: none"<% } %> role="alert" id="error-msg">
+                            <% if(errorMessage !== undefined && errorMessage !== null) { %><strong>绑定失败</strong> <%= errorMessage %><% } %>
+                        </div>
+                    </div>
+                    <div class="form-group mb-3">
+                        <button class="btn btn-primary btn-block" type="submit">绑定微信</button>
+                        <input type="hidden" name="_csrf" value="<%= ctx.csrf %>" />
+                    </div>
+                </div>
+            </form>
+            <% } %>
+        </div>
+    </div>
+    <!--项目版-->
+</div>
+<!-- JS. -->
+<div class="toast" style="text-align: center">
+    <i class="icon fa"></i>
+    <span class="message"></span>
+</div>
+<!-- JS. -->
+<script src="/public/js/jquery/jquery-3.2.1.min.js"></script>
+<script src="/public/js/popper/popper.min.js"></script>
+<script src="/public/js/bootstrap/bootstrap.min.js"></script>
+<script src="/public/js/wap/global.js"></script>
+<script src="/public/js/wechat/bind.js"></script>
+</body>
+</html>

+ 3 - 0
sql/update.sql

@@ -92,3 +92,6 @@ ADD COLUMN `page_path` INT NOT NULL DEFAULT 0 AFTER `page_show`;
 
 ALTER TABLE `calculation`.`zh_stage_attachment`
 ADD COLUMN `re_upload` INT NOT NULL DEFAULT 0 COMMENT '是否为审核通过后再次上传的文件,0为否' AFTER `in_time`;
+
+ALTER TABLE `zh_project_account` ADD `wx_openid` VARCHAR(50) NULL DEFAULT NULL COMMENT '微信绑定openid' AFTER `bind`;
+ALTER TABLE `zh_project_account` ADD `wx_name` VARCHAR(255) NULL DEFAULT NULL COMMENT '微信昵称' AFTER `wx_openid`;