Authored by 陈峰

Merge branch 'feature/weiBinding' into 'gray'

Feature/wei binding



See merge request !234
@@ -12,6 +12,8 @@ const RegService = require('../models/reg-service'); @@ -12,6 +12,8 @@ const RegService = require('../models/reg-service');
12 const BindService = require('../models/bind-service'); 12 const BindService = require('../models/bind-service');
13 const AuthHelper = require('../models/auth-helper'); 13 const AuthHelper = require('../models/auth-helper');
14 const _ = require('lodash'); 14 const _ = require('lodash');
  15 +const config = global.yoho.config;
  16 +const moment = require('moment');
15 17
16 const Sources = { 18 const Sources = {
17 qq: 'QQ', 19 qq: 'QQ',
@@ -87,8 +89,14 @@ const bind = { @@ -87,8 +89,14 @@ const bind = {
87 let openId = req.body.openId; 89 let openId = req.body.openId;
88 let areaCode = req.body.areaCode || '86'; 90 let areaCode = req.body.areaCode || '86';
89 let sourceType = req.body.sourceType; 91 let sourceType = req.body.sourceType;
  92 + let verify = req.body.verify || '';
  93 + let testCode = req.body.yohobuy;
90 94
91 if (_.isNumber(parseInt(phoneNum, 0)) && openId && areaCode && sourceType) { 95 if (_.isNumber(parseInt(phoneNum, 0)) && openId && areaCode && sourceType) {
  96 + if (verify) {
  97 + let captcha = _.get(req, 'session.captcha');
  98 +
  99 + if ((captcha && verify.toString() === captcha) || (testCode === config.testCode)) {
92 BindService.bindCheck(phoneNum, openId, sourceType, areaCode).then(result => { 100 BindService.bindCheck(phoneNum, openId, sourceType, areaCode).then(result => {
93 let data = { 101 let data = {
94 code: result.code, 102 code: result.code,
@@ -107,6 +115,9 @@ const bind = { @@ -107,6 +115,9 @@ const bind = {
107 115
108 data.data.isReg = result.data.is_register; 116 data.data.isReg = result.data.is_register;
109 data.data.next = nextUrl; 117 data.data.next = nextUrl;
  118 +
  119 + _.set(req.session, 'bind.area', areaCode);
  120 + _.set(req.session, 'bind.phoneNum', phoneNum);
110 } else { 121 } else {
111 data.data = result.data; 122 data.data = result.data;
112 } 123 }
@@ -114,6 +125,22 @@ const bind = { @@ -114,6 +125,22 @@ const bind = {
114 res.json(data); 125 res.json(data);
115 }).catch(next); 126 }).catch(next);
116 } else { 127 } else {
  128 + let jsonData = {
  129 + code: 400,
  130 + message: '请将图片旋转到正确位置'
  131 + };
  132 +
  133 + if (req.session.captchaValidCount === 0) {
  134 + req.session.captcha = null; // 验证码 用过就扔
  135 + jsonData.changeCaptcha = true;
  136 + }
  137 +
  138 + return res.json(jsonData);
  139 + }
  140 +
  141 + _.set(req.session, 'captcha', null);
  142 + }
  143 + } else {
117 res.json({ 144 res.json({
118 code: 400, 145 code: 400,
119 message: '', 146 message: '',
@@ -122,13 +149,62 @@ const bind = { @@ -122,13 +149,62 @@ const bind = {
122 } 149 }
123 }, 150 },
124 151
  152 + // 防刷
  153 + sendBefore: (req, res, next) => {
  154 + let count = _.get(req.session, 'bind.count');
  155 + let interval = _.get(req.session, 'bind.interval');
  156 +
  157 + let now = Date.now();
  158 +
  159 + // // 重发次数用完了, 会冻结5min
  160 + // // 1. 过了冻结期, count 重设为 5次
  161 + // // 2. 没过冻结期, end
  162 + // // 没有用完, 判断是否请求太频繁
  163 + let during = moment.duration(interval - now, 'ms').minutes();
  164 + let message = `请${during}分钟后再试`;
  165 +
  166 + if (!count) {
  167 + if (interval > now) {
  168 + return res.json({
  169 + code: 400,
  170 + message: message,
  171 + during: Math.ceil((interval - now) / 1000)
  172 + });
  173 + } else {
  174 + _.set(req.session, 'bind.count', 5);
  175 + }
  176 + } else if (interval > now) {
  177 + return res.json({
  178 + code: 429,
  179 + message: message
  180 + });
  181 + }
  182 +
  183 + next();
  184 + },
  185 +
125 sendBindMsg: (req, res, next) => { 186 sendBindMsg: (req, res, next) => {
126 - let phoneNum = req.body.phoneNum;  
127 - let areaCode = req.body.areaCode; 187 + let phoneNum = _.get(req.session, 'bind.phoneNum');
  188 + let areaCode = _.get(req.session, 'bind.area');
128 189
129 if (req.xhr && _.isNumber(parseInt(phoneNum, 0)) && areaCode) { 190 if (req.xhr && _.isNumber(parseInt(phoneNum, 0)) && areaCode) {
130 BindService.sendBindMsg(areaCode, phoneNum).then(result => { 191 BindService.sendBindMsg(areaCode, phoneNum).then(result => {
131 if (result && result.code) { 192 if (result && result.code) {
  193 +
  194 + if (result.code === 200) {
  195 +
  196 + _.set(req.session, 'bind.area', areaCode);
  197 + _.set(req.session, 'bind.phoneNum', phoneNum);
  198 +
  199 + --req.session.bind.count;
  200 +
  201 + if (!req.session.bind.count) {
  202 + _.set(req.session, 'bind.interval', Date.now() + 5 * 60 * 1000);
  203 + } else {
  204 + _.set(req.session, 'bind.interval', Date.now() + 60 * 1000);
  205 + }
  206 + }
  207 +
132 res.json(result); 208 res.json(result);
133 } else { 209 } else {
134 res.json({ code: 400, message: '', data: '' }); 210 res.json({ code: 400, message: '', data: '' });
@@ -77,7 +77,9 @@ router.get('/login/alipay/callback', login.alipay.callback); @@ -77,7 +77,9 @@ router.get('/login/alipay/callback', login.alipay.callback);
77 router.get('/passport/bind/index', bind.indexPage); 77 router.get('/passport/bind/index', bind.indexPage);
78 router.post('/passport/bind/bindCheck', bind.bindCheck); 78 router.post('/passport/bind/bindCheck', bind.bindCheck);
79 router.get('/passport/bind/code', bind.codePage); 79 router.get('/passport/bind/code', bind.codePage);
80 -router.post('/passport/bind/sendBindMsg', bind.sendBindMsg); 80 +router.post('/passport/bind/sendBindMsg',
  81 + bind.sendBefore,
  82 + bind.sendBindMsg);
81 router.post('/passport/bind/bindMobile', bind.bindMobile); 83 router.post('/passport/bind/bindMobile', bind.bindMobile);
82 84
83 router.post('/passport/bind/relateMobile', bind.relateMobile); 85 router.post('/passport/bind/relateMobile', bind.relateMobile);
@@ -14,6 +14,13 @@ @@ -14,6 +14,13 @@
14 <span id="area-code" class="area-code">{{areaCode}}</span> 14 <span id="area-code" class="area-code">{{areaCode}}</span>
15 <input id="phone-num" class="input phone-num" type="text" placeholder="手机号"> 15 <input id="phone-num" class="input phone-num" type="text" placeholder="手机号">
16 </div> 16 </div>
  17 +
  18 + {{!--图片验证 start--}}
  19 + <div id="js-img-check">
  20 + <input type="hidden" name="captsrc" value="{{captsrc}}">
  21 + </div>
  22 + {{!--图片验证 end--}}
  23 +
17 <span id="btn-next" class="btn btn-next disable row">发送验证码</span> 24 <span id="btn-next" class="btn btn-next disable row">发送验证码</span>
18 25
19 {{#if isWechatLogin}} 26 {{#if isWechatLogin}}
1 { 1 {
2 "name": "m-yohobuy-node", 2 "name": "m-yohobuy-node",
3 - "version": "93.4.10", 3 + "version": "93.4.11",
4 "private": true, 4 "private": true,
5 "description": "A New Yohobuy Project With Express", 5 "description": "A New Yohobuy Project With Express",
6 "repository": { 6 "repository": {
@@ -24,6 +24,17 @@ var requested = false; @@ -24,6 +24,17 @@ var requested = false;
24 24
25 require('../../common'); 25 require('../../common');
26 26
  27 +var ImgCheck = require('plugin/img-check');
  28 +
  29 +var imgCheck = new ImgCheck('#js-img-check', {
  30 + useREM: {
  31 + rootFontSize: 40,
  32 + picWidth: 150
  33 + }
  34 +});
  35 +
  36 +imgCheck.init();
  37 +
27 function nextStep(url, mobileNo, areaCode) { 38 function nextStep(url, mobileNo, areaCode) {
28 if (requested) { 39 if (requested) {
29 return false; 40 return false;
@@ -31,7 +42,6 @@ function nextStep(url, mobileNo, areaCode) { @@ -31,7 +42,6 @@ function nextStep(url, mobileNo, areaCode) {
31 42
32 requested = true; 43 requested = true;
33 $btnNext.addClass('disable').html('绑定中...'); 44 $btnNext.addClass('disable').html('绑定中...');
34 -  
35 $.ajax({ 45 $.ajax({
36 type: 'POST', 46 type: 'POST',
37 url: '/passport/bind/sendBindMsg', 47 url: '/passport/bind/sendBindMsg',
@@ -85,7 +95,8 @@ $btnNext.on('touchstart', function() { @@ -85,7 +95,8 @@ $btnNext.on('touchstart', function() {
85 openId = trim($openId.val()), 95 openId = trim($openId.val()),
86 nickname = trim($nickname.val()), 96 nickname = trim($nickname.val()),
87 sourceType = trim($sourceType.val()), 97 sourceType = trim($sourceType.val()),
88 - areaCode = $countrySelect.val(); 98 + areaCode = $countrySelect.val(),
  99 + verify = trim(imgCheck.getResults());
89 100
90 if ($btnNext.hasClass('disable')) { 101 if ($btnNext.hasClass('disable')) {
91 return; 102 return;
@@ -100,12 +111,11 @@ $btnNext.on('touchstart', function() { @@ -100,12 +111,11 @@ $btnNext.on('touchstart', function() {
100 phoneNum: pn, 111 phoneNum: pn,
101 openId: openId, 112 openId: openId,
102 sourceType: sourceType, 113 sourceType: sourceType,
103 - nickname: nickname 114 + nickname: nickname,
  115 + verify: verify
104 }, 116 },
105 success: function(res) { 117 success: function(res) {
106 118
107 - // console.log(res);  
108 -  
109 // res : { 119 // res : {
110 // code: 'xxx', 120 // code: 'xxx',
111 // data: { 121 // data: {
@@ -5,6 +5,8 @@ @@ -5,6 +5,8 @@
5 */ 5 */
6 var $ = require('yoho-jquery'); 6 var $ = require('yoho-jquery');
7 7
  8 +require('js/common');
  9 +
8 module.exports = function(useInRegister, useForBind, useForRelate) { 10 module.exports = function(useInRegister, useForBind, useForRelate) {
9 var $captcha = $('#captcha'), 11 var $captcha = $('#captcha'),
10 $btnNext = $('#btn-next'), 12 $btnNext = $('#btn-next'),
@@ -79,8 +81,8 @@ module.exports = function(useInRegister, useForBind, useForRelate) { @@ -79,8 +81,8 @@ module.exports = function(useInRegister, useForBind, useForRelate) {
79 }); 81 });
80 } 82 }
81 83
82 - function countDown() {  
83 - var count = 59, 84 + function countDown(during) {
  85 + var count = during || 59,
84 itime; 86 itime;
85 87
86 itime = setInterval(function() { 88 itime = setInterval(function() {
@@ -89,6 +91,11 @@ module.exports = function(useInRegister, useForBind, useForRelate) { @@ -89,6 +91,11 @@ module.exports = function(useInRegister, useForBind, useForRelate) {
89 clearInterval(itime); 91 clearInterval(itime);
90 } else { 92 } else {
91 $captchaTip.text('重新发送 (' + count-- + '秒)'); 93 $captchaTip.text('重新发送 (' + count-- + '秒)');
  94 + window.setCookie('count', count);
  95 +
  96 + if (during && parseInt(during) !== 0) {
  97 + $captchaTip.addClass('disable');
  98 + }
92 } 99 }
93 }, 1000); 100 }, 1000);
94 } 101 }
@@ -121,6 +128,7 @@ module.exports = function(useInRegister, useForBind, useForRelate) { @@ -121,6 +128,7 @@ module.exports = function(useInRegister, useForBind, useForRelate) {
121 $captchaTip.text('重发验证码 (60秒)').addClass('disable'); 128 $captchaTip.text('重发验证码 (60秒)').addClass('disable');
122 countDown(); 129 countDown();
123 } else { 130 } else {
  131 + data.during && countDown(data.during);
124 132
125 // 验证码不正确,显示提示 133 // 验证码不正确,显示提示
126 showErrTip(data.message); 134 showErrTip(data.message);
@@ -148,5 +156,10 @@ module.exports = function(useInRegister, useForBind, useForRelate) { @@ -148,5 +156,10 @@ module.exports = function(useInRegister, useForBind, useForRelate) {
148 } 156 }
149 }); 157 });
150 158
  159 + if (window.cookie('count') && parseInt(window.cookie('count')) > 0) {
  160 + countDown(window.cookie('count'));
  161 + } else {
151 countDown(); 162 countDown();
  163 + }
152 }; 164 };
  165 +