GetLoginUrl.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. const API = require("../../../lib/API")
  2. const axios = require('axios')
  3. const config = require('../../../config.json')
  4. const { BaseStdResponse } = require("../../../BaseStdResponse");
  5. const https = require("https")
  6. const { normalizeSocialType } = require('../../../lib/UniLoginClient')
  7. class GetLoginUrl extends API {
  8. constructor() {
  9. super();
  10. this.setPath('/UniLogin/GetLoginUrl')
  11. this.setMethod('GET')
  12. }
  13. async onRequest(req, res) {
  14. let { type, device, action, from, mode } = req.query
  15. type = normalizeSocialType(type)
  16. if (!type)
  17. return res.json({
  18. ...BaseStdResponse.ERR,
  19. msg: '不支持的第三方登录类型'
  20. })
  21. const uniConfig = config.unilogin
  22. /** 解析 URL 与 hash 内查询串,判断 query 是否已包含某键(避免对整段 URL 做子串误判) */
  23. const redirectUrlHasQueryKey = (redirectUrl, key) => {
  24. if (!redirectUrl || !key) return false
  25. try {
  26. const u = new URL(redirectUrl)
  27. if (u.searchParams.has(key)) return true
  28. const h = u.hash || ''
  29. const qPos = h.indexOf('?')
  30. if (qPos === -1) return false
  31. return new URLSearchParams(h.slice(qPos + 1)).has(key)
  32. } catch {
  33. return false
  34. }
  35. }
  36. const appendQuery = (redirectUrl) => {
  37. const params = []
  38. if (mode && !redirectUrlHasQueryKey(redirectUrl, 'mode'))
  39. params.push(`mode=${encodeURIComponent(mode)}`)
  40. if (action && !redirectUrlHasQueryKey(redirectUrl, 'action'))
  41. params.push(`action=${encodeURIComponent(action)}`)
  42. if (from && !redirectUrlHasQueryKey(redirectUrl, 'from'))
  43. params.push(`from=${encodeURIComponent(from)}`)
  44. if (params.length === 0)
  45. return redirectUrl
  46. return `${redirectUrl}${redirectUrl.includes('?') ? '&' : '?'}${params.join('&')}`
  47. }
  48. let redirectUri = appendQuery(uniConfig.return_url)
  49. let url = `${uniConfig.url}/connect.php?act=login&appid=${uniConfig.appid}&appkey=${uniConfig.appkey}&type=${type}&redirect_uri=${encodeURIComponent(redirectUri)}`
  50. if (device && device === 'uniapp')
  51. url = `${uniConfig.url}/connect.php?act=login&appid=${uniConfig.appid}&appkey=${uniConfig.appkey}&type=${type}&redirect_uri=${encodeURIComponent(appendQuery(uniConfig.uni_return_url))}`
  52. try {
  53. const r = await axios.get(url, {
  54. proxy: false,
  55. httpsAgent: new https.Agent({
  56. rejectUnauthorized: false
  57. })
  58. })
  59. if (!r || r.data?.code !== 0 || !r.data?.url) {
  60. this.logger.error(`获取聚合登录链接失败!${r.data?.msg || 'api接口错误'}`)
  61. return res.json({
  62. ...BaseStdResponse.ERR,
  63. msg: '请尝试其他登录方式或稍后再试'
  64. })
  65. }
  66. res.json({
  67. ...BaseStdResponse.OK,
  68. data: r.data.url
  69. })
  70. } catch (error) {
  71. this.logger.error(`获取聚合登录链接失败!${error.message || 'api接口错误'}`)
  72. return res.json({
  73. ...BaseStdResponse.ERR,
  74. msg: '请尝试其他登录方式或稍后再试!'
  75. })
  76. }
  77. }
  78. }
  79. module.exports.GetLoginUrl = GetLoginUrl;