微信SDK接通

This commit is contained in:
2026-07-01 19:56:44 +08:00
parent a1cbfc7241
commit aea1513836
38 changed files with 1610 additions and 92 deletions
+84
View File
@@ -0,0 +1,84 @@
import type { WechatJssdkConfig } from '@dukang/shared-types';
import { DEFAULT_JS_API_LIST } from './types';
const JSSDK_URL = 'https://res.wx.qq.com/open/js/jweixin-1.6.0.js';
let scriptPromise: Promise<void> | null = null;
let configured = false;
function loadScript(): Promise<void> {
if (typeof document === 'undefined') return Promise.reject(new Error('非浏览器环境'));
if (window.wx) return Promise.resolve();
if (scriptPromise) return scriptPromise;
scriptPromise = new Promise((resolve, reject) => {
const existing = document.querySelector<HTMLScriptElement>('script[data-dukang-wx-jssdk]');
if (existing) {
existing.addEventListener('load', () => resolve());
existing.addEventListener('error', () => reject(new Error('微信 JSSDK 加载失败')));
return;
}
const script = document.createElement('script');
script.src = JSSDK_URL;
script.async = true;
script.dataset.dukangWxJssdk = '1';
script.onload = () => resolve();
script.onerror = () => reject(new Error('微信 JSSDK 加载失败'));
document.head.appendChild(script);
});
return scriptPromise;
}
async function fetchJssdkConfig(apiBase: string, clientApp: string, url: string, token?: string | null) {
const headers: Record<string, string> = { 'X-Client-App': clientApp };
if (token) headers.Authorization = `Bearer ${token}`;
const qs = new URLSearchParams({ url });
const res = await fetch(`${apiBase}/common/wechat/jssdk-config?${qs}`, { headers });
const json = await res.json();
if (json.code !== 0) throw new Error(json.message || '获取 JSSDK 配置失败');
return json.data as WechatJssdkConfig;
}
/** 初始化微信 JSSDKH5 公众号内) */
export async function initWechatJssdk(options: {
apiBase: string;
clientApp: string;
url?: string;
getAccessToken?: () => string | null;
jsApiList?: string[];
}): Promise<void> {
const { apiBase, clientApp, getAccessToken } = options;
const pageUrl = options.url ?? (typeof window !== 'undefined' ? window.location.href.split('#')[0] : '');
await loadScript();
if (!window.wx) throw new Error('微信 JSSDK 不可用');
const config = await fetchJssdkConfig(apiBase, clientApp, pageUrl, getAccessToken?.());
const jsApiList = options.jsApiList ?? [...DEFAULT_JS_API_LIST];
await new Promise<void>((resolve, reject) => {
window.wx!.config({
...config,
jsApiList,
debug: false,
});
window.wx!.ready(() => {
configured = true;
resolve();
});
window.wx!.error((err) => reject(new Error(err.errMsg || 'wx.config 失败')));
});
}
export function isJssdkReady(): boolean {
return configured && !!window.wx;
}
export async function ensureJssdkReady(options: {
apiBase: string;
clientApp: string;
getAccessToken?: () => string | null;
}): Promise<void> {
if (!isJssdkReady()) {
await initWechatJssdk(options);
}
}