index.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. 'use strict';
  2. /**
  3. * 微信相关业务
  4. */
  5. const wxConfigMp = {
  6. appId: 'wxe920d4492b51c1ef',
  7. secret: '1b01ea7c449392739c693ed8f460beda'
  8. }
  9. const crypto = require('crypto')
  10. /**
  11. * 微信小程序授权登录获取session_key
  12. * @param {Object} options
  13. * @param {String} options.code 小程序code
  14. *
  15. * @param {String} options.encryptedData 可选,存在encryptedData和iv时返回用户信息(包含unionid)
  16. * @param {String} options.iv 可选
  17. */
  18. const mpWxGetSessionKey = async options => {
  19. const {
  20. code,
  21. encryptedData,
  22. iv
  23. } = options;
  24. const {
  25. appId,
  26. secret
  27. } = wxConfigMp;
  28. let url = 'https://api.weixin.qq.com/sns/jscode2session';
  29. url += '?appid=' + appId;
  30. url += '&secret=' + secret;
  31. url += '&js_code=' + code + '&grant_type=authorization_code';
  32. const res = await uniCloud.httpclient.request(url, {
  33. method: 'GET',
  34. dataType: 'json'
  35. })
  36. const data = res.res.data;
  37. if (data.errcode) {
  38. return {
  39. status: 0,
  40. msg: 'appid错误',
  41. data,
  42. appId
  43. }
  44. }
  45. if (!data.session_key) {
  46. return {
  47. status: 0,
  48. msg: '获取微信授权失败',
  49. data
  50. }
  51. }
  52. if (!encryptedData || !iv) {
  53. return {
  54. status: 1,
  55. openid: data.openid,
  56. session_key: data.session_key
  57. }
  58. }
  59. const userInfo = WXBizDataCrypt({
  60. sessionKey: data.session_key,
  61. encryptedData,
  62. iv
  63. })
  64. return {
  65. status: 1,
  66. session_key: data.session_key,
  67. userInfo
  68. }
  69. }
  70. /**
  71. * 微信小程序授权登录获取session_key
  72. * @param {Object} options
  73. * @param {String} options.code 小程序code
  74. *
  75. * @param {String} options.encryptedData 可选,存在encryptedData和iv时返回用户信息(包含unionid)
  76. * @param {String} options.iv 可选
  77. */
  78. const mpWxGetPhoneNo = async options => {
  79. const {
  80. sessionKey,
  81. encryptedData,
  82. iv
  83. } = options;
  84. const userInfo = WXBizDataCrypt({
  85. sessionKey: sessionKey,
  86. encryptedData: encryptedData,
  87. iv: iv
  88. })
  89. return {
  90. userInfo
  91. }
  92. }
  93. /**
  94. * 解密encryptedData 获取unionid
  95. * @param {Object} options
  96. * @param {String} options.sessionKey
  97. * @param {String} options.encryptedData
  98. * @param {String} options.iv
  99. */
  100. const WXBizDataCrypt = options => {
  101. const appId = wxConfigMp.appId;
  102. let {
  103. sessionKey,
  104. encryptedData,
  105. iv
  106. } = options;
  107. console.log("sessionKey", sessionKey)
  108. console.log("encryptedData", encryptedData)
  109. console.log("iv", iv)
  110. sessionKey = new Buffer(sessionKey, 'base64')
  111. encryptedData = new Buffer(encryptedData, 'base64')
  112. iv = new Buffer(iv, 'base64')
  113. let decoded;
  114. try {
  115. // 解密
  116. let decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv)
  117. // 设置自动 padding 为 true,删除填充补位
  118. decipher.setAutoPadding(true)
  119. decoded = decipher.update(encryptedData, 'binary', 'utf8')
  120. decoded += decipher.final('utf8')
  121. decoded = JSON.parse(decoded)
  122. } catch (err) {
  123. throw new Error('Illegal Buffer')
  124. }
  125. if (decoded.watermark.appid !== appId) {
  126. throw new Error('Illegal Buffer')
  127. }
  128. return decoded
  129. }
  130. const getWxConfigPart = async options => {
  131. const {
  132. data
  133. } = options;
  134. const {
  135. appId,
  136. secret
  137. } = wxConfigMp;
  138. const res0 = await uniCloud.httpclient.request(
  139. "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" +
  140. appSecret, {
  141. method: 'GET',
  142. data: {},
  143. contentType: 'json', // 指定以application/json发送data内的数据
  144. dataType: 'json' // 指定返回值为json格式,自动进行parse
  145. })
  146. var access_token = res0.data.access_token;
  147. const res = await uniCloud.httpclient.request(
  148. "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + access_token + "&type=jsapi", {
  149. method: 'GET',
  150. data: {},
  151. contentType: 'json', // 指定以application/json发送data内的数据
  152. dataType: 'json' // 指定返回值为json格式,自动进行parse
  153. })
  154. var jsapiticket = res.data.ticket;
  155. var timestamp = new Date().getTime();
  156. var url = data.url;
  157. /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
  158. var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
  159. var maxLen = $chars.length;
  160. var noncestr = '';
  161. for (var i = 0; i < 32; i++) {
  162. noncestr += $chars.charAt(Math.floor(Math.random() * maxLen));
  163. }
  164. var str = "jsapi_ticket=" + jsapiticket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" +
  165. url;
  166. var signature = sha1(str);
  167. console.log("签名=========", {
  168. appId: appId,
  169. timestamp: timestamp,
  170. noncestr: noncestr,
  171. signature: signature,
  172. jsapiticket: jsapiticket
  173. });
  174. return {
  175. code: 200,
  176. data: {
  177. appId: appId,
  178. timestamp: timestamp,
  179. noncestr: noncestr,
  180. signature: signature,
  181. jsapiticket: jsapiticket
  182. }
  183. }
  184. }
  185. module.exports = {
  186. mpWxGetSessionKey,
  187. mpWxGetPhoneNo,
  188. getWxConfigPart
  189. }