login-by-qq.js 3.8 KB

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