Showing
9 changed files
with
201 additions
and
26 deletions
@@ -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 | }; |
-
Please register or login to post a comment