Authored by 张丽霞

代码还原到最新

@@ -39,7 +39,9 @@ app.set('view engine', '.hbs'); @@ -39,7 +39,9 @@ app.set('view engine', '.hbs');
39 app.use(favicon(path.join(__dirname, '/public/favicon.ico'))); 39 app.use(favicon(path.join(__dirname, '/public/favicon.ico')));
40 app.use(express.static(path.join(__dirname, 'public'))); 40 app.use(express.static(path.join(__dirname, 'public')));
41 app.use(bodyParser.json()); 41 app.use(bodyParser.json());
42 -app.use(bodyParser.urlencoded({extended: false})); 42 +app.use(bodyParser.urlencoded({
  43 + extended: false
  44 +}));
43 app.use(cookieParser()); 45 app.use(cookieParser());
44 app.use(session({ 46 app.use(session({
45 proxy: true, 47 proxy: true,
@@ -52,12 +54,13 @@ app.use(session({ @@ -52,12 +54,13 @@ app.use(session({
52 return uuid.v4(); // 兼容 PHP SESSION 54 return uuid.v4(); // 兼容 PHP SESSION
53 }, 55 },
54 cookie: { 56 cookie: {
55 - domain: 'yohobuy.com' 57 + domain: 'yohobuy.com',
  58 + httpOnly: false
56 }, 59 },
57 store: new MemcachedStore({ 60 store: new MemcachedStore({
58 hosts: config.memcache.session, 61 hosts: config.memcache.session,
59 - prefix: 'qinsessionsession:', // 兼容 PHP SESSION  
60 - key: 'yohobuy_session' // 兼容 PHP SESSION 62 + prefix: 'qinsessionsession:', // 兼容 PHP SESSION
  63 + key: 'yohobuy_session' // 兼容 PHP SESSION
61 }) 64 })
62 })); 65 }));
63 66
@@ -48,7 +48,7 @@ const getUserStatus = (param) => { @@ -48,7 +48,7 @@ const getUserStatus = (param) => {
48 } 48 }
49 if (param.data.newUser === 1) { 49 if (param.data.newUser === 1) {
50 dest.newUser = true; 50 dest.newUser = true;
51 - }; 51 + }
52 dest.message = param.data.returnMsg; 52 dest.message = param.data.returnMsg;
53 // 清空变量,释放内存 53 // 清空变量,释放内存
54 param = {}; 54 param = {};
  1 +/**
  2 + * passport 验证策略注册
  3 + * @author: jiangfeng<jeff.jiang@yoho.cn>
  4 + * @date: 2016/5/31
  5 + */
  6 +
  7 +'use strict';
  8 +const passport = require('passport');
  9 +const WeixinStrategy = require('passport-weixin-plus');
  10 +
  11 +const config = require('../../config/common');
  12 +
  13 +let siteUrl = config.siteUrl.indexOf('//') === 0 ? 'http:' + config.siteUrl : config.siteUrl;
  14 +
  15 +/**
  16 + * wechat登录
  17 + */
  18 +passport.use(new WeixinStrategy({
  19 + authorizationURL: 'https://open.weixin.qq.com/connect/oauth2/authorize',
  20 + tokenURL: 'https://api.weixin.qq.com/sns/oauth2/access_token',
  21 + clientID: config.thirdLogin.wechat.appID,
  22 + clientSecret: config.thirdLogin.wechat.appSecret,
  23 + callbackURL: `${siteUrl}/passport/login/wechat/callback`,
  24 + requireState: false,
  25 + scope: 'snsapi_userinfo'
  26 +}, (accessToken, refreshToken, profile, done) => {
  27 + done(null, profile);
  28 +}));
  1 +/**
  2 + * 登录
  3 + * @author: Bi Kai<kai.bi@yoho.cn>
  4 + * @date: 2016/05/09
  5 + */
  6 +'use strict';
  7 +
  8 +const library = '../../../library';
  9 +const passport = require('passport');
  10 +const cookie = require(`${library}/cookie`);
  11 +const helpers = require(`${library}/helpers`);
  12 +const log = require(`${library}/logger`);
  13 +const config = require('../../../config/common');
  14 +const AuthHelper = require('../models/auth-helper');
  15 +
  16 +const loginPage = `${config.siteUrl}/passport/login/index`;
  17 +
  18 +function doPassportCallback(openId, nickname, sourceType, req, res) {
  19 + let shoppingKey = cookie.getShoppingKey(req);
  20 + let refer = req.cookies.refer;
  21 +
  22 + if (refer) {
  23 + refer = decodeURI(req.cookies.refer);
  24 + } else {
  25 + refer = `${config.siteUrl}/home`;
  26 + }
  27 +
  28 + if (/sign|login/.test(refer)) {
  29 + refer = `${config.siteUrl}/home`;
  30 + }
  31 + if (openId && nickname) {
  32 + AuthHelper.signinByOpenID(nickname, openId, sourceType, shoppingKey).then((result) => {
  33 + if (result.data['is_bind'] && result.data['is_bind'] === 'N') { //eslint-disable-line
  34 + return helpers.urlFormat('/passport/bind/index', {
  35 + openId: openId,
  36 + sourceType: sourceType,
  37 + refer: refer
  38 + });
  39 + } else if (result.code === 200 && result.data.uid) {
  40 + return AuthHelper.syncUserSession(result.data.uid, req, res).then(() => {
  41 + return refer;
  42 + });
  43 + }
  44 + }).then((redirectTo) => {
  45 + console.log('redirectTo=', redirectTo);
  46 + return res.redirect(redirectTo);
  47 + }).catch((e) => {
  48 + log.error('频道页面渲染错误:' + JSON.stringify(e));
  49 + return res.send('error');
  50 + });
  51 + }
  52 +}
  53 +
  54 +const wechat = {
  55 + beforeLogin: (req, res, next) => {
  56 + let refer = req.query.refer;
  57 +
  58 + if (!refer) {
  59 + refer = req.get('Referer');
  60 + }
  61 + refer && res.cookie('refer', encodeURI(refer), {
  62 + domain: 'yohobuy.com'
  63 + });
  64 + next();
  65 + },
  66 + login: (req, res, next) => {
  67 + return passport.authenticate('weixin')(req, res, next);
  68 + },
  69 + callback: (req, res, next) => {
  70 + passport.authenticate('weixin', (err, user) => {
  71 + if (err) {
  72 + log.error(`wechat authenticate error : ${JSON.stringify(err)}`);
  73 + return res.redirect(loginPage);
  74 + }
  75 + let nickname = user.displayName || user._json.nickname;
  76 + let openId = user.id || user._json.unionid;
  77 +
  78 + doPassportCallback(openId, nickname, 'wechat', req, res);
  79 + })(req, res, next);
  80 + }
  81 +};
  82 +
  83 +exports.wechat = wechat;
  1 +/**
  2 + * sub app channel
  3 + * @author: Bi Kai<kai.bi@yoho.cn>
  4 + * @date: 2016/05/09
  5 + */
  6 +'use strict';
  7 +var express = require('express'),
  8 + path = require('path'),
  9 + hbs = require('express-handlebars');
  10 +
  11 +var passport = require('passport');
  12 +
  13 +var app = express();
  14 +
  15 +// set view engin
  16 +var doraemon = path.join(__dirname, '../../doraemon/views'); // parent view root
  17 +
  18 +app.on('mount', function(parent) {
  19 + delete parent.locals.settings; // 不继承父 App 的设置
  20 + Object.assign(app.locals, parent.locals);
  21 +});
  22 +
  23 +app.set('views', path.join(__dirname, 'views/action'));
  24 +app.engine('.hbs', hbs({
  25 + extname: '.hbs',
  26 + defaultLayout: 'layout',
  27 + layoutsDir: doraemon,
  28 + partialsDir: [path.join(__dirname, 'views/partial'), `${doraemon}/partial`],
  29 + helpers: require(`${global.library}/helpers`)
  30 +}));
  31 +
  32 +
  33 +require('./auth');
  34 +app.use(passport.initialize());
  35 +app.use(passport.session());
  36 +
  37 +// router
  38 +app.use(require('./router'));
  39 +
  40 +module.exports = app;
  1 +'use strict';
  2 +
  3 +const library = '../../../library';
  4 +const API = require(`${library}/api`).API;
  5 +const sign = require(`${library}/sign`);
  6 +const api = new API();
  7 +
  8 +class Auth {
  9 +
  10 + static signinByOpenID(nickname, openId, sourceType, shoppingKey) {
  11 + let param = {
  12 + nickname: nickname,
  13 + openId: openId,
  14 + source_type: sourceType, // esline-disable-line
  15 + method: 'app.passport.signinByOpenID',
  16 + shoppingKey: shoppingKey
  17 + };
  18 +
  19 + if (shoppingKey) {
  20 + param.shopping_key = shoppingKey;
  21 + }
  22 +
  23 + return api.get('', sign.apiSign(param));
  24 + }
  25 +
  26 + static profile(uid) {
  27 + let param = {
  28 + uid: uid,
  29 + method: 'app.passport.profile'
  30 + };
  31 +
  32 + return api.get('', sign.apiSign(param));
  33 + }
  34 +
  35 + static syncUserSession(uid, req, res) {
  36 + return Auth.profile(uid).then((userInfo) => {
  37 + let token = sign.makeToken(uid);
  38 + let data = userInfo.data;
  39 +
  40 + if (data) {
  41 + let uidCookie = `${data.profile_name}::${data.uid}::${data.vip_info.title}::${token}`;
  42 +
  43 + res.cookie('_UID', uidCookie, {
  44 + domain: 'yohobuy.com'
  45 + });
  46 + }
  47 + req.session._TOKEN = token; // esline-disable-line
  48 + req.session._LOGIN_UID = uid; // esline-disable-line
  49 + res.cookie('_TOKEN', token, {
  50 + domain: 'yohobuy.com'
  51 + }); // esline-disable-line
  52 + }).catch(console.log);
  53 + }
  54 +}
  55 +
  56 +module.exports = Auth;
  1 +/**
  2 + * router of sub app channel
  3 + * @author: Bi Kai<kai.bi@yoho.cn>
  4 + * @date: 2016/05/09
  5 + */
  6 +
  7 +'use strict';
  8 +
  9 +const express = require('express');
  10 +const cRoot = './controllers';
  11 +const login = require(cRoot + '/login');
  12 +
  13 +const router = express.Router(); // eslint-disable-line
  14 +
  15 +router.get('/login/wechat', login.wechat.beforeLogin, login.wechat.login); // 登录
  16 +router.get('/login/wechat/callback', login.wechat.callback);
  17 +
  18 +module.exports = router;
@@ -191,7 +191,7 @@ exports.search = (req, res) => { @@ -191,7 +191,7 @@ exports.search = (req, res) => {
191 191
192 if (req.query.saleType === '2') { 192 if (req.query.saleType === '2') {
193 vipObj = Object.assign({ 193 vipObj = Object.assign({
194 - saleVip: (req.query.saleType === '2' && (!uid || vipLevel === '1')), 194 + saleVip: (req.query.saleType === '2' && (!uid || vipLevel === '0')),
195 vipLevel: vipLevel, 195 vipLevel: vipLevel,
196 saleViplogin: vipLevel >= 1 ? true : false, 196 saleViplogin: vipLevel >= 1 ? true : false,
197 vipPrice1: vipLevel === '1', 197 vipPrice1: vipLevel === '1',
@@ -11,15 +11,15 @@ const isTest = process.env.NODE_ENV === 'test'; @@ -11,15 +11,15 @@ const isTest = process.env.NODE_ENV === 'test';
11 11
12 module.exports = { 12 module.exports = {
13 port: 6001, 13 port: 6001,
14 - siteUrl: 'http://m.yohobuy.com',  
15 - 14 + siteUrl: '//m.yohobuy.com',
16 // domains: { 15 // domains: {
17 // api: 'http://testapi.yoho.cn:28078/', // http://192.168.102.205:8080/gateway 16 // api: 'http://testapi.yoho.cn:28078/', // http://192.168.102.205:8080/gateway
18 // service: 'http://testservice.yoho.cn:28077/' 17 // service: 'http://testservice.yoho.cn:28077/'
19 // }, 18 // },
20 domains: { 19 domains: {
21 - api: 'http://testapi.yoho.cn:28078/', // http://192.168.102.205:8080/gateway  
22 - service: 'http://testservice.yoho.cn:28077/' 20 + api: 'http://devapi.yoho.cn:58078/',
  21 + service: 'http://devservice.yoho.cn:58077/',
  22 + search: 'http://192.168.10.64:8080/yohosearch/'
23 }, 23 },
24 useOneapm: false, 24 useOneapm: false,
25 useCache: false, 25 useCache: false,
@@ -45,13 +45,19 @@ module.exports = { @@ -45,13 +45,19 @@ module.exports = {
45 udp: { // send by udp 45 udp: { // send by udp
46 level: 'debug', // logger level 46 level: 'debug', // logger level
47 host: '192.168.102.162', // influxdb host 47 host: '192.168.102.162', // influxdb host
48 - port: '4444'// influxdb port 48 + port: '4444' // influxdb port
49 }, 49 },
50 console: { 50 console: {
51 level: 'debug', 51 level: 'debug',
52 colorize: 'all', 52 colorize: 'all',
53 prettyPrint: true 53 prettyPrint: true
54 } 54 }
  55 + },
  56 + thirdLogin: {
  57 + wechat: {
  58 + appID: 'wx75e5a7c0c88e45c2',
  59 + appSecret: 'ce21ae4a3f93852279175a167e54509b'
  60 + }
55 } 61 }
56 }; 62 };
57 63
@@ -74,6 +80,12 @@ if (isProduction) { @@ -74,6 +80,12 @@ if (isProduction) {
74 } else if (isTest) { 80 } else if (isTest) {
75 Object.assign(module.exports, { 81 Object.assign(module.exports, {
76 appName: 'm.yohobuy.com for test', 82 appName: 'm.yohobuy.com for test',
  83 + memcache: {
  84 + master: ['127.0.0.1:11212', '127.0.0.1:11213'],
  85 + slave: ['127.0.0.1:11212', '127.0.0.1:11213'],
  86 + session: ['127.0.0.1:11212', '127.0.0.1:11213'],
  87 + timeout: 3000
  88 + },
77 useOneapm: true, 89 useOneapm: true,
78 useCache: true 90 useCache: true
79 }); 91 });
@@ -13,5 +13,6 @@ module.exports = app => { @@ -13,5 +13,6 @@ module.exports = app => {
13 13
14 // 业务模块 14 // 业务模块
15 app.use('/product', require('./apps/product')); 15 app.use('/product', require('./apps/product'));
  16 + app.use('/passport', require('./apps/passport'));
16 app.use('/coupon', require('./apps/coupon')); 17 app.use('/coupon', require('./apps/coupon'));
17 }; 18 };
@@ -35,15 +35,15 @@ @@ -35,15 +35,15 @@
35 {{#if @root.saleViplogin}} 35 {{#if @root.saleViplogin}}
36 <i class="vip-grade vip-grade-{{@root.vipLevel}}"></i> 36 <i class="vip-grade vip-grade-{{@root.vipLevel}}"></i>
37 <span class="sale-price {{^marketPrice}}no-price{{/marketPrice}}">¥ 37 <span class="sale-price {{^marketPrice}}no-price{{/marketPrice}}">¥
38 - {{#if @root.vipPrice1}}{{vip1Price}}{{/if}}  
39 - {{#if @root.vipPrice2}}{{vip2Price}}{{/if}}  
40 - {{#if @root.vipPrice3}}{{vip3Price}}{{/if}} 38 + {{#if @root.vipPrice1}}{{round vip1Price}}{{/if}}
  39 + {{#if @root.vipPrice2}}{{round vip2Price}}{{/if}}
  40 + {{#if @root.vipPrice3}}{{round vip3Price}}{{/if}}
41 </span> 41 </span>
42 {{else}} 42 {{else}}
43 - <span class="sale-price {{^marketPrice}}no-price{{/marketPrice}}">¥{{salesPrice}}</span> 43 + <span class="sale-price {{^marketPrice}}no-price{{/marketPrice}}">¥{{round salesPrice}}</span>
44 {{/if}} 44 {{/if}}
45 {{#marketPrice}} 45 {{#marketPrice}}
46 - <span class="market-price">¥{{.}}</span> 46 + <span class="market-price">¥{{round .}}</span>
47 {{/marketPrice}} 47 {{/marketPrice}}
48 </div> 48 </div>
49 {{#if @root.saleVip}} 49 {{#if @root.saleVip}}
@@ -3,6 +3,8 @@ @@ -3,6 +3,8 @@
3 * @param {[object]} req 3 * @param {[object]} req
4 * @return {[string]} 4 * @return {[string]}
5 */ 5 */
  6 +'use strict';
  7 +
6 exports.getUid = (req) => { 8 exports.getUid = (req) => {
7 const cookie = req.cookies._UID; 9 const cookie = req.cookies._UID;
8 let _uid = 0; 10 let _uid = 0;
@@ -21,3 +23,7 @@ exports.getUid = (req) => { @@ -21,3 +23,7 @@ exports.getUid = (req) => {
21 23
22 return _uid; 24 return _uid;
23 }; 25 };
  26 +
  27 +exports.getShoppingKey = (req) => {
  28 + return req.cookies['_SPK'] ? req.cookies['_SPK'] : ''; // eslint-disable-line
  29 +};
@@ -92,6 +92,19 @@ exports.upperCase = (str) => { @@ -92,6 +92,19 @@ exports.upperCase = (str) => {
92 return str.toUpperCase(); 92 return str.toUpperCase();
93 }; 93 };
94 94
  95 +
  96 +/**
  97 + * 四舍五入
  98 + * @param {[type]} num 数字
  99 + * @param {[type]} precision 精度
  100 + * @return {[type]}
  101 + */
  102 +exports.round = (num, precision) => {
  103 + precision = _.isNumber(precision) ? precision : 2;
  104 + num = _.isInteger(num) ? (+num).toFixed(precision) : _.round(num, precision);
  105 + return num;
  106 +};
  107 +
95 /** 108 /**
96 * 时间格式化 109 * 时间格式化
97 * @param format 格式化token @see{http://momentjs.cn/docs/#/displaying/format/} 110 * @param format 格式化token @see{http://momentjs.cn/docs/#/displaying/format/}
@@ -11,12 +11,12 @@ const FileTransport = require('winston-daily-rotate-file'); @@ -11,12 +11,12 @@ const FileTransport = require('winston-daily-rotate-file');
11 11
12 require('influxdb-winston'); 12 require('influxdb-winston');
13 13
14 -const logger = new (winston.Logger)({ 14 +const logger = new(winston.Logger)({
15 transports: [ 15 transports: [
16 - new (FileTransport)(config.loggers.infoFile),  
17 - new (FileTransport)(config.loggers.errorFile),  
18 - new (winston.transports.UdpTransport)(config.loggers.udp),  
19 - new (winston.transports.Console)(config.loggers.console) 16 + new(FileTransport)(config.loggers.infoFile),
  17 + new(FileTransport)(config.loggers.errorFile),
  18 + new(winston.transports.UdpTransport)(config.loggers.udp),
  19 + new(winston.transports.Console)(config.loggers.console)
20 ], 20 ],
21 exitOnError: false 21 exitOnError: false
22 }); 22 });
@@ -72,7 +72,7 @@ exports.apiSign = (params) => { @@ -72,7 +72,7 @@ exports.apiSign = (params) => {
72 // 检查签名,APP 访问 H5 页面的时候需要检查 72 // 检查签名,APP 访问 H5 页面的时候需要检查
73 exports.checkSign = (params) => { 73 exports.checkSign = (params) => {
74 const // eslint-disable-line camelcase 74 const // eslint-disable-line camelcase
75 - clientSecret = params.client_secret; 75 + clientSecret = params.client_secret;
76 76
77 let sortedParams; 77 let sortedParams;
78 78
@@ -94,3 +94,7 @@ exports.webSign = (params) => { @@ -94,3 +94,7 @@ exports.webSign = (params) => {
94 94
95 return params.key === md5(md5(webPrivateKey) + params.uid); 95 return params.key === md5(md5(webPrivateKey) + params.uid);
96 }; 96 };
  97 +
  98 +exports.makeToken = (string) => {
  99 + return md5(md5(string + '#@!@#'));
  100 +};
@@ -43,6 +43,8 @@ @@ -43,6 +43,8 @@
43 "moment": "^2.13.0", 43 "moment": "^2.13.0",
44 "morgan": "^1.7.0", 44 "morgan": "^1.7.0",
45 "oneapm": "^1.2.20", 45 "oneapm": "^1.2.20",
  46 + "passport": "^0.3.2",
  47 + "passport-weixin-plus": "0.0.4",
46 "request-promise": "^3.0.0", 48 "request-promise": "^3.0.0",
47 "serve-favicon": "^2.3.0", 49 "serve-favicon": "^2.3.0",
48 "uuid": "^2.0.2", 50 "uuid": "^2.0.2",
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.

84.5 KB | W: | H:

44.8 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
@@ -37,6 +37,10 @@ if ($('#activityEnded').html()) { @@ -37,6 +37,10 @@ if ($('#activityEnded').html()) {
37 $('.tip-wrap .title').html(tipMessage); 37 $('.tip-wrap .title').html(tipMessage);
38 } 38 }
39 39
  40 +if (!$('#newUser').html()) {
  41 + $('.gain-coupon-centent .coupon img').attr('src', oldUserCouponPic);
  42 +}
  43 +
40 $('.input-content').on('click', '.verification-code', function() { 44 $('.input-content').on('click', '.verification-code', function() {
41 $('.input-content div').eq('0').removeClass('verification-code'); 45 $('.input-content div').eq('0').removeClass('verification-code');
42 phone = $(this).siblings('input').val(); 46 phone = $(this).siblings('input').val();
@@ -100,7 +100,7 @@ @@ -100,7 +100,7 @@
100 .has-clear { 100 .has-clear {
101 padding-right: 30px; 101 padding-right: 30px;
102 } 102 }
103 - 103 +
104 .clear-input { 104 .clear-input {
105 position: absolute; 105 position: absolute;
106 padding: 10px; 106 padding: 10px;
@@ -72,22 +72,22 @@ exports.processProductList = (list, options) => { @@ -72,22 +72,22 @@ exports.processProductList = (list, options) => {
72 // thumb: product.defaultImages 72 // thumb: product.defaultImages
73 // }); 73 // });
74 74
75 - if (options.showPoint) {  
76 - product.marketPrice += '.00';  
77 - product.salesPrice += '.00';  
78 -  
79 - if (product.vip1Price) {  
80 - product.vip1Price = parseInt(product.vip1Price) + '.00';  
81 - }  
82 -  
83 - if (product.vip2Price) {  
84 - product.vip2Price = parseInt(product.vip2Price) + '.00';  
85 - }  
86 -  
87 - if (product.vip3Price) {  
88 - product.vip3Price = parseInt(product.vip3Price) + '.00';  
89 - }  
90 - } 75 + // if (options.showPoint) {
  76 + // // product.marketPrice += '.00';
  77 + // // product.salesPrice += '.00';
  78 +
  79 + // // if (product.vip1Price) {
  80 + // // product.vip1Price = parseInt(product.vip1Price) + '.00';
  81 + // // }
  82 +
  83 + // // if (product.vip2Price) {
  84 + // // product.vip2Price = parseInt(product.vip2Price) + '.00';
  85 + // // }
  86 +
  87 + // // if (product.vip3Price) {
  88 + // // product.vip3Price = parseInt(product.vip3Price) + '.00';
  89 + // // }
  90 + // }
91 91
92 product.isSoonSoldOut = product.isSoonSoldOut === 'Y'; 92 product.isSoonSoldOut = product.isSoonSoldOut === 'Y';
93 product.url = helpers.urlFormat(`/product/pro_${product.productId}_${product.goodsList[0].goodsId}/${product.cnAlphabet}.html`); // eslint-disable-line 93 product.url = helpers.urlFormat(`/product/pro_${product.productId}_${product.goodsList[0].goodsId}/${product.cnAlphabet}.html`); // eslint-disable-line