weixin.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. 'use strict';
  2. const assert = require('assert');
  3. const uuid = require('uuid');
  4. const _ = require('lodash');
  5. const { BusinessError, ErrorCode } = require('naf-core').Error;
  6. const crypto = require('crypto');
  7. const Service = require('egg').Service;
  8. class WeixinAuthService extends Service {
  9. constructor(ctx) {
  10. super(ctx, {});
  11. }
  12. // 取得微信AccessToken
  13. async accesstoken({ appid }) {
  14. assert(appid, '缺少appid参数项');
  15. const key = `visit:auth:accesstoken:${appid}`;
  16. const val = await this.app.redis.get(key);
  17. const data = {};
  18. if (val) {
  19. const { access_token } = JSON.parse(val);
  20. data.access_token = access_token;
  21. } else {
  22. const { wxapi } = this.app.config;
  23. const appidlist = wxapi;
  24. const wxapp = _.find(appidlist, { appid });
  25. const feturl = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${wxapp.appSecret}`;
  26. const result = await this.ctx.curl(feturl, {
  27. method: 'get',
  28. headers: {
  29. 'content-type': 'application/json',
  30. },
  31. dataType: 'json',
  32. });
  33. if (result) {
  34. console.log(result);
  35. const val = JSON.stringify(result.data);
  36. await this.app.redis.set(key, val, 'EX', 7200);
  37. data.access_token = result.data.access_token;
  38. }
  39. }
  40. return data;
  41. }
  42. // 取得微信jsapiticket
  43. async jsapiticket({ appid }) {
  44. assert(appid, '缺少appid参数项');
  45. const result = await this.accesstoken({ appid });
  46. const accesstoken = result.access_token;
  47. console.log(accesstoken);
  48. assert(accesstoken, '缺少access_token参数项');
  49. const key = `visit:auth:jsapiticket:${appid}`;
  50. const val = await this.app.redis.get(key);
  51. const data = {};
  52. if (val) {
  53. const { ticket } = JSON.parse(val);
  54. data.ticket = ticket;
  55. } else {
  56. const feturl = `https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${accesstoken}&type=jsapi`;
  57. const result = await this.ctx.curl(feturl, {
  58. method: 'get',
  59. headers: {
  60. 'content-type': 'application/json',
  61. },
  62. dataType: 'json',
  63. });
  64. if (result) {
  65. console.log(result);
  66. if (result.data.errcode === 0) {
  67. const val = JSON.stringify(result.data);
  68. await this.app.redis.set(key, val, 'EX', 7200);
  69. data.ticket = result.data.ticket;
  70. }
  71. }
  72. }
  73. return data;
  74. }
  75. // 签名算法
  76. async getsign({ appid, url }) {
  77. assert(appid, '缺少appid参数项');
  78. assert(url, '缺少url参数项');
  79. const result = await this.jsapiticket({ appid });
  80. // const { wxapi } = this.app.config;
  81. // const appidlist = wxapi;
  82. // const wxapp = _.find(appidlist, { appid });
  83. console.log(url);
  84. const noncestr = await this.createNonceStr();
  85. const timestamp = await this.createTimestamp();
  86. const ret = {
  87. jsapi_ticket: result.ticket,
  88. noncestr,
  89. timestamp,
  90. url,
  91. };
  92. console.log(ret);
  93. const string = await this.raw(ret);
  94. ret.sign = await this.sha1(string);
  95. ret.appid = appid;
  96. console.log('ret', ret);
  97. return ret;
  98. }
  99. // sha1加密
  100. async sha1(str) {
  101. const shasum = crypto.createHash('sha1');
  102. shasum.update(str);
  103. str = shasum.digest('hex');
  104. return str;
  105. }
  106. // 生成签名的时间戳
  107. async createTimestamp() {
  108. return parseInt(new Date().getTime() / 1000) + '';
  109. }
  110. // 生成签名的随机串
  111. async createNonceStr() {
  112. return Math.random().toString(36).substr(2, 15);
  113. }
  114. // 对参数对象进行字典排序
  115. // @param {对象} args 签名所需参数对象
  116. // @return {字符串} 排序后生成字符串
  117. async raw(args) {
  118. let keys = Object.keys(args);
  119. keys = keys.sort();
  120. const newArgs = {};
  121. keys.forEach(function(key) {
  122. newArgs[key.toLowerCase()] = args[key];
  123. });
  124. let string = '';
  125. for (const k in newArgs) {
  126. string += '&' + k + '=' + newArgs[k];
  127. }
  128. string = string.substr(1);
  129. return string;
  130. }
  131. }
  132. module.exports = WeixinAuthService;