Authored by yyq

login

@@ -26,6 +26,11 @@ export default { @@ -26,6 +26,11 @@ export default {
26 bounces: false, 26 bounces: false,
27 clearCacheWhenDestroy: false 27 clearCacheWhenDestroy: false
28 }); 28 });
  29 +
  30 + // queryString中携带bind_code,则弹出绑定弹框
  31 + if (this.$route.query.bind_code) {
  32 + this.$createThirdBind().show();
  33 + }
29 }, 34 },
30 watch: { 35 watch: {
31 'yoho.context.needLogin': function(newVal) { 36 'yoho.context.needLogin': function(newVal) {
@@ -18,7 +18,7 @@ const errHandle = (error) => { @@ -18,7 +18,7 @@ const errHandle = (error) => {
18 }); 18 });
19 }; 19 };
20 const request = (options, store) => { 20 const request = (options, store) => {
21 - sign(options); 21 + // sign(options);
22 22
23 return axios(options).then((res) => { 23 return axios(options).then((res) => {
24 if (res.data.code === 401) { 24 if (res.data.code === 401) {
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 <div class="under-row"> 4 <div class="under-row">
5 <i class="iconfont iconphone2"></i> 5 <i class="iconfont iconphone2"></i>
6 <div class="select-block"> 6 <div class="select-block">
7 - <CubeSelect class="area-code-select" v-model="code" :options="options"></CubeSelect> 7 + <CubeSelect class="area-code-select" v-model="code" :options="options" :title="selectTitle"></CubeSelect>
8 </div> 8 </div>
9 <CubeInput class="bind-input" v-model="phone" placeholder="请输入手机号"></CubeInput> 9 <CubeInput class="bind-input" v-model="phone" placeholder="请输入手机号"></CubeInput>
10 </div> 10 </div>
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 <CubeButton class="send-sms-btn" :disabled="!!sendBtnText" @click="sendSMS">{{sendBtnText || '获取验证码'}}</CubeButton> 14 <CubeButton class="send-sms-btn" :disabled="!!sendBtnText" @click="sendSMS">{{sendBtnText || '获取验证码'}}</CubeButton>
15 </div> 15 </div>
16 <div class="submit-row"> 16 <div class="submit-row">
17 - <CubeButton class="bind-btn">登录</CubeButton> 17 + <CubeButton class="bind-btn" @click="bindSubmit">登录</CubeButton>
18 </div> 18 </div>
19 </div> 19 </div>
20 </div> 20 </div>
@@ -23,6 +23,45 @@ @@ -23,6 +23,45 @@
23 <script> 23 <script>
24 24
25 import { Button, Input, Select } from 'cube-ui'; 25 import { Button, Input, Select } from 'cube-ui';
  26 +import { mapActions, mapState } from 'vuex';
  27 +
  28 +const areaList = [{
  29 + value: '+61',
  30 + name: '澳大利亚'
  31 + }, {
  32 + value: '+82',
  33 + text: '韩国'
  34 + }, {
  35 + value: '+1',
  36 + text: '加拿大'
  37 + }, {
  38 + value: '+60',
  39 + text: '马来西亚'
  40 + }, {
  41 + value: '+1',
  42 + text: '美国'
  43 + }, {
  44 + value: '+81',
  45 + text: '日本'
  46 + }, {
  47 + value: '+65',
  48 + text: '新加坡'
  49 + }, {
  50 + value: '+44',
  51 + text: '英国'
  52 + }, {
  53 + value: '+86',
  54 + text: '中国'
  55 + }, {
  56 + value: '+853',
  57 + text: '中国澳门'
  58 + }, {
  59 + value: '+886',
  60 + text: '中国台湾'
  61 + }, {
  62 + value: '+852',
  63 + text: '中国香港'
  64 + }];
26 65
27 export default { 66 export default {
28 name: 'ThirdBind', 67 name: 'ThirdBind',
@@ -30,16 +69,29 @@ export default { @@ -30,16 +69,29 @@ export default {
30 return { 69 return {
31 showBind: false, 70 showBind: false,
32 code: '+86', 71 code: '+86',
33 - options: ['+86', '+8700', '+88'], 72 + options: areaList,
  73 + selectTitle: '选择国家和地区',
34 phone: '', 74 phone: '',
35 smsCode: '', 75 smsCode: '',
36 sendBtnText: '' 76 sendBtnText: ''
37 } 77 }
38 }, 78 },
39 methods: { 79 methods: {
  80 + ...mapActions(['sendBindSms', 'submitThirdBind']),
40 show() { 81 show() {
  82 + this.bindCode = this.$route.query.bind_code;
41 this.showBind = true; 83 this.showBind = true;
42 }, 84 },
  85 + close() {
  86 + this.showBind = false;
  87 + },
  88 + toast(msg, time = 2000) {
  89 + this.$createToast && this.$createToast({
  90 + txt: msg,
  91 + type: 'txt',
  92 + time
  93 + }).show();
  94 + },
43 sendSMS() { 95 sendSMS() {
44 let total = 60; 96 let total = 60;
45 let timer = setInterval(() => { 97 let timer = setInterval(() => {
@@ -47,10 +99,32 @@ export default { @@ -47,10 +99,32 @@ export default {
47 this.sendBtnText = '重新获取 ' + total; 99 this.sendBtnText = '重新获取 ' + total;
48 } else { 100 } else {
49 this.sendBtnText = ''; 101 this.sendBtnText = '';
50 - clearInterval(timer) 102 + clearInterval(timer);
51 } 103 }
52 }, 1000); 104 }, 1000);
53 this.sendBtnText = '重新获取 ' + total; 105 this.sendBtnText = '重新获取 ' + total;
  106 +
  107 + this.sendBindSms({
  108 + mobile: this.phone,
  109 + bindCode: this.bindCode
  110 + });
  111 + },
  112 + bindSubmit() {
  113 + if (this.phone && this.smsCode) {
  114 + this.submitThirdBind({
  115 + mobile: this.phone,
  116 + code: this.smsCode,
  117 + bindCode: this.bindCode
  118 + }).then(res => {
  119 + if (res.code === 200) {
  120 + this.close();
  121 + } else {
  122 + this.toast(res.message);
  123 + }
  124 + });
  125 + } else {
  126 + this.toast(this.phone ? '请输入短信验证码' : '请输入手机号');
  127 + }
54 } 128 }
55 }, 129 },
56 components: { 130 components: {
@@ -101,7 +175,7 @@ export default { @@ -101,7 +175,7 @@ export default {
101 } 175 }
102 176
103 .select-block { 177 .select-block {
104 - width: 130px; 178 + min-width: 130px;
105 position: relative; 179 position: relative;
106 margin-right: 10px; 180 margin-right: 10px;
107 181
@@ -14,7 +14,6 @@ export default { @@ -14,7 +14,6 @@ export default {
14 beforeRouteUpdate(to, from, next) { 14 beforeRouteUpdate(to, from, next) {
15 }, 15 },
16 mounted() { 16 mounted() {
17 - this.$createThirdBind().show();  
18 // this.$yoho.authRealName(); 17 // this.$yoho.authRealName();
19 }, 18 },
20 methods: { 19 methods: {
@@ -149,6 +149,19 @@ export default function(mergeState = {}) { @@ -149,6 +149,19 @@ export default function(mergeState = {}) {
149 backImageUrl 149 backImageUrl
150 }); 150 });
151 }, 151 },
  152 + sendBindSms({ commit }, { mobile, bindCode }) {
  153 + return this.$api.post('/passport/bind/sms/send', {
  154 + mobile,
  155 + bindCode
  156 + });
  157 + },
  158 + submitThirdBind({ commit }, { mobile, code, bindCode }) {
  159 + return this.$api.post('/passport/bind/third', {
  160 + mobile,
  161 + code,
  162 + bindCode
  163 + });
  164 + },
152 reportError(params, {error}) { 165 reportError(params, {error}) {
153 this.$reportError(error); 166 this.$reportError(error);
154 }, 167 },
@@ -12,6 +12,8 @@ router.post('/xianyu/upload/idcard', multipartMiddleware, upload.uploadIdCard); @@ -12,6 +12,8 @@ router.post('/xianyu/upload/idcard', multipartMiddleware, upload.uploadIdCard);
12 12
13 router.get('/xianyu/passport/login/taobao', passport.login.taobaoLogin); 13 router.get('/xianyu/passport/login/taobao', passport.login.taobaoLogin);
14 router.get('/xianyu/passport/callback/taobao', passport.login.taobaoCallback); 14 router.get('/xianyu/passport/callback/taobao', passport.login.taobaoCallback);
  15 +router.post('/xianyu/passport/bind/sms/send', passport.bind.sendSms);
  16 +router.post('/xianyu/passport/bind/third', passport.bind.bindByCode);
15 17
16 app.use(router); 18 app.use(router);
17 19
  1 +const _ = require('lodash');
1 const moment = require('moment'); 2 const moment = require('moment');
2 const crypto = global.yoho.crypto; 3 const crypto = global.yoho.crypto;
3 const log = global.yoho.logger; 4 const log = global.yoho.logger;
@@ -39,7 +40,7 @@ const dynamicDecrypt = (str) => { @@ -39,7 +40,7 @@ const dynamicDecrypt = (str) => {
39 let decryptInfo = {}; 40 let decryptInfo = {};
40 41
41 try { 42 try {
42 - let decryptStr = crypto.decrypt(getDailyKey(), `${str}`); 43 + let decryptStr = _.trim(crypto.decrypt(getDailyKey(), `${str}`));
43 let decryptArr = decryptStr.split(connectSymbol); 44 let decryptArr = decryptStr.split(connectSymbol);
44 45
45 decryptInfo.val = decryptArr[0]; 46 decryptInfo.val = decryptArr[0];
@@ -35,7 +35,7 @@ function signMD5(params, clientSecret) { @@ -35,7 +35,7 @@ function signMD5(params, clientSecret) {
35 */ 35 */
36 function Strategy(options, verify) { 36 function Strategy(options, verify) {
37 options = options || {}; 37 options = options || {};
38 - options.authorizationURL = options.authorizationURL || 'https://oauth.taobao.com/authorize'; 38 + options.authorizationURL = options.authorizationURL || 'https://oauth.taobao.com/authorize?view=wap';
39 options.tokenURL = options.tokenURL || 'https://oauth.taobao.com/token'; 39 options.tokenURL = options.tokenURL || 'https://oauth.taobao.com/token';
40 options.scopeSeparator = options.scopeSeparator || ','; 40 options.scopeSeparator = options.scopeSeparator || ',';
41 options.customHeaders = options.customHeaders || {}; 41 options.customHeaders = options.customHeaders || {};
@@ -13,7 +13,7 @@ const crypto = global.yoho.crypto; @@ -13,7 +13,7 @@ const crypto = global.yoho.crypto;
13 const config = global.yoho.config; 13 const config = global.yoho.config;
14 14
15 const loginPage = `${config.siteUrl}/signin.html`; 15 const loginPage = `${config.siteUrl}/signin.html`;
16 -const bindPage = `/xianyu/passport/bind`; 16 +const homePage = `${config.siteUrl}/xianyu/channel`;
17 17
18 // taobao 登录 18 // taobao 登录
19 passport.use('taobao', new TaobaoStrategy({ 19 passport.use('taobao', new TaobaoStrategy({
@@ -25,7 +25,7 @@ passport.use('taobao', new TaobaoStrategy({ @@ -25,7 +25,7 @@ passport.use('taobao', new TaobaoStrategy({
25 done(null, profile); 25 done(null, profile);
26 })); 26 }));
27 27
28 -class signModel extends global.yoho.BaseModel { 28 +class passportModel extends global.yoho.BaseModel {
29 constructor(ctx) { 29 constructor(ctx) {
30 super(ctx); 30 super(ctx);
31 } 31 }
@@ -41,10 +41,7 @@ class signModel extends global.yoho.BaseModel { @@ -41,10 +41,7 @@ class signModel extends global.yoho.BaseModel {
41 param.business_line = businessLine; 41 param.business_line = businessLine;
42 } 42 }
43 43
44 - return this.get({ data: param }).then(res => {  
45 - console.log(res);  
46 - return res;  
47 - }); 44 + return this.get({ data: param });
48 } 45 }
49 syncUserSession({uid, sessionKey, req, res}) { 46 syncUserSession({uid, sessionKey, req, res}) {
50 let userId = { 47 let userId = {
@@ -106,10 +103,30 @@ class signModel extends global.yoho.BaseModel { @@ -106,10 +103,30 @@ class signModel extends global.yoho.BaseModel {
106 }); 103 });
107 }); 104 });
108 } 105 }
  106 + sendTaobaoBindCode(mobile) {
  107 + return this.post({
  108 + data: {
  109 + method: 'app.bind.sendCodeByTB',
  110 + source_type: 'taobao',
  111 + mobile
  112 + }
  113 + });
  114 + }
  115 + bindTaobaoAccountByCode({ mobile, code, openId }) {
  116 + return this.post({
  117 + data: {
  118 + method: 'app.bind.bindTBByCode',
  119 + source_type: 'taobao',
  120 + mobile,
  121 + code,
  122 + open_id: openId
  123 + }
  124 + });
  125 + }
109 }; 126 };
110 127
111 const login = { 128 const login = {
112 - taobaoLogin: (req, res, next) => { 129 + taobaoLogin(req, res, next) {
113 req.session.authState = uuid.v4(); 130 req.session.authState = uuid.v4();
114 131
115 return passport.authenticate('taobao', { 132 return passport.authenticate('taobao', {
@@ -117,14 +134,14 @@ const login = { @@ -117,14 +134,14 @@ const login = {
117 failWithError: true 134 failWithError: true
118 })(req, res, next); 135 })(req, res, next);
119 }, 136 },
120 - taobaoCallback: (req, res, next) => { 137 + taobaoCallback(req, res, next) {
121 passport.authenticate('taobao', (err, user) => { 138 passport.authenticate('taobao', (err, user) => {
122 if (err || !user) { 139 if (err || !user) {
123 log.error(`taobao authenticate error : ${JSON.stringify(err)}`); 140 log.error(`taobao authenticate error : ${JSON.stringify(err)}`);
124 return res.redirect(loginPage); 141 return res.redirect(loginPage);
125 } 142 }
126 -  
127 - const model = req.ctx(signModel); 143 + console.log(user);
  144 + const model = req.ctx(passportModel);
128 145
129 return model.signinByOpenID({ 146 return model.signinByOpenID({
130 openId: user.open_uid, 147 openId: user.open_uid,
@@ -134,11 +151,9 @@ const login = { @@ -134,11 +151,9 @@ const login = {
134 151
135 if (result.code === 200) { 152 if (result.code === 200) {
136 if (_.get(result, 'data.is_bind') === 'N') { 153 if (_.get(result, 'data.is_bind') === 'N') {
137 - redirectUrl = req.cookies.third_backurl ? url.parse(req.cookies.third_backurl) : '/xianyu/passport/bind';  
138 -  
139 - if (redirectUrl.indexOf('?')) {  
140 - redirectUrl += '&bind_code' + crypto.dynamicEncryption(user.open_uid);  
141 - } 154 + redirectUrl = req.cookies.third_backurl ? url.parse(req.cookies.third_backurl) : homePage;
  155 + redirectUrl += redirectUrl.indexOf('?') > 0 ? '&' : '?';
  156 + redirectUrl += 'bind_code=' + encodeURIComponent(aes.dynamicEncryption(`taobao::${user.open_uid}`));
142 } else if (+_.get(result, 'data.uid') > 0) { 157 } else if (+_.get(result, 'data.uid') > 0) {
143 return model.syncUserSession({ 158 return model.syncUserSession({
144 uid: result.data.uid, 159 uid: result.data.uid,
@@ -146,7 +161,7 @@ const login = { @@ -146,7 +161,7 @@ const login = {
146 req, 161 req,
147 res 162 res
148 }).finally(() => { 163 }).finally(() => {
149 - let refer = req.cookies.third_backurl ? url.parse(req.cookies.third_backurl) : ''; 164 + let refer = req.cookies.third_backurl ? url.parse(req.cookies.third_backurl) : homePage;
150 165
151 return res.redirect(refer); 166 return res.redirect(refer);
152 }); 167 });
@@ -157,8 +172,74 @@ const login = { @@ -157,8 +172,74 @@ const login = {
157 }) 172 })
158 })(req, res, next); 173 })(req, res, next);
159 } 174 }
  175 +};
  176 +
  177 +const bind = {
  178 + getBindThirdInfo(bindCode) {
  179 + let info = aes.dynamicDecrypt(bindCode);
  180 + let bindInfo = {
  181 + timestamp: info.timestamp
  182 + };
  183 +
  184 + if (info.val) {
  185 + let splitArr = info.val.split('::');
  186 +
  187 + bindInfo.type = splitArr[0];
  188 + bindInfo.openId = splitArr[1];
  189 + }
  190 +
  191 + return bindInfo;
  192 + },
  193 + sendSms(req, res, next) {
  194 + let { mobile, bindCode } = req.body || {};
  195 + console.log(this)
  196 + let info = bind.getBindThirdInfo(bindCode);
  197 +
  198 + if (info.type === 'taobao') {
  199 + req.ctx(passportModel).sendTaobaoBindCode(mobile).then(res.json).catch(next);
  200 + } else {
  201 + res.json({
  202 + code: 200,
  203 + message: `${info.type || ''} not found`
  204 + });
  205 + }
  206 + },
  207 + bindByCode(req, res, next) {
  208 + let { mobile, code, bindCode } = req.body || {};
  209 + let info = bind.getBindThirdInfo(bindCode);
  210 +
  211 + if (info.type === 'taobao') {
  212 + const model = req.ctx(passportModel);
  213 +
  214 + model.bindTaobaoAccountByCode({
  215 + mobile,
  216 + code,
  217 + openId: info.openId
  218 + }).then(result => {
  219 + if (_.get(result, 'data.is_bind') === 'Y') {
  220 + model.syncUserSession({
  221 + uid: result.data.uid,
  222 + sessionKey: result.data.session_key,
  223 + req,
  224 + res
  225 + }).finally(() => {
  226 + delete result.data;
  227 + res.json(result);
  228 + });
  229 + } else {
  230 + res.json(result);
  231 + }
  232 + }).catch(next);
  233 + } else {
  234 + res.json({
  235 + code: 400,
  236 + message: '登录失败请稍后重试'
  237 + });
  238 + }
  239 + }
160 } 240 }
161 241
162 module.exports = { 242 module.exports = {
163 - login 243 + login,
  244 + bind
164 }; 245 };