Authored by 邱骏

重写微信JSAPI接口

... ... @@ -22,7 +22,7 @@ const sha1 = (str) => {
// 微信 JS 接口签名校验工具 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign
let getAccessToken = function(req, next, appId, secret, prefix) { // 获取access_token
let getAccessToken = function(appId, secret, prefix) { // 获取access_token
return request({
url: prefix + 'token',
qs: {
... ... @@ -33,11 +33,11 @@ let getAccessToken = function(req, next, appId, secret, prefix) { // 获取acces
json: true
}).then(res => {
return res;
}).catch(next);
});
};
let getTicket = function(req, accessToken, next, appId, secret, prefix) { // 获取ticket
let getTicket = function(accessToken, appId, secret, prefix) { // 获取ticket
return request({
url: prefix + 'ticket/getticket',
qs: {
... ... @@ -50,7 +50,7 @@ let getTicket = function(req, accessToken, next, appId, secret, prefix) { // 获
});
};
let calcSigature = function(ticket_res, res) { // 计算signature
let calcSigature = function(ticket_res) { // 计算signature
let appID = ticket_res.appID;
let ticket = ticket_res.access_ticket;
let nonceStr = Math.random().toString(36).substr(2, 15);
... ... @@ -59,58 +59,32 @@ let calcSigature = function(ticket_res, res) { // 计算signature
let str = `jsapi_ticket=${ticket}&noncestr=${nonceStr}&timestamp=${timestamp}&url=${url}`;
let signature = sha1(str);
let result = {
return {
appId: appID,
nonceStr,
timestamp,
url,
signature
};
return res.jsonp(result);
};
let getResult = function(wechat_res, req, res, next) { // 向微信接口获取access_token及ticket并计算signature
let getResult = function(wechat_res) { // 向微信接口获取access_token及ticket并计算signature
let appID = wechat_res.appID;
let appSecret = wechat_res.appSecret;
let prefix = wechat_res.prefix;
let mpPrefix = wechat_res.mpPrefix;
let url = wechat_res.url;
let type = wechat_res.type;
return getAccessToken(req, next, appID, appSecret, prefix)
return getAccessToken(appID, appSecret, prefix)
.then(result => { // 先获取accessToken
let access_token = result.access_token;
return getTicket(req, access_token, next, appID, appSecret, mpPrefix)
return getTicket(access_token, appID, appSecret, mpPrefix)
.then(ticket_res => { // 通过accessToken获取ticket
if (ticket_res && ticket_res.ticket) {
let access_ticket = ticket_res.ticket;
let expired = parseInt(ticket_res.expires_in, 10) - 100;
let create_time = moment().format('YYYY-MM-DD HH:mm:ss');
let expired_time = moment().add(expired, 'seconds').format('YYYY-MM-DD HH:mm:ss');
req.ctx(WechatModel).
saveAccessKeys(access_token, access_ticket, create_time, expired_time, type)
.then(() => {
let access_res = {
appID: appID,
access_ticket: access_ticket,
url: url
};
calcSigature(access_res, res);
});
} else {
res.jsonp({
appID: appID,
nonceStr: '',
timestamp: '',
url: url,
signature: 'get failed'
});
}
}).catch(next);
return Object.assign({
access_token: access_token,
appID: appID
}, ticket_res);
});
});
};
... ... @@ -127,49 +101,52 @@ const wechatShare = {
req.ctx(WechatModel).getAccessKeys()
.then(keys_res => { // 先查询数据库中是否有access_token并且未过期
if (keys_res.length > 0) {
let access_token = keys_res[0].access_token;
let access_ticket = keys_res[0].access_ticket;
let expired = new Date(keys_res[0].access_expired).getTime();
let now = Date.now();
if (now > expired) { // 过期则去 取新的token与ticket 并且更新数据库
return Promise.reject({
type: 'update'
});
} else {
return Promise.resolve({ // 没过期则直接返回数据库中保存的access_ticket
access_token,
access_ticket
});
}
} else {
return Promise.reject({ // 数据库中没有token数据则新增
type: 'save'
if (keys_res.code === 200) { // code=200说明数据库中查找到数据并且未过期
delete keys_res.code;
return Object.assign({
appID,
url
}, keys_res);
} else if (keys_res.code === 201) {
// code=201说明数据库中没有数据,或者数据已过期,根据返回的type判断是添加还是更新
delete keys_res.code;
keys_res = Object.assign({
appID,
appSecret,
prefix,
mpPrefix,
url
}, keys_res);
return getResult(keys_res).then(ticket_res => {
let appId = ticket_res.appID;
let access_token = ticket_res.access_token || '';
let access_ticket = ticket_res.ticket || '';
let expired = parseInt(ticket_res.expires_in, 10) - 100 || 0;
let create_time = moment().format('YYYY-MM-DD HH:mm:ss') || '';
let expired_time = moment().add(expired, 'seconds').format('YYYY-MM-DD HH:mm:ss') || '';
// 获取到ticket信息之后把相关字段保存到数据库中
return req.ctx(WechatModel).
saveAccessKeys(access_token, access_ticket, create_time, expired_time, keys_res.type)
.then(() => {
return {
appID: appId,
access_ticket: access_ticket,
url: url
};
});
});
}
})
.then(access_res => {
access_res = Object.assign({
appID,
url
}, access_res);
calcSigature(access_res, res); // 组合参数, 计算signature
},
fail_res => {
fail_res = Object.assign({
appID: appID,
appSecret: appSecret,
prefix: prefix,
mpPrefix: mpPrefix,
url: url
}, fail_res);
getResult(fail_res, req, res, next); // 向微信接口获取access_token及ticket并计算signature
});
.then(result => {
let calc_res = calcSigature(result);
res.jsonp(calc_res);
}).catch(next);
}
};
... ...
... ... @@ -13,12 +13,51 @@ class WechatModel extends global.yoho.BaseModel {
super(ctx);
}
/**
* 获取微信token与ticket信息,存在并且未过期则返回code=200,
* 存在且过期返回201,‘update’
* 不存在返回201,‘save’
*/
getAccessKeys() {
let strSql = `select * from ${TABLE_WECHAT} limit 0, 1;`;
return mysqlCli.query(strSql);
return mysqlCli.query(strSql).then(res => {
if (res.length > 0) {
let access_token = res[0].access_token;
let access_ticket = res[0].access_ticket;
let expired = new Date(res[0].access_expired).getTime();
let now = Date.now();
if (now > expired) { // 过期则去 取新的token与ticket 并且更新数据库
return Promise.resolve({
code: 201,
type: 'update'
});
} else {
return Promise.resolve({ // 没过期则直接返回数据库中保存的access_ticket
code: 200,
access_token,
access_ticket
});
}
} else {
return Promise.resolve({ // 数据库中没有token数据则新增
code: 201,
type: 'save'
});
}
});
}
/**
* 保存或者更新微信的token与ticket
* @param access_token
* @param access_ticket
* @param access_create_time
* @param access_expired
* @param type 'save'为添加数据 'update'为更新数据
* @returns {*}
*/
saveAccessKeys(access_token, access_ticket, access_create_time, access_expired, type) {
let strSql = '';
let params = {
... ...