pull/148/head
xiaojunnuo 2024-08-24 23:48:26 +08:00
parent c28f3cdcf7
commit 86ebbcb9bb
5 changed files with 62 additions and 21 deletions

View File

@ -19,14 +19,14 @@ type License = {
duration: number;
version: number;
secret: string;
level: number;
vipType: string;
signature: string;
};
class LicenseHolder {
isPlus = false;
expireTime = 0;
level = 1;
vipType = "";
message?: string = undefined;
secret?: string = undefined;
}
@ -46,11 +46,11 @@ class LicenseVerifier {
holder.isPlus = true;
holder.expireTime = info.expireTime;
holder.secret = info.secret;
holder.level = info.level;
holder.vipType = info.vipType;
} else {
holder.isPlus = false;
holder.expireTime = 0;
holder.level = 1;
holder.vipType = "";
holder.message = info.message;
holder.secret = undefined;
}
@ -69,13 +69,13 @@ class LicenseVerifier {
return this.setPlus(false);
}
const licenseJson = Buffer.from(Buffer.from(license, "hex").toString(), "base64").toString();
const licenseJson = Buffer.from(license, "base64").toString();
const json: License = JSON.parse(licenseJson);
if (json.expireTime < Date.now()) {
logger.warn("授权已过期");
return this.setPlus(false, { message: "授权已过期" });
}
const content = `${appKey},${this.licenseReq.subjectId},${json.code},${json.secret},${json.level},${json.activeTime},${json.duration},${json.expireTime},${json.version}`;
const content = `${appKey},${this.licenseReq.subjectId},${json.code},${json.secret},${json.vipType},${json.activeTime},${json.duration},${json.expireTime},${json.version}`;
// content := fmt.Sprintf("%s,%s,%s,%s,%d,%d,%d,%d,%d", entity.AppKey, entity.SubjectId, entity.Code, entity.Secret, entity.Level, entity.ActiveTime, entity.Duration, entity.ExpireTime, entity.Version)
//z4nXOeTeSnnpUpnmsV,_m9jFTdNHktdaEN4xBDw_,HZz7rAAR3h3zGlDMhScO1wGBYPjXpZ9S_1,uUpr9I8p6K3jWSzu2Wh5NECvgG2FNynU,0,1724199847470,365,1787271324416,1
logger.debug("content:", content);
@ -89,7 +89,7 @@ class LicenseVerifier {
logger.info(`授权校验成功,到期时间:${dayjs(json.expireTime).format("YYYY-MM-DD HH:mm:ss")}`);
return this.setPlus(true, {
expireTime: json.expireTime,
level: json.level || 1,
vipType: json.vipType || "plus",
secret: json.secret,
});
}
@ -104,18 +104,27 @@ class LicenseVerifier {
const verifier = new LicenseVerifier();
export function isPlus() {
return holder.isPlus;
return holder.isPlus && holder.expireTime > Date.now();
}
export function isCommercial() {
return holder.isPlus && holder.vipType === "comm" && holder.expireTime > Date.now();
}
export function getPlusInfo() {
return {
isPlus: holder.isPlus,
level: holder.level,
vipType: holder.vipType,
expireTime: holder.expireTime,
secret: holder.secret,
};
}
export async function verify(req: LicenseVerifyReq) {
return await verifier.reVerify(req);
try {
return await verifier.reVerify(req);
} catch (e) {
logger.error(e);
return verifier.setPlus(false, { message: "授权校验失败" });
}
}

View File

@ -6,20 +6,41 @@
<span v-if="userStore.plusInfo?.isPlus">
<a-tooltip>
<template #title> 到期时间{{ expireTime }} </template>
<span @click="openUpgrade"></span>
<span @click="openUpgrade">{{ texts.plus }}</span>
</a-tooltip>
</span>
<span v-else @click="openUpgrade"> </span>
<span v-else @click="openUpgrade"> {{ texts.free }} </span>
</div>
</div>
</template>
<script lang="tsx" setup>
import { ref, reactive } from "vue";
import { ref, reactive, computed } from "vue";
import { useUserStore } from "/src/store/modules/user";
import dayjs from "dayjs";
import { message, Modal } from "ant-design-vue";
import * as api from "./api";
const props = defineProps<{
mode: "button" | "nav";
}>();
type Texts = {
plus: string;
free: string;
};
const texts = computed<Texts>(() => {
if (props.mode === "button") {
return {
plus: "已开通",
free: "专业版功能"
};
} else {
return {
plus: "专业版",
free: "免费版,立即升级"
};
}
});
const userStore = useUserStore();
const expireTime = ref("");
if (userStore.plusInfo?.isPlus) {
@ -91,6 +112,7 @@ function openUpgrade() {
align-items: center;
justify-content: center;
height: 100%;
cursor: pointer;
&.isPlus {
color: #c5913f;
}

View File

@ -14,11 +14,11 @@
@finish-failed="onFinishFailed"
>
<a-form-item label="使用邮件代理" name="usePlus">
<a-switch v-model:checked="formState.usePlus" :disabled="!userStore.isPlus" />
<div class="helper">专业版功能免除繁琐的邮件配置直接发邮件</div>
<div>
<vip-button></vip-button>
<div class="flex-o">
<a-switch v-model:checked="formState.usePlus" :disabled="!userStore.isPlus" />
<vip-button class="ml-5" mode="button"></vip-button>
</div>
<div class="helper">专业版功能免除繁琐的邮件配置直接发邮件</div>
</a-form-item>
<template v-if="!formState.usePlus">
<a-form-item label="SMTP域名" name="host" :rules="[{ required: true, message: '请输入smtp域名或ip' }]">

View File

@ -1,10 +1,10 @@
import { MidwayEnvironmentService } from '@midwayjs/core';
import { Controller, Get, Inject, Provide } from '@midwayjs/core';
import { logger } from '../utils/logger.js';
import { Constants } from '../basic/constants.js';
import { logger } from '../../../utils/logger.js';
import { Constants } from '../../../basic/constants.js';
@Provide()
@Controller('/hello')
@Controller('/home')
export class HomeController {
@Inject()
environmentService: MidwayEnvironmentService;

View File

@ -1,7 +1,7 @@
import { Config, Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
import { SysSettingsService } from '../../system/service/sys-settings-service.js';
import { SysInstallInfo } from '../../system/service/models.js';
import { appKey, getPlusInfo } from '@certd/pipeline';
import { appKey, getPlusInfo, isPlus } from '@certd/pipeline';
import * as crypto from 'crypto';
import { request } from '../../../utils/http.js';
import { logger } from '../../../utils/logger.js';
@ -20,6 +20,9 @@ export class PlusService {
}
async request(config: any) {
if (!isPlus()) {
throw new Error('您还不是专业版,请先激活专业版');
}
const { url, data } = config;
const timestamps = Date.now();
const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo);
@ -51,6 +54,13 @@ export class PlusService {
const params = JSON.stringify(body);
const plusInfo = getPlusInfo();
const secret = plusInfo.secret;
if (!secret) {
const randomTime = Math.floor(Math.random() * 3 * 60 * 1000 + 30 * 1000);
setTimeout(() => {
process.exit();
}, randomTime);
return 'xxxxx';
}
const content = `${params}.${timestamps}.${secret}`;
// sha256