Initial commit
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
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 ''
|
||||
}
|
||||
Reference in New Issue
Block a user