Merge branch 'feature/captcha'
Showing
27 changed files
with
532 additions
and
188 deletions
@@ -24,7 +24,10 @@ const favicon = require('serve-favicon'); | @@ -24,7 +24,10 @@ const favicon = require('serve-favicon'); | ||
24 | const uuid = require('uuid'); | 24 | const uuid = require('uuid'); |
25 | 25 | ||
26 | const pkg = require('./package.json'); | 26 | const pkg = require('./package.json'); |
27 | -const session = require('client-sessions'); | 27 | +const cookieSession = require('client-sessions'); |
28 | +const memcachedSession = require('yoho-express-session'); | ||
29 | +const memcached = require('connect-memcached'); | ||
30 | +const MemcachedStore = memcached(memcachedSession); | ||
28 | const _ = require('lodash'); | 31 | const _ = require('lodash'); |
29 | 32 | ||
30 | const app = express(); | 33 | const app = express(); |
@@ -73,25 +76,63 @@ app.use(bodyParser.urlencoded({ | @@ -73,25 +76,63 @@ app.use(bodyParser.urlencoded({ | ||
73 | app.use(cookieParser()); | 76 | app.use(cookieParser()); |
74 | app.use(compression()); | 77 | app.use(compression()); |
75 | 78 | ||
76 | -app.use(session({ | ||
77 | - requestKey: 'session', | 79 | +app.use(memcachedSession({ |
80 | + proxy: true, | ||
81 | + resave: false, | ||
82 | + saveUninitialized: true, | ||
83 | + unset: 'destroy', | ||
84 | + secret: '82dd7e724f2c6870472c89dfa43cf48d', | ||
85 | + name: 'yohobuy_session', | ||
86 | + cookie: { | ||
87 | + domain: 'yohobuy.com', | ||
88 | + httpOnly: false | ||
89 | + }, | ||
90 | + store: new MemcachedStore({ | ||
91 | + hosts: config.memcache.session, | ||
92 | + prefix: 'yohobuy_session:', | ||
93 | + reconnect: 5000, | ||
94 | + timeout: 1000, | ||
95 | + retries: 0 | ||
96 | + }) | ||
97 | +})); | ||
98 | + | ||
99 | +app.use(cookieSession({ | ||
100 | + requestKey: 'session2', | ||
78 | cookieName: 'yohobuy_session_cookie', | 101 | cookieName: 'yohobuy_session_cookie', |
79 | secret: '82dd7e724f2c6870472c89dfa43cf48d', | 102 | secret: '82dd7e724f2c6870472c89dfa43cf48d', |
80 | domain: config.cookieDomain | 103 | domain: config.cookieDomain |
81 | })); | 104 | })); |
82 | 105 | ||
83 | app.use((req, res, next) => { | 106 | app.use((req, res, next) => { |
84 | - req.user = {}; // 全局的用户数据 | ||
85 | - req.yoho = {}; // req和res绑定yoho对象,用于传递全局数据, 如req.yoho.channel等 | ||
86 | - req.app.locals.wap = app.locals.wap; // zookeper对象赋值 | ||
87 | - if (!req.session) { | ||
88 | - req.session = {}; | 107 | + if (req.session) { |
108 | + let sessionKeys = Object.keys(req.session || {}); | ||
109 | + let backSessionKeys = Object.keys(req.session2.sessionBack || {}); | ||
110 | + | ||
111 | + if (backSessionKeys.length > sessionKeys.length) { | ||
112 | + let differences = _.difference(backSessionKeys, sessionKeys); | ||
113 | + | ||
114 | + _.forEach(differences, d => { | ||
115 | + req.session[d] = req.session2.sessionBack[d]; | ||
116 | + }); | ||
117 | + } | ||
118 | + req.session2.sessionBack = req.session; | ||
119 | + } else { | ||
120 | + req.session = new memcachedSession.Session(req); | ||
121 | + req.session = _.assign(req.session, req.session2.sessionBack); | ||
89 | } | 122 | } |
90 | - if (!req.session.id) { | ||
91 | - req.session.id = uuid.v4(); | 123 | + |
124 | + if (!req.sessionID) { | ||
125 | + req.sessionID = uuid.v4(); | ||
92 | } | 126 | } |
93 | 127 | ||
94 | - req.sessionID = req.session.id; | 128 | + next(); |
129 | +}); | ||
130 | + | ||
131 | + | ||
132 | +app.use((req, res, next) => { | ||
133 | + req.user = {}; // 全局的用户数据 | ||
134 | + req.yoho = {}; // req和res绑定yoho对象,用于传递全局数据, 如req.yoho.channel等 | ||
135 | + req.app.locals.wap = app.locals.wap; // zookeper对象赋值 | ||
95 | 136 | ||
96 | next(); | 137 | next(); |
97 | }); | 138 | }); |
@@ -8,6 +8,7 @@ | @@ -8,6 +8,7 @@ | ||
8 | const _ = require('lodash'); | 8 | const _ = require('lodash'); |
9 | 9 | ||
10 | const helpers = global.yoho.helpers; | 10 | const helpers = global.yoho.helpers; |
11 | +const config = global.yoho.config; | ||
11 | 12 | ||
12 | const service = require('../models/back-service'); | 13 | const service = require('../models/back-service'); |
13 | const captchaService = require('../models/captcha-service'); | 14 | const captchaService = require('../models/captcha-service'); |
@@ -139,9 +140,16 @@ const setNewPasswordByEmailAPI = (req, res) => { | @@ -139,9 +140,16 @@ const setNewPasswordByEmailAPI = (req, res) => { | ||
139 | * 找回密码页面-通过手机号 | 140 | * 找回密码页面-通过手机号 |
140 | */ | 141 | */ |
141 | const indexMobilePage = (req, res, next) => { | 142 | const indexMobilePage = (req, res, next) => { |
143 | + _.set(req.session, 'backupCaptch.verifyResult', false); | ||
144 | + | ||
145 | + if (req.session.captchaValidCount == null) { // eslint-disable-line | ||
146 | + req.session.captchaValidCount = 5; | ||
147 | + } | ||
148 | + | ||
142 | service.getAreaDataAsync() | 149 | service.getAreaDataAsync() |
143 | .then(result => { | 150 | .then(result => { |
144 | res.render('back/mobile', Object.assign({ | 151 | res.render('back/mobile', Object.assign({ |
152 | + width750: true, | ||
145 | module: 'passport', | 153 | module: 'passport', |
146 | page: 'back-mobile', | 154 | page: 'back-mobile', |
147 | title: '找回密码-通过手机号' | 155 | title: '找回密码-通过手机号' |
@@ -189,6 +197,7 @@ const sendCodeToMobileAPI = (req, res, next) => { | @@ -189,6 +197,7 @@ const sendCodeToMobileAPI = (req, res, next) => { | ||
189 | let verifyCode = req.body.verifyCode || ''; | 197 | let verifyCode = req.body.verifyCode || ''; |
190 | let phoneNum = req.body.phoneNum || ''; | 198 | let phoneNum = req.body.phoneNum || ''; |
191 | let areaCode = req.body.areaCode || '86'; | 199 | let areaCode = req.body.areaCode || '86'; |
200 | + let testCode = req.body.yohobuy; | ||
192 | 201 | ||
193 | /* 如果设置了冻结时间,验证 */ | 202 | /* 如果设置了冻结时间,验证 */ |
194 | if (_.has(req.session, 'backupCaptch.timeout')) { | 203 | if (_.has(req.session, 'backupCaptch.timeout')) { |
@@ -203,32 +212,35 @@ const sendCodeToMobileAPI = (req, res, next) => { | @@ -203,32 +212,35 @@ const sendCodeToMobileAPI = (req, res, next) => { | ||
203 | } | 212 | } |
204 | } | 213 | } |
205 | 214 | ||
206 | - /* 如果设置了验证次数,验证是否合法,验证次数减 1;没有,设置验证次数 */ | ||
207 | - if (_.has(req.session, 'backupCaptch.useTime')) { | ||
208 | - if (parseInt(req.session.backupCaptch.useTime, 10) <= 0) { | 215 | + let errorCount = _.get(req.session, 'captchaValidCount', 4); // 初始1次 + 后续4次, 同一个验证码 共5次 |
209 | 216 | ||
210 | - /* 如果超过验证次数,冻结 5 分钟,更新验证次数 */ | ||
211 | - req.session.backupCaptch.timeout = Date.now() + 5 * 60 * 1000; | ||
212 | - req.session.backupCaptch.useTime = 5; | ||
213 | - return res.json({ | ||
214 | - code: 401, | ||
215 | - message: '请5分钟后尝试!' | ||
216 | - }); | ||
217 | - } | ||
218 | - req.session.backupCaptch.useTime = req.session.backupCaptch.useTime - 1; | 217 | + if (!errorCount) { |
218 | + _.set(req.session, 'captchaValidCount', 4); | ||
219 | } else { | 219 | } else { |
220 | - req.session.backupCaptch.useTime = 5; | 220 | + --req.session.captchaValidCount; |
221 | } | 221 | } |
222 | 222 | ||
223 | if (verifyCode) { | 223 | if (verifyCode) { |
224 | - if (verifyCode.toString() === _.get(req, 'session.backupCaptch.code', '').toString()) { | 224 | + let captcha = _.get(req, 'session.captcha'); |
225 | + | ||
226 | + if ((captcha && verifyCode.toString() === captcha) || (testCode === config.testCode)) { | ||
225 | req.session.backupCaptch.verifyResult = true; | 227 | req.session.backupCaptch.verifyResult = true; |
226 | } else { | 228 | } else { |
227 | - return res.json({ | 229 | + let jsonData = { |
228 | code: 400, | 230 | code: 400, |
229 | - message: '验证码输入错误' | ||
230 | - }); | 231 | + message: '请将图片旋转到正确位置' |
232 | + }; | ||
233 | + | ||
234 | + if (req.session.captchaValidCount === 0) { | ||
235 | + req.session.captcha = null; // 验证码 用过就扔 | ||
236 | + jsonData.changeCaptcha = true; | ||
237 | + } | ||
238 | + | ||
239 | + return res.json(jsonData); | ||
231 | } | 240 | } |
241 | + | ||
242 | + _.set(req.session, 'captcha', null); | ||
243 | + | ||
232 | } else if (!req.session.backupCaptch.verifyResult) { | 244 | } else if (!req.session.backupCaptch.verifyResult) { |
233 | 245 | ||
234 | return res.json({ | 246 | return res.json({ |
@@ -247,6 +259,8 @@ const sendCodeToMobileAPI = (req, res, next) => { | @@ -247,6 +259,8 @@ const sendCodeToMobileAPI = (req, res, next) => { | ||
247 | return res.json(ERR); | 259 | return res.json(ERR); |
248 | } | 260 | } |
249 | 261 | ||
262 | + | ||
263 | + | ||
250 | service.sendCodeToMobileAsync(phoneNum, areaCode) | 264 | service.sendCodeToMobileAsync(phoneNum, areaCode) |
251 | .then(result => { | 265 | .then(result => { |
252 | if (_.isEmpty(result) || result.code !== 200) { | 266 | if (_.isEmpty(result) || result.code !== 200) { |
@@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
5 | * @date: 2016/05/09 | 5 | * @date: 2016/05/09 |
6 | */ | 6 | */ |
7 | 'use strict'; | 7 | 'use strict'; |
8 | - | 8 | +const _ = require('lodash'); |
9 | const passport = require('passport'); | 9 | const passport = require('passport'); |
10 | 10 | ||
11 | // const md5 = require('md5'); | 11 | // const md5 = require('md5'); |
@@ -78,8 +78,13 @@ const common = { | @@ -78,8 +78,13 @@ const common = { | ||
78 | } | 78 | } |
79 | }; | 79 | }; |
80 | 80 | ||
81 | + | ||
81 | const local = { | 82 | const local = { |
82 | loginPage: (req, res) => { | 83 | loginPage: (req, res) => { |
84 | + if (req.session.captchaValidCount == null) { // eslint-disable-line | ||
85 | + req.session.captchaValidCount = 5; | ||
86 | + } | ||
87 | + | ||
83 | // 先清除cookie | 88 | // 先清除cookie |
84 | // res.clearCookie('LE' + md5('_LOGIN_EXPIRE'), { | 89 | // res.clearCookie('LE' + md5('_LOGIN_EXPIRE'), { |
85 | // domain: 'yohobuy.com' | 90 | // domain: 'yohobuy.com' |
@@ -97,7 +102,9 @@ const local = { | @@ -97,7 +102,9 @@ const local = { | ||
97 | }); | 102 | }); |
98 | 103 | ||
99 | res.render('login', { | 104 | res.render('login', { |
105 | + width750: true, | ||
100 | loginIndex: true, // 模板中使用JS的标识 | 106 | loginIndex: true, // 模板中使用JS的标识 |
107 | + captchaShow: _.get(req.session, 'login.errorCount') <= 0, | ||
101 | 108 | ||
102 | // 返回的URL链接 | 109 | // 返回的URL链接 |
103 | backUrl: 'javascript:history.go(-1)', // eslint-disable-line | 110 | backUrl: 'javascript:history.go(-1)', // eslint-disable-line |
@@ -135,9 +142,12 @@ const local = { | @@ -135,9 +142,12 @@ const local = { | ||
135 | }); | 142 | }); |
136 | 143 | ||
137 | res.render('international', { | 144 | res.render('international', { |
145 | + width750: true, | ||
146 | + | ||
138 | // 返回的URL链接 | 147 | // 返回的URL链接 |
139 | backUrl: 'javascript:history.go(-1)', // eslint-disable-line | 148 | backUrl: 'javascript:history.go(-1)', // eslint-disable-line |
140 | loginInternational: true, // 模板中使用JS的标识 | 149 | loginInternational: true, // 模板中使用JS的标识 |
150 | + captchaShow: _.get(req.session, 'login.errorCount') <= 0, | ||
141 | isPassportPage: true, // 模板中模块标识 | 151 | isPassportPage: true, // 模板中模块标识 |
142 | headerText: '登录', | 152 | headerText: '登录', |
143 | areaCode: '+86', // 默认区号 | 153 | areaCode: '+86', // 默认区号 |
@@ -148,13 +158,64 @@ const local = { | @@ -148,13 +158,64 @@ const local = { | ||
148 | }); | 158 | }); |
149 | }, | 159 | }, |
150 | login: (req, res, next) => { | 160 | login: (req, res, next) => { |
161 | + let count = _.get(req.session, 'login.errorCount'); | ||
162 | + | ||
163 | + if (count == null) { // eslint-disable-line | ||
164 | + _.set(req.session, 'login.errorCount', 3); | ||
165 | + } | ||
166 | + | ||
167 | + if (count <= 0) { | ||
168 | + let captchaInput = req.body.captcha; | ||
169 | + let captchaCode = _.get(req.session, 'captcha'); | ||
170 | + let testCode = req.body.yohobuy; | ||
171 | + | ||
172 | + let errorCount = _.get(req.session, 'captchaValidCount'); // 初始1次 + 后续4次, 同一个验证码 共5次 | ||
173 | + | ||
174 | + let jsonData = { | ||
175 | + code: 400, | ||
176 | + message: '请将图片旋转到正确方向', | ||
177 | + captchaShow: true | ||
178 | + }; | ||
179 | + | ||
180 | + --req.session.captchaValidCount; | ||
181 | + | ||
182 | + if (!errorCount) { | ||
183 | + _.set(req.session, 'captchaValidCount', 5); | ||
184 | + | ||
185 | + // delete req.session.captcha; // 验证码 用过就扔 | ||
186 | + req.session.captcha = null; | ||
187 | + jsonData.changeCaptcha = true; | ||
188 | + } | ||
189 | + | ||
190 | + if ( | ||
191 | + !( | ||
192 | + (captchaInput && captchaCode && captchaInput === captchaCode) || | ||
193 | + (testCode === config.testCode) | ||
194 | + ) | ||
195 | + ) { | ||
196 | + res.json(jsonData); | ||
197 | + | ||
198 | + return; | ||
199 | + } | ||
200 | + } | ||
201 | + | ||
151 | passport.authenticate('local', (err, user) => { | 202 | passport.authenticate('local', (err, user) => { |
203 | + let loginSession = req.session.login; | ||
204 | + | ||
152 | if (err) { | 205 | if (err) { |
153 | - res.json({ | 206 | + let obj = { |
154 | code: 400, | 207 | code: 400, |
155 | message: err, | 208 | message: err, |
156 | data: '' | 209 | data: '' |
157 | - }); | 210 | + }; |
211 | + | ||
212 | + --loginSession.errorCount; | ||
213 | + | ||
214 | + if (loginSession.errorCount <= 0) { | ||
215 | + obj.captchaShow = true; | ||
216 | + } | ||
217 | + | ||
218 | + res.json(obj); | ||
158 | } else { | 219 | } else { |
159 | let refer = req.cookies.refer; | 220 | let refer = req.cookies.refer; |
160 | 221 | ||
@@ -182,7 +243,12 @@ const local = { | @@ -182,7 +243,12 @@ const local = { | ||
182 | })(req, res, next); | 243 | })(req, res, next); |
183 | }, | 244 | }, |
184 | logout: (req, res) => { | 245 | logout: (req, res) => { |
185 | - req.session.reset(); | 246 | + if (req.session && req.session.destroy) { |
247 | + req.session.destroy(); | ||
248 | + } | ||
249 | + if (req.session2 && req.session2.reset) { | ||
250 | + req.session2.reset(); | ||
251 | + } | ||
186 | 252 | ||
187 | res.clearCookie('_UID', { | 253 | res.clearCookie('_UID', { |
188 | domain: 'yohobuy.com' | 254 | domain: 'yohobuy.com' |
@@ -8,6 +8,7 @@ | @@ -8,6 +8,7 @@ | ||
8 | 'use strict'; | 8 | 'use strict'; |
9 | 9 | ||
10 | const _ = require('lodash'); | 10 | const _ = require('lodash'); |
11 | +const url = require('url'); | ||
11 | const utils = require(global.utils); | 12 | const utils = require(global.utils); |
12 | const helpers = global.yoho.helpers; | 13 | const helpers = global.yoho.helpers; |
13 | const sign = global.yoho.sign; | 14 | const sign = global.yoho.sign; |
@@ -26,6 +27,7 @@ const captchaService = require('../models/captcha-service'); | @@ -26,6 +27,7 @@ const captchaService = require('../models/captcha-service'); | ||
26 | } | 27 | } |
27 | */ | 28 | */ |
28 | 29 | ||
30 | + | ||
29 | /** | 31 | /** |
30 | * 步骤校验 | 32 | * 步骤校验 |
31 | * step: 预期步骤 | 33 | * step: 预期步骤 |
@@ -58,6 +60,17 @@ let index = (req, res) => { | @@ -58,6 +60,17 @@ let index = (req, res) => { | ||
58 | return res.redirect(req.get('refer') || '/'); | 60 | return res.redirect(req.get('refer') || '/'); |
59 | } | 61 | } |
60 | 62 | ||
63 | + // 判断是否 来自 个人中心 | ||
64 | + if (!_.get(req.session, 'phoneReg.isFromMy')) { | ||
65 | + let referer = req.get('Referer') || ''; | ||
66 | + let urlObj = url.parse(referer, true, true); | ||
67 | + | ||
68 | + referer = _.get(urlObj, 'query.refer', ''); | ||
69 | + | ||
70 | + urlObj = url.parse(referer, true, true); | ||
71 | + urlObj.path === '/home' && _.set(req.session, 'phoneReg.isFromMy', '1'); | ||
72 | + } | ||
73 | + | ||
61 | // 设置注册有效时间30分钟, 防机器刷 | 74 | // 设置注册有效时间30分钟, 防机器刷 |
62 | // req.session.REG_EXPIRE = Date.now() + 1800000; | 75 | // req.session.REG_EXPIRE = Date.now() + 1800000; |
63 | let refer = req.query.refer; | 76 | let refer = req.query.refer; |
@@ -76,6 +89,7 @@ let index = (req, res) => { | @@ -76,6 +89,7 @@ let index = (req, res) => { | ||
76 | } | 89 | } |
77 | 90 | ||
78 | res.render('reg/index', { | 91 | res.render('reg/index', { |
92 | + width750: true, | ||
79 | module: 'passport', | 93 | module: 'passport', |
80 | page: 'reg', | 94 | page: 'reg', |
81 | title: '注册', | 95 | title: '注册', |
@@ -99,7 +113,7 @@ let verifyMobile = (req, res, next) => { | @@ -99,7 +113,7 @@ let verifyMobile = (req, res, next) => { | ||
99 | let mobile = +req.body.phoneNum; | 113 | let mobile = +req.body.phoneNum; |
100 | let area = +(req.body.areaCode || 86); | 114 | let area = +(req.body.areaCode || 86); |
101 | let captcha = (req.body.captcha || '').trim(); | 115 | let captcha = (req.body.captcha || '').trim(); |
102 | - let diffCaptcha = _.get(req.session, 'phoneReg.captcha'); | 116 | + let diffCaptcha = _.get(req.session, 'captcha'); |
103 | 117 | ||
104 | // error case: 没有验证码 | 118 | // error case: 没有验证码 |
105 | if (!diffCaptcha) { | 119 | if (!diffCaptcha) { |
@@ -110,7 +124,7 @@ let verifyMobile = (req, res, next) => { | @@ -110,7 +124,7 @@ let verifyMobile = (req, res, next) => { | ||
110 | }); | 124 | }); |
111 | } | 125 | } |
112 | 126 | ||
113 | - delete req.session.phoneReg.captcha; // captcha 一次性 | 127 | + delete req.session.captcha; // captcha 一次性 |
114 | 128 | ||
115 | // error case: 验证码不匹配 | 129 | // error case: 验证码不匹配 |
116 | if (captcha !== diffCaptcha) { | 130 | if (captcha !== diffCaptcha) { |
@@ -189,7 +203,6 @@ let codeAction = (req, res, next) => { | @@ -189,7 +203,6 @@ let codeAction = (req, res, next) => { | ||
189 | res.render('reg/code', { | 203 | res.render('reg/code', { |
190 | page: 'code', | 204 | page: 'code', |
191 | title: '注册-验证码', | 205 | title: '注册-验证码', |
192 | - backUrl: '/?go=1', // eslint-disable-line | ||
193 | headerText: '注册', // 头部信息 | 206 | headerText: '注册', // 头部信息 |
194 | isPassportPage: true, // 模板中模块标识 | 207 | isPassportPage: true, // 模板中模块标识 |
195 | areaCode: area, // 默认的区号 | 208 | areaCode: area, // 默认的区号 |
@@ -365,6 +378,7 @@ let setPassword = (req, res, next) => { | @@ -365,6 +378,7 @@ let setPassword = (req, res, next) => { | ||
365 | let password = req.body.password; | 378 | let password = req.body.password; |
366 | let token = req.body.token; | 379 | let token = req.body.token; |
367 | let smsCode = +req.body.smsCode; | 380 | let smsCode = +req.body.smsCode; |
381 | + let isFromMy = _.get(req.session, 'phoneReg.isFromMy', '0'); | ||
368 | 382 | ||
369 | // 判断参数是否合法 | 383 | // 判断参数是否合法 |
370 | if (!smsCode || !_.isString(token) || !_.isNumber(mobile) || !_.isNumber(area) || !password) { | 384 | if (!smsCode || !_.isString(token) || !_.isNumber(mobile) || !_.isNumber(area) || !password) { |
@@ -387,29 +401,40 @@ let setPassword = (req, res, next) => { | @@ -387,29 +401,40 @@ let setPassword = (req, res, next) => { | ||
387 | let shoppingKey = cookie.getShoppingKey(req); | 401 | let shoppingKey = cookie.getShoppingKey(req); |
388 | 402 | ||
389 | // 验证注册的标识码是否有效 | 403 | // 验证注册的标识码是否有效 |
390 | - RegService.regMobileAes(area, mobile, password, shoppingKey, smsCode).then((result) => { | 404 | + let resultCopy = null; |
405 | + | ||
406 | + RegService.regMobileAes(area, mobile, password, shoppingKey, smsCode, isFromMy).then((result) => { | ||
391 | if (!result.code || result.code !== 200) { | 407 | if (!result.code || result.code !== 200) { |
392 | return Promise.reject(result); | 408 | return Promise.reject(result); |
393 | } | 409 | } |
394 | if (!result.data || !result.data.uid) { | 410 | if (!result.data || !result.data.uid) { |
395 | return Promise.reject(result); | 411 | return Promise.reject(result); |
396 | } | 412 | } |
413 | + | ||
414 | + resultCopy = result; | ||
415 | + | ||
397 | return AuthHelper.syncUserSession(result.data.uid, req, res); | 416 | return AuthHelper.syncUserSession(result.data.uid, req, res); |
398 | }).then(() => { | 417 | }).then(() => { |
399 | // 返回跳转到来源页面 | 418 | // 返回跳转到来源页面 |
400 | let refer = req.cookies.refer; | 419 | let refer = req.cookies.refer; |
401 | 420 | ||
402 | - if (refer) { | ||
403 | - refer = decodeURI(req.cookies.refer); | 421 | + // isFromMy to 新人会场 |
422 | + if (resultCopy.data.newUserPage) { | ||
423 | + refer = resultCopy.data.msgDelivery; // 来自个人中心,跳新人会场 | ||
404 | } else { | 424 | } else { |
405 | - refer = '/home'; | ||
406 | - } | 425 | + if (refer) { |
426 | + refer = decodeURI(req.cookies.refer); | ||
427 | + } else { | ||
428 | + refer = '/home'; | ||
429 | + } | ||
430 | + | ||
431 | + if (/sign|login/.test(refer)) { | ||
432 | + refer = '/home'; | ||
433 | + } | ||
407 | 434 | ||
408 | - if (/sign|login/.test(refer)) { | ||
409 | - refer = '/home'; | 435 | + refer = utils.refererLimit(refer); |
410 | } | 436 | } |
411 | 437 | ||
412 | - refer = utils.refererLimit(refer); | ||
413 | 438 | ||
414 | delete req.session.phoneNum; | 439 | delete req.session.phoneNum; |
415 | 440 |
1 | /* eslint no-unused-vars: ["error", { "args": "none" }] */ | 1 | /* eslint no-unused-vars: ["error", { "args": "none" }] */ |
2 | 'use strict'; | 2 | 'use strict'; |
3 | const _ = require('lodash'); | 3 | const _ = require('lodash'); |
4 | +const moment = require('moment'); | ||
4 | const helpers = global.yoho.helpers; | 5 | const helpers = global.yoho.helpers; |
5 | const cookie = global.yoho.cookie; | 6 | const cookie = global.yoho.cookie; |
7 | +const config = global.yoho.config; | ||
8 | +const EventEmitter = require('events'); | ||
6 | const utils = require(global.utils); | 9 | const utils = require(global.utils); |
7 | const RegService = require('../models/reg-service'); | 10 | const RegService = require('../models/reg-service'); |
8 | const PhoneService = require('../models/phone-service'); | 11 | const PhoneService = require('../models/phone-service'); |
9 | const AuthHelper = require('../models/auth-helper'); | 12 | const AuthHelper = require('../models/auth-helper'); |
10 | -const captchaService = require('../models/captcha-service'); | ||
11 | 13 | ||
12 | // constrant | 14 | // constrant |
13 | const CODE_REQUIRED = '请输入校验码'; | 15 | const CODE_REQUIRED = '请输入校验码'; |
14 | const PASSWORD_REQUIRED = '请输入密码'; | 16 | const PASSWORD_REQUIRED = '请输入密码'; |
15 | const PASSWORD_LENGTH_ERROR = '密码6-20位,请重新输入'; | 17 | const PASSWORD_LENGTH_ERROR = '密码6-20位,请重新输入'; |
16 | const BAD_PASSWORD = '密码格式不正确'; | 18 | const BAD_PASSWORD = '密码格式不正确'; |
17 | -const TOO_MANY = '请求太频繁'; | ||
18 | const LOGIN_SUCCSS = '登录成功'; | 19 | const LOGIN_SUCCSS = '登录成功'; |
19 | const VERIFY_ERROR = '校验失败'; | 20 | const VERIFY_ERROR = '校验失败'; |
20 | 21 | ||
@@ -38,12 +39,13 @@ exports.beforeIn = (req, res, next) => { | @@ -38,12 +39,13 @@ exports.beforeIn = (req, res, next) => { | ||
38 | const _step1 = (req, res, next) => { | 39 | const _step1 = (req, res, next) => { |
39 | _.set(req.session, 'smsLogin.step', 1); | 40 | _.set(req.session, 'smsLogin.step', 1); |
40 | 41 | ||
41 | - if (req.session.smsLogin.count == null) { // eslint-disable-line | ||
42 | - req.session.smsLogin.count = 5; | 42 | + if (req.session.captchaValidCount == null) { // eslint-disable-line |
43 | + req.session.captchaValidCount = 5; | ||
43 | } | 44 | } |
44 | 45 | ||
45 | let template = 'sms/login'; | 46 | let template = 'sms/login'; |
46 | let viewData = { | 47 | let viewData = { |
48 | + width750: true, | ||
47 | module: 'passport', | 49 | module: 'passport', |
48 | page: 'sms-login', | 50 | page: 'sms-login', |
49 | title: '手机短信登录', | 51 | title: '手机短信登录', |
@@ -55,6 +57,8 @@ const _step1 = (req, res, next) => { | @@ -55,6 +57,8 @@ const _step1 = (req, res, next) => { | ||
55 | }; | 57 | }; |
56 | 58 | ||
57 | res.render(template, viewData); | 59 | res.render(template, viewData); |
60 | + | ||
61 | + | ||
58 | }; | 62 | }; |
59 | 63 | ||
60 | // 短信登录 第二步: 输入 校验码 | 64 | // 短信登录 第二步: 输入 校验码 |
@@ -118,44 +122,90 @@ exports.loginPage = (req, res, next) => { | @@ -118,44 +122,90 @@ exports.loginPage = (req, res, next) => { | ||
118 | } | 122 | } |
119 | }; | 123 | }; |
120 | 124 | ||
121 | -exports.tokenBefore = (req, res, next) => { | ||
122 | - let area = req.query.area = (req.query.area || '').trim(); | ||
123 | - let mobile = req.query.mobile = (req.query.mobile || '').trim(); | ||
124 | - let step = _.get(req.session, 'smsLogin.step'); | ||
125 | - let count = _.get(req.session, 'smsLogin.count'); | ||
126 | - let interval = _.get(req.session, 'smsLogin.interval'); | ||
127 | - let captcha1 = _.get(req.session, 'smsLogin.captcha'); | ||
128 | - let captcha2 = (req.query.captcha || '').trim(); | ||
129 | 125 | ||
126 | +/** | ||
127 | + * step1 的表单提交验证 | ||
128 | + */ | ||
129 | +exports.indexCheck = (req, res, next) => { | ||
130 | + _.set(req.session, 'smsLogin.step', 1); | ||
130 | 131 | ||
131 | - if (!req.xhr) { | ||
132 | - return next(404); | 132 | + let area = req.body.area = (req.body.area || '').trim(); |
133 | + let mobile = req.body.mobile = (req.body.mobile || '').trim(); | ||
134 | + let captcode = (req.body.captcode || '').trim(); | ||
135 | + let captcodeValid = _.get(req.session, 'captcha'); | ||
136 | + let testCode = req.body.yohobuy; | ||
137 | + | ||
138 | + let em = new EventEmitter(); | ||
139 | + | ||
140 | + | ||
141 | + let errorCount = _.get(req.session, 'captchaValidCount', 4 - 1); // 初始1次 + 后续4次, 同一个验证码 共5次 | ||
142 | + let errorData = { | ||
143 | + code: 400, | ||
144 | + message: '' | ||
145 | + }; | ||
146 | + | ||
147 | + if (!errorCount) { | ||
148 | + _.set(req.session, 'captchaValidCount', 3); | ||
149 | + } else { | ||
150 | + --req.session.captchaValidCount; | ||
133 | } | 151 | } |
134 | 152 | ||
135 | - if ([area, mobile].some(val => val === '')) { | ||
136 | - return res.json({ | ||
137 | - code: 401, | ||
138 | - message: '手机号 必填' | 153 | + // 校验 成功 |
154 | + em.on('resolve', () => { | ||
155 | + // 1. 将信息放入 session | ||
156 | + _.set(req.session, 'smsLogin.area', area); | ||
157 | + _.set(req.session, 'smsLogin.mobile', mobile); | ||
158 | + _.set(req.session, 'smsLogin.step', 2); | ||
159 | + req.session.captcha = null; | ||
160 | + | ||
161 | + PhoneService.sendSMS(mobile, area, 1); | ||
162 | + | ||
163 | + res.json({ | ||
164 | + code: 200, | ||
165 | + redirect: '/passport/sms_login?step=2' | ||
139 | }); | 166 | }); |
167 | + }); | ||
168 | + | ||
169 | + // 校验 失败 | ||
170 | + em.on('reject', error => { | ||
171 | + _.set(req.session, 'smsLogin.step', 1); | ||
172 | + | ||
173 | + | ||
174 | + res.json(error); | ||
175 | + }); | ||
176 | + | ||
177 | + if (req.session.captchaValidCount === 0) { | ||
178 | + req.session.captcha = null; // 验证码 用过就扔 | ||
179 | + errorData.changeCaptcha = true; | ||
140 | } | 180 | } |
141 | 181 | ||
142 | - delete req.session.smsLogin.captcha; // 图形验证码 一次性 | ||
143 | 182 | ||
144 | - // step1 要 校验图形验证码 | ||
145 | - if (step === 1) { | ||
146 | - if (!captcha2) { | ||
147 | - return res.json({ | ||
148 | - code: 400, | ||
149 | - message: '请填写验证码' | ||
150 | - }); | ||
151 | - } | 183 | + // 验证 |
184 | + if ([area, mobile].some(val => val === '')) { | ||
185 | + return em.emit('reject', Object.assign(errorData, { message: '请填写手机号'})); | ||
186 | + } else if (!captcode) { | ||
187 | + return em.emit('reject', Object.assign(errorData, {message: '请填写验证码'})); | ||
188 | + } else if ( | ||
189 | + !( | ||
190 | + (captcodeValid && captcode === captcodeValid) || (testCode === config.testCode) | ||
191 | + ) | ||
192 | + ) { | ||
193 | + return em.emit('reject', Object.assign(errorData, {message: '请将图片旋转到正确位置'})); | ||
194 | + } | ||
152 | 195 | ||
153 | - if (captcha1 !== captcha2) { | ||
154 | - return res.json({ | ||
155 | - code: 400, | ||
156 | - message: VERIFY_ERROR | ||
157 | - }); | ||
158 | - } | 196 | + // congratulation~~ |
197 | + em.emit('resolve'); | ||
198 | +}; | ||
199 | + | ||
200 | +exports.tokenBefore = (req, res, next) => { | ||
201 | + | ||
202 | + let step = _.get(req.session, 'smsLogin.step'); | ||
203 | + let count = _.get(req.session, 'smsLogin.count'); | ||
204 | + let interval = _.get(req.session, 'smsLogin.interval'); | ||
205 | + | ||
206 | + | ||
207 | + if (!req.xhr || step !== 2) { | ||
208 | + return next(404); | ||
159 | } | 209 | } |
160 | 210 | ||
161 | let now = Date.now(); | 211 | let now = Date.now(); |
@@ -164,11 +214,14 @@ exports.tokenBefore = (req, res, next) => { | @@ -164,11 +214,14 @@ exports.tokenBefore = (req, res, next) => { | ||
164 | // 1. 过了冻结期, count 重设为 5次 | 214 | // 1. 过了冻结期, count 重设为 5次 |
165 | // 2. 没过冻结期, end | 215 | // 2. 没过冻结期, end |
166 | // 没有用完, 判断是否请求太频繁 | 216 | // 没有用完, 判断是否请求太频繁 |
217 | + let during = moment.duration(interval - now, 'ms').minutes(); | ||
218 | + let message = `请${during}分钟后再试`; | ||
219 | + | ||
167 | if (!count) { | 220 | if (!count) { |
168 | if (interval > now) { | 221 | if (interval > now) { |
169 | return res.json({ | 222 | return res.json({ |
170 | code: 400, | 223 | code: 400, |
171 | - message: TOO_MANY, | 224 | + message: message, |
172 | during: Math.ceil((interval - now) / 1000) | 225 | during: Math.ceil((interval - now) / 1000) |
173 | }); | 226 | }); |
174 | } else { | 227 | } else { |
@@ -177,17 +230,19 @@ exports.tokenBefore = (req, res, next) => { | @@ -177,17 +230,19 @@ exports.tokenBefore = (req, res, next) => { | ||
177 | } else if (interval > now) { | 230 | } else if (interval > now) { |
178 | return res.json({ | 231 | return res.json({ |
179 | code: 429, | 232 | code: 429, |
180 | - message: TOO_MANY | 233 | + message: message |
181 | }); | 234 | }); |
182 | } | 235 | } |
183 | 236 | ||
184 | next(); | 237 | next(); |
185 | }; | 238 | }; |
186 | 239 | ||
240 | + | ||
241 | + | ||
187 | // AJAX 获取验证码 | 242 | // AJAX 获取验证码 |
188 | exports.token = (req, res, next) => { | 243 | exports.token = (req, res, next) => { |
189 | - let area = req.query.area; | ||
190 | - let mobile = req.query.mobile; | 244 | + let area = _.get(req.session, 'smsLogin.area'); |
245 | + let mobile = _.get(req.session, 'smsLogin.mobile'); | ||
191 | 246 | ||
192 | PhoneService.sendSMS(mobile, area, 1).then(result => { | 247 | PhoneService.sendSMS(mobile, area, 1).then(result => { |
193 | if (result.code === 200) { | 248 | if (result.code === 200) { |
@@ -376,6 +431,7 @@ exports.password = (req, res, next) => { | @@ -376,6 +431,7 @@ exports.password = (req, res, next) => { | ||
376 | /** | 431 | /** |
377 | * 生成 校验码 | 432 | * 生成 校验码 |
378 | */ | 433 | */ |
434 | +/* | ||
379 | exports.genCaptcha = (req, res) => { | 435 | exports.genCaptcha = (req, res) => { |
380 | let captcha = captchaService.generateCaptcha(90, 52, 4); | 436 | let captcha = captchaService.generateCaptcha(90, 52, 4); |
381 | 437 | ||
@@ -386,3 +442,4 @@ exports.genCaptcha = (req, res) => { | @@ -386,3 +442,4 @@ exports.genCaptcha = (req, res) => { | ||
386 | .status(200) | 442 | .status(200) |
387 | .send(captcha.image); | 443 | .send(captcha.image); |
388 | }; | 444 | }; |
445 | +*/ |
apps/passport/data/captcha.json
0 → 100644
This diff could not be displayed because it is too large.
1 | 'use strict'; | 1 | 'use strict'; |
2 | +const _ = require('lodash'); | ||
2 | const aes = require('./aes-pwd'); | 3 | const aes = require('./aes-pwd'); |
3 | const sign = global.yoho.sign; | 4 | const sign = global.yoho.sign; |
4 | const api = global.yoho.API; | 5 | const api = global.yoho.API; |
@@ -87,10 +88,17 @@ class Auth { | @@ -87,10 +88,17 @@ class Auth { | ||
87 | domain: 'yohobuy.com', | 88 | domain: 'yohobuy.com', |
88 | expires: new Date(Date.now() + 2592000000) // 有效期一年 | 89 | expires: new Date(Date.now() + 2592000000) // 有效期一年 |
89 | }); | 90 | }); |
91 | + | ||
92 | + req.session.AVATAR = data.head_ico; | ||
93 | + _.set(req.session, 'USER.AVATAR', data.head_ico); | ||
94 | + _.set(req.session, 'USER.NAME', data.profile_name); | ||
90 | } | 95 | } |
91 | 96 | ||
92 | req.session.TOKEN = publicToken; | 97 | req.session.TOKEN = publicToken; |
93 | req.session.LOGIN_UID = uid; | 98 | req.session.LOGIN_UID = uid; |
99 | + | ||
100 | + _.set(req.session, 'USER.ENCRYPTION_UID', encryptionUid); | ||
101 | + | ||
94 | res.cookie('_TOKEN', publicToken, { | 102 | res.cookie('_TOKEN', publicToken, { |
95 | httpOnly: true, | 103 | httpOnly: true, |
96 | domain: 'yohobuy.com', | 104 | domain: 'yohobuy.com', |
1 | 'use strict'; | 1 | 'use strict'; |
2 | +const _ = require('lodash'); | ||
3 | +let captchaData = require('../data/captcha.json'); | ||
2 | 4 | ||
3 | -let api = global.yoho.API; | ||
4 | - | 5 | +// let api = global.yoho.API; |
5 | /** | 6 | /** |
6 | * 获取图形旋转验证码 | 7 | * 获取图形旋转验证码 |
7 | * @return Promise | 8 | * @return Promise |
@@ -24,9 +25,16 @@ let api = global.yoho.API; | @@ -24,9 +25,16 @@ let api = global.yoho.API; | ||
24 | *} | 25 | *} |
25 | */ | 26 | */ |
26 | exports.gen = () => { | 27 | exports.gen = () => { |
27 | - let params = { | ||
28 | - method: 'web.register.getVerifiedGraphicCode' | ||
29 | - }; | 28 | + // let params = { |
29 | + // method: 'web.register.getVerifiedGraphicCode' | ||
30 | + // }; | ||
31 | + | ||
32 | + // return api.get('', params); | ||
33 | + | ||
34 | + let random = _.random(0, captchaData.length); | ||
30 | 35 | ||
31 | - return api.get('', params); | 36 | + return Promise.resolve({ |
37 | + code: 200, | ||
38 | + data: captchaData[random] | ||
39 | + }); | ||
32 | }; | 40 | }; |
@@ -96,13 +96,16 @@ const RegService = { | @@ -96,13 +96,16 @@ const RegService = { | ||
96 | 96 | ||
97 | return api.post('', params); | 97 | return api.post('', params); |
98 | }, | 98 | }, |
99 | - regMobileAes(area, mobile, password, shoppingKey, smsCode) { | 99 | + regMobileAes(area, mobile, password, shoppingKey, smsCode, isFromMy) { |
100 | + isFromMy = isFromMy || '0'; | ||
101 | + | ||
100 | let params = { | 102 | let params = { |
101 | method: 'app.passport.registerAES', | 103 | method: 'app.passport.registerAES', |
102 | area: area, | 104 | area: area, |
103 | profile: mobile, | 105 | profile: mobile, |
104 | password: aes.aesPwd(password), | 106 | password: aes.aesPwd(password), |
105 | - verifyCode: smsCode | 107 | + verifyCode: smsCode, |
108 | + isFromMy | ||
106 | }; | 109 | }; |
107 | 110 | ||
108 | if (shoppingKey) { | 111 | if (shoppingKey) { |
@@ -41,6 +41,7 @@ router.post('/passport/login/auth', login.local.login); | @@ -41,6 +41,7 @@ router.post('/passport/login/auth', login.local.login); | ||
41 | // SMS 短信 | 41 | // SMS 短信 |
42 | router.use('/passport/sms_login', login.common.beforeLogin, smsLogin.beforeIn); | 42 | router.use('/passport/sms_login', login.common.beforeLogin, smsLogin.beforeIn); |
43 | router.get('/passport/sms_login', smsLogin.loginPage); | 43 | router.get('/passport/sms_login', smsLogin.loginPage); |
44 | +router.post('/passport/sms_login/step1_check', smsLogin.indexCheck); | ||
44 | router.get('/passport/sms_login/token.json', | 45 | router.get('/passport/sms_login/token.json', |
45 | smsLogin.tokenBefore, | 46 | smsLogin.tokenBefore, |
46 | smsLogin.token); // only ajax; | 47 | smsLogin.token); // only ajax; |
@@ -48,7 +49,6 @@ router.get('/passport/sms_login/check.json', | @@ -48,7 +49,6 @@ router.get('/passport/sms_login/check.json', | ||
48 | smsLogin.checkBefore, | 49 | smsLogin.checkBefore, |
49 | smsLogin.check); // only ajax | 50 | smsLogin.check); // only ajax |
50 | router.post('/passport/sms_login/password.json', smsLogin.password); | 51 | router.post('/passport/sms_login/password.json', smsLogin.password); |
51 | -router.get('/passport/sms_login/captcha.png', smsLogin.genCaptcha); | ||
52 | 52 | ||
53 | // 微信登录 | 53 | // 微信登录 |
54 | router.get('/passport/login/wechat', login.common.beforeLogin, login.wechat.login); | 54 | router.get('/passport/login/wechat', login.common.beforeLogin, login.wechat.login); |
@@ -126,4 +126,9 @@ router.get('/passport/newpower', agreement.newpower);// 新力传媒 | @@ -126,4 +126,9 @@ router.get('/passport/newpower', agreement.newpower);// 新力传媒 | ||
126 | router.get('/passport/yohobuy', agreement.aboutYoho);// 关于有货 | 126 | router.get('/passport/yohobuy', agreement.aboutYoho);// 关于有货 |
127 | router.get('/passport/agreement', agreement.agreement);// 服务条款 | 127 | router.get('/passport/agreement', agreement.agreement);// 服务条款 |
128 | 128 | ||
129 | +// 验证码 | ||
130 | +let captcha = require(`${cRoot}/captcha`); | ||
131 | + | ||
132 | +router.get('/passport/captcha/get', captcha.get); | ||
133 | + | ||
129 | module.exports = router; | 134 | module.exports = router; |
@@ -6,12 +6,11 @@ | @@ -6,12 +6,11 @@ | ||
6 | <span id="area-code" class="area-code">{{areaCode}}</span> | 6 | <span id="area-code" class="area-code">{{areaCode}}</span> |
7 | <input id="phone-num" class="input phone-num" type="text" placeholder="手机号"> | 7 | <input id="phone-num" class="input phone-num" type="text" placeholder="手机号"> |
8 | </div> | 8 | </div> |
9 | - <div class="passport-captcha row"> | ||
10 | - <div class="passport-captcha-img"><img id="verify-code-img" src="{{verifySrc}}" alt="verify code"></div> | ||
11 | - <div class="passport-captcha-input"> | ||
12 | - <input id="verify-code" type="text" placeholder="验证码"> | ||
13 | - </div> | 9 | + {{!--图片验证 start--}} |
10 | + <div id="js-img-check"> | ||
11 | + <input type="hidden" name="captsrc" value="{{captsrc}}"> | ||
14 | </div> | 12 | </div> |
13 | + {{!--图片验证 end--}} | ||
15 | <span id="btn-next" class="btn btn-next disable row">下一步</span> | 14 | <span id="btn-next" class="btn btn-next disable row">下一步</span> |
16 | </div> | 15 | </div> |
17 | </div> | 16 | </div> |
@@ -9,6 +9,8 @@ | @@ -9,6 +9,8 @@ | ||
9 | <div class="input-container row has-eye"> | 9 | <div class="input-container row has-eye"> |
10 | <input id="pwd" class="pwd input" type="password" placeholder="密码"> | 10 | <input id="pwd" class="pwd input" type="password" placeholder="密码"> |
11 | </div> | 11 | </div> |
12 | + <div id="js-img-check" {{#captchaShow }}data-init{{/captchaShow}}></div> | ||
13 | + | ||
12 | <span id="btn-login" class="btn btn-login disble row">登录</span> | 14 | <span id="btn-login" class="btn btn-login disble row">登录</span> |
13 | </div> | 15 | </div> |
14 | </div> | 16 | </div> |
@@ -8,9 +8,10 @@ | @@ -8,9 +8,10 @@ | ||
8 | <div class="input-container row has-eye"> | 8 | <div class="input-container row has-eye"> |
9 | <input id="pwd" class="pwd input" type="password" placeholder="密码"> | 9 | <input id="pwd" class="pwd input" type="password" placeholder="密码"> |
10 | </div> | 10 | </div> |
11 | + <div id="js-img-check" {{#captchaShow }}data-init{{/captchaShow}}></div> | ||
11 | <span id="btn-login" class="btn btn-login disable">登录</span> | 12 | <span id="btn-login" class="btn btn-login disable">登录</span> |
12 | <p class="op-container"> | 13 | <p class="op-container"> |
13 | - {{!--<a class="sms-login" href={{smsLoginUrl}}>手机号码快捷登录</a>--}} | 14 | + <a class="sms-login" href={{smsLoginUrl}}>手机号码快捷登录</a> |
14 | <span id="forget-pwd" class="forget-pwd">忘记密码</span> | 15 | <span id="forget-pwd" class="forget-pwd">忘记密码</span> |
15 | </p> | 16 | </p> |
16 | <div class="third-party-login"> | 17 | <div class="third-party-login"> |
@@ -43,4 +44,4 @@ | @@ -43,4 +44,4 @@ | ||
43 | </li> | 44 | </li> |
44 | </ul> | 45 | </ul> |
45 | </div> | 46 | </div> |
46 | -</div> | ||
47 | +</div> |
@@ -6,16 +6,13 @@ | @@ -6,16 +6,13 @@ | ||
6 | <span id="area-code" class="area-code">{{areaCode}}</span> | 6 | <span id="area-code" class="area-code">{{areaCode}}</span> |
7 | <input id="phone-num" class="input phone-num" type="text" placeholder="手机号"> | 7 | <input id="phone-num" class="input phone-num" type="text" placeholder="手机号"> |
8 | </div> | 8 | </div> |
9 | - <!-- 验证码: start--> | ||
10 | - <div class="passport-captcha row"> | ||
11 | - <div class="passport-captcha-img"> | ||
12 | - <img class="passport-captcha-png" src="{{captchaUrl}}"> | ||
13 | - </div> | ||
14 | - <div class="passport-captcha-input"> | ||
15 | - <input id="js-captcha" type="text" placeholder="验证码"> | ||
16 | - </div> | 9 | + |
10 | + {{!--图片验证 start--}} | ||
11 | + <div id="js-img-check"> | ||
12 | + <input type="hidden" name="captsrc" value="{{captsrc}}"> | ||
17 | </div> | 13 | </div> |
18 | - <!-- 验证码: end--> | 14 | + {{!--图片验证 end--}} |
15 | + | ||
19 | <span id="btn-next" class="btn btn-next disable row">下一步</span> | 16 | <span id="btn-next" class="btn btn-next disable row">下一步</span> |
20 | <p class="register-tip">Yoho!Family账号可登录Yoho!Buy有货、Yoho!Now、mars及SHOW</p> | 17 | <p class="register-tip">Yoho!Family账号可登录Yoho!Buy有货、Yoho!Now、mars及SHOW</p> |
21 | </div> | 18 | </div> |
@@ -7,12 +7,11 @@ | @@ -7,12 +7,11 @@ | ||
7 | <input id="phone-num" class="input phone-num" type="text" placeholder="手机号"> | 7 | <input id="phone-num" class="input phone-num" type="text" placeholder="手机号"> |
8 | <button class="clear-input" type="button"></button> | 8 | <button class="clear-input" type="button"></button> |
9 | </div> | 9 | </div> |
10 | - <div class="passport-captcha row"> | ||
11 | - <div class="passport-captcha-img"><img src="{{captchaUrl}}" alt=""></div> | ||
12 | - <div class="passport-captcha-input"> | ||
13 | - <input id="js-captcha" type="text" placeholder="验证码"> | ||
14 | - </div> | 10 | + {{!--图片验证 start--}} |
11 | + <div id="js-img-check"> | ||
12 | + <input type="hidden" name="captsrc" value="{{captsrc}}"> | ||
15 | </div> | 13 | </div> |
14 | + {{!--图片验证 end--}} | ||
16 | <button id="btn-next" class="btn btn-next disable row" disabled>获取短信验证码</button> | 15 | <button id="btn-next" class="btn btn-next disable row" disabled>获取短信验证码</button> |
17 | </div> | 16 | </div> |
18 | </div> | 17 | </div> |
@@ -15,6 +15,7 @@ module.exports = { | @@ -15,6 +15,7 @@ module.exports = { | ||
15 | port: 6001, | 15 | port: 6001, |
16 | siteUrl: '//m.yohobuy.com', | 16 | siteUrl: '//m.yohobuy.com', |
17 | assetUrl: '//127.0.0.1:5001', | 17 | assetUrl: '//127.0.0.1:5001', |
18 | + testCode: 'yoho4946abcdef#$%&!@', | ||
18 | domains: { | 19 | domains: { |
19 | // api: 'http://api-test3.yohops.com:9999/', | 20 | // api: 'http://api-test3.yohops.com:9999/', |
20 | // service: 'http://service-test3.yohops.com:9999/', | 21 | // service: 'http://service-test3.yohops.com:9999/', |
@@ -6,7 +6,7 @@ const headerModel = require('../models/header'); | @@ -6,7 +6,7 @@ const headerModel = require('../models/header'); | ||
6 | const logger = global.yoho.logger; | 6 | const logger = global.yoho.logger; |
7 | 7 | ||
8 | const forceNoCache = (res) => { | 8 | const forceNoCache = (res) => { |
9 | - if (res) { | 9 | + if (res && !res.finished) { |
10 | res.set({ | 10 | res.set({ |
11 | 'Cache-Control': 'no-cache', | 11 | 'Cache-Control': 'no-cache', |
12 | Pragma: 'no-cache', | 12 | Pragma: 'no-cache', |
@@ -47,6 +47,8 @@ exports.notFound = () => { | @@ -47,6 +47,8 @@ exports.notFound = () => { | ||
47 | */ | 47 | */ |
48 | exports.serverError = () => { | 48 | exports.serverError = () => { |
49 | return (err, req, res, next) => { | 49 | return (err, req, res, next) => { |
50 | + console.log(err); | ||
51 | + | ||
50 | forceNoCache(res); | 52 | forceNoCache(res); |
51 | 53 | ||
52 | logger.error(`error at path: ${req.url}`); | 54 | logger.error(`error at path: ${req.url}`); |
1 | { | 1 | { |
2 | "name": "m-yohobuy-node", | 2 | "name": "m-yohobuy-node", |
3 | - "version": "5.3.5", | 3 | + "version": "5.3.6", |
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,9 +24,9 @@ | @@ -24,9 +24,9 @@ | ||
24 | "cheerio": "^0.22.0", | 24 | "cheerio": "^0.22.0", |
25 | "client-sessions": "^0.7.0", | 25 | "client-sessions": "^0.7.0", |
26 | "compression": "^1.6.2", | 26 | "compression": "^1.6.2", |
27 | + "connect-memcached": "^0.2.0", | ||
27 | "connect-multiparty": "^2.0.0", | 28 | "connect-multiparty": "^2.0.0", |
28 | "cookie-parser": "^1.4.3", | 29 | "cookie-parser": "^1.4.3", |
29 | - "cookie-session": "^1.2.0", | ||
30 | "express": "^4.14.0", | 30 | "express": "^4.14.0", |
31 | "feed": "^0.3.0", | 31 | "feed": "^0.3.0", |
32 | "lodash": "^4.17.2", | 32 | "lodash": "^4.17.2", |
@@ -43,6 +43,7 @@ | @@ -43,6 +43,7 @@ | ||
43 | "request-promise": "^3.0.0", | 43 | "request-promise": "^3.0.0", |
44 | "serve-favicon": "^2.3.2", | 44 | "serve-favicon": "^2.3.2", |
45 | "uuid": "^2.0.3", | 45 | "uuid": "^2.0.3", |
46 | + "yoho-express-session": "^2.0.0", | ||
46 | "yoho-node-lib": "0.2.2", | 47 | "yoho-node-lib": "0.2.2", |
47 | "yoho-zookeeper": "^1.0.4" | 48 | "yoho-zookeeper": "^1.0.4" |
48 | }, | 49 | }, |
@@ -12,4 +12,6 @@ | @@ -12,4 +12,6 @@ | ||
12 | <li class="img-check-pic" data-val="0" style="background-image:url('{{imgSrc}}');"></li> | 12 | <li class="img-check-pic" data-val="0" style="background-image:url('{{imgSrc}}');"></li> |
13 | </ul> | 13 | </ul> |
14 | </div> | 14 | </div> |
15 | + | ||
16 | + <input id="yohobuy" type="text" style="display:none;"> | ||
15 | </div> | 17 | </div> |
@@ -19,6 +19,18 @@ var tip = require('../../plugin/tip'); | @@ -19,6 +19,18 @@ var tip = require('../../plugin/tip'); | ||
19 | var trim = $.trim; | 19 | var trim = $.trim; |
20 | var showErrTip = tip.show; | 20 | var showErrTip = tip.show; |
21 | 21 | ||
22 | +// 图片验证码 | ||
23 | +let ImgCheck = require('plugin/img-check'); | ||
24 | + | ||
25 | +let imgCheck = new ImgCheck('#js-img-check', { | ||
26 | + useREM: { | ||
27 | + rootFontSize: 40, | ||
28 | + picWidth: 150 | ||
29 | + } | ||
30 | +}); | ||
31 | + | ||
32 | +imgCheck.init(); | ||
33 | + | ||
22 | api.selectCssHack($('#country-select')); | 34 | api.selectCssHack($('#country-select')); |
23 | 35 | ||
24 | api.bindClearEvt(); | 36 | api.bindClearEvt(); |
@@ -45,12 +57,13 @@ $verifyCodeImg.on('touchstart', function() { | @@ -45,12 +57,13 @@ $verifyCodeImg.on('touchstart', function() { | ||
45 | $btnNext.on('touchstart', function() { | 57 | $btnNext.on('touchstart', function() { |
46 | var pn = trim($phoneNum.val()), | 58 | var pn = trim($phoneNum.val()), |
47 | area = trim($countrySelect.val()), | 59 | area = trim($countrySelect.val()), |
48 | - verify = trim($verifyCode.val()); | 60 | + verify = trim(imgCheck.getResults()); |
49 | 61 | ||
50 | if ($btnNext.hasClass('disable')) { | 62 | if ($btnNext.hasClass('disable')) { |
51 | return; | 63 | return; |
52 | } | 64 | } |
53 | 65 | ||
66 | + | ||
54 | if (verify && area && pn && api.phoneRegx[area].test(pn)) { | 67 | if (verify && area && pn && api.phoneRegx[area].test(pn)) { |
55 | $.ajax({ | 68 | $.ajax({ |
56 | url: '/passport/back/sendcode', | 69 | url: '/passport/back/sendcode', |
@@ -58,23 +71,25 @@ $btnNext.on('touchstart', function() { | @@ -58,23 +71,25 @@ $btnNext.on('touchstart', function() { | ||
58 | data: { | 71 | data: { |
59 | areaCode: area.replace('+', ''), | 72 | areaCode: area.replace('+', ''), |
60 | phoneNum: pn, | 73 | phoneNum: pn, |
61 | - verifyCode: verify | 74 | + verifyCode: verify, |
75 | + yohobuy: $('#yohobuy').val() | ||
62 | }, | 76 | }, |
63 | success: function(data) { | 77 | success: function(data) { |
64 | if (data.code === 200) { | 78 | if (data.code === 200) { |
65 | location.href = data.data; | 79 | location.href = data.data; |
80 | + return; | ||
66 | } else if (data.code === 409) { | 81 | } else if (data.code === 409) { |
67 | showErrTip(data.message); | 82 | showErrTip(data.message); |
68 | location.href = data.refer; | 83 | location.href = data.refer; |
69 | } else { | 84 | } else { |
70 | showErrTip(data.message); | 85 | showErrTip(data.message); |
71 | } | 86 | } |
87 | + | ||
88 | + data.changeCaptcha && imgCheck.refresh(); | ||
72 | } | 89 | } |
73 | }); | 90 | }); |
74 | } else if (!area) { | 91 | } else if (!area) { |
75 | showErrTip('出错了,请重新刷新页面'); | 92 | showErrTip('出错了,请重新刷新页面'); |
76 | - } else if (!verify) { | ||
77 | - showErrTip('请输入验证码'); | ||
78 | } else { | 93 | } else { |
79 | showErrTip('手机号格式不正确,请重新输入'); | 94 | showErrTip('手机号格式不正确,请重新输入'); |
80 | } | 95 | } |
@@ -4,6 +4,7 @@ | @@ -4,6 +4,7 @@ | ||
4 | * @date: 2015/10/8 | 4 | * @date: 2015/10/8 |
5 | */ | 5 | */ |
6 | var $ = require('yoho-jquery'); | 6 | var $ = require('yoho-jquery'); |
7 | +var ImgCheck = require('plugin/img-check'); | ||
7 | 8 | ||
8 | var $phoneNum = $('#phone-num'), | 9 | var $phoneNum = $('#phone-num'), |
9 | $countrySelect = $('#country-select'), | 10 | $countrySelect = $('#country-select'), |
@@ -11,6 +12,8 @@ var $phoneNum = $('#phone-num'), | @@ -11,6 +12,8 @@ var $phoneNum = $('#phone-num'), | ||
11 | $pwd = $('#pwd'), | 12 | $pwd = $('#pwd'), |
12 | $loginBtn = $('#btn-login'), | 13 | $loginBtn = $('#btn-login'), |
13 | 14 | ||
15 | + $captcha = $('#js-img-check'), | ||
16 | + | ||
14 | pnPass = false, | 17 | pnPass = false, |
15 | pwdPass = false; | 18 | pwdPass = false; |
16 | 19 | ||
@@ -20,13 +23,28 @@ var tip = require('../../plugin/tip'); | @@ -20,13 +23,28 @@ var tip = require('../../plugin/tip'); | ||
20 | var trim = $.trim; | 23 | var trim = $.trim; |
21 | var showErrTip = tip.show; | 24 | var showErrTip = tip.show; |
22 | 25 | ||
26 | +var imgCheck = new ImgCheck($captcha, { | ||
27 | + useREM: { | ||
28 | + rootFontSize: 40, | ||
29 | + picWidth: 150 | ||
30 | + } | ||
31 | +}); | ||
32 | + | ||
33 | +if ($captcha.data('init') != null) { //eslint-disable-line | ||
34 | + imgCheck.init(); | ||
35 | +} | ||
36 | + | ||
37 | + | ||
23 | // 登录按钮状态切换 | 38 | // 登录按钮状态切换 |
24 | function switchLoginBtnStatus() { | 39 | function switchLoginBtnStatus() { |
25 | - if (pnPass && pwdPass) { | ||
26 | - $loginBtn.removeClass('disable'); | ||
27 | - } else { | ||
28 | - $loginBtn.addClass('disable'); | ||
29 | - } | 40 | + var bool = !(pnPass && pwdPass); |
41 | + | ||
42 | + $loginBtn.toggleClass('disable', bool); | ||
43 | +} | ||
44 | + | ||
45 | +function resetForm() { | ||
46 | + $pwd.val('').focus(); | ||
47 | + $loginBtn.text('登录').addClass('disable'); | ||
30 | } | 48 | } |
31 | 49 | ||
32 | // Android-UC下显示select的direction:rtl无效的临时解决办法 | 50 | // Android-UC下显示select的direction:rtl无效的临时解决办法 |
@@ -67,23 +85,39 @@ $countrySelect.change(function() { | @@ -67,23 +85,39 @@ $countrySelect.change(function() { | ||
67 | $loginBtn.on('touchstart', function() { | 85 | $loginBtn.on('touchstart', function() { |
68 | var pn = trim($phoneNum.val()), | 86 | var pn = trim($phoneNum.val()), |
69 | areaCode = $countrySelect.val(), | 87 | areaCode = $countrySelect.val(), |
70 | - pwd = trim($pwd.val()); | 88 | + pwd = trim($pwd.val()), |
89 | + captcha = null; | ||
71 | 90 | ||
72 | if ($loginBtn.hasClass('disable')) { | 91 | if ($loginBtn.hasClass('disable')) { |
73 | return; | 92 | return; |
74 | } | 93 | } |
75 | 94 | ||
95 | + if (imgCheck.atWorking) { | ||
96 | + captcha = imgCheck.getResults(); | ||
97 | + | ||
98 | + if (captcha === '0000') { | ||
99 | + return tip.show(' 请将图片旋转到正确方向'); | ||
100 | + } | ||
101 | + } | ||
102 | + | ||
103 | + | ||
76 | $loginBtn.text('正在登录...').addClass('disable'); | 104 | $loginBtn.text('正在登录...').addClass('disable'); |
77 | 105 | ||
78 | if ((api.phoneRegx[areaCode].test(pn) || areaCode !== '+86') && api.pwdValidate(pwd)) { | 106 | if ((api.phoneRegx[areaCode].test(pn) || areaCode !== '+86') && api.pwdValidate(pwd)) { |
107 | + let data = { | ||
108 | + areaCode: areaCode.replace('+', ''), | ||
109 | + account: pn, | ||
110 | + password: pwd | ||
111 | + }; | ||
112 | + | ||
113 | + if (imgCheck.atWorking) { | ||
114 | + $.extend(data, {captcha}); | ||
115 | + } | ||
116 | + | ||
79 | $.ajax({ | 117 | $.ajax({ |
80 | type: 'POST', | 118 | type: 'POST', |
81 | url: '/passport/login/auth', | 119 | url: '/passport/login/auth', |
82 | - data: { | ||
83 | - areaCode: areaCode.replace('+', ''), | ||
84 | - account: pn, | ||
85 | - password: pwd | ||
86 | - }, | 120 | + data, |
87 | success: function(data) { | 121 | success: function(data) { |
88 | var res, | 122 | var res, |
89 | time; | 123 | time; |
@@ -110,21 +144,27 @@ $loginBtn.on('touchstart', function() { | @@ -110,21 +144,27 @@ $loginBtn.on('touchstart', function() { | ||
110 | location.href = res.href; | 144 | location.href = res.href; |
111 | }, 3000); | 145 | }, 3000); |
112 | 146 | ||
147 | + $loginBtn.text('登录成功').off(); | ||
113 | showErrTip('登录成功'); | 148 | showErrTip('登录成功'); |
114 | } else { | 149 | } else { |
150 | + if (data.captchaShow) { | ||
151 | + imgCheck.atWorking ? imgCheck.refresh() : imgCheck.init(); | ||
152 | + } | ||
153 | + | ||
115 | showErrTip(data.message); | 154 | showErrTip(data.message); |
155 | + resetForm(); | ||
116 | } | 156 | } |
117 | }, | 157 | }, |
118 | error: function() { | 158 | error: function() { |
119 | showErrTip('网络断开连接啦~'); | 159 | showErrTip('网络断开连接啦~'); |
120 | - }, | ||
121 | - complete: function() { | ||
122 | - $loginBtn.text('登录').removeClass('disable'); | 160 | + $loginBtn.text('登录'); |
161 | + | ||
162 | + imgCheck.atWorking && imgCheck.refresh(); | ||
123 | } | 163 | } |
124 | }); | 164 | }); |
125 | } else { | 165 | } else { |
126 | showErrTip('账号或密码有错误,请重新输入'); | 166 | showErrTip('账号或密码有错误,请重新输入'); |
127 | - $loginBtn.text('登录').removeClass('disable'); | 167 | + $loginBtn.text('登录').addClass('disable'); |
128 | } | 168 | } |
129 | }); | 169 | }); |
130 | 170 |
@@ -4,6 +4,7 @@ | @@ -4,6 +4,7 @@ | ||
4 | * @date: 2015/9/30 | 4 | * @date: 2015/9/30 |
5 | */ | 5 | */ |
6 | var $ = require('yoho-jquery'); | 6 | var $ = require('yoho-jquery'); |
7 | +var ImgCheck = require('plugin/img-check'); | ||
7 | 8 | ||
8 | var $account = $('#account'), | 9 | var $account = $('#account'), |
9 | $pwd = $('#pwd'), | 10 | $pwd = $('#pwd'), |
@@ -12,6 +13,8 @@ var $account = $('#account'), | @@ -12,6 +13,8 @@ var $account = $('#account'), | ||
12 | $mask = $('#retrive-pwd-mask'), | 13 | $mask = $('#retrive-pwd-mask'), |
13 | $ways = $('#retrive-pwd-ways'), | 14 | $ways = $('#retrive-pwd-ways'), |
14 | 15 | ||
16 | + $captcha = $('#js-img-check'), | ||
17 | + | ||
15 | accPass = false, | 18 | accPass = false, |
16 | pwdPass = false; | 19 | pwdPass = false; |
17 | 20 | ||
@@ -21,13 +24,30 @@ var tip = require('../../plugin/tip'); | @@ -21,13 +24,30 @@ var tip = require('../../plugin/tip'); | ||
21 | var trim = $.trim; | 24 | var trim = $.trim; |
22 | var showErrTip = tip.show; | 25 | var showErrTip = tip.show; |
23 | 26 | ||
27 | + | ||
28 | +var imgCheck = new ImgCheck($captcha, { | ||
29 | + useREM: { | ||
30 | + rootFontSize: 40, | ||
31 | + picWidth: 150 | ||
32 | + } | ||
33 | +}); | ||
34 | + | ||
35 | +if ($captcha.data('init') != null) { //eslint-disable-line | ||
36 | + imgCheck.init(); | ||
37 | +} | ||
38 | + | ||
24 | // 登录按钮状态切换 | 39 | // 登录按钮状态切换 |
25 | function switchLoginBtnStatus() { | 40 | function switchLoginBtnStatus() { |
26 | - if (accPass && pwdPass) { | ||
27 | - $loginBtn.removeClass('disable'); | ||
28 | - } else { | ||
29 | - $loginBtn.addClass('disable'); | ||
30 | - } | 41 | + var bool = true; |
42 | + | ||
43 | + bool = !(accPass && pwdPass); | ||
44 | + | ||
45 | + $loginBtn.toggleClass('disable', bool); | ||
46 | +} | ||
47 | + | ||
48 | +function resetForm() { | ||
49 | + $pwd.val('').focus(); | ||
50 | + $loginBtn.text('登录').addClass('disable'); | ||
31 | } | 51 | } |
32 | 52 | ||
33 | // 显示找回密码面板 | 53 | // 显示找回密码面板 |
@@ -70,23 +90,39 @@ $pwd.bind('input', function() { | @@ -70,23 +90,39 @@ $pwd.bind('input', function() { | ||
70 | // Login | 90 | // Login |
71 | $loginBtn.on('touchstart', function() { | 91 | $loginBtn.on('touchstart', function() { |
72 | var acc = trim($account.val()), | 92 | var acc = trim($account.val()), |
73 | - pwd = trim($pwd.val()); | 93 | + pwd = trim($pwd.val()), |
94 | + captcha = null; | ||
74 | 95 | ||
75 | if ($loginBtn.hasClass('disable')) { | 96 | if ($loginBtn.hasClass('disable')) { |
76 | return; | 97 | return; |
77 | } | 98 | } |
78 | 99 | ||
100 | + // if (imgCheck.atWorking) { | ||
101 | + captcha = imgCheck.getResults(); | ||
102 | + | ||
103 | + // if (captcha === '0000') { | ||
104 | + // return tip.show(' 请将图片旋转到正确方向'); | ||
105 | + // } | ||
106 | + // } | ||
107 | + | ||
79 | $loginBtn.text('正在登录...').addClass('disable'); | 108 | $loginBtn.text('正在登录...').addClass('disable'); |
80 | 109 | ||
81 | // 验证账号(数字或者邮箱)和密码合理性 | 110 | // 验证账号(数字或者邮箱)和密码合理性 |
82 | if ((/^[0-9]+$/.test(acc) || api.emailRegx.test(acc)) && api.pwdValidate(pwd)) { | 111 | if ((/^[0-9]+$/.test(acc) || api.emailRegx.test(acc)) && api.pwdValidate(pwd)) { |
112 | + let data = { | ||
113 | + account: acc, | ||
114 | + password: pwd, | ||
115 | + yohobuy: $('#yohobuy').val() | ||
116 | + }; | ||
117 | + | ||
118 | + if (imgCheck.atWorking) { | ||
119 | + $.extend(data, {captcha}); | ||
120 | + } | ||
121 | + | ||
83 | $.ajax({ | 122 | $.ajax({ |
84 | type: 'POST', | 123 | type: 'POST', |
85 | url: '/passport/login/auth', | 124 | url: '/passport/login/auth', |
86 | - data: { | ||
87 | - account: acc, | ||
88 | - password: pwd | ||
89 | - }, | 125 | + data, |
90 | success: function(data) { | 126 | success: function(data) { |
91 | var res; | 127 | var res; |
92 | 128 | ||
@@ -95,12 +131,22 @@ $loginBtn.on('touchstart', function() { | @@ -95,12 +131,22 @@ $loginBtn.on('touchstart', function() { | ||
95 | 131 | ||
96 | showErrTip('登录成功'); | 132 | showErrTip('登录成功'); |
97 | location.href = res.href; | 133 | location.href = res.href; |
134 | + $loginBtn.text('登录成功').off(); | ||
98 | } else { | 135 | } else { |
136 | + if (data.captchaShow) { | ||
137 | + imgCheck.atWorking ? (data.changeCaptcha && imgCheck.refresh()) : imgCheck.init(); | ||
138 | + } | ||
139 | + | ||
99 | showErrTip(data.message); | 140 | showErrTip(data.message); |
141 | + resetForm(); | ||
100 | } | 142 | } |
143 | + | ||
144 | + return data; | ||
101 | }, | 145 | }, |
102 | error: function() { | 146 | error: function() { |
103 | showErrTip('网络断开连接啦~'); | 147 | showErrTip('网络断开连接啦~'); |
148 | + | ||
149 | + imgCheck.atWorking && imgCheck.refresh(); | ||
104 | }, | 150 | }, |
105 | complete: function() { | 151 | complete: function() { |
106 | $loginBtn.text('登录').removeClass('disable'); | 152 | $loginBtn.text('登录').removeClass('disable'); |
@@ -35,7 +35,7 @@ $pwd.bind('input', function() { | @@ -35,7 +35,7 @@ $pwd.bind('input', function() { | ||
35 | }); | 35 | }); |
36 | 36 | ||
37 | $btnSure.toggleClass('disable', !bool); | 37 | $btnSure.toggleClass('disable', !bool); |
38 | -}) | 38 | +}); |
39 | 39 | ||
40 | 40 | ||
41 | qs = window.queryString; | 41 | qs = window.queryString; |
@@ -137,4 +137,4 @@ $('.agreement-detail').on('click', function() { | @@ -137,4 +137,4 @@ $('.agreement-detail').on('click', function() { | ||
137 | // 如果有值, 立刻校验 | 137 | // 如果有值, 立刻校验 |
138 | if ($pwd.val()) { | 138 | if ($pwd.val()) { |
139 | $pwd.triggerHandler('input'); | 139 | $pwd.triggerHandler('input'); |
140 | -} | ||
140 | +} |
@@ -24,17 +24,29 @@ api.selectCssHack($('#country-select')); | @@ -24,17 +24,29 @@ api.selectCssHack($('#country-select')); | ||
24 | 24 | ||
25 | api.bindClearEvt(); | 25 | api.bindClearEvt(); |
26 | 26 | ||
27 | + | ||
28 | +// 图片验证码 | ||
29 | +let ImgCheck = require('plugin/img-check'); | ||
30 | + | ||
31 | +let imgCheck = new ImgCheck('#js-img-check', { | ||
32 | + useREM: { | ||
33 | + rootFontSize: 40, | ||
34 | + picWidth: 150 | ||
35 | + } | ||
36 | +}); | ||
37 | + | ||
38 | +imgCheck.init(); | ||
39 | + | ||
27 | /** | 40 | /** |
28 | * 必填校验 | 41 | * 必填校验 |
29 | */ | 42 | */ |
30 | function checkEnableNext() { | 43 | function checkEnableNext() { |
31 | var phone = trim($phoneNum.val()); | 44 | var phone = trim($phoneNum.val()); |
32 | var area = trim($countrySelect.val()); | 45 | var area = trim($countrySelect.val()); |
33 | - var captcha = trim($captcha.val()); | ||
34 | 46 | ||
35 | var ret = true; | 47 | var ret = true; |
36 | 48 | ||
37 | - $.each([phone, area, captcha], function(i, val) { | 49 | + $.each([phone, area], function(i, val) { |
38 | if (!val) { | 50 | if (!val) { |
39 | ret = false; | 51 | ret = false; |
40 | return ret; | 52 | return ret; |
@@ -44,24 +56,13 @@ function checkEnableNext() { | @@ -44,24 +56,13 @@ function checkEnableNext() { | ||
44 | return ret; | 56 | return ret; |
45 | } | 57 | } |
46 | 58 | ||
47 | - | ||
48 | -/** | ||
49 | - * 刷新 校验码 | ||
50 | - */ | ||
51 | -function refreshCaptcha() { | ||
52 | - $captcha.val('').focus(); | ||
53 | - $captchaPNG.attr('src', ['//m.yohobuy.com/passport/reg/captcha.png', '?t=', Date.now()].join('')); | ||
54 | -} | ||
55 | - | ||
56 | - | ||
57 | /* | 59 | /* |
58 | Event bind | 60 | Event bind |
59 | */ | 61 | */ |
60 | $('.reg-page') | 62 | $('.reg-page') |
61 | - .on('input', '.phone-num, #js-captcha', function() { | 63 | + .on('input', '.phone-num', function() { |
62 | $btnNext.toggleClass('disable', !checkEnableNext()); | 64 | $btnNext.toggleClass('disable', !checkEnableNext()); |
63 | - }) | ||
64 | - .on('click', '.passport-captcha-png', refreshCaptcha); | 65 | + }); |
65 | 66 | ||
66 | $countrySelect.change(function() { | 67 | $countrySelect.change(function() { |
67 | $areaCode.text($countrySelect.val()); | 68 | $areaCode.text($countrySelect.val()); |
@@ -70,10 +71,10 @@ $countrySelect.change(function() { | @@ -70,10 +71,10 @@ $countrySelect.change(function() { | ||
70 | $btnNext.on('touchstart', function() { | 71 | $btnNext.on('touchstart', function() { |
71 | var pn = trim($phoneNum.val()), | 72 | var pn = trim($phoneNum.val()), |
72 | areaCode = $countrySelect.val(), | 73 | areaCode = $countrySelect.val(), |
73 | - captcha = $captcha.val().trim(); | 74 | + captcha = imgCheck.getResults(); |
74 | 75 | ||
75 | - if (!captcha) { | ||
76 | - tip.show('请输入验证码'); | 76 | + if (captcha === '0000') { |
77 | + tip.show('请将图片旋转到正确位置'); | ||
77 | return false; | 78 | return false; |
78 | } | 79 | } |
79 | 80 | ||
@@ -102,7 +103,7 @@ $btnNext.on('touchstart', function() { | @@ -102,7 +103,7 @@ $btnNext.on('touchstart', function() { | ||
102 | if (data.code === 200) { | 103 | if (data.code === 200) { |
103 | location.href = data.data; | 104 | location.href = data.data; |
104 | } else { | 105 | } else { |
105 | - refreshCaptcha(); | 106 | + imgCheck.refresh(); |
106 | 107 | ||
107 | showErrTip(data.message); | 108 | showErrTip(data.message); |
108 | requested = false; | 109 | requested = false; |
@@ -110,7 +111,7 @@ $btnNext.on('touchstart', function() { | @@ -110,7 +111,7 @@ $btnNext.on('touchstart', function() { | ||
110 | }, | 111 | }, |
111 | error: function() { | 112 | error: function() { |
112 | showErrTip('出错了,请重试'); | 113 | showErrTip('出错了,请重试'); |
113 | - refreshCaptcha(); | 114 | + imgCheck.refresh(); |
114 | requested = false; | 115 | requested = false; |
115 | } | 116 | } |
116 | }); | 117 | }); |
@@ -17,10 +17,26 @@ tip = require('plugin/tip'); | @@ -17,10 +17,26 @@ tip = require('plugin/tip'); | ||
17 | api = require('./api'); | 17 | api = require('./api'); |
18 | checkPoint = require('./smslogin/check-point'); | 18 | checkPoint = require('./smslogin/check-point'); |
19 | 19 | ||
20 | + | ||
21 | +// 图片验证码 | ||
22 | +let ImgCheck = require('plugin/img-check'); | ||
23 | + | ||
24 | +let imgCheck = new ImgCheck('#js-img-check', { | ||
25 | + useREM: { | ||
26 | + rootFontSize: 40, | ||
27 | + picWidth: 150 | ||
28 | + } | ||
29 | +}); | ||
30 | + | ||
31 | +imgCheck.init(); | ||
32 | + | ||
33 | + | ||
34 | + | ||
20 | page = { | 35 | page = { |
21 | init: function() { | 36 | init: function() { |
22 | this.domInit(); | 37 | this.domInit(); |
23 | this.bindEvent(); | 38 | this.bindEvent(); |
39 | + this.toggleNextBtn(); | ||
24 | }, | 40 | }, |
25 | domInit: function() { | 41 | domInit: function() { |
26 | $countrySelect = $('#country-select'); | 42 | $countrySelect = $('#country-select'); |
@@ -28,8 +44,6 @@ page = { | @@ -28,8 +44,6 @@ page = { | ||
28 | $nextBtn = $('#btn-next'); | 44 | $nextBtn = $('#btn-next'); |
29 | $phoneNum = $('#phone-num'); | 45 | $phoneNum = $('#phone-num'); |
30 | $resetBtn = $('.clear-input'); | 46 | $resetBtn = $('.clear-input'); |
31 | - $captcha = $('.passport-captcha input'); | ||
32 | - $captchaPNG = $('.passport-captcha-img img'); | ||
33 | }, | 47 | }, |
34 | bindEvent: function() { | 48 | bindEvent: function() { |
35 | var self = this; | 49 | var self = this; |
@@ -41,12 +55,6 @@ page = { | @@ -41,12 +55,6 @@ page = { | ||
41 | self.toggleNextBtn(); | 55 | self.toggleNextBtn(); |
42 | }); | 56 | }); |
43 | 57 | ||
44 | - $captcha.on('input', function() { | ||
45 | - self.toggleNextBtn(); | ||
46 | - }); | ||
47 | - | ||
48 | - $captchaPNG.on('click', $.proxy(this.refreshCapatch, this)); | ||
49 | - | ||
50 | $nextBtn.on('click', function() { | 58 | $nextBtn.on('click', function() { |
51 | self.goNext(); | 59 | self.goNext(); |
52 | }); | 60 | }); |
@@ -62,7 +70,7 @@ page = { | @@ -62,7 +70,7 @@ page = { | ||
62 | 70 | ||
63 | // 切换$nextBtn disable状态 | 71 | // 切换$nextBtn disable状态 |
64 | toggleNextBtn: function() { | 72 | toggleNextBtn: function() { |
65 | - var bool = Boolean($.trim($phoneNum.val())) && Boolean($.trim($captcha.val())); | 73 | + var bool = Boolean($.trim($phoneNum.val())); |
66 | 74 | ||
67 | $nextBtn | 75 | $nextBtn |
68 | .toggleClass('disable', !bool) | 76 | .toggleClass('disable', !bool) |
@@ -71,17 +79,11 @@ page = { | @@ -71,17 +79,11 @@ page = { | ||
71 | $resetBtn.toggle(bool); | 79 | $resetBtn.toggle(bool); |
72 | }, | 80 | }, |
73 | 81 | ||
74 | - refreshCapatch: function() { | ||
75 | - $captchaPNG.attr('src', '/passport/sms_login/captcha.png?t=' + Date.now()); | ||
76 | - $captcha.val(''); | ||
77 | - }, | ||
78 | - | ||
79 | // 提交按钮 | 82 | // 提交按钮 |
80 | goNext: function() { | 83 | goNext: function() { |
81 | - var self = this; | ||
82 | var areaCode = $countrySelect.val(); | 84 | var areaCode = $countrySelect.val(); |
83 | var phone = $.trim($phoneNum.val()); | 85 | var phone = $.trim($phoneNum.val()); |
84 | - var captcha = $.trim($captcha.val()); | 86 | + var captcha = $.trim(imgCheck.getResults()); |
85 | 87 | ||
86 | if ($nextBtn.prop('disabled')) { | 88 | if ($nextBtn.prop('disabled')) { |
87 | return; | 89 | return; |
@@ -92,11 +94,17 @@ page = { | @@ -92,11 +94,17 @@ page = { | ||
92 | return; | 94 | return; |
93 | } | 95 | } |
94 | 96 | ||
97 | + // if (captcha === '0000') { | ||
98 | + // tip.show('请将图片旋转到正确位置'); | ||
99 | + // return; | ||
100 | + // } | ||
101 | + | ||
95 | $nextBtn.prop('disabled', true); | 102 | $nextBtn.prop('disabled', true); |
96 | - $.get('/passport/sms_login/token.json', { | 103 | + $.post('/passport/sms_login/step1_check', { |
97 | area: areaCode.replace('+', ''), | 104 | area: areaCode.replace('+', ''), |
98 | mobile: phone, | 105 | mobile: phone, |
99 | - captcha: captcha | 106 | + captcode: captcha, |
107 | + yohobuy: $('#yohobuy').val() | ||
100 | }) | 108 | }) |
101 | .done(function(data) { | 109 | .done(function(data) { |
102 | if (data.code === 200) { | 110 | if (data.code === 200) { |
@@ -104,11 +112,12 @@ page = { | @@ -104,11 +112,12 @@ page = { | ||
104 | $nextBtn.off(); | 112 | $nextBtn.off(); |
105 | location.href = data.redirect; | 113 | location.href = data.redirect; |
106 | } else { | 114 | } else { |
107 | - self.refreshCapatch(); | 115 | + data.changeCaptcha && imgCheck.refresh(); |
108 | tip.show(data.message); | 116 | tip.show(data.message); |
109 | } | 117 | } |
110 | }) | 118 | }) |
111 | .fail(function() { | 119 | .fail(function() { |
120 | + imgCheck.refresh(); | ||
112 | tip.show('出错了, 请重试'); | 121 | tip.show('出错了, 请重试'); |
113 | }) | 122 | }) |
114 | .always(function() { | 123 | .always(function() { |
@@ -12,10 +12,12 @@ var sendInfo = function(eventName) { | @@ -12,10 +12,12 @@ var sendInfo = function(eventName) { | ||
12 | channel = channelMap[channel] || 1; | 12 | channel = channelMap[channel] || 1; |
13 | param = JSON.stringify({C_ID: channel}); | 13 | param = JSON.stringify({C_ID: channel}); |
14 | 14 | ||
15 | - yas && yas.sendCustomInfo({ | ||
16 | - op: eventName, | ||
17 | - param: param | ||
18 | - }, true); | 15 | + if (yas && yas.sendCustomInfo) { |
16 | + yas.sendCustomInfo({ | ||
17 | + op: eventName, | ||
18 | + param: param | ||
19 | + }, true); | ||
20 | + } | ||
19 | }; | 21 | }; |
20 | 22 | ||
21 | module.exports = sendInfo; | 23 | module.exports = sendInfo; |
-
Please register or login to post a comment