@redonvn/zalo-ads-sdk 0.2.25 → 0.2.30

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/dist/index.js CHANGED
@@ -85,6 +85,7 @@ __export(index_exports, {
85
85
  ZaloAdsUpdateVideoAdRequest: () => ZaloAdsUpdateVideoAdRequest,
86
86
  ZaloAdsUpdateVideoAdResponse: () => ZaloAdsUpdateVideoAdResponse,
87
87
  ZaloAdsUseConversion: () => ZaloAdsUseConversion,
88
+ ZaloAdsVideoPlatform: () => ZaloAdsVideoPlatform,
88
89
  ZaloAdsVideoSrc: () => ZaloAdsVideoSrc,
89
90
  ZaloAdsXTemplates: () => ZaloAdsXTemplates,
90
91
  ZaloAudiencesService: () => ZaloAudiencesService,
@@ -1961,11 +1962,15 @@ var ZaloAdsActionType = {
1961
1962
  MUA_NGAY: 2,
1962
1963
  THU_NGAY: 3,
1963
1964
  TAI_NGAY: 4,
1965
+ /** Nút "Xem thêm" trên Quảng cáo Form (Type 18) gửi mã 4 */
1966
+ XEM_THEM_FORM: 4,
1964
1967
  XEM_THEM: 5,
1965
1968
  NGHE_NGAY: 6,
1966
1969
  CHOI_NGAY: 7,
1967
1970
  DANG_KY: 8,
1968
1971
  GOI_DIEN: 9,
1972
+ /** Nút bấm "Gửi tin nhắn" / "Nhắn tin" dành cho Quảng cáo Tin nhắn (Type 19/30) */
1973
+ NHAN_TIN: 10,
1969
1974
  /** Dành riêng cho Quảng cáo Official Account (Type 2) */
1970
1975
  QUAN_TAM_OA: 6
1971
1976
  };
@@ -1976,6 +1981,12 @@ var ZaloAdsVideoSrc = {
1976
1981
  /** Tự tải video lên hoặc chọn từ Thư viện Media */
1977
1982
  SELF_UPLOAD: 2
1978
1983
  };
1984
+ var ZaloAdsVideoPlatform = {
1985
+ /** Nền tảng Video (toàn màn hình như ZVideo, Báo Mới; sàn CPM 7,300đ) */
1986
+ VIDEO_NETWORK: 1,
1987
+ /** Nhật ký Zalo (Feed xen giữa tin bạn bè; sàn CPM 6,000đ) */
1988
+ ZALO_FEED: 2
1989
+ };
1979
1990
  var ZaloAdsBudgetScheduleType = {
1980
1991
  /** Toàn lịch chạy */
1981
1992
  TOTAL_SCHEDULE: 1,
@@ -2229,7 +2240,10 @@ var VALID_CAMPAIGN_TYPES = {
2229
2240
  var VALID_AD_TYPES = {
2230
2241
  WEBSITE: 5,
2231
2242
  FORM: 18,
2232
- MESSAGE: 30,
2243
+ MESSAGE: 19,
2244
+ // Mã chuẩn của máy chủ Zalo Ads khi UpdateAd
2245
+ MESSAGE_LEGACY: 30,
2246
+ // Hỗ trợ tương thích ngược
2233
2247
  OA: 2,
2234
2248
  VIDEO: 11,
2235
2249
  COMMERCE: 28,
@@ -2288,22 +2302,37 @@ var ALLOWED_CTAS_PER_AD_TYPE = {
2288
2302
  ZaloAdsActionType.CHOI_NGAY,
2289
2303
  ZaloAdsActionType.DANG_KY
2290
2304
  ],
2291
- // Form (Type 18): 5 CTAs
2305
+ // Form (Type 18): 5 CTAs (Đặt ngay: 1, Mua ngay: 2, Thử ngay: 3, Xem thêm: 4/5, Đăng ký: 8)
2292
2306
  [VALID_AD_TYPES.FORM]: [
2293
2307
  ZaloAdsActionType.DAT_NGAY,
2294
2308
  ZaloAdsActionType.MUA_NGAY,
2295
2309
  ZaloAdsActionType.THU_NGAY,
2310
+ 4,
2296
2311
  ZaloAdsActionType.XEM_THEM,
2297
2312
  ZaloAdsActionType.DANG_KY
2298
2313
  ],
2299
- // Commerce (Type 28): 3 CTAs
2314
+ // Commerce (Type 28): 3 CTAs (Đặt ngay: 1, Mua ngay: 2, Xem thêm: 4/5)
2300
2315
  [VALID_AD_TYPES.COMMERCE]: [
2301
2316
  ZaloAdsActionType.DAT_NGAY,
2302
2317
  ZaloAdsActionType.MUA_NGAY,
2318
+ 4,
2303
2319
  ZaloAdsActionType.XEM_THEM
2304
2320
  ],
2305
2321
  // OA (Type 2): Cố định Quan tâm OA (6)
2306
2322
  [VALID_AD_TYPES.OA]: [ZaloAdsActionType.QUAN_TAM_OA],
2323
+ // Message (Type 19 & Type 30 legacy):
2324
+ [VALID_AD_TYPES.MESSAGE]: [
2325
+ ZaloAdsActionType.NHAN_TIN,
2326
+ ZaloAdsActionType.XEM_THEM,
2327
+ ZaloAdsActionType.DANG_KY,
2328
+ ZaloAdsActionType.GOI_DIEN
2329
+ ],
2330
+ [VALID_AD_TYPES.MESSAGE_LEGACY]: [
2331
+ ZaloAdsActionType.NHAN_TIN,
2332
+ ZaloAdsActionType.XEM_THEM,
2333
+ ZaloAdsActionType.DANG_KY,
2334
+ ZaloAdsActionType.GOI_DIEN
2335
+ ],
2307
2336
  // Display (Type 21) & Display Halfpage (Type 26): Hỗ trợ các hành động cơ bản
2308
2337
  [VALID_AD_TYPES.DISPLAY]: [
2309
2338
  ZaloAdsActionType.DAT_NGAY,
@@ -2373,8 +2402,9 @@ function validateCreateCampaignPayload(payload, options = {}) {
2373
2402
  }
2374
2403
  switch (payload.campaignType) {
2375
2404
  case VALID_CAMPAIGN_TYPES.WEBSITE:
2405
+ case VALID_CAMPAIGN_TYPES.VIDEO:
2376
2406
  if (!payload.targetUrl || typeof payload.targetUrl !== "string" || !payload.targetUrl.trim()) {
2377
- errors.push("targetUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Website.");
2407
+ errors.push("targetUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Website / Video.");
2378
2408
  } else if (!/^https?:\/\/.+/i.test(payload.targetUrl)) {
2379
2409
  errors.push("targetUrl ph\u1EA3i l\xE0 m\u1ED9t \u0111\u01B0\u1EDDng link h\u1EE3p l\u1EC7 b\u1EAFt \u0111\u1EA7u b\u1EB1ng http:// ho\u1EB7c https://.");
2380
2410
  }
@@ -2500,20 +2530,149 @@ function validateUpdateAdPayload(payload, options = {}) {
2500
2530
  } else if (payload.Type === VALID_AD_TYPES.VIDEO) {
2501
2531
  if (price.Type !== 1 && price.Type !== 7) {
2502
2532
  errors.push(
2503
- "\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Video (Type 11) tr\xEAn Video Platform, Price.Type b\u1EAFt bu\u1ED9c l\xE0 1 (CPM - L\u01B0\u1EE3t hi\u1EC3n th\u1ECB) ho\u1EB7c 7 (CPV - L\u01B0\u1EE3t xem). N\u1EBFu truy\u1EC1n 2 (CPC), form ch\u1EC9nh s\u1EEDa c\u1EE7a Zalo Ads s\u1EBD kh\xF4ng hi\u1EC3n th\u1ECB \u0111\u01B0\u1EE3c gi\xE1 v\xE0 s\u1ED1 l\u01B0\u1EE3ng."
2533
+ "\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Video (Type 11), Price.Type b\u1EAFt bu\u1ED9c l\xE0 1 (CPM - L\u01B0\u1EE3t hi\u1EC3n th\u1ECB) ho\u1EB7c 7 (CPV - L\u01B0\u1EE3t xem). N\u1EBFu truy\u1EC1n 2 (CPC), form ch\u1EC9nh s\u1EEDa c\u1EE7a Zalo Ads s\u1EBD kh\xF4ng hi\u1EC3n th\u1ECB \u0111\u01B0\u1EE3c gi\xE1 v\xE0 s\u1ED1 l\u01B0\u1EE3ng."
2504
2534
  );
2505
2535
  }
2506
- if (price.Type === 1 && (price.Limit ?? 0) < 50) {
2536
+ if (price.Type === 1) {
2537
+ if ((price.Limit ?? 0) < 50) {
2538
+ errors.push(
2539
+ "\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Video CPM, s\u1ED1 l\u01B0\u1EE3ng hi\u1EC3n th\u1ECB t\u1ED1i thi\u1EC3u (Price.Limit) l\xE0 50 (t\u01B0\u01A1ng \u1EE9ng 50,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB)."
2540
+ );
2541
+ }
2542
+ const videoPlatform = payload.Settings?.VideoPlatform;
2543
+ if (videoPlatform === ZaloAdsVideoPlatform.VIDEO_NETWORK) {
2544
+ if (price.Bid !== void 0 && price.Bid < 7300) {
2545
+ errors.push(
2546
+ `Gi\xE1 \u0111\u1EB7t m\u1ED7i 1,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB (Price.Bid) cho N\u1EC1n t\u1EA3ng Video (ZVideo, B\xE1o M\u1EDBi) t\u1ED1i thi\u1EC3u l\xE0 7,300 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
2547
+ );
2548
+ }
2549
+ } else if (videoPlatform === ZaloAdsVideoPlatform.ZALO_FEED) {
2550
+ if (price.Bid !== void 0 && price.Bid < 6e3) {
2551
+ errors.push(
2552
+ `Gi\xE1 \u0111\u1EB7t m\u1ED7i 1,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB (Price.Bid) cho Video tr\xEAn Nh\u1EADt k\xFD Zalo t\u1ED1i thi\u1EC3u l\xE0 6,000 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
2553
+ );
2554
+ }
2555
+ } else {
2556
+ if (price.Bid !== void 0 && price.Bid < 6e3) {
2557
+ errors.push(
2558
+ `Gi\xE1 \u0111\u1EB7t m\u1ED7i 1,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB (Price.Bid) cho Qu\u1EA3ng c\xE1o Video t\u1ED1i thi\u1EC3u l\xE0 6,000 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
2559
+ );
2560
+ }
2561
+ }
2562
+ }
2563
+ } else if (payload.Type === VALID_AD_TYPES.COMMERCE) {
2564
+ if (price.Type !== 2 && price.Type !== 5) {
2507
2565
  errors.push(
2508
- "\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Video CPM, s\u1ED1 l\u01B0\u1EE3ng hi\u1EC3n th\u1ECB t\u1ED1i thi\u1EC3u (Price.Limit) l\xE0 50 (t\u01B0\u01A1ng \u1EE9ng 50,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB)."
2566
+ "\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Commerce (Type 28), Price.Type ch\u1EC9 h\u1ED7 tr\u1EE3 2 (CPC - L\u01B0\u1EE3t nh\u1EA5n) ho\u1EB7c 5 (CPA - L\u01B0\u1EE3t \u0111\u1EB7t h\xE0ng)."
2509
2567
  );
2510
2568
  }
2511
- } else if (payload.Type === VALID_AD_TYPES.COMMERCE || payload.Type === VALID_AD_TYPES.ARTICLE || payload.Type === VALID_AD_TYPES.FORM) {
2569
+ if (price.Type === 2) {
2570
+ if (price.SpendingMethod === 1) {
2571
+ if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 6e5) {
2572
+ errors.push(
2573
+ `T\u1ED5ng ng\xE2n s\xE1ch cho Qu\u1EA3ng c\xE1o Commerce CPC t\u1ED1i thi\u1EC3u l\xE0 600,000 VN\u0110 (Price.Limit >= 600000). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}\u0111.`
2574
+ );
2575
+ }
2576
+ } else if (price.SpendingMethod === 0) {
2577
+ if (price.Bid !== void 0 && price.Bid < 650) {
2578
+ errors.push(
2579
+ `Gi\xE1 \u0111\u1EB7t m\u1ED7i l\u01B0\u1EE3t nh\u1EA5n (Price.Bid) t\u1ED1i thi\u1EC3u l\xE0 650 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
2580
+ );
2581
+ }
2582
+ if (price.Limit !== void 0 && price.Limit < 50) {
2583
+ errors.push(
2584
+ `S\u1ED1 l\u01B0\u1EE3ng l\u01B0\u1EE3t nh\u1EA5n t\u1ED1i thi\u1EC3u (Price.Limit) m\u1ED7i ng\xE0y l\xE0 50 l\u01B0\u1EE3t. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}.`
2585
+ );
2586
+ }
2587
+ }
2588
+ } else if (price.Type === 5) {
2589
+ if (price.SpendingMethod === 1) {
2590
+ if (price.Bid !== void 0 && price.Bid !== 0) {
2591
+ errors.push(
2592
+ "Khi ch\u1ECDn 'T\u1ED5ng ng\xE2n s\xE1ch qu\u1EA3ng c\xE1o' (SpendingMethod = 1) cho L\u01B0\u1EE3t \u0111\u1EB7t h\xE0ng (CPA), tr\u01B0\u1EDDng Bid b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 0 (h\u1EC7 th\u1ED1ng t\u1EF1 \u0111\u1ED9ng \u0111\u1EA5u th\u1EA7u)."
2593
+ );
2594
+ }
2595
+ if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 15e5) {
2596
+ errors.push(
2597
+ `T\u1ED5ng ng\xE2n s\xE1ch cho Qu\u1EA3ng c\xE1o Commerce CPA (L\u01B0\u1EE3t \u0111\u1EB7t h\xE0ng t\u1EF1 \u0111\u1ED9ng) t\u1ED1i thi\u1EC3u l\xE0 1,500,000 VN\u0110 (Price.Limit >= 1500000). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}\u0111.`
2598
+ );
2599
+ }
2600
+ } else if (price.SpendingMethod === 0) {
2601
+ if (price.Bid !== void 0 && price.Bid < 6e4) {
2602
+ errors.push(
2603
+ `Gi\xE1 \u0111\u1EB7t m\u1ED7i l\u01B0\u1EE3t \u0111\u1EB7t h\xE0ng (Price.Bid) t\u1ED1i thi\u1EC3u l\xE0 60,000 VN\u0110 / l\u01B0\u1EE3t \u0111\u1EB7t h\xE0ng. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
2604
+ );
2605
+ }
2606
+ if (price.Limit !== void 0 && price.Limit < 10) {
2607
+ errors.push(
2608
+ `S\u1ED1 l\u01B0\u1EE3ng l\u01B0\u1EE3t \u0111\u1EB7t h\xE0ng t\u1ED1i thi\u1EC3u (Price.Limit) l\xE0 10 \u0111\u01A1n h\xE0ng (Limit >= 10). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}.`
2609
+ );
2610
+ }
2611
+ } else if (price.SpendingMethod !== void 0) {
2612
+ errors.push(
2613
+ "C\xE1ch \u0111\u1EB7t gi\xE1 SpendingMethod cho Qu\u1EA3ng c\xE1o Commerce CPA ch\u1EC9 ch\u1EA5p nh\u1EADn 1 (T\u1ED5ng ng\xE2n s\xE1ch qu\u1EA3ng c\xE1o) ho\u1EB7c 0 (T\u1EF1 \u0111\u1EB7t gi\xE1)."
2614
+ );
2615
+ }
2616
+ }
2617
+ } else if (payload.Type === VALID_AD_TYPES.ARTICLE) {
2512
2618
  if (price.Type !== 2) {
2513
2619
  errors.push(
2514
2620
  `\u0110\u1ED1i v\u1EDBi Ad Type ${payload.Type}, Price.Type b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 2 (CPC).`
2515
2621
  );
2516
2622
  }
2623
+ } else if (payload.Type === VALID_AD_TYPES.FORM) {
2624
+ if (price.Type !== 1 && price.Type !== 2 && price.Type !== 5) {
2625
+ errors.push(
2626
+ "\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Form (Type 18), Price.Type ch\u1EC9 h\u1ED7 tr\u1EE3 1 (CPM - L\u01B0\u1EE3t hi\u1EC3n th\u1ECB), 2 (CPC - L\u01B0\u1EE3t nh\u1EA5n) ho\u1EB7c 5 (CPA - L\u01B0\u1EE3t li\xEAn h\u1EC7)."
2627
+ );
2628
+ }
2629
+ if (price.Type === 1) {
2630
+ if (price.Bid !== void 0 && price.Bid < 7300) {
2631
+ errors.push(
2632
+ `Gi\xE1 \u0111\u1EB7t m\u1ED7i 1,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB (Price.Bid) cho Qu\u1EA3ng c\xE1o Form t\u1ED1i thi\u1EC3u l\xE0 7,300 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
2633
+ );
2634
+ }
2635
+ if (price.Limit !== void 0 && price.Limit < 50) {
2636
+ errors.push(
2637
+ `S\u1ED1 l\u01B0\u1EE3ng hi\u1EC3n th\u1ECB t\u1ED1i thi\u1EC3u (Price.Limit) cho Qu\u1EA3ng c\xE1o Form CPM l\xE0 50 (t\u01B0\u01A1ng \u1EE9ng 50,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}.`
2638
+ );
2639
+ }
2640
+ } else if (price.Type === 2) {
2641
+ if (price.SpendingMethod === 1) {
2642
+ if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 2e5) {
2643
+ errors.push(
2644
+ `Ng\xE2n s\xE1ch m\u1ED7i ng\xE0y cho Qu\u1EA3ng c\xE1o Form CPC t\u1ED1i thi\u1EC3u l\xE0 200,000 VN\u0110 (Price.Limit >= 200000). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}\u0111.`
2645
+ );
2646
+ }
2647
+ } else if (price.SpendingMethod === 0) {
2648
+ if (price.Bid !== void 0 && price.Bid < 650) {
2649
+ errors.push(
2650
+ `Gi\xE1 \u0111\u1EB7t m\u1ED7i l\u01B0\u1EE3t nh\u1EA5n (Price.Bid) t\u1ED1i thi\u1EC3u l\xE0 650 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
2651
+ );
2652
+ }
2653
+ if (price.Limit !== void 0 && price.Limit < 50) {
2654
+ errors.push(
2655
+ `S\u1ED1 l\u01B0\u1EE3ng l\u01B0\u1EE3t nh\u1EA5n t\u1ED1i thi\u1EC3u (Price.Limit) m\u1ED7i ng\xE0y l\xE0 50 l\u01B0\u1EE3t. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}.`
2656
+ );
2657
+ }
2658
+ }
2659
+ } else if (price.Type === 5) {
2660
+ if (price.SpendingMethod !== 1) {
2661
+ errors.push(
2662
+ "Khi t\xEDnh ti\u1EC1n theo L\u01B0\u1EE3t li\xEAn h\u1EC7 (Price.Type = 5 / CPA), SpendingMethod b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 1 (T\u1ED1i \u01B0u t\u1EF1 \u0111\u1ED9ng theo ng\xE2n s\xE1ch)."
2663
+ );
2664
+ }
2665
+ if (price.Bid !== void 0 && price.Bid !== 0) {
2666
+ errors.push(
2667
+ "Khi t\xEDnh ti\u1EC1n theo L\u01B0\u1EE3t li\xEAn h\u1EC7 (Price.Type = 5 / CPA), tr\u01B0\u1EDDng Bid b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 0 (Zalo Ads t\u1EF1 \u0111\u1ED9ng t\u1ED1i \u01B0u gi\xE1 th\u1EA7u, n\u1EBFu truy\u1EC1n > 0 m\xE1y ch\u1EE7 s\u1EBD b\xE1o l\u1ED7i code 13: Gi\xE1 \u0111\u1EB7t kh\xF4ng h\u1EE3p l\u1EC7)."
2668
+ );
2669
+ }
2670
+ if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 5e5) {
2671
+ errors.push(
2672
+ `Ng\xE2n s\xE1ch m\u1ED7i ng\xE0y cho Qu\u1EA3ng c\xE1o Form CPA (L\u01B0\u1EE3t li\xEAn h\u1EC7) t\u1ED1i thi\u1EC3u l\xE0 500,000 VN\u0110 (Price.Limit >= 500000). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}\u0111.`
2673
+ );
2674
+ }
2675
+ }
2517
2676
  } else if (payload.Type === VALID_AD_TYPES.OA) {
2518
2677
  if (price.Type !== 2 && price.Type !== 5) {
2519
2678
  errors.push(
@@ -2573,13 +2732,43 @@ function validateUpdateAdPayload(payload, options = {}) {
2573
2732
  );
2574
2733
  }
2575
2734
  }
2576
- } else if (payload.Type === VALID_AD_TYPES.MESSAGE) {
2577
- if (price.Type !== 2 && price.Type !== 5) {
2735
+ } else if (payload.Type === VALID_AD_TYPES.MESSAGE || payload.Type === VALID_AD_TYPES.MESSAGE_LEGACY || Number(payload.Type) === 19 || Number(payload.Type) === 30) {
2736
+ if (price.Type !== 1 && price.Type !== 2 && price.Type !== 5) {
2578
2737
  errors.push(
2579
- "\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Tin nh\u1EAFn (Type 30), Price.Type ch\u1EC9 h\u1ED7 tr\u1EE3 2 (L\u01B0\u1EE3t nh\u1EA5n - CPC) ho\u1EB7c 5 (L\u01B0\u1EE3t li\xEAn h\u1EC7 - CPA)."
2738
+ "\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Tin nh\u1EAFn (Type 19), Price.Type ch\u1EC9 h\u1ED7 tr\u1EE3 1 (CPM - L\u01B0\u1EE3t hi\u1EC3n th\u1ECB), 2 (CPC - L\u01B0\u1EE3t nh\u1EA5n) ho\u1EB7c 5 (CPA - L\u01B0\u1EE3t li\xEAn h\u1EC7)."
2580
2739
  );
2581
2740
  }
2582
- if (price.Type === 5) {
2741
+ if (price.Type === 1) {
2742
+ if (price.Bid !== void 0 && price.Bid < 7300) {
2743
+ errors.push(
2744
+ `Gi\xE1 \u0111\u1EB7t m\u1ED7i 1,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB (Price.Bid) cho Qu\u1EA3ng c\xE1o Tin nh\u1EAFn t\u1ED1i thi\u1EC3u l\xE0 7,300 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
2745
+ );
2746
+ }
2747
+ if (price.Limit !== void 0 && price.Limit < 50) {
2748
+ errors.push(
2749
+ `S\u1ED1 l\u01B0\u1EE3ng hi\u1EC3n th\u1ECB t\u1ED1i thi\u1EC3u (Price.Limit) cho Qu\u1EA3ng c\xE1o Tin nh\u1EAFn CPM l\xE0 50 (t\u01B0\u01A1ng \u1EE9ng 50,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}.`
2750
+ );
2751
+ }
2752
+ } else if (price.Type === 2) {
2753
+ if (price.SpendingMethod === 1) {
2754
+ if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 2e5) {
2755
+ errors.push(
2756
+ `Ng\xE2n s\xE1ch m\u1ED7i ng\xE0y cho Qu\u1EA3ng c\xE1o Tin nh\u1EAFn CPC t\u1ED1i thi\u1EC3u l\xE0 200,000 VN\u0110 (Price.Limit >= 200000). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}\u0111.`
2757
+ );
2758
+ }
2759
+ } else if (price.SpendingMethod === 0) {
2760
+ if (price.Bid !== void 0 && price.Bid < 650) {
2761
+ errors.push(
2762
+ `Gi\xE1 \u0111\u1EB7t m\u1ED7i l\u01B0\u1EE3t nh\u1EA5n (Price.Bid) t\u1ED1i thi\u1EC3u l\xE0 650 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
2763
+ );
2764
+ }
2765
+ if (price.Limit !== void 0 && price.Limit < 50) {
2766
+ errors.push(
2767
+ `S\u1ED1 l\u01B0\u1EE3ng l\u01B0\u1EE3t nh\u1EA5n t\u1ED1i thi\u1EC3u (Price.Limit) m\u1ED7i ng\xE0y l\xE0 50 l\u01B0\u1EE3t. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}.`
2768
+ );
2769
+ }
2770
+ }
2771
+ } else if (price.Type === 5) {
2583
2772
  if (price.SpendingMethod !== 1) {
2584
2773
  errors.push(
2585
2774
  "Khi t\xEDnh ti\u1EC1n theo L\u01B0\u1EE3t li\xEAn h\u1EC7 (Price.Type = 5 / CPA), SpendingMethod b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 1 (T\u1ED1i \u01B0u t\u1EF1 \u0111\u1ED9ng theo ng\xE2n s\xE1ch)."
@@ -2590,11 +2779,11 @@ function validateUpdateAdPayload(payload, options = {}) {
2590
2779
  "Khi t\xEDnh ti\u1EC1n theo L\u01B0\u1EE3t li\xEAn h\u1EC7 (Price.Type = 5 / CPA), tr\u01B0\u1EDDng Bid b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 0 (Zalo Ads t\u1EF1 \u0111\u1ED9ng t\u1ED1i \u01B0u gi\xE1 th\u1EA7u, n\u1EBFu truy\u1EC1n > 0 m\xE1y ch\u1EE7 s\u1EBD b\xE1o l\u1ED7i code 13: Gi\xE1 \u0111\u1EB7t kh\xF4ng h\u1EE3p l\u1EC7)."
2591
2780
  );
2592
2781
  }
2593
- }
2594
- if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 6e5) {
2595
- errors.push(
2596
- "Ng\xE2n s\xE1ch t\u1ED1i thi\u1EC3u cho Qu\u1EA3ng c\xE1o Tin nh\u1EAFn l\xE0 600,000 VN\u0110 (Price.Limit >= 600000). N\u1EBFu \u0111\u1EB7t d\u01B0\u1EDBi 600k m\xE1y ch\u1EE7 s\u1EBD t\u1EEB ch\u1ED1i."
2597
- );
2782
+ if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 5e5) {
2783
+ errors.push(
2784
+ `Ng\xE2n s\xE1ch m\u1ED7i ng\xE0y cho Qu\u1EA3ng c\xE1o Tin nh\u1EAFn CPA (L\u01B0\u1EE3t li\xEAn h\u1EC7) t\u1ED1i thi\u1EC3u l\xE0 500,000 VN\u0110 (Price.Limit >= 500000). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}\u0111.`
2785
+ );
2786
+ }
2598
2787
  }
2599
2788
  } else if (Number(payload.Type) === 21 || Number(payload.Type) === 23 || Number(payload.Type) === 26 || payload.Type === VALID_AD_TYPES.DISPLAY || payload.Type === VALID_AD_TYPES.DISPLAY_HALFPAGE || payload.Type === VALID_AD_TYPES.DISPLAY_MEDIUM_RECTANGLE) {
2600
2789
  const adFormat = payload.Settings?.AdInfo?.AdFormat;
@@ -2709,6 +2898,14 @@ function validateUpdateAdPayload(payload, options = {}) {
2709
2898
  errors.push(`M\xE3 h\u1EC7 \u0111i\u1EC1u h\xE0nh kh\xF4ng h\u1EE3p l\u1EC7: ${invalidOs.join(", ")}. H\u1EE3p l\u1EC7: 0 (Android), 1 (iOS), 3 (PC).`);
2710
2899
  }
2711
2900
  }
2901
+ const videoPlatform = payload.Settings?.VideoPlatform;
2902
+ if (videoPlatform !== void 0 && videoPlatform !== null) {
2903
+ if (![1, 2].includes(Number(videoPlatform))) {
2904
+ warnings.push(
2905
+ `VideoPlatform (${videoPlatform}) kh\xF4ng h\u1EE3p l\u1EC7. Gi\xE1 tr\u1ECB chu\u1EA9n: 1 (N\u1EC1n t\u1EA3ng Video - ZVideo, B\xE1o M\u1EDBi) ho\u1EB7c 2 (Nh\u1EADt k\xFD Zalo - Feed).`
2906
+ );
2907
+ }
2908
+ }
2712
2909
  const deliveryType = payload.Settings?.DeliveryType;
2713
2910
  if (deliveryType !== void 0 && deliveryType !== ZaloAdsDeliveryType.STANDARD && deliveryType !== ZaloAdsDeliveryType.SPEED_UP) {
2714
2911
  warnings.push(
@@ -2776,21 +2973,15 @@ function validateUpdateAdPayload(payload, options = {}) {
2776
2973
  if (!payload.ZaloFormId || !payload.ZaloFormId.trim()) {
2777
2974
  errors.push("ZaloFormId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Form (Ad Type 18).");
2778
2975
  }
2779
- } else if (payload.Type === VALID_AD_TYPES.MESSAGE) {
2976
+ } else if (payload.Type === VALID_AD_TYPES.MESSAGE || payload.Type === VALID_AD_TYPES.MESSAGE_LEGACY || Number(payload.Type) === 19 || Number(payload.Type) === 30) {
2780
2977
  if (!payload.Settings?.Image?.LogoUrl) {
2781
- errors.push("Settings.Image.LogoUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn (Ad Type 30).");
2782
- }
2783
- if (!payload.MiniPageId || payload.MiniPageId <= 0) {
2784
- errors.push(
2785
- "MiniPageId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn (Ad Type 30, Template 4 - K\u1ECBch b\u1EA3n gi\u1EDBi thi\u1EC7u th\u01B0\u01A1ng hi\u1EC7u / Tin nh\u1EAFn). N\u1EBFu thi\u1EBFu ho\u1EB7c = 0, m\xE1y ch\u1EE7 Zalo Ads s\u1EBD t\u1EEB ch\u1ED1i v\u1EDBi l\u1ED7i: 'Mini Page kh\xF4ng h\u1EE3p l\u1EC7.'."
2786
- );
2787
- }
2788
- if (!payload.ZaloFlowId) {
2789
- warnings.push("Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn n\xEAn g\u1EAFn ZaloFlowId \u0111\u1EC3 t\u1EF1 \u0111\u1ED9ng k\xEDch ho\u1EA1t k\u1ECBch b\u1EA3n chatbot t\u01B0\u01A1ng t\xE1c khi ng\u01B0\u1EDDi d\xF9ng m\u1EDF tin nh\u1EAFn.");
2978
+ errors.push("Settings.Image.LogoUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn (Ad Type 19/30).");
2790
2979
  }
2791
- if (payload.Settings?.Image?.ExtraImgs && payload.Settings?.Image?.ExtraImgs.length > 0) {
2980
+ const hasFlow = payload.ZaloFlowId && Number(payload.ZaloFlowId) > 0;
2981
+ const hasMiniPage = payload.MiniPageId && Number(payload.MiniPageId) > 0;
2982
+ if (!hasFlow && !hasMiniPage) {
2792
2983
  errors.push(
2793
- "Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn \u0111\u1ECBnh d\u1EA1ng \u1EA3nh \u0111\u01A1n (Landscape Cover) kh\xF4ng \u0111\u01B0\u1EE3c truy\u1EC1n m\u1EA3ng 'ExtraImgs'. N\u1EBFu truy\u1EC1n th\u1EEBa s\u1EBD b\u1ECB m\xE1y ch\u1EE7 b\xE1o l\u1ED7i 'D\u1EEF li\u1EC7u kh\xF4ng h\u1EE3p l\u1EC7'."
2984
+ "Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn y\xEAu c\u1EA7u ph\u1EA3i ch\u1ECDn K\u1ECBch b\u1EA3n tin nh\u1EAFn (ZaloFlowId > 0) ho\u1EB7c Trang gi\u1EDBi thi\u1EC7u th\u01B0\u01A1ng hi\u1EC7u (MiniPageId > 0)."
2794
2985
  );
2795
2986
  }
2796
2987
  } else if (payload.Type === VALID_AD_TYPES.COMMERCE) {
@@ -5165,6 +5356,18 @@ var OP_ZaloAdsPostApiMediaSave = {
5165
5356
  cookieFields: [],
5166
5357
  bodyFields: ["data"]
5167
5358
  };
5359
+ var OP_ZaloAdsPostApiMediaDelete = {
5360
+ operationId: "ZaloAds_postApiMediaDelete",
5361
+ method: "POST",
5362
+ endpoint: "/api/media/delete",
5363
+ baseUrl: "https://ads.zalo.me",
5364
+ binaryFields: [],
5365
+ pathFields: [],
5366
+ queryFields: [],
5367
+ headerFields: [],
5368
+ cookieFields: [],
5369
+ bodyFields: ["data"]
5370
+ };
5168
5371
  var OP_ZaloAdsPostApiMemberUploadImage = {
5169
5372
  operationId: "ZaloAds_postApiMemberUploadImage",
5170
5373
  method: "POST",
@@ -5326,6 +5529,36 @@ var ZaloMediaService = class {
5326
5529
  saveMedia(request, options) {
5327
5530
  return this.postApiMediaSave(request, options);
5328
5531
  }
5532
+ /**
5533
+ * Xóa tài nguyên media khỏi thư viện Zalo Ads theo danh sách IDs (`POST /api/media/delete`).
5534
+ * Phản hồi trả về `{ code: 0, data: <số_lượng_đã_xóa> }`.
5535
+ */
5536
+ postApiMediaDelete(request, options) {
5537
+ let payloadData;
5538
+ if (typeof request.data === "string") {
5539
+ payloadData = request.data;
5540
+ } else if (request.data && typeof request.data === "object") {
5541
+ payloadData = JSON.stringify(request.data);
5542
+ } else if (Array.isArray(request.ids)) {
5543
+ payloadData = JSON.stringify({ Ids: request.ids });
5544
+ } else {
5545
+ payloadData = JSON.stringify({ Ids: [] });
5546
+ }
5547
+ const normalized = {
5548
+ data: payloadData
5549
+ };
5550
+ return this.client.requestMultipart(
5551
+ OP_ZaloAdsPostApiMediaDelete,
5552
+ this.client.toTransportInput(OP_ZaloAdsPostApiMediaDelete, normalized),
5553
+ options
5554
+ );
5555
+ }
5556
+ /**
5557
+ * Alias cho `postApiMediaDelete`.
5558
+ */
5559
+ deleteMedia(request, options) {
5560
+ return this.postApiMediaDelete(request, options);
5561
+ }
5329
5562
  /**
5330
5563
  * Tải ảnh lên kho media của tài khoản quảng cáo (`POST /api/member/upload-image`).
5331
5564
  * Sử dụng multipart/form-data với trường `File` (chữ hoa). Trả về URL CDN Adtima.
@@ -9252,6 +9485,7 @@ var ZaloMediaValidator = {
9252
9485
  ZaloAdsUpdateVideoAdRequest,
9253
9486
  ZaloAdsUpdateVideoAdResponse,
9254
9487
  ZaloAdsUseConversion,
9488
+ ZaloAdsVideoPlatform,
9255
9489
  ZaloAdsVideoSrc,
9256
9490
  ZaloAdsXTemplates,
9257
9491
  ZaloAudiencesService,