1 /* jshint -W079 */ 2 /* jshint -W020 */ 3 4 "use strict"; 5 var _ = require("lodash"); 6 var sha1 = require('sha1'); 7 var urlencode = require('urlencode'); 8 var request = require('request'); 9 var express = require('express'); 10 var router = express.Router(); 11 12 module.exports = function(app) { 13 14 /* 微信中继接口 */ 15 router.get('/wechat/ticket', function (req, res) { 16 var page = req.query.page; 17 18 if (page && page.indexOf('from=singlemessage') > 0 && page.indexOf('&isappinstalled=0') < 0) { 19 page = page + "&isappinstalled=0"; 20 } 21 22 WeChatTicket.findOne({appid: appid}).exec(function (err, ticket) { 23 if (_.isEmpty(ticket)) refreshTicket(appid, appsecret, page, null, res); 24 else { 25 var difference = parseInt(new Date().getTime() / 1000) - ticket.at; 26 if (difference > 7100) refreshTicket(appid, appsecret, page, ticket, res); 27 else { 28 var json = ticket.toJSON(); 29 30 var timestamp = parseInt(new Date().getTime() / 1000); 31 json.at = timestamp; 32 json.signature = wechatSignature(ticket, page, timestamp); 33 34 res.json({ticket: json}); 35 } 36 } 37 }); 38 }); 39 40 // 微信 access_token 接口 41 router.get('/wechat/access_token', function (req, res) { 42 getToken(appid, appsecret, function(token, error) { 43 if(error) console.error(error); 44 res.json(token); 45 }); 46 }); 47 48 function getToken(appid, appsecret, cb) { 49 WeChatAccessToken.findOne({appid: appid}, function (err, token) { 50 if(token) { 51 var difference = parseInt(new Date().getTime() / 1000) - token.at; 52 if (difference > 7100) refreshToken(appid, appsecret, function(data, err) { cb(data, err); }); 53 else cb(token, null); 54 } else refreshToken(appid, appsecret, function(data, err) { cb(data, err); }); 55 }); 56 } 57 58 function refreshToken(appid, appsecret, cb) { 59 var access_token_api = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"; 60 var url = access_token_api.replace('APPID', appid).replace('APPSECRET', appsecret); 61 62 // 参考请求: http://localhost:7000/wechat/ticket?appid=wx8160a61c2d53fb74&appsecret=aa2c953465334823e20090156527a957 63 request.get(url, function (error, response, body) { 64 if (body) { 65 WeChatAccessToken.findOne({appid: appid}, function (err, token) { 66 if (!token) token = new WeChatAccessToken(); 67 var data = JSON.parse(body); 68 69 token.appid = appid; 70 token.access_token = data.access_token; 71 token.expires_in = data.expires_in; 72 token.at = parseInt(new Date().getTime() / 1000); 73 token.save(function (err) { cb(token, err); }); 74 }); 75 } else cb(null, error); 76 }); 77 } 78 79 function refreshTicket(appid, appsecret, page, ticket, res) { 80 getToken(appid, appsecret, function (token, err) { 81 if (err === null) { 82 if (!_.isEmpty(token.access_token)) { 83 // 获取 jsapi_ticket 84 var ticket_url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + token.access_token + '&type=jsapi'; 85 86 request.get(ticket_url, function (error, response, body) { 87 var t = ticket === null ? new WeChatTicket() : ticket; 88 var data = JSON.parse(body); 89 90 if(!data.ticket) res.json({error: response}); 91 else { 92 t.appid = appid; 93 t.ticket = data.ticket; 94 t.noncestr = sha1(new Date()); 95 t.expires_in = data.expires_in; 96 t.at = parseInt(new Date().getTime() / 1000); 97 98 var timestamp = parseInt(new Date().getTime() / 1000); 99 var signature = wechatSignature(t, page, timestamp); 100 101 t.save(function (err) { 102 var json = t.toJSON(); 103 json.at = timestamp; 104 json.signature = signature; 105 res.json({ticket: json, error: err}); 106 }); 107 } 108 }); 109 } else res.json({error: err}); 110 } else res.json({error: err}); 111 }); 112 } 113 114 /* 微信签名实现 */ 115 function wechatSignature(t, page, timestamp) { 116 var string = "jsapi_ticket=" + t.ticket + "&noncestr=" + t.noncestr + "×tamp=" + timestamp + "&url=" + page; 117 return sha1(string); 118 } 119 120 /* 微信授权接口 */ 121 router.get('/wechat/userinfo', function(req, res) { 122 var cb = req.query.cb; 123 res.cookie(wechat_userinfo_callback_url, cb); 124 var url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=http://m.moretao.com/wechat/userinfo/callback&response_type=code&scope=snsapi_userinfo#wechat_redirect"; 125 res.redirect(url); 126 }); 127 128 router.get('/wechat/userinfo/callback', function(req, res) { 129 var code = req.query.code; 130 var url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appid + "&secret=" + appsecret + "&code=" + code + "&grant_type=authorization_code"; 131 request.get(url, function(error, response, body) { 132 var json = JSON.parse(body); 133 134 var refresh_url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + appid + "&grant_type=refresh_token&refresh_token=" + json.refresh_token; 135 136 request.get(refresh_url, function(error, response, refresh) { 137 var json = JSON.parse(refresh); 138 var info_url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + json.access_token + "&openid=" + json.openid + "&lang=zh_CN"; 139 request.get(info_url, function(error, response, info) { 140 var callback = req.cookies[wechat_userinfo_callback_url]; 141 var str = "?data="; 142 if(callback && callback.indexOf('?') > -1) str = "&data="; 143 var ret = callback + str + encodeURIComponent(info); 144 res.redirect(ret); 145 }); 146 }); 147 }); 148 }); 149 150 /* 微信静默授权接口 */ 151 router.get('/wechat/silent', function(req, res) { 152 var cb = req.query.cb; 153 res.cookie(wechat_silent_callback_url, cb); 154 var url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=http://m.moretao.com/wechat/silent/callback&response_type=code&scope=snsapi_base#wechat_redirect"; 155 res.redirect(url); 156 }); 157 158 router.get('/wechat/silent/callback', function(req, res) { 159 var code = req.query.code; 160 var url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appid + "&secret=" + appsecret + "&code=" + code + "&grant_type=authorization_code"; 161 162 request.get(url, function(error, response, body) { 163 var callback = req.cookies[wechat_silent_callback_url]; 164 var str = "?data="; 165 if(callback.indexOf('?') > -1) str = "&data="; 166 res.redirect(callback + str + body); 167 }); 168 }); 169 170 return router; 171 };