Files
xingque/utils/phone-auth.js
2026-06-27 05:41:55 +08:00

209 lines
6.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 手机号强制认证:每次调用 check / ensurePhoneAuth 均请求后端 /peizhi/yhbdsjh
*/
const API_BASE = 'https://www.abas.asia/hqhd';
const AUTH_CHECK_URL = '/peizhi/yhbdsjh';
const AUTH_SUBMIT_URL = '/yonghu/xiugai';
const AUTH_PAGE = '/pages/phone-auth/phone-auth';
const RETURN_ROLE_KEY = 'phone_auth_return_role';
const RETURN_PAGE_KEY = 'phone_auth_return_page';
function buildHeaders(extra = {}) {
const token = wx.getStorageSync('token');
const header = { 'Content-Type': 'application/json', ...extra };
if (token) header['Authorization'] = 'Bearer ' + token;
try {
const { buildClubHeaders } = require('./club-context.js');
return buildClubHeaders(header);
} catch (e) {
const clubId = wx.getStorageSync('club_id') || 'xq';
header['X-Club-Id'] = clubId;
return header;
}
}
function innerRequest(url, data = {}) {
return new Promise((resolve, reject) => {
wx.request({
url: API_BASE + url,
method: 'POST',
data,
header: buildHeaders(),
success: (res) => resolve(res),
fail: (err) => reject(err),
});
});
}
function innerUpload(url, filePath, formData = {}, fileName = 'avatar') {
return new Promise((resolve, reject) => {
const token = wx.getStorageSync('token');
if (!token) {
reject(new Error('未登录'));
return;
}
wx.getFileInfo({
filePath,
success: () => {
wx.uploadFile({
url: API_BASE + url,
filePath,
name: fileName,
formData,
header: buildHeaders({ Authorization: 'Bearer ' + token }),
success: (res) => {
if (res.statusCode === 200) {
try {
resolve(JSON.parse(res.data));
} catch (e) {
reject(new Error('解析响应数据失败'));
}
} else if (res.statusCode === 401) {
wx.removeStorageSync('token');
reject(new Error('认证失败'));
} else {
reject(new Error(`上传失败,状态码:${res.statusCode}`));
}
},
fail: () => reject(new Error('网络请求失败')),
});
},
fail: () => reject(new Error('文件不存在或无法访问')),
});
});
}
function isOnPhoneAuthPage() {
const pages = getCurrentPages();
const cur = pages[pages.length - 1];
return !!(cur && cur.route === 'pages/phone-auth/phone-auth');
}
function parseCheckResponse(res) {
if (!res || res.statusCode === 401) {
return { ok: false, needAuth: false };
}
if (res.statusCode !== 200) {
return { ok: false, needAuth: false };
}
const body = res.data;
if (!body || typeof body !== 'object') {
return { ok: false, needAuth: false };
}
const code = Number(body.code);
if (code !== 0 && code !== 200) {
return { ok: false, needAuth: false };
}
const needAuth = body.need_auth === true
|| (body.data && body.data.need_auth === true);
return { ok: true, needAuth: !!needAuth };
}
/** 根据当前主端/身份推断认证完成后回跳角色 */
function resolveReturnRole() {
const primary = wx.getStorageSync('primaryRole') || wx.getStorageSync('currentRole') || '';
if (primary === 'dashou' || primary === 'shangjia') return primary;
if (Number(wx.getStorageSync('shangjiastatus')) === 1) return 'shangjia';
if (Number(wx.getStorageSync('staffstatus')) === 1) return 'shangjia';
if (
Number(wx.getStorageSync('dashoustatus')) === 1
|| Number(wx.getStorageSync('guanshistatus')) === 1
|| Number(wx.getStorageSync('zuzhangstatus')) === 1
|| Number(wx.getStorageSync('kaoheguanstatus')) === 1
) {
return 'dashou';
}
return 'mine';
}
function defaultReturnPage(role) {
if (role === 'dashou') return '/pages/accept-order/accept-order';
if (role === 'shangjia') return '/pages/merchant-home/merchant-home';
return '/pages/mine/mine';
}
async function check() {
const token = wx.getStorageSync('token');
if (!token) return false;
try {
const res = await innerRequest(AUTH_CHECK_URL, {});
const parsed = parseCheckResponse(res);
if (!parsed.ok) return false;
return parsed.needAuth;
} catch (e) {
return false;
}
}
function redirectToPhoneAuth(returnRole, returnPage) {
const role = returnRole || resolveReturnRole();
wx.setStorageSync(RETURN_ROLE_KEY, role);
if (returnPage) {
wx.setStorageSync(RETURN_PAGE_KEY, returnPage);
} else {
wx.removeStorageSync(RETURN_PAGE_KEY);
}
if (!isOnPhoneAuthPage()) {
wx.reLaunch({ url: AUTH_PAGE });
}
}
/**
* 向后端确认是否需要手机号认证;需要则跳转认证页
* @returns {Promise<boolean>} true=无需认证或已满足false=已跳转认证页
*/
async function ensurePhoneAuth(options = {}) {
const { redirect = true, role, returnPage } = options;
const token = wx.getStorageSync('token');
if (!token) return true;
const needAuth = await check();
if (!needAuth) return true;
if (redirect) {
redirectToPhoneAuth(role || resolveReturnRole(), returnPage);
}
return false;
}
function getPhoneAuthReturnPage() {
const savedPage = wx.getStorageSync(RETURN_PAGE_KEY);
wx.removeStorageSync(RETURN_PAGE_KEY);
if (savedPage) {
wx.removeStorageSync(RETURN_ROLE_KEY);
return savedPage;
}
const role = wx.getStorageSync(RETURN_ROLE_KEY) || resolveReturnRole();
wx.removeStorageSync(RETURN_ROLE_KEY);
return defaultReturnPage(role);
}
async function submit(phoneCode, avatarPath) {
if (!phoneCode || !avatarPath) {
throw new Error('缺少参数');
}
const data = await innerUpload(AUTH_SUBMIT_URL, avatarPath, {
shoujihao_code: phoneCode,
});
if (data && data.code === 0) {
const respData = data.data || data;
if (respData.phone) wx.setStorageSync('phone', respData.phone);
if (respData.touxiang) wx.setStorageSync('touxiang', respData.touxiang);
return respData;
}
throw new Error((data && data.msg) || '认证失败');
}
module.exports = {
check,
submit,
ensurePhoneAuth,
redirectToPhoneAuth,
getPhoneAuthReturnPage,
resolveReturnRole,
};