- 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.
163 lines
4.0 KiB
TypeScript
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();
|
|
}; |