Authored by ccbikai

Merge branch 'feature/wechatShare' into develop

  1 +'use strict';
  2 +const wechatModel = require('../models/wechat');
  3 +
  4 +exports.wechatShare = (req, res, next) => {
  5 + wechatModel.calcSignature({
  6 + url: req.query.url || 'http://www.yohobuy.com/'
  7 + }).then((result) => {
  8 + res.jsonp(result);
  9 + }).catch(next);
  10 +};
  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 = require('../../../library/logger');
  12 +const cache = require('../../../library/cache');
  13 +
  14 +const appId = 'wx75e5a7c0c88e45c2';
  15 +const secret = 'ce21ae4a3f93852279175a167e54509b';
  16 +
  17 +const sha1 = (etr) => {
  18 + const generator = crypto.createHash('sha1');
  19 +
  20 + generator.update(etr);
  21 + return generator.digest('hex');
  22 +};
  23 +
  24 +const accessTokenCacheKey = 'wechatShare:accessToken';
  25 +const ticketCacheKey = 'wechatShare:ticket';
  26 +
  27 +// 微信 JS 接口签名校验工具 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign
  28 +
  29 +const wechat = {
  30 + getAccessToken: Promise.coroutine(function* () {
  31 + let accessToken = yield cache.get(accessTokenCacheKey);
  32 +
  33 + if (accessToken) {
  34 + return accessToken;
  35 + }
  36 +
  37 + logger.info('调用微信 API 获取 accessToken');
  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('微信分享 Token, 缓存 accessToken 时出错', JSON.stringify(err));
  51 + });
  52 + return res.access_token;
  53 + }).catch((err) => {
  54 + logger.error('微信分享 Token, 获取 accessToken 时出错', JSON.stringify(err));
  55 + });
  56 + }),
  57 +
  58 + getTicket: Promise.coroutine(function* (accessToken) {
  59 + let ticket = yield cache.get(ticketCacheKey);
  60 +
  61 + if (ticket) {
  62 + return ticket;
  63 + }
  64 +
  65 + logger.info('调用微信 API 获取 ticket');
  66 + return request({
  67 + url: 'https://api.weixin.qq.com/cgi-bin/ticket/getticket',
  68 + qs: {
  69 + access_token: accessToken,
  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('微信分享 Token, 缓存 ticket 时出错', JSON.stringify(err));
  78 + });
  79 + return res.ticket;
  80 + }).catch((err) => {
  81 + logger.error('微信分享 Token, 获取 ticket 时出错', JSON.stringify(err));
  82 + });
  83 + }),
  84 +
  85 + calcSignature: Promise.coroutine(function* (data) {
  86 + let accessToken = yield this.getAccessToken();
  87 +
  88 + data = Object.assign({
  89 + noncestr: Math.random().toString(36).substr(2, 15),
  90 + timestamp: Math.floor(Date.now() / 1000) + '',
  91 + ticket: yield this.getTicket(accessToken)
  92 + }, data);
  93 + const str = `jsapi_ticket=${data.ticket}&noncestr=${data.noncestr}&timestamp=${data.timestamp}&url=${data.url}`;
  94 +
  95 + data.signature = sha1(str);
  96 + return data;
  97 + })
  98 +};
  99 +
  100 +// 测试
  101 +// wechat.calcSignature({
  102 +// url: 'http://www.yohobuy.com/'
  103 +// }).then(console.log);
  104 +
  105 +module.exports = wechat;
@@ -6,10 +6,11 @@ @@ -6,10 +6,11 @@
6 6
7 'use strict'; 7 'use strict';
8 8
9 -const router = require('express').Router(); 9 +const router = require('express').Router(); // eslint-disable-line
10 const cRoot = './controllers'; 10 const cRoot = './controllers';
11 11
12 const coupon = require(`${cRoot}/coupon`); 12 const coupon = require(`${cRoot}/coupon`);
  13 +const wechat = require(`${cRoot}/wechat`);
13 14
14 // routers 15 // routers
15 16
@@ -19,4 +20,6 @@ router.get('/coupon/phone', coupon.getCoupon); @@ -19,4 +20,6 @@ router.get('/coupon/phone', coupon.getCoupon);
19 20
20 router.get('/coupon/verify', coupon.verify); 21 router.get('/coupon/verify', coupon.verify);
21 22
  23 +router.get('/wechat/share', wechat.wechatShare);
  24 +
22 module.exports = router; 25 module.exports = router;