Authored by ccbikai

Merge branch 'feature/passport' into feature/product-detail

@@ -56,7 +56,7 @@ passport.use(new LocalStrategy({ @@ -56,7 +56,7 @@ passport.use(new LocalStrategy({
56 56
57 let shoppingKey = cookie.getShoppingKey(req); 57 let shoppingKey = cookie.getShoppingKey(req);
58 58
59 - AuthHelper.signin(area, username, password, shoppingKey).then((result) => { 59 + AuthHelper.signinAes(area, username, password, shoppingKey).then((result) => {
60 if (result.code && result.code === 200 && result.data.uid) { 60 if (result.code && result.code === 200 && result.data.uid) {
61 done(null, result.data); 61 done(null, result.data);
62 } else { 62 } else {
@@ -108,4 +108,3 @@ passport.use('alipay', new AlipayStrategy({ @@ -108,4 +108,3 @@ passport.use('alipay', new AlipayStrategy({
108 }), (profile, done) => { 108 }), (profile, done) => {
109 done(null, profile); 109 done(null, profile);
110 }); 110 });
111 -  
@@ -120,7 +120,7 @@ const setNewPasswordByEmailAPI = (req, res) => { @@ -120,7 +120,7 @@ const setNewPasswordByEmailAPI = (req, res) => {
120 data: SIGN_IN 120 data: SIGN_IN
121 }; 121 };
122 122
123 - service.modifyPasswordByEmailAsync(pwd, code) 123 + service.modifyPasswordByEmailAsyncAes(pwd, code)
124 .then(result => { 124 .then(result => {
125 if (result.includes('history.back')) { 125 if (result.includes('history.back')) {
126 data.code = 400; 126 data.code = 400;
@@ -281,9 +281,8 @@ const setNewPasswordByMobileAPI = (req, res, next) => { @@ -281,9 +281,8 @@ const setNewPasswordByMobileAPI = (req, res, next) => {
281 let areaCode = req.body.areaCode || '86'; 281 let areaCode = req.body.areaCode || '86';
282 let newPwd = req.body.password || ''; 282 let newPwd = req.body.password || '';
283 283
284 - service.modifyPasswordByMobileAsync(phoneNum, token, newPwd, areaCode) 284 + service.modifyPasswordByMobileAsyncAes(phoneNum, token, newPwd, areaCode)
285 .then(result => { 285 .then(result => {
286 - console.log(result);  
287 if (result.code === 200) { 286 if (result.code === 200) {
288 res.json({ 287 res.json({
289 code: 200, 288 code: 200,
@@ -35,7 +35,7 @@ const bind = { @@ -35,7 +35,7 @@ const bind = {
35 35
36 res.render('bind/index', { 36 res.render('bind/index', {
37 bindIndex: true, // js标识 37 bindIndex: true, // js标识
38 - backUrl: helpers.urlFormat('/signin.html'), // 返回的URL链接 38 + backUrl: helpers.urlFormat('passport/login'), // 返回的URL链接
39 showHeaderImg: true, // 控制显示头部图片 39 showHeaderImg: true, // 控制显示头部图片
40 isPassportPage: true, // 模板中模块标识 40 isPassportPage: true, // 模板中模块标识
41 sourceType: sourceType, // 第三方登录来源 41 sourceType: sourceType, // 第三方登录来源
@@ -59,7 +59,7 @@ const bind = { @@ -59,7 +59,7 @@ const bind = {
59 let phoneNum = req.query.phoneNum; 59 let phoneNum = req.query.phoneNum;
60 60
61 res.render('bind/code', { 61 res.render('bind/code', {
62 - backUrl: helpers.urlFormat('/signin.html'), 62 + backUrl: helpers.urlFormat('passport/login'),
63 showHeaderImg: true, 63 showHeaderImg: true,
64 isPassportPage: true, 64 isPassportPage: true,
65 sourceType: sourceType, 65 sourceType: sourceType,
@@ -168,12 +168,16 @@ const bind = { @@ -168,12 +168,16 @@ const bind = {
168 }).then(result => { 168 }).then(result => {
169 let refer = req.cookies.refer; 169 let refer = req.cookies.refer;
170 170
171 - refer = refer ? decodeURI(refer) : helpers.urlFormat(); 171 + refer = refer ? decodeURI(refer) : helpers.urlFormat('/passport/bind/success?type=bind');
172 if (result && result.code && result.code === 200 && result.data.uid) { 172 if (result && result.code && result.code === 200 && result.data.uid) {
173 - AuthHelper.syncUserSession(result.data.uid, req, res);  
174 - result.data.refer = refer; 173 + return AuthHelper.syncUserSession(result.data.uid, req, res).then(() => {
  174 + result.data.refer = refer;
  175 + return result;
  176 + });
  177 + } else {
  178 + return { code: 400, message: '绑定失败', data: '' };
175 } 179 }
176 - return result; 180 +
177 }).then(result => { 181 }).then(result => {
178 res.json(result); 182 res.json(result);
179 }).catch(next); 183 }).catch(next);
@@ -200,10 +204,14 @@ const bind = { @@ -200,10 +204,14 @@ const bind = {
200 let refer = helpers.urlFormat('/passport/bind/success', { sourceType: sourceType }); 204 let refer = helpers.urlFormat('/passport/bind/success', { sourceType: sourceType });
201 205
202 if (result && result.code && result.code === 200 && result.data.uid) { 206 if (result && result.code && result.code === 200 && result.data.uid) {
203 - AuthHelper.syncUserSession(result.data.uid, req, res);  
204 - result.data.refer = refer; 207 + return AuthHelper.syncUserSession(result.data.uid, req, res).then(() => {
  208 + result.data.refer = refer;
  209 + return result;
  210 + });
  211 + } else {
  212 + return { code: 400, message: '关联失败', data: '' };
205 } 213 }
206 - return result; 214 +
207 }).then(result => { 215 }).then(result => {
208 res.json(result); 216 res.json(result);
209 }).catch(next); 217 }).catch(next);
@@ -212,11 +220,38 @@ const bind = { @@ -212,11 +220,38 @@ const bind = {
212 } 220 }
213 }, 221 },
214 222
  223 + passwordPage: (req, res) => {
  224 + let openId = req.query.openId;
  225 + let sourceType = req.query.sourceType;
  226 + let areaCode = req.query.areaCode || '86';
  227 + let phoneNum = req.query.phoneNum;
  228 + let code = req.query.code;
  229 +
  230 + res.render('bind/password', {
  231 + module: 'passport',
  232 + page: 'bind-password',
  233 + bindPwd: true, // js标识
  234 + backUrl: helpers.urlFormat('/passport/login'), // 返回的URL链接
  235 + showHeaderImg: true, // 控制显示头部图片
  236 + isPassportPage: true, // 模板中模块标识
  237 + sourceType: sourceType, // 第三方登录来源
  238 + openId: openId, // openId
  239 + areaCode: areaCode, // 国别码
  240 + phoneNum: phoneNum, // 国别码
  241 + code: code // 验证码
  242 + });
  243 + },
  244 +
215 successPage: (req, res) => { 245 successPage: (req, res) => {
  246 + let refer = req.cookies.refer;
  247 + let type = req.query.type;
  248 +
  249 + refer = refer ? decodeURI(refer) : helpers.urlFormat('/?go=1');
  250 +
216 res.render('bind/success', { 251 res.render('bind/success', {
217 isPassportPage: true, 252 isPassportPage: true,
218 - successTip: '恭喜您,第三方账号关联手机号码成功!',  
219 - goUrl: helpers.urlFormat(), 253 + successTip: type === 'bind' ? '恭喜您,第三方账号绑定手机号码成功!' : '恭喜您,第三方账号关联手机号码成功!',
  254 + goUrl: refer,
220 module: 'passport', 255 module: 'passport',
221 page: 'bind-success', 256 page: 'bind-success',
222 title: '绑定手机号' 257 title: '绑定手机号'
@@ -12,9 +12,10 @@ const cookie = global.yoho.cookie; @@ -12,9 +12,10 @@ const cookie = global.yoho.cookie;
12 const helpers = global.yoho.helpers; 12 const helpers = global.yoho.helpers;
13 const log = global.yoho.logger; 13 const log = global.yoho.logger;
14 const config = global.yoho.config; 14 const config = global.yoho.config;
  15 +const RegService = require('../models/reg-service');
15 const AuthHelper = require('../models/auth-helper'); 16 const AuthHelper = require('../models/auth-helper');
16 17
17 -const loginPage = `${config.siteUrl}/passport/login/index`; 18 +const loginPage = `${config.siteUrl}/passport/login`;
18 19
19 function doPassportCallback(openId, nickname, sourceType, req, res) { 20 function doPassportCallback(openId, nickname, sourceType, req, res) {
20 let shoppingKey = cookie.getShoppingKey(req); 21 let shoppingKey = cookie.getShoppingKey(req);
@@ -46,7 +47,7 @@ function doPassportCallback(openId, nickname, sourceType, req, res) { @@ -46,7 +47,7 @@ function doPassportCallback(openId, nickname, sourceType, req, res) {
46 return res.redirect(redirectTo); 47 return res.redirect(redirectTo);
47 }); 48 });
48 } else { 49 } else {
49 - return Promise.reject('openId is null'); 50 + return Promise.reject('missing third party login openId or nickname');
50 } 51 }
51 } 52 }
52 53
@@ -57,7 +58,7 @@ const common = { @@ -57,7 +58,7 @@ const common = {
57 if (!refer) { 58 if (!refer) {
58 refer = req.get('Referer'); 59 refer = req.get('Referer');
59 } 60 }
60 - refer && !/signin|login/.test(refer) && res.cookie('refer', encodeURI(refer), { 61 + refer && !/signin|login|passport/.test(refer) && res.cookie('refer', encodeURI(refer), {
61 domain: 'yohobuy.com' 62 domain: 'yohobuy.com'
62 }); 63 });
63 next(); 64 next();
@@ -66,24 +67,35 @@ const common = { @@ -66,24 +67,35 @@ const common = {
66 67
67 const local = { 68 const local = {
68 loginPage: (req, res) => { 69 loginPage: (req, res) => {
  70 + // 先清除cookie
  71 + res.clearCookie('LE' + md5('_LOGIN_EXPIRE'), {
  72 + domain: 'yohobuy.com'
  73 + });
  74 +
69 // 设置登录有效时间30分钟, 防机器刷,cache不稳定,改为cookie 75 // 设置登录有效时间30分钟, 防机器刷,cache不稳定,改为cookie
70 res.cookie('LE' + md5('_LOGIN_EXPIRE'), (new Date()).getTime() / 1000 + 1800); 76 res.cookie('LE' + md5('_LOGIN_EXPIRE'), (new Date()).getTime() / 1000 + 1800);
71 77
72 // 清除cookie 78 // 清除cookie
73 - res.clearCookie('_UID');  
74 - res.clearCookie('_TOKEN'); 79 + res.clearCookie('_UID', {
  80 + domain: 'yohobuy.com'
  81 + });
  82 + res.clearCookie('_TOKEN', {
  83 + domain: 'yohobuy.com'
  84 + });
75 85
76 res.render('login', { 86 res.render('login', {
77 loginIndex: true, // 模板中使用JS的标识 87 loginIndex: true, // 模板中使用JS的标识
78 - backUrl: 'javascript:history.go(-1)', // eslint-disable-line // 返回的URL链接 88 +
  89 + // 返回的URL链接
  90 + backUrl: 'javascript:history.go(-1)', // eslint-disable-line
79 showHeaderImg: true, // 控制显示头部图片 91 showHeaderImg: true, // 控制显示头部图片
80 isPassportPage: true, // 模板中模块标识 92 isPassportPage: true, // 模板中模块标识
81 - registerUrl: '/reg.html', // 注册的URL链接 93 + registerUrl: '/passport/reg/index', // 注册的URL链接
82 aliLoginUrl: '/passport/login/alipay', // 支付宝快捷登录的URL链接 94 aliLoginUrl: '/passport/login/alipay', // 支付宝快捷登录的URL链接
83 weiboLoginUrl: '/passport/login/sina', // 微博登录的URL链接 95 weiboLoginUrl: '/passport/login/sina', // 微博登录的URL链接
84 qqLoginUrl: '/passport/login/qq', // 腾讯QQ登录的URL链接 96 qqLoginUrl: '/passport/login/qq', // 腾讯QQ登录的URL链接
85 wechatLoginUrl: '/passport/login/wechat', // 微信登录的URL链接 97 wechatLoginUrl: '/passport/login/wechat', // 微信登录的URL链接
86 - internationalUrl: '/login.html', // 国际号登录的URL链接 98 + internationalUrl: '/passport/international', // 国际号登录的URL链接
87 phoneRetriveUrl: '/passport/back/mobile', // 通过手机号找回密码的URL链接 99 phoneRetriveUrl: '/passport/back/mobile', // 通过手机号找回密码的URL链接
88 emailRetriveUrl: '/passport/back/email', // 通过邮箱找回密码的URL链接 100 emailRetriveUrl: '/passport/back/email', // 通过邮箱找回密码的URL链接
89 module: 'passport', 101 module: 'passport',
@@ -91,6 +103,36 @@ const local = { @@ -91,6 +103,36 @@ const local = {
91 title: '登录' 103 title: '登录'
92 }); 104 });
93 }, 105 },
  106 + international: (req, res) => {
  107 + // 先清除cookie
  108 + res.clearCookie('LE' + md5('_LOGIN_EXPIRE'), {
  109 + domain: 'yohobuy.com'
  110 + });
  111 +
  112 + // 设置登录有效时间30分钟, 防机器刷,cache不稳定,改为cookie
  113 + res.cookie('LE' + md5('_LOGIN_EXPIRE'), (new Date()).getTime() / 1000 + 1800);
  114 +
  115 + // 清除cookie
  116 + res.clearCookie('_UID', {
  117 + domain: 'yohobuy.com'
  118 + });
  119 + res.clearCookie('_TOKEN', {
  120 + domain: 'yohobuy.com'
  121 + });
  122 +
  123 + res.render('international', {
  124 + // 返回的URL链接
  125 + backUrl: 'javascript:history.go(-1)', // eslint-disable-line
  126 + loginInternational: true, // 模板中使用JS的标识
  127 + isPassportPage: true, // 模板中模块标识
  128 + headerText: '登录',
  129 + areaCode: '+86', // 默认区号
  130 + countrys: RegService.getAreaData(), // 地区信息列表
  131 + module: 'passport',
  132 + page: 'international',
  133 + title: '国际账号登录'
  134 + });
  135 + },
94 login: (req, res, next) => { 136 login: (req, res, next) => {
95 passport.authenticate('local', (err, user) => { 137 passport.authenticate('local', (err, user) => {
96 if (err) { 138 if (err) {
@@ -205,8 +247,9 @@ const qq = { @@ -205,8 +247,9 @@ const qq = {
205 log.error(`qq authenticate error : ${JSON.stringify(err)}`); 247 log.error(`qq authenticate error : ${JSON.stringify(err)}`);
206 return res.redirect(loginPage); 248 return res.redirect(loginPage);
207 } 249 }
  250 +
208 let nickname = user.nickname; 251 let nickname = user.nickname;
209 - let openId = user.openid; 252 + let openId = user.id;
210 253
211 doPassportCallback(openId, nickname, 'qq', req, res).catch(next); 254 doPassportCallback(openId, nickname, 'qq', req, res).catch(next);
212 })(req, res, next); 255 })(req, res, next);
@@ -26,7 +26,7 @@ let index = (req, res) => { @@ -26,7 +26,7 @@ let index = (req, res) => {
26 26
27 res.render('reg/index', { 27 res.render('reg/index', {
28 title: '注册', 28 title: '注册',
29 - backUrl: 'javascript:history.go(-1)', // eslint-disable-line 29 + backUrl: 'javascript:history.go(-1)', // eslint-disable-line
30 headerText: '注册', // 头部信息 30 headerText: '注册', // 头部信息
31 isPassportPage: true, // 模板中模块标识 31 isPassportPage: true, // 模板中模块标识
32 areaCode: '+86', // 默认的区号 32 areaCode: '+86', // 默认的区号
@@ -235,14 +235,13 @@ let setPassword = (req, res, next) => { @@ -235,14 +235,13 @@ let setPassword = (req, res, next) => {
235 let shoppingKey = cookie.getShoppingKey(req); 235 let shoppingKey = cookie.getShoppingKey(req);
236 236
237 // 验证注册的标识码是否有效 237 // 验证注册的标识码是否有效
238 - RegService.regMobile(area, mobile, password, shoppingKey).then((result) => { 238 + RegService.regMobileAes(area, mobile, password, shoppingKey).then((result) => {
239 if (!result.code || result.code !== 200) { 239 if (!result.code || result.code !== 200) {
240 return Promise.reject(result); 240 return Promise.reject(result);
241 } 241 }
242 if (!result.data || !result.data.uid) { 242 if (!result.data || !result.data.uid) {
243 return Promise.reject(result); 243 return Promise.reject(result);
244 } 244 }
245 -  
246 return AuthHelper.syncUserSession(result.data.uid, req, res); 245 return AuthHelper.syncUserSession(result.data.uid, req, res);
247 }).then(() => { 246 }).then(() => {
248 // 返回跳转到来源页面 247 // 返回跳转到来源页面
  1 +/**
  2 + * 登录注册密码加密
  3 + * @author: wsl<shuiling.wang@yoho.cn>
  4 + * @date: 2016/07/07
  5 + */
  6 +
  7 +'use strict';
  8 +
  9 +const crypto = require('crypto');
  10 +
  11 +const aesPwd = (pwd) => {
  12 + let algorithm = 'aes-128-ecb';
  13 + let key = 'yoho9646yoho9646';
  14 + let clearEncoding = 'utf8';
  15 + let cipherEncoding = 'base64';
  16 + let iv = '';
  17 + let cipher = crypto.createCipheriv(algorithm, key, iv);
  18 + let cipherChunks = [];
  19 +
  20 + cipherChunks.push(cipher.update(pwd, clearEncoding, cipherEncoding));
  21 + cipherChunks.push(cipher.final(cipherEncoding));
  22 +
  23 + return cipherChunks.join('');
  24 +};
  25 +
  26 +module.exports = {
  27 + aesPwd
  28 +};
1 'use strict'; 1 'use strict';
2 - 2 +const aes = require('./aes-pwd');
3 const sign = global.yoho.sign; 3 const sign = global.yoho.sign;
4 const api = global.yoho.API; 4 const api = global.yoho.API;
5 5
@@ -20,6 +20,21 @@ class Auth { @@ -20,6 +20,21 @@ class Auth {
20 return api.post('', param); 20 return api.post('', param);
21 } 21 }
22 22
  23 + static signinAes(area, profile, password, shoppingKey) {
  24 + let param = {
  25 + method: 'app.passport.signinAES',
  26 + area: area,
  27 + profile: profile,
  28 + password: aes.aesPwd(password)
  29 + };
  30 +
  31 + if (shoppingKey) {
  32 + param.shopping_key = shoppingKey;
  33 + }
  34 +
  35 + return api.post('', param);
  36 + }
  37 +
23 static signinByOpenID(nickname, openId, sourceType, shoppingKey) { 38 static signinByOpenID(nickname, openId, sourceType, shoppingKey) {
24 let param = { 39 let param = {
25 nickname: nickname, 40 nickname: nickname,
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 6
7 7
8 const api = global.yoho.API; 8 const api = global.yoho.API;
  9 +const aes = require('./aes-pwd');
9 10
10 const YOHOBUY_URL = 'http://www.yohobuy.com/'; 11 const YOHOBUY_URL = 'http://www.yohobuy.com/';
11 12
@@ -66,6 +67,20 @@ const modifyPasswordByEmailAsync = (pwd, code) => { @@ -66,6 +67,20 @@ const modifyPasswordByEmailAsync = (pwd, code) => {
66 }; 67 };
67 68
68 /** 69 /**
  70 + * 根据邮箱验证码修改密码(调用新接口 采用AES密码加密)
  71 + *
  72 + * @param string pwd 新密码
  73 + * @param string code 邮箱验证码
  74 + */
  75 +const modifyPasswordByEmailAsyncAes = (pwd, code) => {
  76 + return api.get('', {
  77 + code: code,
  78 + newPwd: aes.aesPwd(pwd),
  79 + method: 'app.register.resetPwdByCodeAES'
  80 + });
  81 +};
  82 +
  83 +/**
69 * 通过手机找回密码 84 * 通过手机找回密码
70 * 85 *
71 * @param string mobile 手机号 86 * @param string mobile 手机号
@@ -113,12 +128,24 @@ const modifyPasswordByMobileAsync = (mobile, token, newpwd, area) => { @@ -113,12 +128,24 @@ const modifyPasswordByMobileAsync = (mobile, token, newpwd, area) => {
113 }); 128 });
114 }; 129 };
115 130
  131 +const modifyPasswordByMobileAsyncAes = (mobile, token, newpwd, area) => {
  132 + return api.get('', {
  133 + mobile: mobile,
  134 + token: token,
  135 + newpwd: aes.aesPwd(newpwd),
  136 + area: area,
  137 + method: 'app.register.changepwdByMobileCodeAES'
  138 + });
  139 +};
  140 +
116 module.exports = { 141 module.exports = {
117 getAreaDataAsync, 142 getAreaDataAsync,
118 sendCodeToEmailAsync, 143 sendCodeToEmailAsync,
119 modifyPasswordByEmailAsync, 144 modifyPasswordByEmailAsync,
  145 + modifyPasswordByEmailAsyncAes,
120 sendCodeToMobileAsync, 146 sendCodeToMobileAsync,
121 validateMobileCodeAsync, 147 validateMobileCodeAsync,
122 - modifyPasswordByMobileAsync 148 + modifyPasswordByMobileAsync,
  149 + modifyPasswordByMobileAsyncAes
123 }; 150 };
124 151
@@ -43,10 +43,13 @@ function paramsToRaw(params) { @@ -43,10 +43,13 @@ function paramsToRaw(params) {
43 function AlipayStrategy(options, verify) { 43 function AlipayStrategy(options, verify) {
44 if (typeof options === 'function') { 44 if (typeof options === 'function') {
45 verify = options; 45 verify = options;
  46 + options = {};
46 } 47 }
  48 + options = options || {};
47 passport.Strategy.call(this); 49 passport.Strategy.call(this);
48 this.name = 'alipay'; 50 this.name = 'alipay';
49 this._verify = verify; 51 this._verify = verify;
  52 + this._options = options;
50 } 53 }
51 54
52 util.inherits(AlipayStrategy, passport.Strategy); 55 util.inherits(AlipayStrategy, passport.Strategy);
@@ -60,18 +63,17 @@ AlipayStrategy.prototype.authenticate = function(req, options) { @@ -60,18 +63,17 @@ AlipayStrategy.prototype.authenticate = function(req, options) {
60 63
61 delete query.sign_type; 64 delete query.sign_type;
62 delete query.sign; 65 delete query.sign;
63 - let signString = paramsToRaw(query) + options.key; 66 + let signString = paramsToRaw(query) + this._options.key;
64 67
65 if (signType === 'MD5' && sign !== md5(signString)) { 68 if (signType === 'MD5' && sign !== md5(signString)) {
66 this.error('alipay callback sign check fail'); 69 this.error('alipay callback sign check fail');
67 this.fail('alipay callback sign check fail'); 70 this.fail('alipay callback sign check fail');
68 - return;  
69 } 71 }
70 72
71 if (req.query.is_success === 'T') { 73 if (req.query.is_success === 'T') {
72 let user = { 74 let user = {
73 userId: req.query.user_id, 75 userId: req.query.user_id,
74 - realName: req.query.realName, 76 + realName: req.query.real_name,
75 email: req.query.email 77 email: req.query.email
76 }; 78 };
77 79
@@ -81,12 +83,14 @@ AlipayStrategy.prototype.authenticate = function(req, options) { @@ -81,12 +83,14 @@ AlipayStrategy.prototype.authenticate = function(req, options) {
81 this.fail(req.error_code); 83 this.fail(req.error_code);
82 } 84 }
83 } else { 85 } else {
84 - let params = _.assign(defaultOptions, options); 86 + let params = _.assign(defaultOptions, this._options, options);
85 let signType = params.sign_type; 87 let signType = params.sign_type;
  88 + let key = params.key;
86 89
87 delete params.sign_type; 90 delete params.sign_type;
88 delete params.sign; 91 delete params.sign;
89 - let signString = paramsToRaw(params) + options.key; 92 + delete params.key;
  93 + let signString = paramsToRaw(params) + key;
90 94
91 if (signType === 'MD5') { 95 if (signType === 'MD5') {
92 params.sign = md5(signString); 96 params.sign = md5(signString);
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 'use strict'; 8 'use strict';
9 9
10 const api = global.yoho.API; 10 const api = global.yoho.API;
  11 +const aes = require('./aes-pwd');
11 12
12 const RegService = { 13 const RegService = {
13 getAreaData() { 14 getAreaData() {
@@ -94,6 +95,20 @@ const RegService = { @@ -94,6 +95,20 @@ const RegService = {
94 } 95 }
95 96
96 return api.post('', params); 97 return api.post('', params);
  98 + },
  99 + regMobileAes(area, mobile, password, shoppingKey) {
  100 + let params = {
  101 + method: 'app.passport.registerAES',
  102 + area: area,
  103 + profile: mobile,
  104 + password: aes.aesPwd(password)
  105 + };
  106 +
  107 + if (shoppingKey) {
  108 + params.shopping_key = shoppingKey;
  109 + }
  110 +
  111 + return api.post('', params);
97 } 112 }
98 }; 113 };
99 114
@@ -16,70 +16,80 @@ const reg = require(cRoot + '/reg'); @@ -16,70 +16,80 @@ const reg = require(cRoot + '/reg');
16 16
17 const router = express.Router(); // eslint-disable-line 17 const router = express.Router(); // eslint-disable-line
18 18
  19 +// 兼容老的路由
  20 +router.get('/signin.html', login.common.beforeLogin, login.local.loginPage);
  21 +router.get('/reg.html', reg.index);
  22 +
19 // 登出 23 // 登出
20 -router.get('/signout/index', login.local.logout); 24 +router.get('/passport/signout/index', login.local.logout);
21 25
22 // 登录页面 26 // 登录页面
23 -router.get('/login', login.common.beforeLogin, login.local.loginPage); 27 +router.get('/passport/login', login.common.beforeLogin, login.local.loginPage);
  28 +router.get('/passport/international', login.common.beforeLogin, login.local.international);
24 29
25 // 本地登录 30 // 本地登录
26 -router.post('/login/auth', login.local.login); 31 +router.post('/passport/login/auth', login.local.login);
27 32
28 // 微信登录 33 // 微信登录
29 -router.get('/login/wechat', login.common.beforeLogin, login.wechat.login);  
30 -router.get('/login/wechat/callback', login.wechat.callback); 34 +router.get('/passport/login/wechat', login.common.beforeLogin, login.wechat.login);
  35 +router.get('/passport/login/wechat/callback', login.wechat.callback);
31 36
32 // sina登录 37 // sina登录
33 -router.get('/login/sina', login.common.beforeLogin, login.sina.login);  
34 -router.get('/login/sina/callback', login.sina.callback); 38 +router.get('/passport/login/sina', login.common.beforeLogin, login.sina.login);
  39 +router.get('/passport/login/sina/callback', login.sina.callback);
35 40
36 // qq登录 41 // qq登录
37 -router.get('/login/qq', login.common.beforeLogin, login.qq.login);  
38 -router.get('/login/qq/callback', login.qq.callback); 42 +router.get('/passport/login/qq', login.common.beforeLogin, login.qq.login);
  43 +router.get('/passport/login/qq/callback', login.qq.callback);
  44 +
  45 +// 支付宝登录
  46 +router.get('/passport/login/alipay', login.common.beforeLogin, login.alipay.login);
  47 +router.get('/passport/login/alipay/callback', login.alipay.callback);
39 48
40 // alipay登录 49 // alipay登录
41 router.get('/login/alipay', login.common.beforeLogin, login.alipay.login); 50 router.get('/login/alipay', login.common.beforeLogin, login.alipay.login);
42 router.get('/login/alipay/callback', login.alipay.callback); 51 router.get('/login/alipay/callback', login.alipay.callback);
43 52
44 // 登录绑定 53 // 登录绑定
45 -router.get('/bind/index', bind.indexPage);  
46 -router.post('/bind/bindCheck', bind.bindCheck);  
47 -router.get('/bind/code', bind.codePage);  
48 -router.post('/bind/sendBindMsg', bind.sendBindMsg);  
49 -router.post('/bind/bindMobile', bind.bindMobile); 54 +router.get('/passport/bind/index', bind.indexPage);
  55 +router.post('/passport/bind/bindCheck', bind.bindCheck);
  56 +router.get('/passport/bind/code', bind.codePage);
  57 +router.post('/passport/bind/sendBindMsg', bind.sendBindMsg);
  58 +router.post('/passport/bind/bindMobile', bind.bindMobile);
50 59
51 -router.post('/bind/relateMobile', bind.relateMobile);  
52 -router.get('/bind/success', bind.successPage); 60 +router.post('/passport/bind/relateMobile', bind.relateMobile);
  61 +router.get('/passport/bind/password', bind.passwordPage);
  62 +router.get('/passport/bind/success', bind.successPage);
53 63
54 -router.post('/bind/changeCheck', bind.changeCheck);  
55 -router.post('/bind/changeMobile', bind.changeMobile); 64 +router.post('/passport/bind/changeCheck', bind.changeCheck);
  65 +router.post('/passport/bind/changeMobile', bind.changeMobile);
56 66
57 /** 67 /**
58 * 注册 68 * 注册
59 */ 69 */
60 -router.get('/reg/index', reg.index);  
61 -router.post('/reg/verifymobile', reg.verifyMobile);  
62 -router.get('/reg/code', reg.code);  
63 -router.post('/reg/sendcode', reg.sendCode);  
64 -router.post('/reg/verifycode', reg.verifyCode);  
65 -router.get('/reg/password', reg.password);  
66 -router.post('/reg/setpassword', reg.setPassword); 70 +router.get('/passport/reg/index', reg.index);
  71 +router.post('/passport/reg/verifymobile', reg.verifyMobile);
  72 +router.get('/passport/reg/code', reg.code);
  73 +router.post('/passport/reg/sendcode', reg.sendCode);
  74 +router.post('/passport/reg/verifycode', reg.verifyCode);
  75 +router.get('/passport/reg/password', reg.password);
  76 +router.post('/passport/reg/setpassword', reg.setPassword);
67 77
68 /** 78 /**
69 * 密码找回 79 * 密码找回
70 */ 80 */
71 -router.get('/back/email', back.indexEmailPage);// 通过邮箱找回密码页面  
72 -router.post('/back/sendemail', back.sendCodeToEmailAPI);// 发送邮箱验证码  
73 -router.get('/back/resendemail', back.resendCodeToEmailAPI);// 重新发送邮箱验证码  
74 -router.get('/back/success', back.backSuccessByEmailPage);// 邮箱找回密码-发送成功页面  
75 -  
76 -router.get('/back/mobile', back.indexMobilePage);// 输入手机号找回密码页面  
77 -router.get('/back/mobilecode', back.verifyCodeByMobilePage);// 输入手机验证码页面  
78 -router.post('/back/sendcode', back.sendCodeToMobileAPI);// 发送手机验证码  
79 -router.post('/back/verifycode', back.verifyCodeByMobileAPI);// 校验手机验证码  
80 -  
81 -router.get('/back/backcode', back.setNewPasswordByMobilePage);// 设置新密码页面  
82 -router.post('/back/passwordbyemail', back.setNewPasswordByEmailAPI);// 依据邮箱验证码修改密码  
83 -router.post('/back/passwordbymobile', back.setNewPasswordByMobileAPI);// 依据手机验证码修改密码 81 +router.get('/passport/back/email', back.indexEmailPage);// 通过邮箱找回密码页面
  82 +router.post('/passport/back/sendemail', back.sendCodeToEmailAPI);// 发送邮箱验证码
  83 +router.get('/passport/back/resendemail', back.resendCodeToEmailAPI);// 重新发送邮箱验证码
  84 +router.get('/passport/back/success', back.backSuccessByEmailPage);// 邮箱找回密码-发送成功页面
  85 +
  86 +router.get('/passport/back/mobile', back.indexMobilePage);// 输入手机号找回密码页面
  87 +router.get('/passport/back/mobilecode', back.verifyCodeByMobilePage);// 输入手机验证码页面
  88 +router.post('/passport/back/sendcode', back.sendCodeToMobileAPI);// 发送手机验证码
  89 +router.post('/passport/back/verifycode', back.verifyCodeByMobileAPI);// 校验手机验证码
  90 +
  91 +router.get('/passport/back/backcode', back.setNewPasswordByMobilePage);// 设置新密码页面
  92 +router.post('/passport/back/passwordbyemail', back.setNewPasswordByEmailAPI);// 依据邮箱验证码修改密码
  93 +router.post('/passport/back/passwordbymobile', back.setNewPasswordByMobileAPI);// 依据手机验证码修改密码
84 94
85 module.exports = router; 95 module.exports = router;
  1 +<div class="login-international-page passport-page yoho-page">
  2 + {{> passport/header}}
  3 + <div class="content">
  4 + {{> passport/country_list}}
  5 + <div class="input-container phone-container row has-clear">
  6 + <span id="area-code" class="area-code">{{areaCode}}</span>
  7 + <input id="phone-num" class="input phone-num" type="text" placeholder="手机号" value={{phoneNum}}>
  8 + </div>
  9 + <div class="input-container row has-eye">
  10 + <input id="pwd" class="pwd input" type="password" placeholder="密码">
  11 + </div>
  12 + <span id="btn-login" class="btn btn-login disble row">登录</span>
  13 + </div>
  14 +</div>
@@ -10,10 +10,10 @@ module.exports = app => { @@ -10,10 +10,10 @@ module.exports = app => {
10 10
11 // 四个频道页,频道选择页面 /boys,/girls,/,/kids,/lifestyle 等页面,就直接占用路由了 11 // 四个频道页,频道选择页面 /boys,/girls,/,/kids,/lifestyle 等页面,就直接占用路由了
12 app.use(require('./apps/channel')); 12 app.use(require('./apps/channel'));
  13 + app.use(require('./apps/passport'));
13 14
14 // 业务模块 15 // 业务模块
15 app.use('/product', require('./apps/product')); 16 app.use('/product', require('./apps/product'));
16 app.use('/guang', require('./apps/guang')); 17 app.use('/guang', require('./apps/guang'));
17 - app.use('/passport', require('./apps/passport'));  
18 app.use('/activity', require('./apps/activity')); 18 app.use('/activity', require('./apps/activity'));
19 }; 19 };
  1 +require('./bind/password');
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 * @author: xuqi<qi.xu@yoho.cn> 3 * @author: xuqi<qi.xu@yoho.cn>
4 * @date: 2015/10/8 4 * @date: 2015/10/8
5 */ 5 */
6 -var $ = require('jquery'); 6 +var $ = require('yoho-jquery');
7 7
8 var $pwd = $('#pwd'), 8 var $pwd = $('#pwd'),
9 $btnSure = $('#btn-sure'); 9 $btnSure = $('#btn-sure');
@@ -14,8 +14,7 @@ var tip = require('../../plugin/tip'); @@ -14,8 +14,7 @@ var tip = require('../../plugin/tip');
14 var trim = $.trim; 14 var trim = $.trim;
15 var showErrTip = tip.show; 15 var showErrTip = tip.show;
16 16
17 -var nickname = $('#nickname').val(),  
18 - sourceType = $('#sourceType').val(), 17 +var sourceType = $('#sourceType').val(),
19 openId = $('#openId').val(), 18 openId = $('#openId').val(),
20 phoneNum = $('#phone-num').val(), 19 phoneNum = $('#phone-num').val(),
21 areaCode = $('#area-code').val().replace('+', ''), 20 areaCode = $('#area-code').val().replace('+', ''),
@@ -30,7 +29,6 @@ function startBind(password) { @@ -30,7 +29,6 @@ function startBind(password) {
30 phoneNum: phoneNum, 29 phoneNum: phoneNum,
31 openId: openId, 30 openId: openId,
32 sourceType: sourceType, 31 sourceType: sourceType,
33 - nickname: nickname,  
34 password: password, 32 password: password,
35 code: code 33 code: code
36 }, 34 },
  1 +require('./login/international');
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 * @author: xuqi<qi.xu@yoho.cn> 3 * @author: xuqi<qi.xu@yoho.cn>
4 * @date: 2015/10/8 4 * @date: 2015/10/8
5 */ 5 */
6 -var $ = require('jquery'); 6 +var $ = require('yoho-jquery');
7 7
8 var $phoneNum = $('#phone-num'), 8 var $phoneNum = $('#phone-num'),
9 $countrySelect = $('#country-select'), 9 $countrySelect = $('#country-select'),
@@ -12,3 +12,4 @@ @@ -12,3 +12,4 @@
12 @import "passport/index"; 12 @import "passport/index";
13 @import "guang/index"; 13 @import "guang/index";
14 @import "cart/chose-panel"; 14 @import "cart/chose-panel";
  15 +@import "me/index";
  1 +@import 'suggest';
  1 +.yoho-suggest-page {
  2 + width: 100%;
  3 + height: auto;
  4 +
  5 + /* 意见反馈头部 */
  6 + .suggest-header {
  7 + text-align: center;
  8 + color: #fff;
  9 + font-size: 26px;
  10 + line-height: 46px;
  11 + overflow: hidden;
  12 + padding-bottom: 20px;
  13 + background-image: linear-gradient(#383838, #505050);
  14 +
  15 + &:before {
  16 + content: '';
  17 + display: block;
  18 + background: url("/me/suggest/suggest-logo.png");
  19 + width: 104px;
  20 + height: 35px;
  21 + margin: 10px auto 15px;
  22 + }
  23 + }
  24 +
  25 + /* 意见反馈主体 */
  26 + .suggest-content {
  27 + border-top: 1px solid #e0e0e0;
  28 + }
  29 +
  30 + .suggest-item {
  31 + width: 100%;
  32 + color: #444;
  33 + border-top: 1px solid #e0e0e0;
  34 + border-bottom: 30px solid #f0f0f0;
  35 + overflow: hidden;
  36 +
  37 + .suggest-item-img {
  38 + width: 100%;
  39 + overflow: hidden;
  40 + > img {
  41 + margin: 0 auto;
  42 + display: block;
  43 + max-width: 100%;
  44 + }
  45 + }
  46 +
  47 + > h2 {
  48 + font-size: 38px;
  49 + margin: 30px 0 31px;
  50 + padding: 0 35px;
  51 + }
  52 +
  53 + > p {
  54 + font-size: 26px;
  55 + line-height: 48px;
  56 + padding: 0 35px;
  57 + }
  58 + }
  59 +
  60 + .suggest-type {
  61 + margin-top: 29px - 11px;
  62 + height: 88px;
  63 + line-height: 88px;
  64 + border-top: 1px solid #e0e0e0;
  65 + border-bottom: 1px solid #e0e0e0;
  66 + color: #b0b0b0;
  67 + font-size: 26px;
  68 + display: none;
  69 + text-align: center;
  70 +
  71 + > .active {
  72 + color: #444;
  73 + }
  74 +
  75 + &.show {
  76 + display: block;
  77 + }
  78 + }
  79 +
  80 + .suggest-active {
  81 + > div {
  82 + width: 50%;
  83 + height: 100%;
  84 + float: left;
  85 + text-align: left;
  86 + padding-left: 128px;
  87 + box-sizing: border-box;
  88 + }
  89 +
  90 + > div:nth-last-of-type(1) {
  91 + padding-left: 0;
  92 + padding-right: 128px;
  93 + text-align: right;
  94 + float: right;
  95 +
  96 + > span {
  97 +
  98 + display: inline-block;
  99 + height: 100%;
  100 + overflow: hidden;
  101 +
  102 + &:nth-of-type(1) {
  103 + transform: rotate(180deg);
  104 + }
  105 + }
  106 + }
  107 + }
  108 +
  109 + .suggest-bad {
  110 + > div {
  111 + > span {
  112 + display: inline-block;
  113 + height: 100%;
  114 + overflow: hidden;
  115 +
  116 + &:nth-of-type(1) {
  117 + transform: rotate(180deg);
  118 + }
  119 + }
  120 + }
  121 + }
  122 +
  123 + /* 发表意见 */
  124 + .create-new-suggest {
  125 + display: block;
  126 + width: 100%;
  127 + height: 88px;
  128 + line-height: 88px;
  129 + text-align: center;
  130 + font-size: 30px;
  131 + border-top: 30px solid #f0f0f0;
  132 + border-bottom: 30px solid #f0f0f0;
  133 + position: relative;
  134 +
  135 + .list-item {
  136 + padding: 0 35px;
  137 + }
  138 + .new-right {
  139 + float: right;
  140 + margin-left: 40px;
  141 + color: #e0e0e0;
  142 + }
  143 +
  144 + a {
  145 + color: #444;
  146 + display: inline-block;
  147 + }
  148 +
  149 + }
  150 +}
  151 +
  152 +/* 提交页面 */
  153 +.yoho-suggest-sub-page {
  154 + width: 100%;
  155 + background: #f0f0f0;
  156 +
  157 + .suggest-sub-form {
  158 + background: #fff;
  159 + width: 100%;
  160 +
  161 + #suggest-textarea {
  162 + box-sizing: border-box;
  163 + width: 100%;
  164 + max-width: 100%;
  165 + min-width: 100%;
  166 + height: 255px;
  167 + max-height: 255px;
  168 + min-height: 255px;
  169 + padding: 30px;
  170 + font-size: 26px;
  171 + line-height: 48px;
  172 + color: #000;
  173 + display: block;
  174 + background: #fff;
  175 + border: none;
  176 + outline: none;
  177 + resize: none;
  178 + }
  179 + }
  180 +
  181 + .img-form {
  182 + padding: 0 30px;
  183 + padding-top: 40px;
  184 + overflow: hidden;
  185 +
  186 + .upload-img-list {
  187 + float: left;
  188 +
  189 + > li {
  190 + display: block;
  191 + width: 130px;
  192 + height: 130px;
  193 + float: left;
  194 + margin-right: 30px;
  195 + background: resolve('common/loading.gif') center center no-repeat;
  196 + background-size: 50%;
  197 + position: relative;
  198 +
  199 + > img {
  200 + display: block;
  201 + width: 100%;
  202 + height: 100%;
  203 + overflow: hidden;
  204 + }
  205 +
  206 + > span {
  207 + display: block;
  208 + background: url("/me/suggest/sub_del.png");
  209 + width: 42px;
  210 + height: 42px;
  211 +
  212 + position: absolute;
  213 + top: -21px;
  214 + right: -21px;
  215 +
  216 + }
  217 + }
  218 + }
  219 +
  220 + .img-add {
  221 + display: block;
  222 + width: 130px;
  223 + height: 130px;
  224 + border: 1px dashed #e0e0e0;
  225 + position: relative;
  226 + text-indent: -1000px;
  227 + float: left;
  228 +
  229 + &:after {
  230 + content: '';
  231 + display: block;
  232 + background: url("/me/suggest/suggest-add.png");
  233 + width: 72px;
  234 + height: 72px;
  235 +
  236 + position: absolute;
  237 + top: 50%;
  238 + left: 50%;
  239 + margin-top: -36px;
  240 + margin-left: -36px;
  241 + }
  242 +
  243 + input[type="file"] {
  244 + position: absolute;
  245 + opacity: 0.2;
  246 + border: none;
  247 + outline: none;
  248 + display: block;
  249 +
  250 + width: 130px;
  251 + height: 130px;
  252 +
  253 + top: 0;
  254 + left: 0;
  255 + }
  256 + }
  257 + }
  258 +}
  259 +
  260 +/* dialog */
  261 +.dialog-wrapper {
  262 + background: hsla(0, 0%, 0%, 0.5);
  263 + position: fixed;
  264 + top: 0;
  265 + right: 0;
  266 + bottom: 0;
  267 + left: 0;
  268 + display: none;
  269 +
  270 + .dialog-box {
  271 + width: 540px;
  272 + border-radius: 20px;
  273 + background: hsla(100, 100%, 100%, 0.8);
  274 + position: absolute;
  275 + left: 50%;
  276 + margin-left: -270px;
  277 + font-size: 30px;
  278 + text-align: center;
  279 + color: #000;
  280 + }
  281 +
  282 + .dialog-content {
  283 + padding: 60px 30px;
  284 + }
  285 +
  286 + .dialog-footer {
  287 + border-top: 1px solid #ccc;
  288 + height: 88px;
  289 + line-height: 88px;
  290 +
  291 + > span {
  292 + display: block;
  293 + width: 50%;
  294 + height: 100%;
  295 + float: left;
  296 + box-sizing: border-box;
  297 +
  298 + &:nth-last-of-type(1) {
  299 + border-left: 1px solid #ccc;
  300 + color: #e01;
  301 + }
  302 + }
  303 +
  304 + > span:active {
  305 + background-color: #ccc;
  306 + }
  307 + }
  308 +}
@@ -74,11 +74,13 @@ body.passport-body { @@ -74,11 +74,13 @@ body.passport-body {
74 padding-right: 40PX; 74 padding-right: 40PX;
75 right: 0; 75 right: 0;
76 color: #fff; 76 color: #fff;
77 - background-color: transparent; 77 + background-color: #575757;
78 border: 0; 78 border: 0;
79 border-radius: 5PX; 79 border-radius: 5PX;
80 appearance: none; 80 appearance: none;
81 direction: rtl; 81 direction: rtl;
  82 + -webkit-appearance: none;
  83 +
82 &:focus { 84 &:focus {
83 outline: 0; 85 outline: 0;
84 border: none; 86 border: none;
@@ -2,28 +2,28 @@ @@ -2,28 +2,28 @@
2 color: #fefefe; 2 color: #fefefe;
3 3
4 .success-icon { 4 .success-icon {
5 - width: 74px;  
6 - height: 74px;  
7 - margin: 60px auto 30px; 5 + width: 74PX;
  6 + height: 74PX;
  7 + margin: 60PX auto 30PX;
8 background: resolve("passport/success.png"); 8 background: resolve("passport/success.png");
9 background-size: 100%; 9 background-size: 100%;
10 } 10 }
11 11
12 .success-tip { 12 .success-tip {
13 - padding: 10px;  
14 - font-size: 16px; 13 + padding: 10PX;
  14 + font-size: 16PX;
15 line-height: 1.5; 15 line-height: 1.5;
16 } 16 }
17 17
18 .go { 18 .go {
19 display: block; 19 display: block;
20 - margin: 30px auto;  
21 - width: 270px;  
22 - height: 40px;  
23 - font-size: 14px;  
24 - line-height: 40px; 20 + margin: 30PX auto;
  21 + width: 270PX;
  22 + height: 40PX;
  23 + font-size: 14PX;
  24 + line-height: 40PX;
25 color: #fff; 25 color: #fff;
26 background: rgba(255, 255, 255, 0.4); 26 background: rgba(255, 255, 255, 0.4);
27 - border-radius: 5px; 27 + border-radius: 5PX;
28 } 28 }
29 } 29 }