koa2-wechat2
Version:
koa2 middleware for wechat
951 lines (815 loc) • 25.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = Wechat;
var _requestPromise = require('request-promise');
var _requestPromise2 = _interopRequireDefault(_requestPromise);
var _fs = require('fs');
var _fs2 = _interopRequireDefault(_fs);
var _util = require('./util');
var util = _interopRequireWildcard(_util);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var prefix = 'https://api.weixin.qq.com/cgi-bin/';
var mpPrefix = 'https://mp.weixin.qq.com/cgi-bin/';
var api = {
accessToken: prefix + 'token?grant_type=client_credential',
temporary: {
upload: prefix + 'media/upload?',
fetch: prefix + 'media/get?'
},
permanent: {
fetch: prefix + 'material/get_material?',
del: prefix + 'material/del_material?',
upload: prefix + 'material/add_material?',
uploadnews: prefix + 'material/add_news?',
update_news: prefix + 'material/update_news?',
uploadimg: prefix + 'media/uploadimg?',
count: prefix + 'material/get_materialcount?',
batch: prefix + 'material/batchget_material?'
},
tag: {
create: prefix + 'tags/create?',
fetch: prefix + 'tags/get?',
update: prefix + 'tags/update?',
delete: prefix + 'tags/delete?',
user: prefix + 'user/tag/get?',
batch: prefix + 'tags/members/batchtagging?',
batchUn: prefix + 'tags/members/batchuntagging?',
getIdList: prefix + 'tags/getidlist?'
},
user: {
remark: prefix + 'user/info/updateremark?',
fetch: prefix + 'user/info?',
batchFetch: prefix + 'user/info/batchget?',
list: prefix + 'user/get?'
},
mass: {
sendAll: prefix + 'message/mass/sendall?',
openIds: prefix + 'message/mass/send?',
delete: prefix + 'message/mass/delete?',
preview: prefix + 'message/mass/preview?',
check: prefix + 'message/mass/get?'
},
menu: {
create: prefix + 'menu/create?',
get: prefix + 'menu/get?',
delete: prefix + 'menu/delete?',
current: prefix + 'get_current_selfmenu_info?'
},
qrcode: {
create: prefix + 'qrcode/create?',
show: mpPrefix + 'showqrcode?'
},
shortUrl: {
create: prefix + 'shorturl?'
},
ticket: {
get: prefix + 'ticket/getticket?'
}
/**
* Wechat logic, api function return promise
* @param {[object]} opts [config]
*/
};function Wechat(opts) {
this.appID = opts.appID;
this.appSecret = opts.appSecret;
this.getAccessToken = opts.getAccessToken;
this.saveAccessToken = opts.saveAccessToken;
this.getTicket = opts.getTicket;
this.saveTicket = opts.saveTicket;
this.fetchAccessToken();
}
Wechat.prototype.fetchAccessToken = function () {
var that = this;
if (this.access_token && this.expires_in) {
if (this.isValidAccessToken(this)) {
return Promise.resolve(this);
}
}
return this.getAccessToken().then(function (data) {
try {
data = JSON.parse(data);
} catch (e) {
return that.updateAccessToken();
}
if (that.isValidAccessToken(data)) {
return Promise.resolve(data);
} else {
return that.updateAccessToken();
}
}).then(function (data) {
that.access_token = data.access_token;
that.expires_in = data.expires_in;
that.saveAccessToken(data);
return Promise.resolve(data);
});
};
Wechat.prototype.isValidAccessToken = function (data) {
if (!data || !data.access_token || !data.expires_in) {
return false;
}
// let access_token = data.access_token
var expires_in = data.expires_in;
var now = new Date().getTime();
if (now < expires_in) {
return true;
} else {
return false;
}
};
Wechat.prototype.updateAccessToken = function () {
var appID = this.appID;
var appSecret = this.appSecret;
var url = api.accessToken + '&appid=' + appID + '&secret=' + appSecret;
return new Promise(function (resolve, reject) {
(0, _requestPromise2.default)({ url: url, json: true }).then(function (res) {
var data = res;
var now = new Date().getTime();
var expires_in = now + (data.expires_in - 20) * 1000;
data.expires_in = expires_in;
resolve(data);
}).catch(function (err) {
reject(err);
});
});
};
//js_api_ticket
Wechat.prototype.fetchTicket = function (access_token) {
var that = this;
return this.getTicket().then(function (data) {
try {
data = JSON.parse(data);
} catch (e) {
return that.updateTicket(access_token);
}
if (that.isValidTicket(data)) {
return Promise.resolve(data);
} else {
return that.updateTicket(access_token);
}
}).then(function (data) {
that.saveTicket(data);
return Promise.resolve(data);
});
};
Wechat.prototype.isValidTicket = function (data) {
if (!data || !data.ticket || !data.expires_in) {
return false;
}
var ticket = data.ticket;
var expires_in = data.expires_in;
var now = new Date().getTime();
if (ticket && now < expires_in) {
return true;
} else {
return false;
}
};
Wechat.prototype.updateTicket = function (access_token) {
var url = api.ticket.get + ('access_token=' + access_token + '&type=jsapi');
return new Promise(function (resolve, reject) {
(0, _requestPromise2.default)({ url: url, json: true }).then(function (res) {
var data = res;
var now = new Date().getTime();
var expires_in = now + (data.expires_in - 20) * 1000;
data.expires_in = expires_in;
resolve(data);
}).catch(function (err) {
reject(err);
});
});
};
Wechat.prototype.reply = function () {
var content = this.body;
var message = this.weixin;
var xml = util.tpl(content, message);
this.status = 200;
this.type = 'application/xml';
this.body = xml;
};
Wechat.prototype.uploadMaterial = function (type, material, permanent) {
var that = this;
var form = {};
var uploadUrl = api.temporary.upload;
if (permanent) {
uploadUrl = api.permanent.upload;
Object.assign(form, permanent);
}
if (type === 'pic') {
uploadUrl = api.permanent.uploadimg;
}
if (type === 'news') {
uploadUrl = api.permanent.uploadnews;
form = material;
} else {
form.media = _fs2.default.createReadStream(material);
}
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = uploadUrl + ('access_token=' + data.access_token);
if (!permanent) {
url += '&type=' + type;
} else {
form.access_token = data.access_token;
}
var options = {
url: url,
method: 'POST',
json: true
};
if (type === 'news') {
options.body = form;
} else {
options.formData = form;
}
(0, _requestPromise2.default)(options).then(function (response) {
if (response.errcode) {
// throw new Error('upload material fails')
}
resolve(response);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.fetchMaterial = function (mediaId, type, permanent) {
var that = this;
var fetchUrl = api.temporary.fetch;
if (permanent) {
fetchUrl = api.permanent.fetch;
}
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = fetchUrl + ('access_token=' + data.access_token);
var form = {};
var options = {
url: url,
method: 'POST',
json: true
};
if (permanent) {
form.media_id = mediaId;
options.body = form;
} else {
options.method = 'GET';
if (type === 'video') {
url = url.replace('https://', 'http://');
}
url += '&media_id=' + mediaId;
}
if (type === 'news' || type === 'video') {
(0, _requestPromise2.default)(options).then(function (_data) {
if (_data.errcode) {
throw new Error('fetch Material fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
} else {
resolve(url);
}
});
});
};
Wechat.prototype.deleteMaterial = function (mediaId) {
var that = this;
var form = {
media_id: mediaId
};
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.permanent.del + ('access_token=' + data.access_token);
(0, _requestPromise2.default)({ url: url, method: 'POST', body: form, json: true }).then(function (_data) {
if (_data.errcode !== 0) {
throw new Error('delete Material fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.updateMaterial = function (mediaId, news) {
var that = this;
var form = {
media_id: mediaId
};
Object.assign(form, news);
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.permanent.update_news + ('access_token=' + data.access_token);
(0, _requestPromise2.default)({ url: url, method: 'POST', body: form, json: true }).then(function (_data) {
if (_data.errcode !== 0) {
throw new Error('update Material fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.countMaterial = function () {
var that = this;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.permanent.count + ('access_token=' + data.access_token);
(0, _requestPromise2.default)({ url: url, method: 'GET', json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('count Material fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.batchMaterial = function (options) {
var that = this;
options.type = options.type || 'image';
options.offset = options.offset || 0;
options.count = options.count || 1;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.permanent.batch + ('access_token=' + data.access_token);
(0, _requestPromise2.default)({ url: url, method: 'POST', body: options, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('batch Material fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.createTag = function (name) {
var that = this;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.tag.create + ('access_token=' + data.access_token);
var form = {
tag: {
name: name
}
};
(0, _requestPromise2.default)({ url: url, method: 'POST', body: form, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('create tag fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.fetchTags = function () {
var that = this;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.tag.fetch + ('access_token=' + data.access_token);
(0, _requestPromise2.default)({ url: url, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('fetch Tags fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.updateTag = function (id, name) {
var that = this;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.tag.create + ('access_token=' + data.access_token);
var form = {
tag: {
id: id,
name: name
}
};
(0, _requestPromise2.default)({ url: url, method: 'POST', body: form, json: true }).then(function (_data) {
if (_data.errcode !== 0) {
throw new Error('update Tag fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.deleteTag = function (id) {
var that = this;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.tag.delete + ('access_token=' + data.access_token);
var form = {
tag: {
id: id
}
};
(0, _requestPromise2.default)({ url: url, method: 'POST', body: form, json: true }).then(function (_data) {
if (_data.errcode !== 0) {
throw new Error('delete tag fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.getTagUsers = function (tagId, nextOpenId) {
var that = this;
var form = {
tagid: tagId,
next_openid: nextOpenId || ''
};
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.tag.create + ('access_token=' + data.access_token);
(0, _requestPromise2.default)({ url: url, method: 'POST', body: form, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('get tag users fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.batchTags = function (openIds, tagId) {
var that = this;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.tag.batch + ('access_token=' + data.access_token);
var form = {
openid_list: openIds,
tagid: tagId
};
(0, _requestPromise2.default)({ url: url, method: 'POST', body: form, json: true }).then(function (_data) {
if (_data.errcode !== 0) {
throw new Error('batch tags fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.batchUnTags = function (openIds, tagId) {
var that = this;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.tag.batchUn + ('access_token=' + data.access_token);
var form = {
openid_list: openIds,
tagid: tagId
};
(0, _requestPromise2.default)({ url: url, method: 'POST', body: form, json: true }).then(function (_data) {
if (_data.errcode !== 0) {
throw new Error('batch untagging fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.getUserTags = function (openId) {
var that = this;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.tag.getIdList + ('access_token=' + data.access_token);
var form = {
openid: openId
};
(0, _requestPromise2.default)({ url: url, method: 'POST', body: form, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('get user tags fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.updateRemark = function (openId, remark) {
var that = this;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.user.remark + ('access_token=' + data.access_token);
var form = {
openid: openId,
remark: remark
};
(0, _requestPromise2.default)({ url: url, method: 'POST', body: form, json: true }).then(function (_data) {
if (_data.errcode !== 0) {
throw new Error('update remark fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.fetchUserInfo = function (openId, lang) {
var that = this;
lang = lang || 'zh_CN';
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.user.fetch + ('access_token=' + data.access_token + '&openid=' + openId + '&lang=' + lang);
(0, _requestPromise2.default)({ url: url, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('get user info fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.fetchUsersInfo = function (openIds, lang) {
var that = this;
lang = lang || 'zh_CN';
var form = void 0;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = void 0;
var options = {
url: url,
json: true
};
if (Array.isArray(openIds)) {
options.url = api.user.batchFetch + ('access_token=' + data.access_token);
form = {
user_list: openIds
};
options.body = form;
options.method = 'POST';
} else {
options.url = api.user.fetch + ('access_token=' + data.access_token + '&openid=' + openIds + '&lang=' + lang);
}
(0, _requestPromise2.default)(options).then(function (_data) {
if (_data.errcode) {
throw new Error('get user info fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.fetchUserList = function (nextOpenId) {
var that = this;
nextOpenId = nextOpenId || '';
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.user.list + ('access_token=' + data.access_token + '&next_openid=' + nextOpenId);
(0, _requestPromise2.default)({ url: url, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('get user info fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.sendByTag = function (type, message, tagId) {
var that = this;
var msg = {
filter: {},
msgtype: type
};
if (!tagId) {
msg.filter.is_to_all = true;
} else {
msg.filter = {
is_to_all: false,
tag_id: tagId
};
}
msg[type] = message;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.mass.sendAll + ('access_token=' + data.access_token);
(0, _requestPromise2.default)({ url: url, method: 'POST', body: msg, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('sendAll by Tag fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.sendByOpenIds = function (type, message, openIds) {
var that = this;
var msg = {
touser: openIds,
msgtype: type
};
msg[type] = message;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.mass.openIds + ('access_token=' + data.access_token);
(0, _requestPromise2.default)({ url: url, method: 'POST', body: msg, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('send by openIds fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.deleteMass = function (msgId, articleIdx) {
var that = this;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.mass.delete + ('access_token=' + data.access_token);
var form = {
msg_id: msgId,
article_idx: articleIdx || ''
};
(0, _requestPromise2.default)({ url: url, method: 'POST', body: form, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('delete mass fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.previewMass = function (type, message, openId) {
var that = this;
var msg = {
touser: openId,
msgtype: type
};
msg[type] = message;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.mass.preview + ('access_token=' + data.access_token);
(0, _requestPromise2.default)({ url: url, method: 'POST', body: msg, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('preview mass by openid fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
//TODO fails
Wechat.prototype.checkMass = function (msgId) {
var that = this;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.mass.preview + ('access_token=' + data.access_token);
var form = {
msg_id: msgId
};
(0, _requestPromise2.default)({ url: url, method: 'POST', body: form, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('check mass status fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.createMenu = function (menus) {
var that = this;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.menu.create + ('access_token=' + data.access_token);
var form = {
button: menus
};
(0, _requestPromise2.default)({ url: url, method: 'POST', body: form, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('create menu fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.getMenu = function () {
var that = this;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.menu.get + ('access_token=' + data.access_token);
(0, _requestPromise2.default)({ url: url, json: true }).then(function (_data) {
if (_data.errcode !== 0) {
throw new Error('get menu fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.deleteMenu = function () {
var that = this;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.menu.delete + ('access_token=' + data.access_token);
(0, _requestPromise2.default)({ url: url, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('delete menu fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.getCurrentMenu = function () {
var that = this;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.menu.current + ('access_token=' + data.access_token);
(0, _requestPromise2.default)({ url: url, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('get current menu fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.createQrcode = function (qr) {
var that = this;
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.qrcode.create + ('access_token=' + data.access_token);
(0, _requestPromise2.default)({ url: url, method: 'POST', body: qr, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('create qrcode fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};
Wechat.prototype.showQrcode = function (ticket) {
var encodedTicket = encodeURI(ticket);
return api.qrcode.show + ('ticket=' + encodedTicket);
};
Wechat.prototype.createShortUrl = function (action, longUrl) {
var that = this;
action = action || 'long2short';
return new Promise(function (resolve, reject) {
that.fetchAccessToken().then(function (data) {
var url = api.shortUrl.create + ('access_token=' + data.access_token);
var form = {
action: action,
long_url: longUrl
};
(0, _requestPromise2.default)({ url: url, method: 'POST', body: form, json: true }).then(function (_data) {
if (_data.errcode) {
throw new Error('create shortUrl fails');
}
resolve(_data);
}).catch(function (err) {
reject(err);
});
});
});
};