front/src/api/wechat/index.ts
zzh 37d534edc3 feat: H5 WeChat one-tap authorize login/register and UI polish
Replace QR login with OAuth button; auto-authorize register/bind; follow OA in settings; advisor text styling.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-30 15:56:46 +08:00

97 lines
3.4 KiB
TypeScript
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.

import type { AxiosError } from 'axios';
import { axiosInstance } from '@/api/rbac';
import { omsUrl, unwrapData } from '@/api/oms/common';
import type {
WeChatCustomerBindInput,
WeChatCustomerRegisterInput,
WeChatCustomerRegisterResult,
WeChatOAuthUserInfo,
WxFollowQrcodeResult,
WxLoginQrcodeResult,
WxLoginResult,
} from './types';
export * from './types';
function unwrapOrSelf<T>(body: unknown): T {
if (body == null || typeof body !== 'object') {
return body as T;
}
const record = body as Record<string, unknown>;
if (
'qrCodeUrl' in record ||
'jumpUrl' in record ||
'accessToken' in record ||
'openid' in record
) {
return body as T;
}
return unwrapData<T>(body);
}
/** 获取微信公众号登录二维码(loginUuid 可选,不传则由后端生成 key) */
export async function getLoginQrcode(loginUuid?: string): Promise<WxLoginQrcodeResult> {
const res = await axiosInstance.get(omsUrl('/wechat/mp/login-qrcode'), {
params: loginUuid ? { loginUuid } : undefined,
});
return unwrapOrSelf<WxLoginQrcodeResult>(res.data);
}
/** 获取注册成功后跳转的公众号链接 */
export async function getFollowQrcode(): Promise<WxFollowQrcodeResult> {
const res = await axiosInstance.get(omsUrl('/wechat/mp/follow-qrcode'));
return unwrapOrSelf<WxFollowQrcodeResult>(res.data);
}
/** 查询扫码 key 是否已关联账号(轮询用,无值时不抛错) */
export async function getWxLoginStatus(loginUuid: string): Promise<WxLoginStatusResult> {
const res = await axiosInstance.get('/rbac/auth/wx-login/status', {
params: { loginUuid },
});
return unwrapOrSelf<WxLoginStatusResult>(res.data);
}
/** 是否属于「等待扫码」类错误(轮询时应静默继续) */
export function isWxLoginPendingError(error: unknown): boolean {
const axiosErr = error as AxiosError<{ message?: string; Message?: string }>;
const message =
axiosErr?.response?.data?.message ??
axiosErr?.response?.data?.Message ??
axiosErr?.message ??
'';
const pendingHints = ['请扫码', '扫码登录', '等待扫码', '未扫码'];
return pendingHints.some((hint) => message.includes(hint));
}
/** 微信扫码登录轮询 */
export async function wxLogin(loginUuid: string): Promise<WxLoginResult> {
const res = await axiosInstance.post('/rbac/auth/wx-login', { loginUuid });
return unwrapOrSelf<WxLoginResult>(res.data);
}
/** 微信网页授权登录(H5 点按钮,无需扫码) */
export async function wxOAuthLogin(code: string): Promise<WxLoginResult> {
const res = await axiosInstance.post('/rbac/auth/wx-oauth-login', { code });
return unwrapOrSelf<WxLoginResult>(res.data);
}
/** OAuth code 换取微信用户信息 */
export async function getOAuthUserInfo(code: string): Promise<WeChatOAuthUserInfo> {
const res = await axiosInstance.post(omsUrl('/wechat/oauth/user-info'), { code });
return unwrapOrSelf<WeChatOAuthUserInfo>(res.data);
}
/** 微信授权注册客户 */
export async function registerByWechat(
input: WeChatCustomerRegisterInput,
): Promise<WeChatCustomerRegisterResult> {
const res = await axiosInstance.post(omsUrl('/wechat/customer/register'), input);
return unwrapOrSelf<WeChatCustomerRegisterResult>(res.data);
}
/** 微信授权绑定已有客户 */
export async function bindByWechat(input: WeChatCustomerBindInput): Promise<void> {
const res = await axiosInstance.post(omsUrl('/wechat/customer/bind'), input);
unwrapOrSelf(res.data);
}