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&app;
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?app&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?app&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?app&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 + "&open&;
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?app&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?app&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 };