wx-login/app/src/routes/wx/services.ts

188 lines
5.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { WxTokenResponse, fetchToken, getUserInfo } from '@/modules/wx.ts';
import { useContextKey } from '@kevisual/use-config/context';
import { UserModel } from '@kevisual/code-center-module';
import { Buffer } from 'buffer';
import { CustomError } from '@kevisual/router';
import { customAlphabet } from 'nanoid';
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10);
const User = useContextKey<typeof UserModel>('UserModel');
export class WxServices {
wxToken: WxTokenResponse;
// 创建一个webToken用户登录
webToken: string;
accessToken: string;
refreshToken: string;
isNew: boolean;
// @ts-ignore
user: User;
constructor() {
//
}
async checkUserExist(username: string) {
const user = await User.findOne({
where: {
username,
},
});
return !!user;
}
async randomUsername() {
const a = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10);
const b = customAlphabet('1234567890', 10);
const random = '@' + a(4) + '' + b(4);
const user = await this.checkUserExist(random);
if (user) {
return this.randomUsername();
}
return random;
}
/**
* 获取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');
}
this.wxToken = token;
const unionid = token.unionid;
let user = await User.findOne({
where: {
data: {
wxUnionId: unionid,
},
},
});
// @ts-ignore
if (type === 'open' && user && user.data.wxOpenid !== token.openid) {
user.data = {
...user.data,
// @ts-ignore
wxOpenid: token.openid,
};
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));
let data = {
...user.data,
wxUnionId: unionid,
};
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;
this.accessToken = tokenInfo.accessToken;
this.refreshToken = tokenInfo.refreshToken;
this.user = user;
return {
accessToken: this.accessToken,
refreshToken: this.refreshToken,
isNew: this.isNew,
};
}
async checkHasUser() {}
async getUserInfo() {
try {
if (!this.wxToken) {
throw new CustomError(400, 'wxToken is not set');
}
const userInfo = await getUserInfo(this.wxToken.access_token, this.wxToken.openid);
const { nickname, headimgurl } = userInfo;
this.user.nickname = nickname;
try {
const downloadImgUrl = await this.downloadImg(headimgurl);
this.user.avatar = downloadImgUrl;
} catch (error) {
console.error('Error downloading or converting image:', error);
}
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);
}
}
/**
* 转成base64
* @param url
*/
async downloadImg(url: string): Promise<string> {
try {
return await downloadImag(url);
} catch (error) {
console.error('Error downloading or converting image:', error);
return '';
}
}
}
// https://thirdwx.qlogo.cn/mmopen/vi_32/WvOPpbDwUKEVJvSst8Z91Y68m7CsBeecMqRGlqey5HejByePD89boYGaVCM8vESsYmokk1jABUDsK08IrfI6JEkibZkDIC2zsb96DGBTEF7E/132
export const downloadImag = async (url: string) => {
try {
const res = await fetch(url);
if (!res.ok) {
throw new Error(`HTTP error! Status: ${res.status}`);
}
const arrayBufferToBase64 = (buffer: ArrayBuffer): string => {
const bytes = new Uint8Array(buffer);
let binary = '';
for (let i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i]);
}
return Buffer.from(binary, 'binary').toString('base64');
};
const buffer = await res.arrayBuffer();
return `data:image/jpeg;base64,${arrayBufferToBase64(buffer)}`;
} catch (error) {
console.error('Error downloading or converting image:', error);
throw error;
}
};