Files
code-center/src/routes/user/modules/wx.ts
abearxiong 366a21d621 feat: add CNB login functionality and user management
- Introduced `cnb-login` route to handle user login via CNB token.
- Created `CnbServices` class for managing CNB user interactions.
- Added `findByCnbId` method in the User model to retrieve users by CNB ID.
- Updated error handling to provide more structured error messages.
- Enhanced user creation logic to handle CNB users.
- Added tests for the new CNB login functionality.
2026-02-20 23:30:53 +08:00

163 lines
4.0 KiB
TypeScript

import { CustomError } from '@kevisual/router';
import { useConfig } from '@kevisual/use-config';
export const config = useConfig()
const wxOpen = {
// @ts-ignore
appId: config.WX_OPEN_APP_ID,
// @ts-ignore
appSecret: config.WX_OPEN_APP_SECRET,
}
const wx = {
// @ts-ignore
appId: config.WX_MP_APP_ID,
// @ts-ignore
appSecret: config.WX_MP_APP_SECRET,
}
export type WxTokenResponse = {
access_token: string;
expires_in: number;
refresh_token: string;
openid: string;
scope: string;
unionid: string;
};
export type WxToken = {
access_token: string;
expires_in: number;
refresh_token: string;
openid: string;
scope: string;
unionid: string;
};
/**
* 根据code获取token
* @param code
* @returns
*/
export const fetchToken = async (code: string, type: 'open' | 'mp' = 'open'): Promise<WxToken> => {
let appId = wxOpen.appId;
let appSecret = wxOpen.appSecret;
if (type === 'mp') {
appId = wx.appId;
appSecret = wx.appSecret;
}
if (!appId || !appSecret) {
throw new CustomError(500, { message: 'appId or appSecret is not set' });
}
console.log('fetchToken===', appId, appSecret, code);
const wxUrl = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${appId}&secret=${appSecret}&code=${code}&grant_type=authorization_code`;
const res = await fetch(wxUrl);
const data = await res.json();
console.log('query token', data);
return data;
};
type UserInfo = {
openid: string;
nickname: string;
sex: number;
language: string;
province: string;
country: string;
headimgurl: string;
privilege: string[];
unionid: string;
};
/**
* 获取用户信息, 通过授权登录
* 例子:微信内部网页,开放平台授权网页,确定登录的时候
* @param token
* @param openid
* @returns
*/
export const getUserInfo = async (token: string, openid: string): Promise<UserInfo> => {
const phoneUrl = `https://api.weixin.qq.com/sns/userinfo?access_token=${token}&openid=${openid}`;
const res = await fetch(phoneUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
});
const data = await res.json();
return data;
};
/**
* 公众号获取用户信息,
* 微信公众号扫码,
* 订阅登录,非授权,
* 而是根据你关注了用户才登录
* @param token
* @param openid
* @returns
*/
export const getUserInfoByMp = async (token: string, openid: string) => {
// const phoneUrl = `https://api.weixin.qq.com/sns/userinfo?access_token=${token}&openid=${openid}`;
const phoneUrl = `https://api.weixin.qq.com/cgi-bin/user/info?access_token=${token}&openid=${openid}&lang=zh_CN`;
const res = await fetch(phoneUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
});
const data = await res.json();
return data;
};
// getUserInfo(token.access_token, token.openid)
type AuthRes = {
errcode: number;
errmsg: string;
};
/**
* errorcode 0: 正常
* @param token
* @param openid
* @returns
*/
export const getAuth = async (token: string, openid: string): Promise<AuthRes> => {
const authUrl = `https://api.weixin.qq.com/sns/auth?access_token=${token}&openid=${openid}`;
const res = await fetch(authUrl);
const data = await res.json();
// console.log(data)
return data;
};
// getAuth(token.access_token, token.openid)
type RefreshToken = {
access_token: string;
expires_in: number;
refresh_token: string;
openid: string;
scope: string;
};
export const refreshToken = async (refreshToken: string): Promise<RefreshToken> => {
// @ts-ignore
const { appId } = config?.wx;
const refreshUrl = `https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=${appId}&grant_type=refresh_token&refresh_token=${refreshToken}`;
const res = await fetch(refreshUrl);
const data = await res.json();
return data;
};
// refreshToken(token.refresh_token)
export const post = async (url: string, data: any) => {
const res = await fetch(url, {
method: 'POST',
body: JSON.stringify(data),
});
return await res.json();
};