@warriorteam/redai-zalo-sdk 1.28.1 → 1.30.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/CHANGELOG.md +131 -0
- package/ZNS-TYPE-IMPROVEMENTS.md +220 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/services/consultation.service.d.ts +114 -147
- package/dist/services/consultation.service.d.ts.map +1 -1
- package/dist/services/consultation.service.js +370 -0
- package/dist/services/consultation.service.js.map +1 -1
- package/dist/services/zns.service.d.ts.map +1 -1
- package/dist/services/zns.service.js +142 -141
- package/dist/services/zns.service.js.map +1 -1
- package/dist/types/consultation.d.ts +253 -0
- package/dist/types/consultation.d.ts.map +1 -0
- package/dist/types/consultation.js +13 -0
- package/dist/types/consultation.js.map +1 -0
- package/dist/types/zns.d.ts +95 -0
- package/dist/types/zns.d.ts.map +1 -1
- package/examples/consultation-template-example.ts +324 -0
- package/examples/zns-validation-example.ts +362 -0
- package/package.json +10 -4
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ZNSService = void 0;
|
|
4
|
+
const common_1 = require("../types/common");
|
|
4
5
|
/**
|
|
5
6
|
* Service for Zalo Notification Service (ZNS)
|
|
6
7
|
*
|
|
@@ -207,7 +208,7 @@ class ZNSService {
|
|
|
207
208
|
try {
|
|
208
209
|
// Validate limit (max 100)
|
|
209
210
|
if (limit > 100) {
|
|
210
|
-
throw new
|
|
211
|
+
throw new common_1.ZaloSDKError("Limit không được vượt quá 100", 400);
|
|
211
212
|
}
|
|
212
213
|
// Prepare query parameters
|
|
213
214
|
const params = { offset, limit };
|
|
@@ -359,7 +360,7 @@ class ZNSService {
|
|
|
359
360
|
try {
|
|
360
361
|
// Validate template_id first
|
|
361
362
|
if (!templateData.template_id) {
|
|
362
|
-
throw new
|
|
363
|
+
throw new common_1.ZaloSDKError("template_id là bắt buộc", 400);
|
|
363
364
|
}
|
|
364
365
|
// Comprehensive validation (same as createTemplate)
|
|
365
366
|
this.validateZNSTemplateRequest(templateData);
|
|
@@ -393,13 +394,13 @@ class ZNSService {
|
|
|
393
394
|
.toLowerCase()
|
|
394
395
|
.substring(filename.lastIndexOf("."));
|
|
395
396
|
if (!allowedExtensions.includes(fileExtension)) {
|
|
396
|
-
throw new
|
|
397
|
+
throw new common_1.ZaloSDKError("File phải có định dạng JPG hoặc PNG", 400);
|
|
397
398
|
}
|
|
398
399
|
// Validate file size if it's a Buffer (max 500KB)
|
|
399
400
|
if (Buffer.isBuffer(imageFile)) {
|
|
400
401
|
const maxSize = 500 * 1024; // 500KB
|
|
401
402
|
if (imageFile.length > maxSize) {
|
|
402
|
-
throw new
|
|
403
|
+
throw new common_1.ZaloSDKError("Dung lượng file không được vượt quá 500KB", 400);
|
|
403
404
|
}
|
|
404
405
|
}
|
|
405
406
|
const response = await this.client.apiUploadFile(this.endpoints.template.uploadImage, accessToken, imageFile, filename);
|
|
@@ -426,7 +427,7 @@ class ZNSService {
|
|
|
426
427
|
// 5. Note validation if provided
|
|
427
428
|
if (templateData.note) {
|
|
428
429
|
if (templateData.note.length < 1 || templateData.note.length > 400) {
|
|
429
|
-
throw new
|
|
430
|
+
throw new common_1.ZaloSDKError("note phải có độ dài từ 1 đến 400 ký tự", 400);
|
|
430
431
|
}
|
|
431
432
|
}
|
|
432
433
|
}
|
|
@@ -435,31 +436,31 @@ class ZNSService {
|
|
|
435
436
|
*/
|
|
436
437
|
validateBasicFields(templateData) {
|
|
437
438
|
if (!templateData.template_name) {
|
|
438
|
-
throw new
|
|
439
|
+
throw new common_1.ZaloSDKError("template_name là bắt buộc", 400);
|
|
439
440
|
}
|
|
440
441
|
if (templateData.template_name.length < 10 || templateData.template_name.length > 60) {
|
|
441
|
-
throw new
|
|
442
|
+
throw new common_1.ZaloSDKError("template_name phải có độ dài từ 10 đến 60 ký tự", 400);
|
|
442
443
|
}
|
|
443
444
|
if (!templateData.template_type) {
|
|
444
|
-
throw new
|
|
445
|
+
throw new common_1.ZaloSDKError("template_type là bắt buộc", 400);
|
|
445
446
|
}
|
|
446
447
|
if (![1, 2, 3, 4, 5].includes(templateData.template_type)) {
|
|
447
|
-
throw new
|
|
448
|
+
throw new common_1.ZaloSDKError("template_type phải là 1, 2, 3, 4 hoặc 5", 400);
|
|
448
449
|
}
|
|
449
450
|
if (!templateData.tag) {
|
|
450
|
-
throw new
|
|
451
|
+
throw new common_1.ZaloSDKError("tag là bắt buộc", 400);
|
|
451
452
|
}
|
|
452
453
|
if (!["1", "2", "3"].includes(templateData.tag)) {
|
|
453
|
-
throw new
|
|
454
|
+
throw new common_1.ZaloSDKError("tag phải là '1', '2' hoặc '3'", 400);
|
|
454
455
|
}
|
|
455
456
|
if (!templateData.layout) {
|
|
456
|
-
throw new
|
|
457
|
+
throw new common_1.ZaloSDKError("layout là bắt buộc", 400);
|
|
457
458
|
}
|
|
458
459
|
if (!Array.isArray(templateData.layout) && typeof templateData.layout !== 'object') {
|
|
459
|
-
throw new
|
|
460
|
+
throw new common_1.ZaloSDKError("layout phải là array hoặc object", 400);
|
|
460
461
|
}
|
|
461
462
|
if (!templateData.tracking_id) {
|
|
462
|
-
throw new
|
|
463
|
+
throw new common_1.ZaloSDKError("tracking_id là bắt buộc", 400);
|
|
463
464
|
}
|
|
464
465
|
}
|
|
465
466
|
/**
|
|
@@ -474,7 +475,7 @@ class ZNSService {
|
|
|
474
475
|
5: ["2"] // ZNS đánh giá dịch vụ
|
|
475
476
|
};
|
|
476
477
|
if (!compatibility[templateType]?.includes(tag)) {
|
|
477
|
-
throw new
|
|
478
|
+
throw new common_1.ZaloSDKError(`template_type ${templateType} không tương thích với tag ${tag}`, 400);
|
|
478
479
|
}
|
|
479
480
|
}
|
|
480
481
|
/**
|
|
@@ -507,7 +508,7 @@ class ZNSService {
|
|
|
507
508
|
allComponents = [...headerComponents, ...bodyComponents, ...footerComponents];
|
|
508
509
|
}
|
|
509
510
|
else {
|
|
510
|
-
throw new
|
|
511
|
+
throw new common_1.ZaloSDKError("layout phải là array hoặc object có cấu trúc header/body/footer", 400);
|
|
511
512
|
}
|
|
512
513
|
switch (templateType) {
|
|
513
514
|
case 1: // ZNS tùy chỉnh
|
|
@@ -533,20 +534,20 @@ class ZNSService {
|
|
|
533
534
|
* Check if component belongs to header
|
|
534
535
|
*/
|
|
535
536
|
isHeaderComponent(component) {
|
|
536
|
-
return
|
|
537
|
+
return 'LOGO' in component || 'IMAGES' in component;
|
|
537
538
|
}
|
|
538
539
|
/**
|
|
539
540
|
* Check if component belongs to body
|
|
540
541
|
*/
|
|
541
542
|
isBodyComponent(component) {
|
|
542
|
-
return
|
|
543
|
-
|
|
543
|
+
return 'TITLE' in component || 'PARAGRAPH' in component || 'TABLE' in component ||
|
|
544
|
+
'OTP' in component || 'PAYMENT' in component || 'VOUCHER' in component || 'RATING' in component;
|
|
544
545
|
}
|
|
545
546
|
/**
|
|
546
547
|
* Check if component belongs to footer
|
|
547
548
|
*/
|
|
548
549
|
isFooterComponent(component) {
|
|
549
|
-
return component
|
|
550
|
+
return 'BUTTONS' in component;
|
|
550
551
|
}
|
|
551
552
|
/**
|
|
552
553
|
* Validate custom template layout (type 1)
|
|
@@ -554,29 +555,29 @@ class ZNSService {
|
|
|
554
555
|
validateCustomTemplateLayout(header, body, footer) {
|
|
555
556
|
// Header: Logo OR Image (exactly 1)
|
|
556
557
|
if (header.length !== 1) {
|
|
557
|
-
throw new
|
|
558
|
+
throw new common_1.ZaloSDKError("ZNS tùy chỉnh phải có đúng 1 component trong header (Logo hoặc Image)", 400);
|
|
558
559
|
}
|
|
559
560
|
// Body: Title (1) + Paragraph (0-4) + Table (0-1)
|
|
560
|
-
const titles = body.filter(c => c
|
|
561
|
-
const paragraphs = body.filter(c => c
|
|
562
|
-
const tables = body.filter(c => c
|
|
561
|
+
const titles = body.filter(c => 'TITLE' in c);
|
|
562
|
+
const paragraphs = body.filter(c => 'PARAGRAPH' in c);
|
|
563
|
+
const tables = body.filter(c => 'TABLE' in c);
|
|
563
564
|
if (titles.length !== 1) {
|
|
564
|
-
throw new
|
|
565
|
+
throw new common_1.ZaloSDKError("ZNS tùy chỉnh phải có đúng 1 component TITLE", 400);
|
|
565
566
|
}
|
|
566
567
|
if (paragraphs.length > 4) {
|
|
567
|
-
throw new
|
|
568
|
+
throw new common_1.ZaloSDKError("ZNS tùy chỉnh không được có quá 4 component PARAGRAPH", 400);
|
|
568
569
|
}
|
|
569
570
|
if (tables.length > 1) {
|
|
570
|
-
throw new
|
|
571
|
+
throw new common_1.ZaloSDKError("ZNS tùy chỉnh không được có quá 1 component TABLE", 400);
|
|
571
572
|
}
|
|
572
573
|
// Footer: Buttons (0-2)
|
|
573
574
|
if (footer.length > 2) {
|
|
574
|
-
throw new
|
|
575
|
+
throw new common_1.ZaloSDKError("ZNS tùy chỉnh không được có quá 2 button", 400);
|
|
575
576
|
}
|
|
576
577
|
// If has image, must have at least 1 button
|
|
577
|
-
const hasImage = header.some(c => c
|
|
578
|
+
const hasImage = header.some(c => 'IMAGES' in c);
|
|
578
579
|
if (hasImage && footer.length === 0) {
|
|
579
|
-
throw new
|
|
580
|
+
throw new common_1.ZaloSDKError("ZNS có component Image phải có ít nhất 1 button", 400);
|
|
580
581
|
}
|
|
581
582
|
}
|
|
582
583
|
/**
|
|
@@ -584,21 +585,21 @@ class ZNSService {
|
|
|
584
585
|
*/
|
|
585
586
|
validateAuthTemplateLayout(header, body, footer) {
|
|
586
587
|
// Header: Logo only (1)
|
|
587
|
-
if (header.length !== 1 || !header[0]
|
|
588
|
-
throw new
|
|
588
|
+
if (header.length !== 1 || !('LOGO' in header[0])) {
|
|
589
|
+
throw new common_1.ZaloSDKError("ZNS xác thực phải có đúng 1 component LOGO trong header", 400);
|
|
589
590
|
}
|
|
590
591
|
// Body: OTP (1) + Paragraph (1)
|
|
591
|
-
const otps = body.filter(c => c
|
|
592
|
-
const paragraphs = body.filter(c => c
|
|
592
|
+
const otps = body.filter(c => 'OTP' in c);
|
|
593
|
+
const paragraphs = body.filter(c => 'PARAGRAPH' in c);
|
|
593
594
|
if (otps.length !== 1) {
|
|
594
|
-
throw new
|
|
595
|
+
throw new common_1.ZaloSDKError("ZNS xác thực phải có đúng 1 component OTP", 400);
|
|
595
596
|
}
|
|
596
597
|
if (paragraphs.length !== 1) {
|
|
597
|
-
throw new
|
|
598
|
+
throw new common_1.ZaloSDKError("ZNS xác thực phải có đúng 1 component PARAGRAPH", 400);
|
|
598
599
|
}
|
|
599
600
|
// Footer: None
|
|
600
601
|
if (footer.length > 0) {
|
|
601
|
-
throw new
|
|
602
|
+
throw new common_1.ZaloSDKError("ZNS xác thực không được có component trong footer", 400);
|
|
602
603
|
}
|
|
603
604
|
}
|
|
604
605
|
/**
|
|
@@ -606,29 +607,29 @@ class ZNSService {
|
|
|
606
607
|
*/
|
|
607
608
|
validatePaymentTemplateLayout(header, body, footer) {
|
|
608
609
|
// Header: Logo only (1)
|
|
609
|
-
if (header.length !== 1 || !header[0]
|
|
610
|
-
throw new
|
|
610
|
+
if (header.length !== 1 || !('LOGO' in header[0])) {
|
|
611
|
+
throw new common_1.ZaloSDKError("ZNS yêu cầu thanh toán phải có đúng 1 component LOGO trong header", 400);
|
|
611
612
|
}
|
|
612
613
|
// Body: Title (1) + Paragraph (0-4) + Table (0-1) + Payment (1)
|
|
613
|
-
const titles = body.filter(c => c
|
|
614
|
-
const paragraphs = body.filter(c => c
|
|
615
|
-
const tables = body.filter(c => c
|
|
616
|
-
const payments = body.filter(c => c
|
|
614
|
+
const titles = body.filter(c => 'TITLE' in c);
|
|
615
|
+
const paragraphs = body.filter(c => 'PARAGRAPH' in c);
|
|
616
|
+
const tables = body.filter(c => 'TABLE' in c);
|
|
617
|
+
const payments = body.filter(c => 'PAYMENT' in c);
|
|
617
618
|
if (titles.length !== 1) {
|
|
618
|
-
throw new
|
|
619
|
+
throw new common_1.ZaloSDKError("ZNS yêu cầu thanh toán phải có đúng 1 component TITLE", 400);
|
|
619
620
|
}
|
|
620
621
|
if (paragraphs.length > 4) {
|
|
621
|
-
throw new
|
|
622
|
+
throw new common_1.ZaloSDKError("ZNS yêu cầu thanh toán không được có quá 4 component PARAGRAPH", 400);
|
|
622
623
|
}
|
|
623
624
|
if (tables.length > 1) {
|
|
624
|
-
throw new
|
|
625
|
+
throw new common_1.ZaloSDKError("ZNS yêu cầu thanh toán không được có quá 1 component TABLE", 400);
|
|
625
626
|
}
|
|
626
627
|
if (payments.length !== 1) {
|
|
627
|
-
throw new
|
|
628
|
+
throw new common_1.ZaloSDKError("ZNS yêu cầu thanh toán phải có đúng 1 component PAYMENT", 400);
|
|
628
629
|
}
|
|
629
630
|
// Footer: Buttons (0-2)
|
|
630
631
|
if (footer.length > 2) {
|
|
631
|
-
throw new
|
|
632
|
+
throw new common_1.ZaloSDKError("ZNS yêu cầu thanh toán không được có quá 2 button", 400);
|
|
632
633
|
}
|
|
633
634
|
}
|
|
634
635
|
/**
|
|
@@ -637,33 +638,33 @@ class ZNSService {
|
|
|
637
638
|
validateVoucherTemplateLayout(header, body, footer) {
|
|
638
639
|
// Header: Logo OR Image (exactly 1)
|
|
639
640
|
if (header.length !== 1) {
|
|
640
|
-
throw new
|
|
641
|
+
throw new common_1.ZaloSDKError("ZNS voucher phải có đúng 1 component trong header (Logo hoặc Image)", 400);
|
|
641
642
|
}
|
|
642
643
|
// Body: Title (1) + Paragraph (0-4) + Table (0-1) + Voucher (1)
|
|
643
|
-
const titles = body.filter(c => c
|
|
644
|
-
const paragraphs = body.filter(c => c
|
|
645
|
-
const tables = body.filter(c => c
|
|
646
|
-
const vouchers = body.filter(c => c
|
|
644
|
+
const titles = body.filter(c => 'TITLE' in c);
|
|
645
|
+
const paragraphs = body.filter(c => 'PARAGRAPH' in c);
|
|
646
|
+
const tables = body.filter(c => 'TABLE' in c);
|
|
647
|
+
const vouchers = body.filter(c => 'VOUCHER' in c);
|
|
647
648
|
if (titles.length !== 1) {
|
|
648
|
-
throw new
|
|
649
|
+
throw new common_1.ZaloSDKError("ZNS voucher phải có đúng 1 component TITLE", 400);
|
|
649
650
|
}
|
|
650
651
|
if (paragraphs.length > 4) {
|
|
651
|
-
throw new
|
|
652
|
+
throw new common_1.ZaloSDKError("ZNS voucher không được có quá 4 component PARAGRAPH", 400);
|
|
652
653
|
}
|
|
653
654
|
if (tables.length > 1) {
|
|
654
|
-
throw new
|
|
655
|
+
throw new common_1.ZaloSDKError("ZNS voucher không được có quá 1 component TABLE", 400);
|
|
655
656
|
}
|
|
656
657
|
if (vouchers.length !== 1) {
|
|
657
|
-
throw new
|
|
658
|
+
throw new common_1.ZaloSDKError("ZNS voucher phải có đúng 1 component VOUCHER", 400);
|
|
658
659
|
}
|
|
659
660
|
// Footer: Buttons (0-2)
|
|
660
661
|
if (footer.length > 2) {
|
|
661
|
-
throw new
|
|
662
|
+
throw new common_1.ZaloSDKError("ZNS voucher không được có quá 2 button", 400);
|
|
662
663
|
}
|
|
663
664
|
// If has image, must have at least 1 button, max 2
|
|
664
|
-
const hasImage = header.some(c => c
|
|
665
|
+
const hasImage = header.some(c => 'IMAGES' in c);
|
|
665
666
|
if (hasImage && footer.length === 0) {
|
|
666
|
-
throw new
|
|
667
|
+
throw new common_1.ZaloSDKError("ZNS voucher có component Image phải có ít nhất 1 button", 400);
|
|
667
668
|
}
|
|
668
669
|
}
|
|
669
670
|
/**
|
|
@@ -671,59 +672,59 @@ class ZNSService {
|
|
|
671
672
|
*/
|
|
672
673
|
validateRatingTemplateLayout(header, body, footer) {
|
|
673
674
|
// Header: Logo only (1)
|
|
674
|
-
if (header.length !== 1 || !header[0]
|
|
675
|
-
throw new
|
|
675
|
+
if (header.length !== 1 || !('LOGO' in header[0])) {
|
|
676
|
+
throw new common_1.ZaloSDKError("ZNS đánh giá dịch vụ phải có đúng 1 component LOGO trong header", 400);
|
|
676
677
|
}
|
|
677
678
|
// Body: Title (1) + Paragraph (0-1) + Rating (1)
|
|
678
|
-
const titles = body.filter(c => c
|
|
679
|
-
const paragraphs = body.filter(c => c
|
|
680
|
-
const ratings = body.filter(c => c
|
|
679
|
+
const titles = body.filter(c => 'TITLE' in c);
|
|
680
|
+
const paragraphs = body.filter(c => 'PARAGRAPH' in c);
|
|
681
|
+
const ratings = body.filter(c => 'RATING' in c);
|
|
681
682
|
if (titles.length !== 1) {
|
|
682
|
-
throw new
|
|
683
|
+
throw new common_1.ZaloSDKError("ZNS đánh giá dịch vụ phải có đúng 1 component TITLE", 400);
|
|
683
684
|
}
|
|
684
685
|
if (paragraphs.length > 1) {
|
|
685
|
-
throw new
|
|
686
|
+
throw new common_1.ZaloSDKError("ZNS đánh giá dịch vụ không được có quá 1 component PARAGRAPH", 400);
|
|
686
687
|
}
|
|
687
688
|
if (ratings.length !== 1) {
|
|
688
|
-
throw new
|
|
689
|
+
throw new common_1.ZaloSDKError("ZNS đánh giá dịch vụ phải có đúng 1 component RATING", 400);
|
|
689
690
|
}
|
|
690
691
|
// Footer: Buttons (0-2)
|
|
691
692
|
if (footer.length > 2) {
|
|
692
|
-
throw new
|
|
693
|
+
throw new common_1.ZaloSDKError("ZNS đánh giá dịch vụ không được có quá 2 button", 400);
|
|
693
694
|
}
|
|
694
695
|
}
|
|
695
696
|
/**
|
|
696
697
|
* Validate individual component content
|
|
697
698
|
*/
|
|
698
699
|
validateComponent(component) {
|
|
699
|
-
if (component
|
|
700
|
+
if ('TITLE' in component) {
|
|
700
701
|
this.validateTitleComponent(component.TITLE);
|
|
701
702
|
}
|
|
702
|
-
if (component
|
|
703
|
+
if ('PARAGRAPH' in component) {
|
|
703
704
|
this.validateParagraphComponent(component.PARAGRAPH);
|
|
704
705
|
}
|
|
705
|
-
if (component
|
|
706
|
+
if ('OTP' in component) {
|
|
706
707
|
this.validateOTPComponent(component.OTP);
|
|
707
708
|
}
|
|
708
|
-
if (component
|
|
709
|
+
if ('TABLE' in component) {
|
|
709
710
|
this.validateTableComponent(component.TABLE);
|
|
710
711
|
}
|
|
711
|
-
if (component
|
|
712
|
+
if ('LOGO' in component) {
|
|
712
713
|
this.validateLogoComponent(component.LOGO);
|
|
713
714
|
}
|
|
714
|
-
if (component
|
|
715
|
+
if ('IMAGES' in component) {
|
|
715
716
|
this.validateImagesComponent(component.IMAGES);
|
|
716
717
|
}
|
|
717
|
-
if (component
|
|
718
|
+
if ('BUTTONS' in component) {
|
|
718
719
|
this.validateButtonsComponent(component.BUTTONS);
|
|
719
720
|
}
|
|
720
|
-
if (component
|
|
721
|
+
if ('PAYMENT' in component) {
|
|
721
722
|
this.validatePaymentComponent(component.PAYMENT);
|
|
722
723
|
}
|
|
723
|
-
if (component
|
|
724
|
+
if ('VOUCHER' in component) {
|
|
724
725
|
this.validateVoucherComponent(component.VOUCHER);
|
|
725
726
|
}
|
|
726
|
-
if (component
|
|
727
|
+
if ('RATING' in component) {
|
|
727
728
|
this.validateRatingComponent(component.RATING);
|
|
728
729
|
}
|
|
729
730
|
}
|
|
@@ -732,15 +733,15 @@ class ZNSService {
|
|
|
732
733
|
*/
|
|
733
734
|
validateTitleComponent(title) {
|
|
734
735
|
if (!title.value || typeof title.value !== 'string') {
|
|
735
|
-
throw new
|
|
736
|
+
throw new common_1.ZaloSDKError("TITLE component phải có field value kiểu string", 400);
|
|
736
737
|
}
|
|
737
738
|
if (title.value.length < 9 || title.value.length > 65) {
|
|
738
|
-
throw new
|
|
739
|
+
throw new common_1.ZaloSDKError("TITLE value phải có độ dài từ 9 đến 65 ký tự", 400);
|
|
739
740
|
}
|
|
740
741
|
// Check max 4 params
|
|
741
742
|
const paramCount = (title.value.match(/\{\{[^}]+\}\}/g) || []).length;
|
|
742
743
|
if (paramCount > 4) {
|
|
743
|
-
throw new
|
|
744
|
+
throw new common_1.ZaloSDKError("TITLE component không được có quá 4 params", 400);
|
|
744
745
|
}
|
|
745
746
|
}
|
|
746
747
|
/**
|
|
@@ -748,15 +749,15 @@ class ZNSService {
|
|
|
748
749
|
*/
|
|
749
750
|
validateParagraphComponent(paragraph) {
|
|
750
751
|
if (!paragraph.value || typeof paragraph.value !== 'string') {
|
|
751
|
-
throw new
|
|
752
|
+
throw new common_1.ZaloSDKError("PARAGRAPH component phải có field value kiểu string", 400);
|
|
752
753
|
}
|
|
753
754
|
if (paragraph.value.length < 9 || paragraph.value.length > 400) {
|
|
754
|
-
throw new
|
|
755
|
+
throw new common_1.ZaloSDKError("PARAGRAPH value phải có độ dài từ 9 đến 400 ký tự", 400);
|
|
755
756
|
}
|
|
756
757
|
// Check max 10 params
|
|
757
758
|
const paramCount = (paragraph.value.match(/\{\{[^}]+\}\}/g) || []).length;
|
|
758
759
|
if (paramCount > 10) {
|
|
759
|
-
throw new
|
|
760
|
+
throw new common_1.ZaloSDKError("PARAGRAPH component không được có quá 10 params", 400);
|
|
760
761
|
}
|
|
761
762
|
}
|
|
762
763
|
/**
|
|
@@ -764,10 +765,10 @@ class ZNSService {
|
|
|
764
765
|
*/
|
|
765
766
|
validateOTPComponent(otp) {
|
|
766
767
|
if (!otp.value || typeof otp.value !== 'string') {
|
|
767
|
-
throw new
|
|
768
|
+
throw new common_1.ZaloSDKError("OTP component phải có field value kiểu string", 400);
|
|
768
769
|
}
|
|
769
770
|
if (otp.value.length < 1 || otp.value.length > 10) {
|
|
770
|
-
throw new
|
|
771
|
+
throw new common_1.ZaloSDKError("OTP value phải có độ dài từ 1 đến 10 ký tự", 400);
|
|
771
772
|
}
|
|
772
773
|
}
|
|
773
774
|
/**
|
|
@@ -775,26 +776,26 @@ class ZNSService {
|
|
|
775
776
|
*/
|
|
776
777
|
validateTableComponent(table) {
|
|
777
778
|
if (!table.rows || !Array.isArray(table.rows)) {
|
|
778
|
-
throw new
|
|
779
|
+
throw new common_1.ZaloSDKError("TABLE component phải có field rows kiểu array", 400);
|
|
779
780
|
}
|
|
780
781
|
if (table.rows.length < 2 || table.rows.length > 8) {
|
|
781
|
-
throw new
|
|
782
|
+
throw new common_1.ZaloSDKError("TABLE rows phải có từ 2 đến 8 objects", 400);
|
|
782
783
|
}
|
|
783
784
|
table.rows.forEach((row, index) => {
|
|
784
785
|
if (!row.title || typeof row.title !== 'string') {
|
|
785
|
-
throw new
|
|
786
|
+
throw new common_1.ZaloSDKError(`TABLE row ${index + 1} phải có field title kiểu string`, 400);
|
|
786
787
|
}
|
|
787
788
|
if (row.title.length < 3 || row.title.length > 36) {
|
|
788
|
-
throw new
|
|
789
|
+
throw new common_1.ZaloSDKError(`TABLE row ${index + 1} title phải có độ dài từ 3 đến 36 ký tự`, 400);
|
|
789
790
|
}
|
|
790
791
|
if (!row.value || typeof row.value !== 'string') {
|
|
791
|
-
throw new
|
|
792
|
+
throw new common_1.ZaloSDKError(`TABLE row ${index + 1} phải có field value kiểu string`, 400);
|
|
792
793
|
}
|
|
793
794
|
if (row.value.length < 3 || row.value.length > 90) {
|
|
794
|
-
throw new
|
|
795
|
+
throw new common_1.ZaloSDKError(`TABLE row ${index + 1} value phải có độ dài từ 3 đến 90 ký tự`, 400);
|
|
795
796
|
}
|
|
796
797
|
if (row.row_type !== undefined && ![0, 1, 2, 3, 4, 5].includes(row.row_type)) {
|
|
797
|
-
throw new
|
|
798
|
+
throw new common_1.ZaloSDKError(`TABLE row ${index + 1} row_type phải là 0, 1, 2, 3, 4 hoặc 5`, 400);
|
|
798
799
|
}
|
|
799
800
|
});
|
|
800
801
|
}
|
|
@@ -803,7 +804,7 @@ class ZNSService {
|
|
|
803
804
|
*/
|
|
804
805
|
validateLogoComponent(logo) {
|
|
805
806
|
if (!logo.light || !logo.dark) {
|
|
806
|
-
throw new
|
|
807
|
+
throw new common_1.ZaloSDKError("LOGO component phải có cả light và dark attachment", 400);
|
|
807
808
|
}
|
|
808
809
|
this.validateAttachment(logo.light, "LOGO light");
|
|
809
810
|
this.validateAttachment(logo.dark, "LOGO dark");
|
|
@@ -813,10 +814,10 @@ class ZNSService {
|
|
|
813
814
|
*/
|
|
814
815
|
validateImagesComponent(images) {
|
|
815
816
|
if (!images.items || !Array.isArray(images.items)) {
|
|
816
|
-
throw new
|
|
817
|
+
throw new common_1.ZaloSDKError("IMAGES component phải có field items kiểu array", 400);
|
|
817
818
|
}
|
|
818
819
|
if (images.items.length < 1 || images.items.length > 3) {
|
|
819
|
-
throw new
|
|
820
|
+
throw new common_1.ZaloSDKError("IMAGES items phải có từ 1 đến 3 attachments", 400);
|
|
820
821
|
}
|
|
821
822
|
images.items.forEach((item, index) => {
|
|
822
823
|
this.validateAttachment(item, `IMAGES item ${index + 1}`);
|
|
@@ -827,23 +828,23 @@ class ZNSService {
|
|
|
827
828
|
*/
|
|
828
829
|
validateButtonsComponent(buttons) {
|
|
829
830
|
if (!buttons.items || !Array.isArray(buttons.items)) {
|
|
830
|
-
throw new
|
|
831
|
+
throw new common_1.ZaloSDKError("BUTTONS component phải có field items kiểu array", 400);
|
|
831
832
|
}
|
|
832
833
|
if (buttons.items.length < 1 || buttons.items.length > 2) {
|
|
833
|
-
throw new
|
|
834
|
+
throw new common_1.ZaloSDKError("BUTTONS items phải có từ 1 đến 2 objects", 400);
|
|
834
835
|
}
|
|
835
836
|
buttons.items.forEach((button, index) => {
|
|
836
837
|
if (!button.type || ![1, 2, 3, 4, 5, 6, 7, 8, 9].includes(button.type)) {
|
|
837
|
-
throw new
|
|
838
|
+
throw new common_1.ZaloSDKError(`BUTTON ${index + 1} type phải là 1, 2, 3, 4, 5, 6, 7, 8 hoặc 9`, 400);
|
|
838
839
|
}
|
|
839
840
|
if (!button.title || typeof button.title !== 'string') {
|
|
840
|
-
throw new
|
|
841
|
+
throw new common_1.ZaloSDKError(`BUTTON ${index + 1} phải có field title kiểu string`, 400);
|
|
841
842
|
}
|
|
842
843
|
if (button.title.length < 5 || button.title.length > 30) {
|
|
843
|
-
throw new
|
|
844
|
+
throw new common_1.ZaloSDKError(`BUTTON ${index + 1} title phải có độ dài từ 5 đến 30 ký tự`, 400);
|
|
844
845
|
}
|
|
845
846
|
if (!button.content || typeof button.content !== 'string') {
|
|
846
|
-
throw new
|
|
847
|
+
throw new common_1.ZaloSDKError(`BUTTON ${index + 1} phải có field content kiểu string`, 400);
|
|
847
848
|
}
|
|
848
849
|
});
|
|
849
850
|
}
|
|
@@ -852,25 +853,25 @@ class ZNSService {
|
|
|
852
853
|
*/
|
|
853
854
|
validatePaymentComponent(payment) {
|
|
854
855
|
if (!payment.bank_code || typeof payment.bank_code !== 'string') {
|
|
855
|
-
throw new
|
|
856
|
+
throw new common_1.ZaloSDKError("PAYMENT component phải có field bank_code kiểu string", 400);
|
|
856
857
|
}
|
|
857
858
|
if (!payment.account_name || typeof payment.account_name !== 'string') {
|
|
858
|
-
throw new
|
|
859
|
+
throw new common_1.ZaloSDKError("PAYMENT component phải có field account_name kiểu string", 400);
|
|
859
860
|
}
|
|
860
861
|
if (payment.account_name.length < 1 || payment.account_name.length > 100) {
|
|
861
|
-
throw new
|
|
862
|
+
throw new common_1.ZaloSDKError("PAYMENT account_name phải có độ dài từ 1 đến 100 ký tự", 400);
|
|
862
863
|
}
|
|
863
864
|
if (!payment.bank_account || typeof payment.bank_account !== 'string') {
|
|
864
|
-
throw new
|
|
865
|
+
throw new common_1.ZaloSDKError("PAYMENT component phải có field bank_account kiểu string", 400);
|
|
865
866
|
}
|
|
866
867
|
if (payment.bank_account.length < 1 || payment.bank_account.length > 100) {
|
|
867
|
-
throw new
|
|
868
|
+
throw new common_1.ZaloSDKError("PAYMENT bank_account phải có độ dài từ 1 đến 100 ký tự", 400);
|
|
868
869
|
}
|
|
869
870
|
if (!payment.amount) {
|
|
870
|
-
throw new
|
|
871
|
+
throw new common_1.ZaloSDKError("PAYMENT component phải có field amount", 400);
|
|
871
872
|
}
|
|
872
873
|
if (payment.note && (payment.note.length < 1 || payment.note.length > 90)) {
|
|
873
|
-
throw new
|
|
874
|
+
throw new common_1.ZaloSDKError("PAYMENT note phải có độ dài từ 1 đến 90 ký tự", 400);
|
|
874
875
|
}
|
|
875
876
|
}
|
|
876
877
|
/**
|
|
@@ -878,28 +879,28 @@ class ZNSService {
|
|
|
878
879
|
*/
|
|
879
880
|
validateVoucherComponent(voucher) {
|
|
880
881
|
if (!voucher.name || typeof voucher.name !== 'string') {
|
|
881
|
-
throw new
|
|
882
|
+
throw new common_1.ZaloSDKError("VOUCHER component phải có field name kiểu string", 400);
|
|
882
883
|
}
|
|
883
884
|
if (voucher.name.length < 1 || voucher.name.length > 30) {
|
|
884
|
-
throw new
|
|
885
|
+
throw new common_1.ZaloSDKError("VOUCHER name phải có độ dài từ 1 đến 30 ký tự", 400);
|
|
885
886
|
}
|
|
886
887
|
if (!voucher.condition || typeof voucher.condition !== 'string') {
|
|
887
|
-
throw new
|
|
888
|
+
throw new common_1.ZaloSDKError("VOUCHER component phải có field condition kiểu string", 400);
|
|
888
889
|
}
|
|
889
890
|
if (voucher.condition.length < 1 || voucher.condition.length > 40) {
|
|
890
|
-
throw new
|
|
891
|
+
throw new common_1.ZaloSDKError("VOUCHER condition phải có độ dài từ 1 đến 40 ký tự", 400);
|
|
891
892
|
}
|
|
892
893
|
if (!voucher.end_date || typeof voucher.end_date !== 'string') {
|
|
893
|
-
throw new
|
|
894
|
+
throw new common_1.ZaloSDKError("VOUCHER component phải có field end_date kiểu string", 400);
|
|
894
895
|
}
|
|
895
896
|
if (!voucher.voucher_code || typeof voucher.voucher_code !== 'string') {
|
|
896
|
-
throw new
|
|
897
|
+
throw new common_1.ZaloSDKError("VOUCHER component phải có field voucher_code kiểu string", 400);
|
|
897
898
|
}
|
|
898
899
|
if (voucher.voucher_code.length < 1 || voucher.voucher_code.length > 25) {
|
|
899
|
-
throw new
|
|
900
|
+
throw new common_1.ZaloSDKError("VOUCHER voucher_code phải có độ dài từ 1 đến 25 ký tự", 400);
|
|
900
901
|
}
|
|
901
902
|
if (voucher.display_code !== undefined && ![1, 2, 3].includes(voucher.display_code)) {
|
|
902
|
-
throw new
|
|
903
|
+
throw new common_1.ZaloSDKError("VOUCHER display_code phải là 1, 2 hoặc 3", 400);
|
|
903
904
|
}
|
|
904
905
|
}
|
|
905
906
|
/**
|
|
@@ -907,46 +908,46 @@ class ZNSService {
|
|
|
907
908
|
*/
|
|
908
909
|
validateRatingComponent(rating) {
|
|
909
910
|
if (!rating.items || !Array.isArray(rating.items)) {
|
|
910
|
-
throw new
|
|
911
|
+
throw new common_1.ZaloSDKError("RATING component phải có field items kiểu array", 400);
|
|
911
912
|
}
|
|
912
913
|
if (rating.items.length !== 5) {
|
|
913
|
-
throw new
|
|
914
|
+
throw new common_1.ZaloSDKError("RATING items phải có đúng 5 objects", 400);
|
|
914
915
|
}
|
|
915
916
|
rating.items.forEach((item, index) => {
|
|
916
|
-
const starValue = index + 1;
|
|
917
|
+
const starValue = (index + 1);
|
|
917
918
|
if (item.star !== starValue) {
|
|
918
|
-
throw new
|
|
919
|
+
throw new common_1.ZaloSDKError(`RATING item ${index + 1} phải có star = ${starValue}`, 400);
|
|
919
920
|
}
|
|
920
921
|
if (!item.title || typeof item.title !== 'string') {
|
|
921
|
-
throw new
|
|
922
|
+
throw new common_1.ZaloSDKError(`RATING item ${index + 1} phải có field title kiểu string`, 400);
|
|
922
923
|
}
|
|
923
924
|
if (item.title.length < 1 || item.title.length > 50) {
|
|
924
|
-
throw new
|
|
925
|
+
throw new common_1.ZaloSDKError(`RATING item ${index + 1} title phải có độ dài từ 1 đến 50 ký tự`, 400);
|
|
925
926
|
}
|
|
926
927
|
if (item.question && (item.question.length < 1 || item.question.length > 100)) {
|
|
927
|
-
throw new
|
|
928
|
+
throw new common_1.ZaloSDKError(`RATING item ${index + 1} question phải có độ dài từ 1 đến 100 ký tự`, 400);
|
|
928
929
|
}
|
|
929
930
|
if (item.answers && Array.isArray(item.answers)) {
|
|
930
931
|
if (item.answers.length < 1 || item.answers.length > 5) {
|
|
931
|
-
throw new
|
|
932
|
+
throw new common_1.ZaloSDKError(`RATING item ${index + 1} answers phải có từ 1 đến 5 câu trả lời`, 400);
|
|
932
933
|
}
|
|
933
934
|
item.answers.forEach((answer, answerIndex) => {
|
|
934
935
|
if (!answer || answer.length < 1 || answer.length > 50) {
|
|
935
|
-
throw new
|
|
936
|
+
throw new common_1.ZaloSDKError(`RATING item ${index + 1} answer ${answerIndex + 1} phải có độ dài từ 1 đến 50 ký tự`, 400);
|
|
936
937
|
}
|
|
937
938
|
});
|
|
938
939
|
}
|
|
939
940
|
if (!item.thanks || typeof item.thanks !== 'string') {
|
|
940
|
-
throw new
|
|
941
|
+
throw new common_1.ZaloSDKError(`RATING item ${index + 1} phải có field thanks kiểu string`, 400);
|
|
941
942
|
}
|
|
942
943
|
if (item.thanks.length < 1 || item.thanks.length > 100) {
|
|
943
|
-
throw new
|
|
944
|
+
throw new common_1.ZaloSDKError(`RATING item ${index + 1} thanks phải có độ dài từ 1 đến 100 ký tự`, 400);
|
|
944
945
|
}
|
|
945
946
|
if (!item.description || typeof item.description !== 'string') {
|
|
946
|
-
throw new
|
|
947
|
+
throw new common_1.ZaloSDKError(`RATING item ${index + 1} phải có field description kiểu string`, 400);
|
|
947
948
|
}
|
|
948
949
|
if (item.description.length < 1 || item.description.length > 200) {
|
|
949
|
-
throw new
|
|
950
|
+
throw new common_1.ZaloSDKError(`RATING item ${index + 1} description phải có độ dài từ 1 đến 200 ký tự`, 400);
|
|
950
951
|
}
|
|
951
952
|
});
|
|
952
953
|
}
|
|
@@ -955,10 +956,10 @@ class ZNSService {
|
|
|
955
956
|
*/
|
|
956
957
|
validateAttachment(attachment, context) {
|
|
957
958
|
if (!attachment.type || !attachment.media_id) {
|
|
958
|
-
throw new
|
|
959
|
+
throw new common_1.ZaloSDKError(`${context} phải có type và media_id`, 400);
|
|
959
960
|
}
|
|
960
961
|
if (attachment.type !== "IMAGE") {
|
|
961
|
-
throw new
|
|
962
|
+
throw new common_1.ZaloSDKError(`${context} type phải là "IMAGE"`, 400);
|
|
962
963
|
}
|
|
963
964
|
}
|
|
964
965
|
/**
|
|
@@ -995,36 +996,36 @@ class ZNSService {
|
|
|
995
996
|
// Validate each param
|
|
996
997
|
params.forEach((param, index) => {
|
|
997
998
|
if (!param.name || typeof param.name !== 'string') {
|
|
998
|
-
throw new
|
|
999
|
+
throw new common_1.ZaloSDKError(`Param ${index + 1} phải có field name kiểu string`, 400);
|
|
999
1000
|
}
|
|
1000
1001
|
if (!param.type || typeof param.type !== 'string') {
|
|
1001
|
-
throw new
|
|
1002
|
+
throw new common_1.ZaloSDKError(`Param ${index + 1} phải có field type kiểu string`, 400);
|
|
1002
1003
|
}
|
|
1003
1004
|
if (!Object.keys(paramTypeConstraints).includes(param.type)) {
|
|
1004
|
-
throw new
|
|
1005
|
+
throw new common_1.ZaloSDKError(`Param ${index + 1} type phải là 1-15`, 400);
|
|
1005
1006
|
}
|
|
1006
1007
|
if (!param.sample_value || typeof param.sample_value !== 'string') {
|
|
1007
|
-
throw new
|
|
1008
|
+
throw new common_1.ZaloSDKError(`Param ${index + 1} phải có field sample_value kiểu string`, 400);
|
|
1008
1009
|
}
|
|
1009
1010
|
// Validate sample_value length based on type
|
|
1010
1011
|
const maxLength = paramTypeConstraints[param.type];
|
|
1011
1012
|
if (param.sample_value.length > maxLength) {
|
|
1012
|
-
throw new
|
|
1013
|
+
throw new common_1.ZaloSDKError(`Param ${index + 1} sample_value không được vượt quá ${maxLength} ký tự cho type ${param.type}`, 400);
|
|
1013
1014
|
}
|
|
1014
1015
|
// Remove param from used set if found
|
|
1015
1016
|
usedParams.delete(param.name);
|
|
1016
1017
|
});
|
|
1017
1018
|
// Check if all used params are defined
|
|
1018
1019
|
if (usedParams.size > 0) {
|
|
1019
|
-
throw new
|
|
1020
|
+
throw new common_1.ZaloSDKError(`Các param sau được sử dụng trong layout nhưng chưa được định nghĩa: ${Array.from(usedParams).join(', ')}`, 400);
|
|
1020
1021
|
}
|
|
1021
1022
|
}
|
|
1022
1023
|
handleZNSError(error, defaultMessage) {
|
|
1023
1024
|
if (error.response?.data) {
|
|
1024
1025
|
const errorData = error.response.data;
|
|
1025
|
-
return new
|
|
1026
|
+
return new common_1.ZaloSDKError(`${defaultMessage}: ${errorData.message || errorData.error || "Unknown error"}`, errorData.error || -1, errorData);
|
|
1026
1027
|
}
|
|
1027
|
-
return new
|
|
1028
|
+
return new common_1.ZaloSDKError(`${defaultMessage}: ${error.message || "Unknown error"}`, -1, error);
|
|
1028
1029
|
}
|
|
1029
1030
|
}
|
|
1030
1031
|
exports.ZNSService = ZNSService;
|