@jayfong/x-server 2.118.1 → 3.0.0
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/lib/_virtual/_rolldown/runtime.mjs +4 -0
- package/lib/cli/api_generator.d.mts +74 -0
- package/lib/cli/api_generator.mjs +310 -0
- package/lib/cli/build_util.d.mts +17 -0
- package/lib/cli/build_util.mjs +156 -0
- package/lib/cli/cli.d.mts +1 -0
- package/lib/cli/cli.mjs +355 -0
- package/lib/cli/css_register.d.mts +1 -0
- package/lib/cli/css_register.mjs +7 -0
- package/lib/cli/deploy_util.d.mts +23 -0
- package/lib/cli/deploy_util.mjs +70 -0
- package/lib/cli/dev_util.d.mts +7 -0
- package/lib/cli/dev_util.mjs +25 -0
- package/lib/cli/env_util.d.mts +45 -0
- package/lib/cli/env_util.mjs +207 -0
- package/lib/cli/esbuild_register.d.mts +1 -0
- package/lib/cli/esbuild_register.mjs +7 -0
- package/lib/cli/template_util.d.mts +18 -0
- package/lib/cli/template_util.mjs +85 -0
- package/lib/cli/templates/crons.ts +1 -1
- package/lib/cli/templates/handlers.ts +1 -1
- package/lib/cli/templates/hooks.ts +1 -1
- package/lib/cli/templates/models.ts +7 -7
- package/lib/cli/templates/package.json +11 -1
- package/lib/cli/templates/routes.ts +2 -1
- package/lib/core/ctx_storage.d.mts +3 -0
- package/lib/core/ctx_storage.mjs +4 -0
- package/lib/core/define_bus.d.mts +37 -0
- package/lib/core/define_bus.mjs +12 -0
- package/lib/core/{define_cron.d.ts → define_cron.d.mts} +2 -2
- package/lib/core/define_cron.mjs +11 -0
- package/lib/core/{define_handler.d.ts → define_handler.d.mts} +19 -19
- package/lib/core/define_handler.mjs +44 -0
- package/lib/core/define_hook.d.mts +2 -0
- package/lib/core/define_hook.mjs +6 -0
- package/lib/core/define_server.d.mts +3 -0
- package/lib/core/define_server.mjs +8 -0
- package/lib/core/{define_task.d.ts → define_task.d.mts} +2 -2
- package/lib/core/define_task.mjs +102 -0
- package/lib/core/get_handler_url.d.mts +2 -0
- package/lib/core/get_handler_url.mjs +7 -0
- package/lib/core/handler.d.mts +16 -0
- package/lib/core/handler.mjs +132 -0
- package/lib/core/http_error.d.mts +2 -0
- package/lib/core/http_error.mjs +1 -0
- package/lib/core/http_header.d.mts +856 -0
- package/lib/core/http_header.mjs +860 -0
- package/lib/core/http_method.d.mts +3 -0
- package/lib/core/http_method.mjs +10 -0
- package/lib/core/http_redirect.d.mts +5 -0
- package/lib/core/http_redirect.mjs +10 -0
- package/lib/core/server.d.mts +20 -0
- package/lib/core/server.mjs +186 -0
- package/lib/core/types.d.mts +256 -0
- package/lib/exports.d.mts +46 -0
- package/lib/exports.mjs +46 -0
- package/lib/index.d.mts +48 -0
- package/lib/index.mjs +45 -0
- package/lib/plugins/base.d.mts +4 -0
- package/lib/plugins/compress.d.mts +12 -0
- package/lib/plugins/compress.mjs +15 -0
- package/lib/plugins/cookie.d.mts +12 -0
- package/lib/plugins/cookie.mjs +15 -0
- package/lib/plugins/cors.d.mts +22 -0
- package/lib/plugins/cors.mjs +34 -0
- package/lib/plugins/file_parser.d.mts +15 -0
- package/lib/plugins/file_parser.mjs +24 -0
- package/lib/plugins/form_body_parser.d.mts +12 -0
- package/lib/plugins/form_body_parser.mjs +15 -0
- package/lib/plugins/ws_parser.d.mts +12 -0
- package/lib/plugins/ws_parser.mjs +15 -0
- package/lib/plugins/xml_parser.d.mts +19 -0
- package/lib/plugins/xml_parser.mjs +40 -0
- package/lib/services/ai.d.mts +31 -0
- package/lib/services/ai.mjs +44 -0
- package/lib/services/base.d.mts +4 -0
- package/lib/services/base.mjs +1 -0
- package/lib/services/cache.d.mts +165 -0
- package/lib/services/cache.mjs +323 -0
- package/lib/services/captcha.d.mts +65 -0
- package/lib/services/captcha.mjs +61 -0
- package/lib/services/{crypto.js → crypto.d.mts} +19 -78
- package/lib/services/crypto.mjs +141 -0
- package/lib/services/db_value.d.mts +60 -0
- package/lib/services/db_value.mjs +64 -0
- package/lib/services/dingtalk.d.mts +39 -0
- package/lib/services/dingtalk.mjs +44 -0
- package/lib/services/dispose.d.mts +17 -0
- package/lib/services/dispose.mjs +18 -0
- package/lib/services/emoji.d.mts +10 -0
- package/lib/services/emoji.mjs +2025 -0
- package/lib/services/file_store.d.mts +49 -0
- package/lib/services/file_store.mjs +58 -0
- package/lib/services/html.d.mts +11 -0
- package/lib/services/html.mjs +12 -0
- package/lib/services/jwt.d.mts +33 -0
- package/lib/services/jwt.mjs +42 -0
- package/lib/services/log.d.mts +37 -0
- package/lib/services/log.mjs +99 -0
- package/lib/services/mail.d.mts +22 -0
- package/lib/services/mail.mjs +28 -0
- package/lib/services/pay.d.mts +123 -0
- package/lib/services/pay.mjs +157 -0
- package/lib/services/random.d.mts +27 -0
- package/lib/services/random.mjs +42 -0
- package/lib/services/rate_limit.d.mts +37 -0
- package/lib/services/rate_limit.mjs +40 -0
- package/lib/services/redis.d.mts +11 -0
- package/lib/services/redis.mjs +6 -0
- package/lib/services/sensitive_words.d.mts +29 -0
- package/lib/services/sensitive_words.mjs +37 -0
- package/lib/services/sms.d.mts +40 -0
- package/lib/services/sms.mjs +30238 -0
- package/lib/types/dto.d.mts +30 -0
- package/lib/types/dto.mjs +1 -0
- package/lib/x.d.mts +11 -0
- package/lib/x.mjs +21 -0
- package/lib/x_init.d.mts +1 -0
- package/lib/x_init.mjs +10 -0
- package/package.json +99 -43
- package/lib/_cjs/cli/api_generator.js +0 -438
- package/lib/_cjs/cli/build_util.js +0 -243
- package/lib/_cjs/cli/cli.js +0 -378
- package/lib/_cjs/cli/css_register.js +0 -7
- package/lib/_cjs/cli/deploy_util.js +0 -76
- package/lib/_cjs/cli/dev_util.js +0 -25
- package/lib/_cjs/cli/env_util.js +0 -252
- package/lib/_cjs/cli/esbuild_register.js +0 -7
- package/lib/_cjs/cli/template_util.js +0 -101
- package/lib/_cjs/cli/templates/crons.ts +0 -2
- package/lib/_cjs/cli/templates/handlers.ts +0 -3
- package/lib/_cjs/cli/templates/hooks.ts +0 -2
- package/lib/_cjs/cli/templates/models.ts +0 -123
- package/lib/_cjs/cli/templates/package.json +0 -3
- package/lib/_cjs/cli/templates/routes.ts +0 -68
- package/lib/_cjs/core/ctx_storage.js +0 -6
- package/lib/_cjs/core/define_bus.js +0 -31
- package/lib/_cjs/core/define_cron.js +0 -13
- package/lib/_cjs/core/define_handler.js +0 -56
- package/lib/_cjs/core/define_hook.js +0 -8
- package/lib/_cjs/core/define_server.js +0 -10
- package/lib/_cjs/core/define_task.js +0 -113
- package/lib/_cjs/core/get_handler_url.js +0 -11
- package/lib/_cjs/core/handler.js +0 -216
- package/lib/_cjs/core/http_error.js +0 -6
- package/lib/_cjs/core/http_header.js +0 -142
- package/lib/_cjs/core/http_method.js +0 -12
- package/lib/_cjs/core/http_redirect.js +0 -11
- package/lib/_cjs/core/server.js +0 -221
- package/lib/_cjs/core/types.js +0 -8
- package/lib/_cjs/exports.js +0 -273
- package/lib/_cjs/index.js +0 -15
- package/lib/_cjs/plugins/base.js +0 -3
- package/lib/_cjs/plugins/compress.js +0 -18
- package/lib/_cjs/plugins/cookie.js +0 -18
- package/lib/_cjs/plugins/cors.js +0 -38
- package/lib/_cjs/plugins/file_parser.js +0 -28
- package/lib/_cjs/plugins/form_body_parser.js +0 -18
- package/lib/_cjs/plugins/ws_parser.js +0 -18
- package/lib/_cjs/plugins/xml_parser.js +0 -48
- package/lib/_cjs/services/ai.js +0 -48
- package/lib/_cjs/services/base.js +0 -3
- package/lib/_cjs/services/cache.js +0 -400
- package/lib/_cjs/services/captcha.js +0 -78
- package/lib/_cjs/services/crypto.js +0 -175
- package/lib/_cjs/services/db_value.js +0 -77
- package/lib/_cjs/services/dingtalk.js +0 -51
- package/lib/_cjs/services/dispose.js +0 -23
- package/lib/_cjs/services/emoji.js +0 -2034
- package/lib/_cjs/services/file_store.js +0 -67
- package/lib/_cjs/services/html.js +0 -17
- package/lib/_cjs/services/jwt.js +0 -65
- package/lib/_cjs/services/log.js +0 -108
- package/lib/_cjs/services/mail.js +0 -31
- package/lib/_cjs/services/pay.js +0 -191
- package/lib/_cjs/services/random.js +0 -51
- package/lib/_cjs/services/rate_limit.js +0 -54
- package/lib/_cjs/services/redis.js +0 -12
- package/lib/_cjs/services/sensitive_words.js +0 -62
- package/lib/_cjs/services/sms.js +0 -84
- package/lib/_cjs/types/dto.js +0 -3
- package/lib/_cjs/x.js +0 -35
- package/lib/cli/api_generator.d.ts +0 -74
- package/lib/cli/api_generator.js +0 -432
- package/lib/cli/build_util.d.ts +0 -17
- package/lib/cli/build_util.js +0 -236
- package/lib/cli/cli.d.ts +0 -2
- package/lib/cli/cli.js +0 -374
- package/lib/cli/css_register.js +0 -5
- package/lib/cli/deploy_util.d.ts +0 -23
- package/lib/cli/deploy_util.js +0 -70
- package/lib/cli/dev_util.d.ts +0 -8
- package/lib/cli/dev_util.js +0 -19
- package/lib/cli/env_util.d.ts +0 -45
- package/lib/cli/env_util.js +0 -246
- package/lib/cli/esbuild_register.js +0 -5
- package/lib/cli/template_util.d.ts +0 -18
- package/lib/cli/template_util.js +0 -95
- package/lib/core/ctx_storage.d.ts +0 -3
- package/lib/core/ctx_storage.js +0 -2
- package/lib/core/define_bus.d.ts +0 -37
- package/lib/core/define_bus.js +0 -27
- package/lib/core/define_cron.js +0 -9
- package/lib/core/define_handler.js +0 -48
- package/lib/core/define_hook.d.ts +0 -2
- package/lib/core/define_hook.js +0 -4
- package/lib/core/define_server.d.ts +0 -3
- package/lib/core/define_server.js +0 -6
- package/lib/core/define_task.js +0 -107
- package/lib/core/get_handler_url.d.ts +0 -2
- package/lib/core/get_handler_url.js +0 -7
- package/lib/core/handler.d.ts +0 -16
- package/lib/core/handler.js +0 -209
- package/lib/core/http_error.d.ts +0 -2
- package/lib/core/http_error.js +0 -2
- package/lib/core/http_header.d.ts +0 -856
- package/lib/core/http_header.js +0 -139
- package/lib/core/http_method.d.ts +0 -3
- package/lib/core/http_method.js +0 -8
- package/lib/core/http_redirect.d.ts +0 -5
- package/lib/core/http_redirect.js +0 -6
- package/lib/core/server.d.ts +0 -20
- package/lib/core/server.js +0 -215
- package/lib/core/types.d.ts +0 -265
- package/lib/core/types.js +0 -4
- package/lib/exports.d.ts +0 -45
- package/lib/exports.js +0 -47
- package/lib/index.d.ts +0 -2
- package/lib/index.js +0 -3
- package/lib/plugins/base.d.ts +0 -4
- package/lib/plugins/base.js +0 -1
- package/lib/plugins/compress.d.ts +0 -13
- package/lib/plugins/compress.js +0 -12
- package/lib/plugins/cookie.d.ts +0 -13
- package/lib/plugins/cookie.js +0 -12
- package/lib/plugins/cors.d.ts +0 -22
- package/lib/plugins/cors.js +0 -33
- package/lib/plugins/file_parser.d.ts +0 -16
- package/lib/plugins/file_parser.js +0 -22
- package/lib/plugins/form_body_parser.d.ts +0 -13
- package/lib/plugins/form_body_parser.js +0 -12
- package/lib/plugins/ws_parser.d.ts +0 -13
- package/lib/plugins/ws_parser.js +0 -12
- package/lib/plugins/xml_parser.d.ts +0 -19
- package/lib/plugins/xml_parser.js +0 -43
- package/lib/services/ai.d.ts +0 -31
- package/lib/services/ai.js +0 -43
- package/lib/services/base.d.ts +0 -4
- package/lib/services/base.js +0 -1
- package/lib/services/cache.d.ts +0 -173
- package/lib/services/cache.js +0 -394
- package/lib/services/captcha.d.ts +0 -65
- package/lib/services/captcha.js +0 -72
- package/lib/services/crypto.d.ts +0 -110
- package/lib/services/db_value.d.ts +0 -60
- package/lib/services/db_value.js +0 -72
- package/lib/services/dingtalk.d.ts +0 -39
- package/lib/services/dingtalk.js +0 -45
- package/lib/services/dispose.d.ts +0 -17
- package/lib/services/dispose.js +0 -17
- package/lib/services/emoji.d.ts +0 -10
- package/lib/services/emoji.js +0 -2029
- package/lib/services/file_store.d.ts +0 -49
- package/lib/services/file_store.js +0 -61
- package/lib/services/html.d.ts +0 -11
- package/lib/services/html.js +0 -12
- package/lib/services/jwt.d.ts +0 -34
- package/lib/services/jwt.js +0 -59
- package/lib/services/log.d.ts +0 -37
- package/lib/services/log.js +0 -102
- package/lib/services/mail.d.ts +0 -23
- package/lib/services/mail.js +0 -25
- package/lib/services/pay.d.ts +0 -123
- package/lib/services/pay.js +0 -185
- package/lib/services/random.d.ts +0 -27
- package/lib/services/random.js +0 -45
- package/lib/services/rate_limit.d.ts +0 -37
- package/lib/services/rate_limit.js +0 -49
- package/lib/services/redis.d.ts +0 -12
- package/lib/services/redis.js +0 -7
- package/lib/services/sensitive_words.d.ts +0 -30
- package/lib/services/sensitive_words.js +0 -57
- package/lib/services/sms.d.ts +0 -40
- package/lib/services/sms.js +0 -78
- package/lib/types/dto.d.ts +0 -86
- package/lib/types/dto.js +0 -1
- package/lib/x.d.ts +0 -17
- package/lib/x.js +0 -30
- /package/lib/{cli/css_register.d.ts → core/types.mjs} +0 -0
- /package/lib/{cli/esbuild_register.d.ts → plugins/base.mjs} +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { BaseService } from "./base.mjs";
|
|
2
|
+
export type FileStoreServiceOptions = {
|
|
3
|
+
accessKey: string;
|
|
4
|
+
secretKey: string;
|
|
5
|
+
/** 如: cos.ap-guangzhou.myqcloud.com */
|
|
6
|
+
endpoint: string;
|
|
7
|
+
/** 如: image-311111 */
|
|
8
|
+
bucket: string;
|
|
9
|
+
/** 如: x */
|
|
10
|
+
dir: string;
|
|
11
|
+
/** 如: cdn.com */
|
|
12
|
+
cdnUrl: string;
|
|
13
|
+
};
|
|
14
|
+
export type FileStoreServiceGetUploadUrlPayload = {
|
|
15
|
+
fileName: string;
|
|
16
|
+
ttl: number;
|
|
17
|
+
keepName?: boolean;
|
|
18
|
+
};
|
|
19
|
+
export type FileStoreServiceGetUploadUrlResult = {
|
|
20
|
+
/** 文件类型 */
|
|
21
|
+
contentType: string;
|
|
22
|
+
/** 文件上传地址 */
|
|
23
|
+
uploadUrl: string;
|
|
24
|
+
/** 文件公开访问地址 */
|
|
25
|
+
publicUrl: string;
|
|
26
|
+
};
|
|
27
|
+
export type FileStoreServiceUploadPayload = {
|
|
28
|
+
/** 文件名 */
|
|
29
|
+
fileName: string;
|
|
30
|
+
/** 文件内容 */
|
|
31
|
+
content: Buffer;
|
|
32
|
+
keepName?: boolean;
|
|
33
|
+
};
|
|
34
|
+
export type FileStoreServiceUploadResult = FileStoreServiceGetUploadUrlResult;
|
|
35
|
+
export declare class FileStoreService implements BaseService {
|
|
36
|
+
private options;
|
|
37
|
+
serviceName: string;
|
|
38
|
+
private endpoint;
|
|
39
|
+
private dir;
|
|
40
|
+
private cdnUrl;
|
|
41
|
+
constructor(options: FileStoreServiceOptions);
|
|
42
|
+
getUploadUrl(payload: FileStoreServiceGetUploadUrlPayload): Promise<FileStoreServiceGetUploadUrlResult>;
|
|
43
|
+
upload(payload: FileStoreServiceUploadPayload): Promise<FileStoreServiceUploadResult>;
|
|
44
|
+
}
|
|
45
|
+
declare module '../x.mjs' {
|
|
46
|
+
interface X {
|
|
47
|
+
fileStore: FileStoreService;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { x } from "../x.mjs";
|
|
2
|
+
import { isUrl, ms } from "vtils";
|
|
3
|
+
import { xr } from "@jayfong/x-request";
|
|
4
|
+
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
5
|
+
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
|
6
|
+
import mime from "mime";
|
|
7
|
+
// src/services/file_store.ts
|
|
8
|
+
var FileStoreService = class {
|
|
9
|
+
options;
|
|
10
|
+
serviceName = "fileStore";
|
|
11
|
+
endpoint = "";
|
|
12
|
+
dir = "";
|
|
13
|
+
cdnUrl = "";
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.options = options;
|
|
16
|
+
this.endpoint = isUrl(this.options.endpoint) ? this.options.endpoint : `https://${this.options.endpoint}`;
|
|
17
|
+
this.dir = this.options.dir ? `${this.options.dir.replace(/^\/+/, "").replace(/\/+$/, "")}` : "";
|
|
18
|
+
this.cdnUrl = (isUrl(this.options.cdnUrl) ? this.options.cdnUrl : `https://${this.options.cdnUrl}`).replace(/\/+$/, "");
|
|
19
|
+
}
|
|
20
|
+
async getUploadUrl(payload) {
|
|
21
|
+
const s3Client = new S3Client({
|
|
22
|
+
credentials: {
|
|
23
|
+
accessKeyId: this.options.accessKey,
|
|
24
|
+
secretAccessKey: this.options.secretKey
|
|
25
|
+
},
|
|
26
|
+
endpoint: this.endpoint,
|
|
27
|
+
region: "x"
|
|
28
|
+
});
|
|
29
|
+
const contentType = mime.getType(payload.fileName) || "application/octet-stream";
|
|
30
|
+
const fileName = payload.keepName ? payload.fileName : `${x.random.cuid2()}.${mime.getExtension(contentType)}`;
|
|
31
|
+
const dir = this.dir ? `${this.dir}/` : "";
|
|
32
|
+
const command = new PutObjectCommand({
|
|
33
|
+
Bucket: this.options.bucket,
|
|
34
|
+
Key: `${dir}${fileName}`,
|
|
35
|
+
ContentType: contentType
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
contentType,
|
|
39
|
+
uploadUrl: await getSignedUrl(s3Client, command, { expiresIn: ms(payload.ttl, true) }),
|
|
40
|
+
publicUrl: `${this.cdnUrl}/${dir}${fileName}`
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
async upload(payload) {
|
|
44
|
+
const res = await this.getUploadUrl({
|
|
45
|
+
fileName: payload.fileName,
|
|
46
|
+
ttl: ms("1m"),
|
|
47
|
+
keepName: payload.keepName
|
|
48
|
+
});
|
|
49
|
+
await xr.post({
|
|
50
|
+
url: res.uploadUrl,
|
|
51
|
+
method: "PUT",
|
|
52
|
+
headers: { "Content-Type": res.contentType },
|
|
53
|
+
data: payload.content
|
|
54
|
+
});
|
|
55
|
+
return res;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
export { FileStoreService };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BaseService } from "./base.mjs";
|
|
2
|
+
export declare class HtmlService implements BaseService {
|
|
3
|
+
serviceName: string;
|
|
4
|
+
escape(html: string): string;
|
|
5
|
+
unescape(html: string): string;
|
|
6
|
+
}
|
|
7
|
+
declare module '../x.mjs' {
|
|
8
|
+
interface X {
|
|
9
|
+
html: HtmlService;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { escapeHTML, unescapeHTML } from "fast-escape-html";
|
|
2
|
+
// src/services/html.ts
|
|
3
|
+
var HtmlService = class {
|
|
4
|
+
serviceName = "html";
|
|
5
|
+
escape(html) {
|
|
6
|
+
return escapeHTML(html);
|
|
7
|
+
}
|
|
8
|
+
unescape(html) {
|
|
9
|
+
return unescapeHTML(html);
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
export { HtmlService };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { BaseService } from "./base.mjs";
|
|
2
|
+
import { MsValue } from "vtils";
|
|
3
|
+
import jwt from "jsonwebtoken";
|
|
4
|
+
import { LRUCache } from "lru-cache";
|
|
5
|
+
import { RequiredBy } from "vtils/types";
|
|
6
|
+
import { IncomingHttpHeaders } from "node:http";
|
|
7
|
+
export interface JwtServiceJwtPayload extends Record<string, any> {}
|
|
8
|
+
export interface JwtServiceOptions {
|
|
9
|
+
secret: string;
|
|
10
|
+
ttl: MsValue;
|
|
11
|
+
cache?: LRUCache.Options<string, JwtServiceJwtPayload, any>;
|
|
12
|
+
onVerify?: (payload: JwtServiceJwtPayload & RequiredBy<jwt.JwtPayload, 'iat' | 'exp'> & {
|
|
13
|
+
token: string;
|
|
14
|
+
}) => any;
|
|
15
|
+
}
|
|
16
|
+
export declare class JwtService implements BaseService {
|
|
17
|
+
private options;
|
|
18
|
+
serviceName: string;
|
|
19
|
+
private cache;
|
|
20
|
+
constructor(options: JwtServiceOptions);
|
|
21
|
+
sign<T extends JwtServiceJwtPayload>(payload: T, ttl?: MsValue): string;
|
|
22
|
+
verify<T extends JwtServiceJwtPayload>(token: string): Promise<T & {
|
|
23
|
+
token: string;
|
|
24
|
+
}>;
|
|
25
|
+
verifyFromHttpHeaders<T extends JwtServiceJwtPayload>(headers: IncomingHttpHeaders): Promise<T & {
|
|
26
|
+
token: string;
|
|
27
|
+
}>;
|
|
28
|
+
}
|
|
29
|
+
declare module '../x.mjs' {
|
|
30
|
+
interface X {
|
|
31
|
+
jwt: JwtService;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { HttpError } from "../core/http_error.mjs";
|
|
2
|
+
import { ms } from "vtils";
|
|
3
|
+
import jwt from "jsonwebtoken";
|
|
4
|
+
import { LRUCache } from "lru-cache";
|
|
5
|
+
import { differenceInMilliseconds, fromUnixTime } from "vtils/date";
|
|
6
|
+
// src/services/jwt.ts
|
|
7
|
+
var JwtService = class {
|
|
8
|
+
options;
|
|
9
|
+
serviceName = "jwt";
|
|
10
|
+
cache;
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.options = options;
|
|
13
|
+
if (options.cache) this.cache = new LRUCache(options.cache);
|
|
14
|
+
}
|
|
15
|
+
sign(payload, ttl = this.options.ttl) {
|
|
16
|
+
const token = jwt.sign(payload, this.options.secret, { expiresIn: ms(ttl, true) });
|
|
17
|
+
if (this.cache) this.cache.set(token, payload, { ttl: ms(ttl) });
|
|
18
|
+
return token;
|
|
19
|
+
}
|
|
20
|
+
async verify(token) {
|
|
21
|
+
const data = await new Promise((resolve, reject) => {
|
|
22
|
+
if (this.cache && this.cache.has(token)) resolve(this.cache.get(token));
|
|
23
|
+
else jwt.verify(token, this.options.secret, { ignoreExpiration: false }, (err, data) => {
|
|
24
|
+
if (err || !data || typeof data === "string" || !data.iat || !data.exp) reject(new HttpError.Unauthorized("data"));
|
|
25
|
+
else {
|
|
26
|
+
data.token = token;
|
|
27
|
+
if (this.cache) this.cache.set(token, data, { ttl: differenceInMilliseconds(fromUnixTime(data.exp), /* @__PURE__ */ new Date()) });
|
|
28
|
+
resolve(data);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
await this.options.onVerify?.(data);
|
|
33
|
+
return data;
|
|
34
|
+
}
|
|
35
|
+
async verifyFromHttpHeaders(headers) {
|
|
36
|
+
const authorization = headers.authorization || headers["sec-websocket-protocol"] && `Bearer ${headers["sec-websocket-protocol"]}` || "";
|
|
37
|
+
if (!authorization) throw new HttpError.Unauthorized("header");
|
|
38
|
+
const [scheme, token = scheme] = authorization.split(" ");
|
|
39
|
+
return this.verify(token);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
export { JwtService };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { BaseService } from "./base.mjs";
|
|
2
|
+
import { Merge } from "vtils/types";
|
|
3
|
+
export type LogServiceLevel = 'error' | 'info' | 'success';
|
|
4
|
+
export type LogServiceDesc = Record<string, any> | any[];
|
|
5
|
+
export type LogServiceWriter = 'file' | 'console';
|
|
6
|
+
export type LogServicePayload = {
|
|
7
|
+
writer?: LogServiceWriter;
|
|
8
|
+
level: LogServiceLevel;
|
|
9
|
+
title: string;
|
|
10
|
+
desc?: LogServiceDesc;
|
|
11
|
+
};
|
|
12
|
+
export type LogServiceLogItem<K extends string = string> = Merge<LogServicePayload, {
|
|
13
|
+
traceId: string;
|
|
14
|
+
time: string;
|
|
15
|
+
desc: Record<K, any>;
|
|
16
|
+
}>;
|
|
17
|
+
export declare class LogService implements BaseService {
|
|
18
|
+
serviceName: string;
|
|
19
|
+
getLogFile(date: Date): string;
|
|
20
|
+
private get logFile();
|
|
21
|
+
private getLogWriter;
|
|
22
|
+
parseLogLineText<K extends string = string>(text: string, keysMap?: Record<string, string[]>): LogServiceLogItem<K>;
|
|
23
|
+
private log;
|
|
24
|
+
info: (title: string, desc?: LogServiceDesc) => void;
|
|
25
|
+
success: (title: string, desc?: LogServiceDesc) => void;
|
|
26
|
+
error: (title: string, desc?: LogServiceDesc) => void;
|
|
27
|
+
console: {
|
|
28
|
+
info: (title: string, desc?: LogServiceDesc) => void;
|
|
29
|
+
success: (title: string, desc?: LogServiceDesc) => void;
|
|
30
|
+
error: (title: string, desc?: LogServiceDesc) => void;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
declare module '../x.mjs' {
|
|
34
|
+
interface X {
|
|
35
|
+
log: LogService;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { x } from "../x.mjs";
|
|
2
|
+
import { memoize } from "vtils";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import fs from "fs-extra";
|
|
5
|
+
import { formatDate } from "vtils/date";
|
|
6
|
+
// src/services/log.ts
|
|
7
|
+
var LogService = class {
|
|
8
|
+
serviceName = "log";
|
|
9
|
+
getLogFile(date) {
|
|
10
|
+
const year = date.getFullYear();
|
|
11
|
+
const month = date.getMonth() + 1;
|
|
12
|
+
return path.join(x.dataDir, `log/${year}/${month < 10 ? `0${month}` : month}.log`);
|
|
13
|
+
}
|
|
14
|
+
get logFile() {
|
|
15
|
+
return this.getLogFile(/* @__PURE__ */ new Date());
|
|
16
|
+
}
|
|
17
|
+
getLogWriter = memoize((logFile) => {
|
|
18
|
+
fs.ensureFileSync(logFile);
|
|
19
|
+
return fs.createWriteStream(logFile, { flags: "a" });
|
|
20
|
+
}, (logFile) => logFile);
|
|
21
|
+
parseLogLineText(text, keysMap = {}) {
|
|
22
|
+
const segments = text.split(/\t+/);
|
|
23
|
+
if (segments[1].length < 10) segments.splice(1, 0, "");
|
|
24
|
+
const [time, traceId, level, title, ...desc] = segments;
|
|
25
|
+
return {
|
|
26
|
+
time,
|
|
27
|
+
traceId,
|
|
28
|
+
level,
|
|
29
|
+
title,
|
|
30
|
+
desc: desc.reduce((res, item, index) => {
|
|
31
|
+
if (keysMap[title]) res[keysMap[title][index]] = item;
|
|
32
|
+
else {
|
|
33
|
+
const i = item.indexOf(":");
|
|
34
|
+
res[item.substring(0, i)] = item.substring(i + 1);
|
|
35
|
+
}
|
|
36
|
+
return res;
|
|
37
|
+
}, {})
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
log(payload) {
|
|
41
|
+
const getContent = () => `${[
|
|
42
|
+
formatDate(/* @__PURE__ */ new Date(), "yyyy-mm-dd hh:ii:ss"),
|
|
43
|
+
...!x.ctx ? [] : [x.ctx.traceId],
|
|
44
|
+
payload.level,
|
|
45
|
+
payload.title,
|
|
46
|
+
...!payload.desc ? [] : Array.isArray(payload.desc) ? payload.desc : Object.keys(payload.desc).map((key) => `${key}:${payload.desc[key]}`)
|
|
47
|
+
].map((item) => String(item).replace(/[\r\n\t]+/g, " ")).join(" ")}`;
|
|
48
|
+
if (payload.writer === "console") console[payload.level === "error" ? "error" : "log"](getContent());
|
|
49
|
+
else this.getLogWriter(this.logFile).write(`${getContent()}\n`);
|
|
50
|
+
}
|
|
51
|
+
info = (title, desc) => {
|
|
52
|
+
this.log({
|
|
53
|
+
level: "info",
|
|
54
|
+
title,
|
|
55
|
+
desc
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
success = (title, desc) => {
|
|
59
|
+
this.log({
|
|
60
|
+
level: "success",
|
|
61
|
+
title,
|
|
62
|
+
desc
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
error = (title, desc) => {
|
|
66
|
+
this.log({
|
|
67
|
+
level: "error",
|
|
68
|
+
title,
|
|
69
|
+
desc
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
console = {
|
|
73
|
+
info: (title, desc) => {
|
|
74
|
+
this.log({
|
|
75
|
+
writer: "console",
|
|
76
|
+
level: "info",
|
|
77
|
+
title,
|
|
78
|
+
desc
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
success: (title, desc) => {
|
|
82
|
+
this.log({
|
|
83
|
+
writer: "console",
|
|
84
|
+
level: "success",
|
|
85
|
+
title,
|
|
86
|
+
desc
|
|
87
|
+
});
|
|
88
|
+
},
|
|
89
|
+
error: (title, desc) => {
|
|
90
|
+
this.log({
|
|
91
|
+
writer: "console",
|
|
92
|
+
level: "error",
|
|
93
|
+
title,
|
|
94
|
+
desc
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
export { LogService };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { BaseService } from "./base.mjs";
|
|
2
|
+
import nodemailer from "nodemailer";
|
|
3
|
+
export interface MailServiceOptions {
|
|
4
|
+
host: string;
|
|
5
|
+
port: number;
|
|
6
|
+
secure: boolean;
|
|
7
|
+
user: string;
|
|
8
|
+
pass: string;
|
|
9
|
+
}
|
|
10
|
+
export interface MailServiceSendOptions extends nodemailer.SendMailOptions {}
|
|
11
|
+
export declare class MailService implements BaseService {
|
|
12
|
+
private options;
|
|
13
|
+
serviceName: string;
|
|
14
|
+
private transporter;
|
|
15
|
+
constructor(options: MailServiceOptions);
|
|
16
|
+
send(options: MailServiceSendOptions): Promise<any>;
|
|
17
|
+
}
|
|
18
|
+
declare module '../x.mjs' {
|
|
19
|
+
interface X {
|
|
20
|
+
mail: MailService;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { x } from "../x.mjs";
|
|
2
|
+
import nodemailer from "nodemailer";
|
|
3
|
+
// src/services/mail.ts
|
|
4
|
+
var MailService = class {
|
|
5
|
+
options;
|
|
6
|
+
serviceName = "mail";
|
|
7
|
+
transporter;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.options = options;
|
|
10
|
+
}
|
|
11
|
+
async send(options) {
|
|
12
|
+
if (!this.transporter) {
|
|
13
|
+
this.transporter = nodemailer.createTransport({
|
|
14
|
+
host: this.options.host,
|
|
15
|
+
port: this.options.port,
|
|
16
|
+
secure: this.options.secure,
|
|
17
|
+
auth: {
|
|
18
|
+
user: this.options.user,
|
|
19
|
+
pass: this.options.pass
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
await this.transporter.verify();
|
|
23
|
+
x.dispose.add(() => this.transporter.close());
|
|
24
|
+
}
|
|
25
|
+
return this.transporter.sendMail(options);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
export { MailService };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { BaseService } from "./base.mjs";
|
|
2
|
+
export interface PayServiceOptions {
|
|
3
|
+
/** 支付宝 */
|
|
4
|
+
alipay?: {
|
|
5
|
+
/** 应用 ID */
|
|
6
|
+
appId: string;
|
|
7
|
+
/** 商户应用私钥 */
|
|
8
|
+
privateKey: string;
|
|
9
|
+
/** 支付宝公钥,用于对返回结果验签 */
|
|
10
|
+
publicKey: string;
|
|
11
|
+
};
|
|
12
|
+
/** 微信支付(APIv3),未实现回调验签,因此验证微信支付身份块不需要关心 */
|
|
13
|
+
wepay?: {
|
|
14
|
+
/** 公众号 APPID */
|
|
15
|
+
appId: string;
|
|
16
|
+
/** 商户 ID */
|
|
17
|
+
merchantId: string;
|
|
18
|
+
/** 商户API证书私钥 */
|
|
19
|
+
privateKey: string;
|
|
20
|
+
/** 商户API证书序列号 */
|
|
21
|
+
certificateSerialNumber: string;
|
|
22
|
+
/** 密钥,用于解密回调数据 */
|
|
23
|
+
secretKey: string;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface PayServicePrepareAlipayOptions {
|
|
27
|
+
/** 商品名称 */
|
|
28
|
+
goodsName: string;
|
|
29
|
+
/** 交易单号 */
|
|
30
|
+
tradeNumber: string;
|
|
31
|
+
/** 总金额 */
|
|
32
|
+
totalMoney: number;
|
|
33
|
+
/** 通知地址(POST) */
|
|
34
|
+
notifyUrl: string;
|
|
35
|
+
/** 返回地址 */
|
|
36
|
+
returnUrl?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface PayServicePrepareAlipayResult {
|
|
39
|
+
/** 支付地址,需跳转过去 */
|
|
40
|
+
payUrl: string;
|
|
41
|
+
}
|
|
42
|
+
export interface PayServicePrepareWepayOptions {
|
|
43
|
+
/** 商品名称 */
|
|
44
|
+
goodsName: string;
|
|
45
|
+
/** 交易单号 */
|
|
46
|
+
tradeNumber: string;
|
|
47
|
+
/** 总金额 */
|
|
48
|
+
totalMoney: number;
|
|
49
|
+
/** 通知地址(POST) */
|
|
50
|
+
notifyUrl: string;
|
|
51
|
+
/** 公众号用户的 openid */
|
|
52
|
+
openid: string;
|
|
53
|
+
}
|
|
54
|
+
export interface PayServicePrepareWepayResult {
|
|
55
|
+
/** 支付参数,可直接传给 JSSDK 调用 */
|
|
56
|
+
payParams: {
|
|
57
|
+
appId: string;
|
|
58
|
+
timestamp: string;
|
|
59
|
+
nonceStr: string;
|
|
60
|
+
package: string;
|
|
61
|
+
signType: string;
|
|
62
|
+
paySign: string;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export interface PayServiceVerifyNotifyDataResult {
|
|
66
|
+
/**
|
|
67
|
+
* 渠道订单号。
|
|
68
|
+
*
|
|
69
|
+
* - 支付宝最长 `64` 位;
|
|
70
|
+
* - 微信支付最长 `32` 位。
|
|
71
|
+
*/
|
|
72
|
+
channelOrderNo: string;
|
|
73
|
+
}
|
|
74
|
+
export interface PayServiceGetOrderInfoPayload {
|
|
75
|
+
/**
|
|
76
|
+
* 渠道。
|
|
77
|
+
*/
|
|
78
|
+
channel: 'alipay' | 'wepay';
|
|
79
|
+
/**
|
|
80
|
+
* 商家订单号。
|
|
81
|
+
*/
|
|
82
|
+
orderNo?: string;
|
|
83
|
+
/**
|
|
84
|
+
* 渠道订单号。
|
|
85
|
+
*/
|
|
86
|
+
channelOrderNo?: string;
|
|
87
|
+
}
|
|
88
|
+
export interface PayServiceGetOrderInfoResult {
|
|
89
|
+
/**
|
|
90
|
+
* 商家订单号。
|
|
91
|
+
*/
|
|
92
|
+
orderNo: string;
|
|
93
|
+
/**
|
|
94
|
+
* 渠道订单号。
|
|
95
|
+
*
|
|
96
|
+
* - 支付宝最长 `64` 位;
|
|
97
|
+
* - 微信支付最长 `32` 位。
|
|
98
|
+
*/
|
|
99
|
+
channelOrderNo: string;
|
|
100
|
+
/**
|
|
101
|
+
* 订单状态。
|
|
102
|
+
*/
|
|
103
|
+
status: 'success' | 'fail';
|
|
104
|
+
}
|
|
105
|
+
export declare class PayService implements BaseService {
|
|
106
|
+
private options;
|
|
107
|
+
serviceName: string;
|
|
108
|
+
private alipaySdk;
|
|
109
|
+
constructor(options: PayServiceOptions);
|
|
110
|
+
prepareAlipay(options: PayServicePrepareAlipayOptions): Promise<PayServicePrepareAlipayResult>;
|
|
111
|
+
prepareWepay(options: PayServicePrepareWepayOptions): Promise<PayServicePrepareWepayResult>;
|
|
112
|
+
verifyNotifyData(data: any): false | PayServiceVerifyNotifyDataResult;
|
|
113
|
+
verifyNotifyDataOrFail(data: any, message?: string): PayServiceVerifyNotifyDataResult;
|
|
114
|
+
getOrderInfo(payload: PayServiceGetOrderInfoPayload): Promise<PayServiceGetOrderInfoResult>;
|
|
115
|
+
private wepaySign;
|
|
116
|
+
private wepayDecrypt;
|
|
117
|
+
private wepayRequest;
|
|
118
|
+
}
|
|
119
|
+
declare module '../x.mjs' {
|
|
120
|
+
interface X {
|
|
121
|
+
pay: PayService;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { HttpError } from "../core/http_error.mjs";
|
|
2
|
+
import { xr } from "@jayfong/x-request";
|
|
3
|
+
import crypto from "node:crypto";
|
|
4
|
+
import { AlipayFormData, AlipaySdk } from "alipay-sdk";
|
|
5
|
+
// src/services/pay.ts
|
|
6
|
+
var PayService = class {
|
|
7
|
+
options;
|
|
8
|
+
serviceName = "pay";
|
|
9
|
+
alipaySdk;
|
|
10
|
+
constructor(options) {
|
|
11
|
+
this.options = options;
|
|
12
|
+
}
|
|
13
|
+
async prepareAlipay(options) {
|
|
14
|
+
if (!this.alipaySdk) this.alipaySdk = new AlipaySdk({
|
|
15
|
+
appId: this.options.alipay.appId,
|
|
16
|
+
privateKey: this.options.alipay.privateKey,
|
|
17
|
+
alipayPublicKey: this.options.alipay.publicKey
|
|
18
|
+
});
|
|
19
|
+
const formData = new AlipayFormData();
|
|
20
|
+
formData.setMethod("get");
|
|
21
|
+
formData.addField("notifyUrl", options.notifyUrl);
|
|
22
|
+
if (options.returnUrl) formData.addField("returnUrl", options.returnUrl);
|
|
23
|
+
formData.addField("bizContent", {
|
|
24
|
+
outTradeNo: options.tradeNumber,
|
|
25
|
+
productCode: "FAST_INSTANT_TRADE_PAY",
|
|
26
|
+
totalAmount: options.totalMoney,
|
|
27
|
+
subject: options.goodsName,
|
|
28
|
+
goodsType: "0",
|
|
29
|
+
passbackParams: "alipay"
|
|
30
|
+
});
|
|
31
|
+
return { payUrl: await this.alipaySdk.exec("alipay.trade.page.pay", {}, { formData }) };
|
|
32
|
+
}
|
|
33
|
+
async prepareWepay(options) {
|
|
34
|
+
const res = await this.wepayRequest("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi", {
|
|
35
|
+
appid: this.options.wepay.appId,
|
|
36
|
+
mchid: this.options.wepay.merchantId,
|
|
37
|
+
description: options.goodsName,
|
|
38
|
+
out_trade_no: options.tradeNumber,
|
|
39
|
+
attach: "wepay",
|
|
40
|
+
notify_url: options.notifyUrl,
|
|
41
|
+
amount: {
|
|
42
|
+
total: options.totalMoney * 100,
|
|
43
|
+
currency: "CNY"
|
|
44
|
+
},
|
|
45
|
+
payer: { openid: options.openid }
|
|
46
|
+
});
|
|
47
|
+
if (!res || !res.prepay_id) {
|
|
48
|
+
const error = res && res.message || "支付错误";
|
|
49
|
+
throw new Error(error);
|
|
50
|
+
}
|
|
51
|
+
const params = {
|
|
52
|
+
appId: this.options.wepay.appId,
|
|
53
|
+
timestamp: String(Math.round(Date.now() / 1e3)),
|
|
54
|
+
nonceStr: Math.random().toString().substr(2, 12),
|
|
55
|
+
package: `prepay_id=${res.prepay_id}`,
|
|
56
|
+
signType: "RSA",
|
|
57
|
+
paySign: ""
|
|
58
|
+
};
|
|
59
|
+
params.paySign = this.wepaySign([
|
|
60
|
+
params.appId,
|
|
61
|
+
params.timestamp,
|
|
62
|
+
params.nonceStr,
|
|
63
|
+
params.package
|
|
64
|
+
]);
|
|
65
|
+
return { payParams: params };
|
|
66
|
+
}
|
|
67
|
+
verifyNotifyData(data) {
|
|
68
|
+
try {
|
|
69
|
+
if (!data || typeof data !== "object") return false;
|
|
70
|
+
if (data.passback_params === "alipay") {
|
|
71
|
+
if (!this.alipaySdk?.checkNotifySign(data)) return false;
|
|
72
|
+
return { channelOrderNo: data.trade_no };
|
|
73
|
+
}
|
|
74
|
+
if (data.resource) {
|
|
75
|
+
const params = JSON.parse(this.wepayDecrypt(data.resource));
|
|
76
|
+
if (params.attach === "wepay") return { channelOrderNo: params.transaction_id };
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
return false;
|
|
80
|
+
} catch {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
verifyNotifyDataOrFail(data, message) {
|
|
85
|
+
const res = this.verifyNotifyData(data);
|
|
86
|
+
if (!res) throw new HttpError.BadRequest(message);
|
|
87
|
+
return res;
|
|
88
|
+
}
|
|
89
|
+
async getOrderInfo(payload) {
|
|
90
|
+
if (payload.channel === "wepay") {
|
|
91
|
+
const res = await this.wepayRequest(payload.orderNo ? `https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/${payload.orderNo}?mchid=${this.options.wepay.merchantId}` : `https://api.mch.weixin.qq.com/v3/pay/transactions/id/${payload.channelOrderNo}?mchid=${this.options.wepay.merchantId}`);
|
|
92
|
+
return {
|
|
93
|
+
channelOrderNo: res.transaction_id,
|
|
94
|
+
orderNo: res.out_trade_no,
|
|
95
|
+
status: res.trade_state === "SUCCESS" ? "success" : "fail"
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const res = await this.alipaySdk.exec("alipay.trade.query", { biz_content: payload.orderNo ? { out_trade_no: payload.orderNo } : { trade_no: payload.channelOrderNo } });
|
|
99
|
+
return {
|
|
100
|
+
channelOrderNo: res.trade_no,
|
|
101
|
+
orderNo: res.out_trade_no,
|
|
102
|
+
status: res.trade_status === "TRADE_SUCCESS" || res.trade_status === "TRADE_FINISHED" ? "success" : "fail"
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
wepaySign(data) {
|
|
106
|
+
return crypto.createSign("RSA-SHA256").update(data.map((v) => `${v}\n`).join("")).sign(this.options.wepay.privateKey, "base64");
|
|
107
|
+
}
|
|
108
|
+
wepayDecrypt(payload) {
|
|
109
|
+
const ciphertextBuffer = Buffer.from(payload.ciphertext, "base64");
|
|
110
|
+
const authTag = ciphertextBuffer.slice(ciphertextBuffer.length - 16);
|
|
111
|
+
const data = ciphertextBuffer.slice(0, ciphertextBuffer.length - 16);
|
|
112
|
+
const decipherIv = crypto.createDecipheriv("aes-256-gcm", this.options.wepay.secretKey, payload.nonce);
|
|
113
|
+
decipherIv.setAuthTag(Buffer.from(authTag));
|
|
114
|
+
decipherIv.setAAD(Buffer.from(payload.associated_data));
|
|
115
|
+
const decryptStr = decipherIv.update(data, void 0, "utf8");
|
|
116
|
+
decipherIv.final();
|
|
117
|
+
return decryptStr;
|
|
118
|
+
}
|
|
119
|
+
async wepayRequest(url, data) {
|
|
120
|
+
const path = url.replace(/^https?:\/\/[^/]+/, "");
|
|
121
|
+
const method = data == null ? "GET" : "POST";
|
|
122
|
+
const body = method === "POST" ? JSON.stringify(data) : "";
|
|
123
|
+
const params = {
|
|
124
|
+
method,
|
|
125
|
+
url: path,
|
|
126
|
+
time: String(Math.round(Date.now() / 1e3)),
|
|
127
|
+
rand: Math.random().toString().substr(2, 12),
|
|
128
|
+
body,
|
|
129
|
+
signature: ""
|
|
130
|
+
};
|
|
131
|
+
params.signature = this.wepaySign([
|
|
132
|
+
params.method,
|
|
133
|
+
params.url,
|
|
134
|
+
params.time,
|
|
135
|
+
params.rand,
|
|
136
|
+
params.body
|
|
137
|
+
]);
|
|
138
|
+
const Authorization = [
|
|
139
|
+
`WECHATPAY2-SHA256-RSA2048 `,
|
|
140
|
+
`mchid="${this.options.wepay.merchantId}",`,
|
|
141
|
+
`nonce_str="${params.rand}",`,
|
|
142
|
+
`signature="${params.signature}",`,
|
|
143
|
+
`timestamp="${params.time}",`,
|
|
144
|
+
`serial_no="${this.options.wepay.certificateSerialNumber}"`
|
|
145
|
+
].join("");
|
|
146
|
+
const { data: res } = method === "POST" ? await xr.postJson({
|
|
147
|
+
url,
|
|
148
|
+
headers: { Authorization },
|
|
149
|
+
data
|
|
150
|
+
}) : await xr.getJson({
|
|
151
|
+
url,
|
|
152
|
+
headers: { Authorization }
|
|
153
|
+
});
|
|
154
|
+
return res;
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
export { PayService };
|