Files
wxapp-guantong/uniapp/utils/user.uts
T
2026-09-22 22:51:19 +08:00

198 lines
5.7 KiB
Plaintext

import { apiBase, post } from './api.uts'
import { User } from './types.uts'
const USER_KEY = 'sf_user'
export function demoUser(): User {
const openid = generateFakeOpenID()
return {
id: openid,
openid,
phone: null
} as User
}
export function currentUser(): User | null {
const raw = uni.getStorageSync(USER_KEY)
if (raw == null || raw == '') return null
return raw as User
}
export function phoneFromUser(user: any | null): string {
if (user == null) return ''
const phone = (user as any).phone
if (phone == null) return ''
if (typeof phone == 'string') return phone as string
const obj = phone as any
if (obj.Valid == true || obj.valid == true) {
if (obj.String != null) return obj.String as string
if (obj.string != null) return obj.string as string
}
return ''
}
export function openidFromUser(user: any | null): string {
if (user == null) return fallbackOpenID()
const obj = user as any
if (obj.openid != null) {
const openid = obj.openid as string
if (openid.length > 0) return openid
}
if (obj.Openid != null) {
const openid = obj.Openid as string
if (openid.length > 0) return openid
}
return fallbackOpenID()
}
export function setUser(user: User): void {
uni.setStorageSync(USER_KEY, user)
}
export function bindPhoneFromEvent(event: UniEvent): Promise<any> {
const detail = (event as any).detail as any
const errMsg = detail != null && detail.errMsg != null ? detail.errMsg as string : ''
console.log('[phone-auth] getPhoneNumber event', phoneAuthDetailLog(detail))
if (errMsg.indexOf('ok') < 0) {
console.log('[phone-auth] getPhoneNumber rejected', { errMsg })
return Promise.reject(new Error('手机号授权未完成'))
}
const user = currentUser()
const phoneCode = detail != null && detail.code != null ? detail.code as string : ''
if (phoneCode.length == 0) {
console.log('[phone-auth] getPhoneNumber missing code', phoneAuthDetailLog(detail))
return Promise.reject(new Error('没有拿到手机号授权 code'))
}
const openid = openidFromUser(user)
console.log('[phone-auth] backend bind start', {
openid: maskIdentifier(openid),
hasStoredPhone: phoneFromUser(user).length > 0,
phoneCodeLength: phoneCode.length,
envVersion: miniProgramEnvVersion(),
apiBase: apiBase()
})
return post('/api/auth/wechat/phone', {
openid,
phoneCode
}).then((res) => {
const nextUser = (res as any).user as User
const phone = phoneFromUser(nextUser)
if (phone.length == 0) {
console.log('[phone-auth] backend bind empty phone', {
openid: maskIdentifier(openidFromUser(nextUser))
})
return Promise.reject(new Error('后端未返回已绑定手机号'))
}
setUser(nextUser)
console.log('[phone-auth] backend bind success', {
openid: maskIdentifier(openidFromUser(nextUser)),
phone: maskPhoneForLog(phone)
})
return {
user: nextUser,
phone
}
}).catch((err) => {
const message = err != null && (err as any).message != null ? (err as any).message as string : '手机号绑定失败'
console.log('[phone-auth] backend bind failed', {
openid: maskIdentifier(openid),
message
})
return Promise.reject(err)
})
}
function phoneAuthDetailLog(detail: any | null): any {
if (detail == null) {
return {
errMsg: '',
hasCode: false,
codeLength: 0,
hasEncryptedData: false,
hasIv: false,
hasCloudID: false
}
}
const code = detail.code != null ? detail.code as string : ''
const encryptedData = detail.encryptedData != null ? detail.encryptedData as string : ''
const iv = detail.iv != null ? detail.iv as string : ''
const cloudID = detail.cloudID != null ? detail.cloudID as string : ''
return {
errMsg: detail.errMsg != null ? detail.errMsg as string : '',
hasCode: code.length > 0,
codeLength: code.length,
hasEncryptedData: encryptedData.length > 0,
hasIv: iv.length > 0,
hasCloudID: cloudID.length > 0
}
}
function maskIdentifier(value: string): string {
if (value.length <= 8) return value
return value.slice(0, 4) + '...' + value.slice(value.length - 4)
}
function maskPhoneForLog(phone: string): string {
if (phone.length < 7) return phone
return phone.slice(0, 3) + '****' + phone.slice(phone.length - 4)
}
function fallbackOpenID(): string {
const stored = currentUser()
if (stored != null) {
const obj = stored as any
if (obj.openid != null) {
const openid = obj.openid as string
if (openid.length > 0) return openid
}
if (obj.Openid != null) {
const openid = obj.Openid as string
if (openid.length > 0) return openid
}
}
const user = demoUser()
setUser(user)
return user.openid
}
function generateFakeOpenID(): string {
return 'fake_user_' + compactDateTime(new Date()) + '_' + randomFourDigits()
}
function compactDateTime(date: Date): string {
return date.getFullYear().toString()
+ padNumber(date.getMonth() + 1, 2)
+ padNumber(date.getDate(), 2)
+ padNumber(date.getHours(), 2)
+ padNumber(date.getMinutes(), 2)
+ padNumber(date.getSeconds(), 2)
}
function randomFourDigits(): string {
return padNumber(Math.floor(Math.random() * 10000), 4)
}
function padNumber(value: number, size: number): string {
let text = value.toString()
while (text.length < size) {
text = '0' + text
}
return text
}
function miniProgramEnvVersion(): string {
// #ifdef MP-WEIXIN
try {
const accountInfo = uni.getAccountInfoSync()
const info = accountInfo as any
if (info.miniProgram == null) return ''
const miniProgram = info.miniProgram as any
if (miniProgram.envVersion == null) return ''
return miniProgram.envVersion as string
} catch (e) {
return ''
}
// #endif
return ''
}