const API = require("../../../lib/API") const axios = require('axios') const config = require('../../../config.json') const { BaseStdResponse } = require("../../../BaseStdResponse"); const https = require("https") const { normalizeSocialType } = require('../../../lib/UniLoginClient') class GetLoginUrl extends API { constructor() { super(); this.setPath('/UniLogin/GetLoginUrl') this.setMethod('GET') } async onRequest(req, res) { let { type, device, action, from, mode } = req.query type = normalizeSocialType(type) if (!type) return res.json({ ...BaseStdResponse.ERR, msg: '不支持的第三方登录类型' }) const uniConfig = config.unilogin /** 解析 URL 与 hash 内查询串,判断 query 是否已包含某键(避免对整段 URL 做子串误判) */ const redirectUrlHasQueryKey = (redirectUrl, key) => { if (!redirectUrl || !key) return false try { const u = new URL(redirectUrl) if (u.searchParams.has(key)) return true const h = u.hash || '' const qPos = h.indexOf('?') if (qPos === -1) return false return new URLSearchParams(h.slice(qPos + 1)).has(key) } catch { return false } } const appendQuery = (redirectUrl) => { const params = [] if (mode && !redirectUrlHasQueryKey(redirectUrl, 'mode')) params.push(`mode=${encodeURIComponent(mode)}`) if (action && !redirectUrlHasQueryKey(redirectUrl, 'action')) params.push(`action=${encodeURIComponent(action)}`) if (from && !redirectUrlHasQueryKey(redirectUrl, 'from')) params.push(`from=${encodeURIComponent(from)}`) if (params.length === 0) return redirectUrl return `${redirectUrl}${redirectUrl.includes('?') ? '&' : '?'}${params.join('&')}` } let redirectUri = appendQuery(uniConfig.return_url) let url = `${uniConfig.url}/connect.php?act=login&appid=${uniConfig.appid}&appkey=${uniConfig.appkey}&type=${type}&redirect_uri=${encodeURIComponent(redirectUri)}` if (device && device === 'uniapp') url = `${uniConfig.url}/connect.php?act=login&appid=${uniConfig.appid}&appkey=${uniConfig.appkey}&type=${type}&redirect_uri=${encodeURIComponent(appendQuery(uniConfig.uni_return_url))}` try { const r = await axios.get(url, { proxy: false, httpsAgent: new https.Agent({ rejectUnauthorized: false }) }) if (!r || r.data?.code !== 0 || !r.data?.url) { this.logger.error(`获取聚合登录链接失败!${r.data?.msg || 'api接口错误'}`) return res.json({ ...BaseStdResponse.ERR, msg: '请尝试其他登录方式或稍后再试' }) } res.json({ ...BaseStdResponse.OK, data: r.data.url }) } catch (error) { this.logger.error(`获取聚合登录链接失败!${error.message || 'api接口错误'}`) return res.json({ ...BaseStdResponse.ERR, msg: '请尝试其他登录方式或稍后再试!' }) } } } module.exports.GetLoginUrl = GetLoginUrl;