fix: add wx-login check
This commit is contained in:
parent
197d6415d3
commit
e5111227fd
@ -5,7 +5,7 @@
|
||||
"main": "index.js",
|
||||
"basename": "/root/wx-app-services",
|
||||
"app": {
|
||||
"key": "wx-app",
|
||||
"key": "wx-app-services",
|
||||
"entry": "dist/app.mjs",
|
||||
"type": "system-app",
|
||||
"files": [
|
||||
|
@ -24,10 +24,10 @@ export type WxToken = {
|
||||
* @param code
|
||||
* @returns
|
||||
*/
|
||||
export const fetchToken = async (code: string): Promise<WxToken> => {
|
||||
export const fetchToken = async (code: string, type: 'open' | 'mp' = 'open'): Promise<WxToken> => {
|
||||
let appId = config.wxOpen.appId;
|
||||
let appSecret = config.wxOpen.appSecret;
|
||||
if (!appId && !appSecret) {
|
||||
if (type === 'mp') {
|
||||
appId = config.wx.appId;
|
||||
appSecret = config.wx.appSecret;
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ app
|
||||
const code = ctx.query.code;
|
||||
try {
|
||||
const wx = new WxServices();
|
||||
const token = await wx.login(code);
|
||||
const token = await wx.login(code, 'mp');
|
||||
const redis = useContextKey('redis');
|
||||
await redis.set(`wx:mp:login:${state}`, token, 'EX', 10000); // 30秒过期
|
||||
ctx.body = {
|
||||
@ -81,6 +81,24 @@ app
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
app
|
||||
.route({
|
||||
path: 'wx',
|
||||
key: 'mp-get-openid',
|
||||
isDebug: true,
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
const code = ctx.query.code;
|
||||
if (!code) {
|
||||
ctx.throw(400, 'code is required');
|
||||
return;
|
||||
}
|
||||
const wx = new WxServices();
|
||||
const mpInfo = await wx.getOpenid(code, 'mp');
|
||||
ctx.body = mpInfo;
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
app
|
||||
.route({
|
||||
path: 'wx',
|
||||
|
@ -36,8 +36,22 @@ export class WxServices {
|
||||
}
|
||||
return random;
|
||||
}
|
||||
async login(code: string) {
|
||||
const token = await fetchToken(code);
|
||||
/**
|
||||
* 获取openid
|
||||
* @param code
|
||||
* @returns
|
||||
*/
|
||||
async getOpenid(code: string, type: 'mp' | 'open' = 'open') {
|
||||
const token = await fetchToken(code, type);
|
||||
console.log('login token', token);
|
||||
return {
|
||||
openid: token.openid,
|
||||
scope: token.scope,
|
||||
unionid: token.unionid,
|
||||
};
|
||||
}
|
||||
async login(code: string, type: 'mp' | 'open' = 'open') {
|
||||
const token = await fetchToken(code, type);
|
||||
console.log('login token', token);
|
||||
if (!token.unionid) {
|
||||
throw new CustomError(400, 'code is invalid, wxdata can not be found');
|
||||
@ -52,32 +66,49 @@ export class WxServices {
|
||||
},
|
||||
});
|
||||
// @ts-ignore
|
||||
if (user && user.data.wxOpenid !== token.openid) {
|
||||
if (type === 'open' && user && user.data.wxOpenid !== token.openid) {
|
||||
user.data = {
|
||||
...user.data,
|
||||
// @ts-ignore
|
||||
wxOpenid: token.openid,
|
||||
};
|
||||
await user.update({ data: user.data });
|
||||
user = await user.update({ data: user.data });
|
||||
console.log('mp-user login openid update=============', token.openid, token.unionid);
|
||||
// @ts-ignore
|
||||
} else if (type === 'mp' && user && user.data.wxmpOpenid !== token.openid) {
|
||||
user.data = {
|
||||
...user.data,
|
||||
// @ts-ignore
|
||||
wxmpOpenid: token.openid,
|
||||
};
|
||||
user = await user.update({ data: user.data });
|
||||
}
|
||||
if (!user) {
|
||||
const username = await this.randomUsername();
|
||||
user = await User.createUser(username, nanoid(10));
|
||||
user.data = {
|
||||
let data = {
|
||||
...user.data,
|
||||
// @ts-ignore
|
||||
wxOpenid: token.openid,
|
||||
wxUnionId: unionid,
|
||||
};
|
||||
await user.save({ fields: ['data'] });
|
||||
user.data = data;
|
||||
if ((type = 'mp')) {
|
||||
// @ts-ignore
|
||||
data.wxmpOpenid = token.openid;
|
||||
} else {
|
||||
// @ts-ignore
|
||||
data.wxOpenid = token.openid;
|
||||
}
|
||||
this.user = await user.save({ fields: ['data'] });
|
||||
|
||||
this.getUserInfo();
|
||||
this.isNew = true;
|
||||
}
|
||||
|
||||
this.user = user;
|
||||
const tokenInfo = await user.createToken(null, 'plugin', {
|
||||
wx: {
|
||||
openid: token.openid,
|
||||
unionid: unionid,
|
||||
type,
|
||||
},
|
||||
});
|
||||
this.webToken = tokenInfo.accessToken;
|
||||
@ -107,7 +138,12 @@ export class WxServices {
|
||||
} catch (error) {
|
||||
console.error('Error downloading or converting image:', error);
|
||||
}
|
||||
await this.user.save();
|
||||
const data = {
|
||||
...this.user.data,
|
||||
wxUserInfo: userInfo,
|
||||
};
|
||||
this.user.data = data;
|
||||
await this.user.save({ fields: ['data', 'nickname', 'avatar'] });
|
||||
} catch (error) {
|
||||
console.error('Error getting user info:', error);
|
||||
}
|
||||
@ -121,7 +157,7 @@ export class WxServices {
|
||||
return await downloadImag(url);
|
||||
} catch (error) {
|
||||
console.error('Error downloading or converting image:', error);
|
||||
throw error;
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
3
mini-web/README.md
Normal file
3
mini-web/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# 登陆逻辑
|
||||
|
||||
微信访问 `login.html` 的界面, 然后 `login.html` 去获取 `/authorize` 获取 openid
|
@ -3,9 +3,15 @@ export const config = {
|
||||
appid: 'wxff97d569b1db16b6',
|
||||
appid_open: 'wx9378885c8390e09b', // 公众开放平台, 逸文设计 //
|
||||
redirect_uri: 'https://kevisual.xiongxiao.me/root/mini-web/callback.html',
|
||||
scope: 'snsapi_userinfo',
|
||||
scope: 'snsapi_userinfo', // 授权作用域, 默认是snsapi_base
|
||||
};
|
||||
|
||||
export const loginUrl = `https://kevisual.xiongxiao.me/root/mini-web/login.html`;
|
||||
|
||||
export const loginSuccessUrl = `/apps/wallnote/`;
|
||||
|
||||
export const openidConfig = {
|
||||
appid: config.appid,
|
||||
redirect_uri: 'https://kevisual.xiongxiao.me/root/mini-web/wx-get-openid.html',
|
||||
scope: 'snsapi_base',
|
||||
};
|
||||
|
57
mini-web/envision/utils.js
Normal file
57
mini-web/envision/utils.js
Normal file
@ -0,0 +1,57 @@
|
||||
import { openidConfig } from './config.js';
|
||||
|
||||
export const isWechat = () => {
|
||||
const ua = navigator.userAgent.toLowerCase();
|
||||
return /micromessenger/i.test(ua);
|
||||
};
|
||||
|
||||
export const getOpenid = async () => {
|
||||
const url = new URL(window.location.href);
|
||||
const state = url.searchParams.get('state');
|
||||
const code = url.searchParams.get('code');
|
||||
const orgin = url.origin;
|
||||
const res = await fetch(`${orgin}/api/router?path=wx&key=mp-get-openid&state=${state}&code=${code}`)
|
||||
.then((res) => res.json())
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
alert('登录失败,请稍后再试');
|
||||
document.body.append('登录失败,请稍后再试');
|
||||
// closePage();
|
||||
});
|
||||
if (res.code === 200) {
|
||||
document.body.append(JSON.stringify(res.data, null, 2));
|
||||
}
|
||||
};
|
||||
|
||||
export const checkHasCode = () => {
|
||||
const url = new URL(window.location.href);
|
||||
const code = url.searchParams.get('code');
|
||||
return code;
|
||||
};
|
||||
|
||||
export const initGetOpenidEvent = () => {
|
||||
if (!isWechat()) {
|
||||
document.body.append('请在微信中打开');
|
||||
return;
|
||||
}
|
||||
const hasCode = checkHasCode();
|
||||
if (hasCode) {
|
||||
getOpenid();
|
||||
} else {
|
||||
// 没有code,则跳转获取code
|
||||
getCodeRedirect();
|
||||
}
|
||||
};
|
||||
|
||||
const randomString = () => {
|
||||
return Math.random().toString(36).substring(2, 15);
|
||||
};
|
||||
export const getCodeRedirect = () => {
|
||||
const defaultURL = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect`;
|
||||
const appid = openidConfig.appid;
|
||||
const redirect_uri = encodeURIComponent(openidConfig.redirect_uri);
|
||||
const scope = openidConfig.scope;
|
||||
const state = randomString();
|
||||
const link = defaultURL.replace('APPID', appid).replace('REDIRECT_URI', redirect_uri).replace('SCOPE', scope).replace('STATE', state);
|
||||
window.location.href = link;
|
||||
};
|
50
mini-web/envision/wx-get-openid.html
Normal file
50
mini-web/envision/wx-get-openid.html
Normal file
@ -0,0 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0, maximum-scale=1, user-scalable=no">
|
||||
<title>登录</title>
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.loading {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 1.5em;
|
||||
/* Adjust font size for mobile */
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.loading {
|
||||
font-size: 1em;
|
||||
/* Smaller font size for smaller screens */
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="loading"></div>
|
||||
<div class="openid"></div>
|
||||
<script type="module">
|
||||
import { initGetOpenidEvent, isWechat } from './utils.js';
|
||||
const loading = document.querySelector('.loading');
|
||||
loading.textContent = !isWechat() ? '微信打开当前页面获取openid' : '';
|
||||
initGetOpenidEvent();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "mini-web",
|
||||
"version": "0.0.4",
|
||||
"version": "0.0.5",
|
||||
"description": "",
|
||||
"basename": "/root/mini-web",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"pub": "envision deploy ./envision -k mini-web -v 0.0.4 -y y",
|
||||
"pub": "envision deploy ./envision -k mini-web -v 0.0.5 -u ",
|
||||
"ev": "npm run build && npm run deploy"
|
||||
},
|
||||
"keywords": [],
|
||||
|
Loading…
x
Reference in New Issue
Block a user