wechatLogin登录后token指向wechatLogin

This commit is contained in:
lxy 2024-08-16 16:21:54 +08:00
parent cf3b2a9186
commit f6e5fa2d72
10 changed files with 179 additions and 110 deletions

View File

@ -1,6 +1,7 @@
import { EntityDict } from '../oak-app-domain';
import { NativeEnv, WebEnv, WechatMpEnv } from 'oak-domain/lib/types/Environment';
import { BRC } from '../types/RuntimeCxt';
export declare function sendEmail(): void;
export declare function loginByMobile<ED extends EntityDict>(params: {
captcha?: string;
password?: string;

View File

@ -9,6 +9,10 @@ import { tokenProjection } from '../types/Projection';
import { sendSms } from '../utils/sms';
import { mergeUser } from './user';
import { cloneDeep } from 'oak-domain/lib/utils/lodash';
import { sendEmail as sendEmailFn } from '../utils/email';
export function sendEmail() {
sendEmailFn();
}
async function makeDistinguishException(userId, context, message) {
const [user] = await context.select('user', {
data: {
@ -687,18 +691,6 @@ export async function loginByWechat(params, context) {
const { wechatLoginId, env } = params;
const closeRootMode = context.openRootMode();
const [wechatLoginData] = await context.select('wechatLogin', {
data: {
id: 1,
userId: 1,
type: 1,
},
filter: {
id: wechatLoginId,
},
}, {
dontCollect: true,
});
const [wechatUserLogin] = await context.select('wechatUser', {
data: {
id: 1,
userId: 1,
@ -710,14 +702,15 @@ export async function loginByWechat(params, context) {
refId: 1,
isRoot: 1,
},
type: 1,
},
filter: {
userId: wechatLoginData.userId,
id: wechatLoginId,
},
}, {
dontCollect: true,
});
const tokenValue = await setUpTokenAndUser(env, context, 'wechatUser', wechatUserLogin.id, undefined, wechatUserLogin.user);
const tokenValue = await setUpTokenAndUser(env, context, 'wechatLogin', wechatLoginId, undefined, wechatLoginData.user);
await loadTokenInfo(tokenValue, context);
closeRootMode();
return tokenValue;
@ -754,7 +747,7 @@ async function loginFromWechatEnv(code, env, context, wechatLoginId) {
wechatMp: 'mp',
native: 'native',
};
const createWechatUserAndReturnTokenId = async (user) => {
const createWechatUserAndReturnTokenId = async (user, wechatLoginId) => {
const wechatUserCreateData = {
id: await generateNewIdAsync(),
unionId,
@ -763,8 +756,14 @@ async function loginFromWechatEnv(code, env, context, wechatLoginId) {
applicationId: application.id,
...wechatUserData,
};
const tokenValue = await setUpTokenAndUser(env, context, 'wechatUser', undefined, wechatUserCreateData, user);
return tokenValue;
let tokenValue;
if (wechatLoginId) {
tokenValue = await setUpTokenAndUser(env, context, 'wechatLogin', wechatLoginId, undefined, user);
}
else {
tokenValue = await setUpTokenAndUser(env, context, 'wechatUser', undefined, wechatUserCreateData, user);
}
return { tokenValue, wechatUserId: wechatUserCreateData.id };
};
// 扫码者
const [wechatUser] = await context.select('wechatUser', {
@ -865,7 +864,7 @@ async function loginFromWechatEnv(code, env, context, wechatLoginId) {
return tokenValue;
}
else {
const tokenValue = await createWechatUserAndReturnTokenId(wechatLoginData.user);
const { tokenValue } = await createWechatUserAndReturnTokenId(wechatLoginData.user);
await updateWechatLogin({ successed: true });
return tokenValue;
}
@ -875,7 +874,7 @@ async function loginFromWechatEnv(code, env, context, wechatLoginId) {
// wechatUser存在直接登录
if (wechatUser) {
const tokenValue = await setUpTokenAndUser(env, context, 'wechatUser', wechatUser.id, undefined, wechatUser.user);
await updateWechatLogin({ userId: wechatUser.userId, successed: true });
await updateWechatLogin({ userId: wechatUser.userId, wechatUserId: wechatUser.id, successed: true });
return tokenValue;
}
else {
@ -890,8 +889,8 @@ async function loginFromWechatEnv(code, env, context, wechatLoginId) {
action: 'create',
data: userData,
}, {});
const tokenValue = await createWechatUserAndReturnTokenId(userData);
await updateWechatLogin({ userId, successed: true });
const { tokenValue, wechatUserId } = await createWechatUserAndReturnTokenId(userData, wechatLoginId);
await updateWechatLogin({ userId, wechatUserId, successed: true });
return tokenValue;
}
}
@ -965,7 +964,7 @@ async function loginFromWechatEnv(code, env, context, wechatLoginId) {
}
}
// 到这里都是要同时创建wechatUser和user对象了
return await createWechatUserAndReturnTokenId();
return (await createWechatUserAndReturnTokenId()).tokenValue;
}
/**
* 公众号授权登录
@ -976,9 +975,24 @@ export async function loginWechat({ code, env, wechatLoginId, }, context) {
const closeRootMode = context.openRootMode();
const tokenValue = await loginFromWechatEnv(code, env, context, wechatLoginId);
const [tokenInfo] = await loadTokenInfo(tokenValue, context);
assert(tokenInfo.entity === 'wechatUser');
assert(tokenInfo.entity === 'wechatUser' || tokenInfo.entity === 'wechatLogin');
await context.setTokenValue(tokenValue);
await tryRefreshWechatPublicUserInfo(tokenInfo.entityId, context);
if (tokenInfo.entity === 'wechatUser') {
await tryRefreshWechatPublicUserInfo(tokenInfo.entityId, context);
}
else if (tokenInfo.entity === 'wechatLogin') {
const [wechatLogin] = await context.select('wechatLogin', {
data: {
id: 1,
wechatUserId: 1,
},
filter: {
id: tokenInfo.entityId,
},
}, {});
assert(wechatLogin?.wechatUserId);
await tryRefreshWechatPublicUserInfo(wechatLogin.wechatUserId, context);
}
closeRootMode();
return tokenValue;
}
@ -1407,8 +1421,8 @@ export async function refreshToken(params, context) {
// 只有server模式去刷新token
// 'development' | 'production' | 'staging'
const intervals = {
development: 7200 * 1000,
staging: 600 * 1000,
development: 7200 * 1000, // 2小时
staging: 600 * 1000, // 十分钟
production: 600 * 1000, // 十分钟
};
const application = context.getApplication();

View File

@ -4,6 +4,8 @@ import { Schema as User } from './User';
import { Schema as WechatQrCode } from './WechatQrCode';
import { QrCodeType } from '../types/Config';
import { EntityDesc } from 'oak-domain/lib/types/EntityDesc';
import { Schema as Token } from './Token';
import { Schema as WechatUser } from './WechatUser';
export interface Schema extends EntityShape {
user?: User;
type: 'bind' | 'login';
@ -13,6 +15,8 @@ export interface Schema extends EntityShape {
expiresAt?: Datetime;
expired?: Boolean;
codes: Array<WechatQrCode>;
tokens?: Array<Token>;
wechatUser?: WechatUser;
}
export type Action = 'success';
export declare const entityDesc: EntityDesc<Schema, Action, '', {

View File

@ -11,6 +11,8 @@ export const entityDesc = {
expired: '是否过期',
expiresAt: '过期时间',
qrCodeType: '二维码类型',
tokens: '相关令牌',
wechatUser: '微信用户',
},
action: {
success: '成功',

View File

@ -1,6 +1,7 @@
import { EntityDict } from '../oak-app-domain';
import { NativeEnv, WebEnv, WechatMpEnv } from 'oak-domain/lib/types/Environment';
import { BRC } from '../types/RuntimeCxt';
export declare function sendEmail(): void;
export declare function loginByMobile<ED extends EntityDict>(params: {
captcha?: string;
password?: string;

View File

@ -1,6 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.refreshToken = exports.wakeupParasite = exports.logout = exports.getWechatMpUserPhoneNumber = exports.switchTo = exports.sendCaptcha = exports.syncUserInfoWechatMp = exports.loginWechatMp = exports.loginWechat = exports.loginByWechat = exports.refreshWechatPublicUserInfo = exports.loginByMobile = void 0;
exports.sendEmail = sendEmail;
exports.loginByMobile = loginByMobile;
exports.refreshWechatPublicUserInfo = refreshWechatPublicUserInfo;
exports.loginByWechat = loginByWechat;
exports.loginWechat = loginWechat;
exports.loginWechatMp = loginWechatMp;
exports.syncUserInfoWechatMp = syncUserInfoWechatMp;
exports.sendCaptcha = sendCaptcha;
exports.switchTo = switchTo;
exports.getWechatMpUserPhoneNumber = getWechatMpUserPhoneNumber;
exports.logout = logout;
exports.wakeupParasite = wakeupParasite;
exports.refreshToken = refreshToken;
const tslib_1 = require("tslib");
const uuid_1 = require("oak-domain/lib/utils/uuid");
const WechatSDK_1 = tslib_1.__importDefault(require("oak-external-sdk/lib/WechatSDK"));
@ -13,6 +25,10 @@ const Projection_1 = require("../types/Projection");
const sms_1 = require("../utils/sms");
const user_1 = require("./user");
const lodash_1 = require("oak-domain/lib/utils/lodash");
const email_1 = require("../utils/email");
function sendEmail() {
(0, email_1.sendEmail)();
}
async function makeDistinguishException(userId, context, message) {
const [user] = await context.select('user', {
data: {
@ -533,7 +549,6 @@ async function loginByMobile(params, context) {
closeRootMode();
return tokenValue;
}
exports.loginByMobile = loginByMobile;
async function setUserInfoFromWechat(user, userInfo, context) {
const application = context.getApplication();
const applicationId = context.getApplicationId();
@ -687,24 +702,11 @@ async function refreshWechatPublicUserInfo({}, context) {
(0, assert_1.assert)(token.entityId);
return await tryRefreshWechatPublicUserInfo(token.entityId, context);
}
exports.refreshWechatPublicUserInfo = refreshWechatPublicUserInfo;
// 用户在微信端授权登录后在web端触发该方法
async function loginByWechat(params, context) {
const { wechatLoginId, env } = params;
const closeRootMode = context.openRootMode();
const [wechatLoginData] = await context.select('wechatLogin', {
data: {
id: 1,
userId: 1,
type: 1,
},
filter: {
id: wechatLoginId,
},
}, {
dontCollect: true,
});
const [wechatUserLogin] = await context.select('wechatUser', {
data: {
id: 1,
userId: 1,
@ -716,19 +718,19 @@ async function loginByWechat(params, context) {
refId: 1,
isRoot: 1,
},
type: 1,
},
filter: {
userId: wechatLoginData.userId,
id: wechatLoginId,
},
}, {
dontCollect: true,
});
const tokenValue = await setUpTokenAndUser(env, context, 'wechatUser', wechatUserLogin.id, undefined, wechatUserLogin.user);
const tokenValue = await setUpTokenAndUser(env, context, 'wechatLogin', wechatLoginId, undefined, wechatLoginData.user);
await loadTokenInfo(tokenValue, context);
closeRootMode();
return tokenValue;
}
exports.loginByWechat = loginByWechat;
async function loginFromWechatEnv(code, env, context, wechatLoginId) {
const application = context.getApplication();
const { type, config, systemId } = application;
@ -761,7 +763,7 @@ async function loginFromWechatEnv(code, env, context, wechatLoginId) {
wechatMp: 'mp',
native: 'native',
};
const createWechatUserAndReturnTokenId = async (user) => {
const createWechatUserAndReturnTokenId = async (user, wechatLoginId) => {
const wechatUserCreateData = {
id: await (0, uuid_1.generateNewIdAsync)(),
unionId,
@ -770,8 +772,14 @@ async function loginFromWechatEnv(code, env, context, wechatLoginId) {
applicationId: application.id,
...wechatUserData,
};
const tokenValue = await setUpTokenAndUser(env, context, 'wechatUser', undefined, wechatUserCreateData, user);
return tokenValue;
let tokenValue;
if (wechatLoginId) {
tokenValue = await setUpTokenAndUser(env, context, 'wechatLogin', wechatLoginId, undefined, user);
}
else {
tokenValue = await setUpTokenAndUser(env, context, 'wechatUser', undefined, wechatUserCreateData, user);
}
return { tokenValue, wechatUserId: wechatUserCreateData.id };
};
// 扫码者
const [wechatUser] = await context.select('wechatUser', {
@ -872,7 +880,7 @@ async function loginFromWechatEnv(code, env, context, wechatLoginId) {
return tokenValue;
}
else {
const tokenValue = await createWechatUserAndReturnTokenId(wechatLoginData.user);
const { tokenValue } = await createWechatUserAndReturnTokenId(wechatLoginData.user);
await updateWechatLogin({ successed: true });
return tokenValue;
}
@ -882,7 +890,7 @@ async function loginFromWechatEnv(code, env, context, wechatLoginId) {
// wechatUser存在直接登录
if (wechatUser) {
const tokenValue = await setUpTokenAndUser(env, context, 'wechatUser', wechatUser.id, undefined, wechatUser.user);
await updateWechatLogin({ userId: wechatUser.userId, successed: true });
await updateWechatLogin({ userId: wechatUser.userId, wechatUserId: wechatUser.id, successed: true });
return tokenValue;
}
else {
@ -897,8 +905,8 @@ async function loginFromWechatEnv(code, env, context, wechatLoginId) {
action: 'create',
data: userData,
}, {});
const tokenValue = await createWechatUserAndReturnTokenId(userData);
await updateWechatLogin({ userId, successed: true });
const { tokenValue, wechatUserId } = await createWechatUserAndReturnTokenId(userData, wechatLoginId);
await updateWechatLogin({ userId, wechatUserId, successed: true });
return tokenValue;
}
}
@ -972,7 +980,7 @@ async function loginFromWechatEnv(code, env, context, wechatLoginId) {
}
}
// 到这里都是要同时创建wechatUser和user对象了
return await createWechatUserAndReturnTokenId();
return (await createWechatUserAndReturnTokenId()).tokenValue;
}
/**
* 公众号授权登录
@ -983,13 +991,27 @@ async function loginWechat({ code, env, wechatLoginId, }, context) {
const closeRootMode = context.openRootMode();
const tokenValue = await loginFromWechatEnv(code, env, context, wechatLoginId);
const [tokenInfo] = await loadTokenInfo(tokenValue, context);
(0, assert_1.assert)(tokenInfo.entity === 'wechatUser');
(0, assert_1.assert)(tokenInfo.entity === 'wechatUser' || tokenInfo.entity === 'wechatLogin');
await context.setTokenValue(tokenValue);
await tryRefreshWechatPublicUserInfo(tokenInfo.entityId, context);
if (tokenInfo.entity === 'wechatUser') {
await tryRefreshWechatPublicUserInfo(tokenInfo.entityId, context);
}
else if (tokenInfo.entity === 'wechatLogin') {
const [wechatLogin] = await context.select('wechatLogin', {
data: {
id: 1,
wechatUserId: 1,
},
filter: {
id: tokenInfo.entityId,
},
}, {});
(0, assert_1.assert)(wechatLogin?.wechatUserId);
await tryRefreshWechatPublicUserInfo(wechatLogin.wechatUserId, context);
}
closeRootMode();
return tokenValue;
}
exports.loginWechat = loginWechat;
/**
* 小程序授权登录
* @param param0
@ -1003,7 +1025,6 @@ async function loginWechatMp({ code, env, }, context) {
closeRootMode();
return tokenValue;
}
exports.loginWechatMp = loginWechatMp;
/**
* 同步从wx.getUserProfile拿到的用户信息
* @param param0
@ -1057,7 +1078,6 @@ async function syncUserInfoWechatMp({ nickname, avatarUrl, encryptedData, iv, si
// 实测发现解密出来的和userInfo完全一致……
await setUserInfoFromWechat(user, { nickname, avatar: avatarUrl }, context);
}
exports.syncUserInfoWechatMp = syncUserInfoWechatMp;
async function sendCaptcha({ mobile, env, type: type2, }, context) {
const { type } = env;
// assert(type === 'web' || type === 'native');
@ -1223,7 +1243,6 @@ async function sendCaptcha({ mobile, env, type: type2, }, context) {
}
}
}
exports.sendCaptcha = sendCaptcha;
async function switchTo({ userId }, context) {
const reallyRoot = context.isReallyRoot();
if (!reallyRoot) {
@ -1245,7 +1264,6 @@ async function switchTo({ userId }, context) {
},
}, {});
}
exports.switchTo = switchTo;
async function getWechatMpUserPhoneNumber({ code, env }, context) {
const application = context.getApplication();
const { type, config, systemId } = application;
@ -1261,7 +1279,6 @@ async function getWechatMpUserPhoneNumber({ code, env }, context) {
closeRootMode();
return reuslt;
}
exports.getWechatMpUserPhoneNumber = getWechatMpUserPhoneNumber;
async function logout(params, context) {
const { tokenValue } = params;
if (tokenValue) {
@ -1284,7 +1301,6 @@ async function logout(params, context) {
closeRootMode();
}
}
exports.logout = logout;
/**
* 创建一个当前parasite上的token
* @param params
@ -1351,7 +1367,6 @@ async function wakeupParasite(params, context) {
closeRootMode();
return tokenValue;
}
exports.wakeupParasite = wakeupParasite;
/**
* todo 检查登录环境一致性同一个token不能跨越不同设备
* @param env1
@ -1422,8 +1437,8 @@ async function refreshToken(params, context) {
// 只有server模式去刷新token
// 'development' | 'production' | 'staging'
const intervals = {
development: 7200 * 1000,
staging: 600 * 1000,
development: 7200 * 1000, // 2小时
staging: 600 * 1000, // 十分钟
production: 600 * 1000, // 十分钟
};
const application = context.getApplication();
@ -1457,4 +1472,3 @@ async function refreshToken(params, context) {
closeRootMode();
return tokenValue;
}
exports.refreshToken = refreshToken;

View File

@ -4,6 +4,8 @@ import { Schema as User } from './User';
import { Schema as WechatQrCode } from './WechatQrCode';
import { QrCodeType } from '../types/Config';
import { EntityDesc } from 'oak-domain/lib/types/EntityDesc';
import { Schema as Token } from './Token';
import { Schema as WechatUser } from './WechatUser';
export interface Schema extends EntityShape {
user?: User;
type: 'bind' | 'login';
@ -13,6 +15,8 @@ export interface Schema extends EntityShape {
expiresAt?: Datetime;
expired?: Boolean;
codes: Array<WechatQrCode>;
tokens?: Array<Token>;
wechatUser?: WechatUser;
}
export type Action = 'success';
export declare const entityDesc: EntityDesc<Schema, Action, '', {

View File

@ -14,6 +14,8 @@ exports.entityDesc = {
expired: '是否过期',
expiresAt: '过期时间',
qrCodeType: '二维码类型',
tokens: '相关令牌',
wechatUser: '微信用户',
},
action: {
success: '成功',

View File

@ -39,6 +39,11 @@ import { mergeUser } from './user';
import { cloneDeep, pick } from 'oak-domain/lib/utils/lodash';
import { BRC } from '../types/RuntimeCxt';
import { SmsConfig } from '../entities/Passport';
import { sendEmail as sendEmailFn } from '../utils/email';
export function sendEmail() {
sendEmailFn();
}
async function makeDistinguishException<ED extends EntityDict>(userId: string, context: BRC<ED>, message?: string) {
const [user] = await context.select(
@ -948,6 +953,14 @@ export async function loginByWechat<ED extends EntityDict>(
data: {
id: 1,
userId: 1,
user: {
id: 1,
name: 1,
nickname: 1,
userState: 1,
refId: 1,
isRoot: 1,
},
type: 1,
},
filter: {
@ -958,36 +971,13 @@ export async function loginByWechat<ED extends EntityDict>(
dontCollect: true,
}
);
const [wechatUserLogin] = await context.select(
'wechatUser',
{
data: {
id: 1,
userId: 1,
user: {
id: 1,
name: 1,
nickname: 1,
userState: 1,
refId: 1,
isRoot: 1,
},
},
filter: {
userId: wechatLoginData.userId!,
},
},
{
dontCollect: true,
}
);
const tokenValue = await setUpTokenAndUser<ED>(
env,
context,
'wechatUser',
wechatUserLogin.id,
'wechatLogin',
wechatLoginId,
undefined,
(wechatUserLogin as EntityDict['wechatUser']['Schema']).user!
wechatLoginData.user!
);
await loadTokenInfo<ED>(tokenValue, context);
closeRootMode();
@ -1039,7 +1029,8 @@ async function loginFromWechatEnv<ED extends EntityDict>(
};
const createWechatUserAndReturnTokenId = async (
user?: EntityDict['user']['Schema']
user?: EntityDict['user']['Schema'],
wechatLoginId?: string,
) => {
const wechatUserCreateData: CreateWechatUser = {
id: await generateNewIdAsync(),
@ -1050,15 +1041,27 @@ async function loginFromWechatEnv<ED extends EntityDict>(
...wechatUserData,
};
const tokenValue = await setUpTokenAndUser<ED>(
env,
context,
'wechatUser',
undefined,
wechatUserCreateData,
user
);
return tokenValue;
let tokenValue;
if (wechatLoginId) {
tokenValue = await setUpTokenAndUser<ED>(
env,
context,
'wechatLogin',
wechatLoginId,
undefined,
user
);
} else {
tokenValue = await setUpTokenAndUser<ED>(
env,
context,
'wechatUser',
undefined,
wechatUserCreateData,
user,
)
}
return { tokenValue, wechatUserId: wechatUserCreateData.id };
};
// 扫码者
@ -1186,8 +1189,8 @@ async function loginFromWechatEnv<ED extends EntityDict>(
await updateWechatLogin({ successed: true });
return tokenValue;
} else {
const tokenValue = await createWechatUserAndReturnTokenId(
wechatLoginData.user!
const { tokenValue } = await createWechatUserAndReturnTokenId(
wechatLoginData.user!,
);
await updateWechatLogin({ successed: true });
return tokenValue;
@ -1205,7 +1208,7 @@ async function loginFromWechatEnv<ED extends EntityDict>(
undefined,
wechatUser.user!
);
await updateWechatLogin({ userId: wechatUser.userId, successed: true });
await updateWechatLogin({ userId: wechatUser.userId, wechatUserId: wechatUser.id, successed: true });
return tokenValue;
} else {
// 创建user和wechatUser(绑定并登录)
@ -1223,10 +1226,11 @@ async function loginFromWechatEnv<ED extends EntityDict>(
},
{}
);
const tokenValue = await createWechatUserAndReturnTokenId(
userData as EntityDict['user']['Schema']
const { tokenValue, wechatUserId } = await createWechatUserAndReturnTokenId(
userData as EntityDict['user']['Schema'],
wechatLoginId,
);
await updateWechatLogin({ userId, successed: true });
await updateWechatLogin({ userId, wechatUserId, successed: true });
return tokenValue;
}
}
@ -1328,7 +1332,7 @@ async function loginFromWechatEnv<ED extends EntityDict>(
}
// 到这里都是要同时创建wechatUser和user对象了
return await createWechatUserAndReturnTokenId();
return (await createWechatUserAndReturnTokenId()).tokenValue;
}
/**
@ -1356,9 +1360,26 @@ export async function loginWechat<ED extends EntityDict>(
wechatLoginId
);
const [tokenInfo] = await loadTokenInfo<ED>(tokenValue, context);
assert(tokenInfo.entity === 'wechatUser');
assert(tokenInfo.entity === 'wechatUser' || tokenInfo.entity === 'wechatLogin');
await context.setTokenValue(tokenValue);
await tryRefreshWechatPublicUserInfo<ED>(tokenInfo.entityId!, context);
if (tokenInfo.entity === 'wechatUser') {
await tryRefreshWechatPublicUserInfo<ED>(tokenInfo.entityId!, context);
} else if (tokenInfo.entity === 'wechatLogin') {
const [wechatLogin] = await context.select('wechatLogin',
{
data: {
id: 1,
wechatUserId: 1,
},
filter: {
id: tokenInfo.entityId,
},
},
{}
)
assert(wechatLogin?.wechatUserId);
await tryRefreshWechatPublicUserInfo<ED>(wechatLogin.wechatUserId, context);
}
closeRootMode();
return tokenValue;

View File

@ -4,6 +4,8 @@ import { Schema as User } from './User';
import { Schema as WechatQrCode } from './WechatQrCode';
import { QrCodeType } from '../types/Config';
import { EntityDesc } from 'oak-domain/lib/types/EntityDesc';
import { Schema as Token } from './Token';
import { Schema as WechatUser } from './WechatUser';
export interface Schema extends EntityShape {
user?: User;
@ -14,6 +16,8 @@ export interface Schema extends EntityShape {
expiresAt?: Datetime;
expired?: Boolean;
codes: Array<WechatQrCode>;
tokens?: Array<Token>;
wechatUser?: WechatUser;
}
export type Action = 'success';
@ -40,6 +44,8 @@ export const entityDesc: EntityDesc<
expired: '是否过期',
expiresAt: '过期时间',
qrCodeType: '二维码类型',
tokens: '相关令牌',
wechatUser: '微信用户',
},
action: {
success: '成功',