t-comm
Version:
专业、稳定、纯粹的工具库
218 lines (216 loc) • 6.92 kB
JavaScript
/**
* qq-wxmini-plugin 微信小程序插件封装
*
* 背景:QQ 用户无法直接打开微信小程序,但微信提供了 qq-wxmini-plugin 插件,
* 让 QQ 用户能够以 QQ 身份访问微信小程序。本文件封装插件初始化与环境检测。
*
* 使用前置条件:
* 1. 在微信公众平台后台添加 qq-wxmini-plugin 插件授权
* 2. 在 manifest.json / app.json 的 plugins 节点声明:
* {
* "qq-wxmini-plugin": {
* "version": "1.0.7",
* "provider": "wx41f6784ad4052201"
* }
* }
*/
var PLUGIN_NAME = 'qq-wxmini-plugin';
/**
* 安全获取 wx 全局对象
*/
function getWX() {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return typeof wx !== 'undefined' ? wx : globalThis.wx;
}
/**
* 安全获取 requirePlugin(小程序环境内置全局函数)
*/
function getRequirePlugin() {
var g = globalThis;
if (typeof g.requirePlugin === 'function') {
return g.requirePlugin;
}
// 微信小游戏部分版本下挂在 wx 上
var w = getWX();
if (typeof (w === null || w === void 0 ? void 0 : w.requirePlugin) === 'function') {
return w.requirePlugin.bind(w);
}
return undefined;
}
var cachedPlugin = null;
var inited = false;
/**
* 加载并初始化 qq-wxmini-plugin
*
* 内部带缓存,重复调用安全。
*
* @returns 插件实例;非微信小程序环境或未安装插件时返回 undefined
*/
function initQQMiniPlugin() {
var _a;
if (cachedPlugin && inited) {
return cachedPlugin;
}
var requirePlugin = getRequirePlugin();
if (!requirePlugin) {
console.info('[qq-mini-plugin] requirePlugin is not available (非微信小程序环境)');
return;
}
try {
var plugin = requirePlugin(PLUGIN_NAME);
if (!plugin) {
console.warn('[qq-mini-plugin] requirePlugin returned null');
return;
}
(_a = plugin.initPlugin) === null || _a === void 0 ? void 0 : _a.call(plugin, getWX());
cachedPlugin = plugin;
inited = true;
return plugin;
} catch (e) {
console.warn('[qq-mini-plugin] init failed:', e);
return;
}
}
/**
* 获取插件实例(不重复初始化时使用)
*/
function getQQWXMiniPlugin() {
return cachedPlugin || initQQMiniPlugin();
}
/**
* 检测当前是否为 QQ 环境(QQ 用户通过 qq-wxmini-plugin 访问微信小程序)
*
* 注意:必须先调用 initQQMiniPlugin(本函数内部会兜底调用)。
*
* @returns true 表示 QQ 环境;非微信小程序环境或插件未安装时返回 false
*/
function checkIsQQEnv() {
var _a;
var isQQEnv = false;
try {
var plugin = getQQWXMiniPlugin();
isQQEnv = !!((_a = plugin === null || plugin === void 0 ? void 0 : plugin.isQQEnv) === null || _a === void 0 ? void 0 : _a.call(plugin));
} catch (e) {
console.warn('[qq-mini-plugin] checkIsQQEnv failed:', e);
}
console.info('[qq-mini-plugin] isQQEnv:', isQQEnv);
return isQQEnv;
}
/**
* QQ 环境下若检测到微信登录态则清除 storage
*
* 由调用方提供「当前是否为微信登录态」的判断函数,
* 以避免本工具与具体 cookie/storage 字段耦合。
*
* 典型用法:
* ```ts
* clearWxLoginStorageIfQQEnv({
* isWxLoggedIn: () => cookie.get('tip_utype') === '2',
* });
* ```
*
* @param options.isWxLoggedIn 判断当前是否为微信登录态(必填)
* @param options.clearStorage 自定义清除函数,默认 wx.clearStorageSync
* @param options.shouldForceQQ 是否强制 QQ 登录态(即在 QQ 环境下
* 一旦检测到微信登录态就清掉 storage 让用户重走 QQ 登录)。
*
* 默认 `() => true`(保留旧行为)。
*
* 若业务希望「QQ App 下也允许用户手动用微信账号登录」,请传入 `() => false`,
* 或基于业务自身的「用户是否手动切到微信账号」状态返回值。
*/
function clearWxLoginStorageIfQQEnv(options) {
var _a;
var isWxLoggedIn = options.isWxLoggedIn,
clearStorage = options.clearStorage,
shouldForceQQ = options.shouldForceQQ;
try {
if (!checkIsQQEnv()) {
return false;
}
// 业务方关闭了「QQ 环境强制 QQ 登录」开关:直接放行
if (shouldForceQQ && !shouldForceQQ()) {
return false;
}
if (!isWxLoggedIn()) {
return false;
}
console.info('[qq-mini-plugin] QQ 环境检测到微信登录态,清除 storage');
if (clearStorage) {
clearStorage();
} else {
var w = getWX();
(_a = w === null || w === void 0 ? void 0 : w.clearStorageSync) === null || _a === void 0 ? void 0 : _a.call(w);
}
return true;
} catch (e) {
console.error('[qq-mini-plugin] clearWxLoginStorageIfQQEnv error:', e);
return false;
}
}
/**
* QQ 环境下直接通过 qq-wxmini-plugin 拿 QQ 登录 code
*
* 适用场景:用户已在 QQ App 中(即 `checkIsQQEnv() === true`),
* 此时无需 `wx.navigateToMiniProgram` 跳腾讯 QQ 小程序,
* 可直接调用插件的 `plugin.login()` 同步拿到 QQ code,
* 再交给业务后台用 `_ltype=tiploginqqproc` 换登录态。
*
* @returns code 字符串;插件不可用或登录失败时 reject
*/
function qqPluginLogin() {
return new Promise(function (resolve, reject) {
var plugin = getQQWXMiniPlugin();
if (!plugin || typeof plugin.login !== 'function') {
reject(new Error('[qq-mini-plugin] plugin.login is not available'));
return;
}
try {
Promise.resolve(plugin.login()).then(function (res) {
var code = (res === null || res === void 0 ? void 0 : res.code) || '';
if (!code) {
reject(new Error('[qq-mini-plugin] plugin.login returned empty code'));
return;
}
resolve({
code: code
});
})["catch"](reject);
} catch (e) {
reject(e);
}
});
}
/**
* 通过 wx.login 拿微信登录 code
*
* 适用场景:微信宿主下走微信登录,或 QQ App 下用户主动选择「微信账号登录」时。
* 拿到 code 后由业务后台用 `_ltype=tiploginwxproc` 换登录态。
*
* @returns code 字符串;wx.login 不可用或失败时 reject
*/
function wxLogin() {
return new Promise(function (resolve, reject) {
var w = getWX();
if (!w || typeof w.login !== 'function') {
reject(new Error('[qq-mini-plugin] wx.login is not available'));
return;
}
w.login({
success: function success(res) {
var code = (res === null || res === void 0 ? void 0 : res.code) || '';
if (!code) {
reject(new Error('[qq-mini-plugin] wx.login returned empty code'));
return;
}
resolve({
code: code
});
},
fail: function fail(err) {
return reject(err);
}
});
});
}
export { checkIsQQEnv, clearWxLoginStorageIfQQEnv, getQQWXMiniPlugin, initQQMiniPlugin, qqPluginLogin, wxLogin };