@@ -1,17 +1,124 @@
|
||||
import type { WechatLoginResult } from '@dukang/shared-types';
|
||||
import { isWxAuthorizeEnabled } from '@dukang/shared-types';
|
||||
import { stripOAuthParamsFromLocation } from '@dukang/weixin-sdk';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { request } from './api';
|
||||
import { saveAuth } from './api';
|
||||
import { syncMiniWechatProfile } from './mini-wechat-profile';
|
||||
import {
|
||||
authorizeWechatForPay,
|
||||
fetchClientConfig,
|
||||
fetchUserProfile,
|
||||
needsWechatAuthForPay,
|
||||
saveWechatLoginResult,
|
||||
type WechatBindResult,
|
||||
} from './pay-wechat';
|
||||
import { isWechatEnv, weixinSdk } from './weixin';
|
||||
|
||||
/** 小程序微信授权登录:Taro.login → /auth/login/wechat(资料上报由调用方 saveAuth 后执行) */
|
||||
export async function loginWithWechat(): Promise<WechatLoginResult> {
|
||||
export type WechatAuthEnsureResult =
|
||||
| { ok: true }
|
||||
| { ok: false; redirecting: true }
|
||||
| { ok: false; needBindPhone: true; wxSessionKey: string };
|
||||
|
||||
/** 小程序:Taro.login → /auth/login/wechat;H5:公众号 OAuth */
|
||||
export async function loginWithWechat(): Promise<WechatLoginResult | void> {
|
||||
if (process.env.TARO_ENV === 'h5') {
|
||||
return loginWithWechatSdk();
|
||||
}
|
||||
const res = await Taro.login();
|
||||
if (!res.code) {
|
||||
throw new Error(res.errMsg || '微信登录失败,未获取到 code');
|
||||
}
|
||||
const { request } = await import('./api');
|
||||
return request<WechatLoginResult>('/auth/login/wechat', {
|
||||
method: 'POST',
|
||||
data: { code: res.code, platform: 'mini' },
|
||||
});
|
||||
}
|
||||
|
||||
export { bindWechatForUser } from './pay-wechat';
|
||||
export async function checkNeedsWechatAuth(): Promise<boolean> {
|
||||
const [config, profile] = await Promise.all([fetchClientConfig(), fetchUserProfile()]);
|
||||
return needsWechatAuthForPay(config, profile);
|
||||
}
|
||||
|
||||
/** 真实微信支付前确保已绑定微信;OAuth 跳转时返回 redirecting */
|
||||
export async function ensureWechatAuthForPay(): Promise<WechatAuthEnsureResult> {
|
||||
if (!isWechatEnv()) return { ok: true };
|
||||
if (!(await checkNeedsWechatAuth())) return { ok: true };
|
||||
|
||||
const result = await authorizeWechatForPay();
|
||||
if (!result) return { ok: false, redirecting: true };
|
||||
|
||||
if (result.needBindPhone && result.wxSessionKey) {
|
||||
return { ok: false, needBindPhone: true, wxSessionKey: result.wxSessionKey };
|
||||
}
|
||||
|
||||
if (saveWechatLoginResult(result)) {
|
||||
return { ok: true };
|
||||
}
|
||||
return { ok: false, redirecting: true };
|
||||
}
|
||||
|
||||
/** 处理 URL 中 OAuth ?code= 回调(H5 公众号) */
|
||||
export async function handleWechatAuthCallback(): Promise<WechatLoginResult | null> {
|
||||
if (process.env.TARO_ENV !== 'h5') return null;
|
||||
if (!isWechatEnv()) return null;
|
||||
const config = await fetchClientConfig();
|
||||
if (!isWxAuthorizeEnabled(config)) return null;
|
||||
const result = await weixinSdk.handleOAuthCallback();
|
||||
if (result) stripOAuthParamsFromLocation();
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function loginWithWechatSdk(): Promise<WechatLoginResult | void> {
|
||||
const config = await fetchClientConfig();
|
||||
if (!isWxAuthorizeEnabled(config)) return;
|
||||
if (!isWechatEnv()) {
|
||||
throw new Error('请在微信内打开以使用微信一键授权');
|
||||
}
|
||||
return weixinSdk.login();
|
||||
}
|
||||
|
||||
export function applyWechatLoginResult(result: WechatLoginResult): boolean {
|
||||
return saveWechatLoginResult(result);
|
||||
}
|
||||
|
||||
/** 已登录用户绑定微信:小程序 code;H5 走公众号 OAuth(带 JWT 时服务端会 attach) */
|
||||
export async function bindWechatForUser(
|
||||
prefetchedWxProfile?: { nickname?: string; avatarUrl?: string } | null,
|
||||
): Promise<WechatBindResult> {
|
||||
if (process.env.TARO_ENV === 'h5') {
|
||||
const result = await authorizeWechatForPay();
|
||||
if (!result) {
|
||||
return { ok: false, redirecting: true };
|
||||
}
|
||||
if (result.needBindPhone && result.wxSessionKey) {
|
||||
return { ok: false, needBindPhone: true, wxSessionKey: result.wxSessionKey };
|
||||
}
|
||||
if (result.accessToken) {
|
||||
saveAuth({
|
||||
accessToken: result.accessToken,
|
||||
refreshToken: result.refreshToken,
|
||||
});
|
||||
}
|
||||
const profile = await fetchUserProfile();
|
||||
return { ok: true, profile };
|
||||
}
|
||||
|
||||
const res = await Taro.login();
|
||||
if (!res.code) {
|
||||
throw new Error(res.errMsg || '微信授权失败');
|
||||
}
|
||||
const { request } = await import('./api');
|
||||
const data = await request<WechatLoginResult>('/auth/wechat/bind', {
|
||||
method: 'POST',
|
||||
data: { code: res.code, platform: 'mini' },
|
||||
});
|
||||
if (data.needBindPhone && data.wxSessionKey) {
|
||||
return { ok: false, needBindPhone: true, wxSessionKey: data.wxSessionKey };
|
||||
}
|
||||
await syncMiniWechatProfile(prefetchedWxProfile);
|
||||
const profile = await fetchUserProfile();
|
||||
return { ok: true, profile };
|
||||
}
|
||||
|
||||
export type { WechatBindResult };
|
||||
|
||||
Reference in New Issue
Block a user