Showing
4 changed files
with
124 additions
and
1 deletions
apps/api/controllers/wechat.js
0 → 100644
1 | +/** | ||
2 | + * 微信分享签名 | ||
3 | + * Bi Kai <kai.bi@yoho.cn> | ||
4 | + */ | ||
5 | +'use strict'; | ||
6 | +const wechatModel = require('../models/wechat'); | ||
7 | + | ||
8 | +exports.shareToken = (req, res, next) => { | ||
9 | + wechatModel.calcSignature({ | ||
10 | + url: req.query.url || 'http://www.yohoblk.com/' | ||
11 | + }).then((result) => { | ||
12 | + res.jsonp(result); | ||
13 | + }).catch(next); | ||
14 | +}; |
apps/api/models/wechat.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +/* | ||
4 | + * 生成微信分享所需的签名 | ||
5 | + * bikai <kai.bi@yoho.cn> | ||
6 | + * 2016.6.15 | ||
7 | + */ | ||
8 | +const request = require('request-promise'); | ||
9 | +const Promise = require('bluebird'); | ||
10 | +const crypto = require('crypto'); | ||
11 | +const logger = global.yoho.logger; | ||
12 | +const cache = global.yoho.cache; | ||
13 | + | ||
14 | +// 此处请勿使用有货公众号的 appId, 此处使用的是 女生志 的appId | ||
15 | +const appId = 'wxb52ec6a352f0b090'; | ||
16 | +const secret = '9fe6bedb0b7f30986a168c7fc44f34c0'; | ||
17 | + | ||
18 | +const sha1 = (str) => { | ||
19 | + const generator = crypto.createHash('sha1'); | ||
20 | + | ||
21 | + generator.update(str); | ||
22 | + return generator.digest('hex'); | ||
23 | +}; | ||
24 | + | ||
25 | +const accessTokenCacheKey = 'wechatShare:accessToken'; | ||
26 | +const ticketCacheKey = 'wechatShare:ticket'; | ||
27 | + | ||
28 | +// 微信 JS 接口签名校验工具 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign | ||
29 | + | ||
30 | +let _getAccessToken = Promise.coroutine(function* () { | ||
31 | + let accessToken = yield cache.get(accessTokenCacheKey); | ||
32 | + | ||
33 | + if (accessToken) { | ||
34 | + return accessToken; | ||
35 | + } | ||
36 | + | ||
37 | + logger.info('get accessToken from wechat API'); | ||
38 | + return request({ | ||
39 | + url: 'https://api.weixin.qq.com/cgi-bin/token', | ||
40 | + qs: { | ||
41 | + grant_type: 'client_credential', | ||
42 | + appid: appId, | ||
43 | + secret: secret | ||
44 | + }, | ||
45 | + json: true | ||
46 | + }).then((res) => { | ||
47 | + | ||
48 | + // accessToken 有效期 7200s,缓存 7100s | ||
49 | + cache.set(accessTokenCacheKey, res.access_token, 7100).catch((err) => { | ||
50 | + logger.error('set wechat accessToken cache error', JSON.stringify(err)); | ||
51 | + }); | ||
52 | + return res.access_token; | ||
53 | + }).catch((err) => { | ||
54 | + logger.error('get accessToken from wechat API error', JSON.stringify(err)); | ||
55 | + }); | ||
56 | +}); | ||
57 | + | ||
58 | +let _getTicket = Promise.coroutine(function* () { | ||
59 | + let ticket = yield cache.get(ticketCacheKey); | ||
60 | + | ||
61 | + if (ticket) { | ||
62 | + return ticket; | ||
63 | + } | ||
64 | + | ||
65 | + logger.info('get ticket from wechat API'); | ||
66 | + return request({ | ||
67 | + url: 'https://api.weixin.qq.com/cgi-bin/ticket/getticket', | ||
68 | + qs: { | ||
69 | + access_token: yield _getAccessToken(), | ||
70 | + type: 'jsapi' | ||
71 | + }, | ||
72 | + json: true | ||
73 | + }).then(res => { | ||
74 | + | ||
75 | + // ticket 有效期 7200s,缓存 7100s | ||
76 | + cache.set(ticketCacheKey, res.ticket, 7100).catch((err) => { | ||
77 | + logger.error('set wechat Token cache error', JSON.stringify(err)); | ||
78 | + }); | ||
79 | + return res.ticket; | ||
80 | + }).catch((err) => { | ||
81 | + logger.error('get ticket from wechat API error', JSON.stringify(err)); | ||
82 | + }); | ||
83 | +}); | ||
84 | + | ||
85 | +let calcSignature = Promise.coroutine(function* (data) { | ||
86 | + data = Object.assign({ | ||
87 | + nonceStr: Math.random().toString(36).substr(2, 15), | ||
88 | + timestamp: Math.floor(Date.now() / 1000) + '', | ||
89 | + ticket: yield _getTicket(), | ||
90 | + appId: appId | ||
91 | + }, data); | ||
92 | + | ||
93 | + const str = `jsapi_ticket=${data.ticket}&noncestr=${data.nonceStr}×tamp=${data.timestamp}&url=${data.url}`; | ||
94 | + | ||
95 | + data.signature = sha1(str); | ||
96 | + return data; | ||
97 | +}); | ||
98 | + | ||
99 | +// 测试 | ||
100 | +// calcSignature({ | ||
101 | +// url: 'http://www.yohobuy.com/' | ||
102 | +// }).then(console.log); | ||
103 | + | ||
104 | +module.exports = { | ||
105 | + calcSignature | ||
106 | +}; |
@@ -11,8 +11,11 @@ const router = require('express').Router(); // eslint-disable-line | @@ -11,8 +11,11 @@ const router = require('express').Router(); // eslint-disable-line | ||
11 | var multipart = require('connect-multiparty'); | 11 | var multipart = require('connect-multiparty'); |
12 | var multipartMiddleware = multipart(); | 12 | var multipartMiddleware = multipart(); |
13 | 13 | ||
14 | -const uploadApi = require('./upload/upload.js'); | 14 | +const uploadApi = require('./controllers/upload.js'); |
15 | +const wechat = require('./controllers/wechat.js'); | ||
15 | 16 | ||
16 | router.post('/upload/image', multipartMiddleware, uploadApi.uploadImg); | 17 | router.post('/upload/image', multipartMiddleware, uploadApi.uploadImg); |
17 | 18 | ||
19 | +router.get('/wechat/share/token', wechat.shareToken); | ||
20 | + | ||
18 | module.exports = router; | 21 | module.exports = router; |
-
Please register or login to post a comment