longz
2026-05-28 23fe797f9dded6d7ec9ecbcf760f764374dea8e0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import type { ApiError } from '@/api/core/handlers'
import type { MiniLoginResponse, MiniOfficialLoginResponse } from '@/types/auth'
import { fetchMiniMe, fetchOfficialOAuthUrl, loginByOfficialCode } from '@/api/auth'
import { normalizeLoginProfile, normalizeMeProfile } from '@/types/auth'
import { useMiniAuthStore } from '@/store/auth'
 
export const MINI_PHONE_AUTH_REQUIRED = 10008
 
export function getApiErrorCode(error: unknown) {
  return typeof error === 'object' && error != null && 'code' in error
    ? Number((error as ApiError).code)
    : NaN
}
 
function getCurrentH5UrlWithoutOAuthParams() {
  // #ifdef H5
  const url = new URL(window.location.href)
  url.searchParams.delete('code')
  url.searchParams.delete('state')
  if (url.hash.includes('?')) {
    const [hashPath, hashQuery = ''] = url.hash.split('?')
    const hashParams = new URLSearchParams(hashQuery)
    hashParams.delete('code')
    hashParams.delete('state')
    const nextHashQuery = hashParams.toString()
    url.hash = nextHashQuery ? `${hashPath}?${nextHashQuery}` : hashPath
  }
  return url.toString()
  // #endif
  // #ifndef H5
  return ''
  // #endif
}
 
export function clearOfficialOAuthQuery() {
  // #ifdef H5
  const url = new URL(window.location.href)
  let changed = url.searchParams.has('code') || url.searchParams.has('state')
  if (url.hash.includes('?')) {
    const [hashPath, hashQuery = ''] = url.hash.split('?')
    const hashParams = new URLSearchParams(hashQuery)
    if (hashParams.has('code') || hashParams.has('state')) {
      changed = true
    }
    hashParams.delete('code')
    hashParams.delete('state')
    const nextHashQuery = hashParams.toString()
    url.hash = nextHashQuery ? `${hashPath}?${nextHashQuery}` : hashPath
  }
  if (!changed) {
    return
  }
  url.searchParams.delete('code')
  url.searchParams.delete('state')
  window.history.replaceState({}, document.title, url.toString())
  // #endif
}
 
export async function startOfficialOAuthLogin() {
  // #ifdef H5
  const redirectUri = getCurrentH5UrlWithoutOAuthParams()
  const state = `${Date.now()}`
  const response = await fetchOfficialOAuthUrl({ redirectUri, state })
  window.location.href = response.url
  return
  // #endif
  // #ifndef H5
  throw new Error('当前环境暂不支持公众号授权登录')
  // #endif
}
 
export async function handleOfficialOAuthCallback(): Promise<MiniOfficialLoginResponse | null> {
  // #ifdef H5
  const url = new URL(window.location.href)
  let code = url.searchParams.get('code')
  if (!code && url.hash.includes('?')) {
    const hashQuery = url.hash.split('?')[1] || ''
    code = new URLSearchParams(hashQuery).get('code')
  }
  if (!code) {
    return null
  }
  return await loginByOfficialCode({ code })
  // #endif
  // #ifndef H5
  return null
  // #endif
}
 
export async function finishMiniLogin(loginData: MiniLoginResponse) {
  const authStore = useMiniAuthStore()
  authStore.setSession({
    token: loginData.token,
    profile: normalizeLoginProfile(loginData),
  })
 
  try {
    const profile = await fetchMiniMe(loginData.token)
    authStore.setProfile(normalizeMeProfile(profile))
  }
  catch (error) {
    console.warn('load mini profile failed after login', error)
  }
}