import { getPublicAppOrigin } from '@/lib/public-app-url' import { normalizeInternalRedirectPath } from '@/lib/safe-redirect' const FALLBACK_DINGTALK_CLIENT_ID = 'ding1bs1gxwrcfu16x0f' export const DINGTALK_DIRECT_LOGIN_SOURCE = 'work_notice_direct' export function getDingtalkOAuthClientId() { return ( process.env.DINGTALK_CLIENT_ID || process.env.DINGTALK_APP_KEY || process.env.NEXT_PUBLIC_DINGTALK_CLIENT_ID || FALLBACK_DINGTALK_CLIENT_ID ) } export function encodeDingtalkOAuthState( redirectPath: unknown, origin = getPublicAppOrigin(), options?: { source?: string }, ) { const payload: Record = { origin, redirect: normalizeInternalRedirectPath(redirectPath), } if (options?.source) { payload.source = options.source } return JSON.stringify(payload) } export function parseDingtalkOAuthState(value: unknown) { let raw = String(value ?? '').trim() if (!raw) { return { origin: '', redirectPath: '/', source: '', nonce: '', handoffId: '', } } try { raw = decodeURIComponent(raw) } catch { // URLSearchParams 已经会解码,遇到普通 JSON 字符串时这里可以安全忽略。 } try { const data = JSON.parse(raw) return { origin: typeof data?.origin === 'string' ? data.origin : '', redirectPath: normalizeInternalRedirectPath(data?.redirect), source: typeof data?.source === 'string' ? data.source : '', nonce: typeof data?.nonce === 'string' ? data.nonce : '', handoffId: typeof data?.handoffId === 'string' ? data.handoffId : '', } } catch { return { origin: '', redirectPath: '/', source: '', nonce: '', handoffId: '', } } } export function buildDingtalkOAuthUrl({ redirectPath, callbackPath = '/api/dingtalk/callback', clientId, prompt, source, }: { redirectPath: unknown callbackPath?: string clientId?: string prompt?: string source?: string }) { const publicOrigin = getPublicAppOrigin() const redirectUrl = `${publicOrigin}${callbackPath}` const params = new URLSearchParams({ redirect_uri: redirectUrl, client_id: clientId || getDingtalkOAuthClientId(), scope: 'openid', response_type: 'code', state: encodeDingtalkOAuthState(redirectPath, publicOrigin, { source }), }) if (prompt) { params.set('prompt', prompt) } return `https://login.dingtalk.com/oauth2/auth?${params.toString()}` }