Authored by 郭成尧

Merge branch 'master' into feature/giftcard

@@ -286,17 +286,14 @@ const getOrders = (params) => { @@ -286,17 +286,14 @@ const getOrders = (params) => {
286 286
287 let perOrder = _getOrderStatus(value); 287 let perOrder = _getOrderStatus(value);
288 288
289 - /* 是否是虚拟商品 */  
290 - let isTickets = order.virtual_type && parseInt(order.virtual_type, 10) === 3;  
291 -  
292 Object.assign(perOrder, { 289 Object.assign(perOrder, {
293 orderNum: value.order_code, 290 orderNum: value.order_code,
294 orderStatus: value.status_str, 291 orderStatus: value.status_str,
295 sumCost: value.amount, 292 sumCost: value.amount,
296 - goods: _formatOrderGoods(value.order_goods, count, false, isTickets), 293 + goods: _formatOrderGoods(value.order_goods, count, false),
297 detailUrl: helpers.urlFormat('/home/orderdetail', {order_code: value.order_code}), 294 detailUrl: helpers.urlFormat('/home/orderdetail', {order_code: value.order_code}),
298 count: value.buy_total, 295 count: value.buy_total,
299 - isVirtual: isTickets, 296 + isVirtual: _.get(value, 'order_goods[0].goods_type'),
300 orderTitle: value.order_title 297 orderTitle: value.order_title
301 }); 298 });
302 299
@@ -129,9 +129,9 @@ @@ -129,9 +129,9 @@
129 </a> 129 </a>
130 </div> 130 </div>
131 <div class="group-list"> 131 <div class="group-list">
132 - <a class="list-item invite" href="http://activity.yoho.cn/feature/357.html?share_id=2391&title=邀请好友50元现金券无限赚"> 132 + <a class="list-item invite" href="http://activity.yoho.cn/feature/623.html?share_id=2795&title=邀请好友100元现金券无限赚">
133 <span class="horn"></span> 133 <span class="horn"></span>
134 - 邀请好友,50元现金券无限赚 134 + 邀请好友,100元礼券无限赚!
135 <span class="iconfont num">&#xe604;</span> 135 <span class="iconfont num">&#xe604;</span>
136 </a> 136 </a>
137 <a class="list-item message" href="/home/message"> 137 <a class="list-item message" href="/home/message">
@@ -228,10 +228,11 @@ const bind = { @@ -228,10 +228,11 @@ const bind = {
228 let refer = helpers.urlFormat('/passport/bind/success?type=bind'); 228 let refer = helpers.urlFormat('/passport/bind/success?type=bind');
229 229
230 if (result && result.code && result.code === 200 && result.data.uid) { 230 if (result && result.code && result.code === 200 && result.data.uid) {
231 - return AuthHelper.syncUserSession(result.data.uid, req, res, result.data.session_key).then(() => {  
232 - result.data.refer = refer;  
233 - return result;  
234 - }); 231 + return AuthHelper.syncUserSession(result.data.uid, req, res, result.data.session_key)
  232 + .then((authData) => {
  233 + result.data.refer = _.get(authData, 'refer') || refer;
  234 + return result;
  235 + });
235 } else { 236 } else {
236 return { code: 400, message: '绑定失败', data: '' }; 237 return { code: 400, message: '绑定失败', data: '' };
237 } 238 }
@@ -262,10 +263,11 @@ const bind = { @@ -262,10 +263,11 @@ const bind = {
262 let refer = helpers.urlFormat('/passport/bind/success', { sourceType: sourceType }); 263 let refer = helpers.urlFormat('/passport/bind/success', { sourceType: sourceType });
263 264
264 if (result && result.code && result.code === 200 && result.data.uid) { 265 if (result && result.code && result.code === 200 && result.data.uid) {
265 - return AuthHelper.syncUserSession(result.data.uid, req, res, result.data.session_key).then(() => {  
266 - result.data.refer = refer;  
267 - return result;  
268 - }); 266 + return AuthHelper.syncUserSession(result.data.uid, req, res, result.data.session_key)
  267 + .then((authData) => {
  268 + result.data.refer = _.get(authData, 'refer') || refer;
  269 + return result;
  270 + });
269 } else { 271 } else {
270 return { code: 400, message: '关联失败', data: '' }; 272 return { code: 400, message: '关联失败', data: '' };
271 } 273 }
@@ -8,8 +8,9 @@ @@ -8,8 +8,9 @@
8 const _ = require('lodash'); 8 const _ = require('lodash');
9 const passport = require('passport'); 9 const passport = require('passport');
10 10
11 -// const md5 = require('yoho-md5');  
12 const uuid = require('uuid'); 11 const uuid = require('uuid');
  12 +const url = require('url');
  13 +const moment = require('moment');
13 const co = Promise.coroutine; 14 const co = Promise.coroutine;
14 const cookie = global.yoho.cookie; 15 const cookie = global.yoho.cookie;
15 const helpers = global.yoho.helpers; 16 const helpers = global.yoho.helpers;
@@ -19,6 +20,8 @@ const cache = global.yoho.cache; @@ -19,6 +20,8 @@ const cache = global.yoho.cache;
19 const utils = require(global.utils); 20 const utils = require(global.utils);
20 const RegService = require('../models/reg-service'); 21 const RegService = require('../models/reg-service');
21 const AuthHelper = require('../models/auth-helper'); 22 const AuthHelper = require('../models/auth-helper');
  23 +const thirdAccount = require('../data/third-account.json');
  24 +const auth = require('../models/auth-helper');
22 25
23 const loginPage = `${config.siteUrl}/signin.html`; 26 const loginPage = `${config.siteUrl}/signin.html`;
24 27
@@ -50,9 +53,10 @@ function doPassportCallback(openId, nickname, sourceType, req, res) { @@ -50,9 +53,10 @@ function doPassportCallback(openId, nickname, sourceType, req, res) {
50 refer: refer 53 refer: refer
51 }); 54 });
52 } else if (result.code === 200 && result.data.uid) { 55 } else if (result.code === 200 && result.data.uid) {
53 - return AuthHelper.syncUserSession(result.data.uid, req, res, result.data.session_key).then(() => {  
54 - return refer;  
55 - }); 56 + return AuthHelper.syncUserSession(result.data.uid, req, res, result.data.session_key)
  57 + .then((authData) => {
  58 + return _.get(authData, 'refer') || refer;
  59 + });
56 } 60 }
57 }).then((redirectTo) => { 61 }).then((redirectTo) => {
58 return res.redirect(redirectTo); 62 return res.redirect(redirectTo);
@@ -63,6 +67,73 @@ function doPassportCallback(openId, nickname, sourceType, req, res) { @@ -63,6 +67,73 @@ function doPassportCallback(openId, nickname, sourceType, req, res) {
63 } 67 }
64 68
65 const common = { 69 const common = {
  70 + // 第三方登录有货逻辑
  71 + thirdLogin(req, res, next) {
  72 + let refer = req.get('referer');
  73 + let thirdRefer = req.cookies.third_refer;
  74 +
  75 + if (thirdRefer && !/signin|login|passport\/international/.test(refer)) {
  76 + res.clearCookie('third_refer', {
  77 + domain: 'yohobuy.com'
  78 + });
  79 + }
  80 +
  81 + // TODO 记录token并验证有效期或者实现oauth
  82 + if (req.query.yh_type &&
  83 + req.query.yh_sign &&
  84 + req.query.yh_time &&
  85 + req.query.yh_backurl) {
  86 + let reqTime = moment(req.query.yh_time);
  87 + let timeDiff = moment().diff(reqTime);
  88 +
  89 + if (!reqTime.isValid() ||
  90 + timeDiff >= 1000 * 60 * 5 || // 如果服务器之间大于5分钟验证失败
  91 + timeDiff < 0) {
  92 +
  93 + return res.json({
  94 + code: 401,
  95 + message: 'yh_time已过期或者格式错误'
  96 + });
  97 + }
  98 + let account = thirdAccount[req.query.yh_type];
  99 +
  100 + if (!account) {
  101 + return res.json({
  102 + code: 401,
  103 + message: 'yh_type验证失败'
  104 + });
  105 + }
  106 + let backurl = url.parse(req.query.yh_backurl);
  107 + let regDomain = new RegExp(`${account.domain.replace(/\./g, '\\.')}$`);
  108 +
  109 + if (!regDomain.test(backurl.host || '')) {
  110 + return res.json({
  111 + code: 401,
  112 + message: 'yh_backurl回调域名验证失败'
  113 + });
  114 + }
  115 + let signStr = auth.thirdSign(req.query, account.clientSecret);
  116 +
  117 + if (signStr.toLowerCase() !== req.query.yh_sign.toLowerCase()) {
  118 + return res.json({
  119 + code: 401,
  120 + message: 'yh_sign签名验证错误'
  121 + });
  122 + }
  123 + res.cookie('third_refer', refer, {
  124 + domain: 'yohobuy.com'
  125 + });
  126 + res.cookie('third_type', req.query.yh_type, {
  127 + domain: 'yohobuy.com'
  128 + });
  129 + res.cookie('third_backurl', req.query.yh_backurl, {
  130 + domain: 'yohobuy.com'
  131 + });
  132 +
  133 + req.query.from = req.query.yh_type;
  134 + }
  135 + next();
  136 + },
66 beforeLogin: (req, res, next) => { 137 beforeLogin: (req, res, next) => {
67 if (req.session.passwordWeak) { 138 if (req.session.passwordWeak) {
68 return res.redirect('/passport/password/resetpage'); 139 return res.redirect('/passport/password/resetpage');
@@ -297,10 +368,11 @@ const local = { @@ -297,10 +368,11 @@ const local = {
297 return res.json(passwordWeakReturn); 368 return res.json(passwordWeakReturn);
298 } 369 }
299 370
300 - AuthHelper.syncUserSession(user.uid, req, res, user.session_key).then(() => { 371 + AuthHelper.syncUserSession(user.uid, req, res, user.session_key).then((authData) => {
301 if (user.weakPassword) { 372 if (user.weakPassword) {
302 return res.json(passwordWeakReturn); 373 return res.json(passwordWeakReturn);
303 } else { 374 } else {
  375 + user.href = _.get(authData, 'refer', user.href);
304 res.json({ 376 res.json({
305 code: 200, 377 code: 200,
306 data: user 378 data: user
@@ -127,7 +127,7 @@ class Reg { @@ -127,7 +127,7 @@ class Reg {
127 return res.json(regMobileAesResult); 127 return res.json(regMobileAesResult);
128 } 128 }
129 129
130 - yield AuthHelper.syncUserSession(regMobileAesResult.data.uid, 130 + let authData = yield AuthHelper.syncUserSession(regMobileAesResult.data.uid,
131 req, res, regMobileAesResult.data.session_key); 131 req, res, regMobileAesResult.data.session_key);
132 132
133 // 返回跳转到来源页面 133 // 返回跳转到来源页面
@@ -156,7 +156,7 @@ class Reg { @@ -156,7 +156,7 @@ class Reg {
156 message: '注册成功', 156 message: '注册成功',
157 data: { 157 data: {
158 session: refer, 158 session: refer,
159 - href: '//m.yohobuy.com/activity/invite-reg', 159 + href: _.get(authData, 'refer') || '//m.yohobuy.com/activity/invite-reg',
160 msgDelivery: _.get(regMobileAesResult, 'data.msgDelivery', '') 160 msgDelivery: _.get(regMobileAesResult, 'data.msgDelivery', '')
161 } 161 }
162 }); 162 });
@@ -406,7 +406,7 @@ let setPassword = (req, res, next) => { @@ -406,7 +406,7 @@ let setPassword = (req, res, next) => {
406 resultCopy = result; 406 resultCopy = result;
407 407
408 return AuthHelper.syncUserSession(result.data.uid, req, res, result.data.session_key); 408 return AuthHelper.syncUserSession(result.data.uid, req, res, result.data.session_key);
409 - }).then(() => { 409 + }).then((authData) => {
410 if (!resultCopy) { 410 if (!resultCopy) {
411 return; 411 return;
412 } 412 }
@@ -438,7 +438,7 @@ let setPassword = (req, res, next) => { @@ -438,7 +438,7 @@ let setPassword = (req, res, next) => {
438 message: '注册成功', 438 message: '注册成功',
439 data: { 439 data: {
440 session: refer, 440 session: refer,
441 - href: '//m.yohobuy.com/activity/invite-reg', 441 + href: _.get(authData, 'refer') || '//m.yohobuy.com/activity/invite-reg',
442 msgDelivery: _.get(resultCopy, 'data.msgDelivery', '') 442 msgDelivery: _.get(resultCopy, 'data.msgDelivery', '')
443 } 443 }
444 }); 444 });
@@ -351,11 +351,11 @@ exports.check = (req, res, next) => { @@ -351,11 +351,11 @@ exports.check = (req, res, next) => {
351 }); 351 });
352 return AuthHelper.syncUserSession(info.data.uid, req, res, info.data.session_key); 352 return AuthHelper.syncUserSession(info.data.uid, req, res, info.data.session_key);
353 }) 353 })
354 - .then(() => { 354 + .then((authData) => {
355 res.json({ 355 res.json({
356 code: 200, 356 code: 200,
357 message: LOGIN_SUCCSS, 357 message: LOGIN_SUCCSS,
358 - redirect: utils.refererLimit(req.cookies.refer) 358 + redirect: _.get(authData, 'refer') || utils.refererLimit(req.cookies.refer)
359 }); 359 });
360 360
361 delete req.session.smsLogin; 361 delete req.session.smsLogin;
@@ -418,14 +418,14 @@ exports.password = (req, res, next) => { @@ -418,14 +418,14 @@ exports.password = (req, res, next) => {
418 resultCopy = result; 418 resultCopy = result;
419 419
420 return AuthHelper.syncUserSession(result.data.uid, req, res, result.data.session_key); 420 return AuthHelper.syncUserSession(result.data.uid, req, res, result.data.session_key);
421 - }).then(() => { 421 + }).then((authData) => {
422 if (!resultCopy) { 422 if (!resultCopy) {
423 return; 423 return;
424 } 424 }
425 res.json({ 425 res.json({
426 code: 200, 426 code: 200,
427 message: LOGIN_SUCCSS, 427 message: LOGIN_SUCCSS,
428 - redirect: utils.refererLimit(req.cookies.refer) 428 + redirect: _.get(authData, 'refer') || utils.refererLimit(req.cookies.refer)
429 }); 429 });
430 delete req.session.smsLogin; 430 delete req.session.smsLogin;
431 }).catch(next); 431 }).catch(next);
  1 +{
  2 + "mars": {
  3 + "clientSecret": "f30368d65fcad4a265074948a2a2e6e6",
  4 + "domain": "yohomars.com"
  5 + },
  6 + "activity": {
  7 + "clientSecret": "3bd815162342d9733f06ab6811082c64",
  8 + "domain": "yoho.cn"
  9 + }
  10 +}
@@ -6,6 +6,11 @@ const logger = global.yoho.logger; @@ -6,6 +6,11 @@ const logger = global.yoho.logger;
6 const sign = global.yoho.sign; 6 const sign = global.yoho.sign;
7 const api = global.yoho.API; 7 const api = global.yoho.API;
8 const uuid = require('uuid'); 8 const uuid = require('uuid');
  9 +const url = require('url');
  10 +const md5 = require('yoho-md5');
  11 +const moment = require('moment');
  12 +const querystring = require('querystring');
  13 +const thirdAccount = require('../data/third-account.json');
9 14
10 class Auth { 15 class Auth {
11 16
@@ -73,6 +78,54 @@ class Auth { @@ -73,6 +78,54 @@ class Auth {
73 return api.get('', param); 78 return api.get('', param);
74 } 79 }
75 80
  81 + static thirdSign(params, clientSecret) {
  82 + let secretParams = {},
  83 + secretStr = '';
  84 +
  85 + for (const k of Object.keys(params).sort()) {
  86 + if (k === 'yh_sign') {
  87 + continue;
  88 + }
  89 + secretParams[k] = params[k];
  90 + }
  91 + secretStr = _.join(_.map(secretParams, (v, k) => {
  92 + return `${k}=${v}`;
  93 + }), '&');
  94 + return md5(secretStr + clientSecret);
  95 + }
  96 +
  97 + static thirdLogin(req, res, uid) {
  98 + if (req.cookies.third_type && req.cookies.third_backurl && req.cookies.third_refer) {
  99 + let backurl = url.parse(req.cookies.third_backurl),
  100 + account = thirdAccount[req.cookies.third_type];
  101 +
  102 + let params = Object.assign({
  103 + yh_uid: uid,
  104 + yh_type: req.cookies.third_type,
  105 + yh_time: moment().format('YYYY-MM-DD HH:mm:ss')
  106 + }, querystring.parse(backurl.query));
  107 + let signStr = this.thirdSign(params, account.clientSecret);
  108 +
  109 + params.yh_sign = signStr;
  110 + let queryStr = _.join(_.map(params, (v, k) => {
  111 + return `${k}=${encodeURIComponent(v)}`;
  112 + }), '&');
  113 +
  114 + return {
  115 + refer: `${backurl.protocol}//${backurl.host}${backurl.pathname}?${queryStr}`
  116 + };
  117 + }
  118 + res.clearCookie('third_type', {
  119 + domain: 'yohobuy.com'
  120 + });
  121 + res.clearCookie('third_backurl', {
  122 + domain: 'yohobuy.com'
  123 + });
  124 + res.clearCookie('third_refer', {
  125 + domain: 'yohobuy.com'
  126 + });
  127 + }
  128 +
76 static syncUserSession(uid, req, res, sessionKey) { 129 static syncUserSession(uid, req, res, sessionKey) {
77 let userId = { 130 let userId = {
78 toString: () => { 131 toString: () => {
@@ -132,6 +185,9 @@ class Auth { @@ -132,6 +185,9 @@ class Auth {
132 domain: 'yohobuy.com', 185 domain: 'yohobuy.com',
133 expires: new Date(Date.now() + 2592000000) // 有效期一年 186 expires: new Date(Date.now() + 2592000000) // 有效期一年
134 }); 187 });
  188 +
  189 + // 第三方登录逻辑
  190 + return this.thirdLogin(req, res, uid);
135 }); 191 });
136 } 192 }
137 } 193 }
@@ -203,6 +203,7 @@ router.get('/signin.html', @@ -203,6 +203,7 @@ router.get('/signin.html',
203 validateCode.load, 203 validateCode.load,
204 login.common.beforeLogin, 204 login.common.beforeLogin,
205 login.common.clearCookie, 205 login.common.clearCookie,
  206 + login.common.thirdLogin,
206 smsNew.smsLoginPage); // 短信验证码登录 207 smsNew.smsLoginPage); // 短信验证码登录
207 router.get('/reg.html', 208 router.get('/reg.html',
208 validateCode.load, 209 validateCode.load,
@@ -79,6 +79,7 @@ module.exports = () => { @@ -79,6 +79,7 @@ module.exports = () => {
79 } 79 }
80 } 80 }
81 81
  82 + res.locals.isLogin = Boolean(req.user.uid); // 用户是否登录
82 next(); 83 next();
83 }; 84 };
84 }; 85 };
@@ -66,22 +66,26 @@ @@ -66,22 +66,26 @@
66 var s = document.getElementsByTagName("script")[0]; 66 var s = document.getElementsByTagName("script")[0];
67 s.parentNode.insertBefore(hm, s); 67 s.parentNode.insertBefore(hm, s);
68 })(); 68 })();
69 - (function() { 69 + {{!-- (function() {
70 var hm = document.createElement("script"); 70 var hm = document.createElement("script");
71 hm.src = "https://hm.baidu.com/hm.js?e5b83a487a4458aa5abca43f5779b764"; 71 hm.src = "https://hm.baidu.com/hm.js?e5b83a487a4458aa5abca43f5779b764";
72 var s = document.getElementsByTagName("script")[0]; 72 var s = document.getElementsByTagName("script")[0];
73 s.parentNode.insertBefore(hm, s); 73 s.parentNode.insertBefore(hm, s);
74 - })(); 74 + })(); --}}
  75 +
  76 + {{#if @root.isLogin}}
  77 + {{#if @root.isApp}}
  78 + _hmt.push(['_setCustomVar', 1, 'login', 'APP', 2]);
  79 + {{^}}
  80 + _hmt.push(['_setCustomVar', 1, 'login', 'H5', 2]);
  81 + {{/if}}
  82 + {{/if}}
75 }, 1000); 83 }, 1000);
76 }()); 84 }());
77 85
78 - {{!--/* tar add 170426 品众代码去除 */--}}  
79 - {{!--/* tar add 170601 品众代码恢复 */--}}  
80 window._fxcmd = window._fxcmd || []; 86 window._fxcmd = window._fxcmd || [];
81 _fxcmd.sid = 'bb3b16fa1106a6ab8619da0095755f32'; 87 _fxcmd.sid = 'bb3b16fa1106a6ab8619da0095755f32';
82 _fxcmd.trackAll = false; 88 _fxcmd.trackAll = false;
83 - // 参数配置(可选)...  
84 - // 追踪配置(可选)...  
85 89
86 setTimeout(function() { 90 setTimeout(function() {
87 var _pzfx = document['createElement']('script'); 91 var _pzfx = document['createElement']('script');
This diff could not be displayed because it is too large.
1 { 1 {
2 "name": "m-yohobuy-node", 2 "name": "m-yohobuy-node",
3 - "version": "6.0.13", 3 + "version": "6.0.14",
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": {
@@ -425,3 +425,23 @@ @@ -425,3 +425,23 @@
425 } 425 }
426 } 426 }
427 } 427 }
  428 +
  429 +.is-mars-app {
  430 + .chose-panel {
  431 + .block {
  432 + &.chosed {
  433 + background-color: #89b374;
  434 + color: #fff;
  435 + border-color: #89b374;
  436 + }
  437 + }
  438 +
  439 + .btn-wrap {
  440 + .btn-sure,
  441 + .btn-sure-addtocart {
  442 + background-color: #89b374 !important;
  443 + color: #fff;
  444 + }
  445 + }
  446 + }
  447 +}