/** * @Author HonorLee (dev@honorlee.me) * @Version 1.0 (2018-05-05) * @License MIT */ 'use strict' const sha1 = require('sha1'); const tmpTokenFile = Core.Path.Temp + '/wechat_AccessToken.txt'; const tmpTicketFile = Core.Path.Temp + '/wechat_JsApiTicket.txt'; const WechatDomain = `https://${Config.Wechat.apiDomain}`; const errCode = require('./errMsg.js'); const WechatApiURL = { getAccessToken:`${WechatDomain}/cgi-bin/token?grant_type=client_credential&appid=${Config.Wechat.appId}&secret=${Config.Wechat.appSecret}`, getJsApiTicket:`${WechatDomain}/cgi-bin/ticket/getticket?type=jsapi&access_token=` } let Wechat = { checkSignature:function(signature,timestamp,nonce){ let arr = [Config.Wechat.token, timestamp, nonce]; arr.sort(); let content = arr.join(''); return sha1(content) === signature; }, getAccessToken:function(callback){ let _this = this; getTokenFromCache(function(data){ if(data){ callback.call(_this,null,data); }else{ Core.Request({url:WechatApiURL.getAccessToken,encoding:'UTF-8',json:true},function(err,response,body){ if(err || !body){ Logger.error('Wechat getAccessToken error!'); Logger.error(err); callback.call(_this,new Error('Wechat getAccessToken error!'),null); return; } if(body.errcode){ callback(_this,errcode,errcode[body.errcode]); } let token = body.access_token; let expires = body.expires_in; setTokenToCahe(token,expires); callback.call(_this,null,token); }) } }); }, getJsApiTicket:function(callback){ let _this = this; Wechat.getAccessToken(function(err,token){ if(!err){ getTicketFromCache(function(data){ if(data){ callback.call(_this,null,data); }else{ let url = WechatApiURL.getJsApiTicket + token; Core.Request({url:url,encoding:'UTF-8',json:true},function(err,response,body){ if(err || !body){ Logger.error('Wechat getJsApiTicket error!'); Logger.error(err); callback.call(_this,new Error('Wechat getJsApiTicket error!'),null); return; } if(body.errcode){ callback(_this,errcode,errcode[body.errcode]); } let ticket = body.ticket; let expires = body.expires_in; setTicketToCahe(ticket,expires); callback.call(_this,null,ticket); }) } }); }else{ Logger.error('Wechat getJsApiTicket error!'); Logger.error(err); } }); }, getSignature:function(url,callback){ if(!url) return callback.call(this,new Error('URL is empty!'),null); let _this = this; let noncestr = String.random(16); let timestamp = Math.floor(Moment().valueOf()/1000); Wechat.getJsApiTicket(function(err,ticket){ if(err){ Logger.error('Wechat getSignature error!'); Logger.error(err); callback.call(_this,err,null); return; } let combineStr = `jsapi_ticket=${ticket}&noncestr=${noncestr}×tamp=${timestamp}&url=${url}`; let signature = sha1(combineStr); callback.call(_this,null,{nonceStr:noncestr,timestamp:timestamp,signature:signature}); }); } } module.exports = Wechat; function getTokenFromCache(callback){ if(Config.Wechat.StoreType=='Memcache' && Config.Database.Memcache.on){ Memcache.get('wechat_AccessToken',function(err,data){ if(!err && data){ callback(data); }else{ callback(); } }); return; } try{ FILE.statSync(tmpTokenFile); }catch(e){ callback(null); return; } let obj = JSON.parse(FILE.readFileSync(tmpTokenFile,'UTF-8')); let now = Math.floor(Moment().valueOf()/1000)+60; if(now < obj.expires){ callback(obj.token); }else{ callback(null); } } function setTokenToCahe(token,expires){ expires = expires - 60; if(Config.Wechat.StoreType=='Memcache' && Config.Database.Memcache.on){ Memcache.set('wechat_AccessToken',token,expires,function(err){ if(err) console.log(err); }) return; } let expiresTime = Math.floor(Moment().valueOf()/1000) + expires; FILE.writeFileSync(tmpTokenFile,JSON.stringify({token:token,expires:expiresTime}),'UTF-8'); } function getTicketFromCache(callback){ if(Config.Wechat.StoreType=='Memcache' && Config.Database.Memcache.on){ Memcache.get('wechat_JsApiTicket',function(err,data){ if(!err && data){ callback(data); }else{ callback(); } }); return; } try{ FILE.statSync(tmpTicketFile); }catch(e){ callback(null); return; } let obj = JSON.parse(FILE.readFileSync(tmpTicketFile,'UTF-8')); let now = Math.floor(Moment().valueOf()/1000)+60; if(now < obj.expires){ callback(obj.ticket); }else{ callback(null); } } function setTicketToCahe(ticket,expires){ expires = expires - 5; if(Config.Wechat.StoreType=='Memcache' && Config.Database.Memcache.on){ Memcache.set('wechat_JsApiTicket',ticket,expires,function(err){ if(err) console.log(err); }) return; } let expiresTime = Math.floor(Moment().valueOf()/1000) + expires; FILE.writeFileSync(tmpTicketFile,JSON.stringify({ticket:ticket,expires:expiresTime}),'UTF-8'); }