@certd/plus-core 1.27.0 → 1.27.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
7
+
8
+ **Note:** Version bump only for package @certd/plus-core
9
+
10
+ ## [1.27.1](https://github.com/certd/certd/compare/v1.27.0...v1.27.1) (2024-11-04)
11
+
12
+ **Note:** Version bump only for package @certd/plus-core
13
+
6
14
  # [1.27.0](https://github.com/certd/certd/compare/v1.26.16...v1.27.0) (2024-10-31)
7
15
 
8
16
  **Note:** Version bump only for package @certd/plus-core
@@ -0,0 +1,2 @@
1
+ export declare function checkPlus(): void;
2
+ export declare function checkComm(): void;
package/dist/d/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
- export * from "./license.js";
2
1
  export * from "./logger.js";
3
2
  export * from "./service.js";
3
+ export * from "./expose.js";
4
+ export * from "./license.js";
@@ -1,12 +1,16 @@
1
- import { PlusRequestService } from "./service.js";
2
1
  export declare const AppKey: string;
2
+ export type CheckRes = {
3
+ ok: boolean;
4
+ message?: string;
5
+ };
3
6
  export type LicenseVerifyReq = {
4
7
  subjectId: string;
5
8
  license: string;
6
9
  bindUrl?: string;
7
- plusRequestService?: PlusRequestService;
10
+ doCheckFromRemote: () => Promise<CheckRes>;
8
11
  };
9
12
  export declare function isPlus(): boolean;
13
+ export declare function getSecret(): string;
10
14
  export declare function isComm(): boolean;
11
15
  export declare function getPlusInfo(): {
12
16
  isPlus: boolean;
@@ -15,7 +19,10 @@ export declare function getPlusInfo(): {
15
19
  expireTime: number;
16
20
  secret: string;
17
21
  };
22
+ export declare function getLicense(): any;
23
+ export declare function getLicenseReq(): any;
18
24
  export declare function verify(req: LicenseVerifyReq): Promise<{
25
+ verified: boolean;
19
26
  isPlus: boolean;
20
27
  isComm: boolean;
21
28
  expireTime: number;
@@ -1,18 +1,46 @@
1
- import { HttpClient, ILogger } from "@certd/basic";
1
+ import { HttpClient, HttpRequestConfig, ILogger } from "@certd/basic";
2
2
  export declare class PlusRequestService {
3
3
  plusServerBaseUrls: string[];
4
4
  _validPlusServerBaseUrl: string;
5
5
  _lastCheckTime: number;
6
6
  http: HttpClient;
7
7
  logger: ILogger;
8
- subjectId: string;
8
+ siteInfo: {
9
+ subjectId: string;
10
+ bindUrl?: string;
11
+ installTime: number;
12
+ };
13
+ saveLicense: any;
9
14
  constructor(opts: {
10
- plusServerBaseUrls: string[];
11
15
  subjectId: string;
16
+ installTime: number;
17
+ bindUrl?: string;
18
+ saveLicense: (license: string) => Promise<void>;
12
19
  });
20
+ getSubjectId(): string;
21
+ verify({ license }: {
22
+ license?: string;
23
+ }): Promise<void>;
13
24
  checkServer(): Promise<any>;
14
25
  sendCheckRequest(baseServerUrl: string): Promise<any>;
15
- requestWithoutSign(config: any, checkOff?: boolean): Promise<any>;
26
+ requestWithoutSign(config: HttpRequestConfig, checkOff?: boolean): Promise<any>;
27
+ getBaseURL(): string;
16
28
  request(config: any): Promise<any>;
17
29
  sign(body: any, timestamps: number): Promise<string>;
30
+ bindUrl(url: string): Promise<any>;
31
+ register(): Promise<any>;
32
+ updateLicense(opts: {
33
+ license: string;
34
+ }): Promise<void>;
35
+ getAccessToken(): Promise<{
36
+ accessToken: any;
37
+ expiresIn: any;
38
+ }>;
39
+ doVipCheck({ bindUrl }: {
40
+ bindUrl?: string;
41
+ }): Promise<{
42
+ ok: any;
43
+ message: any;
44
+ }>;
45
+ active(code: string): Promise<void>;
18
46
  }
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var e=require("node:crypto"),t=require("dayjs"),s=require("@certd/basic");function r(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(s){if("default"!==s){var r=Object.getOwnPropertyDescriptor(e,s);Object.defineProperty(t,s,r.get?r:{enumerable:!0,get:function(){return e[s]}})}})),t.default=e,Object.freeze(t)}var i=r(e);const n={logger:{info(...e){console.log(...e)},warn(...e){console.warn(...e)},error(...e){console.error(...e)},debug(...e){console.log(...e)}}};function o(){return n.logger}let a="LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFQW9VWE1EWUhjdi82WFROWEZFSUI2RlpuR2FER0cwZnR5bTV1dVhPck9NaVl0UkxSb1lvSGMKNVZxenE0N00rdEFqRFBhaTBlOFhWS1c3aytUQUw3MUs0N2JCQVEyWTBxNU5Ya3lYcE5PTVdueVFMYXBwb0tWNgpPMkFJMnpFVURWMVJVa0ZtMFZTVjU0VXNzMDcrdjI2aW5aQU1CWitDMU42eWFDc2tZL3grNnVlNkVRNVcyZXdFCjZOWEhJcUU1bHdEUmU2SXJtdEpnU2doSnlHTS91azIyejN6NGEraFVPVUlWMy9DbEhYV0VhRHBBRFFsakt3NSsKeHR0dURiTHZyUmdzdWp6czB0dEI2OE1SbXE0R0FJL0JtNWVPWkhlNGxFQjBFVVhFUXdVWE1jV1N1VFZSMUE2cApUM21LRGo5MGcwVDFZUlNOdE5TMm9aRzgvRWIwOVlxK3Z3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K",c="kQth6FHM71IPV3qdWc";"false"===process.env.plus_use_prod&&(a="LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFQXY3TGtMaUp1dGM0NzhTU3RaTExjajVGZXh1YjJwR2NLMGxwa0hwVnlZWjhMY29rRFhuUlAKUGQ5UlJSTVRTaGJsbFl2Mzd4QUhOV1ZIQ0ZsWHkrQklVU001bUlBU1NDQTV0azlJNmpZZ2F4bEFDQm1BY0lGMwozKzBjeGZIYVkrVW9YdVluMkZ6YUt2Ym5GdFZIZ0lkMDg4a3d4clZTZzlCT3BDRVZIR1pxR2I5TWN5MXVHVXhUClFTVENCbmpoTWZlZ0p6cXVPYWVOY0ZPSE5tbmtWRWpLTythbTBPeEhNS1lyS3ZnQnVEbzdoVnFENlBFMUd6V3AKZHdwZUV4QXZDSVJxL2pWTkdRK3FtMkRWOVNJZ3U5bmF4MktmSUtFeU50dUFFS1VpekdqL0VmRFhDM1cxMExhegpKaGNYNGw1SUFZU1o3L3JWVmpGbExWSVl0WDU1T054L1Z3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K",c="z4nXOeTeSnnpUpnmsV"),"true"===process.env.plus_off&&(c="12132");const l=c;const u=new class{isPlus=!1;isComm=!1;expireTime=0;vipType="";message=void 0;secret=void 0};u.isPlus=!1,u.isComm=!1;const p=new class{checked=!1;licenseReq=void 0;async reVerify(e){return this.checked=!1,await this.verify(e)}setPlus(e,t={}){return e&&t?(u.isPlus=!0,u.expireTime=t.expireTime,u.secret=t.secret,u.vipType=t.vipType,"comm"===t.vipType&&(u.isComm=!0)):(u.isPlus=!1,u.isComm=!1,u.expireTime=0,u.vipType="",u.message=t.message,u.secret=void 0),{...u}}async verify(e){if(!e.plusRequestService)return console.error("plusRequestService is not set"),this.setPlus(!1);if(this.licenseReq=e,this.checked)return this.setPlus(!1);const s=e?.license;if(!s)return this.checked=!0,this.setPlus(!1);const r=Buffer.from(s,"base64").toString(),i=JSON.parse(r),n=o();if(i.expireTime<Date.now())return n.warn("授权已过期"),this.setPlus(!1,{message:"授权已过期"});const l=`${c},${this.licenseReq.subjectId},${i.code},${i.secret},${i.vipType},${i.activeTime},${i.duration},${i.expireTime},${i.version}`;n.debug("content:",l);const u=Buffer.from(a,"base64").toString(),p=this.verifySignature(l,i.signature,u);return this.checked=!0,p?(n.info(`授权校验成功,到期时间:${t(i.expireTime).format("YYYY-MM-DD HH:mm:ss")}`),this.setPlus(!0,{expireTime:i.expireTime,vipType:i.vipType||"plus",secret:i.secret})):(n.warn("授权校验失败"),this.setPlus(!1,{message:"授权校验失败"}))}verifySignature(t,s,r){const i=e.createVerify("RSA-SHA256");return i.update(t),i.verify(r,s,"base64")}async verifyFromRemote(){if(this.licenseReq?.plusRequestService)try{const e=await this.licenseReq.plusRequestService.request({url:"/activation/subject/vip/check",data:{url:this.licenseReq.bindUrl}});if(1004===e.code)return void console.log("请求参数错误:",e.message);if(e.data?.ok)h()||await this.reVerify(this.licenseReq);else if(!1===e.data?.ok){const t=e.data?.message||e.message;return console.log("vip校验失败,退回基础版:",JSON.stringify(e.data)),this.setPlus(!1,{message:t})}}catch(e){console.error(e.message)}}};function h(){return u.isPlus&&u.expireTime>Date.now()}function d(){return{isPlus:u.isPlus,isComm:u.isComm,vipType:u.vipType,expireTime:u.expireTime,secret:u.secret}}!function(){async function e(){if(!h())return;const e=o();if(e.info("check license"),h()&&!u.secret)return e.info("license 校验失败!!!"),function(){const e=Math.floor(1e3*Math.random()*60*60);setTimeout((()=>{console.log("11111"),process.exit(0)}),e)}();await p.verifyFromRemote()}setInterval((async()=>{await e()}),864e5),setTimeout((async()=>{await e()}),6e4)}();exports.AppKey=l,exports.PlusRequestService=class{plusServerBaseUrls;_validPlusServerBaseUrl;_lastCheckTime=0;http;logger;subjectId;constructor(e){this.plusServerBaseUrls=e.plusServerBaseUrls,this.http=s.http,this.logger=s.logger,this.subjectId=e.subjectId}async checkServer(){if(this._validPlusServerBaseUrl&&Date.now()<this._lastCheckTime+828e5)return!0;for(const e of this.plusServerBaseUrls)try{const t=await this.sendCheckRequest(e);return this._validPlusServerBaseUrl=e,t}catch(t){this.logger.error(`server [${e}] is invalid:`,t)}this._lastCheckTime=Date.now()}async sendCheckRequest(e){const t={appKey:l};return await this.http.request({url:"/activation/app/get",method:"POST",data:t,baseURL:e})}async requestWithoutSign(e,t=!1){return!0!==t&&await this.checkServer(),e.baseURL=this._validPlusServerBaseUrl||this.plusServerBaseUrls[0],e.method=e.method||"POST",await this.http.request(e)}async request(e){if(!h())throw new Error("您还不是专业版,请先激活专业版");const{url:t,data:s}=e,r=Date.now(),i=await this.sign(s,r),n={subjectId:this.subjectId,appKey:l,sign:i,timestamps:r};let o=JSON.stringify(n);o=Buffer.from(o).toString("base64");const a={"Content-Type":"application/json","X-Plus-Subject":o};return await this.requestWithoutSign({url:t,method:"POST",data:s,headers:a})}async sign(e,t){const s=JSON.stringify(e),r=d().secret;if(!r)throw new Error("secret is not set");const n=`${s}.${t}.${r}`,o=i.createHash("sha256").update(n).digest("base64");return this.logger.info("content:",n,"sign:",o),o}},exports.getLogger=o,exports.getPlusInfo=d,exports.isComm=function(){return u.isComm&&u.expireTime>Date.now()},exports.isPlus=h,exports.setLogger=function(e){n.logger=e},exports.verify=async function(e){try{const t=await p.reVerify(e);return h()&&setTimeout((()=>{p.verifyFromRemote()}),1e3),t}catch(e){return o().error(e),p.setPlus(!1,{message:"授权校验失败"})}};
1
+ "use strict";var e=require("node:crypto"),t=require("dayjs"),s=require("lodash-es"),i=require("@certd/basic");function r(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(s){if("default"!==s){var i=Object.getOwnPropertyDescriptor(e,s);Object.defineProperty(t,s,i.get?i:{enumerable:!0,get:function(){return e[s]}})}})),t.default=e,Object.freeze(t)}var n=r(e);const c={logger:{info(...e){console.log(...e)},warn(...e){console.warn(...e)},error(...e){console.error(...e)},debug(...e){console.log(...e)}}};function a(e){c.logger=e}function o(){return c.logger}let l="LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFQW9VWE1EWUhjdi82WFROWEZFSUI2RlpuR2FER0cwZnR5bTV1dVhPck9NaVl0UkxSb1lvSGMKNVZxenE0N00rdEFqRFBhaTBlOFhWS1c3aytUQUw3MUs0N2JCQVEyWTBxNU5Ya3lYcE5PTVdueVFMYXBwb0tWNgpPMkFJMnpFVURWMVJVa0ZtMFZTVjU0VXNzMDcrdjI2aW5aQU1CWitDMU42eWFDc2tZL3grNnVlNkVRNVcyZXdFCjZOWEhJcUU1bHdEUmU2SXJtdEpnU2doSnlHTS91azIyejN6NGEraFVPVUlWMy9DbEhYV0VhRHBBRFFsakt3NSsKeHR0dURiTHZyUmdzdWp6czB0dEI2OE1SbXE0R0FJL0JtNWVPWkhlNGxFQjBFVVhFUXdVWE1jV1N1VFZSMUE2cApUM21LRGo5MGcwVDFZUlNOdE5TMm9aRzgvRWIwOVlxK3Z3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K",u="kQth6FHM71IPV3qdWc";"false"===process.env.plus_use_prod&&(l="LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFQXY3TGtMaUp1dGM0NzhTU3RaTExjajVGZXh1YjJwR2NLMGxwa0hwVnlZWjhMY29rRFhuUlAKUGQ5UlJSTVRTaGJsbFl2Mzd4QUhOV1ZIQ0ZsWHkrQklVU001bUlBU1NDQTV0azlJNmpZZ2F4bEFDQm1BY0lGMwozKzBjeGZIYVkrVW9YdVluMkZ6YUt2Ym5GdFZIZ0lkMDg4a3d4clZTZzlCT3BDRVZIR1pxR2I5TWN5MXVHVXhUClFTVENCbmpoTWZlZ0p6cXVPYWVOY0ZPSE5tbmtWRWpLTythbTBPeEhNS1lyS3ZnQnVEbzdoVnFENlBFMUd6V3AKZHdwZUV4QXZDSVJxL2pWTkdRK3FtMkRWOVNJZ3U5bmF4MktmSUtFeU50dUFFS1VpekdqL0VmRFhDM1cxMExhegpKaGNYNGw1SUFZU1o3L3JWVmpGbExWSVl0WDU1T054L1Z3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K",u="z4nXOeTeSnnpUpnmsV"),"true"===process.env.plus_off&&(u="12132");const h=u;const p=new class{verified=!1;isPlus=!1;isComm=!1;expireTime=0;vipType="";message=void 0;secret=void 0};p.isPlus=!1,p.isComm=!1;const d=new class{checked=!1;licenseReq=void 0;async reVerify(e){return this.checked=!1,await this.verify(e)}setPlus(e,t={}){return e?(p.verified=!0,p.expireTime=t.expireTime,p.secret=t.secret,p.vipType=t.vipType,p.isPlus=t.vipType&&"free"!==t.vipType,p.isComm="comm"===t.vipType):(p.verified=!1,p.isPlus=!1,p.isComm=!1,p.expireTime=0,p.vipType="",p.message=t.message),{...p}}async verify(e){if(this.licenseReq=e,this.checked)return this.setPlus(!1);const s=e?.license;if(!s)return this.checked=!0,this.setPlus(!1);const i=Buffer.from(s,"base64").toString(),r=JSON.parse(i),n=o(),c=`${u},${this.licenseReq.subjectId},${r.code},${r.secret},${r.vipType},${r.activeTime},${r.duration},${r.expireTime},${r.version}`;n.info("content:",c);const a=Buffer.from(l,"base64").toString(),h=this.verifySignature(c,r.signature,a);return this.checked=!0,h?(n.info(`授权校验成功,到期时间:${t(r.expireTime).format("YYYY-MM-DD HH:mm:ss")}`),this.setPlus(!0,{expireTime:r.expireTime,vipType:r.vipType||"free",secret:r.secret})):(n.warn("授权校验失败"),this.setPlus(!1,{message:"授权校验失败",secret:r.secret}))}verifySignature(t,s,i){const r=e.createVerify("RSA-SHA256");return r.update(t),r.verify(i,s,"base64")}async verifyFromRemote(){try{const e=await this.licenseReq.doCheckFromRemote();if(e.ok)f()||await this.reVerify(this.licenseReq);else if(!1===e.ok){const t=e.message;return console.log("vip校验失败,退回基础版:"+t),this.setPlus(!1,{message:t})}}catch(e){console.error(e.message)}}};function f(){return p.isPlus&&p.expireTime>Date.now()}function m(){return p.secret}function g(){return p.isComm&&p.expireTime>Date.now()}function S(){if(null==d.licenseReq)throw new Error("请先调用verify方法");return s.cloneDeep(d.licenseReq)}async function U(e){try{const t=await d.reVerify(e);return f()&&setTimeout((()=>{d.verifyFromRemote()}),1e3),t}catch(e){return o().error(e),d.setPlus(!1,{message:"授权校验失败"})}}!function(){async function e(){if(!f())return;const e=o();if(e.info("check license"),f()&&!p.secret)return e.info("license 校验失败!!!"),function(){const e=Math.floor(1e3*Math.random()*60*60);setTimeout((()=>{console.log("11111"),process.exit(0)}),e)}();await d.verifyFromRemote()}setInterval((async()=>{await e()}),864e5),setTimeout((async()=>{await e()}),6e4)}();a(i.logger),exports.AppKey=h,exports.PlusRequestService=class{plusServerBaseUrls=["https://api.handfree.work","https://api.ai.docmirror.cn"];_validPlusServerBaseUrl;_lastCheckTime=0;http;logger;siteInfo;saveLicense;constructor(e){this.http=i.http,this.logger=i.logger,this.siteInfo={bindUrl:e.bindUrl,subjectId:e.subjectId,installTime:e.installTime},this.saveLicense=e.saveLicense,process.env.PLUS_SERVER_BASE_URL&&(this.plusServerBaseUrls=[process.env.PLUS_SERVER_BASE_URL])}getSubjectId(){return this.siteInfo.subjectId}async verify({license:e}){if(!e)return;const t=this.siteInfo.bindUrl,s=await U({subjectId:this.getSubjectId(),bindUrl:t,license:e,doCheckFromRemote:async()=>await this.doVipCheck({bindUrl:t})});if(!s.verified){const e=s.message||"授权码校验失败";throw i.logger.error(e),new Error(e)}}async checkServer(){if(this._validPlusServerBaseUrl&&Date.now()<this._lastCheckTime+828e5)return!0;for(const e of this.plusServerBaseUrls)try{const t=await this.sendCheckRequest(e);return this._validPlusServerBaseUrl=e,t}catch(t){this.logger.error(`server [${e}] is invalid:`,t)}this._lastCheckTime=Date.now()}async sendCheckRequest(e){const t={appKey:h};return await this.http.request({url:"/activation/app/get",method:"POST",data:t,baseURL:e})}async requestWithoutSign(e,t=!1){!0!==t&&await this.checkServer(),e.baseURL=this.getBaseURL(),e.method=e.method||"POST";const s=await this.http.request(e);if(!0===e.skipCheckRes)return s;if(0!==s.code)throw new Error("请求失败:"+s.message);return s.data}getBaseURL(){return this._validPlusServerBaseUrl||this.plusServerBaseUrls[0]}async request(e){if(!m())throw new Error("secret不存在");const{url:t,data:s}=e,i=Date.now(),r=await this.sign(s,i),n={subjectId:this.getSubjectId(),appKey:h,sign:r,timestamps:i};let c=JSON.stringify(n);c=Buffer.from(c).toString("base64");const a={"Content-Type":"application/json","X-Plus-Subject":c};return await this.requestWithoutSign({url:t,method:"POST",data:s,headers:a})}async sign(e,t){const s=JSON.stringify(e),i=m();if(!i)throw new Error("secret is not set");const r=`${s}.${t}.${i}`,c=n.createHash("sha256").update(r).digest("base64");return this.logger.info("content:",r,"sign:",c),c}async bindUrl(e){const t=await this.request({url:"/activation/subject/urlBind",data:{subjectId:this.getSubjectId(),appKey:h,url:e}});return this.siteInfo.bindUrl=e,t}async register(){const e=(await this.requestWithoutSign({url:"/activation/subject/register",data:{appKey:h,subjectId:this.getSubjectId(),installTime:this.siteInfo.installTime}})).license;return await this.saveLicense(e),await this.verify({license:e}),e}async updateLicense(e){await this.saveLicense(e.license),await this.verify({license:e.license})}async getAccessToken(){const e=await this.request({url:"/activation/subject/getAccessToken",data:{}});return{accessToken:e.accessToken,expiresIn:e.expiresIn}}async doVipCheck({bindUrl:e}){const t=await this.request({url:"/activation/subject/vip/check",data:{url:e},skipCheckRes:!0});if(1004===t?.code)throw console.log("请求参数错误:",t.message),new Error(t.message);return i.logger.info(JSON.stringify(t.data)),{ok:t?.data?.ok,message:t?.data?.message||t.message}}async active(e){const t={appKey:h,code:e,subjectId:this.getSubjectId()},s=(await this.requestWithoutSign({url:"/activation/active",method:"post",data:t})).license;await this.updateLicense({license:s})}},exports.checkComm=function(){if(!g())throw new Error("此为商业版功能,请升级到商业版")},exports.checkPlus=function(){if(!f())throw new Error("此为专业版功能,请升级到专业版")},exports.getLicense=function(){return S()?.license},exports.getLicenseReq=S,exports.getLogger=o,exports.getPlusInfo=function(){return{isPlus:p.isPlus,isComm:p.isComm,vipType:p.vipType,expireTime:p.expireTime,secret:p.secret}},exports.getSecret=m,exports.isComm=g,exports.isPlus=f,exports.setLogger=a,exports.verify=U;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import*as e from"node:crypto";import{createVerify as t}from"node:crypto";import s from"dayjs";import{http as r,logger as i}from"@certd/basic";const n={logger:{info(...e){console.log(...e)},warn(...e){console.warn(...e)},error(...e){console.error(...e)},debug(...e){console.log(...e)}}};function o(e){n.logger=e}function a(){return n.logger}let c="LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFQW9VWE1EWUhjdi82WFROWEZFSUI2RlpuR2FER0cwZnR5bTV1dVhPck9NaVl0UkxSb1lvSGMKNVZxenE0N00rdEFqRFBhaTBlOFhWS1c3aytUQUw3MUs0N2JCQVEyWTBxNU5Ya3lYcE5PTVdueVFMYXBwb0tWNgpPMkFJMnpFVURWMVJVa0ZtMFZTVjU0VXNzMDcrdjI2aW5aQU1CWitDMU42eWFDc2tZL3grNnVlNkVRNVcyZXdFCjZOWEhJcUU1bHdEUmU2SXJtdEpnU2doSnlHTS91azIyejN6NGEraFVPVUlWMy9DbEhYV0VhRHBBRFFsakt3NSsKeHR0dURiTHZyUmdzdWp6czB0dEI2OE1SbXE0R0FJL0JtNWVPWkhlNGxFQjBFVVhFUXdVWE1jV1N1VFZSMUE2cApUM21LRGo5MGcwVDFZUlNOdE5TMm9aRzgvRWIwOVlxK3Z3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K",l="kQth6FHM71IPV3qdWc";"false"===process.env.plus_use_prod&&(c="LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFQXY3TGtMaUp1dGM0NzhTU3RaTExjajVGZXh1YjJwR2NLMGxwa0hwVnlZWjhMY29rRFhuUlAKUGQ5UlJSTVRTaGJsbFl2Mzd4QUhOV1ZIQ0ZsWHkrQklVU001bUlBU1NDQTV0azlJNmpZZ2F4bEFDQm1BY0lGMwozKzBjeGZIYVkrVW9YdVluMkZ6YUt2Ym5GdFZIZ0lkMDg4a3d4clZTZzlCT3BDRVZIR1pxR2I5TWN5MXVHVXhUClFTVENCbmpoTWZlZ0p6cXVPYWVOY0ZPSE5tbmtWRWpLTythbTBPeEhNS1lyS3ZnQnVEbzdoVnFENlBFMUd6V3AKZHdwZUV4QXZDSVJxL2pWTkdRK3FtMkRWOVNJZ3U5bmF4MktmSUtFeU50dUFFS1VpekdqL0VmRFhDM1cxMExhegpKaGNYNGw1SUFZU1o3L3JWVmpGbExWSVl0WDU1T054L1Z3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K",l="z4nXOeTeSnnpUpnmsV"),"true"===process.env.plus_off&&(l="12132");const u=l;const h=new class{isPlus=!1;isComm=!1;expireTime=0;vipType="";message=void 0;secret=void 0};h.isPlus=!1,h.isComm=!1;const p=new class{checked=!1;licenseReq=void 0;async reVerify(e){return this.checked=!1,await this.verify(e)}setPlus(e,t={}){return e&&t?(h.isPlus=!0,h.expireTime=t.expireTime,h.secret=t.secret,h.vipType=t.vipType,"comm"===t.vipType&&(h.isComm=!0)):(h.isPlus=!1,h.isComm=!1,h.expireTime=0,h.vipType="",h.message=t.message,h.secret=void 0),{...h}}async verify(e){if(!e.plusRequestService)return console.error("plusRequestService is not set"),this.setPlus(!1);if(this.licenseReq=e,this.checked)return this.setPlus(!1);const t=e?.license;if(!t)return this.checked=!0,this.setPlus(!1);const r=Buffer.from(t,"base64").toString(),i=JSON.parse(r),n=a();if(i.expireTime<Date.now())return n.warn("授权已过期"),this.setPlus(!1,{message:"授权已过期"});const o=`${l},${this.licenseReq.subjectId},${i.code},${i.secret},${i.vipType},${i.activeTime},${i.duration},${i.expireTime},${i.version}`;n.debug("content:",o);const u=Buffer.from(c,"base64").toString(),h=this.verifySignature(o,i.signature,u);return this.checked=!0,h?(n.info(`授权校验成功,到期时间:${s(i.expireTime).format("YYYY-MM-DD HH:mm:ss")}`),this.setPlus(!0,{expireTime:i.expireTime,vipType:i.vipType||"plus",secret:i.secret})):(n.warn("授权校验失败"),this.setPlus(!1,{message:"授权校验失败"}))}verifySignature(e,s,r){const i=t("RSA-SHA256");return i.update(e),i.verify(r,s,"base64")}async verifyFromRemote(){if(this.licenseReq?.plusRequestService)try{const e=await this.licenseReq.plusRequestService.request({url:"/activation/subject/vip/check",data:{url:this.licenseReq.bindUrl}});if(1004===e.code)return void console.log("请求参数错误:",e.message);if(e.data?.ok)m()||await this.reVerify(this.licenseReq);else if(!1===e.data?.ok){const t=e.data?.message||e.message;return console.log("vip校验失败,退回基础版:",JSON.stringify(e.data)),this.setPlus(!1,{message:t})}}catch(e){console.error(e.message)}}};function m(){return h.isPlus&&h.expireTime>Date.now()}function d(){return h.isComm&&h.expireTime>Date.now()}function S(){return{isPlus:h.isPlus,isComm:h.isComm,vipType:h.vipType,expireTime:h.expireTime,secret:h.secret}}async function U(e){try{const t=await p.reVerify(e);return m()&&setTimeout((()=>{p.verifyFromRemote()}),1e3),t}catch(e){return a().error(e),p.setPlus(!1,{message:"授权校验失败"})}}!function(){async function e(){if(!m())return;const e=a();if(e.info("check license"),m()&&!h.secret)return e.info("license 校验失败!!!"),function(){const e=Math.floor(1e3*Math.random()*60*60);setTimeout((()=>{console.log("11111"),process.exit(0)}),e)}();await p.verifyFromRemote()}setInterval((async()=>{await e()}),864e5),setTimeout((async()=>{await e()}),6e4)}();class V{plusServerBaseUrls;_validPlusServerBaseUrl;_lastCheckTime=0;http;logger;subjectId;constructor(e){this.plusServerBaseUrls=e.plusServerBaseUrls,this.http=r,this.logger=i,this.subjectId=e.subjectId}async checkServer(){if(this._validPlusServerBaseUrl&&Date.now()<this._lastCheckTime+828e5)return!0;for(const e of this.plusServerBaseUrls)try{const t=await this.sendCheckRequest(e);return this._validPlusServerBaseUrl=e,t}catch(t){this.logger.error(`server [${e}] is invalid:`,t)}this._lastCheckTime=Date.now()}async sendCheckRequest(e){const t={appKey:u};return await this.http.request({url:"/activation/app/get",method:"POST",data:t,baseURL:e})}async requestWithoutSign(e,t=!1){return!0!==t&&await this.checkServer(),e.baseURL=this._validPlusServerBaseUrl||this.plusServerBaseUrls[0],e.method=e.method||"POST",await this.http.request(e)}async request(e){if(!m())throw new Error("您还不是专业版,请先激活专业版");const{url:t,data:s}=e,r=Date.now(),i=await this.sign(s,r),n={subjectId:this.subjectId,appKey:u,sign:i,timestamps:r};let o=JSON.stringify(n);o=Buffer.from(o).toString("base64");const a={"Content-Type":"application/json","X-Plus-Subject":o};return await this.requestWithoutSign({url:t,method:"POST",data:s,headers:a})}async sign(t,s){const r=JSON.stringify(t),i=S().secret;if(!i)throw new Error("secret is not set");const n=`${r}.${s}.${i}`,o=e.createHash("sha256").update(n).digest("base64");return this.logger.info("content:",n,"sign:",o),o}}export{u as AppKey,V as PlusRequestService,a as getLogger,S as getPlusInfo,d as isComm,m as isPlus,o as setLogger,U as verify};
1
+ import*as e from"node:crypto";import{createVerify as t}from"node:crypto";import s from"dayjs";import{cloneDeep as i}from"lodash-es";import{http as r,logger as n}from"@certd/basic";const a={logger:{info(...e){console.log(...e)},warn(...e){console.warn(...e)},error(...e){console.error(...e)},debug(...e){console.log(...e)}}};function c(e){a.logger=e}function o(){return a.logger}let l="LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFQW9VWE1EWUhjdi82WFROWEZFSUI2RlpuR2FER0cwZnR5bTV1dVhPck9NaVl0UkxSb1lvSGMKNVZxenE0N00rdEFqRFBhaTBlOFhWS1c3aytUQUw3MUs0N2JCQVEyWTBxNU5Ya3lYcE5PTVdueVFMYXBwb0tWNgpPMkFJMnpFVURWMVJVa0ZtMFZTVjU0VXNzMDcrdjI2aW5aQU1CWitDMU42eWFDc2tZL3grNnVlNkVRNVcyZXdFCjZOWEhJcUU1bHdEUmU2SXJtdEpnU2doSnlHTS91azIyejN6NGEraFVPVUlWMy9DbEhYV0VhRHBBRFFsakt3NSsKeHR0dURiTHZyUmdzdWp6czB0dEI2OE1SbXE0R0FJL0JtNWVPWkhlNGxFQjBFVVhFUXdVWE1jV1N1VFZSMUE2cApUM21LRGo5MGcwVDFZUlNOdE5TMm9aRzgvRWIwOVlxK3Z3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K",u="kQth6FHM71IPV3qdWc";"false"===process.env.plus_use_prod&&(l="LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFQXY3TGtMaUp1dGM0NzhTU3RaTExjajVGZXh1YjJwR2NLMGxwa0hwVnlZWjhMY29rRFhuUlAKUGQ5UlJSTVRTaGJsbFl2Mzd4QUhOV1ZIQ0ZsWHkrQklVU001bUlBU1NDQTV0azlJNmpZZ2F4bEFDQm1BY0lGMwozKzBjeGZIYVkrVW9YdVluMkZ6YUt2Ym5GdFZIZ0lkMDg4a3d4clZTZzlCT3BDRVZIR1pxR2I5TWN5MXVHVXhUClFTVENCbmpoTWZlZ0p6cXVPYWVOY0ZPSE5tbmtWRWpLTythbTBPeEhNS1lyS3ZnQnVEbzdoVnFENlBFMUd6V3AKZHdwZUV4QXZDSVJxL2pWTkdRK3FtMkRWOVNJZ3U5bmF4MktmSUtFeU50dUFFS1VpekdqL0VmRFhDM1cxMExhegpKaGNYNGw1SUFZU1o3L3JWVmpGbExWSVl0WDU1T054L1Z3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K",u="z4nXOeTeSnnpUpnmsV"),"true"===process.env.plus_off&&(u="12132");const h=u;const d=new class{verified=!1;isPlus=!1;isComm=!1;expireTime=0;vipType="";message=void 0;secret=void 0};d.isPlus=!1,d.isComm=!1;const p=new class{checked=!1;licenseReq=void 0;async reVerify(e){return this.checked=!1,await this.verify(e)}setPlus(e,t={}){return e?(d.verified=!0,d.expireTime=t.expireTime,d.secret=t.secret,d.vipType=t.vipType,d.isPlus=t.vipType&&"free"!==t.vipType,d.isComm="comm"===t.vipType):(d.verified=!1,d.isPlus=!1,d.isComm=!1,d.expireTime=0,d.vipType="",d.message=t.message),{...d}}async verify(e){if(this.licenseReq=e,this.checked)return this.setPlus(!1);const t=e?.license;if(!t)return this.checked=!0,this.setPlus(!1);const i=Buffer.from(t,"base64").toString(),r=JSON.parse(i),n=o(),a=`${u},${this.licenseReq.subjectId},${r.code},${r.secret},${r.vipType},${r.activeTime},${r.duration},${r.expireTime},${r.version}`;n.info("content:",a);const c=Buffer.from(l,"base64").toString(),h=this.verifySignature(a,r.signature,c);return this.checked=!0,h?(n.info(`授权校验成功,到期时间:${s(r.expireTime).format("YYYY-MM-DD HH:mm:ss")}`),this.setPlus(!0,{expireTime:r.expireTime,vipType:r.vipType||"free",secret:r.secret})):(n.warn("授权校验失败"),this.setPlus(!1,{message:"授权校验失败",secret:r.secret}))}verifySignature(e,s,i){const r=t("RSA-SHA256");return r.update(e),r.verify(i,s,"base64")}async verifyFromRemote(){try{const e=await this.licenseReq.doCheckFromRemote();if(e.ok)m()||await this.reVerify(this.licenseReq);else if(!1===e.ok){const t=e.message;return console.log("vip校验失败,退回基础版:"+t),this.setPlus(!1,{message:t})}}catch(e){console.error(e.message)}}};function m(){return d.isPlus&&d.expireTime>Date.now()}function f(){return d.secret}function U(){return d.isComm&&d.expireTime>Date.now()}function S(){return{isPlus:d.isPlus,isComm:d.isComm,vipType:d.vipType,expireTime:d.expireTime,secret:d.secret}}function g(){return T()?.license}function T(){if(null==p.licenseReq)throw new Error("请先调用verify方法");return i(p.licenseReq)}async function v(e){try{const t=await p.reVerify(e);return m()&&setTimeout((()=>{p.verifyFromRemote()}),1e3),t}catch(e){return o().error(e),p.setPlus(!1,{message:"授权校验失败"})}}!function(){async function e(){if(!m())return;const e=o();if(e.info("check license"),m()&&!d.secret)return e.info("license 校验失败!!!"),function(){const e=Math.floor(1e3*Math.random()*60*60);setTimeout((()=>{console.log("11111"),process.exit(0)}),e)}();await p.verifyFromRemote()}setInterval((async()=>{await e()}),864e5),setTimeout((async()=>{await e()}),6e4)}();class y{plusServerBaseUrls=["https://api.handfree.work","https://api.ai.docmirror.cn"];_validPlusServerBaseUrl;_lastCheckTime=0;http;logger;siteInfo;saveLicense;constructor(e){this.http=r,this.logger=n,this.siteInfo={bindUrl:e.bindUrl,subjectId:e.subjectId,installTime:e.installTime},this.saveLicense=e.saveLicense,process.env.PLUS_SERVER_BASE_URL&&(this.plusServerBaseUrls=[process.env.PLUS_SERVER_BASE_URL])}getSubjectId(){return this.siteInfo.subjectId}async verify({license:e}){if(!e)return;const t=this.siteInfo.bindUrl,s=await v({subjectId:this.getSubjectId(),bindUrl:t,license:e,doCheckFromRemote:async()=>await this.doVipCheck({bindUrl:t})});if(!s.verified){const e=s.message||"授权码校验失败";throw n.error(e),new Error(e)}}async checkServer(){if(this._validPlusServerBaseUrl&&Date.now()<this._lastCheckTime+828e5)return!0;for(const e of this.plusServerBaseUrls)try{const t=await this.sendCheckRequest(e);return this._validPlusServerBaseUrl=e,t}catch(t){this.logger.error(`server [${e}] is invalid:`,t)}this._lastCheckTime=Date.now()}async sendCheckRequest(e){const t={appKey:h};return await this.http.request({url:"/activation/app/get",method:"POST",data:t,baseURL:e})}async requestWithoutSign(e,t=!1){!0!==t&&await this.checkServer(),e.baseURL=this.getBaseURL(),e.method=e.method||"POST";const s=await this.http.request(e);if(!0===e.skipCheckRes)return s;if(0!==s.code)throw new Error("请求失败:"+s.message);return s.data}getBaseURL(){return this._validPlusServerBaseUrl||this.plusServerBaseUrls[0]}async request(e){if(!f())throw new Error("secret不存在");const{url:t,data:s}=e,i=Date.now(),r=await this.sign(s,i),n={subjectId:this.getSubjectId(),appKey:h,sign:r,timestamps:i};let a=JSON.stringify(n);a=Buffer.from(a).toString("base64");const c={"Content-Type":"application/json","X-Plus-Subject":a};return await this.requestWithoutSign({url:t,method:"POST",data:s,headers:c})}async sign(t,s){const i=JSON.stringify(t),r=f();if(!r)throw new Error("secret is not set");const n=`${i}.${s}.${r}`,a=e.createHash("sha256").update(n).digest("base64");return this.logger.info("content:",n,"sign:",a),a}async bindUrl(e){const t=await this.request({url:"/activation/subject/urlBind",data:{subjectId:this.getSubjectId(),appKey:h,url:e}});return this.siteInfo.bindUrl=e,t}async register(){const e=(await this.requestWithoutSign({url:"/activation/subject/register",data:{appKey:h,subjectId:this.getSubjectId(),installTime:this.siteInfo.installTime}})).license;return await this.saveLicense(e),await this.verify({license:e}),e}async updateLicense(e){await this.saveLicense(e.license),await this.verify({license:e.license})}async getAccessToken(){const e=await this.request({url:"/activation/subject/getAccessToken",data:{}});return{accessToken:e.accessToken,expiresIn:e.expiresIn}}async doVipCheck({bindUrl:e}){const t=await this.request({url:"/activation/subject/vip/check",data:{url:e},skipCheckRes:!0});if(1004===t?.code)throw console.log("请求参数错误:",t.message),new Error(t.message);return n.info(JSON.stringify(t.data)),{ok:t?.data?.ok,message:t?.data?.message||t.message}}async active(e){const t={appKey:h,code:e,subjectId:this.getSubjectId()},s=(await this.requestWithoutSign({url:"/activation/active",method:"post",data:t})).license;await this.updateLicense({license:s})}}function V(){if(!m())throw new Error("此为专业版功能,请升级到专业版")}function w(){if(!U())throw new Error("此为商业版功能,请升级到商业版")}c(n);export{h as AppKey,y as PlusRequestService,w as checkComm,V as checkPlus,g as getLicense,T as getLicenseReq,o as getLogger,S as getPlusInfo,f as getSecret,U as isComm,m as isPlus,c as setLogger,v as verify};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@certd/plus-core",
3
3
  "private": false,
4
- "version": "1.27.0",
4
+ "version": "1.27.2",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/d/index.d.ts",
@@ -14,7 +14,7 @@
14
14
  "preview": "vite preview"
15
15
  },
16
16
  "dependencies": {
17
- "@certd/basic": "^1.27.0",
17
+ "@certd/basic": "^1.27.2",
18
18
  "dayjs": "^1.11.7"
19
19
  },
20
20
  "devDependencies": {
@@ -27,14 +27,13 @@
27
27
  "chai": "4.3.10",
28
28
  "eslint": "^8.41.0",
29
29
  "eslint-config-prettier": "^8.8.0",
30
- "eslint-plugin-import": "^2.27.5",
31
- "eslint-plugin-node": "^11.1.0",
32
30
  "eslint-plugin-prettier": "^4.2.1",
33
31
  "mocha": "^10.2.0",
32
+ "prettier": "^2.8.8",
34
33
  "rimraf": "^5.0.5",
35
34
  "rollup": "^3.7.4",
36
- "ts-node": "^10.9.1",
35
+ "tslib": "^2.8.1",
37
36
  "typescript": "^5.4.2"
38
37
  },
39
- "gitHead": "c643d7edc3721a6d2ac701a35ef600f6b6ff4b34"
38
+ "gitHead": "3a0178b2949083c770ed96a4122e4c0a5e0bcc11"
40
39
  }
package/tsconfig.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "compileOnSave": false,
2
+ "compileOnSave": true,
3
3
  "compilerOptions": {
4
- "importHelpers": true,
4
+ "importHelpers": false,
5
5
  "target": "ESNext",
6
6
  "module": "ESNext",
7
7
  "moduleResolution": "node",
@@ -19,7 +19,7 @@
19
19
  "typeRoots": [ "./typings", "./node_modules/@types"],
20
20
  "outDir": "dist",
21
21
  "rootDir": "src",
22
- "composite": true,
22
+ "composite": false,
23
23
  "useDefineForClassFields": true,
24
24
  "strict": false,
25
25
  "sourceMap": false,