login-by-weixin.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. const {
  2. initWeixin
  3. } = require('../../lib/third-party/index')
  4. const {
  5. ERROR
  6. } = require('../../common/error')
  7. const {
  8. preUnifiedLogin,
  9. postUnifiedLogin
  10. } = require('../../lib/utils/unified-login')
  11. const {
  12. generateWeixinCache,
  13. getWeixinPlatform,
  14. saveWeixinUserKey,
  15. saveSecureNetworkCache
  16. } = require('../../lib/utils/weixin')
  17. const {
  18. LOG_TYPE
  19. } = require('../../common/constants')
  20. const url = require('url')
  21. /**
  22. * 微信登录
  23. * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#login-by-weixin
  24. * @param {Object} params
  25. * @param {String} params.code 微信登录返回的code
  26. * @param {String} params.inviteCode 邀请码
  27. * @returns
  28. */
  29. module.exports = async function (params = {}) {
  30. const schema = {
  31. code: 'string',
  32. inviteCode: {
  33. type: 'string',
  34. required: false
  35. }
  36. }
  37. this.middleware.validate(params, schema)
  38. const {
  39. code,
  40. inviteCode,
  41. // 内部参数,暂不暴露
  42. secureNetworkCache = false
  43. } = params
  44. const {
  45. appId
  46. } = this.getUniversalClientInfo()
  47. const weixinApi = initWeixin.call(this)
  48. const weixinPlatform = getWeixinPlatform.call(this)
  49. let apiName
  50. switch (weixinPlatform) {
  51. case 'mp':
  52. apiName = 'code2Session'
  53. break
  54. case 'app':
  55. case 'h5':
  56. case 'web':
  57. apiName = 'getOauthAccessToken'
  58. break
  59. default:
  60. throw new Error('Unsupported weixin platform')
  61. }
  62. let getWeixinAccountResult
  63. try {
  64. getWeixinAccountResult = await weixinApi[apiName](code)
  65. } catch (error) {
  66. console.error(error)
  67. await this.middleware.uniIdLog({
  68. success: false,
  69. type: LOG_TYPE.LOGIN
  70. })
  71. throw {
  72. errCode: ERROR.GET_THIRD_PARTY_ACCOUNT_FAILED
  73. }
  74. }
  75. const {
  76. openid,
  77. unionid,
  78. // 保存下面四个字段
  79. sessionKey, // 微信小程序用户sessionKey
  80. accessToken, // App端微信用户accessToken
  81. refreshToken, // App端微信用户refreshToken
  82. expired: accessTokenExpired // App端微信用户accessToken过期时间
  83. } = getWeixinAccountResult
  84. if (secureNetworkCache) {
  85. if (weixinPlatform !== 'mp') {
  86. throw new Error('Unsupported weixin platform, expect mp-weixin')
  87. }
  88. await saveSecureNetworkCache.call(this, {
  89. code,
  90. openid,
  91. unionid,
  92. sessionKey
  93. })
  94. }
  95. const {
  96. type,
  97. user
  98. } = await preUnifiedLogin.call(this, {
  99. user: {
  100. wx_openid: {
  101. [weixinPlatform]: openid
  102. },
  103. wx_unionid: unionid
  104. }
  105. })
  106. const extraData = {
  107. wx_openid: {
  108. [`${weixinPlatform}_${appId}`]: openid
  109. },
  110. wx_unionid: unionid
  111. }
  112. if (type === 'register' && weixinPlatform !== 'mp') {
  113. const {
  114. nickname,
  115. avatar
  116. } = await weixinApi.getUserInfo({
  117. accessToken,
  118. openid
  119. })
  120. if (avatar) {
  121. // eslint-disable-next-line n/no-deprecated-api
  122. const avatarPath = url.parse(avatar).pathname
  123. const extName = avatarPath.indexOf('.') > -1 ? url.parse(avatar).pathname.split('.').pop() : 'jpg'
  124. const cloudPath = `user/avatar/${openid.slice(-8) + Date.now()}-avatar.${extName}`
  125. const getAvatarRes = await uniCloud.httpclient.request(avatar)
  126. if (getAvatarRes.status >= 400) {
  127. throw {
  128. errCode: ERROR.GET_THIRD_PARTY_USER_INFO_FAILED
  129. }
  130. }
  131. const {
  132. fileID
  133. } = await uniCloud.uploadFile({
  134. cloudPath,
  135. fileContent: getAvatarRes.data
  136. })
  137. extraData.avatar_file = {
  138. name: cloudPath,
  139. extname: extName,
  140. url: fileID
  141. }
  142. }
  143. extraData.nickname = nickname
  144. }
  145. await saveWeixinUserKey.call(this, {
  146. openid,
  147. sessionKey,
  148. accessToken,
  149. refreshToken,
  150. accessTokenExpired
  151. })
  152. return postUnifiedLogin.call(this, {
  153. user,
  154. extraData: {
  155. ...extraData,
  156. ...generateWeixinCache.call(this, {
  157. openid,
  158. sessionKey, // 微信小程序用户sessionKey
  159. accessToken, // App端微信用户accessToken
  160. refreshToken, // App端微信用户refreshToken
  161. accessTokenExpired // App端微信用户accessToken过期时间
  162. })
  163. },
  164. isThirdParty: true,
  165. type,
  166. inviteCode
  167. })
  168. }