01 | /* |
02 | * 微信公众平台 Node.js SDK 1.0.0 |
03 | * (c) 2012-2013 ____′↘夏悸 <wmails@126.cn>, MIT Licensed |
04 | * http://www.jeasyuicn.com/wechat |
05 | */ |
06 | var http = require( 'http' ); |
07 |
08 | var wechat = require( './wechat' ); |
09 | http.createServer( function (req, res) { |
10 | wechat.process(req, res); |
11 | }).listen(3000, "127.0.0.1" ); |
12 |
13 | /* |
14 | 实现自定义消息处理器 |
15 | var myMsgHandler = require('./myMsgHandler'); |
16 | http.createServer(function (req, res) { |
17 | wechat.process(req, res,myMsgHandler); |
18 | }).listen(3000, "127.0.0.1"); |
19 | */ |
20 |
21 | /* |
22 | 实现自定义请求过滤类型 |
23 | http.createServer(function (req, res) { |
24 | wechat.process(req, res,null,'/mywechat/'); |
25 | }).listen(3000, "127.0.0.1"); |
26 | */ |
001 | /* |
002 | * 微信公众平台开发模式 Node.js SDK 1.0.0 |
003 | * (c) 2012-2013 ____′↘夏悸 <wmails@126.cn>, MIT Licensed |
004 | * http://www.jeasyuicn.com/wechat |
005 | */ |
006 |
007 | var path, method, query, body, _token; |
008 | var igon = [ "attributes" , "parent" , "count" , "at" , "each" , "text" ]; |
009 | var url = require( 'url' ); |
010 | var util = require( './util' ); |
011 | var querystring = require( 'querystring' ); |
012 | var xmlreader = require( "xmlreader" ); |
013 | //默认过滤请求类型 |
014 | var defaultFilter = "/wechat/" ; |
015 | //默认消息处理器 |
016 | var msgHandler = require( './defaultMsgHandler' ); |
017 |
018 | //处理入口 |
019 | exports.process = function (req, res, handler, filter) { |
020 | path = url.parse(req.url).pathname; |
021 | filter = filter || defaultFilter; |
022 | res.writeHead(200, { |
023 | 'Content-Type' : 'text/plain' |
024 | }); |
025 | if (path.indexOf(filter) != 0) { |
026 | res.end(path); |
027 | return ; |
028 | } |
029 |
030 | method = req.method; |
031 | query = querystring.parse(req.url.split( "?" )[1]); |
032 | msgHandler = handler || msgHandler; |
033 | |
034 | //处理wechat类型的请求 |
035 | _token = path.replace(filter, "" ); |
036 | if (method == "GET" ) { |
037 | doGet(res); |
038 | } else { |
039 | body = '' ; |
040 | req.setEncoding( 'utf8' ); |
041 | req.addListener( 'data' , function (chunk) { |
042 | body += chunk; |
043 | }); |
044 | req.addListener( 'end' , function () { |
045 | doPost(res); |
046 | }); |
047 | } |
048 | }; |
049 |
050 | function doGet(res) { |
051 | if (checkSignature()) { |
052 | res.end(query.echostr); |
053 | } else { |
054 | res.end( "signature error" ); |
055 | } |
056 | } |
057 |
058 | function doPost(res) { |
059 | xmlreader.read(body, function (errors, response) { |
060 | if ( null !== errors) { |
061 | console.log(errors); |
062 | return ; |
063 | } |
064 | var msg = {}; |
065 | for ( var k in response.xml) { |
066 | if (igon.indexOf(k) == -1) { |
067 | if (response.xml[k] && response.xml[k].text) { |
068 | msg[k] = response.xml[k].text.call(); |
069 | } |
070 | } |
071 | } |
072 | var callBack = msgHandler[msg.MsgType + "TypeMsg" ]; |
073 | if (callBack && typeof callBack == "function" ){ |
074 | callBack.call(msg, new outPut(res,msg)); |
075 | } else { |
076 | res.end( "signature error" ); |
077 | } |
078 | }); |
079 | } |
080 | /* |
081 | * 签名认证 |
082 | */ |
083 | function checkSignature() { |
084 | var params = [_token, query.timestamp, query.nonce]; |
085 | var signature = query.signature; |
086 | params = params.sort(); |
087 | var temp = params[0] + params[1] + params[2]; |
088 | var crypto = require( 'crypto' ); |
089 | var sha1 = crypto.createHash( 'sha1' ); |
090 | sha1.update(temp) |
091 | var hex = sha1.digest( 'hex' ); |
092 | return (hex === signature); |
093 | } |
094 |
095 | /*********输出消息处理**************/ |
096 | //输出模板 |
097 | var textMsg = '<xml> <ToUserName><![CDATA[{{ToUserName}}]]></ToUserName> <FromUserName><![CDATA[{{FromUserName}}]]></FromUserName> <CreateTime>{{CreateTime}}</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[{{Content}}]]></Content> </xml>' ; |
098 | var musicMsg = '<xml> <ToUserName><![CDATA[{{ToUserName}}]]></ToUserName> <FromUserName><![CDATA[{{FromUserName}}]]></FromUserName> <CreateTime>{{CreateTime}}</CreateTime> <MsgType><![CDATA[music]]></MsgType> <Music> <Title><![CDATA[{{Title}}]]></Title> <Description><![CDATA[{{Description}}]]></Description> <MusicUrl><![CDATA[{{MusicUrl}}]]></MusicUrl> <HQMusicUrl><![CDATA[{{HQMusicUrl}}]]></HQMusicUrl> </Music> </xml>' ; |
099 |
100 | function outPut(res,msg){ |
101 | res.writeHead(200, { |
102 | 'Content-Type' : 'text/xml' |
103 | }); |
104 | /* |
105 | * 输出文本消息 |
106 | */ |
107 | this .text = function (text) { |
108 | var data = {}; |
109 | data[ "Content" ] = text; |
110 | data[ "CreateTime" ] = new Date().getTime(); |
111 | data[ "ToUserName" ] = msg.FromUserName; |
112 | data[ "FromUserName" ] = msg.ToUserName; |
113 | res.end(util.template(textMsg, data)); |
114 | }, |
115 | /* |
116 | * 输出音乐消息 |
117 | */ |
118 | this .music = function (Title, Description, MusicUrl, HQMusicUrl) { |
119 | var data = {}; |
120 | data[ "Title" ] = Title; |
121 | data[ "Description" ] = Description; |
122 | data[ "MusicUrl" ] = MusicUrl; |
123 | data[ "HQMusicUrl" ] = HQMusicUrl; |
124 |
125 | data[ "CreateTime" ] = new Date().getTime(); |
126 | data[ "ToUserName" ] = msg.FromUserName; |
127 | data[ "FromUserName" ] = msg.ToUserName; |
128 | res.end(musicMsg, data); |
129 | }, |
130 | /* |
131 | *输出图文消息 |
132 | */ |
133 | this .news = function (data) { |
134 | res.end( this .MsgType); |
135 | } |
136 | } |
01 | /* |
02 | * 微信公众平台开发模式 Node.js SDK 1.0.0 |
03 | * (c) 2012-2013 ____′↘夏悸 <wmails@126.cn>, MIT Licensed |
04 | * http://www.jeasyuicn.com/wechat |
05 | * |
06 | * 默认的消息处理器,可以直接修改本默认处理器,如果自定义请保证结构. |
07 | */ |
08 | |
09 |
10 | /* |
11 | * 文字消息 |
12 | */ |
13 | exports.textTypeMsg = function (outPut) { |
14 | outPut.text( "这是文字消息" ); |
15 | }; |
16 | /* |
17 | * 地理位置消息 |
18 | */ |
19 | exports.locationTypeMsg = function (outPut) { |
20 | outPut.text( "这是地理位置消息" ); |
21 | }; |
22 | /* |
23 | * 链接消息 |
24 | */ |
25 | exports.linkTypeMsg = function (outPut) { |
26 | outPut.text( "这是链接消息" ); |
27 | }; |
28 | /* |
29 | * 图片消息 |
30 | */ |
31 | exports.imageTypeMsg = function (outPut) { |
32 | outPut.text( "这是图片消息" ); |
33 | }; |
34 | /* |
35 | * 语音消息 |
36 | */ |
37 | exports.voiceTypeMsg = function (outPut) { |
38 | outPut.text( "这是语音消息" ); |
39 | }; |
40 | /* |
41 | * 事件 |
42 | */ |
43 | exports.eventTypeMsg = function (outPut) { |
44 | var event = this .Event; |
45 | //订阅 |
46 | if (event == "subscribe" ) { |
47 | outPut.text( "订阅成功!" ); |
48 | } |
49 | }; |