wechat.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /**
  2. * @Author HonorLee (dev@honorlee.me)
  3. * @Version 1.0 (2018-05-05)
  4. * @License MIT
  5. */
  6. 'use strict'
  7. const sha1 = require('sha1');
  8. const tmpTokenFile = Core.Path.Temp + '/wechat_AccessToken.txt';
  9. const tmpTicketFile = Core.Path.Temp + '/wechat_JsApiTicket.txt';
  10. const WechatDomain = `https://${Config.Wechat.apiDomain}`;
  11. const errCode = require('./errMsg.js');
  12. const WechatApiURL = {
  13. getAccessToken:`${WechatDomain}/cgi-bin/token?grant_type=client_credential&appid=${Config.Wechat.appId}&secret=${Config.Wechat.appSecret}`,
  14. getJsApiTicket:`${WechatDomain}/cgi-bin/ticket/getticket?type=jsapi&access_token=`
  15. }
  16. let Wechat = {
  17. checkSignature:function(signature,timestamp,nonce){
  18. let arr = [Config.Wechat.token, timestamp, nonce];
  19. arr.sort();
  20. let content = arr.join('');
  21. return sha1(content) === signature;
  22. },
  23. getAccessToken:function(callback){
  24. let _this = this;
  25. getTokenFromCache(function(data){
  26. if(data){
  27. callback.call(_this,null,data);
  28. }else{
  29. Core.Request({url:WechatApiURL.getAccessToken,encoding:'UTF-8',json:true},function(err,response,body){
  30. if(err || !body){
  31. Logger.error('Wechat getAccessToken error!');
  32. Logger.error(err);
  33. callback.call(_this,new Error('Wechat getAccessToken error!'),null);
  34. return;
  35. }
  36. if(body.errcode){
  37. callback(_this,errcode,errcode[body.errcode]);
  38. }
  39. let token = body.access_token;
  40. let expires = body.expires_in;
  41. setTokenToCahe(token,expires);
  42. callback.call(_this,null,token);
  43. })
  44. }
  45. });
  46. },
  47. getJsApiTicket:function(callback){
  48. let _this = this;
  49. Wechat.getAccessToken(function(err,token){
  50. if(!err){
  51. getTicketFromCache(function(data){
  52. if(data){
  53. callback.call(_this,null,data);
  54. }else{
  55. let url = WechatApiURL.getJsApiTicket + token;
  56. Core.Request({url:url,encoding:'UTF-8',json:true},function(err,response,body){
  57. if(err || !body){
  58. Logger.error('Wechat getJsApiTicket error!');
  59. Logger.error(err);
  60. callback.call(_this,new Error('Wechat getJsApiTicket error!'),null);
  61. return;
  62. }
  63. if(body.errcode){
  64. callback(_this,errcode,errcode[body.errcode]);
  65. }
  66. let ticket = body.ticket;
  67. let expires = body.expires_in;
  68. setTicketToCahe(ticket,expires);
  69. callback.call(_this,null,ticket);
  70. })
  71. }
  72. });
  73. }else{
  74. Logger.error('Wechat getJsApiTicket error!');
  75. Logger.error(err);
  76. }
  77. });
  78. },
  79. getSignature:function(url,callback){
  80. if(!url) return callback.call(this,new Error('URL is empty!'),null);
  81. let _this = this;
  82. let noncestr = String.random(16);
  83. let timestamp = Math.floor(Moment().valueOf()/1000);
  84. Wechat.getJsApiTicket(function(err,ticket){
  85. if(err){
  86. Logger.error('Wechat getSignature error!');
  87. Logger.error(err);
  88. callback.call(_this,err,null);
  89. return;
  90. }
  91. let combineStr = `jsapi_ticket=${ticket}&noncestr=${noncestr}&timestamp=${timestamp}&url=${url}`;
  92. let signature = sha1(combineStr);
  93. callback.call(_this,null,{nonceStr:noncestr,timestamp:timestamp,signature:signature});
  94. });
  95. }
  96. }
  97. module.exports = Wechat;
  98. function getTokenFromCache(callback){
  99. if(Config.Wechat.StoreType=='Memcache' && Config.Database.Memcache.on){
  100. Memcache.get('wechat_AccessToken',function(err,data){
  101. if(!err && data){
  102. callback(data);
  103. }else{
  104. callback();
  105. }
  106. });
  107. return;
  108. }
  109. try{
  110. FILE.statSync(tmpTokenFile);
  111. }catch(e){
  112. callback(null);
  113. return;
  114. }
  115. let obj = JSON.parse(FILE.readFileSync(tmpTokenFile,'UTF-8'));
  116. let now = Math.floor(Moment().valueOf()/1000)+60;
  117. if(now < obj.expires){
  118. callback(obj.token);
  119. }else{
  120. callback(null);
  121. }
  122. }
  123. function setTokenToCahe(token,expires){
  124. expires = expires - 60;
  125. if(Config.Wechat.StoreType=='Memcache' && Config.Database.Memcache.on){
  126. Memcache.set('wechat_AccessToken',token,expires,function(err){
  127. if(err) console.log(err);
  128. })
  129. return;
  130. }
  131. let expiresTime = Math.floor(Moment().valueOf()/1000) + expires;
  132. FILE.writeFileSync(tmpTokenFile,JSON.stringify({token:token,expires:expiresTime}),'UTF-8');
  133. }
  134. function getTicketFromCache(callback){
  135. if(Config.Wechat.StoreType=='Memcache' && Config.Database.Memcache.on){
  136. Memcache.get('wechat_JsApiTicket',function(err,data){
  137. if(!err && data){
  138. callback(data);
  139. }else{
  140. callback();
  141. }
  142. });
  143. return;
  144. }
  145. try{
  146. FILE.statSync(tmpTicketFile);
  147. }catch(e){
  148. callback(null);
  149. return;
  150. }
  151. let obj = JSON.parse(FILE.readFileSync(tmpTicketFile,'UTF-8'));
  152. let now = Math.floor(Moment().valueOf()/1000)+60;
  153. if(now < obj.expires){
  154. callback(obj.ticket);
  155. }else{
  156. callback(null);
  157. }
  158. }
  159. function setTicketToCahe(ticket,expires){
  160. expires = expires - 5;
  161. if(Config.Wechat.StoreType=='Memcache' && Config.Database.Memcache.on){
  162. Memcache.set('wechat_JsApiTicket',ticket,expires,function(err){
  163. if(err) console.log(err);
  164. })
  165. return;
  166. }
  167. let expiresTime = Math.floor(Moment().valueOf()/1000) + expires;
  168. FILE.writeFileSync(tmpTicketFile,JSON.stringify({ticket:ticket,expires:expiresTime}),'UTF-8');
  169. }