From e06d49b02b975f7aa854f819dc84098cab06a82b Mon Sep 17 00:00:00 2001 From: Jackson Tian Date: Thu, 31 Oct 2013 23:59:53 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E8=A1=A5=E4=B8=80=E4=BA=9B=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + lib/common.js | 33 +++++++---- test/common.test.js | 123 +++++++++++++++++++++++++++++++++++++++++ test/fixture/image.jpg | Bin 0 -> 76053 bytes 4 files changed, 146 insertions(+), 11 deletions(-) create mode 100644 test/fixture/image.jpg diff --git a/.gitignore b/.gitignore index 9de9b70d..f0fe0cba 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules lib-cov coverage.html +example diff --git a/lib/common.js b/lib/common.js index 3b99c0e5..aa8e3c06 100644 --- a/lib/common.js +++ b/lib/common.js @@ -1,9 +1,12 @@ +var path = require('path'); +var fs = require('fs'); var urllib = require('urllib'); var formstream = require('formstream'); // http://mp.weixin.qq.com/wiki/index.php?title=%E8%BF%94%E5%9B%9E%E7%A0%81%E8%AF%B4%E6%98%8E var wrapper = function (callback) { return function (err, data, res) { + if (err) { err.name = 'WeChatAPI' + err.name; return callback(err, data, res); @@ -388,18 +391,26 @@ API.prototype.sendNews = function (openid, articles, callback) { ['image', 'voice', 'video', 'thumb'].forEach(function (type) { var method = 'upload' + type[0].toUpperCase() + type.substring(1); API.prototype[method] = function (filepath, callback) { - var form = formstream(); - form.file('media', filepath); - form.headers({ - 'Content-Type': 'application/json' + var that = this; + fs.stat(filepath, function (err, stat) { + if (err) { + return callback(err); + } + var form = formstream(); + form.file('media', filepath, path.basename(filepath), stat.size); + form.headers({ + 'Content-Type': 'application/json' + }); + var url = that.fileServerPrefix + 'media/upload?access_token=' + that.token + '&type=' + type; + var opts = { + dataType: 'json', + type: 'POST', + timeout: 60000, // 60秒超时 + headers: form.headers(), + stream: form + }; + urllib.request(url, opts, wrapper(callback)); }); - var url = this.fileServerPrefix + 'media/upload?access_token=' + this.token + '&type=' + type; - urllib.request(url, { - dataType: 'json', - type: 'POST', - headers: form.headers(), - stream: form - }, wrapper(callback)); }; }); diff --git a/test/common.test.js b/test/common.test.js index db9e348c..d583b5ce 100644 --- a/test/common.test.js +++ b/test/common.test.js @@ -1,6 +1,7 @@ var should = require('should'); var urllib = require('urllib'); var muk = require('muk'); +var path = require('path'); var API = require('../').API; describe('common.js', function () { @@ -262,6 +263,128 @@ describe('common.js', function () { done(); }); }); + + describe('upload media', function () { + ['Image', 'Voice', 'Video', 'Thumb'].forEach(function (method) { + before(function () { + muk(urllib, 'request', function (url, args, callback) { + var resp = { + "type":"image", + "media_id":"usr5xL_gcxapoRjwH3bQZw_zKvcXL-DU4tRJtLtrtN71-3bXL52p3xX63ebp7tqA", + "created_at":1383233542 + }; + process.nextTick(function () { + callback(null, resp); + }); + }); + }); + + after(function () { + muk.restore(); + }); + it('upload' + method + ' should ok', function (done) { + api['upload' + method](path.join(__dirname, './fixture/image.jpg'), function (err, data, res) { + should.not.exist(err); + data.should.have.property('type', 'image'); + data.should.have.property('media_id'); + data.should.have.property('created_at'); + done(); + }); + }); + + it('upload' + method + ' should not ok', function (done) { + api['upload' + method](path.join(__dirname, './fixture/inexist.jpg'), function (err, data, res) { + should.exist(err); + err.should.have.property('name', 'Error'); + err.should.have.property('code', 'ENOENT'); + done(); + }); + }); + }); + }); + + describe('get media with buffer', function () { + before(function () { + muk(urllib, 'request', function (url, args, callback) { + var buffer = new Buffer('Hello world!'); + var res = { + headers: { + 'content-type': 'image/jpeg' + } + }; + process.nextTick(function () { + callback(null, buffer, res); + }); + }); + }); + + after(function () { + muk.restore(); + }); + + it('getMedia with buffer', function (done) { + api.getMedia('media_id', function (err, data, res) { + should.not.exist(err); + data.toString().should.be.equal('Hello world!'); + done(); + }); + }); + }); + + describe('get media with json', function () { + before(function () { + muk(urllib, 'request', function (url, args, callback) { + var data = JSON.stringify({"errcode":40007, "errmsg":"invalid media_id"}); + var res = { + headers: { + 'content-type': 'application/json' + } + }; + process.nextTick(function () { + callback(null, data, res); + }); + }); + }); + + after(function () { + muk.restore(); + }); + it('getMedia with json', function (done) { + api.getMedia('media_id', function (err, data, res) { + should.exist(err); + err.should.have.property('name', 'WeChatAPIError'); + err.should.have.property('message', 'invalid media_id'); + done(); + }); + }); + }); + + describe('get media with err json', function () { + before(function () { + muk(urllib, 'request', function (url, args, callback) { + var data = '{"errcode":40007, "errmsg":"invalid media_id"'; + var res = { + headers: { + 'content-type': 'application/json' + } + }; + process.nextTick(function () { + callback(null, data, res); + }); + }); + }); + + after(function () { + muk.restore(); + }); + it('getMedia with err json', function (done) { + api.getMedia('media_id', function (err, data, res) { + should.exist(err); + err.should.have.property('name', 'SyntaxError'); + done(); + }); + }); + }); }); describe('mock', function () { diff --git a/test/fixture/image.jpg b/test/fixture/image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a03993103c9b393e1e5d6bcef5504c6ddf9a42af GIT binary patch literal 76053 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 F{|9MYr9S`w literal 0 HcmV?d00001 From 1953941a42e6c17c70097cc718408680e2c4b114 Mon Sep 17 00:00:00 2001 From: Jackson Tian Date: Sun, 3 Nov 2013 22:17:56 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common.js | 559 +++++++++++++++++++++++++++++++++++++++++-------- lib/session.js | 30 ++- lib/wechat.js | 14 +- 3 files changed, 507 insertions(+), 96 deletions(-) diff --git a/lib/common.js b/lib/common.js index aa8e3c06..63128121 100644 --- a/lib/common.js +++ b/lib/common.js @@ -31,6 +31,17 @@ var postJSON = function (data) { }; }; +/** + * 根据appid和appsecret创建API的构造函数 + * + * Examples: + * ``` + * var API = require('wechat').API; + * var api = new API('appid', 'secret'); + * ``` + * @param {String} appid 在公众平台上申请得到的appid + * @param {String} appsecret 在公众平台上申请得到的app secret + */ var API = function (appid, appsecret) { this.appid = appid; this.appsecret = appsecret; @@ -39,9 +50,23 @@ var API = function (appid, appsecret) { }; /** - * 根据appid和appsecret获取access token - * @param {String} appid appid - * @param {String} appsecret secret + * 根据创建API时传入的appid和appsecret获取access token + * 进行后续所有API调用时,需要先获取access token + * 详细请看: + * + * Examples: + * ``` + * api.getAccessToken(callback); + * ``` + * Callback: + * + * - `err`, 获取access token出现异常时的异常对象 + * - `result`, 成功时得到的响应结果 + * + * Result: + * ``` + * {"access_token": "ACCESS_TOKEN","expires_in": 7200} + * ``` * @param {Function} callback 回调函数 */ API.prototype.getAccessToken = function (callback) { @@ -58,7 +83,49 @@ API.prototype.getAccessToken = function (callback) { }; /** - * 创建菜单 + * 创建自定义菜单 + * 详细请看:http://mp.weixin.qq.com/wiki/index.php?title=自定义菜单创建接口 + * + * Menu: + * ``` + * { + * "button":[ + * { + * "type":"click", + * "name":"今日歌曲", + * "key":"V1001_TODAY_MUSIC" + * }, + * { + * "name":"菜单", + * "sub_button":[ + * { + * "type":"view", + * "name":"搜索", + * "url":"http://www.soso.com/" + * }, + * { + * "type":"click", + * "name":"赞一下我们", + * "key":"V1001_GOOD" + * }] + * }] + * } + * ] + * } + * ``` + * Examples: + * ``` + * api.createMenu(menu, callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * + * Result: + * ``` + * {"errcode":0,"errmsg":"ok"} + * ``` * @param {Object} menu 菜单对象 * @param {Function} callback 回调函数 */ @@ -69,6 +136,34 @@ API.prototype.createMenu = function (menu, callback) { /** * 获取菜单 + * 详细请看: + * + * Examples: + * ``` + * api.getMenu(callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * + * Result: + * ``` + * // 结果示例 + * { + * "menu": { + * "button":[ + * {"type":"click","name":"今日歌曲","key":"V1001_TODAY_MUSIC","sub_button":[]}, + * {"type":"click","name":"歌手简介","key":"V1001_TODAY_SINGER","sub_button":[]}, + * {"name":"菜单","sub_button":[ + * {"type":"view","name":"搜索","url":"http://www.soso.com/","sub_button":[]}, + * {"type":"view","name":"视频","url":"http://v.qq.com/","sub_button":[]}, + * {"type":"click","name":"赞一下我们","key":"V1001_GOOD","sub_button":[]}] + * } + * ] + * } + * } + * ``` * @param {Function} callback 回调函数 */ API.prototype.getMenu = function (callback) { @@ -77,7 +172,21 @@ API.prototype.getMenu = function (callback) { }; /** - * 删除菜单 + * 删除自定义菜单 + * 详细请看: + * Examples: + * ``` + * api.removeMenu(callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * + * Result: + * ``` + * {"errcode":0,"errmsg":"ok"} + * ``` * @param {Function} callback 回调函数 */ API.prototype.removeMenu = function (callback) { @@ -97,7 +206,24 @@ API.prototype.getQRCode = function (data, callback) { /** * 创建临时二维码 - * @param {String} sceneId 场景ID + * 详细请看: + * Examples: + * ``` + * api.createTmpQRCode(10000, 1800, callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * + * Result: + * ``` + * { + * "ticket":"gQG28DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL0FuWC1DNmZuVEhvMVp4NDNMRnNRAAIEesLvUQMECAcAAA==", + * "expire_seconds":1800 + * } + * ``` + * @param {Number} sceneId 场景ID * @param {Number} expire 过期时间,单位秒。最大不超过1800 * @param {Function} callback 回调函数 */ @@ -113,7 +239,23 @@ API.prototype.createTmpQRCode = function (sceneId, expire, callback) { /** * 创建永久二维码 - * @param {String} sceneId 场景ID。ID不能大于1000 + * 详细请看: + * Examples: + * ``` + * api.createLimitQRCode(100, callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * + * Result: + * ``` + * { + * "ticket":"gQG28DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL0FuWC1DNmZuVEhvMVp4NDNMRnNRAAIEesLvUQMECAcAAA==" + * } + * ``` + * @param {Number} sceneId 场景ID。ID不能大于1000 * @param {Function} callback 回调函数 */ API.prototype.createLimitQRCode = function (sceneId, callback) { @@ -126,16 +268,41 @@ API.prototype.createLimitQRCode = function (sceneId, callback) { }; /** - * 生成显示二维码的链接 + * 生成显示二维码的链接。微信扫描后,可立即进入场景 + * Examples: + * ``` + * api.showQRCodeURL(titck); + * // => https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET + * ``` * @param {String} ticket 二维码Ticket + * @return {String} 显示二维码的URL地址,通过img标签可以显示出来 */ API.prototype.showQRCodeURL = function (ticket) { return this.prefix + 'showqrcode?ticket=' + ticket; }; -// ## 分组API http://mp.weixin.qq.com/wiki/index.php?title=%E5%88%86%E7%BB%84%E7%AE%A1%E7%90%86%E6%8E%A5%E5%8F%A3 /** * 获取分组列表 + * 详情请见: + * Examples: + * ``` + * api.getGroups(callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * + * Result: + * ``` + * { + * "groups": [ + * {"id": 0, "name": "未分组", "count": 72596}, + * {"id": 1, "name": "黑名单", "count": 36} + * ] + * } + * ``` + * @param {Function} callback 回调函数 */ API.prototype.getGroups = function (callback) { // https://api.weixin.qq.com/cgi-bin/groups/get?access_token=ACCESS_TOKEN @@ -145,7 +312,22 @@ API.prototype.getGroups = function (callback) { /** * 创建分组 + * 详情请见: + * Examples: + * ``` + * api.createGroup('groupname', callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * + * Result: + * ``` + * {"group": {"id": 107, "name": "test"}} + * ``` * @param {String} name 分组名字 + * @param {Function} callback 回调函数 */ API.prototype.createGroup = function (name, callback) { // https://api.weixin.qq.com/cgi-bin/groups/create?access_token=ACCESS_TOKEN @@ -160,8 +342,23 @@ API.prototype.createGroup = function (name, callback) { /** * 更新分组名字 + * 详情请见: + * Examples: + * ``` + * api.updateGroup(107, 'new groupname', callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * + * Result: + * ``` + * {"errcode": 0, "errmsg": "ok"} + * ``` * @param {Number} id 分组ID * @param {String} name 新的分组名字 + * @param {Function} callback 回调函数 */ API.prototype.updateGroup = function (id, name, callback) { // http请求方式: POST(请使用https协议) @@ -177,8 +374,23 @@ API.prototype.updateGroup = function (id, name, callback) { /** * 移动用户进分组 + * 详情请见: + * Examples: + * ``` + * api.moveUserToGroup(openid, groupId, callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * + * Result: + * ``` + * {"errcode": 0, "errmsg": "ok"} + * ``` * @param {String} openid 用户的openid * @param {Number} groupId 分组ID + * @param {Function} callback 回调函数 */ API.prototype.moveUserToGroup = function (openid, groupId, callback) { // http请求方式: POST(请使用https协议) @@ -194,8 +406,34 @@ API.prototype.moveUserToGroup = function (openid, groupId, callback) { }; /** - * 获取用户信息 + * 获取用户基本信息 + * 详情请见: + * Examples: + * ``` + * api.getUser(openid, callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * + * Result: + * ``` + * { + * "subscribe": 1, + * "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", + * "nickname": "Band", + * "sex": 1, + * "language": "zh_CN", + * "city": "广州", + * "province": "广东", + * "country": "中国", + * "headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0", + * "subscribe_time": 1382694957 + * } + * ``` * @param {String} openid 用户的openid + * @param {Function} callback 回调函数 */ API.prototype.getUser = function (openid, callback) { // https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID @@ -205,8 +443,31 @@ API.prototype.getUser = function (openid, callback) { /** * 获取关注者列表 - * 详细细节 http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E5%85%B3%E6%B3%A8%E8%80%85%E5%88%97%E8%A1%A8 + * 详细细节 http://mp.weixin.qq.com/wiki/index.php?title=获取关注者列表 + * Examples: + * ``` + * api.getFollowers(callback); + * // or + * api.getFollowers(nextOpenid, callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * + * Result: + * ``` + * { + * "total":2, + * "count":2, + * "data":{ + * "openid":["","OPENID1","OPENID2"] + * }, + * "next_openid":"NEXT_OPENID" + * } + * ``` * @param {String} nextOpenid 调用一次之后,传递回来的nextOpenid。第一次获取时可不填 + * @param {Function} callback 回调函数 */ API.prototype.getFollowers = function (nextOpenid, callback) { // https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID @@ -218,21 +479,29 @@ API.prototype.getFollowers = function (nextOpenid, callback) { urllib.request(url, {dataType: 'json'}, wrapper(callback)); }; -// 客服消息 -// http请求方式: POST https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN /** - * 发送文字消息 + * 客服消息,发送文字消息 + * 详细细节 http://mp.weixin.qq.com/wiki/index.php?title=发送客服消息 + * Examples: + * ``` + * api.sendText('openid', 'Hello world', callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * * @param {String} openid 用户的openid * @param {String} text 发送的消息内容 + * @param {Function} callback 回调函数 */ API.prototype.sendText = function (openid, text, callback) { // { - // "touser":"OPENID", - // "msgtype":"text", - // "text": - // { - // "content":"Hello World" - // } + // "touser":"OPENID", + // "msgtype":"text", + // "text": { + // "content":"Hello World" + // } // } var url = this.prefix + 'message/custom/send?access_token=' + this.token; var data = { @@ -247,17 +516,27 @@ API.prototype.sendText = function (openid, text, callback) { /** * 发送图片消息 + * 详细细节 http://mp.weixin.qq.com/wiki/index.php?title=发送客服消息 + * Examples: + * ``` + * api.sendImage('openid', 'media_id', callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * * @param {String} openid 用户的openid - * @param {String} mediaId 媒体文件的ID + * @param {String} mediaId 媒体文件的ID,参见uploadMedia方法 + * @param {Function} callback 回调函数 */ API.prototype.sendImage = function (openid, mediaId, callback) { // { - // "touser":"OPENID", - // "msgtype":"image", - // "image": - // { - // "media_id":"MEDIA_ID" - // } + // "touser":"OPENID", + // "msgtype":"image", + // "image": { + // "media_id":"MEDIA_ID" + // } // } var url = this.prefix + 'message/custom/send?access_token=' + this.token; var data = { @@ -272,17 +551,27 @@ API.prototype.sendImage = function (openid, mediaId, callback) { /** * 发送语音消息 + * 详细细节 http://mp.weixin.qq.com/wiki/index.php?title=发送客服消息 + * Examples: + * ``` + * api.sendVoice('openid', 'media_id', callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * * @param {String} openid 用户的openid * @param {String} mediaId 媒体文件的ID + * @param {Function} callback 回调函数 */ API.prototype.sendVoice = function (openid, mediaId, callback) { // { - // "touser":"OPENID", - // "msgtype":"image", - // "image": - // { - // "media_id":"MEDIA_ID" - // } + // "touser":"OPENID", + // "msgtype":"image", + // "image": { + // "media_id":"MEDIA_ID" + // } // } var url = this.prefix + 'message/custom/send?access_token=' + this.token; var data = { @@ -297,19 +586,29 @@ API.prototype.sendVoice = function (openid, mediaId, callback) { /** * 发送视频消息 + * 详细细节 http://mp.weixin.qq.com/wiki/index.php?title=发送客服消息 + * Examples: + * ``` + * api.sendVideo('openid', 'media_id', 'thumb_media_id', callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * * @param {String} openid 用户的openid * @param {String} mediaId 媒体文件的ID * @param {String} thumbMediaId 缩略图文件的ID + * @param {Function} callback 回调函数 */ API.prototype.sendVideo = function (openid, mediaId, thumbMediaId, callback) { // { - // "touser":"OPENID", - // "msgtype":"video", - // "image": - // { - // "media_id":"MEDIA_ID" - // "thumb_media_id":"THUMB_MEDIA_ID" - // } + // "touser":"OPENID", + // "msgtype":"video", + // "image": { + // "media_id":"MEDIA_ID" + // "thumb_media_id":"THUMB_MEDIA_ID" + // } // } var url = this.prefix + 'message/custom/send?access_token=' + this.token; var data = { @@ -325,21 +624,38 @@ API.prototype.sendVideo = function (openid, mediaId, thumbMediaId, callback) { /** * 发送音乐消息 + * 详细细节 http://mp.weixin.qq.com/wiki/index.php?title=发送客服消息 + * Examples: + * ``` + * var music = { + * title: '音乐标题', // 可选 + * description: '描述内容', // 可选 + * musicurl: 'http://url.cn/xxx', 音乐文件地址 + * hqmusicurl: "HQ_MUSIC_URL", + * thumb_media_id: "THUMB_MEDIA_ID" + * }; + * api.sendMusic('openid', music, callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * * @param {String} openid 用户的openid * @param {Object} music 音乐文件 + * @param {Function} callback 回调函数 */ API.prototype.sendMusic = function (openid, music, callback) { // { - // "touser":"OPENID", - // "msgtype":"music", - // "music": - // { - // "title":"MUSIC_TITLE", // 可选 - // "description":"MUSIC_DESCRIPTION", // 可选 - // "musicurl":"MUSIC_URL", - // "hqmusicurl":"HQ_MUSIC_URL", - // "thumb_media_id":"THUMB_MEDIA_ID" - // } + // "touser":"OPENID", + // "msgtype":"music", + // "music": { + // "title":"MUSIC_TITLE", // 可选 + // "description":"MUSIC_DESCRIPTION", // 可选 + // "musicurl":"MUSIC_URL", + // "hqmusicurl":"HQ_MUSIC_URL", + // "thumb_media_id":"THUMB_MEDIA_ID" + // } // } var url = this.prefix + 'message/custom/send?access_token=' + this.token; var data = { @@ -352,29 +668,52 @@ API.prototype.sendMusic = function (openid, music, callback) { /** * 发送图文消息 + * 详细细节 http://mp.weixin.qq.com/wiki/index.php?title=发送客服消息 + * Examples: + * ``` + * var articles = [ + * { + * "title":"Happy Day", + * "description":"Is Really A Happy Day", + * "url":"URL", + * "picurl":"PIC_URL" + * }, + * { + * "title":"Happy Day", + * "description":"Is Really A Happy Day", + * "url":"URL", + * "picurl":"PIC_URL" + * }]; + * api.sendNews('openid', articles, callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * * @param {String} openid 用户的openid * @param {Array} articles 图文列表 + * @param {Function} callback 回调函数 */ API.prototype.sendNews = function (openid, articles, callback) { // { - // "touser":"OPENID", - // "msgtype":"news", - // "news":{ - // "articles": [ - // { - // "title":"Happy Day", - // "description":"Is Really A Happy Day", - // "url":"URL", - // "picurl":"PIC_URL" - // }, - // { - // "title":"Happy Day", - // "description":"Is Really A Happy Day", - // "url":"URL", - // "picurl":"PIC_URL" - // } - // ] - // } + // "touser":"OPENID", + // "msgtype":"news", + // "news":{ + // "articles": [ + // { + // "title":"Happy Day", + // "description":"Is Really A Happy Day", + // "url":"URL", + // "picurl":"PIC_URL" + // }, + // { + // "title":"Happy Day", + // "description":"Is Really A Happy Day", + // "url":"URL", + // "picurl":"PIC_URL" + // }] + // } // } var url = this.prefix + 'message/custom/send?access_token=' + this.token; var data = { @@ -387,36 +726,78 @@ API.prototype.sendNews = function (openid, articles, callback) { urllib.request(url, postJSON(data), wrapper(callback)); }; -// 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb) +/** + * 上传多媒体文件,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb) + * 详情请见: + * Examples: + * ``` + * api.uploadMedia('filepath', type, callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的对象 + * + * Result: + * ``` + * {"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789} + * ``` + * Shortcut: + * + * - API.prototype.uploadImage(filepath, callback); + * - API.prototype.uploadVoice(filepath, callback); + * - API.prototype.uploadVideo(filepath, callback); + * - API.prototype.uploadThumb(filepath, callback); + * + * @param {String} filepath 文件路径 + * @param {String} type 媒体类型,可用值有image、voice、video、thumb + * @param {Function} callback 回调函数 + */ +API.prototype.uploadMedia = function (filepath, type, callback) { + var that = this; + fs.stat(filepath, function (err, stat) { + if (err) { + return callback(err); + } + var form = formstream(); + form.file('media', filepath, path.basename(filepath), stat.size); + form.headers({ + 'Content-Type': 'application/json' + }); + var url = that.fileServerPrefix + 'media/upload?access_token=' + that.token + '&type=' + type; + var opts = { + dataType: 'json', + type: 'POST', + timeout: 60000, // 60秒超时 + headers: form.headers(), + stream: form + }; + urllib.request(url, opts, wrapper(callback)); + }); +}; + ['image', 'voice', 'video', 'thumb'].forEach(function (type) { var method = 'upload' + type[0].toUpperCase() + type.substring(1); API.prototype[method] = function (filepath, callback) { - var that = this; - fs.stat(filepath, function (err, stat) { - if (err) { - return callback(err); - } - var form = formstream(); - form.file('media', filepath, path.basename(filepath), stat.size); - form.headers({ - 'Content-Type': 'application/json' - }); - var url = that.fileServerPrefix + 'media/upload?access_token=' + that.token + '&type=' + type; - var opts = { - dataType: 'json', - type: 'POST', - timeout: 60000, // 60秒超时 - headers: form.headers(), - stream: form - }; - urllib.request(url, opts, wrapper(callback)); - }); + this.uploadMedia(filepath, type, callback); }; }); /** * 根据媒体ID获取媒体内容 + * 详情请见: + * Examples: + * ``` + * api.getMedia('media_id', callback); + * ``` + * Callback: + * + * - `err`, 调用失败时得到的异常 + * - `result`, 调用正常时得到的文件Buffer对象 + * - `res`, HTTP响应对象 + * * @param {String} mediaId 媒体文件的ID + * @param {Function} callback 回调函数 */ API.prototype.getMedia = function (mediaId, callback) { var url = this.fileServerPrefix + 'media/get?access_token=' + this.token + '&media_id=' + mediaId; diff --git a/lib/session.js b/lib/session.js index 2c2a303f..973d6ba6 100644 --- a/lib/session.js +++ b/lib/session.js @@ -1,3 +1,9 @@ +/** + * Session构造函数,用于与Connect的Session中间件集成的会话脚本 + * @param {String} id Session ID + * @param {Object} req Connect中的请求对象 + * @param {Object} data 可选的其余数据,将被合并进Session对象中 + */ var Session = function (id, req, data) { Object.defineProperty(this, 'id', { value: id }); Object.defineProperty(this, 'req', { value: req }); @@ -8,14 +14,30 @@ var Session = function (id, req, data) { } }; -Session.prototype.save = function(fn){ - this.req.sessionStore.set(this.id, this, fn || function(){}); +/** + * 保存Session对象到实际的存储中 + * + * Callback: + * + * - `err`, 错误对象,保存发生错误时传入 + * @param {Function} callback 保存Session的回调函数 + */ +Session.prototype.save = function (callback) { + this.req.sessionStore.set(this.id, this, callback || function(){}); return this; }; -Session.prototype.destroy = function(fn){ +/** + * 销毁Session对象 + * + * Callback: + * + * - `err`, 错误对象,删除发生错误时传入 + * @param {Function} callback 从存储中删除Session数据后的回调函数 + */ +Session.prototype.destroy = function (callback) { delete this.req.wxsession; - this.req.sessionStore.destroy(this.id, fn); + this.req.sessionStore.destroy(this.id, callback); return this; }; diff --git a/lib/wechat.js b/lib/wechat.js index 0739b1fd..291d7367 100644 --- a/lib/wechat.js +++ b/lib/wechat.js @@ -244,16 +244,24 @@ Handler.prototype.middlewarify = function () { }; /** + * 根据口令 + * * Examples: * ``` * wechat(token, function (req, res, next) {}); + * * wechat(token, wechat.text(function (message, req, res, next) { + * // TODO * }).location(function (message, req, res, next) { + * // TODO * })); + * * wechat(token) - * .text(function (message, req, res, next) {}) - * .location(function (message, req, res, next) {}) - * .middleware(); + * .text(function (message, req, res, next) { + * // TODO + * }).location(function (message, req, res, next) { + * // TODO + * }).middleware(); * ``` * @param {String} token 在微信平台填写的口令 * @param {Function} handle 生成的回调函数,参见示例