插件 Demo · 替换 wx.login 的 Code
这个 Demo 对应市场里的 JSLogin 替换(login-code-switcher)。它演示:
- 逻辑层包装
wx.login - 用
wadLogicLayer.register暴露setCode / getCode - 面板通过
logicLayer.call设置 code onDetach恢复原始wx.login,避免残留
逻辑段
js
// <script type="text/wad-logic">
(function () {
// 当前要返回给业务的 code;空字符串表示“不替换、走真实登录”。
var state = { code: '' };
// 当前由本插件安装的 wrapper;恢复时用它判断 wx.login 是否仍属于我们。
var installed = null;
/**
* 还原真实 wx.login。
*
* 只在插件停用/卸载/切小程序时调用。恢复后要把临时保存的原始函数也删掉,
* 避免下一次注入把旧函数误当成“原始函数”。
*/
function restore() {
try {
// 只有当前 wx.login 仍是我们替换过的函数时才恢复;
// 如果别的插件/业务又包装过,不能强行覆盖。
if (wx.__wadOrigLogin && wx.login === installed) {
Object.defineProperty(wx, 'login', {
value: wx.__wadOrigLogin,
configurable: true,
writable: true
});
}
try { delete wx.__wadOrigLogin; } catch (e) { wx.__wadOrigLogin = undefined; }
installed = null;
} catch (e) {
// 恢复失败也不能阻断 detach;下一次 attach 会重新安装。
}
}
/**
* 安装/更新 wx.login 包装。
*
* 每次注入都会重新执行:用最新闭包里的 state 生成 wrapper。
* 原始函数只保存一次(__wadOrigLogin),所以不会 wrapper 套 wrapper。
*/
function install() {
if (!wx.__wadOrigLogin) wx.__wadOrigLogin = wx.login;
var orig = wx.__wadOrigLogin;
/**
* 替换后的 wx.login。
*
* @param {object} opt wx.login 的原始参数对象
* - success({code, errMsg})
* - fail(err)
* - complete(res)
*/
var wrapped = function (opt) {
opt = opt || {};
// 没设置 code:原样调用真实 wx.login,业务完全无感。
if (!state.code) {
return orig ? orig.call(wx, opt) : undefined;
}
// 设置了 code:构造和真实 wx.login 一样的成功返回。
var res = { code: state.code, errMsg: 'login:ok' };
// 广播给面板,便于在面板日志里看到“业务确实调用了 wx.login”。
wadLogicLayer.messaging.emit('loginCalled', {
code: state.code,
replaced: true
});
// 按 wx API 约定依次回调 success / complete。
// 业务回调抛错要吞掉,不能影响插件自身。
try { opt.success && opt.success(res); } catch (e) {}
try { opt.complete && opt.complete(res); } catch (e) {}
};
// 打标记,调试/诊断时可确认当前 wx.login 已被接管。
wrapped.__wadDemo = true;
installed = wrapped;
try {
Object.defineProperty(wx, 'login', {
value: wrapped,
configurable: true,
writable: true
});
} catch (e) {
// 个别基础库对 wx 属性不可配置,退回直接赋值。
try { wx.login = wrapped; } catch (e2) {}
}
}
/**
* 面板设置替换 code。
*
* @param {string} code 自定义 code;传空字符串表示恢复真实登录
* @returns {string} 'ok:<code>',让面板能确认设置成功
*/
wadLogicLayer.register('setCode', function (code) {
state.code = String(code || '');
install(); // 立即用新状态重装 wrapper
return 'ok:' + state.code;
});
/** 面板读取当前替换值。 */
wadLogicLayer.register('getCode', function () {
return state.code;
});
// 每次注入都重新安装:换页/重新启用/小程序重启都会走这里。
wadLogicLayer.onAttach(function (appid) {
wadLogicLayer.log('attach ' + appid);
install();
});
// 停用/卸载/切小程序:恢复真实 wx.login,并清空替换值。
wadLogicLayer.onDetach(function () {
restore();
state.code = '';
});
})();面板
html
<input id="code" placeholder="自定义 code">
<button id="set">替换</button>
<button id="clear">恢复</button>
<pre id="log"></pre>
<script>
// 简单日志:每次追加一行。
const log = (s) => {
document.getElementById('log').textContent += s + '\n';
};
// 设置自定义 code:
// logicLayer.call 第一个参数是逻辑层注册的函数名,后面是逐个展开的参数。
document.getElementById('set').onclick = async () => {
const code = document.getElementById('code').value.trim();
if (!code) return log('请先输入 code');
const r = await wadPanelLayer.logicLayer.call('setCode', code);
log('已替换:' + r + '(下一次 wx.login 生效)');
};
// 恢复真实登录:传空字符串,逻辑层 wrapper 会走 orig。
document.getElementById('clear').onclick = async () => {
await wadPanelLayer.logicLayer.call('setCode', '');
log('已恢复真实 wx.login');
};
// 业务每次调用 wx.login 时,逻辑层会广播 loginCalled。
// 这里展示业务实际拿到的 code,便于确认替换已生效。
wadPanelLayer.messaging.on('loginCalled', (d) => {
log('小程序调用 wx.login → ' + d.code);
});
</script>验证清单
- [ ] 输入 code 后,业务拿到的
res.code等于输入值 - [ ] 清空后,业务重新走真实
wx.login - [ ] 停用插件后,
wx.login恢复为原始函数 - [ ] 小程序重启后不会带着上一次的 code
- [ ] 其它插件也包装
wx.login时,停用本插件不会误删对方的 wrapper
完整实现见市场插件 JSLogin 替换(login-code-switcher,版本 1.0.0)。