709 字
4 分钟
微信扫码登录统一封装
2025-11-12
无标签

微信扫描登录#

微信官方文档

在网页中嵌入微信的登录二维码,会在login_container 下嵌入一个iframeiframe 的地址其实就是 “https://open.weixin.qq.com/connect/qrconnect?`appid`=APPID&`redirect_uri`=REDIRECT_URI&`response_type`=code&`scope`=SCOPE&`state`=STATE#wechat_redirect” ,URL中对应的参数就是WxLogin的构造参数。

var obj = new WxLogin({
self_redirect:true,
id:"login_container",
appid: "",
scope: "",
redirect_uri: "",
state: "",
style: "",
href: "",
onReady: function(isReady){
console.log(isReady);
}
});

在扫码完成登录后,该iframe就会重定向到redirect_uri ,并在url的参数中拼接code参数。 redirect_uri 是微信登录成功界面。此页面可以获取到code,在页面加载后,读取code 通过window.postMessage ,将code传递给上一级网页。

统一的重定向地址#

扩展实现一个支持多种方式回传code与state的网页:

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Redirect...</title>
</head>
<body>
<div class="container">
<div class="loading">
加载中...
</div>
<script>
var urlParams = new URLSearchParams(window.location.search);
var code = urlParams.get('code')
var state = urlParams.get('state')
var key = urlParams.get('key')
var redirect = urlParams.get('redirect')
/*
回传 JSON.stringfy({ code, state }) 的方式:
pm: parent.postMessage
ss: 直接将值设置到 sessionStorage.setItem(key, ... )
r: 重定向:调整到 redirect 的地址,拼接参数 code与state,redirect需要解码
*/
var ct = urlParams.get('ct');
function main() {
// 根据 ct 参数值执行不同的操作
const data = {code, state};
const dataStr = JSON.stringify(data);
switch (ct) {
case 'pm':
// 使用 parent.postMessage 回传数据
if (window.parent && window.parent !== window) {
let targetOrigin;
try {
targetOrigin = window.parent.origin;
} catch (error) {
console.log('读取 window.parent.origin 失败,使用默认 targetOrigin:', error);
targetOrigin = location.origin
}
window.parent.postMessage({action: 'WECHAT_LOGIN_SUCCESS', data}, targetOrigin);
}
break;
case 'ss':
// 使用 sessionStorage.setItem 回传数据
if (key) {
sessionStorage.setItem(key, dataStr);
}
break;
case 'r':
// 重定向:调整到 redirect 的地址,拼接参数 code 与 state
if (redirect) {
const decodedRedirect = decodeURIComponent(redirect);
const redirectUrl = new URL(decodedRedirect);
redirectUrl.searchParams.set('code', code);
redirectUrl.searchParams.set('state', state);
window.location.href = redirectUrl.toString();
}
break;
default:
// 如果未指定或指定错误的 ct 值,默认使用 postMessage
if (window.parent && window.parent !== window) {
let targetOrigin = '*';
try {
targetOrigin = window.parent.origin;
} catch (error) {
console.log('读取 window.parent.origin 失败,使用默认 targetOrigin:', error);
}
window.parent.postMessage(data, targetOrigin);
}
break;
}
}
main();
</script>
</div>
</body>
</html>

例如使用:#

预期使用同源的postMessage来传递消息: 本地、开发、测试、线上域名都不一样。而微信的验证回调只能填写一个地址。 所以预期的方案是由这个唯一的地址根据参数进行不同的操作,将参数回传。 假设验证回调为:https://q.xxxx.com/wxcb?ct=r&redirect=${redirect} 本地是localhost:9000 ,用户扫描登陆后会触发回调https://q.xxxx.com/wxcb?ct=r&redirect=${redirect}&code=x&state=x ,将 redirect 调整为本地的localhost:9000/wxcb.html?ct=pm ,就会再跳转到localhost:9000/wxcb.html?ct=pm&code=x&state=x再由此网页通过同源postMessage将code传递给当前网页去完成登陆。这样当前网页就不用刷新了,几个步骤的网页都在当前网页的iframe中刷新

const initWechatLogin = useCallback(() => {
try {
const redirect = encodeURIComponent(
`${location.protocol}//${location.host}/wxcb.html?ct=pm`
)
// 创建微信登录实例
new window.WxLogin({
id: 'wechat-login-container',
self_redirect: true,
appid: APP_ID,
scope: 'snsapi_login',
redirect_uri: encodeURIComponent(
`https://q.xxxx.com/wxcb?ct=r&redirect=${redirect}`
),
state: 'lite',
style: '',
})
} catch (error) {
onError?.(error)
}
}, [])

img.png

微信扫码登录统一封装
https://fuwari.vercel.app/blog/posts/wx-mini/微信扫码登录统一封装/
作者
Byte.n
发布于
2025-11-12
许可协议
CC BY-NC-SA 4.0