import { requestJson } from '@/services/api.uts' import { acceptSession } from './auth.uts' export function wechatLoginSupported(): boolean { // App微信SDK及各平台应用凭据接入后再开放原生入口。 // #ifdef MP-WEIXIN return true // #endif // #ifndef MP-WEIXIN return false // #endif } export function requestWechatAuthorization(): Promise { // #ifdef MP-WEIXIN return new Promise((resolve, reject) => { uni.login({ provider: 'weixin', success: (result) => { const code = result.code if (code.length == 0) { reject(new Error('未能取得微信登录凭证,请重新操作')); return } resolve(code) }, fail: (error) => { const cancelled = error.errMsg.toLowerCase().includes('cancel') || error.errCode == 1310509 reject(new Error(cancelled ? '已取消微信登录' : '微信授权失败,请重新操作')) } }) }) // #endif // #ifndef MP-WEIXIN return new Promise((resolve, reject) => { reject(new Error('当前平台暂未开放微信登录,请使用手机号登录')) }) // #endif } function validTicket(value: string): boolean { return /^[A-Za-z0-9_-]{32,128}$/.test(value) } function validPhone(value: string): boolean { return /^1[3-9][0-9]{9}$/.test(value) } function validateResult(result: UTSJSONObject): UTSJSONObject { const status = result.getString('status') ?? '' if (status == 'bind_required') { const expires = result.getNumber('expiresIn') ?? 0 if (!validTicket(result.getString('bindingTicket') ?? '') || expires < 1 || expires > 600 || Math.floor(expires) != expires || result['token'] != null) throw new Error('微信绑定响应格式不完整,请重新微信登录') } else if (status == 'authenticated') { const expiry = Date.parse(result.getString('expiresAt') ?? '') if (result.getBoolean('consentsConfirmed') != true || !validPhone(result.getString('phone') ?? '') || !/^[1-9][0-9]{0,18}$/.test(result.getString('userId') ?? '') || (result.getString('token') ?? '').length == 0 || isNaN(expiry) || expiry <= Date.now()) throw new Error('微信登录响应缺少有效账户或协议确认') } else throw new Error('微信登录响应状态无效') return result } export async function requestWechatLogin(code: string, agreements: UTSJSONObject[]): Promise { if (code.length == 0 || code.length > 256 || agreements.length != 2) throw new Error('请重新确认协议并微信登录') let terms = false; let privacy = false; let previousRequestId = '' for (const item of agreements) { const agreementCode = item['agreementCode'] as string | null ?? '' const requestId = item['requestId'] as string | null ?? '' if ((agreementCode == 'terms' && !terms)) terms = true else if ((agreementCode == 'privacy' && !privacy)) privacy = true else throw new Error('用户协议和隐私政策必须分别确认') if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(item['agreementVersion'] as string | null ?? '') || !/^[a-f0-9]{64}$/.test(item['contentHash'] as string | null ?? '') || !/^[A-Za-z0-9_-]{16,64}$/.test(requestId) || requestId == previousRequestId) throw new Error('协议确认信息不完整,请重新阅读并确认') previousRequestId = requestId } return validateResult(await requestJson('/auth/wechat-login', 'POST', { platform: 'mp-weixin', code, agreements })) } export async function requestWechatBindingCode(bindingTicket: string, phone: string): Promise { if (!validTicket(bindingTicket) || !validPhone(phone)) throw new Error('请重新微信登录并输入正确手机号') await requestJson('/auth/wechat/sms-code', 'POST', { bindingTicket, phone }) return true } export async function bindWechatPhone(bindingTicket: string, phone: string, code: string): Promise { if (!validTicket(bindingTicket) || !validPhone(phone) || !/^[0-9]{6}$/.test(code)) throw new Error('请核对手机号和6位验证码') const result = validateResult(await requestJson('/auth/wechat/bind-phone', 'POST', { bindingTicket, phone, code })) if (result.getString('status') != 'authenticated') throw new Error('手机号绑定尚未完成,请重新微信登录') return result } export function acceptWechatSession(result: UTSJSONObject): string { validateResult(result) if (result.getString('status') != 'authenticated') throw new Error('请先完成手机号绑定') return acceptSession(result, result.getString('phone') ?? '') }