@redonvn/zalo-ads-sdk 0.2.13 → 0.2.14
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.d.mts +651 -19
- package/dist/index.d.ts +651 -19
- package/dist/index.js +2468 -1543
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2442 -1543
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -32,15 +32,28 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
ALLOWED_CTAS_PER_AD_TYPE: () => ALLOWED_CTAS_PER_AD_TYPE,
|
|
34
34
|
ALL_ZALO_ADS_DOMAINS: () => ALL_ZALO_ADS_DOMAINS,
|
|
35
|
+
AutomatedRuleActionTypeEnum: () => AutomatedRuleActionTypeEnum,
|
|
36
|
+
AutomatedRuleConditionFieldEnum: () => AutomatedRuleConditionFieldEnum,
|
|
37
|
+
AutomatedRuleFrequencyEnum: () => AutomatedRuleFrequencyEnum,
|
|
38
|
+
AutomatedRuleOperatorEnum: () => AutomatedRuleOperatorEnum,
|
|
39
|
+
AutomatedRuleScopeEnum: () => AutomatedRuleScopeEnum,
|
|
40
|
+
AutomatedRuleTimeRangeEnum: () => AutomatedRuleTimeRangeEnum,
|
|
41
|
+
ConversionLabelEnum: () => ConversionLabelEnum,
|
|
42
|
+
ConversionUrlTypeEnum: () => ConversionUrlTypeEnum,
|
|
35
43
|
MemoryZaloSessionStore: () => MemoryZaloSessionStore,
|
|
36
44
|
RedisZaloSessionStore: () => RedisZaloSessionStore,
|
|
37
45
|
TieredZaloSessionStore: () => TieredZaloSessionStore,
|
|
38
46
|
VALID_AD_TYPES: () => VALID_AD_TYPES,
|
|
39
47
|
VALID_CAMPAIGN_TYPES: () => VALID_CAMPAIGN_TYPES,
|
|
48
|
+
ZALO_NEW_REGION_PROVINCE_CODES: () => ZALO_NEW_REGION_PROVINCE_CODES,
|
|
49
|
+
ZALO_PROVINCE_MERGE_MAPPING: () => ZALO_PROVINCE_MERGE_MAPPING,
|
|
50
|
+
ZALO_REGION_PROVINCE_CODES: () => ZALO_REGION_PROVINCE_CODES,
|
|
40
51
|
ZaloAccountService: () => ZaloAccountService,
|
|
41
52
|
ZaloAdsAccountPool: () => ZaloAdsIntegrationManager,
|
|
42
53
|
ZaloAdsActionType: () => ZaloAdsActionType,
|
|
43
54
|
ZaloAdsAgeRangeId: () => ZaloAdsAgeRangeId,
|
|
55
|
+
ZaloAdsBudgetScheduleType: () => ZaloAdsBudgetScheduleType,
|
|
56
|
+
ZaloAdsCampaignStatus: () => ZaloAdsCampaignStatus,
|
|
44
57
|
ZaloAdsCreateFlowRequest: () => ZaloAdsCreateFlowRequest,
|
|
45
58
|
ZaloAdsCreateFlowResponse: () => ZaloAdsCreateFlowResponse,
|
|
46
59
|
ZaloAdsCreatePostCampaignRequest: () => ZaloAdsCreatePostCampaignRequest,
|
|
@@ -49,28 +62,40 @@ __export(index_exports, {
|
|
|
49
62
|
ZaloAdsFlowButtonDto: () => ZaloAdsFlowButtonDto,
|
|
50
63
|
ZaloAdsFlowChildMessageDto: () => ZaloAdsFlowChildMessageDto,
|
|
51
64
|
ZaloAdsFlowMessageDto: () => ZaloAdsFlowMessageDto,
|
|
65
|
+
ZaloAdsImageRatio: () => ZaloAdsImageRatio,
|
|
52
66
|
ZaloAdsIntegrationManager: () => ZaloAdsIntegrationManager,
|
|
53
67
|
ZaloAdsMessageAdUpdateDataDto: () => ZaloAdsMessageAdUpdateDataDto,
|
|
54
68
|
ZaloAdsOsId: () => ZaloAdsOsId,
|
|
69
|
+
ZaloAdsPriceLimitType: () => ZaloAdsPriceLimitType,
|
|
70
|
+
ZaloAdsPriceType: () => ZaloAdsPriceType,
|
|
71
|
+
ZaloAdsProvinceCode: () => ZaloAdsProvinceCode,
|
|
72
|
+
ZaloAdsRegionId: () => ZaloAdsRegionId,
|
|
55
73
|
ZaloAdsSdk: () => ZaloAdsSdk,
|
|
56
74
|
ZaloAdsService: () => ZaloAdsService,
|
|
75
|
+
ZaloAdsSpendingMethod: () => ZaloAdsSpendingMethod,
|
|
57
76
|
ZaloAdsUpdateMessageAdRequest: () => ZaloAdsUpdateMessageAdRequest,
|
|
58
77
|
ZaloAdsUpdateMessageAdResponse: () => ZaloAdsUpdateMessageAdResponse,
|
|
59
78
|
ZaloAdsUpdateVideoAdRequest: () => ZaloAdsUpdateVideoAdRequest,
|
|
60
79
|
ZaloAdsUpdateVideoAdResponse: () => ZaloAdsUpdateVideoAdResponse,
|
|
80
|
+
ZaloAdsUseConversion: () => ZaloAdsUseConversion,
|
|
81
|
+
ZaloAdsVideoSrc: () => ZaloAdsVideoSrc,
|
|
82
|
+
ZaloAdsXTemplates: () => ZaloAdsXTemplates,
|
|
61
83
|
ZaloAudiencesService: () => ZaloAudiencesService,
|
|
62
84
|
ZaloAudiencesValidator: () => ZaloAudiencesValidator,
|
|
63
85
|
ZaloAuthManager: () => ZaloAuthManager,
|
|
64
86
|
ZaloAutomatedRulesService: () => ZaloAutomatedRulesService,
|
|
87
|
+
ZaloAutomatedRulesValidator: () => ZaloAutomatedRulesValidator,
|
|
65
88
|
ZaloCampaignsService: () => ZaloCampaignsService,
|
|
66
89
|
ZaloCampaignsValidator: () => ZaloCampaignsValidator,
|
|
67
90
|
ZaloChatWidgetService: () => ZaloChatWidgetService,
|
|
68
91
|
ZaloConversionsService: () => ZaloConversionsService,
|
|
92
|
+
ZaloConversionsValidator: () => ZaloConversionsValidator,
|
|
69
93
|
ZaloFlowsService: () => ZaloFlowsService,
|
|
70
94
|
ZaloFlowsValidator: () => ZaloFlowsValidator,
|
|
71
95
|
ZaloFormsService: () => ZaloFormsService,
|
|
72
96
|
ZaloFormsValidator: () => ZaloFormsValidator,
|
|
73
97
|
ZaloInstantPageBlockType: () => ZaloInstantPageBlockType,
|
|
98
|
+
ZaloInstantPageSharePermission: () => ZaloInstantPageSharePermission,
|
|
74
99
|
ZaloInstantPagesService: () => ZaloInstantPagesService,
|
|
75
100
|
ZaloInstantPagesValidator: () => ZaloInstantPagesValidator,
|
|
76
101
|
ZaloMediaService: () => ZaloMediaService,
|
|
@@ -92,6 +117,7 @@ __export(index_exports, {
|
|
|
92
117
|
validateCreateFlowRequest: () => validateCreateFlowRequest,
|
|
93
118
|
validateCreateFormEventAudienceRequest: () => validateCreateFormEventAudienceRequest,
|
|
94
119
|
validateCreateFormRequest: () => validateCreateFormRequest,
|
|
120
|
+
validateCreateInstantPageRequest: () => validateCreateInstantPageRequest,
|
|
95
121
|
validateCreateLookalikeAudienceRequest: () => validateCreateLookalikeAudienceRequest,
|
|
96
122
|
validateCreateMessageOaEventAudienceRequest: () => validateCreateMessageOaEventAudienceRequest,
|
|
97
123
|
validateCreateMessagePersonalEventAudienceRequest: () => validateCreateMessagePersonalEventAudienceRequest,
|
|
@@ -1052,7 +1078,8 @@ var ZaloSdkHttpClient = class {
|
|
|
1052
1078
|
const body = asRecord(input.body);
|
|
1053
1079
|
if (bodyType === "json") {
|
|
1054
1080
|
headers.set("content-type", headers.get("content-type") ?? "application/json");
|
|
1055
|
-
|
|
1081
|
+
const jsonPayload = input.body !== void 0 ? input.body : body;
|
|
1082
|
+
init.body = JSON.stringify(jsonPayload);
|
|
1056
1083
|
} else if (bodyType === "urlencoded") {
|
|
1057
1084
|
headers.set("content-type", headers.get("content-type") ?? "application/x-www-form-urlencoded;charset=UTF-8");
|
|
1058
1085
|
const encoded = new URLSearchParams();
|
|
@@ -1168,1742 +1195,2242 @@ async function resolveCookies(auth, context) {
|
|
|
1168
1195
|
return { ...auth?.cookies ?? {}, ...await auth?.getCookies?.(context) ?? {} };
|
|
1169
1196
|
}
|
|
1170
1197
|
|
|
1171
|
-
// src/
|
|
1172
|
-
var
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
var ZaloAdsCreateFlowRequest = class {
|
|
1203
|
-
/** ID Official Account sở hữu kịch bản. */
|
|
1204
|
-
oaId;
|
|
1205
|
-
/** Luôn null khi tạo kịch bản mới. */
|
|
1206
|
-
id;
|
|
1207
|
-
/** Tên kịch bản, tối đa 33 ký tự theo giao diện Zalo Ads. */
|
|
1208
|
-
name;
|
|
1209
|
-
/** Các tin nhắn được gửi theo thứ tự trong kịch bản. */
|
|
1210
|
-
messages;
|
|
1211
|
-
};
|
|
1212
|
-
var ZaloAdsCreateFlowResponse = class {
|
|
1213
|
-
/** 0 khi tạo thành công; 1 khi lỗi (ví dụ: đã tới hạn mức 20 kịch bản). */
|
|
1214
|
-
code;
|
|
1215
|
-
/** Thông báo lỗi từ Zalo Ads khi code khác 0. */
|
|
1216
|
-
msg;
|
|
1217
|
-
/** ID kịch bản mới, truyền vào data.ZaloFlowId khi cập nhật quảng cáo Tin nhắn. */
|
|
1218
|
-
data;
|
|
1219
|
-
};
|
|
1220
|
-
var ZaloAdsActionType = {
|
|
1221
|
-
DAT_NGAY: 1,
|
|
1222
|
-
MUA_NGAY: 2,
|
|
1223
|
-
THU_NGAY: 3,
|
|
1224
|
-
TAI_NGAY: 4,
|
|
1225
|
-
XEM_THEM: 5,
|
|
1226
|
-
QUAN_TAM_OA: 6,
|
|
1227
|
-
NGHE_NGAY: 7,
|
|
1228
|
-
CHOI_NGAY: 8,
|
|
1229
|
-
DANG_KY: 9,
|
|
1230
|
-
GOI_DIEN: 10
|
|
1231
|
-
};
|
|
1232
|
-
var ZaloAdsAgeRangeId = {
|
|
1233
|
-
UNDER_18: 10282,
|
|
1234
|
-
FROM_18_TO_24: 10283,
|
|
1235
|
-
FROM_25_TO_34: 10284,
|
|
1236
|
-
FROM_35_TO_44: 10285,
|
|
1237
|
-
FROM_45_TO_54: 10286,
|
|
1238
|
-
FROM_55_TO_64: 10287,
|
|
1239
|
-
OVER_64: 10288
|
|
1240
|
-
};
|
|
1241
|
-
var ZaloAdsOsId = {
|
|
1242
|
-
ANDROID: 0,
|
|
1243
|
-
IOS: 1,
|
|
1244
|
-
PC: 3
|
|
1245
|
-
};
|
|
1246
|
-
var ZaloAdsDeliveryType = {
|
|
1247
|
-
STANDARD: 1,
|
|
1248
|
-
ACCELERATED: 2
|
|
1249
|
-
};
|
|
1250
|
-
var ZaloAdsUpdateVideoAdRequest = class {
|
|
1251
|
-
data;
|
|
1252
|
-
est;
|
|
1253
|
-
isBoostAd;
|
|
1254
|
-
stt;
|
|
1255
|
-
};
|
|
1256
|
-
var ZaloAdsUpdateVideoAdResponse = class {
|
|
1257
|
-
code;
|
|
1258
|
-
msg;
|
|
1259
|
-
data;
|
|
1260
|
-
};
|
|
1261
|
-
var ZaloAdsCreatePostCampaignRequest = class {
|
|
1262
|
-
/** Cấu hình chiến dịch Bài viết (object hoặc chuỗi JSON). */
|
|
1263
|
-
data;
|
|
1264
|
-
};
|
|
1265
|
-
var ZaloAdsCreatePostCampaignResponse = class {
|
|
1266
|
-
code;
|
|
1267
|
-
/** Chuỗi ID quảng cáo mới trong response Zalo Ads. */
|
|
1268
|
-
msg;
|
|
1269
|
-
data;
|
|
1270
|
-
};
|
|
1271
|
-
var ZaloAdsMessageAdUpdateDataDto = class {
|
|
1272
|
-
AdId;
|
|
1273
|
-
CampaignId;
|
|
1274
|
-
MemberId;
|
|
1275
|
-
/** Phiên bản lạc quan lấy từ bản quảng cáo hiện tại. */
|
|
1276
|
-
RowVersion;
|
|
1277
|
-
AdName;
|
|
1278
|
-
/** 20 (hoặc 19) là quảng cáo Tin nhắn. */
|
|
1279
|
-
Type;
|
|
1280
|
-
Settings;
|
|
1281
|
-
Status;
|
|
1282
|
-
StartDate;
|
|
1283
|
-
EndDate;
|
|
1284
|
-
/** ID kịch bản, lấy từ createFlow hoặc listFlowsByOfficialAccount. */
|
|
1285
|
-
ZaloFlowId;
|
|
1286
|
-
ZaloPageId;
|
|
1287
|
-
ZaloFormId;
|
|
1288
|
-
ConversionId;
|
|
1289
|
-
Report;
|
|
1290
|
-
};
|
|
1291
|
-
var ZaloAdsUpdateMessageAdRequest = class {
|
|
1292
|
-
/** Payload quảng cáo đầy đủ (object hoặc chuỗi JSON); service tự tuần tự hóa thành field form data. */
|
|
1293
|
-
data;
|
|
1294
|
-
/** Tham số UI phụ trợ; capture Zalo Ads có giá trị literal "undefined". */
|
|
1295
|
-
est;
|
|
1296
|
-
/** 0 là quảng cáo thông thường, 1 là boost ad. */
|
|
1297
|
-
isBoostAd;
|
|
1298
|
-
/** Trạng thái thao tác của giao diện; mẫu đã ghi nhận 0. */
|
|
1299
|
-
stt;
|
|
1300
|
-
};
|
|
1301
|
-
var ZaloAdsUpdateMessageAdResponse = class {
|
|
1302
|
-
msg;
|
|
1303
|
-
code;
|
|
1304
|
-
data;
|
|
1305
|
-
};
|
|
1306
|
-
|
|
1307
|
-
// src/validators/campaigns.validator.ts
|
|
1308
|
-
var VALID_CAMPAIGN_TYPES = {
|
|
1309
|
-
WEBSITE: 6,
|
|
1310
|
-
FORM: 17,
|
|
1311
|
-
MESSAGE: 18,
|
|
1312
|
-
OA: 3,
|
|
1313
|
-
VIDEO: 14,
|
|
1314
|
-
COMMERCE: 22,
|
|
1315
|
-
ARTICLE: 4,
|
|
1316
|
-
DISPLAY: 20
|
|
1317
|
-
};
|
|
1318
|
-
var VALID_AD_TYPES = {
|
|
1319
|
-
WEBSITE: 5,
|
|
1320
|
-
FORM: 18,
|
|
1321
|
-
MESSAGE: 30,
|
|
1322
|
-
OA: 2,
|
|
1323
|
-
VIDEO: 11,
|
|
1324
|
-
COMMERCE: 28,
|
|
1325
|
-
// Server trả về 28 (không phải 23)
|
|
1326
|
-
ARTICLE: 3,
|
|
1327
|
-
DISPLAY: 21
|
|
1328
|
-
};
|
|
1329
|
-
var ALLOWED_CTAS_PER_AD_TYPE = {
|
|
1330
|
-
// Website (Type 5): 9 CTAs
|
|
1331
|
-
[VALID_AD_TYPES.WEBSITE]: [
|
|
1332
|
-
ZaloAdsActionType.DAT_NGAY,
|
|
1333
|
-
ZaloAdsActionType.MUA_NGAY,
|
|
1334
|
-
ZaloAdsActionType.THU_NGAY,
|
|
1335
|
-
ZaloAdsActionType.TAI_NGAY,
|
|
1336
|
-
ZaloAdsActionType.XEM_THEM,
|
|
1337
|
-
ZaloAdsActionType.NGHE_NGAY,
|
|
1338
|
-
ZaloAdsActionType.CHOI_NGAY,
|
|
1339
|
-
ZaloAdsActionType.DANG_KY,
|
|
1340
|
-
ZaloAdsActionType.GOI_DIEN
|
|
1341
|
-
],
|
|
1342
|
-
// Video (Type 11): 8 CTAs
|
|
1343
|
-
[VALID_AD_TYPES.VIDEO]: [
|
|
1344
|
-
ZaloAdsActionType.DAT_NGAY,
|
|
1345
|
-
ZaloAdsActionType.MUA_NGAY,
|
|
1346
|
-
ZaloAdsActionType.THU_NGAY,
|
|
1347
|
-
ZaloAdsActionType.TAI_NGAY,
|
|
1348
|
-
ZaloAdsActionType.XEM_THEM,
|
|
1349
|
-
ZaloAdsActionType.NGHE_NGAY,
|
|
1350
|
-
ZaloAdsActionType.CHOI_NGAY,
|
|
1351
|
-
ZaloAdsActionType.DANG_KY
|
|
1352
|
-
],
|
|
1353
|
-
// Article (Type 3): 7 CTAs
|
|
1354
|
-
[VALID_AD_TYPES.ARTICLE]: [
|
|
1355
|
-
ZaloAdsActionType.DAT_NGAY,
|
|
1356
|
-
ZaloAdsActionType.MUA_NGAY,
|
|
1357
|
-
ZaloAdsActionType.THU_NGAY,
|
|
1358
|
-
ZaloAdsActionType.TAI_NGAY,
|
|
1359
|
-
ZaloAdsActionType.XEM_THEM,
|
|
1360
|
-
ZaloAdsActionType.CHOI_NGAY,
|
|
1361
|
-
ZaloAdsActionType.DANG_KY
|
|
1362
|
-
],
|
|
1363
|
-
// Form (Type 18): 5 CTAs
|
|
1364
|
-
[VALID_AD_TYPES.FORM]: [
|
|
1365
|
-
ZaloAdsActionType.DAT_NGAY,
|
|
1366
|
-
ZaloAdsActionType.MUA_NGAY,
|
|
1367
|
-
ZaloAdsActionType.THU_NGAY,
|
|
1368
|
-
ZaloAdsActionType.XEM_THEM,
|
|
1369
|
-
ZaloAdsActionType.DANG_KY
|
|
1198
|
+
// src/validators/audiences.validator.ts
|
|
1199
|
+
var ZALO_REGION_PROVINCE_CODES = {
|
|
1200
|
+
1: [
|
|
1201
|
+
"VN58",
|
|
1202
|
+
"VN44",
|
|
1203
|
+
"VN72",
|
|
1204
|
+
"VN83",
|
|
1205
|
+
"VN50",
|
|
1206
|
+
"VN13",
|
|
1207
|
+
"VN82",
|
|
1208
|
+
"VN70",
|
|
1209
|
+
"VN53",
|
|
1210
|
+
"VN30",
|
|
1211
|
+
"VN74",
|
|
1212
|
+
"VN34",
|
|
1213
|
+
"VN52",
|
|
1214
|
+
"VN79",
|
|
1215
|
+
"VN80",
|
|
1216
|
+
"VN32",
|
|
1217
|
+
"VN71",
|
|
1218
|
+
"VN59",
|
|
1219
|
+
"VN86",
|
|
1220
|
+
"VN05",
|
|
1221
|
+
"VN85",
|
|
1222
|
+
"VN39",
|
|
1223
|
+
"VN35",
|
|
1224
|
+
"VN89",
|
|
1225
|
+
"VN81",
|
|
1226
|
+
"VN92",
|
|
1227
|
+
"VN90",
|
|
1228
|
+
"VN68"
|
|
1370
1229
|
],
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1230
|
+
2: [
|
|
1231
|
+
"VN55",
|
|
1232
|
+
"VN88",
|
|
1233
|
+
"VN47",
|
|
1234
|
+
"VN62",
|
|
1235
|
+
"VN54",
|
|
1236
|
+
"VN61",
|
|
1237
|
+
"VN64",
|
|
1238
|
+
"VN49",
|
|
1239
|
+
"VN63",
|
|
1240
|
+
"VN46",
|
|
1241
|
+
"VN84",
|
|
1242
|
+
"VN66",
|
|
1243
|
+
"VN91",
|
|
1244
|
+
"VN60",
|
|
1245
|
+
"VN23",
|
|
1246
|
+
"VN78"
|
|
1376
1247
|
],
|
|
1377
|
-
|
|
1378
|
-
|
|
1248
|
+
3: [
|
|
1249
|
+
"VN87",
|
|
1250
|
+
"VN03",
|
|
1251
|
+
"VN76",
|
|
1252
|
+
"VN43",
|
|
1253
|
+
"VN65",
|
|
1254
|
+
"VN21",
|
|
1255
|
+
"VN24",
|
|
1256
|
+
"VN75",
|
|
1257
|
+
"VN45",
|
|
1258
|
+
"VN67",
|
|
1259
|
+
"VN01",
|
|
1260
|
+
"VN73",
|
|
1261
|
+
"VN77",
|
|
1262
|
+
"VN37",
|
|
1263
|
+
"VN20",
|
|
1264
|
+
"VN09",
|
|
1265
|
+
"VN69",
|
|
1266
|
+
"VN33",
|
|
1267
|
+
"VN93"
|
|
1268
|
+
]
|
|
1379
1269
|
};
|
|
1380
|
-
|
|
1270
|
+
var ZALO_NEW_REGION_PROVINCE_CODES = {
|
|
1271
|
+
1: ["VN58", "VN44", "VN83", "VN32", "VN59", "VN13", "VN89", "VN30", "VN74", "VN34", "VN52", "VN05", "VN85", "VN39", "VN81", "VN92", "VN90", "VN68"],
|
|
1272
|
+
2: ["VN66", "VN88", "VN54", "VN64", "VN49", "VN63", "VN23", "VN78"],
|
|
1273
|
+
3: ["VN20", "VN87", "VN43", "VN33", "VN01", "VN77", "VN09", "VN69"]
|
|
1274
|
+
};
|
|
1275
|
+
var ZALO_PROVINCE_MERGE_MAPPING = {
|
|
1276
|
+
VN75: { newCode: "VN20", regionId: 3, name: "B\xECnh D\u01B0\u01A1ng (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m H\u1ED3 Ch\xED Minh VN20)" },
|
|
1277
|
+
VN45: { newCode: "VN20", regionId: 3, name: "B\xE0 R\u1ECBa - V\u0169ng T\xE0u (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m H\u1ED3 Ch\xED Minh VN20)" },
|
|
1278
|
+
VN76: { newCode: "VN43", regionId: 3, name: "B\xECnh Ph\u01B0\u1EDBc (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m \u0110\u1ED3ng Nai VN43)" },
|
|
1279
|
+
VN24: { newCode: "VN33", regionId: 3, name: "Long An (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m T\xE2y Ninh VN33)" },
|
|
1280
|
+
VN21: { newCode: "VN01", regionId: 3, name: "Ki\xEAn Giang (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m An Giang VN01)" },
|
|
1281
|
+
VN73: { newCode: "VN77", regionId: 3, name: "B\u1EA1c Li\xEAu (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m C\xE0 Mau VN77)" },
|
|
1282
|
+
VN37: { newCode: "VN09", regionId: 3, name: "Ti\u1EC1n Giang (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m \u0110\u1ED3ng Th\xE1p VN09)" },
|
|
1283
|
+
VN03: { newCode: "VN69", regionId: 3, name: "B\u1EBFn Tre (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m V\u0129nh Long VN69)" },
|
|
1284
|
+
VN67: { newCode: "VN69", regionId: 3, name: "Tr\xE0 Vinh (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m V\u0129nh Long VN69)" },
|
|
1285
|
+
VN65: { newCode: "VN87", regionId: 3, name: "S\xF3c Tr\u0103ng (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m C\u1EA7n Th\u01A1 VN87)" },
|
|
1286
|
+
VN93: { newCode: "VN87", regionId: 3, name: "H\u1EADu Giang (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m C\u1EA7n Th\u01A1 VN87)" },
|
|
1287
|
+
VN61: { newCode: "VN88", regionId: 2, name: "Ph\xFA Y\xEAn (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m \u0110\u1EAFk L\u1EAFk VN88)" },
|
|
1288
|
+
VN60: { newCode: "VN54", regionId: 2, name: "Ninh Thu\u1EADn (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Kh\xE1nh H\xF2a VN54)" },
|
|
1289
|
+
VN62: { newCode: "VN64", regionId: 2, name: "Qu\u1EA3ng B\xECnh (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Qu\u1EA3ng Tr\u1ECB VN64)" },
|
|
1290
|
+
VN46: { newCode: "VN49", regionId: 2, name: "B\xECnh \u0110\u1ECBnh (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Gia Lai VN49)" },
|
|
1291
|
+
VN55: { newCode: "VN63", regionId: 2, name: "Kon Tum (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Qu\u1EA3ng Ng\xE3i VN63)" },
|
|
1292
|
+
VN47: { newCode: "VN23", regionId: 2, name: "B\xECnh Thu\u1EADn (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m L\xE2m \u0110\u1ED3ng VN23)" },
|
|
1293
|
+
VN91: { newCode: "VN23", regionId: 2, name: "\u0110\u1EAFk N\xF4ng (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m L\xE2m \u0110\u1ED3ng VN23)" },
|
|
1294
|
+
VN84: { newCode: "VN78", regionId: 2, name: "Qu\u1EA3ng Nam (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m \u0110\xE0 N\u1EB5ng VN78)" },
|
|
1295
|
+
VN86: { newCode: "VN83", regionId: 1, name: "Ninh B\xECnh (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Ph\xFA Th\u1ECD VN83)" },
|
|
1296
|
+
VN53: { newCode: "VN83", regionId: 1, name: "B\u1EAFc K\u1EA1n (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Ph\xFA Th\u1ECD VN83)" },
|
|
1297
|
+
VN82: { newCode: "VN59", regionId: 1, name: "B\u1EAFc Giang (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Ninh B\xECnh VN59)" },
|
|
1298
|
+
VN80: { newCode: "VN59", regionId: 1, name: "Ph\xFA Th\u1ECD c\u0169 (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Ninh B\xECnh VN59)" },
|
|
1299
|
+
VN79: { newCode: "VN13", regionId: 1, name: "H\u1EA3i D\u01B0\u01A1ng (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m H\u1EA3i Ph\xF2ng VN13)" },
|
|
1300
|
+
VN71: { newCode: "VN74", regionId: 1, name: "H\u01B0ng Y\xEAn c\u0169 (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m B\u1EAFc Ninh VN74)" },
|
|
1301
|
+
VN72: { newCode: "VN85", regionId: 1, name: "Y\xEAn B\xE1i (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Th\xE1i Nguy\xEAn VN85)" },
|
|
1302
|
+
VN35: { newCode: "VN81", regionId: 1, name: "Th\xE1i B\xECnh (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m H\u01B0ng Y\xEAn VN81)" },
|
|
1303
|
+
VN70: { newCode: "VN90", regionId: 1, name: "V\u0129nh Ph\xFAc (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m L\xE0o Cai VN90)" },
|
|
1304
|
+
VN50: { newCode: "VN68", regionId: 1, name: "H\xF2a B\xECnh (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Tuy\xEAn Quang VN68)" }
|
|
1305
|
+
};
|
|
1306
|
+
function validateCreateSavedAudienceRequest(input) {
|
|
1381
1307
|
const errors = [];
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
errors.push("name l\xE0 b\u1EAFt bu\u1ED9c v\xE0 kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
|
|
1385
|
-
} else if (payload.name.length > 255) {
|
|
1386
|
-
errors.push("name kh\xF4ng \u0111\u01B0\u1EE3c v\u01B0\u1EE3t qu\xE1 255 k\xFD t\u1EF1.");
|
|
1308
|
+
if (!input || typeof input !== "object") {
|
|
1309
|
+
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
1387
1310
|
}
|
|
1388
|
-
const
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
);
|
|
1311
|
+
const raw = input;
|
|
1312
|
+
const name = typeof raw.name === "string" ? raw.name.trim() : "";
|
|
1313
|
+
if (!name) {
|
|
1314
|
+
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
1315
|
+
} else if (name.length < 2 || name.length > 255) {
|
|
1316
|
+
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
|
|
1395
1317
|
}
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1318
|
+
let targetingObj;
|
|
1319
|
+
if (typeof raw.targeting === "string") {
|
|
1320
|
+
try {
|
|
1321
|
+
targetingObj = JSON.parse(raw.targeting);
|
|
1322
|
+
} catch {
|
|
1323
|
+
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
|
|
1324
|
+
targetingObj = {};
|
|
1399
1325
|
}
|
|
1326
|
+
} else if (raw.targeting && typeof raw.targeting === "object") {
|
|
1327
|
+
targetingObj = raw.targeting;
|
|
1400
1328
|
} else {
|
|
1401
|
-
|
|
1402
|
-
|
|
1329
|
+
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c (chu\u1ED7i JSON ho\u1EB7c Object c\u1EA5u h\xECnh targeting).");
|
|
1330
|
+
targetingObj = {};
|
|
1331
|
+
}
|
|
1332
|
+
const gender = typeof targetingObj.Gender === "number" ? targetingObj.Gender : 0;
|
|
1333
|
+
if (![0, 1, 2].includes(gender)) {
|
|
1334
|
+
errors.push("Tr\u01B0\u1EDDng 'Gender' ph\u1EA3i l\xE0 0 (T\u1EA5t c\u1EA3), 1 (Nam), ho\u1EB7c 2 (N\u1EEF).");
|
|
1335
|
+
}
|
|
1336
|
+
const VALID_AGE_RANGES = [10282, 10283, 10284, 10285, 10286, 10287, 10288];
|
|
1337
|
+
const newAgeRanges = Array.isArray(targetingObj.NewAgeRanges) && targetingObj.NewAgeRanges.length > 0 ? targetingObj.NewAgeRanges.map(Number) : VALID_AGE_RANGES;
|
|
1338
|
+
for (const age of newAgeRanges) {
|
|
1339
|
+
if (!VALID_AGE_RANGES.includes(age)) {
|
|
1340
|
+
errors.push(`M\xE3 \u0111\u1ED9 tu\u1ED5i '${age}' kh\xF4ng h\u1EE3p l\u1EC7. C\xE1c m\xE3 cho ph\xE9p: ${VALID_AGE_RANGES.join(", ")}.`);
|
|
1403
1341
|
}
|
|
1404
1342
|
}
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
}
|
|
1410
|
-
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://.");
|
|
1411
|
-
}
|
|
1412
|
-
break;
|
|
1413
|
-
case VALID_CAMPAIGN_TYPES.ARTICLE:
|
|
1414
|
-
if (!payload.articleId || payload.articleId <= 0) {
|
|
1415
|
-
errors.push("articleId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o B\xE0i Vi\u1EBFt (ph\u1EA3i > 0, l\u1EA5y t\u1EEB getOwnedArticles).");
|
|
1416
|
-
}
|
|
1417
|
-
break;
|
|
1418
|
-
case VALID_CAMPAIGN_TYPES.COMMERCE:
|
|
1419
|
-
if (payload.productId === void 0 || payload.productId === null) {
|
|
1420
|
-
warnings.push("Qu\u1EA3ng c\xE1o Commerce n\xEAn ch\u1EC9 \u0111\u1ECBnh productId (ho\u1EB7c -1/0 khi d\xF9ng Instant Page s\u1EA3n ph\u1EA9m).");
|
|
1421
|
-
}
|
|
1422
|
-
break;
|
|
1423
|
-
case VALID_CAMPAIGN_TYPES.FORM:
|
|
1424
|
-
case VALID_CAMPAIGN_TYPES.MESSAGE:
|
|
1425
|
-
break;
|
|
1426
|
-
}
|
|
1427
|
-
if (payload.budgetType !== void 0 && payload.budgetlimit !== void 0) {
|
|
1428
|
-
if (payload.budgetType === 2) {
|
|
1429
|
-
if (payload.budgetlimit > 0 && payload.budgetlimit < 6e5) {
|
|
1430
|
-
errors.push("Ng\xE2n s\xE1ch cho To\xE0n l\u1ECBch ch\u1EA1y t\u1ED1i thi\u1EC3u l\xE0 600,000 VN\u0110.");
|
|
1431
|
-
}
|
|
1432
|
-
} else if (payload.budgetType === 1) {
|
|
1433
|
-
if (payload.budgetlimit > 0 && payload.budgetlimit < 50) {
|
|
1434
|
-
warnings.push("S\u1ED1 l\u01B0\u1EE3ng t\u01B0\u01A1ng t\xE1c m\u1ED7i ng\xE0y t\u1ED1i thi\u1EC3u \u0111\u01B0\u1EE3c khuy\u1EBFn ngh\u1ECB t\u1EEB 50 l\u01B0\u1EE3t.");
|
|
1435
|
-
}
|
|
1343
|
+
const VALID_OS = [0, 1, 2, 3];
|
|
1344
|
+
const os = Array.isArray(targetingObj.Os) && targetingObj.Os.length > 0 ? targetingObj.Os.map(Number) : [0, 1, 3];
|
|
1345
|
+
for (const o of os) {
|
|
1346
|
+
if (!VALID_OS.includes(o)) {
|
|
1347
|
+
errors.push(`M\xE3 h\u1EC7 \u0111i\u1EC1u h\xE0nh '${o}' kh\xF4ng h\u1EE3p l\u1EC7 (0: Android, 1: iOS, 2: Windows Phone, 3: PC).`);
|
|
1436
1348
|
}
|
|
1437
1349
|
}
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1350
|
+
let location = targetingObj.Location;
|
|
1351
|
+
if (!location || typeof location !== "object") {
|
|
1352
|
+
location = {
|
|
1353
|
+
Addresses: [],
|
|
1354
|
+
Cities: [],
|
|
1355
|
+
DistrictTargeting: { Includes: [], Excludes: [] },
|
|
1356
|
+
WardTargeting: { Includes: [], Excludes: [] },
|
|
1357
|
+
IsConvertedToWard: false
|
|
1358
|
+
};
|
|
1359
|
+
} else {
|
|
1360
|
+
const rawWard = location.WardTargeting && typeof location.WardTargeting === "object" ? location.WardTargeting : void 0;
|
|
1361
|
+
const rawDistrict = location.DistrictTargeting && typeof location.DistrictTargeting === "object" ? location.DistrictTargeting : void 0;
|
|
1362
|
+
const baseTargeting = rawWard || rawDistrict || { Includes: [], Excludes: [] };
|
|
1363
|
+
location = {
|
|
1364
|
+
Addresses: Array.isArray(location.Addresses) ? location.Addresses : [],
|
|
1365
|
+
Cities: Array.isArray(location.Cities) ? location.Cities : [],
|
|
1366
|
+
DistrictTargeting: rawDistrict || baseTargeting,
|
|
1367
|
+
WardTargeting: rawWard || baseTargeting,
|
|
1368
|
+
IsConvertedToWard: location.IsConvertedToWard !== void 0 ? Boolean(location.IsConvertedToWard) : false
|
|
1369
|
+
};
|
|
1370
|
+
const includes = location.WardTargeting.Includes || location.DistrictTargeting.Includes;
|
|
1371
|
+
if (includes && !Array.isArray(includes)) {
|
|
1372
|
+
errors.push("Tr\u01B0\u1EDDng 'Location.WardTargeting.Includes' (ho\u1EB7c DistrictTargeting.Includes) ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng khu v\u1EF1c.");
|
|
1373
|
+
} else if (Array.isArray(includes)) {
|
|
1374
|
+
for (const inc of includes) {
|
|
1375
|
+
if (![1, 2, 3].includes(Number(inc.Id))) {
|
|
1376
|
+
errors.push(`M\xE3 v\xF9ng mi\u1EC1n Id='${inc.Id}' kh\xF4ng h\u1EE3p l\u1EC7 (1: Mi\u1EC1n B\u1EAFc, 2: Mi\u1EC1n Trung, 3: Mi\u1EC1n Nam).`);
|
|
1377
|
+
}
|
|
1378
|
+
if (inc.Provinces && !Array.isArray(inc.Provinces)) {
|
|
1379
|
+
errors.push(`Tr\u01B0\u1EDDng 'Provinces' trong v\xF9ng mi\u1EC1n Id=${inc.Id} ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng t\u1EC9nh/th\xE0nh.`);
|
|
1380
|
+
} else if (Array.isArray(inc.Provinces)) {
|
|
1381
|
+
for (const prov of inc.Provinces) {
|
|
1382
|
+
if (!prov.Id || typeof prov.Id !== "string") {
|
|
1383
|
+
errors.push(`M\xE3 t\u1EC9nh 'Id' (${JSON.stringify(prov)}) trong v\xF9ng mi\u1EC1n ${inc.Id} ph\u1EA3i l\xE0 chu\u1ED7i h\u1EE3p l\u1EC7 (v\xED d\u1EE5: 'VN44', 'VN20').`);
|
|
1384
|
+
} else {
|
|
1385
|
+
const mergeInfo = ZALO_PROVINCE_MERGE_MAPPING[prov.Id];
|
|
1386
|
+
if (mergeInfo) {
|
|
1387
|
+
errors.push(
|
|
1388
|
+
`M\xE3 t\u1EC9nh '${prov.Id}' (${mergeInfo.name}) \u0111\xE3 \u0111\u01B0\u1EE3c Zalo Ads g\u1ED9p/s\xE1p nh\u1EADp v\xE0o c\u1EE5m m\xE3 '${mergeInfo.newCode}'. Vui l\xF2ng s\u1EED d\u1EE5ng m\xE3 c\u1EE5m '${mergeInfo.newCode}' trong WardTargeting, n\u1EBFu kh\xF4ng giao di\u1EC7n Zalo Ads Web s\u1EBD b\xE1o l\u1ED7i \u0111\u1ECF 'Invalid wards params'.`
|
|
1389
|
+
);
|
|
1390
|
+
} else {
|
|
1391
|
+
const validNewRegionProvs = ZALO_NEW_REGION_PROVINCE_CODES[Number(inc.Id)] || [];
|
|
1392
|
+
if (!validNewRegionProvs.includes(prov.Id)) {
|
|
1393
|
+
const actualRegion = Object.keys(ZALO_NEW_REGION_PROVINCE_CODES).find((r) => ZALO_NEW_REGION_PROVINCE_CODES[Number(r)].includes(prov.Id));
|
|
1394
|
+
errors.push(
|
|
1395
|
+
`M\xE3 t\u1EC9nh '${prov.Id}' kh\xF4ng n\u1EB1m trong 34 C\u1EE5m T\u1EC9nh/Th\xE0nh m\u1EDBi c\u1EE7a V\xF9ng ${inc.Id} tr\xEAn Zalo Ads (s\u1EBD g\xE2y l\u1ED7i 'Invalid wards params' tr\xEAn UI). ` + (actualRegion ? `M\xE3 n\xE0y thu\u1ED9c V\xF9ng ${actualRegion}. ` : "")
|
|
1396
|
+
);
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
if (prov.Districts && !Array.isArray(prov.Districts)) {
|
|
1401
|
+
errors.push(`Tr\u01B0\u1EDDng 'Districts' c\u1EE7a t\u1EC9nh ${prov.Id} ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng (ho\u1EB7c [] khi ch\u1ECDn c\u1EA3 t\u1EC9nh).`);
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1441
1406
|
}
|
|
1442
1407
|
}
|
|
1408
|
+
const finalTargeting = {
|
|
1409
|
+
...targetingObj,
|
|
1410
|
+
CustomAudienceId: 0,
|
|
1411
|
+
Gender: gender,
|
|
1412
|
+
NewAgeRanges: newAgeRanges,
|
|
1413
|
+
Os: os,
|
|
1414
|
+
Location: location
|
|
1415
|
+
};
|
|
1443
1416
|
return {
|
|
1444
1417
|
isValid: errors.length === 0,
|
|
1445
1418
|
errors,
|
|
1446
|
-
|
|
1419
|
+
data: errors.length === 0 ? {
|
|
1420
|
+
name,
|
|
1421
|
+
caType: 1,
|
|
1422
|
+
targeting: JSON.stringify(finalTargeting)
|
|
1423
|
+
} : void 0
|
|
1447
1424
|
};
|
|
1448
1425
|
}
|
|
1449
|
-
function
|
|
1426
|
+
function validateCreatePhoneAudienceRequest(input) {
|
|
1450
1427
|
const errors = [];
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
errors.push("AdId l\xE0 b\u1EAFt bu\u1ED9c (ph\u1EA3i > 0).");
|
|
1454
|
-
}
|
|
1455
|
-
if (!payload.CampaignId || payload.CampaignId <= 0) {
|
|
1456
|
-
errors.push("CampaignId l\xE0 b\u1EAFt bu\u1ED9c (ph\u1EA3i > 0).");
|
|
1428
|
+
if (!input || typeof input !== "object") {
|
|
1429
|
+
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
1457
1430
|
}
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
errors.push(
|
|
1431
|
+
const raw = input;
|
|
1432
|
+
const name = typeof raw.name === "string" ? raw.name.trim() : "";
|
|
1433
|
+
if (!name || name.length < 2 || name.length > 255) {
|
|
1434
|
+
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
|
|
1462
1435
|
}
|
|
1463
|
-
|
|
1464
|
-
if (
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
errors.push("
|
|
1469
|
-
} else {
|
|
1470
|
-
const captionLen = adInfo.Caption.trim().length;
|
|
1471
|
-
if (captionLen < 35) {
|
|
1472
|
-
errors.push(`Settings.AdInfo.Caption qu\xE1 ng\u1EAFn (${captionLen}/35 k\xFD t\u1EF1 t\u1ED1i thi\u1EC3u).`);
|
|
1473
|
-
} else if (captionLen > 90) {
|
|
1474
|
-
errors.push(`Settings.AdInfo.Caption qu\xE1 d\xE0i (${captionLen}/90 k\xFD t\u1EF1 t\u1ED1i \u0111a).`);
|
|
1475
|
-
}
|
|
1476
|
-
}
|
|
1477
|
-
if (adInfo.MoreInfo && adInfo.MoreInfo.trim()) {
|
|
1478
|
-
const moreInfoLen = adInfo.MoreInfo.trim().length;
|
|
1479
|
-
if (moreInfoLen < 90) {
|
|
1480
|
-
warnings.push(`Ch\xFA th\xEDch m\u1EDF r\u1ED9ng n\xEAn \u0111\u1EA1t t\u1ED1i thi\u1EC3u 90 k\xFD t\u1EF1 (hi\u1EC7n t\u1EA1i: ${moreInfoLen}).`);
|
|
1481
|
-
} else if (moreInfoLen > 2e3) {
|
|
1482
|
-
errors.push(`Ch\xFA th\xEDch m\u1EDF r\u1ED9ng v\u01B0\u1EE3t qu\xE1 gi\u1EDBi h\u1EA1n t\u1ED1i \u0111a 2000 k\xFD t\u1EF1 (hi\u1EC7n t\u1EA1i: ${moreInfoLen}).`);
|
|
1483
|
-
}
|
|
1484
|
-
}
|
|
1485
|
-
if (adInfo.Action !== void 0 && payload.Type) {
|
|
1486
|
-
const allowedCtas = ALLOWED_CTAS_PER_AD_TYPE[payload.Type];
|
|
1487
|
-
if (allowedCtas && !allowedCtas.includes(adInfo.Action)) {
|
|
1488
|
-
warnings.push(
|
|
1489
|
-
`M\xE3 h\xE0nh \u0111\u1ED9ng Action: ${adInfo.Action} c\xF3 th\u1EC3 kh\xF4ng n\u1EB1m trong danh m\u1EE5c n\xFAt CTA h\u1ED7 tr\u1EE3 cho Ad Type ${payload.Type}.`
|
|
1490
|
-
);
|
|
1491
|
-
}
|
|
1436
|
+
let targetingObj = {};
|
|
1437
|
+
if (typeof raw.targeting === "string") {
|
|
1438
|
+
try {
|
|
1439
|
+
targetingObj = JSON.parse(raw.targeting);
|
|
1440
|
+
} catch {
|
|
1441
|
+
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
|
|
1492
1442
|
}
|
|
1493
|
-
}
|
|
1494
|
-
|
|
1495
|
-
if (!price) {
|
|
1496
|
-
errors.push("Settings.Price l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
1443
|
+
} else if (raw.targeting && typeof raw.targeting === "object") {
|
|
1444
|
+
targetingObj = raw.targeting;
|
|
1497
1445
|
} else {
|
|
1498
|
-
|
|
1499
|
-
if (price.Type !== 1) {
|
|
1500
|
-
errors.push(
|
|
1501
|
-
"\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Website (Type 5), Price.Type b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 1 (CPC). N\u1EBFu truy\u1EC1n 2 s\u1EBD b\u1ECB m\xE1y ch\u1EE7 l\u1ED7i."
|
|
1502
|
-
);
|
|
1503
|
-
}
|
|
1504
|
-
if (price.LimitType === 1) {
|
|
1505
|
-
errors.push(
|
|
1506
|
-
"Qu\u1EA3ng c\xE1o Website kh\xF4ng h\u1ED7 tr\u1EE3 LimitType: 1 (t\u1ED5ng ng\xE2n s\xE1ch). B\u1EAFt bu\u1ED9c ph\u1EA3i d\xF9ng LimitType: 0 (ng\xE2n s\xE1ch ng\xE0y)."
|
|
1507
|
-
);
|
|
1508
|
-
}
|
|
1509
|
-
} else if (payload.Type === VALID_AD_TYPES.COMMERCE || payload.Type === VALID_AD_TYPES.OA || payload.Type === VALID_AD_TYPES.ARTICLE || payload.Type === VALID_AD_TYPES.VIDEO || payload.Type === VALID_AD_TYPES.FORM || payload.Type === VALID_AD_TYPES.MESSAGE) {
|
|
1510
|
-
if (price.Type !== 2) {
|
|
1511
|
-
errors.push(
|
|
1512
|
-
`\u0110\u1ED1i v\u1EDBi Ad Type ${payload.Type}, Price.Type b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 2. N\u1EBFu truy\u1EC1n 1, Zalo Ads s\u1EBD b\xE1o l\u1ED7i code 14 (\u0110\u1EB7t gi\xE1 theo L\u01B0\u1EE3t hi\u1EC3n th\u1ECB kh\xF4ng h\u1ED7 tr\u1EE3).`
|
|
1513
|
-
);
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
|
-
if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 50) {
|
|
1517
|
-
warnings.push("S\u1ED1 l\u01B0\u1EE3ng l\u01B0\u1EE3t t\u01B0\u01A1ng t\xE1c \u0111\u1EB7t m\u1ED7i ng\xE0y t\u1ED1i thi\u1EC3u l\xE0 50 l\u01B0\u1EE3t.");
|
|
1518
|
-
}
|
|
1446
|
+
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
1519
1447
|
}
|
|
1520
|
-
const
|
|
1521
|
-
if (
|
|
1522
|
-
|
|
1523
|
-
const validAges = Object.values(ZaloAdsAgeRangeId);
|
|
1524
|
-
const invalidAges = targeting.AgeRanges.filter((a) => !validAges.includes(a));
|
|
1525
|
-
if (invalidAges.length > 0) {
|
|
1526
|
-
errors.push(`M\xE3 kho\u1EA3ng tu\u1ED5i kh\xF4ng h\u1EE3p l\u1EC7: ${invalidAges.join(", ")}. H\u1EE3p l\u1EC7: ${validAges.join(", ")}.`);
|
|
1527
|
-
}
|
|
1528
|
-
}
|
|
1529
|
-
if (targeting.OsTypes && targeting.OsTypes.length > 0) {
|
|
1530
|
-
const validOs = Object.values(ZaloAdsOsId);
|
|
1531
|
-
const invalidOs = targeting.OsTypes.filter((os) => !validOs.includes(os));
|
|
1532
|
-
if (invalidOs.length > 0) {
|
|
1533
|
-
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).`);
|
|
1534
|
-
}
|
|
1535
|
-
}
|
|
1536
|
-
const deliveryType = payload.Settings?.DeliveryType;
|
|
1537
|
-
if (deliveryType !== void 0 && deliveryType !== 1 && deliveryType !== 2) {
|
|
1538
|
-
warnings.push("DeliveryType n\xEAn l\xE0 1 (Ti\xEAu chu\u1EA9n) ho\u1EB7c 2 (T\u0103ng t\u1ED1c).");
|
|
1539
|
-
}
|
|
1448
|
+
const path = typeof targetingObj.Path === "string" ? targetingObj.Path.trim() : "";
|
|
1449
|
+
if (!path) {
|
|
1450
|
+
errors.push("Tr\u01B0\u1EDDng 'Path' (URL file .txt sau khi upload) l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
1540
1451
|
}
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
}
|
|
1545
|
-
} else if (payload.Type === VALID_AD_TYPES.MESSAGE) {
|
|
1546
|
-
if (!payload.Settings?.Image?.LogoUrl) {
|
|
1547
|
-
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).");
|
|
1548
|
-
}
|
|
1549
|
-
if (!payload.ZaloFlowId && !payload.MiniPageId) {
|
|
1550
|
-
warnings.push("Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn n\xEAn g\u1EAFn ZaloFlowId ho\u1EB7c MiniPageId (Template 4 k\u1ECBch b\u1EA3n tin nh\u1EAFn).");
|
|
1551
|
-
}
|
|
1552
|
-
} else if (payload.Type === VALID_AD_TYPES.COMMERCE) {
|
|
1553
|
-
if (!payload.MiniPageId || payload.MiniPageId <= 0) {
|
|
1554
|
-
errors.push("MiniPageId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Commerce (Ad Type 28, Template 1/2/3).");
|
|
1555
|
-
}
|
|
1556
|
-
} else if (payload.Type === VALID_AD_TYPES.VIDEO) {
|
|
1557
|
-
if (!payload.ZaloVideoId && !payload.Settings?.Image?.VideoUrl) {
|
|
1558
|
-
errors.push("ZaloVideoId ho\u1EB7c Settings.Image.VideoUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Video (Ad Type 11).");
|
|
1559
|
-
}
|
|
1560
|
-
if (payload.Settings?.Image?.VideoUrl && !payload.Settings.Image.VideoUrl.includes("zascdn.me")) {
|
|
1561
|
-
warnings.push("VideoUrl n\xEAn l\xE0 \u0111\u01B0\u1EDDng d\u1EABn CDN ch\xEDnh th\u1EE9c c\u1EE7a Zalo Ads (*.zascdn.me).");
|
|
1562
|
-
}
|
|
1563
|
-
} else if (payload.Type === VALID_AD_TYPES.ARTICLE) {
|
|
1564
|
-
if (!payload.ZaloFeedId && !payload.articleId) {
|
|
1565
|
-
errors.push("ZaloFeedId ho\u1EB7c articleId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o B\xE0i Vi\u1EBFt (Ad Type 3).");
|
|
1566
|
-
}
|
|
1452
|
+
const total = typeof targetingObj.Total === "number" ? targetingObj.Total : 0;
|
|
1453
|
+
if (total <= 0) {
|
|
1454
|
+
errors.push("Tr\u01B0\u1EDDng 'Total' (s\u1ED1 l\u01B0\u1EE3ng S\u0110T trong file) ph\u1EA3i l\u1EDBn h\u01A1n 0.");
|
|
1567
1455
|
}
|
|
1568
1456
|
return {
|
|
1569
1457
|
isValid: errors.length === 0,
|
|
1570
1458
|
errors,
|
|
1571
|
-
|
|
1459
|
+
data: errors.length === 0 ? {
|
|
1460
|
+
name,
|
|
1461
|
+
caType: 3,
|
|
1462
|
+
targeting: JSON.stringify({
|
|
1463
|
+
Name: String(targetingObj.Name || "phones.txt"),
|
|
1464
|
+
Path: path,
|
|
1465
|
+
Total: total,
|
|
1466
|
+
ZaloId: Number(targetingObj.ZaloId || 0),
|
|
1467
|
+
OriginAudience: 0
|
|
1468
|
+
})
|
|
1469
|
+
} : void 0
|
|
1572
1470
|
};
|
|
1573
1471
|
}
|
|
1574
|
-
function
|
|
1472
|
+
function validateCreateLookalikeAudienceRequest(input) {
|
|
1575
1473
|
const errors = [];
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
const name = params.newname || params.newName || params.name;
|
|
1579
|
-
if (!id || id <= 0) {
|
|
1580
|
-
errors.push("ID chi\u1EBFn d\u1ECBch (campid/campaignId) l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i > 0.");
|
|
1474
|
+
if (!input || typeof input !== "object") {
|
|
1475
|
+
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
1581
1476
|
}
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
errors.push(
|
|
1477
|
+
const raw = input;
|
|
1478
|
+
const name = typeof raw.name === "string" ? raw.name.trim() : "";
|
|
1479
|
+
if (!name || name.length < 2 || name.length > 255) {
|
|
1480
|
+
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
|
|
1586
1481
|
}
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
errors.push("
|
|
1482
|
+
let targetingObj = {};
|
|
1483
|
+
if (typeof raw.targeting === "string") {
|
|
1484
|
+
try {
|
|
1485
|
+
targetingObj = JSON.parse(raw.targeting);
|
|
1486
|
+
} catch {
|
|
1487
|
+
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
|
|
1488
|
+
}
|
|
1489
|
+
} else if (raw.targeting && typeof raw.targeting === "object") {
|
|
1490
|
+
targetingObj = raw.targeting;
|
|
1491
|
+
} else {
|
|
1492
|
+
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
1598
1493
|
}
|
|
1599
|
-
|
|
1600
|
-
|
|
1494
|
+
const originAudience = Number(targetingObj.OriginAudience);
|
|
1495
|
+
if (!originAudience || originAudience <= 0) {
|
|
1496
|
+
errors.push("Tr\u01B0\u1EDDng 'OriginAudience' (ID nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng S\u0110T g\u1ED1c) l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
1601
1497
|
}
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
);
|
|
1498
|
+
const total = Number(targetingObj.Total);
|
|
1499
|
+
if (![1e6, 15e5, 2e6].includes(total)) {
|
|
1500
|
+
errors.push("Tr\u01B0\u1EDDng 'Total' c\u1EE7a Lookalike ch\u1EC9 ch\u1EA5p nh\u1EADn c\xE1c m\u1ED1c: 1.000.000, 1.500.000 ho\u1EB7c 2.000.000.");
|
|
1606
1501
|
}
|
|
1607
1502
|
return {
|
|
1608
1503
|
isValid: errors.length === 0,
|
|
1609
1504
|
errors,
|
|
1610
|
-
|
|
1505
|
+
data: errors.length === 0 ? {
|
|
1506
|
+
name,
|
|
1507
|
+
caType: 6,
|
|
1508
|
+
targeting: JSON.stringify({
|
|
1509
|
+
OriginAudience: originAudience,
|
|
1510
|
+
Total: total,
|
|
1511
|
+
Name: String(targetingObj.Name || "Lookalike Audience"),
|
|
1512
|
+
Path: String(targetingObj.Path || "")
|
|
1513
|
+
})
|
|
1514
|
+
} : void 0
|
|
1611
1515
|
};
|
|
1612
1516
|
}
|
|
1613
|
-
function
|
|
1517
|
+
function validateCreateFormEventAudienceRequest(input) {
|
|
1614
1518
|
const errors = [];
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1519
|
+
if (!input || typeof input !== "object") {
|
|
1520
|
+
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
1521
|
+
}
|
|
1522
|
+
const raw = input;
|
|
1523
|
+
const name = typeof raw.name === "string" ? raw.name.trim() : "";
|
|
1524
|
+
if (!name || name.length < 2 || name.length > 255) {
|
|
1525
|
+
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
|
|
1526
|
+
}
|
|
1527
|
+
let targetingObj = {};
|
|
1528
|
+
if (typeof raw.targeting === "string") {
|
|
1529
|
+
try {
|
|
1530
|
+
targetingObj = JSON.parse(raw.targeting);
|
|
1531
|
+
} catch {
|
|
1532
|
+
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
|
|
1533
|
+
}
|
|
1534
|
+
} else if (raw.targeting && typeof raw.targeting === "object") {
|
|
1535
|
+
targetingObj = raw.targeting;
|
|
1536
|
+
}
|
|
1537
|
+
const eventType = Number(targetingObj.EventType);
|
|
1538
|
+
if (![1, 2, 3, 4].includes(eventType)) {
|
|
1539
|
+
errors.push("Tr\u01B0\u1EDDng 'EventType' ph\u1EA3i l\xE0 1 (\u0110\xE3 xem ch\u01B0a g\u1EEDi), 2 (\u0110\xE3 xem & g\u1EEDi), 3 (\u0110\xE3 xem), ho\u1EB7c 4 (M\u1EDF chat t\u1EEB Form).");
|
|
1540
|
+
}
|
|
1541
|
+
const oaId = typeof targetingObj.OaId === "string" ? targetingObj.OaId.trim() : String(targetingObj.OaId || "");
|
|
1542
|
+
if (!oaId) {
|
|
1543
|
+
errors.push("Tr\u01B0\u1EDDng 'OaId' (d\u1EA1ng chu\u1ED7i c\u1EE7a pageId ho\u1EB7c noisedId) l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
1544
|
+
}
|
|
1545
|
+
const numDays = Number(targetingObj.NumDays);
|
|
1546
|
+
if (isNaN(numDays) || numDays < 1 || numDays > 90) {
|
|
1547
|
+
errors.push("Tr\u01B0\u1EDDng 'NumDays' ph\u1EA3i n\u1EB1m trong kho\u1EA3ng t\u1EEB 1 \u0111\u1EBFn 90 ng\xE0y.");
|
|
1548
|
+
}
|
|
1549
|
+
const formIds = Array.isArray(targetingObj.FormIds) ? targetingObj.FormIds : [];
|
|
1550
|
+
if (formIds.length === 0) {
|
|
1551
|
+
errors.push("Tr\u01B0\u1EDDng 'FormIds' ph\u1EA3i ch\u1EE9a \xEDt nh\u1EA5t 1 ID Form.");
|
|
1619
1552
|
}
|
|
1620
1553
|
return {
|
|
1621
1554
|
isValid: errors.length === 0,
|
|
1622
1555
|
errors,
|
|
1623
|
-
|
|
1556
|
+
data: errors.length === 0 ? {
|
|
1557
|
+
name,
|
|
1558
|
+
caType: 12,
|
|
1559
|
+
targeting: JSON.stringify({
|
|
1560
|
+
EventType: eventType,
|
|
1561
|
+
OaId: oaId,
|
|
1562
|
+
NumDays: numDays,
|
|
1563
|
+
FormIds: formIds
|
|
1564
|
+
})
|
|
1565
|
+
} : void 0
|
|
1624
1566
|
};
|
|
1625
1567
|
}
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1568
|
+
function validateCreateMessageOaEventAudienceRequest(input) {
|
|
1569
|
+
const errors = [];
|
|
1570
|
+
if (!input || typeof input !== "object") {
|
|
1571
|
+
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
1572
|
+
}
|
|
1573
|
+
const raw = input;
|
|
1574
|
+
const name = typeof raw.name === "string" ? raw.name.trim() : "";
|
|
1575
|
+
if (!name || name.length < 2 || name.length > 255) {
|
|
1576
|
+
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
|
|
1577
|
+
}
|
|
1578
|
+
let targetingObj = {};
|
|
1579
|
+
if (typeof raw.targeting === "string") {
|
|
1580
|
+
try {
|
|
1581
|
+
targetingObj = JSON.parse(raw.targeting);
|
|
1582
|
+
} catch {
|
|
1583
|
+
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
|
|
1584
|
+
}
|
|
1585
|
+
} else if (raw.targeting && typeof raw.targeting === "object") {
|
|
1586
|
+
targetingObj = raw.targeting;
|
|
1587
|
+
}
|
|
1588
|
+
const eventId = Number(targetingObj.EventId ?? targetingObj.EventType ?? 1);
|
|
1589
|
+
const oaId = typeof targetingObj.OaId === "string" ? targetingObj.OaId.trim() : String(targetingObj.OaId || "");
|
|
1590
|
+
if (!oaId) {
|
|
1591
|
+
errors.push("Tr\u01B0\u1EDDng 'OaId' (chu\u1ED7i pageId ho\u1EB7c noisedId c\u1EE7a OA) l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
1592
|
+
}
|
|
1593
|
+
const numDays = Number(targetingObj.NumDays);
|
|
1594
|
+
if (isNaN(numDays) || numDays < 1 || numDays > 90) {
|
|
1595
|
+
errors.push("Tr\u01B0\u1EDDng 'NumDays' ph\u1EA3i n\u1EB1m trong kho\u1EA3ng t\u1EEB 1 \u0111\u1EBFn 90 ng\xE0y.");
|
|
1596
|
+
}
|
|
1597
|
+
return {
|
|
1598
|
+
isValid: errors.length === 0,
|
|
1599
|
+
errors,
|
|
1600
|
+
data: errors.length === 0 ? {
|
|
1601
|
+
name,
|
|
1602
|
+
caType: 11,
|
|
1603
|
+
targeting: JSON.stringify({
|
|
1604
|
+
EventId: eventId,
|
|
1605
|
+
OaId: oaId,
|
|
1606
|
+
NumDays: numDays
|
|
1607
|
+
})
|
|
1608
|
+
} : void 0
|
|
1609
|
+
};
|
|
1610
|
+
}
|
|
1611
|
+
function validateCreateMessagePersonalEventAudienceRequest(input) {
|
|
1612
|
+
const errors = [];
|
|
1613
|
+
if (!input || typeof input !== "object") {
|
|
1614
|
+
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
1615
|
+
}
|
|
1616
|
+
const raw = input;
|
|
1617
|
+
const name = typeof raw.name === "string" ? raw.name.trim() : "";
|
|
1618
|
+
if (!name || name.length < 2 || name.length > 255) {
|
|
1619
|
+
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
|
|
1620
|
+
}
|
|
1621
|
+
let targetingObj = {};
|
|
1622
|
+
if (typeof raw.targeting === "string") {
|
|
1623
|
+
try {
|
|
1624
|
+
targetingObj = JSON.parse(raw.targeting);
|
|
1625
|
+
} catch {
|
|
1626
|
+
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
|
|
1627
|
+
}
|
|
1628
|
+
} else if (raw.targeting && typeof raw.targeting === "object") {
|
|
1629
|
+
targetingObj = raw.targeting;
|
|
1630
|
+
}
|
|
1631
|
+
const eventId = Number(targetingObj.EventId ?? targetingObj.EventType ?? 1);
|
|
1632
|
+
if (![1, 2, 3].includes(eventId)) {
|
|
1633
|
+
errors.push("Tr\u01B0\u1EDDng 'EventId' ph\u1EA3i l\xE0 1 (\u0110\xE3 li\xEAn h\u1EC7), 2 (\u0110\xE3 xem kh\xF4ng li\xEAn h\u1EC7), ho\u1EB7c 3 (Xem carousel kh\xF4ng li\xEAn h\u1EC7).");
|
|
1634
|
+
}
|
|
1635
|
+
const numDays = Number(targetingObj.NumDays);
|
|
1636
|
+
if (isNaN(numDays) || numDays < 1 || numDays > 90) {
|
|
1637
|
+
errors.push("Tr\u01B0\u1EDDng 'NumDays' ph\u1EA3i n\u1EB1m trong kho\u1EA3ng t\u1EEB 1 \u0111\u1EBFn 90 ng\xE0y.");
|
|
1638
|
+
}
|
|
1639
|
+
const pageIds = Array.isArray(targetingObj.PageIds) ? targetingObj.PageIds.map(String) : [];
|
|
1640
|
+
if (pageIds.length === 0) {
|
|
1641
|
+
errors.push("Tr\u01B0\u1EDDng 'PageIds' ph\u1EA3i ch\u1EE9a \xEDt nh\u1EA5t 1 ID trang c\xE1 nh\xE2n.");
|
|
1642
|
+
}
|
|
1643
|
+
return {
|
|
1644
|
+
isValid: errors.length === 0,
|
|
1645
|
+
errors,
|
|
1646
|
+
data: errors.length === 0 ? {
|
|
1647
|
+
name,
|
|
1648
|
+
caType: 14,
|
|
1649
|
+
targeting: JSON.stringify({
|
|
1650
|
+
EventId: eventId,
|
|
1651
|
+
NumDays: numDays,
|
|
1652
|
+
PageIds: pageIds
|
|
1653
|
+
})
|
|
1654
|
+
} : void 0
|
|
1655
|
+
};
|
|
1656
|
+
}
|
|
1657
|
+
function validateEstimateAudienceRequest(input) {
|
|
1658
|
+
const errors = [];
|
|
1659
|
+
if (!input || typeof input !== "object") {
|
|
1660
|
+
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
1661
|
+
}
|
|
1662
|
+
const raw = input;
|
|
1663
|
+
const gender = typeof raw.gender === "number" ? raw.gender : 0;
|
|
1664
|
+
if (![0, 1, 2].includes(gender)) {
|
|
1665
|
+
errors.push("Tr\u01B0\u1EDDng 'gender' ph\u1EA3i l\xE0 0, 1 ho\u1EB7c 2.");
|
|
1666
|
+
}
|
|
1667
|
+
const ageRanges = Array.isArray(raw.ageRanges) && raw.ageRanges.length > 0 ? raw.ageRanges.map(Number) : [10283, 10284, 10285, 10286, 10287];
|
|
1668
|
+
const platforms = Array.isArray(raw.platforms) && raw.platforms.length > 0 ? raw.platforms.map(Number) : [0, 1, 3];
|
|
1669
|
+
const priceType = typeof raw.priceType === "number" ? raw.priceType : 2;
|
|
1670
|
+
const wardsTargeting = typeof raw.wardsTargeting === "string" && raw.wardsTargeting.trim() ? raw.wardsTargeting.trim() : JSON.stringify({ Includes: [], Excludes: [] });
|
|
1671
|
+
return {
|
|
1672
|
+
isValid: errors.length === 0,
|
|
1673
|
+
errors,
|
|
1674
|
+
data: errors.length === 0 ? {
|
|
1675
|
+
gender,
|
|
1676
|
+
ageRanges,
|
|
1677
|
+
platforms,
|
|
1678
|
+
locations: typeof raw.locations === "string" ? raw.locations : "",
|
|
1679
|
+
provinces: Array.isArray(raw.provinces) ? raw.provinces.map(Number) : [],
|
|
1680
|
+
wardsTargeting,
|
|
1681
|
+
priceType,
|
|
1682
|
+
number: typeof raw.number === "string" ? raw.number : String(raw.number || "0")
|
|
1683
|
+
} : void 0
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1686
|
+
var ZaloAudiencesValidator = {
|
|
1687
|
+
createSavedAudience: validateCreateSavedAudienceRequest,
|
|
1688
|
+
createPhoneAudience: validateCreatePhoneAudienceRequest,
|
|
1689
|
+
createLookalikeAudience: validateCreateLookalikeAudienceRequest,
|
|
1690
|
+
createFormEventAudience: validateCreateFormEventAudienceRequest,
|
|
1691
|
+
createMessageOaEventAudience: validateCreateMessageOaEventAudienceRequest,
|
|
1692
|
+
createMessagePersonalEventAudience: validateCreateMessagePersonalEventAudienceRequest,
|
|
1693
|
+
estimateAudience: validateEstimateAudienceRequest
|
|
1632
1694
|
};
|
|
1633
1695
|
|
|
1634
|
-
// src/
|
|
1635
|
-
var
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
binaryFields: [],
|
|
1641
|
-
pathFields: [],
|
|
1642
|
-
queryFields: [],
|
|
1643
|
-
headerFields: [],
|
|
1644
|
-
cookieFields: [],
|
|
1645
|
-
bodyFields: ["data", "est", "isBoostAd", "stt"]
|
|
1696
|
+
// src/dtos/ads.dto.ts
|
|
1697
|
+
var ZaloAdsFlowChildMessageDto = class {
|
|
1698
|
+
/** Mẫu Zalo đã xác minh dùng 8 cho tin nhắn văn bản trong nhánh. */
|
|
1699
|
+
type;
|
|
1700
|
+
/** Nội dung phản hồi trong nhánh. */
|
|
1701
|
+
text;
|
|
1646
1702
|
};
|
|
1647
|
-
var
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
]
|
|
1703
|
+
var ZaloAdsFlowButtonDto = class {
|
|
1704
|
+
/** 3 = Gửi tin nhắn vào nhánh hội thoại; 10 = Mở website; 12 = Thực hiện cuộc gọi. */
|
|
1705
|
+
type;
|
|
1706
|
+
/** Nhãn nút hiển thị cho người dùng. */
|
|
1707
|
+
text;
|
|
1708
|
+
/** URL website; bắt buộc với type 10. */
|
|
1709
|
+
url;
|
|
1710
|
+
/** Cờ của nút website; dùng true với type 10. */
|
|
1711
|
+
editable;
|
|
1712
|
+
/** Số hotline, bắt buộc khi type là 12. */
|
|
1713
|
+
phone;
|
|
1714
|
+
/** Nhánh tin nhắn, bắt buộc khi type là 3. Với type 10 hoặc 12, để null hoặc bỏ qua. */
|
|
1715
|
+
messages;
|
|
1661
1716
|
};
|
|
1662
|
-
var
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
"cookieFields": [],
|
|
1672
|
-
"bodyFields": [
|
|
1673
|
-
"data"
|
|
1674
|
-
]
|
|
1717
|
+
var ZaloAdsFlowMessageDto = class {
|
|
1718
|
+
/** 1 = Tin nhắn văn bản; 2 = Tin nhắn kèm hình ảnh. */
|
|
1719
|
+
type;
|
|
1720
|
+
/** Nội dung tin nhắn, tối đa 1961 ký tự. Hỗ trợ biến: {{user_name}}, {{page_name}}, {{user_gender}}, {{user_id}}, {{page_id}}, {{date}}, {{datetime}}. */
|
|
1721
|
+
text;
|
|
1722
|
+
/** URL media hoặc null với tin nhắn văn bản thuần. Bắt buộc và không được null khi type = 2. */
|
|
1723
|
+
url;
|
|
1724
|
+
/** Các nút đi kèm tin nhắn. */
|
|
1725
|
+
buttons;
|
|
1675
1726
|
};
|
|
1676
|
-
var
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
"cookieFields": [],
|
|
1686
|
-
"bodyFields": [
|
|
1687
|
-
"data"
|
|
1688
|
-
]
|
|
1727
|
+
var ZaloAdsCreateFlowRequest = class {
|
|
1728
|
+
/** ID Official Account sở hữu kịch bản. */
|
|
1729
|
+
oaId;
|
|
1730
|
+
/** Luôn null khi tạo kịch bản mới. */
|
|
1731
|
+
id;
|
|
1732
|
+
/** Tên kịch bản, tối đa 33 ký tự theo giao diện Zalo Ads. */
|
|
1733
|
+
name;
|
|
1734
|
+
/** Các tin nhắn được gửi theo thứ tự trong kịch bản. */
|
|
1735
|
+
messages;
|
|
1689
1736
|
};
|
|
1690
|
-
var
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
"queryFields": [],
|
|
1698
|
-
"headerFields": [],
|
|
1699
|
-
"cookieFields": [],
|
|
1700
|
-
"bodyFields": [
|
|
1701
|
-
"data"
|
|
1702
|
-
]
|
|
1737
|
+
var ZaloAdsCreateFlowResponse = class {
|
|
1738
|
+
/** 0 khi tạo thành công; 1 khi lỗi (ví dụ: đã tới hạn mức 20 kịch bản). */
|
|
1739
|
+
code;
|
|
1740
|
+
/** Thông báo lỗi từ Zalo Ads khi code khác 0. */
|
|
1741
|
+
msg;
|
|
1742
|
+
/** ID kịch bản mới, truyền vào data.ZaloFlowId khi cập nhật quảng cáo Tin nhắn. */
|
|
1743
|
+
data;
|
|
1703
1744
|
};
|
|
1704
|
-
var
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1745
|
+
var ZaloAdsActionType = {
|
|
1746
|
+
DAT_NGAY: 1,
|
|
1747
|
+
MUA_NGAY: 2,
|
|
1748
|
+
THU_NGAY: 3,
|
|
1749
|
+
TAI_NGAY: 4,
|
|
1750
|
+
XEM_THEM: 5,
|
|
1751
|
+
NGHE_NGAY: 6,
|
|
1752
|
+
CHOI_NGAY: 7,
|
|
1753
|
+
DANG_KY: 8,
|
|
1754
|
+
GOI_DIEN: 9,
|
|
1755
|
+
/** Dành riêng cho Quảng cáo Official Account (Type 2) */
|
|
1756
|
+
QUAN_TAM_OA: 6
|
|
1757
|
+
};
|
|
1758
|
+
var ZaloAdsVideoSrc = {
|
|
1759
|
+
UNUSED: -1,
|
|
1760
|
+
/** Sử dụng mã Zalo Video được cấp từ kênh */
|
|
1761
|
+
VIDEO_CODE: 1,
|
|
1762
|
+
/** Tự tải video lên hoặc chọn từ Thư viện Media */
|
|
1763
|
+
SELF_UPLOAD: 2
|
|
1764
|
+
};
|
|
1765
|
+
var ZaloAdsBudgetScheduleType = {
|
|
1766
|
+
/** Toàn lịch chạy */
|
|
1767
|
+
TOTAL_SCHEDULE: 1,
|
|
1768
|
+
/** Mỗi ngày */
|
|
1769
|
+
DAILY: 2
|
|
1717
1770
|
};
|
|
1718
|
-
var
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
"headerFields": [],
|
|
1727
|
-
"cookieFields": [],
|
|
1728
|
-
"bodyFields": [
|
|
1729
|
-
"data"
|
|
1730
|
-
]
|
|
1771
|
+
var ZaloAdsAgeRangeId = {
|
|
1772
|
+
UNDER_18: 10282,
|
|
1773
|
+
FROM_18_TO_24: 10283,
|
|
1774
|
+
FROM_25_TO_34: 10284,
|
|
1775
|
+
FROM_35_TO_44: 10285,
|
|
1776
|
+
FROM_45_TO_54: 10286,
|
|
1777
|
+
FROM_55_TO_64: 10287,
|
|
1778
|
+
OVER_64: 10288
|
|
1731
1779
|
};
|
|
1732
|
-
var
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1737
|
-
"binaryFields": [],
|
|
1738
|
-
"pathFields": [],
|
|
1739
|
-
"queryFields": [],
|
|
1740
|
-
"headerFields": [],
|
|
1741
|
-
"cookieFields": [],
|
|
1742
|
-
"bodyFields": [
|
|
1743
|
-
"data"
|
|
1744
|
-
]
|
|
1780
|
+
var ZaloAdsOsId = {
|
|
1781
|
+
ANDROID: 0,
|
|
1782
|
+
IOS: 1,
|
|
1783
|
+
PC: 3
|
|
1745
1784
|
};
|
|
1746
|
-
var
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
"
|
|
1759
|
-
"
|
|
1760
|
-
"
|
|
1785
|
+
var ZaloAdsRegionId = {
|
|
1786
|
+
/** Miền Bắc (28 tỉnh/thành phố) */
|
|
1787
|
+
NORTH: 1,
|
|
1788
|
+
/** Miền Trung (16 tỉnh/thành phố) */
|
|
1789
|
+
CENTRAL: 2,
|
|
1790
|
+
/** Miền Nam (19 tỉnh/thành phố) */
|
|
1791
|
+
SOUTH: 3
|
|
1792
|
+
};
|
|
1793
|
+
var ZaloAdsProvinceCode = {
|
|
1794
|
+
// Miền Bắc (Region 1 - 28 tỉnh/thành)
|
|
1795
|
+
HANOI: "VN44",
|
|
1796
|
+
HAI_PHONG: "VN13",
|
|
1797
|
+
BAC_NINH: "VN74",
|
|
1798
|
+
QUANG_NINH: "VN30",
|
|
1799
|
+
HAI_DUONG: "VN79",
|
|
1800
|
+
HUNG_YEN: "VN81",
|
|
1801
|
+
VINH_PHUC: "VN86",
|
|
1802
|
+
THAI_NGUYEN: "VN85",
|
|
1803
|
+
BAC_GIANG: "VN71",
|
|
1804
|
+
PHU_THO: "VN83",
|
|
1805
|
+
NAM_DINH: "VN82",
|
|
1806
|
+
THAI_BINH: "VN35",
|
|
1807
|
+
NINH_BINH: "VN59",
|
|
1808
|
+
THANH_HOA: "VN34",
|
|
1809
|
+
NGHE_AN: "VN58",
|
|
1810
|
+
HA_TINH: "VN52",
|
|
1811
|
+
HOA_BINH: "VN53",
|
|
1812
|
+
SON_LA: "VN32",
|
|
1813
|
+
DIEN_BIEN: "VN92",
|
|
1814
|
+
LAI_CHAU: "VN89",
|
|
1815
|
+
LAO_CAI: "VN90",
|
|
1816
|
+
YEN_BAI: "VN70",
|
|
1817
|
+
TUYEN_QUANG: "VN68",
|
|
1818
|
+
HA_GIANG: "VN50",
|
|
1819
|
+
CAO_BANG: "VN05",
|
|
1820
|
+
BAC_KAN: "VN72",
|
|
1821
|
+
LANG_SON: "VN39",
|
|
1822
|
+
HA_NAM: "VN80",
|
|
1823
|
+
// Miền Trung (Region 2 - 16 tỉnh/thành)
|
|
1824
|
+
DA_NANG: "VN78",
|
|
1825
|
+
THUA_THIEN_HUE: "VN66",
|
|
1826
|
+
QUANG_NAM: "VN84",
|
|
1827
|
+
QUANG_NGAI: "VN63",
|
|
1828
|
+
BINH_DINH: "VN46",
|
|
1829
|
+
PHU_YEN: "VN61",
|
|
1830
|
+
KHANH_HOA: "VN54",
|
|
1831
|
+
NINH_THUAN: "VN60",
|
|
1832
|
+
BINH_THUAN: "VN47",
|
|
1833
|
+
KON_TUM: "VN55",
|
|
1834
|
+
GIA_LAI: "VN49",
|
|
1835
|
+
DAK_LAK: "VN88",
|
|
1836
|
+
DAK_NONG: "VN91",
|
|
1837
|
+
LAM_DONG: "VN23",
|
|
1838
|
+
QUANG_BINH: "VN62",
|
|
1839
|
+
QUANG_TRI: "VN64",
|
|
1840
|
+
// Miền Nam (Region 3 - 19 tỉnh/thành)
|
|
1841
|
+
HO_CHI_MINH: "VN20",
|
|
1842
|
+
BINH_DUONG: "VN75",
|
|
1843
|
+
DONG_NAI: "VN43",
|
|
1844
|
+
BA_RIA_VUNG_TAU: "VN45",
|
|
1845
|
+
LONG_AN: "VN24",
|
|
1846
|
+
TIEN_GIANG: "VN37",
|
|
1847
|
+
BEN_TRE: "VN03",
|
|
1848
|
+
DONG_THAP: "VN09",
|
|
1849
|
+
VINH_LONG: "VN69",
|
|
1850
|
+
CAN_THO: "VN87",
|
|
1851
|
+
HAU_GIANG: "VN93",
|
|
1852
|
+
AN_GIANG: "VN01",
|
|
1853
|
+
KIEN_GIANG: "VN21",
|
|
1854
|
+
SOC_TRANG: "VN65",
|
|
1855
|
+
BAC_LIEU: "VN73",
|
|
1856
|
+
CA_MAU: "VN77",
|
|
1857
|
+
TAY_NINH: "VN33",
|
|
1858
|
+
BINH_PHUOC: "VN76",
|
|
1859
|
+
TRA_VINH: "VN67"
|
|
1761
1860
|
};
|
|
1762
|
-
var
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1861
|
+
var ZaloAdsDeliveryType = {
|
|
1862
|
+
/** Tiêu chuẩn (0): Phân phối đồng đều nhất có thể theo giờ cao điểm (Standard). */
|
|
1863
|
+
STANDARD: 0,
|
|
1864
|
+
/** Tăng tốc (1): Phân phối nhanh nhất có thể để tối đa hóa tiếp cận (SpeedUp). */
|
|
1865
|
+
SPEED_UP: 1,
|
|
1866
|
+
/** Alias tương thích ngược cho SPEED_UP (1). */
|
|
1867
|
+
ACCELERATED: 1
|
|
1868
|
+
};
|
|
1869
|
+
var ZaloAdsSpendingMethod = {
|
|
1870
|
+
/** Tiêu chuẩn (0): Rải đều ngân sách xuyên suốt ngày. */
|
|
1871
|
+
STANDARD: 0,
|
|
1872
|
+
/** Tăng tốc (1): Phân phối nhanh, ưu tiên thắng thầu ngay khi có phiên đấu giá. */
|
|
1873
|
+
FAST: 1,
|
|
1874
|
+
/** Alias cho FAST (1). */
|
|
1875
|
+
ACCELERATED: 1
|
|
1876
|
+
};
|
|
1877
|
+
var ZaloAdsPriceType = {
|
|
1878
|
+
CPM: 1,
|
|
1879
|
+
CPC: 2,
|
|
1880
|
+
CPI: 3,
|
|
1881
|
+
CPF: 4,
|
|
1882
|
+
CPA: 5,
|
|
1883
|
+
CPO: 6,
|
|
1884
|
+
CPV: 7,
|
|
1885
|
+
CPD: 8,
|
|
1886
|
+
CPV1S: 9
|
|
1887
|
+
};
|
|
1888
|
+
var ZaloAdsPriceLimitType = {
|
|
1889
|
+
/** Áp dụng ngân sách cho toàn lịch chạy (Life time budget). */
|
|
1890
|
+
LIFE_TIME: 1,
|
|
1891
|
+
/** Áp dụng ngân sách cho mỗi ngày (Daily budget). */
|
|
1892
|
+
DAILY: 2
|
|
1893
|
+
};
|
|
1894
|
+
var ZaloAdsXTemplates = {
|
|
1895
|
+
/** Định dạng thẻ quay vòng lướt ngang nhiều hình ảnh. */
|
|
1896
|
+
CAROUSEL: 42,
|
|
1897
|
+
/** Định dạng bộ sưu tập album ảnh (lưới 4 ảnh). */
|
|
1898
|
+
ALBUM: 43,
|
|
1899
|
+
/** Định dạng video tự động phát trên Feed. */
|
|
1900
|
+
ZALO_VIDEO: 44,
|
|
1901
|
+
/** Định dạng ảnh dọc toàn màn hình. */
|
|
1902
|
+
PORTRAIT_IMAGE: 45,
|
|
1903
|
+
/** Định dạng ảnh đơn truyền thống (1024x533). */
|
|
1904
|
+
SINGLE_IMAGE: 46,
|
|
1905
|
+
/** Định dạng ảnh bìa cho quảng cáo video. */
|
|
1906
|
+
COVER_IMAGE_FOR_VIDEO_AD: 47,
|
|
1907
|
+
/** Định dạng ảnh vuông. */
|
|
1908
|
+
SQUARE_IMAGE: 48,
|
|
1909
|
+
/** Định dạng chú thích nội dung dài (tối đa 2.000 ký tự). */
|
|
1910
|
+
LONG_CAPTION: 49
|
|
1911
|
+
};
|
|
1912
|
+
var ZaloAdsImageRatio = {
|
|
1913
|
+
/** Tỉ lệ 16:9 (1024x576 px - Video / Banner phong cảnh). */
|
|
1914
|
+
RATIO_16_9: 0,
|
|
1915
|
+
/** Tỉ lệ 4:3 (1024x768 px - Ảnh phụ Album / Carousel). */
|
|
1916
|
+
RATIO_4_3: 1,
|
|
1917
|
+
/** Tỉ lệ 2:1 (1024x512 px - ẢNH BÌA NGANG BẮT BUỘC CỦA ALBUM). */
|
|
1918
|
+
RATIO_2_1: 2,
|
|
1919
|
+
/** Tỉ lệ 3:2. */
|
|
1920
|
+
RATIO_3_2: 3,
|
|
1921
|
+
/** Tỉ lệ 1:1 (1024x1024 px - Ảnh vuông). */
|
|
1922
|
+
RATIO_1_1: 4
|
|
1923
|
+
};
|
|
1924
|
+
var ZaloAdsUseConversion = {
|
|
1925
|
+
/** Không chọn pixel (0): Tắt tối ưu hóa chuyển đổi. */
|
|
1926
|
+
NOT_USE: 0,
|
|
1927
|
+
/** Pixel của tôi (1): Zalo Pixel tự host chèn script, cần kèm ConversionId. */
|
|
1928
|
+
USE: 1,
|
|
1929
|
+
/** Pixel liên kết Ladipage (2): Landing Page đối tác LadiPage. */
|
|
1930
|
+
LADI_PAGE: 2,
|
|
1931
|
+
/** Zalo Mini App (3): Ứng dụng Zalo Mini App. */
|
|
1932
|
+
MINI_APP: 3,
|
|
1933
|
+
/** Tạm thời tắt Pixel của tôi (-1): Cờ lưu nháp. */
|
|
1934
|
+
USE_OFF: -1,
|
|
1935
|
+
/** Tạm thời tắt Pixel Ladipage (-2): Cờ lưu nháp. */
|
|
1936
|
+
LADI_PAGE_OFF: -2,
|
|
1937
|
+
/** Tạm thời tắt Pixel Mini App (-3): Cờ lưu nháp. */
|
|
1938
|
+
MINI_APP_OFF: -3
|
|
1777
1939
|
};
|
|
1778
|
-
var
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
"binaryFields": [],
|
|
1784
|
-
"pathFields": [],
|
|
1785
|
-
"queryFields": [],
|
|
1786
|
-
"headerFields": [],
|
|
1787
|
-
"cookieFields": [],
|
|
1788
|
-
"bodyFields": []
|
|
1940
|
+
var ZaloAdsUpdateVideoAdRequest = class {
|
|
1941
|
+
data;
|
|
1942
|
+
est;
|
|
1943
|
+
isBoostAd;
|
|
1944
|
+
stt;
|
|
1789
1945
|
};
|
|
1790
|
-
var
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1795
|
-
"binaryFields": [],
|
|
1796
|
-
"pathFields": [],
|
|
1797
|
-
"queryFields": [
|
|
1798
|
-
"text"
|
|
1799
|
-
],
|
|
1800
|
-
"headerFields": [],
|
|
1801
|
-
"cookieFields": [],
|
|
1802
|
-
"bodyFields": []
|
|
1946
|
+
var ZaloAdsUpdateVideoAdResponse = class {
|
|
1947
|
+
code;
|
|
1948
|
+
msg;
|
|
1949
|
+
data;
|
|
1803
1950
|
};
|
|
1804
|
-
var
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
"binaryFields": [],
|
|
1810
|
-
"pathFields": [],
|
|
1811
|
-
"queryFields": [
|
|
1812
|
-
"campaignId",
|
|
1813
|
-
"campId"
|
|
1814
|
-
],
|
|
1815
|
-
"headerFields": [],
|
|
1816
|
-
"cookieFields": [],
|
|
1817
|
-
"bodyFields": []
|
|
1951
|
+
var ZaloAdsCampaignStatus = {
|
|
1952
|
+
OFF: 0,
|
|
1953
|
+
ACTIVE: 1,
|
|
1954
|
+
PAUSED: 2,
|
|
1955
|
+
DELETED: -2
|
|
1818
1956
|
};
|
|
1819
|
-
var
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
"endpoint": "/zaapi/getAdsFromCampaignId",
|
|
1823
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1824
|
-
"binaryFields": [],
|
|
1825
|
-
"pathFields": [],
|
|
1826
|
-
"queryFields": [
|
|
1827
|
-
"campaignId",
|
|
1828
|
-
"campId",
|
|
1829
|
-
"dataType",
|
|
1830
|
-
"v"
|
|
1831
|
-
],
|
|
1832
|
-
"headerFields": [],
|
|
1833
|
-
"cookieFields": [],
|
|
1834
|
-
"bodyFields": []
|
|
1957
|
+
var ZaloAdsCreatePostCampaignRequest = class {
|
|
1958
|
+
/** Cấu hình chiến dịch Bài viết (object hoặc chuỗi JSON). */
|
|
1959
|
+
data;
|
|
1835
1960
|
};
|
|
1836
|
-
var
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
"binaryFields": [],
|
|
1842
|
-
"pathFields": [],
|
|
1843
|
-
"queryFields": [],
|
|
1844
|
-
"headerFields": [],
|
|
1845
|
-
"cookieFields": [],
|
|
1846
|
-
"bodyFields": []
|
|
1961
|
+
var ZaloAdsCreatePostCampaignResponse = class {
|
|
1962
|
+
code;
|
|
1963
|
+
/** Chuỗi ID quảng cáo mới trong response Zalo Ads. */
|
|
1964
|
+
msg;
|
|
1965
|
+
data;
|
|
1847
1966
|
};
|
|
1848
|
-
var
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1967
|
+
var ZaloAdsMessageAdUpdateDataDto = class {
|
|
1968
|
+
AdId;
|
|
1969
|
+
CampaignId;
|
|
1970
|
+
MemberId;
|
|
1971
|
+
/** Phiên bản lạc quan lấy từ bản quảng cáo hiện tại. */
|
|
1972
|
+
RowVersion;
|
|
1973
|
+
AdName;
|
|
1974
|
+
/** 20 (hoặc 19) là quảng cáo Tin nhắn. */
|
|
1975
|
+
Type;
|
|
1976
|
+
Settings;
|
|
1977
|
+
Status;
|
|
1978
|
+
StartDate;
|
|
1979
|
+
EndDate;
|
|
1980
|
+
/** ID kịch bản, lấy từ createFlow hoặc listFlowsByOfficialAccount. */
|
|
1981
|
+
ZaloFlowId;
|
|
1982
|
+
ZaloPageId;
|
|
1983
|
+
ZaloFormId;
|
|
1984
|
+
UseConversion;
|
|
1985
|
+
ConversionId;
|
|
1986
|
+
Report;
|
|
1861
1987
|
};
|
|
1862
|
-
var
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
"
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
"cookieFields": [],
|
|
1872
|
-
"bodyFields": []
|
|
1988
|
+
var ZaloAdsUpdateMessageAdRequest = class {
|
|
1989
|
+
/** Payload quảng cáo đầy đủ (object hoặc chuỗi JSON); service tự tuần tự hóa thành field form data. */
|
|
1990
|
+
data;
|
|
1991
|
+
/** Tham số UI phụ trợ; capture Zalo Ads có giá trị literal "undefined". */
|
|
1992
|
+
est;
|
|
1993
|
+
/** 0 là quảng cáo thông thường, 1 là boost ad. */
|
|
1994
|
+
isBoostAd;
|
|
1995
|
+
/** Trạng thái thao tác của giao diện; mẫu đã ghi nhận 0. */
|
|
1996
|
+
stt;
|
|
1873
1997
|
};
|
|
1874
|
-
var
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1879
|
-
"binaryFields": [],
|
|
1880
|
-
"pathFields": [],
|
|
1881
|
-
"queryFields": [
|
|
1882
|
-
"oaId",
|
|
1883
|
-
"isAll"
|
|
1884
|
-
],
|
|
1885
|
-
"headerFields": [],
|
|
1886
|
-
"cookieFields": [],
|
|
1887
|
-
"bodyFields": []
|
|
1888
|
-
};
|
|
1889
|
-
var OP_ZaloAdsListMiniPagesByTemplate = {
|
|
1890
|
-
"operationId": "ZaloAds_listMiniPagesByTemplate",
|
|
1891
|
-
"method": "GET",
|
|
1892
|
-
"endpoint": "/api/mini-pages",
|
|
1893
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1894
|
-
"binaryFields": [],
|
|
1895
|
-
"pathFields": [],
|
|
1896
|
-
"queryFields": [
|
|
1897
|
-
"templateIds"
|
|
1898
|
-
],
|
|
1899
|
-
"headerFields": [],
|
|
1900
|
-
"cookieFields": [],
|
|
1901
|
-
"bodyFields": []
|
|
1902
|
-
};
|
|
1903
|
-
var OP_ZaloAdsPostZaapiDeletead = {
|
|
1904
|
-
"operationId": "ZaloAds_postZaapiDeletead",
|
|
1905
|
-
"method": "POST",
|
|
1906
|
-
"endpoint": "/zaapi/deleteAd",
|
|
1907
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1908
|
-
"binaryFields": [],
|
|
1909
|
-
"pathFields": [],
|
|
1910
|
-
"queryFields": [
|
|
1911
|
-
"adId"
|
|
1912
|
-
],
|
|
1913
|
-
"headerFields": [],
|
|
1914
|
-
"cookieFields": [],
|
|
1915
|
-
"bodyFields": [
|
|
1916
|
-
"adId"
|
|
1917
|
-
]
|
|
1918
|
-
};
|
|
1919
|
-
var OP_ZaloAdsRenameCampaign = {
|
|
1920
|
-
"operationId": "ZaloAds_renameCampaign",
|
|
1921
|
-
"method": "POST",
|
|
1922
|
-
"endpoint": "/api/campaign/change-name",
|
|
1923
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1924
|
-
"binaryFields": [],
|
|
1925
|
-
"pathFields": [],
|
|
1926
|
-
"queryFields": [],
|
|
1927
|
-
"headerFields": [],
|
|
1928
|
-
"cookieFields": [],
|
|
1929
|
-
"bodyFields": [
|
|
1930
|
-
"campid",
|
|
1931
|
-
"newname"
|
|
1932
|
-
]
|
|
1933
|
-
};
|
|
1934
|
-
var OP_ZaloAdsUpdateEcommerceAd = {
|
|
1935
|
-
"operationId": "ZaloAds_updateEcommerceAd",
|
|
1936
|
-
"method": "POST",
|
|
1937
|
-
"endpoint": "/zaapi/UpdateAd",
|
|
1938
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1939
|
-
"binaryFields": [],
|
|
1940
|
-
"pathFields": [],
|
|
1941
|
-
"queryFields": [],
|
|
1942
|
-
"headerFields": [],
|
|
1943
|
-
"cookieFields": [],
|
|
1944
|
-
"bodyFields": [
|
|
1945
|
-
"est",
|
|
1946
|
-
"stt",
|
|
1947
|
-
"data",
|
|
1948
|
-
"isBoostAd"
|
|
1949
|
-
]
|
|
1998
|
+
var ZaloAdsUpdateMessageAdResponse = class {
|
|
1999
|
+
msg;
|
|
2000
|
+
code;
|
|
2001
|
+
data;
|
|
1950
2002
|
};
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
"est",
|
|
1963
|
-
"stt",
|
|
1964
|
-
"data",
|
|
1965
|
-
"isBoostAd"
|
|
1966
|
-
]
|
|
2003
|
+
|
|
2004
|
+
// src/validators/campaigns.validator.ts
|
|
2005
|
+
var VALID_CAMPAIGN_TYPES = {
|
|
2006
|
+
WEBSITE: 6,
|
|
2007
|
+
FORM: 17,
|
|
2008
|
+
MESSAGE: 18,
|
|
2009
|
+
OA: 3,
|
|
2010
|
+
VIDEO: 14,
|
|
2011
|
+
COMMERCE: 22,
|
|
2012
|
+
ARTICLE: 4,
|
|
2013
|
+
DISPLAY: 20
|
|
1967
2014
|
};
|
|
1968
|
-
var
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
"bodyFields": [
|
|
1979
|
-
"est",
|
|
1980
|
-
"stt",
|
|
1981
|
-
"data",
|
|
1982
|
-
"isBoostAd"
|
|
1983
|
-
]
|
|
2015
|
+
var VALID_AD_TYPES = {
|
|
2016
|
+
WEBSITE: 5,
|
|
2017
|
+
FORM: 18,
|
|
2018
|
+
MESSAGE: 30,
|
|
2019
|
+
OA: 2,
|
|
2020
|
+
VIDEO: 11,
|
|
2021
|
+
COMMERCE: 28,
|
|
2022
|
+
// Server trả về 28 (không phải 23)
|
|
2023
|
+
ARTICLE: 3,
|
|
2024
|
+
DISPLAY: 21
|
|
1984
2025
|
};
|
|
1985
|
-
var
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
2026
|
+
var ALLOWED_CTAS_PER_AD_TYPE = {
|
|
2027
|
+
// Website (Type 5): 9 CTAs
|
|
2028
|
+
[VALID_AD_TYPES.WEBSITE]: [
|
|
2029
|
+
ZaloAdsActionType.DAT_NGAY,
|
|
2030
|
+
ZaloAdsActionType.MUA_NGAY,
|
|
2031
|
+
ZaloAdsActionType.THU_NGAY,
|
|
2032
|
+
ZaloAdsActionType.TAI_NGAY,
|
|
2033
|
+
ZaloAdsActionType.XEM_THEM,
|
|
2034
|
+
ZaloAdsActionType.NGHE_NGAY,
|
|
2035
|
+
ZaloAdsActionType.CHOI_NGAY,
|
|
2036
|
+
ZaloAdsActionType.DANG_KY,
|
|
2037
|
+
ZaloAdsActionType.GOI_DIEN
|
|
1992
2038
|
],
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
]
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
"queryFields": [],
|
|
2031
|
-
"headerFields": [],
|
|
2032
|
-
"cookieFields": [],
|
|
2033
|
-
"bodyFields": [
|
|
2034
|
-
"est",
|
|
2035
|
-
"stt",
|
|
2036
|
-
"data",
|
|
2037
|
-
"isBoostAd"
|
|
2038
|
-
]
|
|
2039
|
-
};
|
|
2040
|
-
var OP_ZaloAdsCreateWebsiteCampaign = {
|
|
2041
|
-
"operationId": "ZaloAds_createWebsiteCampaign",
|
|
2042
|
-
"method": "POST",
|
|
2043
|
-
"endpoint": "/zaapi/addNewCamp",
|
|
2044
|
-
"baseUrl": "https://ads.zalo.me",
|
|
2045
|
-
"binaryFields": [],
|
|
2046
|
-
"pathFields": [],
|
|
2047
|
-
"queryFields": [],
|
|
2048
|
-
"headerFields": [],
|
|
2049
|
-
"cookieFields": [],
|
|
2050
|
-
"bodyFields": [
|
|
2051
|
-
"data"
|
|
2052
|
-
]
|
|
2039
|
+
// Video (Type 11): 8 CTAs
|
|
2040
|
+
[VALID_AD_TYPES.VIDEO]: [
|
|
2041
|
+
ZaloAdsActionType.DAT_NGAY,
|
|
2042
|
+
ZaloAdsActionType.MUA_NGAY,
|
|
2043
|
+
ZaloAdsActionType.THU_NGAY,
|
|
2044
|
+
ZaloAdsActionType.TAI_NGAY,
|
|
2045
|
+
ZaloAdsActionType.XEM_THEM,
|
|
2046
|
+
ZaloAdsActionType.NGHE_NGAY,
|
|
2047
|
+
ZaloAdsActionType.CHOI_NGAY,
|
|
2048
|
+
ZaloAdsActionType.DANG_KY
|
|
2049
|
+
],
|
|
2050
|
+
// Article (Type 3): 7 CTAs
|
|
2051
|
+
[VALID_AD_TYPES.ARTICLE]: [
|
|
2052
|
+
ZaloAdsActionType.DAT_NGAY,
|
|
2053
|
+
ZaloAdsActionType.MUA_NGAY,
|
|
2054
|
+
ZaloAdsActionType.THU_NGAY,
|
|
2055
|
+
ZaloAdsActionType.TAI_NGAY,
|
|
2056
|
+
ZaloAdsActionType.XEM_THEM,
|
|
2057
|
+
ZaloAdsActionType.CHOI_NGAY,
|
|
2058
|
+
ZaloAdsActionType.DANG_KY
|
|
2059
|
+
],
|
|
2060
|
+
// Form (Type 18): 5 CTAs
|
|
2061
|
+
[VALID_AD_TYPES.FORM]: [
|
|
2062
|
+
ZaloAdsActionType.DAT_NGAY,
|
|
2063
|
+
ZaloAdsActionType.MUA_NGAY,
|
|
2064
|
+
ZaloAdsActionType.THU_NGAY,
|
|
2065
|
+
ZaloAdsActionType.XEM_THEM,
|
|
2066
|
+
ZaloAdsActionType.DANG_KY
|
|
2067
|
+
],
|
|
2068
|
+
// Commerce (Type 28): 3 CTAs
|
|
2069
|
+
[VALID_AD_TYPES.COMMERCE]: [
|
|
2070
|
+
ZaloAdsActionType.DAT_NGAY,
|
|
2071
|
+
ZaloAdsActionType.MUA_NGAY,
|
|
2072
|
+
ZaloAdsActionType.XEM_THEM
|
|
2073
|
+
],
|
|
2074
|
+
// OA (Type 2): Cố định Quan tâm OA (6)
|
|
2075
|
+
[VALID_AD_TYPES.OA]: [ZaloAdsActionType.QUAN_TAM_OA]
|
|
2053
2076
|
};
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
"
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
"queryFields": [],
|
|
2062
|
-
"headerFields": [],
|
|
2063
|
-
"cookieFields": [],
|
|
2064
|
-
"bodyFields": [
|
|
2065
|
-
"est",
|
|
2066
|
-
"stt",
|
|
2067
|
-
"data",
|
|
2068
|
-
"isBoostAd"
|
|
2069
|
-
]
|
|
2070
|
-
};
|
|
2071
|
-
var OP_ZaloAdsCreateDisplayCampaign = {
|
|
2072
|
-
"operationId": "ZaloAds_createDisplayCampaign",
|
|
2073
|
-
"method": "POST",
|
|
2074
|
-
"endpoint": "/zaapi/addNewCamp",
|
|
2075
|
-
"baseUrl": "https://ads.zalo.me",
|
|
2076
|
-
"binaryFields": [],
|
|
2077
|
-
"pathFields": [],
|
|
2078
|
-
"queryFields": [],
|
|
2079
|
-
"headerFields": [],
|
|
2080
|
-
"cookieFields": [],
|
|
2081
|
-
"bodyFields": [
|
|
2082
|
-
"data"
|
|
2083
|
-
]
|
|
2084
|
-
};
|
|
2085
|
-
var OP_ZaloAdsUpdateDisplayAd = {
|
|
2086
|
-
"operationId": "ZaloAds_updateDisplayAd",
|
|
2087
|
-
"method": "POST",
|
|
2088
|
-
"endpoint": "/zaapi/UpdateAd",
|
|
2089
|
-
"baseUrl": "https://ads.zalo.me",
|
|
2090
|
-
"binaryFields": [],
|
|
2091
|
-
"pathFields": [],
|
|
2092
|
-
"queryFields": [],
|
|
2093
|
-
"headerFields": [],
|
|
2094
|
-
"cookieFields": [],
|
|
2095
|
-
"bodyFields": [
|
|
2096
|
-
"est",
|
|
2097
|
-
"stt",
|
|
2098
|
-
"data",
|
|
2099
|
-
"isBoostAd"
|
|
2100
|
-
]
|
|
2101
|
-
};
|
|
2102
|
-
var OP_ZaloAdsCreateVideoCampaign = {
|
|
2103
|
-
"operationId": "ZaloAds_createVideoCampaign",
|
|
2104
|
-
"method": "POST",
|
|
2105
|
-
"endpoint": "/zaapi/addNewCamp",
|
|
2106
|
-
"baseUrl": "https://ads.zalo.me",
|
|
2107
|
-
"binaryFields": [],
|
|
2108
|
-
"pathFields": [],
|
|
2109
|
-
"queryFields": [],
|
|
2110
|
-
"headerFields": [],
|
|
2111
|
-
"cookieFields": [],
|
|
2112
|
-
"bodyFields": [
|
|
2113
|
-
"data"
|
|
2114
|
-
]
|
|
2115
|
-
};
|
|
2116
|
-
var OP_ZaloAdsDeleteCampaign = {
|
|
2117
|
-
"operationId": "ZaloAds_deleteCampaign",
|
|
2118
|
-
"method": "POST",
|
|
2119
|
-
"endpoint": "/api/campaign/change-status",
|
|
2120
|
-
"baseUrl": "https://ads.zalo.me",
|
|
2121
|
-
"binaryFields": [],
|
|
2122
|
-
"pathFields": [],
|
|
2123
|
-
"queryFields": [],
|
|
2124
|
-
"headerFields": [],
|
|
2125
|
-
"cookieFields": [],
|
|
2126
|
-
"bodyFields": [
|
|
2127
|
-
"campaignId",
|
|
2128
|
-
"status"
|
|
2129
|
-
]
|
|
2130
|
-
};
|
|
2131
|
-
var OP_ZaloAdsDuplicateAd = {
|
|
2132
|
-
operationId: "zalo_ads_duplicate_ad",
|
|
2133
|
-
method: "POST",
|
|
2134
|
-
endpoint: "/zaapi/DuplicateAd",
|
|
2135
|
-
baseUrl: "https://ads.zalo.me",
|
|
2136
|
-
binaryFields: [],
|
|
2137
|
-
pathFields: [],
|
|
2138
|
-
queryFields: [],
|
|
2139
|
-
headerFields: [],
|
|
2140
|
-
cookieFields: [],
|
|
2141
|
-
bodyFields: ["adid"]
|
|
2142
|
-
};
|
|
2143
|
-
var OP_ZaloAdsCreateSpellCheckV3Job = {
|
|
2144
|
-
operationId: "zalo_ads_create_spell_check_v3_job",
|
|
2145
|
-
method: "POST",
|
|
2146
|
-
endpoint: "/api/spell-check/v3",
|
|
2147
|
-
baseUrl: "https://ads.zalo.me",
|
|
2148
|
-
binaryFields: [],
|
|
2149
|
-
pathFields: [],
|
|
2150
|
-
queryFields: [],
|
|
2151
|
-
headerFields: [],
|
|
2152
|
-
cookieFields: [],
|
|
2153
|
-
bodyFields: ["title", "caption"]
|
|
2154
|
-
};
|
|
2155
|
-
var OP_ZaloAdsGetSpellCheckV3Job = {
|
|
2156
|
-
operationId: "zalo_ads_get_spell_check_v3_job",
|
|
2157
|
-
method: "GET",
|
|
2158
|
-
endpoint: "/api/spell-check/v3/{jobId}",
|
|
2159
|
-
baseUrl: "https://ads.zalo.me",
|
|
2160
|
-
binaryFields: [],
|
|
2161
|
-
pathFields: ["jobId"],
|
|
2162
|
-
queryFields: [],
|
|
2163
|
-
headerFields: [],
|
|
2164
|
-
cookieFields: [],
|
|
2165
|
-
bodyFields: []
|
|
2166
|
-
};
|
|
2167
|
-
var ZaloCampaignsService = class {
|
|
2168
|
-
constructor(client) {
|
|
2169
|
-
this.client = client;
|
|
2170
|
-
}
|
|
2171
|
-
validator = ZaloCampaignsValidator;
|
|
2172
|
-
static validator = ZaloCampaignsValidator;
|
|
2173
|
-
updateVideoAd(request, options) {
|
|
2174
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateVideoAd, this.client.toTransportInput(OP_ZaloAdsUpdateVideoAd, request), options);
|
|
2175
|
-
}
|
|
2176
|
-
changeCampaignStatus(request, options) {
|
|
2177
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsChangeCampaignStatus, this.client.toTransportInput(OP_ZaloAdsChangeCampaignStatus, request), options);
|
|
2178
|
-
}
|
|
2179
|
-
deleteCampaign(request, options) {
|
|
2180
|
-
const payload = { campaignId: request.campaignId, status: request.status ?? -2 };
|
|
2181
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsDeleteCampaign, this.client.toTransportInput(OP_ZaloAdsDeleteCampaign, payload), options);
|
|
2182
|
-
}
|
|
2183
|
-
createWebsiteCampaign(request, options) {
|
|
2184
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateWebsiteCampaign, this.client.toTransportInput(OP_ZaloAdsCreateWebsiteCampaign, request), options);
|
|
2185
|
-
}
|
|
2186
|
-
updateWebsiteAd(request, options) {
|
|
2187
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateWebsiteAd, this.client.toTransportInput(OP_ZaloAdsUpdateWebsiteAd, request), options);
|
|
2188
|
-
}
|
|
2189
|
-
createDisplayCampaign(request, options) {
|
|
2190
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateDisplayCampaign, this.client.toTransportInput(OP_ZaloAdsCreateDisplayCampaign, request), options);
|
|
2191
|
-
}
|
|
2192
|
-
updateDisplayAd(request, options) {
|
|
2193
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateDisplayAd, this.client.toTransportInput(OP_ZaloAdsUpdateDisplayAd, request), options);
|
|
2077
|
+
function validateCreateCampaignPayload(payload, options = {}) {
|
|
2078
|
+
const errors = [];
|
|
2079
|
+
const warnings = [];
|
|
2080
|
+
if (!payload.name || typeof payload.name !== "string" || !payload.name.trim()) {
|
|
2081
|
+
errors.push("name l\xE0 b\u1EAFt bu\u1ED9c v\xE0 kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
|
|
2082
|
+
} else if (payload.name.length > 255) {
|
|
2083
|
+
errors.push("name kh\xF4ng \u0111\u01B0\u1EE3c v\u01B0\u1EE3t qu\xE1 255 k\xFD t\u1EF1.");
|
|
2194
2084
|
}
|
|
2195
|
-
|
|
2196
|
-
|
|
2085
|
+
const validTypes = Object.values(VALID_CAMPAIGN_TYPES);
|
|
2086
|
+
if (payload.campaignType === void 0 || payload.campaignType === null) {
|
|
2087
|
+
errors.push("campaignType l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
2088
|
+
} else if (!validTypes.includes(payload.campaignType)) {
|
|
2089
|
+
errors.push(
|
|
2090
|
+
`campaignType: ${payload.campaignType} kh\xF4ng h\u1EE3p l\u1EC7. C\xE1c lo\u1EA1i h\u1ED7 tr\u1EE3: 6 (Website), 17 (Form), 18 (Message), 3 (OA), 14 (Video), 22 (Commerce), 4 (Article), 20 (Display).`
|
|
2091
|
+
);
|
|
2197
2092
|
}
|
|
2198
|
-
|
|
2199
|
-
|
|
2093
|
+
if (payload.campaignType !== VALID_CAMPAIGN_TYPES.DISPLAY) {
|
|
2094
|
+
if (!payload.pageId || payload.pageId <= 0) {
|
|
2095
|
+
errors.push("pageId c\u1EE7a Official Account l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi lo\u1EA1i chi\u1EBFn d\u1ECBch n\xE0y (ph\u1EA3i > 0).");
|
|
2096
|
+
}
|
|
2097
|
+
} else {
|
|
2098
|
+
if (payload.pageId !== -1 && payload.pageId !== 0 && !payload.pageId) {
|
|
2099
|
+
warnings.push("Qu\u1EA3ng c\xE1o Display th\u01B0\u1EDDng s\u1EED d\u1EE5ng pageId = -1.");
|
|
2100
|
+
}
|
|
2200
2101
|
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2102
|
+
switch (payload.campaignType) {
|
|
2103
|
+
case VALID_CAMPAIGN_TYPES.WEBSITE:
|
|
2104
|
+
if (!payload.targetUrl || typeof payload.targetUrl !== "string" || !payload.targetUrl.trim()) {
|
|
2105
|
+
errors.push("targetUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Website.");
|
|
2106
|
+
} else if (!/^https?:\/\/.+/i.test(payload.targetUrl)) {
|
|
2107
|
+
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://.");
|
|
2108
|
+
}
|
|
2109
|
+
break;
|
|
2110
|
+
case VALID_CAMPAIGN_TYPES.ARTICLE:
|
|
2111
|
+
if (!payload.articleId || payload.articleId <= 0) {
|
|
2112
|
+
errors.push("articleId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o B\xE0i Vi\u1EBFt (ph\u1EA3i > 0, l\u1EA5y t\u1EEB getOwnedArticles).");
|
|
2113
|
+
}
|
|
2114
|
+
break;
|
|
2115
|
+
case VALID_CAMPAIGN_TYPES.COMMERCE:
|
|
2116
|
+
if (payload.productId === void 0 || payload.productId === null) {
|
|
2117
|
+
warnings.push("Qu\u1EA3ng c\xE1o Commerce n\xEAn ch\u1EC9 \u0111\u1ECBnh productId (ho\u1EB7c -1/0 khi d\xF9ng Instant Page s\u1EA3n ph\u1EA9m).");
|
|
2118
|
+
}
|
|
2119
|
+
break;
|
|
2120
|
+
case VALID_CAMPAIGN_TYPES.FORM:
|
|
2121
|
+
case VALID_CAMPAIGN_TYPES.MESSAGE:
|
|
2122
|
+
break;
|
|
2204
2123
|
}
|
|
2205
|
-
|
|
2206
|
-
|
|
2124
|
+
if (payload.budgetType !== void 0 && payload.budgetlimit !== void 0) {
|
|
2125
|
+
if (payload.budgetType === 2) {
|
|
2126
|
+
if (payload.budgetlimit > 0 && payload.budgetlimit < 6e5) {
|
|
2127
|
+
errors.push("Ng\xE2n s\xE1ch cho To\xE0n l\u1ECBch ch\u1EA1y t\u1ED1i thi\u1EC3u l\xE0 600,000 VN\u0110.");
|
|
2128
|
+
}
|
|
2129
|
+
} else if (payload.budgetType === 1) {
|
|
2130
|
+
if (payload.budgetlimit > 0 && payload.budgetlimit < 50) {
|
|
2131
|
+
warnings.push("S\u1ED1 l\u01B0\u1EE3ng t\u01B0\u01A1ng t\xE1c m\u1ED7i ng\xE0y t\u1ED1i thi\u1EC3u \u0111\u01B0\u1EE3c khuy\u1EBFn ngh\u1ECB t\u1EEB 50 l\u01B0\u1EE3t.");
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2207
2134
|
}
|
|
2208
|
-
|
|
2209
|
-
|
|
2135
|
+
if (payload.campaignId && payload.campaignId > 0) {
|
|
2136
|
+
if (payload.adId !== 0) {
|
|
2137
|
+
warnings.push("Khi th\xEAm Ad m\u1EDBi v\xE0o chi\u1EBFn d\u1ECBch hi\u1EC7n c\xF3 (Multi-Ad), adId n\xEAn \u0111\u1EC3 b\u1EB1ng 0.");
|
|
2138
|
+
}
|
|
2210
2139
|
}
|
|
2211
|
-
|
|
2212
|
-
|
|
2140
|
+
return {
|
|
2141
|
+
isValid: errors.length === 0,
|
|
2142
|
+
errors,
|
|
2143
|
+
warnings
|
|
2144
|
+
};
|
|
2145
|
+
}
|
|
2146
|
+
function validateUpdateAdPayload(payload, options = {}) {
|
|
2147
|
+
const errors = [];
|
|
2148
|
+
const warnings = [];
|
|
2149
|
+
if (!payload.AdId || payload.AdId <= 0) {
|
|
2150
|
+
errors.push("AdId l\xE0 b\u1EAFt bu\u1ED9c (ph\u1EA3i > 0).");
|
|
2213
2151
|
}
|
|
2214
|
-
|
|
2215
|
-
|
|
2152
|
+
if (!payload.CampaignId || payload.CampaignId <= 0) {
|
|
2153
|
+
errors.push("CampaignId l\xE0 b\u1EAFt bu\u1ED9c (ph\u1EA3i > 0).");
|
|
2216
2154
|
}
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2155
|
+
if (!payload.AdName || !payload.AdName.trim()) {
|
|
2156
|
+
errors.push("AdName l\xE0 b\u1EAFt bu\u1ED9c v\xE0 kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
|
|
2157
|
+
} else if (payload.AdName.length > 255) {
|
|
2158
|
+
errors.push(`AdName qu\xE1 d\xE0i (${payload.AdName.length}/255 k\xFD t\u1EF1).`);
|
|
2220
2159
|
}
|
|
2221
|
-
|
|
2222
|
-
|
|
2160
|
+
const adInfo = payload.Settings?.AdInfo;
|
|
2161
|
+
if (!adInfo) {
|
|
2162
|
+
errors.push("Settings.AdInfo l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
2163
|
+
} else {
|
|
2164
|
+
if (!adInfo.Caption || !adInfo.Caption.trim()) {
|
|
2165
|
+
errors.push("Settings.AdInfo.Caption l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
2166
|
+
} else {
|
|
2167
|
+
const captionLen = adInfo.Caption.trim().length;
|
|
2168
|
+
if (captionLen < 35) {
|
|
2169
|
+
errors.push(`Settings.AdInfo.Caption qu\xE1 ng\u1EAFn (${captionLen}/35 k\xFD t\u1EF1 t\u1ED1i thi\u1EC3u).`);
|
|
2170
|
+
} else if (captionLen > 90) {
|
|
2171
|
+
errors.push(`Settings.AdInfo.Caption qu\xE1 d\xE0i (${captionLen}/90 k\xFD t\u1EF1 t\u1ED1i \u0111a).`);
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
const longCaption = adInfo.LongCaption ?? adInfo.MoreInfo;
|
|
2175
|
+
if (longCaption !== void 0 && longCaption !== null && longCaption.trim().length > 0) {
|
|
2176
|
+
const longCaptionLen = longCaption.trim().length;
|
|
2177
|
+
if (longCaptionLen < 90) {
|
|
2178
|
+
errors.push(
|
|
2179
|
+
`Settings.AdInfo.LongCaption (Ch\xFA th\xEDch m\u1EDF r\u1ED9ng) qu\xE1 ng\u1EAFn (${longCaptionLen}/90 k\xFD t\u1EF1 t\u1ED1i thi\u1EC3u). Theo quy chu\u1EA9n Zalo Ads, tr\u01B0\u1EDDng n\xE0y kh\xF4ng b\u1EAFt bu\u1ED9c, nh\u01B0ng n\u1EBFu nh\u1EADp th\xEC b\u1EAFt bu\u1ED9c ph\u1EA3i t\u1EEB 90 \u0111\u1EBFn 2,000 k\xFD t\u1EF1.`
|
|
2180
|
+
);
|
|
2181
|
+
} else if (longCaptionLen > 2e3) {
|
|
2182
|
+
errors.push(
|
|
2183
|
+
`Settings.AdInfo.LongCaption (Ch\xFA th\xEDch m\u1EDF r\u1ED9ng) qu\xE1 d\xE0i (${longCaptionLen}/2000 k\xFD t\u1EF1 t\u1ED1i \u0111a).`
|
|
2184
|
+
);
|
|
2185
|
+
}
|
|
2186
|
+
if (adInfo.XTemplates && Array.isArray(adInfo.XTemplates) && !adInfo.XTemplates.includes(49)) {
|
|
2187
|
+
warnings.push(
|
|
2188
|
+
"Khi c\xF3 Ch\xFA th\xEDch m\u1EDF r\u1ED9ng (LongCaption), b\u1EA1n n\xEAn th\xEAm m\xE3 49 (LONG_CAPTION) v\xE0o Settings.AdInfo.XTemplates \u0111\u1EC3 k\xEDch ho\u1EA1t giao di\u1EC7n hi\u1EC3n th\u1ECB b\xE0i vi\u1EBFt d\xE0i tr\xEAn Zalo Feed."
|
|
2189
|
+
);
|
|
2190
|
+
}
|
|
2191
|
+
}
|
|
2192
|
+
if (adInfo.Action !== void 0 && payload.Type) {
|
|
2193
|
+
const allowedCtas = ALLOWED_CTAS_PER_AD_TYPE[payload.Type];
|
|
2194
|
+
if (allowedCtas && !allowedCtas.includes(adInfo.Action)) {
|
|
2195
|
+
warnings.push(
|
|
2196
|
+
`M\xE3 h\xE0nh \u0111\u1ED9ng Action: ${adInfo.Action} c\xF3 th\u1EC3 kh\xF4ng n\u1EB1m trong danh m\u1EE5c n\xFAt CTA h\u1ED7 tr\u1EE3 cho Ad Type ${payload.Type}.`
|
|
2197
|
+
);
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2223
2200
|
}
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
}
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2201
|
+
const price = payload.Settings?.Price;
|
|
2202
|
+
if (!price) {
|
|
2203
|
+
errors.push("Settings.Price l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
2204
|
+
} else {
|
|
2205
|
+
if (payload.Type === VALID_AD_TYPES.WEBSITE) {
|
|
2206
|
+
if (price.Type !== 1) {
|
|
2207
|
+
errors.push(
|
|
2208
|
+
"\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Website (Type 5), Price.Type b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 1 (CPC). N\u1EBFu truy\u1EC1n 2 s\u1EBD b\u1ECB m\xE1y ch\u1EE7 l\u1ED7i."
|
|
2209
|
+
);
|
|
2210
|
+
}
|
|
2211
|
+
if (price.LimitType === 1) {
|
|
2212
|
+
errors.push(
|
|
2213
|
+
"Qu\u1EA3ng c\xE1o Website kh\xF4ng h\u1ED7 tr\u1EE3 LimitType: 1 (t\u1ED5ng ng\xE2n s\xE1ch). B\u1EAFt bu\u1ED9c ph\u1EA3i d\xF9ng LimitType: 0 (ng\xE2n s\xE1ch ng\xE0y)."
|
|
2214
|
+
);
|
|
2215
|
+
}
|
|
2216
|
+
} else if (payload.Type === VALID_AD_TYPES.VIDEO) {
|
|
2217
|
+
if (price.Type !== 1 && price.Type !== 7) {
|
|
2218
|
+
errors.push(
|
|
2219
|
+
"\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."
|
|
2220
|
+
);
|
|
2221
|
+
}
|
|
2222
|
+
if (price.Type === 1 && (price.Limit ?? 0) < 50) {
|
|
2223
|
+
errors.push(
|
|
2224
|
+
"\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)."
|
|
2225
|
+
);
|
|
2226
|
+
}
|
|
2227
|
+
} else if (payload.Type === VALID_AD_TYPES.COMMERCE || payload.Type === VALID_AD_TYPES.ARTICLE || payload.Type === VALID_AD_TYPES.FORM) {
|
|
2228
|
+
if (price.Type !== 2) {
|
|
2229
|
+
errors.push(
|
|
2230
|
+
`\u0110\u1ED1i v\u1EDBi Ad Type ${payload.Type}, Price.Type b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 2 (CPC).`
|
|
2231
|
+
);
|
|
2232
|
+
}
|
|
2233
|
+
} else if (payload.Type === VALID_AD_TYPES.OA) {
|
|
2234
|
+
if (price.Type !== 2 && price.Type !== 5) {
|
|
2235
|
+
errors.push(
|
|
2236
|
+
"\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o OA (Type 2), Price.Type ch\u1EC9 h\u1ED7 tr\u1EE3 2 (L\u01B0\u1EE3t nh\u1EA5n - CPC) ho\u1EB7c 5 (L\u01B0\u1EE3t quan t\xE2m - CPA Beta)."
|
|
2237
|
+
);
|
|
2238
|
+
}
|
|
2239
|
+
if (price.Type === 2) {
|
|
2240
|
+
if (price.SpendingMethod !== 0 && price.SpendingMethod !== void 0) {
|
|
2241
|
+
errors.push(
|
|
2242
|
+
"Khi t\xEDnh ti\u1EC1n theo L\u01B0\u1EE3t nh\u1EA5n (Price.Type = 2 / CPC), SpendingMethod b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 0 (\u0110\u1EB7t gi\xE1 th\u1EA7u th\u1EE7 c\xF4ng theo s\u1ED1 l\u01B0\u1EE3ng t\u01B0\u01A1ng t\xE1c)."
|
|
2243
|
+
);
|
|
2244
|
+
}
|
|
2245
|
+
if (price.Bid !== void 0 && price.Bid < 650) {
|
|
2246
|
+
errors.push(
|
|
2247
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i l\u01B0\u1EE3t nh\u1EA5n (Price.Bid) t\u1ED1i thi\u1EC3u l\xE0 650 VN\u0110 (s\xE0n h\u1EC7 th\u1ED1ng Zalo Ads). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2248
|
+
);
|
|
2249
|
+
}
|
|
2250
|
+
if (price.Limit !== void 0 && price.Limit < 50) {
|
|
2251
|
+
errors.push(
|
|
2252
|
+
`S\u1ED1 l\u01B0\u1EE3ng l\u01B0\u1EE3t nh\u1EA5n (Price.Limit) t\u1ED1i thi\u1EC3u l\xE0 50 l\u01B0\u1EE3t/ng\xE0y (minCTA = 50). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}.`
|
|
2253
|
+
);
|
|
2254
|
+
} else if (price.Limit !== void 0 && price.Limit > 5e3) {
|
|
2255
|
+
warnings.push(
|
|
2256
|
+
`\u26A0\uFE0F C\u1EA2NH B\xC1O B\u1EAAY NG\xC2N S\xC1CH ZALO ADS: Khi Price.Type = 2 (CPC), tr\u01B0\u1EDDng Price.Limit mang \xFD ngh\u0129a l\xE0 S\u1ED0 L\u01AF\u1EE2NG L\u01AF\u1EE2T NH\u1EA4N (Clicks count), KH\xD4NG PH\u1EA2I S\u1ED0 TI\u1EC0N VN\u0110. B\u1EA1n \u0111ang truy\u1EC1n Limit = ${price.Limit} l\u01B0\u1EE3t nh\u1EA5n, c\xF3 th\u1EC3 khi\u1EBFn T\u1ED5ng chi ph\xED d\u1EF1 ki\u1EBFn t\u0103ng v\u1ECDt l\xEAn h\xE0ng tr\u0103m tri\u1EC7u VN\u0110.`
|
|
2257
|
+
);
|
|
2258
|
+
}
|
|
2259
|
+
} else if (price.Type === 5) {
|
|
2260
|
+
if (price.SpendingMethod === 1) {
|
|
2261
|
+
if (price.Bid !== void 0 && price.Bid !== 0) {
|
|
2262
|
+
errors.push(
|
|
2263
|
+
"Khi ch\u1ECDn 'T\u1ED5ng ng\xE2n s\xE1ch qu\u1EA3ng c\xE1o' cho L\u01B0\u1EE3t quan t\xE2m (SpendingMethod = 1), 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)."
|
|
2264
|
+
);
|
|
2265
|
+
}
|
|
2266
|
+
if (price.Limit !== void 0 && price.Limit < 5e5) {
|
|
2267
|
+
errors.push(
|
|
2268
|
+
`Ng\xE2n s\xE1ch t\u1ED1i thi\u1EC3u cho L\u01B0\u1EE3t quan t\xE2m theo T\u1ED5ng ng\xE2n s\xE1ch l\xE0 500,000 VN\u0110 / ng\xE0y (Price.Limit >= 500000). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}\u0111.`
|
|
2269
|
+
);
|
|
2270
|
+
}
|
|
2271
|
+
} else if (price.SpendingMethod === 0) {
|
|
2272
|
+
if (price.Bid !== void 0 && price.Bid < 1e4) {
|
|
2273
|
+
errors.push(
|
|
2274
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i L\u01B0\u1EE3t quan t\xE2m (Price.Bid) t\u1ED1i thi\u1EC3u l\xE0 10,000 VN\u0110 / l\u01B0\u1EE3t quan t\xE2m (s\xE0n h\u1EC7 th\u1ED1ng cho OA Follow). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2275
|
+
);
|
|
2276
|
+
}
|
|
2277
|
+
if (price.Limit !== void 0 && price.Limit < 100) {
|
|
2278
|
+
errors.push(
|
|
2279
|
+
`S\u1ED1 l\u01B0\u1EE3ng L\u01B0\u1EE3t quan t\xE2m (Price.Limit) t\u1ED1i thi\u1EC3u l\xE0 100 l\u01B0\u1EE3t (minCTA = 100). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}.`
|
|
2280
|
+
);
|
|
2281
|
+
} else if (price.Limit !== void 0 && price.Limit > 5e3) {
|
|
2282
|
+
warnings.push(
|
|
2283
|
+
`\u26A0\uFE0F C\u1EA2NH B\xC1O B\u1EAAY NG\xC2N S\xC1CH ZALO ADS: Khi ch\u1ECDn 'T\u1EF1 \u0111\u1EB7t gi\xE1' cho L\u01B0\u1EE3t quan t\xE2m (SpendingMethod = 0), tr\u01B0\u1EDDng Price.Limit l\xE0 S\u1ED0 L\u01AF\u1EE2NG L\u01AF\u1EE2T QUAN T\xC2M (t\u1ED1i thi\u1EC3u 100 l\u01B0\u1EE3t), KH\xD4NG PH\u1EA2I S\u1ED0 TI\u1EC0N VN\u0110.`
|
|
2284
|
+
);
|
|
2285
|
+
}
|
|
2286
|
+
} else if (price.SpendingMethod !== void 0) {
|
|
2287
|
+
errors.push(
|
|
2288
|
+
"C\xE1ch \u0111\u1EB7t gi\xE1 SpendingMethod cho L\u01B0\u1EE3t quan t\xE2m 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)."
|
|
2289
|
+
);
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
} else if (payload.Type === VALID_AD_TYPES.MESSAGE) {
|
|
2293
|
+
if (price.Type !== 2 && price.Type !== 5) {
|
|
2294
|
+
errors.push(
|
|
2295
|
+
"\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)."
|
|
2296
|
+
);
|
|
2297
|
+
}
|
|
2298
|
+
if (price.Type === 5) {
|
|
2299
|
+
if (price.SpendingMethod !== 1) {
|
|
2300
|
+
errors.push(
|
|
2301
|
+
"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)."
|
|
2302
|
+
);
|
|
2303
|
+
}
|
|
2304
|
+
if (price.Bid !== void 0 && price.Bid !== 0) {
|
|
2305
|
+
errors.push(
|
|
2306
|
+
"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)."
|
|
2307
|
+
);
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 6e5) {
|
|
2311
|
+
errors.push(
|
|
2312
|
+
"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."
|
|
2313
|
+
);
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
if (payload.Settings && payload.Settings.DeliveryType !== void 0) {
|
|
2317
|
+
const deliveryType = payload.Settings.DeliveryType;
|
|
2318
|
+
if (deliveryType !== 0 && deliveryType !== 1) {
|
|
2319
|
+
errors.push("C\xE0i \u0111\u1EB7t ph\xE2n ph\u1ED1i Settings.DeliveryType ch\u1EC9 ch\u1EA5p nh\u1EADn 0 (Ti\xEAu chu\u1EA9n - Standard) ho\u1EB7c 1 (T\u0103ng t\u1ED1c - SpeedUp).");
|
|
2320
|
+
}
|
|
2321
|
+
if ((price.LimitType === 2 || price.LimitType === 0) && deliveryType === 1) {
|
|
2322
|
+
warnings.push("Ph\xE2n ph\u1ED1i T\u0103ng t\u1ED1c (DeliveryType = 1) ch\u1EC9 c\xF3 hi\u1EC7u l\u1EF1c khi \u0111\u1EB7t Ng\xE2n s\xE1ch to\xE0n l\u1ECBch ch\u1EA1y (Price.LimitType = 1).");
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
if (price.SpendingMethod === 0 && price.Limit !== void 0 && price.Limit > 0 && price.Limit < 50) {
|
|
2326
|
+
warnings.push("S\u1ED1 l\u01B0\u1EE3ng l\u01B0\u1EE3t t\u01B0\u01A1ng t\xE1c \u0111\u1EB7t m\u1ED7i ng\xE0y t\u1ED1i thi\u1EC3u l\xE0 50 l\u01B0\u1EE3t.");
|
|
2327
|
+
}
|
|
2313
2328
|
}
|
|
2314
|
-
|
|
2315
|
-
|
|
2329
|
+
const targeting = payload.Settings?.Targeting;
|
|
2330
|
+
if (targeting) {
|
|
2331
|
+
const newAges = targeting.NewAgeRanges;
|
|
2332
|
+
const oldAges = targeting.AgeRanges;
|
|
2333
|
+
if (newAges && newAges.length > 0) {
|
|
2334
|
+
const validNewAgeKeys = ["13_17", "18_24", "25_34", "35_44", "45_54", "55_64", "65_plus", "10283", "10284", "10285", "10286", "10287", "10288"];
|
|
2335
|
+
const invalid = newAges.filter((a) => !validNewAgeKeys.includes(String(a)));
|
|
2336
|
+
if (invalid.length > 0) {
|
|
2337
|
+
warnings.push(`M\xE3 NewAgeRanges kh\xF4ng ph\u1ED5 bi\u1EBFn: ${invalid.join(", ")}.`);
|
|
2338
|
+
}
|
|
2339
|
+
} else if (oldAges && oldAges.length > 0) {
|
|
2340
|
+
const validAges = Object.values(ZaloAdsAgeRangeId);
|
|
2341
|
+
const invalidAges = oldAges.filter((a) => !validAges.includes(a));
|
|
2342
|
+
if (invalidAges.length > 0) {
|
|
2343
|
+
errors.push(`M\xE3 kho\u1EA3ng tu\u1ED5i kh\xF4ng h\u1EE3p l\u1EC7: ${invalidAges.join(", ")}. H\u1EE3p l\u1EC7: ${validAges.join(", ")}.`);
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
const osList = targeting.Os || targeting.OsTypes;
|
|
2347
|
+
if (osList && osList.length > 0) {
|
|
2348
|
+
const validOs = [0, 1, 2, 3];
|
|
2349
|
+
const invalidOs = osList.filter((os) => !validOs.includes(Number(os)));
|
|
2350
|
+
if (invalidOs.length > 0) {
|
|
2351
|
+
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).`);
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
const deliveryType = payload.Settings?.DeliveryType;
|
|
2355
|
+
if (deliveryType !== void 0 && deliveryType !== ZaloAdsDeliveryType.STANDARD && deliveryType !== ZaloAdsDeliveryType.SPEED_UP) {
|
|
2356
|
+
warnings.push(
|
|
2357
|
+
"DeliveryType kh\xF4ng h\u1EE3p l\u1EC7. Gi\xE1 tr\u1ECB chu\u1EA9n: 0 (Ti\xEAu chu\u1EA9n / Standard) ho\u1EB7c 1 (T\u0103ng t\u1ED1c / SpeedUp)."
|
|
2358
|
+
);
|
|
2359
|
+
}
|
|
2360
|
+
const location = targeting.Location;
|
|
2361
|
+
if (location) {
|
|
2362
|
+
const container = location.WardTargeting || location.DistrictTargeting;
|
|
2363
|
+
if (container && Array.isArray(container.Includes)) {
|
|
2364
|
+
const validRegions = [1, 2, 3];
|
|
2365
|
+
for (const item of container.Includes) {
|
|
2366
|
+
if (!validRegions.includes(Number(item.Id))) {
|
|
2367
|
+
warnings.push(
|
|
2368
|
+
`M\xE3 v\xF9ng mi\u1EC1n (Id: ${item.Id}) kh\xF4ng h\u1EE3p l\u1EC7. C\xE1c m\xE3 v\xF9ng chu\u1EA9n: 1 (Mi\u1EC1n B\u1EAFc), 2 (Mi\u1EC1n Trung), 3 (Mi\u1EC1n Nam).`
|
|
2369
|
+
);
|
|
2370
|
+
}
|
|
2371
|
+
if (item.Provinces && !Array.isArray(item.Provinces)) {
|
|
2372
|
+
warnings.push(`Tr\u01B0\u1EDDng 'Provinces' trong v\xF9ng mi\u1EC1n Id=${item.Id} ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng t\u1EC9nh/th\xE0nh.`);
|
|
2373
|
+
} else if (Array.isArray(item.Provinces)) {
|
|
2374
|
+
for (const prov of item.Provinces) {
|
|
2375
|
+
if (!prov.Id || typeof prov.Id !== "string") {
|
|
2376
|
+
warnings.push(
|
|
2377
|
+
`M\xE3 t\u1EC9nh 'Id' (${JSON.stringify(prov)}) trong v\xF9ng mi\u1EC1n ${item.Id} ph\u1EA3i l\xE0 chu\u1ED7i h\u1EE3p l\u1EC7 (v\xED d\u1EE5: 'VN44', 'VN20').`
|
|
2378
|
+
);
|
|
2379
|
+
} else {
|
|
2380
|
+
const mergeInfo = ZALO_PROVINCE_MERGE_MAPPING[prov.Id];
|
|
2381
|
+
if (mergeInfo) {
|
|
2382
|
+
errors.push(
|
|
2383
|
+
`M\xE3 t\u1EC9nh '${prov.Id}' (${mergeInfo.name}) \u0111\xE3 \u0111\u01B0\u1EE3c Zalo Ads g\u1ED9p/s\xE1p nh\u1EADp v\xE0o c\u1EE5m m\xE3 '${mergeInfo.newCode}'. Vui l\xF2ng s\u1EED d\u1EE5ng m\xE3 c\u1EE5m '${mergeInfo.newCode}' trong WardTargeting, n\u1EBFu kh\xF4ng giao di\u1EC7n Zalo Ads Web s\u1EBD b\xE1o l\u1ED7i \u0111\u1ECF 'Invalid wards params'.`
|
|
2384
|
+
);
|
|
2385
|
+
} else {
|
|
2386
|
+
const validNewRegionProvs = ZALO_NEW_REGION_PROVINCE_CODES[Number(item.Id)] || [];
|
|
2387
|
+
if (!validNewRegionProvs.includes(prov.Id)) {
|
|
2388
|
+
const actualRegion = Object.keys(ZALO_NEW_REGION_PROVINCE_CODES).find((r) => ZALO_NEW_REGION_PROVINCE_CODES[Number(r)].includes(prov.Id));
|
|
2389
|
+
errors.push(
|
|
2390
|
+
`M\xE3 t\u1EC9nh '${prov.Id}' kh\xF4ng n\u1EB1m trong 34 C\u1EE5m T\u1EC9nh/Th\xE0nh m\u1EDBi c\u1EE7a V\xF9ng ${item.Id} tr\xEAn Zalo Ads (s\u1EBD g\xE2y l\u1ED7i 'Invalid wards params' tr\xEAn UI). ` + (actualRegion ? `M\xE3 n\xE0y thu\u1ED9c V\xF9ng ${actualRegion}. ` : "")
|
|
2391
|
+
);
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
if (prov.Districts && !Array.isArray(prov.Districts)) {
|
|
2396
|
+
warnings.push(`Tr\u01B0\u1EDDng 'Districts' c\u1EE7a t\u1EC9nh ${prov.Id} ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng (ho\u1EB7c [] khi ch\u1ECDn c\u1EA3 t\u1EC9nh).`);
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
2402
|
+
}
|
|
2316
2403
|
}
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2404
|
+
if (payload.UseConversion !== void 0) {
|
|
2405
|
+
const validUseConversions = Object.values(ZaloAdsUseConversion);
|
|
2406
|
+
if (!validUseConversions.includes(payload.UseConversion)) {
|
|
2407
|
+
warnings.push(
|
|
2408
|
+
`UseConversion (${payload.UseConversion}) kh\xF4ng n\u1EB1m trong danh m\u1EE5c chu\u1EA9n: 0 (NOT_USE), 1 (USE), 2 (LADI_PAGE), 3 (MINI_APP), -1 (USE_OFF), -2 (LADI_PAGE_OFF), -3 (MINI_APP_OFF).`
|
|
2409
|
+
);
|
|
2410
|
+
}
|
|
2411
|
+
if (payload.UseConversion === ZaloAdsUseConversion.USE && (!payload.ConversionId || payload.ConversionId <= 0)) {
|
|
2412
|
+
warnings.push(
|
|
2413
|
+
"Khi ch\u1ECDn UseConversion = 1 (Pixel c\u1EE7a t\xF4i), n\xEAn c\u1EA5u h\xECnh ConversionId h\u1EE3p l\u1EC7 t\u1EEB danh s\xE1ch GET /api/conversion/all \u0111\u1EC3 thu\u1EADt to\xE1n m\xE1y h\u1ECDc Zalo Ads t\u1ED1i \u01B0u t\u1EF7 l\u1EC7 chuy\u1EC3n \u0111\u1ED5i."
|
|
2414
|
+
);
|
|
2415
|
+
}
|
|
2320
2416
|
}
|
|
2321
|
-
|
|
2322
|
-
|
|
2417
|
+
if (payload.Type === VALID_AD_TYPES.FORM) {
|
|
2418
|
+
if (!payload.ZaloFormId || !payload.ZaloFormId.trim()) {
|
|
2419
|
+
errors.push("ZaloFormId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Form (Ad Type 18).");
|
|
2420
|
+
}
|
|
2421
|
+
} else if (payload.Type === VALID_AD_TYPES.MESSAGE) {
|
|
2422
|
+
if (!payload.Settings?.Image?.LogoUrl) {
|
|
2423
|
+
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).");
|
|
2424
|
+
}
|
|
2425
|
+
if (!payload.MiniPageId || payload.MiniPageId <= 0) {
|
|
2426
|
+
errors.push(
|
|
2427
|
+
"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.'."
|
|
2428
|
+
);
|
|
2429
|
+
}
|
|
2430
|
+
if (!payload.ZaloFlowId) {
|
|
2431
|
+
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.");
|
|
2432
|
+
}
|
|
2433
|
+
if (payload.Settings?.Image?.ExtraImgs && payload.Settings?.Image?.ExtraImgs.length > 0) {
|
|
2434
|
+
errors.push(
|
|
2435
|
+
"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'."
|
|
2436
|
+
);
|
|
2437
|
+
}
|
|
2438
|
+
} else if (payload.Type === VALID_AD_TYPES.COMMERCE) {
|
|
2439
|
+
if (!payload.MiniPageId || payload.MiniPageId <= 0) {
|
|
2440
|
+
errors.push("MiniPageId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Commerce (Ad Type 28, Template 1/2/3).");
|
|
2441
|
+
}
|
|
2442
|
+
} else if (payload.Type === VALID_AD_TYPES.VIDEO) {
|
|
2443
|
+
if (!payload.ZaloVideoId && !payload.Settings?.Image?.VideoUrl) {
|
|
2444
|
+
errors.push("ZaloVideoId ho\u1EB7c Settings.Image.VideoUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Video (Ad Type 11).");
|
|
2445
|
+
}
|
|
2446
|
+
if (payload.Settings?.Image?.VideoUrl && !payload.Settings.Image.VideoUrl.includes("zascdn.me")) {
|
|
2447
|
+
warnings.push("VideoUrl n\xEAn l\xE0 \u0111\u01B0\u1EDDng d\u1EABn CDN ch\xEDnh th\u1EE9c c\u1EE7a Zalo Ads (*.zascdn.me).");
|
|
2448
|
+
}
|
|
2449
|
+
} else if (payload.Type === VALID_AD_TYPES.ARTICLE) {
|
|
2450
|
+
if (!payload.ZaloFeedId && !payload.articleId) {
|
|
2451
|
+
errors.push("ZaloFeedId ho\u1EB7c articleId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o B\xE0i Vi\u1EBFt (Ad Type 3).");
|
|
2452
|
+
}
|
|
2323
2453
|
}
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2454
|
+
return {
|
|
2455
|
+
isValid: errors.length === 0,
|
|
2456
|
+
errors,
|
|
2457
|
+
warnings
|
|
2458
|
+
};
|
|
2459
|
+
}
|
|
2460
|
+
function validateRenameCampaignParams(params) {
|
|
2461
|
+
const errors = [];
|
|
2462
|
+
const warnings = [];
|
|
2463
|
+
const id = params.campid || params.campaignId;
|
|
2464
|
+
const name = params.newname || params.newName || params.name;
|
|
2465
|
+
if (!id || id <= 0) {
|
|
2466
|
+
errors.push("ID chi\u1EBFn d\u1ECBch (campid/campaignId) l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i > 0.");
|
|
2327
2467
|
}
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2468
|
+
if (!name || !name.trim()) {
|
|
2469
|
+
errors.push("T\xEAn m\u1EDBi c\u1EE7a chi\u1EBFn d\u1ECBch (newname/name) l\xE0 b\u1EAFt bu\u1ED9c v\xE0 kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
|
|
2470
|
+
} else if (name.length > 255) {
|
|
2471
|
+
errors.push(`T\xEAn chi\u1EBFn d\u1ECBch qu\xE1 d\xE0i (${name.length}/255 k\xFD t\u1EF1).`);
|
|
2331
2472
|
}
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2473
|
+
return {
|
|
2474
|
+
isValid: errors.length === 0,
|
|
2475
|
+
errors,
|
|
2476
|
+
warnings
|
|
2477
|
+
};
|
|
2478
|
+
}
|
|
2479
|
+
function validateChangeCampaignStatusParams(params) {
|
|
2480
|
+
const errors = [];
|
|
2481
|
+
const warnings = [];
|
|
2482
|
+
if (!params.campaignId || params.campaignId <= 0) {
|
|
2483
|
+
errors.push("campaignId l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i > 0.");
|
|
2335
2484
|
}
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
return this.getApiSpellCheckV2(...args);
|
|
2485
|
+
if (![0, 1, 2, -2].includes(params.status)) {
|
|
2486
|
+
errors.push(`status: ${params.status} kh\xF4ng h\u1EE3p l\u1EC7. C\xE1c tr\u1EA1ng th\xE1i h\u1EE3p l\u1EC7: 1 (B\u1EADt), 0 (T\u1EAFt), 2 (T\u1EA1m d\u1EEBng), -2 (X\xF3a).`);
|
|
2339
2487
|
}
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
createSpellCheckV3Job(request, options) {
|
|
2344
|
-
return this.client.requestJson(
|
|
2345
|
-
OP_ZaloAdsCreateSpellCheckV3Job,
|
|
2346
|
-
this.client.toTransportInput(OP_ZaloAdsCreateSpellCheckV3Job, request),
|
|
2347
|
-
options
|
|
2488
|
+
if (params.status === 2 && params.isDraft) {
|
|
2489
|
+
warnings.push(
|
|
2490
|
+
"Chi\u1EBFn d\u1ECBch nh\xE1p ch\u01B0a c\xF3 qu\u1EA3ng c\xE1o ho\u1EA1t \u0111\u1ED9ng khi g\u1ECDi status: 2 (T\u1EA1m d\u1EEBng) s\u1EBD b\u1ECB m\xE1y ch\u1EE7 n\xE9m l\u1ED7i HTTP 500 Internal Server Error. \u0110\u1EC3 d\u1ECDn d\u1EB9p h\xE3y d\xF9ng status: -2 (X\xF3a)."
|
|
2348
2491
|
);
|
|
2349
2492
|
}
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
* @param request Tiêu đề (title) và chú thích (caption) cần kiểm tra.
|
|
2363
|
-
* @param pollIntervalMs Chu kỳ polling kiểm tra trạng thái (mặc định: 600ms).
|
|
2364
|
-
* @param timeoutMs Thời gian chờ tối đa (mặc định: 15.000ms = 15 giây).
|
|
2365
|
-
*/
|
|
2366
|
-
async checkSpellV3AndWait(request, pollIntervalMs = 600, timeoutMs = 15e3, options) {
|
|
2367
|
-
const jobRes = await this.createSpellCheckV3Job(request, options);
|
|
2368
|
-
const jobId = jobRes?.data?.jobId;
|
|
2369
|
-
if (!jobId) {
|
|
2370
|
-
throw new Error(`[SpellCheckV3] Kh\xF4ng nh\u1EADn \u0111\u01B0\u1EE3c jobId t\u1EEB Zalo Ads (code: ${jobRes?.code})`);
|
|
2371
|
-
}
|
|
2372
|
-
const startTime = Date.now();
|
|
2373
|
-
while (Date.now() - startTime < timeoutMs) {
|
|
2374
|
-
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
2375
|
-
const res = await this.getSpellCheckV3Job({ jobId }, options);
|
|
2376
|
-
if (res?.data?.status === "COMPLETED") {
|
|
2377
|
-
return res;
|
|
2378
|
-
}
|
|
2379
|
-
}
|
|
2380
|
-
throw new Error(`[SpellCheckV3] Qu\xE1 th\u1EDDi gian ch\u1EDD (${timeoutMs}ms) cho t\xE1c v\u1EE5 ki\u1EC3m tra ch\xEDnh t\u1EA3 jobId: ${jobId}`);
|
|
2381
|
-
}
|
|
2382
|
-
/**
|
|
2383
|
-
* Nhân bản (sao chép / duplicate) một mẫu quảng cáo đã tồn tại trên Zalo Ads (POST /zaapi/DuplicateAd).
|
|
2384
|
-
* Giúp tạo nhanh một bản sao Ad mới trong cùng chiến dịch để thực hiện A/B testing.
|
|
2385
|
-
*/
|
|
2386
|
-
duplicateAd(request, options) {
|
|
2387
|
-
const payload = {
|
|
2388
|
-
adid: request.adid ?? request.adId
|
|
2389
|
-
};
|
|
2390
|
-
return this.client.requestFormUrlEncoded(
|
|
2391
|
-
OP_ZaloAdsDuplicateAd,
|
|
2392
|
-
this.client.toTransportInput(OP_ZaloAdsDuplicateAd, payload),
|
|
2393
|
-
options
|
|
2394
|
-
);
|
|
2493
|
+
return {
|
|
2494
|
+
isValid: errors.length === 0,
|
|
2495
|
+
errors,
|
|
2496
|
+
warnings
|
|
2497
|
+
};
|
|
2498
|
+
}
|
|
2499
|
+
function validateDuplicateAdParams(params) {
|
|
2500
|
+
const errors = [];
|
|
2501
|
+
const warnings = [];
|
|
2502
|
+
const id = params.adid || params.adId;
|
|
2503
|
+
if (!id || id <= 0) {
|
|
2504
|
+
errors.push("ID m\u1EABu qu\u1EA3ng c\xE1o g\u1ED1c c\u1EA7n nh\xE2n b\u1EA3n (adid/adId) l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i > 0.");
|
|
2395
2505
|
}
|
|
2506
|
+
return {
|
|
2507
|
+
isValid: errors.length === 0,
|
|
2508
|
+
errors,
|
|
2509
|
+
warnings
|
|
2510
|
+
};
|
|
2511
|
+
}
|
|
2512
|
+
var ZaloCampaignsValidator = {
|
|
2513
|
+
createCampaign: validateCreateCampaignPayload,
|
|
2514
|
+
updateAd: validateUpdateAdPayload,
|
|
2515
|
+
renameCampaign: validateRenameCampaignParams,
|
|
2516
|
+
changeStatus: validateChangeCampaignStatusParams,
|
|
2517
|
+
duplicateAd: validateDuplicateAdParams
|
|
2518
|
+
};
|
|
2519
|
+
|
|
2520
|
+
// src/services/campaigns.service.ts
|
|
2521
|
+
var OP_ZaloAdsUpdateVideoAd = {
|
|
2522
|
+
operationId: "ZaloAds_updateVideoAd",
|
|
2523
|
+
method: "POST",
|
|
2524
|
+
endpoint: "/zaapi/UpdateAd",
|
|
2525
|
+
baseUrl: "https://ads.zalo.me",
|
|
2526
|
+
binaryFields: [],
|
|
2527
|
+
pathFields: [],
|
|
2528
|
+
queryFields: [],
|
|
2529
|
+
headerFields: [],
|
|
2530
|
+
cookieFields: [],
|
|
2531
|
+
bodyFields: ["data", "est", "isBoostAd", "stt"]
|
|
2532
|
+
};
|
|
2533
|
+
var OP_ZaloAdsChangeCampaignStatus = {
|
|
2534
|
+
"operationId": "ZaloAds_changeCampaignStatus",
|
|
2535
|
+
"method": "POST",
|
|
2536
|
+
"endpoint": "/api/campaign/change-status",
|
|
2537
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2538
|
+
"binaryFields": [],
|
|
2539
|
+
"pathFields": [],
|
|
2540
|
+
"queryFields": [],
|
|
2541
|
+
"headerFields": [],
|
|
2542
|
+
"cookieFields": [],
|
|
2543
|
+
"bodyFields": [
|
|
2544
|
+
"status",
|
|
2545
|
+
"campaignId"
|
|
2546
|
+
]
|
|
2547
|
+
};
|
|
2548
|
+
var OP_ZaloAdsCreateEcommerceCampaign = {
|
|
2549
|
+
"operationId": "ZaloAds_createEcommerceCampaign",
|
|
2550
|
+
"method": "POST",
|
|
2551
|
+
"endpoint": "/zaapi/addNewCamp",
|
|
2552
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2553
|
+
"binaryFields": [],
|
|
2554
|
+
"pathFields": [],
|
|
2555
|
+
"queryFields": [],
|
|
2556
|
+
"headerFields": [],
|
|
2557
|
+
"cookieFields": [],
|
|
2558
|
+
"bodyFields": [
|
|
2559
|
+
"data"
|
|
2560
|
+
]
|
|
2561
|
+
};
|
|
2562
|
+
var OP_ZaloAdsCreateForm = {
|
|
2563
|
+
"operationId": "ZaloAds_createForm",
|
|
2564
|
+
"method": "POST",
|
|
2565
|
+
"endpoint": "/api/form/create",
|
|
2566
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2567
|
+
"binaryFields": [],
|
|
2568
|
+
"pathFields": [],
|
|
2569
|
+
"queryFields": [],
|
|
2570
|
+
"headerFields": [],
|
|
2571
|
+
"cookieFields": [],
|
|
2572
|
+
"bodyFields": [
|
|
2573
|
+
"data"
|
|
2574
|
+
]
|
|
2575
|
+
};
|
|
2576
|
+
var OP_ZaloAdsCreateFormCampaign = {
|
|
2577
|
+
"operationId": "ZaloAds_createFormCampaign",
|
|
2578
|
+
"method": "POST",
|
|
2579
|
+
"endpoint": "/zaapi/addNewCamp",
|
|
2580
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2581
|
+
"binaryFields": [],
|
|
2582
|
+
"pathFields": [],
|
|
2583
|
+
"queryFields": [],
|
|
2584
|
+
"headerFields": [],
|
|
2585
|
+
"cookieFields": [],
|
|
2586
|
+
"bodyFields": [
|
|
2587
|
+
"data"
|
|
2588
|
+
]
|
|
2589
|
+
};
|
|
2590
|
+
var OP_ZaloAdsCreateMessageCampaign = {
|
|
2591
|
+
"operationId": "ZaloAds_createMessageCampaign",
|
|
2592
|
+
"method": "POST",
|
|
2593
|
+
"endpoint": "/zaapi/addNewCamp",
|
|
2594
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2595
|
+
"binaryFields": [],
|
|
2596
|
+
"pathFields": [],
|
|
2597
|
+
"queryFields": [],
|
|
2598
|
+
"headerFields": [],
|
|
2599
|
+
"cookieFields": [],
|
|
2600
|
+
"bodyFields": [
|
|
2601
|
+
"data"
|
|
2602
|
+
]
|
|
2603
|
+
};
|
|
2604
|
+
var OP_ZaloAdsCreateOfficialAccountCampaign = {
|
|
2605
|
+
"operationId": "ZaloAds_createOfficialAccountCampaign",
|
|
2606
|
+
"method": "POST",
|
|
2607
|
+
"endpoint": "/zaapi/addNewCamp",
|
|
2608
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2609
|
+
"binaryFields": [],
|
|
2610
|
+
"pathFields": [],
|
|
2611
|
+
"queryFields": [],
|
|
2612
|
+
"headerFields": [],
|
|
2613
|
+
"cookieFields": [],
|
|
2614
|
+
"bodyFields": [
|
|
2615
|
+
"data"
|
|
2616
|
+
]
|
|
2617
|
+
};
|
|
2618
|
+
var OP_ZaloAdsCreatePostCampaign = {
|
|
2619
|
+
"operationId": "ZaloAds_createPostCampaign",
|
|
2620
|
+
"method": "POST",
|
|
2621
|
+
"endpoint": "/zaapi/addNewCamp",
|
|
2622
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2623
|
+
"binaryFields": [],
|
|
2624
|
+
"pathFields": [],
|
|
2625
|
+
"queryFields": [],
|
|
2626
|
+
"headerFields": [],
|
|
2627
|
+
"cookieFields": [],
|
|
2628
|
+
"bodyFields": [
|
|
2629
|
+
"data"
|
|
2630
|
+
]
|
|
2631
|
+
};
|
|
2632
|
+
var OP_ZaloAdsGetAdById = {
|
|
2633
|
+
"operationId": "ZaloAds_getAdById",
|
|
2634
|
+
"method": "GET",
|
|
2635
|
+
"endpoint": "/zaapi/getAdFromAdId",
|
|
2636
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2637
|
+
"binaryFields": [],
|
|
2638
|
+
"pathFields": [],
|
|
2639
|
+
"queryFields": [
|
|
2640
|
+
"adId",
|
|
2641
|
+
"v",
|
|
2642
|
+
"newWard"
|
|
2643
|
+
],
|
|
2644
|
+
"headerFields": [],
|
|
2645
|
+
"cookieFields": [],
|
|
2646
|
+
"bodyFields": []
|
|
2647
|
+
};
|
|
2648
|
+
var OP_ZaloAdsGetAdChangeLog = {
|
|
2649
|
+
"operationId": "ZaloAds_getAdChangeLog",
|
|
2650
|
+
"method": "GET",
|
|
2651
|
+
"endpoint": "/api/ad/log/{adId}",
|
|
2652
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2653
|
+
"binaryFields": [],
|
|
2654
|
+
"pathFields": [
|
|
2655
|
+
"adId"
|
|
2656
|
+
],
|
|
2657
|
+
"queryFields": [
|
|
2658
|
+
"type"
|
|
2659
|
+
],
|
|
2660
|
+
"headerFields": [],
|
|
2661
|
+
"cookieFields": [],
|
|
2662
|
+
"bodyFields": []
|
|
2663
|
+
};
|
|
2664
|
+
var OP_ZaloAdsGetApiPlaceGetalldistricts = {
|
|
2665
|
+
"operationId": "ZaloAds_getApiPlaceGetalldistricts",
|
|
2666
|
+
"method": "GET",
|
|
2667
|
+
"endpoint": "/api/place/getAllDistricts",
|
|
2668
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2669
|
+
"binaryFields": [],
|
|
2670
|
+
"pathFields": [],
|
|
2671
|
+
"queryFields": [],
|
|
2672
|
+
"headerFields": [],
|
|
2673
|
+
"cookieFields": [],
|
|
2674
|
+
"bodyFields": []
|
|
2675
|
+
};
|
|
2676
|
+
var OP_ZaloAdsGetApiSpellCheckV2 = {
|
|
2677
|
+
"operationId": "ZaloAds_getApiSpellCheckV2",
|
|
2678
|
+
"method": "GET",
|
|
2679
|
+
"endpoint": "/api/spell-check/v2",
|
|
2680
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2681
|
+
"binaryFields": [],
|
|
2682
|
+
"pathFields": [],
|
|
2683
|
+
"queryFields": [
|
|
2684
|
+
"text"
|
|
2685
|
+
],
|
|
2686
|
+
"headerFields": [],
|
|
2687
|
+
"cookieFields": [],
|
|
2688
|
+
"bodyFields": []
|
|
2689
|
+
};
|
|
2690
|
+
var OP_ZaloAdsGetZaapiCheckcamphasmanyads = {
|
|
2691
|
+
"operationId": "ZaloAds_getZaapiCheckcamphasmanyads",
|
|
2692
|
+
"method": "GET",
|
|
2693
|
+
"endpoint": "/zaapi/checkCampHasManyAds",
|
|
2694
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2695
|
+
"binaryFields": [],
|
|
2696
|
+
"pathFields": [],
|
|
2697
|
+
"queryFields": [
|
|
2698
|
+
"campaignId",
|
|
2699
|
+
"campId"
|
|
2700
|
+
],
|
|
2701
|
+
"headerFields": [],
|
|
2702
|
+
"cookieFields": [],
|
|
2703
|
+
"bodyFields": []
|
|
2704
|
+
};
|
|
2705
|
+
var OP_ZaloAdsGetZaapiGetadsfromcampaignid = {
|
|
2706
|
+
"operationId": "ZaloAds_getZaapiGetadsfromcampaignid",
|
|
2707
|
+
"method": "GET",
|
|
2708
|
+
"endpoint": "/zaapi/getAdsFromCampaignId",
|
|
2709
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2710
|
+
"binaryFields": [],
|
|
2711
|
+
"pathFields": [],
|
|
2712
|
+
"queryFields": [
|
|
2713
|
+
"campaignId",
|
|
2714
|
+
"campId",
|
|
2715
|
+
"dataType",
|
|
2716
|
+
"v"
|
|
2717
|
+
],
|
|
2718
|
+
"headerFields": [],
|
|
2719
|
+
"cookieFields": [],
|
|
2720
|
+
"bodyFields": []
|
|
2721
|
+
};
|
|
2722
|
+
var OP_ZaloAdsGetZaapiGetallpages = {
|
|
2723
|
+
"operationId": "ZaloAds_getZaapiGetallpages",
|
|
2724
|
+
"method": "GET",
|
|
2725
|
+
"endpoint": "/zaapi/getAllPages",
|
|
2726
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2727
|
+
"binaryFields": [],
|
|
2728
|
+
"pathFields": [],
|
|
2729
|
+
"queryFields": [],
|
|
2730
|
+
"headerFields": [],
|
|
2731
|
+
"cookieFields": [],
|
|
2732
|
+
"bodyFields": []
|
|
2733
|
+
};
|
|
2734
|
+
var OP_ZaloAdsGetZaapiGetownedarticles = {
|
|
2735
|
+
"operationId": "ZaloAds_getZaapiGetownedarticles",
|
|
2736
|
+
"method": "GET",
|
|
2737
|
+
"endpoint": "/zaapi/getOwnedArticles",
|
|
2738
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2739
|
+
"binaryFields": [],
|
|
2740
|
+
"pathFields": [],
|
|
2741
|
+
"queryFields": [
|
|
2742
|
+
"pageId"
|
|
2743
|
+
],
|
|
2744
|
+
"headerFields": [],
|
|
2745
|
+
"cookieFields": [],
|
|
2746
|
+
"bodyFields": []
|
|
2747
|
+
};
|
|
2748
|
+
var OP_ZaloAdsGetZaapiGetownedpages = {
|
|
2749
|
+
"operationId": "ZaloAds_getZaapiGetownedpages",
|
|
2750
|
+
"method": "GET",
|
|
2751
|
+
"endpoint": "/zaapi/getOwnedPages",
|
|
2752
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2753
|
+
"binaryFields": [],
|
|
2754
|
+
"pathFields": [],
|
|
2755
|
+
"queryFields": [],
|
|
2756
|
+
"headerFields": [],
|
|
2757
|
+
"cookieFields": [],
|
|
2758
|
+
"bodyFields": []
|
|
2759
|
+
};
|
|
2760
|
+
var OP_ZaloAdsListFormsByOfficialAccount = {
|
|
2761
|
+
"operationId": "ZaloAds_listFormsByOfficialAccount",
|
|
2762
|
+
"method": "GET",
|
|
2763
|
+
"endpoint": "/api/form/getByOaId",
|
|
2764
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2765
|
+
"binaryFields": [],
|
|
2766
|
+
"pathFields": [],
|
|
2767
|
+
"queryFields": [
|
|
2768
|
+
"oaId",
|
|
2769
|
+
"isAll"
|
|
2770
|
+
],
|
|
2771
|
+
"headerFields": [],
|
|
2772
|
+
"cookieFields": [],
|
|
2773
|
+
"bodyFields": []
|
|
2774
|
+
};
|
|
2775
|
+
var OP_ZaloAdsListMiniPagesByTemplate = {
|
|
2776
|
+
"operationId": "ZaloAds_listMiniPagesByTemplate",
|
|
2777
|
+
"method": "GET",
|
|
2778
|
+
"endpoint": "/api/mini-pages",
|
|
2779
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2780
|
+
"binaryFields": [],
|
|
2781
|
+
"pathFields": [],
|
|
2782
|
+
"queryFields": [
|
|
2783
|
+
"templateIds"
|
|
2784
|
+
],
|
|
2785
|
+
"headerFields": [],
|
|
2786
|
+
"cookieFields": [],
|
|
2787
|
+
"bodyFields": []
|
|
2788
|
+
};
|
|
2789
|
+
var OP_ZaloAdsPostZaapiDeletead = {
|
|
2790
|
+
"operationId": "ZaloAds_postZaapiDeletead",
|
|
2791
|
+
"method": "POST",
|
|
2792
|
+
"endpoint": "/zaapi/deleteAd",
|
|
2793
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2794
|
+
"binaryFields": [],
|
|
2795
|
+
"pathFields": [],
|
|
2796
|
+
"queryFields": [
|
|
2797
|
+
"adId"
|
|
2798
|
+
],
|
|
2799
|
+
"headerFields": [],
|
|
2800
|
+
"cookieFields": [],
|
|
2801
|
+
"bodyFields": [
|
|
2802
|
+
"adId"
|
|
2803
|
+
]
|
|
2804
|
+
};
|
|
2805
|
+
var OP_ZaloAdsRenameCampaign = {
|
|
2806
|
+
"operationId": "ZaloAds_renameCampaign",
|
|
2807
|
+
"method": "POST",
|
|
2808
|
+
"endpoint": "/api/campaign/change-name",
|
|
2809
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2810
|
+
"binaryFields": [],
|
|
2811
|
+
"pathFields": [],
|
|
2812
|
+
"queryFields": [],
|
|
2813
|
+
"headerFields": [],
|
|
2814
|
+
"cookieFields": [],
|
|
2815
|
+
"bodyFields": [
|
|
2816
|
+
"campid",
|
|
2817
|
+
"newname"
|
|
2818
|
+
]
|
|
2819
|
+
};
|
|
2820
|
+
var OP_ZaloAdsUpdateEcommerceAd = {
|
|
2821
|
+
"operationId": "ZaloAds_updateEcommerceAd",
|
|
2822
|
+
"method": "POST",
|
|
2823
|
+
"endpoint": "/zaapi/UpdateAd",
|
|
2824
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2825
|
+
"binaryFields": [],
|
|
2826
|
+
"pathFields": [],
|
|
2827
|
+
"queryFields": [],
|
|
2828
|
+
"headerFields": [],
|
|
2829
|
+
"cookieFields": [],
|
|
2830
|
+
"bodyFields": [
|
|
2831
|
+
"est",
|
|
2832
|
+
"stt",
|
|
2833
|
+
"data",
|
|
2834
|
+
"isBoostAd"
|
|
2835
|
+
]
|
|
2396
2836
|
};
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
"
|
|
2401
|
-
"method": "GET",
|
|
2402
|
-
"endpoint": "/api/whoami",
|
|
2837
|
+
var OP_ZaloAdsUpdateFormAd = {
|
|
2838
|
+
"operationId": "ZaloAds_updateFormAd",
|
|
2839
|
+
"method": "POST",
|
|
2840
|
+
"endpoint": "/zaapi/UpdateAd",
|
|
2403
2841
|
"baseUrl": "https://ads.zalo.me",
|
|
2404
2842
|
"binaryFields": [],
|
|
2405
2843
|
"pathFields": [],
|
|
2406
2844
|
"queryFields": [],
|
|
2407
2845
|
"headerFields": [],
|
|
2408
2846
|
"cookieFields": [],
|
|
2409
|
-
"bodyFields": [
|
|
2847
|
+
"bodyFields": [
|
|
2848
|
+
"est",
|
|
2849
|
+
"stt",
|
|
2850
|
+
"data",
|
|
2851
|
+
"isBoostAd"
|
|
2852
|
+
]
|
|
2410
2853
|
};
|
|
2411
|
-
var
|
|
2412
|
-
"operationId": "
|
|
2413
|
-
"method": "
|
|
2414
|
-
"endpoint": "/
|
|
2854
|
+
var OP_ZaloAdsUpdateMessageAd = {
|
|
2855
|
+
"operationId": "ZaloAds_updateMessageAd",
|
|
2856
|
+
"method": "POST",
|
|
2857
|
+
"endpoint": "/zaapi/UpdateAd",
|
|
2415
2858
|
"baseUrl": "https://ads.zalo.me",
|
|
2416
2859
|
"binaryFields": [],
|
|
2417
2860
|
"pathFields": [],
|
|
2418
|
-
"queryFields": [
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2861
|
+
"queryFields": [],
|
|
2862
|
+
"headerFields": [],
|
|
2863
|
+
"cookieFields": [],
|
|
2864
|
+
"bodyFields": [
|
|
2865
|
+
"est",
|
|
2866
|
+
"stt",
|
|
2867
|
+
"data",
|
|
2868
|
+
"isBoostAd"
|
|
2869
|
+
]
|
|
2870
|
+
};
|
|
2871
|
+
var OP_ZaloAdsUpdateNewAds = {
|
|
2872
|
+
"operationId": "ZaloAds_UpdateNewAds",
|
|
2873
|
+
"method": "POST",
|
|
2874
|
+
"endpoint": "/zaapi/UploadCrop",
|
|
2875
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2876
|
+
"binaryFields": [
|
|
2877
|
+
"File"
|
|
2422
2878
|
],
|
|
2879
|
+
"pathFields": [],
|
|
2880
|
+
"queryFields": [],
|
|
2423
2881
|
"headerFields": [],
|
|
2424
2882
|
"cookieFields": [],
|
|
2425
|
-
"bodyFields": [
|
|
2883
|
+
"bodyFields": [
|
|
2884
|
+
"File",
|
|
2885
|
+
"x",
|
|
2886
|
+
"y",
|
|
2887
|
+
"width",
|
|
2888
|
+
"height",
|
|
2889
|
+
"scale"
|
|
2890
|
+
]
|
|
2426
2891
|
};
|
|
2427
|
-
var
|
|
2428
|
-
"operationId": "
|
|
2429
|
-
"method": "
|
|
2430
|
-
"endpoint": "/
|
|
2892
|
+
var OP_ZaloAdsUpdateOfficialAccountAd = {
|
|
2893
|
+
"operationId": "ZaloAds_updateOfficialAccountAd",
|
|
2894
|
+
"method": "POST",
|
|
2895
|
+
"endpoint": "/zaapi/UpdateAd",
|
|
2431
2896
|
"baseUrl": "https://ads.zalo.me",
|
|
2432
2897
|
"binaryFields": [],
|
|
2433
2898
|
"pathFields": [],
|
|
2434
|
-
"queryFields": [
|
|
2435
|
-
"isShowAll"
|
|
2436
|
-
],
|
|
2899
|
+
"queryFields": [],
|
|
2437
2900
|
"headerFields": [],
|
|
2438
2901
|
"cookieFields": [],
|
|
2439
|
-
"bodyFields": [
|
|
2902
|
+
"bodyFields": [
|
|
2903
|
+
"est",
|
|
2904
|
+
"stt",
|
|
2905
|
+
"data",
|
|
2906
|
+
"isBoostAd"
|
|
2907
|
+
]
|
|
2440
2908
|
};
|
|
2441
|
-
var
|
|
2442
|
-
"operationId": "
|
|
2443
|
-
"method": "
|
|
2444
|
-
"endpoint": "/
|
|
2909
|
+
var OP_ZaloAdsUpdatePostAd = {
|
|
2910
|
+
"operationId": "ZaloAds_updatePostAd",
|
|
2911
|
+
"method": "POST",
|
|
2912
|
+
"endpoint": "/zaapi/UpdateAd",
|
|
2445
2913
|
"baseUrl": "https://ads.zalo.me",
|
|
2446
2914
|
"binaryFields": [],
|
|
2447
2915
|
"pathFields": [],
|
|
2448
2916
|
"queryFields": [],
|
|
2449
2917
|
"headerFields": [],
|
|
2450
2918
|
"cookieFields": [],
|
|
2451
|
-
"bodyFields": [
|
|
2919
|
+
"bodyFields": [
|
|
2920
|
+
"est",
|
|
2921
|
+
"stt",
|
|
2922
|
+
"data",
|
|
2923
|
+
"isBoostAd"
|
|
2924
|
+
]
|
|
2452
2925
|
};
|
|
2453
|
-
var
|
|
2454
|
-
"operationId": "
|
|
2455
|
-
"method": "
|
|
2456
|
-
"endpoint": "/
|
|
2926
|
+
var OP_ZaloAdsCreateWebsiteCampaign = {
|
|
2927
|
+
"operationId": "ZaloAds_createWebsiteCampaign",
|
|
2928
|
+
"method": "POST",
|
|
2929
|
+
"endpoint": "/zaapi/addNewCamp",
|
|
2457
2930
|
"baseUrl": "https://ads.zalo.me",
|
|
2458
2931
|
"binaryFields": [],
|
|
2459
2932
|
"pathFields": [],
|
|
2460
|
-
"queryFields": [
|
|
2461
|
-
"limit",
|
|
2462
|
-
"offset",
|
|
2463
|
-
"joinDateAsc"
|
|
2464
|
-
],
|
|
2933
|
+
"queryFields": [],
|
|
2465
2934
|
"headerFields": [],
|
|
2466
2935
|
"cookieFields": [],
|
|
2467
|
-
"bodyFields": [
|
|
2936
|
+
"bodyFields": [
|
|
2937
|
+
"data"
|
|
2938
|
+
]
|
|
2468
2939
|
};
|
|
2469
|
-
var
|
|
2470
|
-
"operationId": "
|
|
2471
|
-
"method": "
|
|
2472
|
-
"endpoint": "/
|
|
2940
|
+
var OP_ZaloAdsUpdateWebsiteAd = {
|
|
2941
|
+
"operationId": "ZaloAds_updateWebsiteAd",
|
|
2942
|
+
"method": "POST",
|
|
2943
|
+
"endpoint": "/zaapi/UpdateAd",
|
|
2473
2944
|
"baseUrl": "https://ads.zalo.me",
|
|
2474
2945
|
"binaryFields": [],
|
|
2475
2946
|
"pathFields": [],
|
|
2476
2947
|
"queryFields": [],
|
|
2477
2948
|
"headerFields": [],
|
|
2478
2949
|
"cookieFields": [],
|
|
2479
|
-
"bodyFields": [
|
|
2950
|
+
"bodyFields": [
|
|
2951
|
+
"est",
|
|
2952
|
+
"stt",
|
|
2953
|
+
"data",
|
|
2954
|
+
"isBoostAd"
|
|
2955
|
+
]
|
|
2480
2956
|
};
|
|
2481
|
-
var
|
|
2482
|
-
"operationId": "
|
|
2483
|
-
"method": "
|
|
2484
|
-
"endpoint": "/
|
|
2957
|
+
var OP_ZaloAdsCreateDisplayCampaign = {
|
|
2958
|
+
"operationId": "ZaloAds_createDisplayCampaign",
|
|
2959
|
+
"method": "POST",
|
|
2960
|
+
"endpoint": "/zaapi/addNewCamp",
|
|
2485
2961
|
"baseUrl": "https://ads.zalo.me",
|
|
2486
2962
|
"binaryFields": [],
|
|
2487
2963
|
"pathFields": [],
|
|
2488
2964
|
"queryFields": [],
|
|
2489
2965
|
"headerFields": [],
|
|
2490
2966
|
"cookieFields": [],
|
|
2491
|
-
"bodyFields": [
|
|
2967
|
+
"bodyFields": [
|
|
2968
|
+
"data"
|
|
2969
|
+
]
|
|
2492
2970
|
};
|
|
2493
|
-
var
|
|
2971
|
+
var OP_ZaloAdsUpdateDisplayAd = {
|
|
2972
|
+
"operationId": "ZaloAds_updateDisplayAd",
|
|
2973
|
+
"method": "POST",
|
|
2974
|
+
"endpoint": "/zaapi/UpdateAd",
|
|
2975
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2976
|
+
"binaryFields": [],
|
|
2977
|
+
"pathFields": [],
|
|
2978
|
+
"queryFields": [],
|
|
2979
|
+
"headerFields": [],
|
|
2980
|
+
"cookieFields": [],
|
|
2981
|
+
"bodyFields": [
|
|
2982
|
+
"est",
|
|
2983
|
+
"stt",
|
|
2984
|
+
"data",
|
|
2985
|
+
"isBoostAd"
|
|
2986
|
+
]
|
|
2987
|
+
};
|
|
2988
|
+
var OP_ZaloAdsCreateVideoCampaign = {
|
|
2989
|
+
"operationId": "ZaloAds_createVideoCampaign",
|
|
2990
|
+
"method": "POST",
|
|
2991
|
+
"endpoint": "/zaapi/addNewCamp",
|
|
2992
|
+
"baseUrl": "https://ads.zalo.me",
|
|
2993
|
+
"binaryFields": [],
|
|
2994
|
+
"pathFields": [],
|
|
2995
|
+
"queryFields": [],
|
|
2996
|
+
"headerFields": [],
|
|
2997
|
+
"cookieFields": [],
|
|
2998
|
+
"bodyFields": [
|
|
2999
|
+
"data"
|
|
3000
|
+
]
|
|
3001
|
+
};
|
|
3002
|
+
var OP_ZaloAdsDeleteCampaign = {
|
|
3003
|
+
"operationId": "ZaloAds_deleteCampaign",
|
|
3004
|
+
"method": "POST",
|
|
3005
|
+
"endpoint": "/api/campaign/change-status",
|
|
3006
|
+
"baseUrl": "https://ads.zalo.me",
|
|
3007
|
+
"binaryFields": [],
|
|
3008
|
+
"pathFields": [],
|
|
3009
|
+
"queryFields": [],
|
|
3010
|
+
"headerFields": [],
|
|
3011
|
+
"cookieFields": [],
|
|
3012
|
+
"bodyFields": [
|
|
3013
|
+
"campaignId",
|
|
3014
|
+
"status"
|
|
3015
|
+
]
|
|
3016
|
+
};
|
|
3017
|
+
var OP_ZaloAdsDuplicateAd = {
|
|
3018
|
+
operationId: "zalo_ads_duplicate_ad",
|
|
3019
|
+
method: "POST",
|
|
3020
|
+
endpoint: "/zaapi/DuplicateAd",
|
|
3021
|
+
baseUrl: "https://ads.zalo.me",
|
|
3022
|
+
binaryFields: [],
|
|
3023
|
+
pathFields: [],
|
|
3024
|
+
queryFields: [],
|
|
3025
|
+
headerFields: [],
|
|
3026
|
+
cookieFields: [],
|
|
3027
|
+
bodyFields: ["adid"]
|
|
3028
|
+
};
|
|
3029
|
+
var OP_ZaloAdsCreateSpellCheckV3Job = {
|
|
3030
|
+
operationId: "zalo_ads_create_spell_check_v3_job",
|
|
3031
|
+
method: "POST",
|
|
3032
|
+
endpoint: "/api/spell-check/v3",
|
|
3033
|
+
baseUrl: "https://ads.zalo.me",
|
|
3034
|
+
binaryFields: [],
|
|
3035
|
+
pathFields: [],
|
|
3036
|
+
queryFields: [],
|
|
3037
|
+
headerFields: [],
|
|
3038
|
+
cookieFields: [],
|
|
3039
|
+
bodyFields: ["title", "caption"]
|
|
3040
|
+
};
|
|
3041
|
+
var OP_ZaloAdsGetSpellCheckV3Job = {
|
|
3042
|
+
operationId: "zalo_ads_get_spell_check_v3_job",
|
|
3043
|
+
method: "GET",
|
|
3044
|
+
endpoint: "/api/spell-check/v3/{jobId}",
|
|
3045
|
+
baseUrl: "https://ads.zalo.me",
|
|
3046
|
+
binaryFields: [],
|
|
3047
|
+
pathFields: ["jobId"],
|
|
3048
|
+
queryFields: [],
|
|
3049
|
+
headerFields: [],
|
|
3050
|
+
cookieFields: [],
|
|
3051
|
+
bodyFields: []
|
|
3052
|
+
};
|
|
3053
|
+
var ZaloCampaignsService = class {
|
|
2494
3054
|
constructor(client) {
|
|
2495
3055
|
this.client = client;
|
|
2496
3056
|
}
|
|
2497
|
-
|
|
2498
|
-
|
|
3057
|
+
validator = ZaloCampaignsValidator;
|
|
3058
|
+
static validator = ZaloCampaignsValidator;
|
|
3059
|
+
updateVideoAd(request, options) {
|
|
3060
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateVideoAd, this.client.toTransportInput(OP_ZaloAdsUpdateVideoAd, request), options);
|
|
3061
|
+
}
|
|
3062
|
+
changeCampaignStatus(request, options) {
|
|
3063
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsChangeCampaignStatus, this.client.toTransportInput(OP_ZaloAdsChangeCampaignStatus, request), options);
|
|
3064
|
+
}
|
|
3065
|
+
deleteCampaign(request, options) {
|
|
3066
|
+
const payload = { campaignId: request.campaignId, status: request.status ?? -2 };
|
|
3067
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsDeleteCampaign, this.client.toTransportInput(OP_ZaloAdsDeleteCampaign, payload), options);
|
|
3068
|
+
}
|
|
3069
|
+
createWebsiteCampaign(request, options) {
|
|
3070
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateWebsiteCampaign, this.client.toTransportInput(OP_ZaloAdsCreateWebsiteCampaign, request), options);
|
|
3071
|
+
}
|
|
3072
|
+
updateWebsiteAd(request, options) {
|
|
3073
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateWebsiteAd, this.client.toTransportInput(OP_ZaloAdsUpdateWebsiteAd, request), options);
|
|
3074
|
+
}
|
|
3075
|
+
createDisplayCampaign(request, options) {
|
|
3076
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateDisplayCampaign, this.client.toTransportInput(OP_ZaloAdsCreateDisplayCampaign, request), options);
|
|
3077
|
+
}
|
|
3078
|
+
updateDisplayAd(request, options) {
|
|
3079
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateDisplayAd, this.client.toTransportInput(OP_ZaloAdsUpdateDisplayAd, request), options);
|
|
3080
|
+
}
|
|
3081
|
+
createVideoCampaign(request, options) {
|
|
3082
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateVideoCampaign, this.client.toTransportInput(OP_ZaloAdsCreateVideoCampaign, request), options);
|
|
3083
|
+
}
|
|
3084
|
+
createEcommerceCampaign(request, options) {
|
|
3085
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateEcommerceCampaign, this.client.toTransportInput(OP_ZaloAdsCreateEcommerceCampaign, request), options);
|
|
3086
|
+
}
|
|
3087
|
+
/** Alias theo tên tool chuẩn `zalo_ads_create_commerce_campaign` trong Project Schema Zalo ADS (`campaignType = 22`). */
|
|
3088
|
+
createCommerceCampaign(request, options) {
|
|
3089
|
+
return this.createEcommerceCampaign(request, options);
|
|
2499
3090
|
}
|
|
2500
|
-
|
|
2501
|
-
return this.client.
|
|
3091
|
+
createForm(request, options) {
|
|
3092
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateForm, this.client.toTransportInput(OP_ZaloAdsCreateForm, request), options);
|
|
2502
3093
|
}
|
|
2503
|
-
|
|
2504
|
-
return this.client.
|
|
3094
|
+
createFormCampaign(request, options) {
|
|
3095
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateFormCampaign, this.client.toTransportInput(OP_ZaloAdsCreateFormCampaign, request), options);
|
|
2505
3096
|
}
|
|
2506
|
-
|
|
2507
|
-
return this.client.
|
|
3097
|
+
createMessageCampaign(request, options) {
|
|
3098
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateMessageCampaign, this.client.toTransportInput(OP_ZaloAdsCreateMessageCampaign, request), options);
|
|
2508
3099
|
}
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
limit: 15,
|
|
2512
|
-
offset: 0,
|
|
2513
|
-
joinDateAsc: true,
|
|
2514
|
-
...request
|
|
2515
|
-
};
|
|
2516
|
-
return this.client.requestWithoutBody(OP_ZaloAdsListAgencyCustomersWithBudget, this.client.toTransportInput(OP_ZaloAdsListAgencyCustomersWithBudget, normalized), options);
|
|
3100
|
+
createOfficialAccountCampaign(request, options) {
|
|
3101
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateOfficialAccountCampaign, this.client.toTransportInput(OP_ZaloAdsCreateOfficialAccountCampaign, request), options);
|
|
2517
3102
|
}
|
|
2518
|
-
|
|
2519
|
-
|
|
3103
|
+
/** Alias theo tên tool chuẩn `zalo_ads_create_oa_campaign` trong Project Schema Zalo ADS (`campaignType = 3`). */
|
|
3104
|
+
createOaCampaign(request, options) {
|
|
3105
|
+
return this.createOfficialAccountCampaign(request, options);
|
|
2520
3106
|
}
|
|
2521
|
-
|
|
2522
|
-
return this.client.
|
|
3107
|
+
createPostCampaign(request, options) {
|
|
3108
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreatePostCampaign, this.client.toTransportInput(OP_ZaloAdsCreatePostCampaign, request), options);
|
|
2523
3109
|
}
|
|
2524
|
-
/**
|
|
2525
|
-
|
|
2526
|
-
return this.
|
|
3110
|
+
/** Alias theo tên tool chuẩn `zalo_ads_create_article_campaign` trong Project Schema Zalo ADS (`campaignType = 4`). */
|
|
3111
|
+
createArticleCampaign(request, options) {
|
|
3112
|
+
return this.createPostCampaign(request, options);
|
|
2527
3113
|
}
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
3114
|
+
getAdById(request = {}, options) {
|
|
3115
|
+
const normalized = {
|
|
3116
|
+
adId: request.adId,
|
|
3117
|
+
v: request.v ?? 2,
|
|
3118
|
+
newWard: request.newWard ?? true
|
|
3119
|
+
};
|
|
3120
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetAdById, this.client.toTransportInput(OP_ZaloAdsGetAdById, normalized), options);
|
|
2531
3121
|
}
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
3122
|
+
getAdChangeLog(request, options) {
|
|
3123
|
+
const normalized = {
|
|
3124
|
+
adId: request.adId,
|
|
3125
|
+
type: request.type ?? 1
|
|
3126
|
+
};
|
|
3127
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetAdChangeLog, this.client.toTransportInput(OP_ZaloAdsGetAdChangeLog, normalized), options);
|
|
2535
3128
|
}
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
return this.getApiBaAccountAllgrantedmembers(...args);
|
|
3129
|
+
getApiPlaceGetalldistricts(request = {}, options) {
|
|
3130
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetApiPlaceGetalldistricts, this.client.toTransportInput(OP_ZaloAdsGetApiPlaceGetalldistricts, request), options);
|
|
2539
3131
|
}
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
return this.getApiNotifiesHeader(...args);
|
|
3132
|
+
getApiSpellCheckV2(request, options) {
|
|
3133
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetApiSpellCheckV2, this.client.toTransportInput(OP_ZaloAdsGetApiSpellCheckV2, request), options);
|
|
2543
3134
|
}
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
return this.getApiLpNews(...args);
|
|
3135
|
+
getZaapiCheckcamphasmanyads(request = {}, options) {
|
|
3136
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiCheckcamphasmanyads, this.client.toTransportInput(OP_ZaloAdsGetZaapiCheckcamphasmanyads, request), options);
|
|
2547
3137
|
}
|
|
2548
|
-
}
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
return
|
|
3138
|
+
getZaapiGetadsfromcampaignid(request = {}, options) {
|
|
3139
|
+
const normalized = {
|
|
3140
|
+
campaignId: request.campaignId ?? request.campId,
|
|
3141
|
+
dataType: request.dataType ?? 1,
|
|
3142
|
+
v: request.v ?? 2
|
|
3143
|
+
};
|
|
3144
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetadsfromcampaignid, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetadsfromcampaignid, normalized), options);
|
|
2555
3145
|
}
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
2560
|
-
} else if (name.length < 2 || name.length > 255) {
|
|
2561
|
-
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
|
|
3146
|
+
/** Alias lấy danh sách quảng cáo của chiến dịch kèm metadata extend và extra.appliedRuleInfo */
|
|
3147
|
+
getAdsFromCampaignId(request = {}, options) {
|
|
3148
|
+
return this.getZaapiGetadsfromcampaignid(request, options);
|
|
2562
3149
|
}
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
try {
|
|
2566
|
-
targetingObj = JSON.parse(raw.targeting);
|
|
2567
|
-
} catch {
|
|
2568
|
-
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
|
|
2569
|
-
targetingObj = {};
|
|
2570
|
-
}
|
|
2571
|
-
} else if (raw.targeting && typeof raw.targeting === "object") {
|
|
2572
|
-
targetingObj = raw.targeting;
|
|
2573
|
-
} else {
|
|
2574
|
-
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c (chu\u1ED7i JSON ho\u1EB7c Object c\u1EA5u h\xECnh targeting).");
|
|
2575
|
-
targetingObj = {};
|
|
3150
|
+
getZaapiGetallpages(request = {}, options) {
|
|
3151
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetallpages, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetallpages, request), options);
|
|
2576
3152
|
}
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
errors.push("Tr\u01B0\u1EDDng 'Gender' ph\u1EA3i l\xE0 0 (T\u1EA5t c\u1EA3), 1 (Nam), ho\u1EB7c 2 (N\u1EEF).");
|
|
3153
|
+
getAllPages(request = {}, options) {
|
|
3154
|
+
return this.getZaapiGetallpages(request, options);
|
|
2580
3155
|
}
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
for (const age of newAgeRanges) {
|
|
2584
|
-
if (!VALID_AGE_RANGES.includes(age)) {
|
|
2585
|
-
errors.push(`M\xE3 \u0111\u1ED9 tu\u1ED5i '${age}' kh\xF4ng h\u1EE3p l\u1EC7. C\xE1c m\xE3 cho ph\xE9p: ${VALID_AGE_RANGES.join(", ")}.`);
|
|
2586
|
-
}
|
|
3156
|
+
getZaapiGetownedarticles(request, options) {
|
|
3157
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetownedarticles, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetownedarticles, request), options);
|
|
2587
3158
|
}
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
for (const o of os) {
|
|
2591
|
-
if (!VALID_OS.includes(o)) {
|
|
2592
|
-
errors.push(`M\xE3 h\u1EC7 \u0111i\u1EC1u h\xE0nh '${o}' kh\xF4ng h\u1EE3p l\u1EC7 (0: Android, 1: iOS, 2: Windows Phone, 3: PC).`);
|
|
2593
|
-
}
|
|
3159
|
+
getOwnedArticles(request, options) {
|
|
3160
|
+
return this.getZaapiGetownedarticles(request, options);
|
|
2594
3161
|
}
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
location = {
|
|
2598
|
-
Addresses: [],
|
|
2599
|
-
Cities: [],
|
|
2600
|
-
WardTargeting: { Includes: [], Excludes: [] }
|
|
2601
|
-
};
|
|
2602
|
-
} else {
|
|
2603
|
-
location = {
|
|
2604
|
-
Addresses: Array.isArray(location.Addresses) ? location.Addresses : [],
|
|
2605
|
-
Cities: Array.isArray(location.Cities) ? location.Cities : [],
|
|
2606
|
-
WardTargeting: location.WardTargeting && typeof location.WardTargeting === "object" ? location.WardTargeting : { Includes: [], Excludes: [] }
|
|
2607
|
-
};
|
|
2608
|
-
if (location.WardTargeting.Includes && !Array.isArray(location.WardTargeting.Includes)) {
|
|
2609
|
-
errors.push("Tr\u01B0\u1EDDng 'Location.WardTargeting.Includes' ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng khu v\u1EF1c.");
|
|
2610
|
-
} else if (Array.isArray(location.WardTargeting.Includes)) {
|
|
2611
|
-
for (const inc of location.WardTargeting.Includes) {
|
|
2612
|
-
if (![1, 2, 3].includes(Number(inc.Id))) {
|
|
2613
|
-
errors.push(`M\xE3 v\xF9ng mi\u1EC1n Id='${inc.Id}' kh\xF4ng h\u1EE3p l\u1EC7 (1: Mi\u1EC1n B\u1EAFc, 2: Mi\u1EC1n Trung, 3: Mi\u1EC1n Nam).`);
|
|
2614
|
-
}
|
|
2615
|
-
if (inc.Provinces && !Array.isArray(inc.Provinces)) {
|
|
2616
|
-
errors.push(`Tr\u01B0\u1EDDng 'Provinces' trong v\xF9ng mi\u1EC1n Id=${inc.Id} ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng t\u1EC9nh/th\xE0nh.`);
|
|
2617
|
-
}
|
|
2618
|
-
}
|
|
2619
|
-
}
|
|
3162
|
+
getZaapiGetownedpages(request = {}, options) {
|
|
3163
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetownedpages, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetownedpages, request), options);
|
|
2620
3164
|
}
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
CustomAudienceId: 0,
|
|
2624
|
-
Gender: gender,
|
|
2625
|
-
NewAgeRanges: newAgeRanges,
|
|
2626
|
-
Os: os,
|
|
2627
|
-
Location: location
|
|
2628
|
-
};
|
|
2629
|
-
return {
|
|
2630
|
-
isValid: errors.length === 0,
|
|
2631
|
-
errors,
|
|
2632
|
-
data: errors.length === 0 ? {
|
|
2633
|
-
name,
|
|
2634
|
-
caType: 1,
|
|
2635
|
-
targeting: JSON.stringify(finalTargeting)
|
|
2636
|
-
} : void 0
|
|
2637
|
-
};
|
|
2638
|
-
}
|
|
2639
|
-
function validateCreatePhoneAudienceRequest(input) {
|
|
2640
|
-
const errors = [];
|
|
2641
|
-
if (!input || typeof input !== "object") {
|
|
2642
|
-
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
3165
|
+
getOwnedPages(request = {}, options) {
|
|
3166
|
+
return this.getZaapiGetownedpages(request, options);
|
|
2643
3167
|
}
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
if (!name || name.length < 2 || name.length > 255) {
|
|
2647
|
-
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
|
|
3168
|
+
listFormsByOfficialAccount(request, options) {
|
|
3169
|
+
return this.client.requestWithoutBody(OP_ZaloAdsListFormsByOfficialAccount, this.client.toTransportInput(OP_ZaloAdsListFormsByOfficialAccount, request), options);
|
|
2648
3170
|
}
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
try {
|
|
2652
|
-
targetingObj = JSON.parse(raw.targeting);
|
|
2653
|
-
} catch {
|
|
2654
|
-
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
|
|
2655
|
-
}
|
|
2656
|
-
} else if (raw.targeting && typeof raw.targeting === "object") {
|
|
2657
|
-
targetingObj = raw.targeting;
|
|
2658
|
-
} else {
|
|
2659
|
-
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
3171
|
+
listMiniPagesByTemplate(request, options) {
|
|
3172
|
+
return this.client.requestWithoutBody(OP_ZaloAdsListMiniPagesByTemplate, this.client.toTransportInput(OP_ZaloAdsListMiniPagesByTemplate, request), options);
|
|
2660
3173
|
}
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
errors.push("Tr\u01B0\u1EDDng 'Path' (URL file .txt sau khi upload) l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
3174
|
+
postZaapiDeletead(request = {}, options) {
|
|
3175
|
+
return this.client.requestWithoutBody(OP_ZaloAdsPostZaapiDeletead, this.client.toTransportInput(OP_ZaloAdsPostZaapiDeletead, request), options);
|
|
2664
3176
|
}
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
3177
|
+
renameCampaign(request, options) {
|
|
3178
|
+
const normalized = {
|
|
3179
|
+
campid: request.campid ?? request.campaignId,
|
|
3180
|
+
newname: request.newname ?? request.campaignName ?? request.name
|
|
3181
|
+
};
|
|
3182
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsRenameCampaign, this.client.toTransportInput(OP_ZaloAdsRenameCampaign, normalized), options);
|
|
2668
3183
|
}
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
errors,
|
|
2672
|
-
data: errors.length === 0 ? {
|
|
2673
|
-
name,
|
|
2674
|
-
caType: 3,
|
|
2675
|
-
targeting: JSON.stringify({
|
|
2676
|
-
Name: String(targetingObj.Name || "phones.txt"),
|
|
2677
|
-
Path: path,
|
|
2678
|
-
Total: total,
|
|
2679
|
-
ZaloId: Number(targetingObj.ZaloId || 0),
|
|
2680
|
-
OriginAudience: 0
|
|
2681
|
-
})
|
|
2682
|
-
} : void 0
|
|
2683
|
-
};
|
|
2684
|
-
}
|
|
2685
|
-
function validateCreateLookalikeAudienceRequest(input) {
|
|
2686
|
-
const errors = [];
|
|
2687
|
-
if (!input || typeof input !== "object") {
|
|
2688
|
-
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
3184
|
+
updateEcommerceAd(request, options) {
|
|
3185
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateEcommerceAd, this.client.toTransportInput(OP_ZaloAdsUpdateEcommerceAd, request), options);
|
|
2689
3186
|
}
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
|
|
3187
|
+
/** Alias theo tên tool chuẩn `zalo_ads_update_commerce_ad` trong Project Schema Zalo ADS (`Type = 23`, gắn `MiniPageId`). */
|
|
3188
|
+
updateCommerceAd(request, options) {
|
|
3189
|
+
return this.updateEcommerceAd(request, options);
|
|
2694
3190
|
}
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
try {
|
|
2698
|
-
targetingObj = JSON.parse(raw.targeting);
|
|
2699
|
-
} catch {
|
|
2700
|
-
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
|
|
2701
|
-
}
|
|
2702
|
-
} else if (raw.targeting && typeof raw.targeting === "object") {
|
|
2703
|
-
targetingObj = raw.targeting;
|
|
2704
|
-
} else {
|
|
2705
|
-
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
3191
|
+
updateFormAd(request, options) {
|
|
3192
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateFormAd, this.client.toTransportInput(OP_ZaloAdsUpdateFormAd, request), options);
|
|
2706
3193
|
}
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
errors.push("Tr\u01B0\u1EDDng 'OriginAudience' (ID nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng S\u0110T g\u1ED1c) l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
3194
|
+
updateMessageAd(request, options) {
|
|
3195
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateMessageAd, this.client.toTransportInput(OP_ZaloAdsUpdateMessageAd, request), options);
|
|
2710
3196
|
}
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
errors.push("Tr\u01B0\u1EDDng 'Total' c\u1EE7a Lookalike ch\u1EC9 ch\u1EA5p nh\u1EADn c\xE1c m\u1ED1c: 1.000.000, 1.500.000 ho\u1EB7c 2.000.000.");
|
|
3197
|
+
updateNewAds(request, options) {
|
|
3198
|
+
return this.client.requestMultipart(OP_ZaloAdsUpdateNewAds, this.client.toTransportInput(OP_ZaloAdsUpdateNewAds, request), options);
|
|
2714
3199
|
}
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
errors,
|
|
2718
|
-
data: errors.length === 0 ? {
|
|
2719
|
-
name,
|
|
2720
|
-
caType: 6,
|
|
2721
|
-
targeting: JSON.stringify({
|
|
2722
|
-
OriginAudience: originAudience,
|
|
2723
|
-
Total: total,
|
|
2724
|
-
Name: String(targetingObj.Name || "Lookalike Audience"),
|
|
2725
|
-
Path: String(targetingObj.Path || "")
|
|
2726
|
-
})
|
|
2727
|
-
} : void 0
|
|
2728
|
-
};
|
|
2729
|
-
}
|
|
2730
|
-
function validateCreateFormEventAudienceRequest(input) {
|
|
2731
|
-
const errors = [];
|
|
2732
|
-
if (!input || typeof input !== "object") {
|
|
2733
|
-
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
3200
|
+
updateOfficialAccountAd(request, options) {
|
|
3201
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateOfficialAccountAd, this.client.toTransportInput(OP_ZaloAdsUpdateOfficialAccountAd, request), options);
|
|
2734
3202
|
}
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
|
|
3203
|
+
/** Alias theo tên tool chuẩn `zalo_ads_update_oa_ad` trong Project Schema Zalo ADS (`Type = 2`, `Action = 6`). */
|
|
3204
|
+
updateOaAd(request, options) {
|
|
3205
|
+
return this.updateOfficialAccountAd(request, options);
|
|
2739
3206
|
}
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
try {
|
|
2743
|
-
targetingObj = JSON.parse(raw.targeting);
|
|
2744
|
-
} catch {
|
|
2745
|
-
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
|
|
2746
|
-
}
|
|
2747
|
-
} else if (raw.targeting && typeof raw.targeting === "object") {
|
|
2748
|
-
targetingObj = raw.targeting;
|
|
3207
|
+
updatePostAd(request, options) {
|
|
3208
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdatePostAd, this.client.toTransportInput(OP_ZaloAdsUpdatePostAd, request), options);
|
|
2749
3209
|
}
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
3210
|
+
/** Alias theo tên tool chuẩn `zalo_ads_update_article_ad` trong Project Schema Zalo ADS (`Type = 3`, gắn `ZaloFeedId`). */
|
|
3211
|
+
updateArticleAd(request, options) {
|
|
3212
|
+
return this.updatePostAd(request, options);
|
|
2753
3213
|
}
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
3214
|
+
/** Xóa quảng cáo */
|
|
3215
|
+
deleteAd(...args) {
|
|
3216
|
+
return this.postZaapiDeletead(...args);
|
|
2757
3217
|
}
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
3218
|
+
/** Danh sách quận/huyện để nhắm mục tiêu */
|
|
3219
|
+
getAllDistricts(...args) {
|
|
3220
|
+
return this.getApiPlaceGetalldistricts(...args);
|
|
2761
3221
|
}
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
3222
|
+
/** Kiểm tra chính tả văn bản quảng cáo */
|
|
3223
|
+
getSpellCheckV2(...args) {
|
|
3224
|
+
return this.getApiSpellCheckV2(...args);
|
|
2765
3225
|
}
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
NumDays: numDays,
|
|
2776
|
-
FormIds: formIds
|
|
2777
|
-
})
|
|
2778
|
-
} : void 0
|
|
2779
|
-
};
|
|
2780
|
-
}
|
|
2781
|
-
function validateCreateMessageOaEventAudienceRequest(input) {
|
|
2782
|
-
const errors = [];
|
|
2783
|
-
if (!input || typeof input !== "object") {
|
|
2784
|
-
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
3226
|
+
/**
|
|
3227
|
+
* Khởi tạo tác vụ kiểm tra chính tả và vi phạm quy chuẩn quảng cáo AI V3 (POST /api/spell-check/v3).
|
|
3228
|
+
*/
|
|
3229
|
+
createSpellCheckV3Job(request, options) {
|
|
3230
|
+
return this.client.requestJson(
|
|
3231
|
+
OP_ZaloAdsCreateSpellCheckV3Job,
|
|
3232
|
+
this.client.toTransportInput(OP_ZaloAdsCreateSpellCheckV3Job, request),
|
|
3233
|
+
options
|
|
3234
|
+
);
|
|
2785
3235
|
}
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
3236
|
+
/**
|
|
3237
|
+
* Lấy kết quả kiểm tra chính tả AI V3 theo jobId (GET /api/spell-check/v3/{jobId}).
|
|
3238
|
+
*/
|
|
3239
|
+
getSpellCheckV3Job(request, options) {
|
|
3240
|
+
return this.client.requestWithoutBody(
|
|
3241
|
+
OP_ZaloAdsGetSpellCheckV3Job,
|
|
3242
|
+
this.client.toTransportInput(OP_ZaloAdsGetSpellCheckV3Job, request),
|
|
3243
|
+
options
|
|
3244
|
+
);
|
|
2790
3245
|
}
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
3246
|
+
/**
|
|
3247
|
+
* Helper kiểm tra chính tả AI V3 trọn gói: Gửi kiểm tra và tự động polling cho đến khi hoàn thành (hoặc timeout).
|
|
3248
|
+
* @param request Tiêu đề (title) và chú thích (caption) cần kiểm tra.
|
|
3249
|
+
* @param pollIntervalMs Chu kỳ polling kiểm tra trạng thái (mặc định: 600ms).
|
|
3250
|
+
* @param timeoutMs Thời gian chờ tối đa (mặc định: 15.000ms = 15 giây).
|
|
3251
|
+
*/
|
|
3252
|
+
async checkSpellV3AndWait(request, pollIntervalMs = 600, timeoutMs = 15e3, options) {
|
|
3253
|
+
const jobRes = await this.createSpellCheckV3Job(request, options);
|
|
3254
|
+
const jobId = jobRes?.data?.jobId;
|
|
3255
|
+
if (!jobId) {
|
|
3256
|
+
throw new Error(`[SpellCheckV3] Kh\xF4ng nh\u1EADn \u0111\u01B0\u1EE3c jobId t\u1EEB Zalo Ads (code: ${jobRes?.code})`);
|
|
2797
3257
|
}
|
|
2798
|
-
|
|
2799
|
-
|
|
3258
|
+
const startTime = Date.now();
|
|
3259
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
3260
|
+
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
3261
|
+
const res = await this.getSpellCheckV3Job({ jobId }, options);
|
|
3262
|
+
if (res?.data?.status === "COMPLETED") {
|
|
3263
|
+
return res;
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
throw new Error(`[SpellCheckV3] Qu\xE1 th\u1EDDi gian ch\u1EDD (${timeoutMs}ms) cho t\xE1c v\u1EE5 ki\u1EC3m tra ch\xEDnh t\u1EA3 jobId: ${jobId}`);
|
|
3267
|
+
}
|
|
3268
|
+
/**
|
|
3269
|
+
* Nhân bản (sao chép / duplicate) một mẫu quảng cáo đã tồn tại trên Zalo Ads (POST /zaapi/DuplicateAd).
|
|
3270
|
+
* Giúp tạo nhanh một bản sao Ad mới trong cùng chiến dịch để thực hiện A/B testing.
|
|
3271
|
+
*/
|
|
3272
|
+
duplicateAd(request, options) {
|
|
3273
|
+
const payload = {
|
|
3274
|
+
adid: request.adid ?? request.adId
|
|
3275
|
+
};
|
|
3276
|
+
return this.client.requestFormUrlEncoded(
|
|
3277
|
+
OP_ZaloAdsDuplicateAd,
|
|
3278
|
+
this.client.toTransportInput(OP_ZaloAdsDuplicateAd, payload),
|
|
3279
|
+
options
|
|
3280
|
+
);
|
|
3281
|
+
}
|
|
3282
|
+
};
|
|
3283
|
+
|
|
3284
|
+
// src/services/account.service.ts
|
|
3285
|
+
var OP_ZaloAdsGetApiWhoami = {
|
|
3286
|
+
"operationId": "ZaloAds_getApiWhoami",
|
|
3287
|
+
"method": "GET",
|
|
3288
|
+
"endpoint": "/api/whoami",
|
|
3289
|
+
"baseUrl": "https://ads.zalo.me",
|
|
3290
|
+
"binaryFields": [],
|
|
3291
|
+
"pathFields": [],
|
|
3292
|
+
"queryFields": [],
|
|
3293
|
+
"headerFields": [],
|
|
3294
|
+
"cookieFields": [],
|
|
3295
|
+
"bodyFields": []
|
|
3296
|
+
};
|
|
3297
|
+
var OP_ZaloAdsGetApiPaymentTransactionHistory = {
|
|
3298
|
+
"operationId": "ZaloAds_getApiPaymentTransactionHistory",
|
|
3299
|
+
"method": "GET",
|
|
3300
|
+
"endpoint": "/api/payment/transaction-history",
|
|
3301
|
+
"baseUrl": "https://ads.zalo.me",
|
|
3302
|
+
"binaryFields": [],
|
|
3303
|
+
"pathFields": [],
|
|
3304
|
+
"queryFields": [
|
|
3305
|
+
"to",
|
|
3306
|
+
"from",
|
|
3307
|
+
"memberId"
|
|
3308
|
+
],
|
|
3309
|
+
"headerFields": [],
|
|
3310
|
+
"cookieFields": [],
|
|
3311
|
+
"bodyFields": []
|
|
3312
|
+
};
|
|
3313
|
+
var OP_ZaloAdsGetApiBaAccountAllaccessors = {
|
|
3314
|
+
"operationId": "ZaloAds_getApiBaAccountAllaccessors",
|
|
3315
|
+
"method": "GET",
|
|
3316
|
+
"endpoint": "/api/ba/account/allAccessors",
|
|
3317
|
+
"baseUrl": "https://ads.zalo.me",
|
|
3318
|
+
"binaryFields": [],
|
|
3319
|
+
"pathFields": [],
|
|
3320
|
+
"queryFields": [
|
|
3321
|
+
"isShowAll"
|
|
3322
|
+
],
|
|
3323
|
+
"headerFields": [],
|
|
3324
|
+
"cookieFields": [],
|
|
3325
|
+
"bodyFields": []
|
|
3326
|
+
};
|
|
3327
|
+
var OP_ZaloAdsGetApiBaAccountAllgrantedmembers = {
|
|
3328
|
+
"operationId": "ZaloAds_getApiBaAccountAllgrantedmembers",
|
|
3329
|
+
"method": "GET",
|
|
3330
|
+
"endpoint": "/api/ba/account/allGrantedMembers",
|
|
3331
|
+
"baseUrl": "https://ads.zalo.me",
|
|
3332
|
+
"binaryFields": [],
|
|
3333
|
+
"pathFields": [],
|
|
3334
|
+
"queryFields": [],
|
|
3335
|
+
"headerFields": [],
|
|
3336
|
+
"cookieFields": [],
|
|
3337
|
+
"bodyFields": []
|
|
3338
|
+
};
|
|
3339
|
+
var OP_ZaloAdsListAgencyCustomersWithBudget = {
|
|
3340
|
+
"operationId": "ZaloAds_listAgencyCustomersWithBudget",
|
|
3341
|
+
"method": "GET",
|
|
3342
|
+
"endpoint": "/api/ba/agency/customersWithBudget",
|
|
3343
|
+
"baseUrl": "https://ads.zalo.me",
|
|
3344
|
+
"binaryFields": [],
|
|
3345
|
+
"pathFields": [],
|
|
3346
|
+
"queryFields": [
|
|
3347
|
+
"limit",
|
|
3348
|
+
"offset",
|
|
3349
|
+
"joinDateAsc"
|
|
3350
|
+
],
|
|
3351
|
+
"headerFields": [],
|
|
3352
|
+
"cookieFields": [],
|
|
3353
|
+
"bodyFields": []
|
|
3354
|
+
};
|
|
3355
|
+
var OP_ZaloAdsGetApiNotifiesHeader = {
|
|
3356
|
+
"operationId": "ZaloAds_getApiNotifiesHeader",
|
|
3357
|
+
"method": "GET",
|
|
3358
|
+
"endpoint": "/api/notifies/header",
|
|
3359
|
+
"baseUrl": "https://ads.zalo.me",
|
|
3360
|
+
"binaryFields": [],
|
|
3361
|
+
"pathFields": [],
|
|
3362
|
+
"queryFields": [],
|
|
3363
|
+
"headerFields": [],
|
|
3364
|
+
"cookieFields": [],
|
|
3365
|
+
"bodyFields": []
|
|
3366
|
+
};
|
|
3367
|
+
var OP_ZaloAdsGetApiLpNews = {
|
|
3368
|
+
"operationId": "ZaloAds_getApiLpNews",
|
|
3369
|
+
"method": "GET",
|
|
3370
|
+
"endpoint": "/api/lp-news",
|
|
3371
|
+
"baseUrl": "https://ads.zalo.me",
|
|
3372
|
+
"binaryFields": [],
|
|
3373
|
+
"pathFields": [],
|
|
3374
|
+
"queryFields": [],
|
|
3375
|
+
"headerFields": [],
|
|
3376
|
+
"cookieFields": [],
|
|
3377
|
+
"bodyFields": []
|
|
3378
|
+
};
|
|
3379
|
+
var ZaloAccountService = class {
|
|
3380
|
+
constructor(client) {
|
|
3381
|
+
this.client = client;
|
|
3382
|
+
}
|
|
3383
|
+
getApiWhoami(request = {}, options) {
|
|
3384
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetApiWhoami, this.client.toTransportInput(OP_ZaloAdsGetApiWhoami, request), options);
|
|
2800
3385
|
}
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
if (!oaId) {
|
|
2804
|
-
errors.push("Tr\u01B0\u1EDDng 'OaId' (chu\u1ED7i pageId ho\u1EB7c noisedId c\u1EE7a OA) l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
3386
|
+
getApiPaymentTransactionHistory(request, options) {
|
|
3387
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetApiPaymentTransactionHistory, this.client.toTransportInput(OP_ZaloAdsGetApiPaymentTransactionHistory, request), options);
|
|
2805
3388
|
}
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
errors.push("Tr\u01B0\u1EDDng 'NumDays' ph\u1EA3i n\u1EB1m trong kho\u1EA3ng t\u1EEB 1 \u0111\u1EBFn 90 ng\xE0y.");
|
|
3389
|
+
getApiBaAccountAllaccessors(request = {}, options) {
|
|
3390
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetApiBaAccountAllaccessors, this.client.toTransportInput(OP_ZaloAdsGetApiBaAccountAllaccessors, request), options);
|
|
2809
3391
|
}
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
errors,
|
|
2813
|
-
data: errors.length === 0 ? {
|
|
2814
|
-
name,
|
|
2815
|
-
caType: 11,
|
|
2816
|
-
targeting: JSON.stringify({
|
|
2817
|
-
EventId: eventId,
|
|
2818
|
-
OaId: oaId,
|
|
2819
|
-
NumDays: numDays
|
|
2820
|
-
})
|
|
2821
|
-
} : void 0
|
|
2822
|
-
};
|
|
2823
|
-
}
|
|
2824
|
-
function validateCreateMessagePersonalEventAudienceRequest(input) {
|
|
2825
|
-
const errors = [];
|
|
2826
|
-
if (!input || typeof input !== "object") {
|
|
2827
|
-
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
3392
|
+
getApiBaAccountAllgrantedmembers(request = {}, options) {
|
|
3393
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetApiBaAccountAllgrantedmembers, this.client.toTransportInput(OP_ZaloAdsGetApiBaAccountAllgrantedmembers, request), options);
|
|
2828
3394
|
}
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
3395
|
+
listAgencyCustomersWithBudget(request = { limit: 15, offset: 0, joinDateAsc: true }, options) {
|
|
3396
|
+
const normalized = {
|
|
3397
|
+
limit: 15,
|
|
3398
|
+
offset: 0,
|
|
3399
|
+
joinDateAsc: true,
|
|
3400
|
+
...request
|
|
3401
|
+
};
|
|
3402
|
+
return this.client.requestWithoutBody(OP_ZaloAdsListAgencyCustomersWithBudget, this.client.toTransportInput(OP_ZaloAdsListAgencyCustomersWithBudget, normalized), options);
|
|
2833
3403
|
}
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
try {
|
|
2837
|
-
targetingObj = JSON.parse(raw.targeting);
|
|
2838
|
-
} catch {
|
|
2839
|
-
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
|
|
2840
|
-
}
|
|
2841
|
-
} else if (raw.targeting && typeof raw.targeting === "object") {
|
|
2842
|
-
targetingObj = raw.targeting;
|
|
3404
|
+
getApiNotifiesHeader(request = {}, options) {
|
|
3405
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetApiNotifiesHeader, this.client.toTransportInput(OP_ZaloAdsGetApiNotifiesHeader, request), options);
|
|
2843
3406
|
}
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
errors.push("Tr\u01B0\u1EDDng 'EventId' ph\u1EA3i l\xE0 1 (\u0110\xE3 li\xEAn h\u1EC7), 2 (\u0110\xE3 xem kh\xF4ng li\xEAn h\u1EC7), ho\u1EB7c 3 (Xem carousel kh\xF4ng li\xEAn h\u1EC7).");
|
|
3407
|
+
getApiLpNews(request = {}, options) {
|
|
3408
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetApiLpNews, this.client.toTransportInput(OP_ZaloAdsGetApiLpNews, request), options);
|
|
2847
3409
|
}
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
3410
|
+
/** Lấy thông tin tài khoản đang đăng nhập */
|
|
3411
|
+
getWhoami(...args) {
|
|
3412
|
+
return this.getApiWhoami(...args);
|
|
2851
3413
|
}
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
3414
|
+
/** Lịch sử giao dịch thanh toán */
|
|
3415
|
+
getPaymentTransactionHistory(...args) {
|
|
3416
|
+
return this.getApiPaymentTransactionHistory(...args);
|
|
2855
3417
|
}
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
data: errors.length === 0 ? {
|
|
2860
|
-
name,
|
|
2861
|
-
caType: 14,
|
|
2862
|
-
targeting: JSON.stringify({
|
|
2863
|
-
EventId: eventId,
|
|
2864
|
-
NumDays: numDays,
|
|
2865
|
-
PageIds: pageIds
|
|
2866
|
-
})
|
|
2867
|
-
} : void 0
|
|
2868
|
-
};
|
|
2869
|
-
}
|
|
2870
|
-
function validateEstimateAudienceRequest(input) {
|
|
2871
|
-
const errors = [];
|
|
2872
|
-
if (!input || typeof input !== "object") {
|
|
2873
|
-
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
3418
|
+
/** Danh sách accessor tài khoản BA */
|
|
3419
|
+
getBaAccountAllAccessors(...args) {
|
|
3420
|
+
return this.getApiBaAccountAllaccessors(...args);
|
|
2874
3421
|
}
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
3422
|
+
/** Danh sách thành viên được cấp quyền BA */
|
|
3423
|
+
getBaAccountAllGrantedMembers(...args) {
|
|
3424
|
+
return this.getApiBaAccountAllgrantedmembers(...args);
|
|
3425
|
+
}
|
|
3426
|
+
/** Thông báo trên thanh tiêu đề */
|
|
3427
|
+
getNotifiesHeader(...args) {
|
|
3428
|
+
return this.getApiNotifiesHeader(...args);
|
|
3429
|
+
}
|
|
3430
|
+
/** Tin tức landing page / bảng tin */
|
|
3431
|
+
getLpNews(...args) {
|
|
3432
|
+
return this.getApiLpNews(...args);
|
|
2879
3433
|
}
|
|
2880
|
-
const ageRanges = Array.isArray(raw.ageRanges) && raw.ageRanges.length > 0 ? raw.ageRanges.map(Number) : [10283, 10284, 10285, 10286, 10287];
|
|
2881
|
-
const platforms = Array.isArray(raw.platforms) && raw.platforms.length > 0 ? raw.platforms.map(Number) : [0, 1, 3];
|
|
2882
|
-
const priceType = typeof raw.priceType === "number" ? raw.priceType : 2;
|
|
2883
|
-
const wardsTargeting = typeof raw.wardsTargeting === "string" && raw.wardsTargeting.trim() ? raw.wardsTargeting.trim() : JSON.stringify({ Includes: [], Excludes: [] });
|
|
2884
|
-
return {
|
|
2885
|
-
isValid: errors.length === 0,
|
|
2886
|
-
errors,
|
|
2887
|
-
data: errors.length === 0 ? {
|
|
2888
|
-
gender,
|
|
2889
|
-
ageRanges,
|
|
2890
|
-
platforms,
|
|
2891
|
-
locations: typeof raw.locations === "string" ? raw.locations : "",
|
|
2892
|
-
provinces: Array.isArray(raw.provinces) ? raw.provinces.map(Number) : [],
|
|
2893
|
-
wardsTargeting,
|
|
2894
|
-
priceType,
|
|
2895
|
-
number: typeof raw.number === "string" ? raw.number : String(raw.number || "0")
|
|
2896
|
-
} : void 0
|
|
2897
|
-
};
|
|
2898
|
-
}
|
|
2899
|
-
var ZaloAudiencesValidator = {
|
|
2900
|
-
createSavedAudience: validateCreateSavedAudienceRequest,
|
|
2901
|
-
createPhoneAudience: validateCreatePhoneAudienceRequest,
|
|
2902
|
-
createLookalikeAudience: validateCreateLookalikeAudienceRequest,
|
|
2903
|
-
createFormEventAudience: validateCreateFormEventAudienceRequest,
|
|
2904
|
-
createMessageOaEventAudience: validateCreateMessageOaEventAudienceRequest,
|
|
2905
|
-
createMessagePersonalEventAudience: validateCreateMessagePersonalEventAudienceRequest,
|
|
2906
|
-
estimateAudience: validateEstimateAudienceRequest
|
|
2907
3434
|
};
|
|
2908
3435
|
|
|
2909
3436
|
// src/services/audiences.service.ts
|
|
@@ -3547,6 +4074,20 @@ var OP_ZaloAdsListAutomatedRules = {
|
|
|
3547
4074
|
"cookieFields": [],
|
|
3548
4075
|
"bodyFields": []
|
|
3549
4076
|
};
|
|
4077
|
+
var OP_ZaloAdsGetAutomatedRuleDetail = {
|
|
4078
|
+
"operationId": "ZaloAds_getAutomatedRuleDetail",
|
|
4079
|
+
"method": "GET",
|
|
4080
|
+
"endpoint": "/api/automatedrules/{automatedRuleId}",
|
|
4081
|
+
"baseUrl": "https://ads.zalo.me",
|
|
4082
|
+
"binaryFields": [],
|
|
4083
|
+
"pathFields": [
|
|
4084
|
+
"automatedRuleId"
|
|
4085
|
+
],
|
|
4086
|
+
"queryFields": [],
|
|
4087
|
+
"headerFields": [],
|
|
4088
|
+
"cookieFields": [],
|
|
4089
|
+
"bodyFields": []
|
|
4090
|
+
};
|
|
3550
4091
|
var OP_ZaloAdsCreateAutomatedRule = {
|
|
3551
4092
|
"operationId": "ZaloAds_createAutomatedRule",
|
|
3552
4093
|
"method": "POST",
|
|
@@ -3573,7 +4114,7 @@ var OP_ZaloAdsCreateAutomatedRule = {
|
|
|
3573
4114
|
var OP_ZaloAdsUpdateAutomatedRule = {
|
|
3574
4115
|
"operationId": "ZaloAds_updateAutomatedRule",
|
|
3575
4116
|
"method": "POST",
|
|
3576
|
-
"endpoint": "/api/automatedrules/update",
|
|
4117
|
+
"endpoint": "/api/ad/automatedrules/update",
|
|
3577
4118
|
"baseUrl": "https://ads.zalo.me",
|
|
3578
4119
|
"binaryFields": [],
|
|
3579
4120
|
"pathFields": [],
|
|
@@ -3582,11 +4123,15 @@ var OP_ZaloAdsUpdateAutomatedRule = {
|
|
|
3582
4123
|
"cookieFields": [],
|
|
3583
4124
|
"bodyFields": [
|
|
3584
4125
|
"automatedRuleId",
|
|
3585
|
-
"
|
|
3586
|
-
"appliedTo",
|
|
4126
|
+
"scope",
|
|
3587
4127
|
"ruleName",
|
|
3588
4128
|
"action",
|
|
3589
4129
|
"conditions",
|
|
4130
|
+
"frequency",
|
|
4131
|
+
"appliedItems",
|
|
4132
|
+
"appliedIds",
|
|
4133
|
+
"rowVersion",
|
|
4134
|
+
"appliedTo",
|
|
3590
4135
|
"schedule",
|
|
3591
4136
|
"campaignIds",
|
|
3592
4137
|
"adIds"
|
|
@@ -3644,6 +4189,9 @@ var ZaloAutomatedRulesService = class {
|
|
|
3644
4189
|
const queryInput = { query_param: { ruleName: request.ruleName ?? "" } };
|
|
3645
4190
|
return this.client.requestWithoutBody(OP_ZaloAdsListAutomatedRules, queryInput, options);
|
|
3646
4191
|
}
|
|
4192
|
+
getAutomatedRuleDetail(request, options) {
|
|
4193
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetAutomatedRuleDetail, this.client.toTransportInput(OP_ZaloAdsGetAutomatedRuleDetail, request), options);
|
|
4194
|
+
}
|
|
3647
4195
|
createAutomatedRule(request, options) {
|
|
3648
4196
|
return this.client.requestJson(OP_ZaloAdsCreateAutomatedRule, this.client.toTransportInput(OP_ZaloAdsCreateAutomatedRule, request), options);
|
|
3649
4197
|
}
|
|
@@ -4755,6 +5303,9 @@ var ZaloAdsService = class extends ZaloCampaignsService {
|
|
|
4755
5303
|
listAutomatedRules(request = {}, options) {
|
|
4756
5304
|
return this.automatedRules.listAutomatedRules(request, options);
|
|
4757
5305
|
}
|
|
5306
|
+
getAutomatedRuleDetail(request, options) {
|
|
5307
|
+
return this.automatedRules.getAutomatedRuleDetail(request, options);
|
|
5308
|
+
}
|
|
4758
5309
|
createAutomatedRule(request, options) {
|
|
4759
5310
|
return this.automatedRules.createAutomatedRule(request, options);
|
|
4760
5311
|
}
|
|
@@ -5437,6 +5988,34 @@ function isPositiveInteger2(val) {
|
|
|
5437
5988
|
function toPositiveInteger2(val) {
|
|
5438
5989
|
return typeof val === "number" ? Math.floor(val) : parseInt(String(val), 10);
|
|
5439
5990
|
}
|
|
5991
|
+
function validateCreateInstantPageRequest(input) {
|
|
5992
|
+
const errors = [];
|
|
5993
|
+
if (!input || typeof input !== "object") {
|
|
5994
|
+
return { isValid: false, errors: ["D\u1EEF li\u1EC7u y\xEAu c\u1EA7u t\u1EA1o Instant Page ph\u1EA3i l\xE0 m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng (object)."] };
|
|
5995
|
+
}
|
|
5996
|
+
const obj = input;
|
|
5997
|
+
const validTemplates = [1, 3, 4, 5];
|
|
5998
|
+
if (!isPositiveInteger2(obj.templateId) || !validTemplates.includes(Number(obj.templateId))) {
|
|
5999
|
+
errors.push(`Tr\u01B0\u1EDDng 'templateId' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i thu\u1ED9c danh m\u1EE5c m\u1EABu h\u1EE3p l\u1EC7: ${validTemplates.join(", ")} (1: S\u1EA3n ph\u1EA9m form nh\xFAng, 3: S\u1EA3n ph\u1EA9m popup, 4: K\u1ECBch b\u1EA3n tin nh\u1EAFn, 5: Mua s\u1EAFm).`);
|
|
6000
|
+
}
|
|
6001
|
+
if (obj.oaId !== void 0 && obj.oaId !== null) {
|
|
6002
|
+
const oaIdStr = String(obj.oaId).trim();
|
|
6003
|
+
if (!oaIdStr) {
|
|
6004
|
+
errors.push("Tr\u01B0\u1EDDng 'oaId' n\u1EBFu cung c\u1EA5p kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
|
|
6005
|
+
} else if (oaIdStr.length < 10) {
|
|
6006
|
+
errors.push("Tr\u01B0\u1EDDng 'oaId' tr\xEAn domain page.ads.zalo.me b\u1EAFt bu\u1ED9c ph\u1EA3i l\xE0 chu\u1ED7i \u0111\u1ECBnh danh 64-bit c\u1EE7a Official Account (l\u1EA5y t\u1EEB GET /api/official-accounts), kh\xF4ng d\xF9ng ID s\u1ED1 nguy\xEAn ng\u1EAFn.");
|
|
6007
|
+
}
|
|
6008
|
+
}
|
|
6009
|
+
const data = {
|
|
6010
|
+
templateId: toPositiveInteger2(obj.templateId),
|
|
6011
|
+
oaId: obj.oaId ? String(obj.oaId).trim() : void 0
|
|
6012
|
+
};
|
|
6013
|
+
return {
|
|
6014
|
+
isValid: errors.length === 0,
|
|
6015
|
+
errors,
|
|
6016
|
+
data: errors.length === 0 ? data : void 0
|
|
6017
|
+
};
|
|
6018
|
+
}
|
|
5440
6019
|
function validateCloneInstantPageRequest(input) {
|
|
5441
6020
|
const errors = [];
|
|
5442
6021
|
if (!input || typeof input !== "object") {
|
|
@@ -5799,6 +6378,7 @@ function validateUpsertInstantPageFormRequest(input) {
|
|
|
5799
6378
|
};
|
|
5800
6379
|
}
|
|
5801
6380
|
var ZaloInstantPagesValidator = {
|
|
6381
|
+
validateCreateInstantPage: validateCreateInstantPageRequest,
|
|
5802
6382
|
validateCloneInstantPage: validateCloneInstantPageRequest,
|
|
5803
6383
|
validateGetInstantPageDetail: validateGetInstantPageDetailRequest,
|
|
5804
6384
|
validateGetInstantPageSharedUser: validateGetInstantPageSharedUserRequest,
|
|
@@ -5815,6 +6395,21 @@ var ZaloInstantPagesValidator = {
|
|
|
5815
6395
|
};
|
|
5816
6396
|
|
|
5817
6397
|
// src/services/instant-pages.service.ts
|
|
6398
|
+
var OP_ZaloInstantPagesCreateInstantPage = {
|
|
6399
|
+
"operationId": "ZaloInstantPages_createInstantPage",
|
|
6400
|
+
"method": "POST",
|
|
6401
|
+
"endpoint": "/api/instant-pages",
|
|
6402
|
+
"baseUrl": "https://page.ads.zalo.me",
|
|
6403
|
+
"binaryFields": [],
|
|
6404
|
+
"pathFields": [],
|
|
6405
|
+
"queryFields": [],
|
|
6406
|
+
"headerFields": [],
|
|
6407
|
+
"cookieFields": [],
|
|
6408
|
+
"bodyFields": [
|
|
6409
|
+
"templateId",
|
|
6410
|
+
"oaId"
|
|
6411
|
+
]
|
|
6412
|
+
};
|
|
5818
6413
|
var OP_ZaloInstantPagesCloneInstantPage = {
|
|
5819
6414
|
"operationId": "ZaloInstantPages_cloneInstantPage",
|
|
5820
6415
|
"method": "POST",
|
|
@@ -5904,6 +6499,20 @@ var OP_ZaloInstantPagesListInstantPageShares = {
|
|
|
5904
6499
|
"cookieFields": [],
|
|
5905
6500
|
"bodyFields": []
|
|
5906
6501
|
};
|
|
6502
|
+
var OP_ZaloInstantPagesUpdateInstantPageShares = {
|
|
6503
|
+
"operationId": "ZaloInstantPages_updateInstantPageShares",
|
|
6504
|
+
"method": "POST",
|
|
6505
|
+
"endpoint": "/api/instant-pages/{instantPageId}/shares",
|
|
6506
|
+
"baseUrl": "https://page.ads.zalo.me",
|
|
6507
|
+
"binaryFields": [],
|
|
6508
|
+
"pathFields": [
|
|
6509
|
+
"instantPageId"
|
|
6510
|
+
],
|
|
6511
|
+
"queryFields": [],
|
|
6512
|
+
"headerFields": [],
|
|
6513
|
+
"cookieFields": [],
|
|
6514
|
+
"bodyFields": []
|
|
6515
|
+
};
|
|
5907
6516
|
var OP_ZaloInstantPagesListInstantPageUsers = {
|
|
5908
6517
|
"operationId": "ZaloInstantPages_listInstantPageUsers",
|
|
5909
6518
|
"method": "GET",
|
|
@@ -6021,6 +6630,9 @@ var ZaloInstantPagesService = class {
|
|
|
6021
6630
|
* Dùng ở backend (NestJS/Express/Fastify), middleware hoặc AI Agent để verify payload trước khi gọi SDK.
|
|
6022
6631
|
*/
|
|
6023
6632
|
static validator = ZaloInstantPagesValidator;
|
|
6633
|
+
createInstantPage(request, options) {
|
|
6634
|
+
return this.client.requestJson(OP_ZaloInstantPagesCreateInstantPage, this.client.toTransportInput(OP_ZaloInstantPagesCreateInstantPage, request), options);
|
|
6635
|
+
}
|
|
6024
6636
|
cloneInstantPage(request, options) {
|
|
6025
6637
|
return this.client.requestJson(OP_ZaloInstantPagesCloneInstantPage, this.client.toTransportInput(OP_ZaloInstantPagesCloneInstantPage, request), options);
|
|
6026
6638
|
}
|
|
@@ -6039,6 +6651,13 @@ var ZaloInstantPagesService = class {
|
|
|
6039
6651
|
listInstantPageShares(request, options) {
|
|
6040
6652
|
return this.client.requestWithoutBody(OP_ZaloInstantPagesListInstantPageShares, this.client.toTransportInput(OP_ZaloInstantPagesListInstantPageShares, request), options);
|
|
6041
6653
|
}
|
|
6654
|
+
updateInstantPageShares(request, options) {
|
|
6655
|
+
const transportInput = {
|
|
6656
|
+
path_param: { instantPageId: request.instantPageId },
|
|
6657
|
+
body: request.shares
|
|
6658
|
+
};
|
|
6659
|
+
return this.client.requestJson(OP_ZaloInstantPagesUpdateInstantPageShares, transportInput, options);
|
|
6660
|
+
}
|
|
6042
6661
|
listInstantPageUsers(request = {}, options) {
|
|
6043
6662
|
return this.client.requestWithoutBody(OP_ZaloInstantPagesListInstantPageUsers, this.client.toTransportInput(OP_ZaloInstantPagesListInstantPageUsers, request), options);
|
|
6044
6663
|
}
|
|
@@ -6575,19 +7194,312 @@ var ZaloInstantPageBlockType = /* @__PURE__ */ ((ZaloInstantPageBlockType2) => {
|
|
|
6575
7194
|
ZaloInstantPageBlockType2[ZaloInstantPageBlockType2["CONSENT_NOTICE"] = 27] = "CONSENT_NOTICE";
|
|
6576
7195
|
return ZaloInstantPageBlockType2;
|
|
6577
7196
|
})(ZaloInstantPageBlockType || {});
|
|
7197
|
+
var ZaloInstantPageSharePermission = {
|
|
7198
|
+
/** Quản trị viên: Toàn quyền quản trị, chỉnh sửa, phân quyền và gắn quảng cáo. */
|
|
7199
|
+
ADMIN: 1,
|
|
7200
|
+
/** Biên tập viên: Quyền chỉnh sửa nội dung trang. */
|
|
7201
|
+
UPDATE_PAGE: 2,
|
|
7202
|
+
/** Tải dữ liệu: Quyền tải thông tin khách hàng / Leads. */
|
|
7203
|
+
DOWNLOAD_INFO: 3,
|
|
7204
|
+
/** Chỉ xem: Quyền xem trước và thống kê. */
|
|
7205
|
+
READ_ONLY: 4
|
|
7206
|
+
};
|
|
7207
|
+
|
|
7208
|
+
// src/validators/automated-rules.validator.ts
|
|
7209
|
+
var AutomatedRuleScopeEnum = /* @__PURE__ */ ((AutomatedRuleScopeEnum2) => {
|
|
7210
|
+
AutomatedRuleScopeEnum2[AutomatedRuleScopeEnum2["Ads"] = 1] = "Ads";
|
|
7211
|
+
return AutomatedRuleScopeEnum2;
|
|
7212
|
+
})(AutomatedRuleScopeEnum || {});
|
|
7213
|
+
var AutomatedRuleActionTypeEnum = /* @__PURE__ */ ((AutomatedRuleActionTypeEnum2) => {
|
|
7214
|
+
AutomatedRuleActionTypeEnum2[AutomatedRuleActionTypeEnum2["Resume"] = 1] = "Resume";
|
|
7215
|
+
AutomatedRuleActionTypeEnum2[AutomatedRuleActionTypeEnum2["Pause"] = 2] = "Pause";
|
|
7216
|
+
AutomatedRuleActionTypeEnum2[AutomatedRuleActionTypeEnum2["IncreaseByAmount"] = 3] = "IncreaseByAmount";
|
|
7217
|
+
AutomatedRuleActionTypeEnum2[AutomatedRuleActionTypeEnum2["DecreaseByAmount"] = 4] = "DecreaseByAmount";
|
|
7218
|
+
AutomatedRuleActionTypeEnum2[AutomatedRuleActionTypeEnum2["IncreaseByPercentage"] = 5] = "IncreaseByPercentage";
|
|
7219
|
+
AutomatedRuleActionTypeEnum2[AutomatedRuleActionTypeEnum2["DecreaseByPercentage"] = 6] = "DecreaseByPercentage";
|
|
7220
|
+
return AutomatedRuleActionTypeEnum2;
|
|
7221
|
+
})(AutomatedRuleActionTypeEnum || {});
|
|
7222
|
+
var AutomatedRuleFrequencyEnum = /* @__PURE__ */ ((AutomatedRuleFrequencyEnum2) => {
|
|
7223
|
+
AutomatedRuleFrequencyEnum2[AutomatedRuleFrequencyEnum2["OneHour"] = 1] = "OneHour";
|
|
7224
|
+
AutomatedRuleFrequencyEnum2[AutomatedRuleFrequencyEnum2["HalfDay"] = 12] = "HalfDay";
|
|
7225
|
+
AutomatedRuleFrequencyEnum2[AutomatedRuleFrequencyEnum2["OneDay"] = 24] = "OneDay";
|
|
7226
|
+
AutomatedRuleFrequencyEnum2[AutomatedRuleFrequencyEnum2["OneWeek"] = 168] = "OneWeek";
|
|
7227
|
+
return AutomatedRuleFrequencyEnum2;
|
|
7228
|
+
})(AutomatedRuleFrequencyEnum || {});
|
|
7229
|
+
var AutomatedRuleConditionFieldEnum = /* @__PURE__ */ ((AutomatedRuleConditionFieldEnum2) => {
|
|
7230
|
+
AutomatedRuleConditionFieldEnum2[AutomatedRuleConditionFieldEnum2["Status"] = 1] = "Status";
|
|
7231
|
+
AutomatedRuleConditionFieldEnum2[AutomatedRuleConditionFieldEnum2["Impression"] = 11] = "Impression";
|
|
7232
|
+
AutomatedRuleConditionFieldEnum2[AutomatedRuleConditionFieldEnum2["Click"] = 16] = "Click";
|
|
7233
|
+
AutomatedRuleConditionFieldEnum2[AutomatedRuleConditionFieldEnum2["CTR"] = 9999] = "CTR";
|
|
7234
|
+
AutomatedRuleConditionFieldEnum2[AutomatedRuleConditionFieldEnum2["Cost"] = 100001] = "Cost";
|
|
7235
|
+
return AutomatedRuleConditionFieldEnum2;
|
|
7236
|
+
})(AutomatedRuleConditionFieldEnum || {});
|
|
7237
|
+
var AutomatedRuleOperatorEnum = /* @__PURE__ */ ((AutomatedRuleOperatorEnum2) => {
|
|
7238
|
+
AutomatedRuleOperatorEnum2[AutomatedRuleOperatorEnum2["GreaterThan"] = 1] = "GreaterThan";
|
|
7239
|
+
AutomatedRuleOperatorEnum2[AutomatedRuleOperatorEnum2["LessThan"] = 2] = "LessThan";
|
|
7240
|
+
AutomatedRuleOperatorEnum2[AutomatedRuleOperatorEnum2["Between"] = 3] = "Between";
|
|
7241
|
+
AutomatedRuleOperatorEnum2[AutomatedRuleOperatorEnum2["NotBetween"] = 4] = "NotBetween";
|
|
7242
|
+
AutomatedRuleOperatorEnum2[AutomatedRuleOperatorEnum2["Include"] = 5] = "Include";
|
|
7243
|
+
AutomatedRuleOperatorEnum2[AutomatedRuleOperatorEnum2["Exclude"] = 6] = "Exclude";
|
|
7244
|
+
return AutomatedRuleOperatorEnum2;
|
|
7245
|
+
})(AutomatedRuleOperatorEnum || {});
|
|
7246
|
+
var AutomatedRuleTimeRangeEnum = /* @__PURE__ */ ((AutomatedRuleTimeRangeEnum2) => {
|
|
7247
|
+
AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["AllTime"] = 1] = "AllTime";
|
|
7248
|
+
AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["AllTimeExcludeToday"] = 2] = "AllTimeExcludeToday";
|
|
7249
|
+
AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Today"] = 3] = "Today";
|
|
7250
|
+
AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Yesterday"] = 4] = "Yesterday";
|
|
7251
|
+
AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous2Day"] = 1002] = "Previous2Day";
|
|
7252
|
+
AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous3Day"] = 1003] = "Previous3Day";
|
|
7253
|
+
AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous4Day"] = 1004] = "Previous4Day";
|
|
7254
|
+
AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous5Day"] = 1005] = "Previous5Day";
|
|
7255
|
+
AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous6Day"] = 1006] = "Previous6Day";
|
|
7256
|
+
AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous7Day"] = 1007] = "Previous7Day";
|
|
7257
|
+
AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous14Day"] = 1014] = "Previous14Day";
|
|
7258
|
+
AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous21Day"] = 1021] = "Previous21Day";
|
|
7259
|
+
AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous30Day"] = 1030] = "Previous30Day";
|
|
7260
|
+
return AutomatedRuleTimeRangeEnum2;
|
|
7261
|
+
})(AutomatedRuleTimeRangeEnum || {});
|
|
7262
|
+
var ZaloAutomatedRulesValidator = class {
|
|
7263
|
+
/**
|
|
7264
|
+
* Kiểm tra và chuẩn hóa payload tạo mới quy tắc tự động (`POST /api/automatedrules/create`)
|
|
7265
|
+
*/
|
|
7266
|
+
static validateCreateRule(payload) {
|
|
7267
|
+
const errors = [];
|
|
7268
|
+
const warnings = [];
|
|
7269
|
+
if (!payload || typeof payload !== "object") {
|
|
7270
|
+
return { isValid: false, errors: ["Payload quy t\u1EAFc t\u1EF1 \u0111\u1ED9ng ph\u1EA3i l\xE0 m\u1ED9t object."], warnings };
|
|
7271
|
+
}
|
|
7272
|
+
const ruleName = String(payload.ruleName || "").trim();
|
|
7273
|
+
if (!ruleName) {
|
|
7274
|
+
errors.push("T\xEAn quy t\u1EAFc (ruleName) kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
|
|
7275
|
+
} else if (ruleName.length > 100) {
|
|
7276
|
+
errors.push(`T\xEAn quy t\u1EAFc kh\xF4ng \u0111\u01B0\u1EE3c v\u01B0\u1EE3t qu\xE1 100 k\xFD t\u1EF1 (hi\u1EC7n c\xF3 ${ruleName.length} k\xFD t\u1EF1).`);
|
|
7277
|
+
}
|
|
7278
|
+
const scope = payload.scope !== void 0 ? Number(payload.scope) : 1;
|
|
7279
|
+
if (scope !== 1) {
|
|
7280
|
+
errors.push("Zalo Ads hi\u1EC7n ch\u1EC9 h\u1ED7 tr\u1EE3 scope: 1 (\xC1p d\u1EE5ng cho Qu\u1EA3ng c\xE1o).");
|
|
7281
|
+
}
|
|
7282
|
+
if (!payload.action || typeof payload.action !== "object") {
|
|
7283
|
+
errors.push("Thi\u1EBFu c\u1EA5u h\xECnh h\xE0nh \u0111\u1ED9ng (action).");
|
|
7284
|
+
} else {
|
|
7285
|
+
const act = payload.action;
|
|
7286
|
+
const actType2 = Number(act.type);
|
|
7287
|
+
if (![3, 4, 5, 6].includes(actType2)) {
|
|
7288
|
+
if ([1, 2].includes(actType2)) {
|
|
7289
|
+
errors.push(`H\xE0nh \u0111\u1ED9ng ${actType2 === 1 ? "Ti\u1EBFp t\u1EE5c" : "T\u1EA1m d\u1EEBng"} qu\u1EA3ng c\xE1o (type: ${actType2}) hi\u1EC7n ch\u01B0a \u0111\u01B0\u1EE3c backend Zalo Ads k\xEDch ho\u1EA1t trong scope n\xE0y.`);
|
|
7290
|
+
} else {
|
|
7291
|
+
errors.push(`Lo\u1EA1i h\xE0nh \u0111\u1ED9ng kh\xF4ng h\u1EE3p l\u1EC7: ${act.type}. Ch\u1EC9 h\u1ED7 tr\u1EE3 3 (T\u0103ng gi\xE1 \u0111), 4 (Gi\u1EA3m gi\xE1 \u0111), 5 (T\u0103ng gi\xE1 %), 6 (Gi\u1EA3m gi\xE1 %).`);
|
|
7292
|
+
}
|
|
7293
|
+
}
|
|
7294
|
+
if (!Array.isArray(act.values) || act.values.length === 0 || Number(act.values[0]) <= 0) {
|
|
7295
|
+
errors.push("Gi\xE1 tr\u1ECB thay \u0111\u1ED5i gi\xE1 th\u1EA7u (action.values) ph\u1EA3i l\xE0 m\u1EA3ng ch\u1EE9a s\u1ED1 d\u01B0\u01A1ng > 0.");
|
|
7296
|
+
} else {
|
|
7297
|
+
const val = Number(act.values[0]);
|
|
7298
|
+
if ([5, 6].includes(actType2) && (val < 1 || val > 100)) {
|
|
7299
|
+
errors.push(`Thay \u0111\u1ED5i theo % (type: ${actType2}) y\xEAu c\u1EA7u gi\xE1 tr\u1ECB trong kho\u1EA3ng t\u1EEB 1% \u0111\u1EBFn 100% (hi\u1EC7n l\xE0 ${val}%).`);
|
|
7300
|
+
}
|
|
7301
|
+
}
|
|
7302
|
+
if (act.limit !== void 0 && Number(act.limit) <= 0) {
|
|
7303
|
+
errors.push("H\u1EA1n m\u1EE9c gi\xE1 th\u1EA7u (action.limit) n\u1EBFu c\xF3 ph\u1EA3i l\xE0 s\u1ED1 ti\u1EC1n d\u01B0\u01A1ng > 0 VN\u0110.");
|
|
7304
|
+
}
|
|
7305
|
+
}
|
|
7306
|
+
const frequency = payload.frequency !== void 0 ? Number(payload.frequency) : 12;
|
|
7307
|
+
const actType = payload.action ? Number(payload.action.type) : 0;
|
|
7308
|
+
if ([3, 4, 5, 6].includes(actType)) {
|
|
7309
|
+
if (![1, 12, 24, 168].includes(frequency)) {
|
|
7310
|
+
errors.push(`T\u1EA7n su\u1EA5t h\xE0nh \u0111\u1ED9ng cho \u0111i\u1EC1u ch\u1EC9nh gi\xE1 th\u1EA7u ph\u1EA3i thu\u1ED9c [1 (1 gi\u1EDD), 12 (12 gi\u1EDD), 24 (1 ng\xE0y), 168 (1 tu\u1EA7n)]. Gi\xE1 tr\u1ECB ${frequency} s\u1EBD b\u1ECB t\u1EEB ch\u1ED1i v\u1EDBi l\u1ED7i "T\u1EA7n su\u1EA5t h\xE0nh \u0111\u1ED9ng kh\xF4ng h\u1EE3p l\u1EC7."`);
|
|
7311
|
+
}
|
|
7312
|
+
}
|
|
7313
|
+
if (!Array.isArray(payload.conditions) || payload.conditions.length === 0) {
|
|
7314
|
+
errors.push("Quy t\u1EAFc t\u1EF1 \u0111\u1ED9ng ph\u1EA3i c\xF3 \xEDt nh\u1EA5t 1 \u0111i\u1EC1u ki\u1EC7n ch\u1EC9 s\u1ED1 (conditions).");
|
|
7315
|
+
} else {
|
|
7316
|
+
payload.conditions.forEach((c, idx) => {
|
|
7317
|
+
const f = Number(c.field);
|
|
7318
|
+
if (![1, 11, 16, 9999, 100001].includes(f)) {
|
|
7319
|
+
errors.push(`\u0110i\u1EC1u ki\u1EC7n [${idx + 1}]: Ch\u1EC9 s\u1ED1 kh\xF4ng h\u1EE3p l\u1EC7 (field: ${c.field}). H\u1ED7 tr\u1EE3: 1 (Status), 11 (Impression), 16 (Click), 9999 (CTR), 100001 (Cost).`);
|
|
7320
|
+
}
|
|
7321
|
+
const op = Number(c.operator);
|
|
7322
|
+
if (![1, 2, 3, 4, 5, 6].includes(op)) {
|
|
7323
|
+
errors.push(`\u0110i\u1EC1u ki\u1EC7n [${idx + 1}]: Ph\xE9p to\xE1n kh\xF4ng h\u1EE3p l\u1EC7 (operator: ${c.operator}). H\u1ED7 tr\u1EE3 1 (>), 2 (<), 3 (between), 4 (not between), 5 (include), 6 (exclude).`);
|
|
7324
|
+
}
|
|
7325
|
+
if (!Array.isArray(c.values) || c.values.length === 0) {
|
|
7326
|
+
errors.push(`\u0110i\u1EC1u ki\u1EC7n [${idx + 1}]: values ph\u1EA3i l\xE0 m\u1EA3ng gi\xE1 tr\u1ECB ng\u01B0\u1EE1ng.`);
|
|
7327
|
+
}
|
|
7328
|
+
if (f !== 1 && !c.timeRange) {
|
|
7329
|
+
warnings.push(`\u0110i\u1EC1u ki\u1EC7n [${idx + 1}]: Thi\u1EBFu timeRange, h\u1EC7 th\u1ED1ng s\u1EBD m\u1EB7c \u0111\u1ECBnh l\xE0 1 (Lifetime).`);
|
|
7330
|
+
}
|
|
7331
|
+
});
|
|
7332
|
+
}
|
|
7333
|
+
const sanitizedData = {
|
|
7334
|
+
ruleName,
|
|
7335
|
+
scope: 1,
|
|
7336
|
+
action: {
|
|
7337
|
+
type: Number(payload.action?.type),
|
|
7338
|
+
field: 1,
|
|
7339
|
+
values: payload.action?.values?.map(Number) || [10],
|
|
7340
|
+
limit: payload.action?.limit !== void 0 ? Number(payload.action.limit) : 1e6
|
|
7341
|
+
},
|
|
7342
|
+
conditions: (payload.conditions || []).map((c) => ({
|
|
7343
|
+
field: Number(c.field),
|
|
7344
|
+
operator: Number(c.operator),
|
|
7345
|
+
values: c.values.map(Number),
|
|
7346
|
+
timeRange: c.timeRange !== void 0 ? Number(c.timeRange) : 1
|
|
7347
|
+
})),
|
|
7348
|
+
frequency,
|
|
7349
|
+
appliedIds: Array.isArray(payload.appliedIds) ? payload.appliedIds.map(Number) : []
|
|
7350
|
+
};
|
|
7351
|
+
return {
|
|
7352
|
+
isValid: errors.length === 0,
|
|
7353
|
+
errors,
|
|
7354
|
+
warnings,
|
|
7355
|
+
sanitizedData: errors.length === 0 ? sanitizedData : void 0
|
|
7356
|
+
};
|
|
7357
|
+
}
|
|
7358
|
+
/**
|
|
7359
|
+
* Kiểm tra và chuẩn hóa payload cập nhật quy tắc tự động (`POST /api/ad/automatedrules/update`)
|
|
7360
|
+
*/
|
|
7361
|
+
static validateUpdateRule(payload) {
|
|
7362
|
+
const base = this.validateCreateRule(payload);
|
|
7363
|
+
const errors = [...base.errors];
|
|
7364
|
+
const warnings = [...base.warnings];
|
|
7365
|
+
if (!payload.automatedRuleId || Number(payload.automatedRuleId) <= 0) {
|
|
7366
|
+
errors.unshift("ID quy t\u1EAFc t\u1EF1 \u0111\u1ED9ng (automatedRuleId) l\xE0 b\u1EAFt bu\u1ED9c khi c\u1EADp nh\u1EADt.");
|
|
7367
|
+
}
|
|
7368
|
+
const appliedItems = Array.isArray(payload.appliedItems) ? payload.appliedItems.map((item) => ({
|
|
7369
|
+
appliedId: Number(item.appliedId),
|
|
7370
|
+
mode: Number(item.mode) === -1 ? -1 : 1
|
|
7371
|
+
// -1: Unapply, 1: Apply
|
|
7372
|
+
})) : [];
|
|
7373
|
+
const sanitizedData = base.sanitizedData ? {
|
|
7374
|
+
automatedRuleId: Number(payload.automatedRuleId),
|
|
7375
|
+
...base.sanitizedData,
|
|
7376
|
+
appliedItems
|
|
7377
|
+
} : void 0;
|
|
7378
|
+
return {
|
|
7379
|
+
isValid: errors.length === 0,
|
|
7380
|
+
errors,
|
|
7381
|
+
warnings,
|
|
7382
|
+
sanitizedData
|
|
7383
|
+
};
|
|
7384
|
+
}
|
|
7385
|
+
};
|
|
7386
|
+
|
|
7387
|
+
// src/validators/conversions.validator.ts
|
|
7388
|
+
var ConversionLabelEnum = /* @__PURE__ */ ((ConversionLabelEnum2) => {
|
|
7389
|
+
ConversionLabelEnum2[ConversionLabelEnum2["AddToCart"] = 2] = "AddToCart";
|
|
7390
|
+
ConversionLabelEnum2[ConversionLabelEnum2["CompleteRegistration"] = 4] = "CompleteRegistration";
|
|
7391
|
+
ConversionLabelEnum2[ConversionLabelEnum2["Contact"] = 5] = "Contact";
|
|
7392
|
+
ConversionLabelEnum2[ConversionLabelEnum2["InitiateCheckout"] = 9] = "InitiateCheckout";
|
|
7393
|
+
ConversionLabelEnum2[ConversionLabelEnum2["Lead"] = 10] = "Lead";
|
|
7394
|
+
ConversionLabelEnum2[ConversionLabelEnum2["Purchase"] = 11] = "Purchase";
|
|
7395
|
+
ConversionLabelEnum2[ConversionLabelEnum2["Other"] = 19] = "Other";
|
|
7396
|
+
return ConversionLabelEnum2;
|
|
7397
|
+
})(ConversionLabelEnum || {});
|
|
7398
|
+
var ConversionUrlTypeEnum = /* @__PURE__ */ ((ConversionUrlTypeEnum2) => {
|
|
7399
|
+
ConversionUrlTypeEnum2[ConversionUrlTypeEnum2["Exact"] = 0] = "Exact";
|
|
7400
|
+
ConversionUrlTypeEnum2[ConversionUrlTypeEnum2["Contains"] = 1] = "Contains";
|
|
7401
|
+
return ConversionUrlTypeEnum2;
|
|
7402
|
+
})(ConversionUrlTypeEnum || {});
|
|
7403
|
+
var ZaloConversionsValidator = class {
|
|
7404
|
+
/**
|
|
7405
|
+
* Danh mục 7 nhãn chuẩn được Zalo Ads hỗ trợ chính thức
|
|
7406
|
+
*/
|
|
7407
|
+
static SUPPORTED_LABELS = {
|
|
7408
|
+
[10 /* Lead */]: "Tr\u1EDF th\xE0nh kh\xE1ch h\xE0ng ti\u1EC1m n\u0103ng",
|
|
7409
|
+
[11 /* Purchase */]: "Ho\xE0n t\u1EA5t mua h\xE0ng",
|
|
7410
|
+
[5 /* Contact */]: "Li\xEAn h\u1EC7",
|
|
7411
|
+
[4 /* CompleteRegistration */]: "Ho\xE0n t\u1EA5t \u0111\u0103ng k\xFD",
|
|
7412
|
+
[9 /* InitiateCheckout */]: "B\u1EAFt \u0111\u1EA7u thanh to\xE1n",
|
|
7413
|
+
[2 /* AddToCart */]: "Th\xEAm v\xE0o gi\u1ECF h\xE0ng",
|
|
7414
|
+
[19 /* Other */]: "Kh\xE1c"
|
|
7415
|
+
};
|
|
7416
|
+
/**
|
|
7417
|
+
* Kiểm tra và chuẩn hóa payload tạo mới Conversion (`POST /api/conversion/add`)
|
|
7418
|
+
*/
|
|
7419
|
+
static validateCreateConversion(payload) {
|
|
7420
|
+
const errors = [];
|
|
7421
|
+
const warnings = [];
|
|
7422
|
+
if (!payload || typeof payload !== "object") {
|
|
7423
|
+
return { isValid: false, errors: ["Payload conversion ph\u1EA3i l\xE0 m\u1ED9t object."], warnings };
|
|
7424
|
+
}
|
|
7425
|
+
const name = String(payload.name || "").trim();
|
|
7426
|
+
if (!name) {
|
|
7427
|
+
errors.push("T\xEAn conversion (name) kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
|
|
7428
|
+
} else if (name.length > 180) {
|
|
7429
|
+
errors.push(`T\xEAn conversion kh\xF4ng \u0111\u01B0\u1EE3c v\u01B0\u1EE3t qu\xE1 180 k\xFD t\u1EF1 (hi\u1EC7n c\xF3 ${name.length} k\xFD t\u1EF1).`);
|
|
7430
|
+
}
|
|
7431
|
+
const landingPage = String(payload.landingPage || "").trim();
|
|
7432
|
+
if (!landingPage) {
|
|
7433
|
+
errors.push("Trang \u0111\xEDch (landingPage) kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
|
|
7434
|
+
} else {
|
|
7435
|
+
const urlPattern = /^https?:\/\/.+/i;
|
|
7436
|
+
if (!urlPattern.test(landingPage)) {
|
|
7437
|
+
errors.push("Trang \u0111\xEDch (landingPage) ph\u1EA3i l\xE0 m\u1ED9t URL h\u1EE3p l\u1EC7 b\u1EAFt \u0111\u1EA7u b\u1EB1ng http:// ho\u1EB7c https:// (v\xED d\u1EE5: https://redai.vn).");
|
|
7438
|
+
}
|
|
7439
|
+
}
|
|
7440
|
+
const urlType = payload.urlType !== void 0 ? Number(payload.urlType) : 1;
|
|
7441
|
+
if (![0, 1].includes(urlType)) {
|
|
7442
|
+
errors.push(`Lo\u1EA1i URL kh\xF4ng h\u1EE3p l\u1EC7: ${payload.urlType}. Ch\u1EC9 h\u1ED7 tr\u1EE3 0 (Exact URL) ho\u1EB7c 1 (Contains keywords).`);
|
|
7443
|
+
}
|
|
7444
|
+
const labelId = payload.labelId !== void 0 ? Number(payload.labelId) : 10;
|
|
7445
|
+
if (!Object.keys(this.SUPPORTED_LABELS).map(Number).includes(labelId)) {
|
|
7446
|
+
errors.push(`Nh\xE3n conversion kh\xF4ng h\u1EE3p l\u1EC7 (labelId: ${payload.labelId}). Zalo Ads ch\u1EC9 h\u1ED7 tr\u1EE3: 10 (Lead), 11 (Purchase), 5 (Contact), 4 (Registration), 9 (Checkout), 2 (AddToCart), 19 (Other).`);
|
|
7447
|
+
}
|
|
7448
|
+
const buttonIds = Array.isArray(payload.buttonIds) ? payload.buttonIds.map(String).map((s) => s.trim()).filter((s) => Boolean(s)) : [];
|
|
7449
|
+
const elements = Array.isArray(payload.elements) ? payload.elements : [];
|
|
7450
|
+
const keywords = Array.isArray(payload.keywords) ? payload.keywords.map(String).map((s) => s.trim()).filter((s) => Boolean(s)) : [];
|
|
7451
|
+
if (buttonIds.length === 0 && elements.length === 0 && keywords.length === 0) {
|
|
7452
|
+
errors.push("Conversion b\u1EAFt bu\u1ED9c ph\u1EA3i c\xF3 \xEDt nh\u1EA5t 1 c\u01A1 ch\u1EBF nh\u1EADn di\u1EC7n s\u1EF1 ki\u1EC7n: URL ch\u1EE9a t\u1EEB kh\xF3a (keywords), ID n\xFAt b\u1EA5m (buttonIds), ho\u1EB7c ph\u1EA7n t\u1EED giao di\u1EC7n (elements).");
|
|
7453
|
+
}
|
|
7454
|
+
const sanitizedElements = elements.map((el) => {
|
|
7455
|
+
if (typeof el === "object" && Array.isArray(el.class)) {
|
|
7456
|
+
return { class: el.class.map(String).map((s) => s.trim()).filter((s) => Boolean(s)) };
|
|
7457
|
+
}
|
|
7458
|
+
return el;
|
|
7459
|
+
});
|
|
7460
|
+
const sanitizedData = {
|
|
7461
|
+
name,
|
|
7462
|
+
landingPage,
|
|
7463
|
+
urlType,
|
|
7464
|
+
labelId,
|
|
7465
|
+
buttonIds,
|
|
7466
|
+
elements: sanitizedElements,
|
|
7467
|
+
keywords
|
|
7468
|
+
};
|
|
7469
|
+
return {
|
|
7470
|
+
isValid: errors.length === 0,
|
|
7471
|
+
errors,
|
|
7472
|
+
warnings,
|
|
7473
|
+
sanitizedData: errors.length === 0 ? sanitizedData : void 0
|
|
7474
|
+
};
|
|
7475
|
+
}
|
|
7476
|
+
};
|
|
6578
7477
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6579
7478
|
0 && (module.exports = {
|
|
6580
7479
|
ALLOWED_CTAS_PER_AD_TYPE,
|
|
6581
7480
|
ALL_ZALO_ADS_DOMAINS,
|
|
7481
|
+
AutomatedRuleActionTypeEnum,
|
|
7482
|
+
AutomatedRuleConditionFieldEnum,
|
|
7483
|
+
AutomatedRuleFrequencyEnum,
|
|
7484
|
+
AutomatedRuleOperatorEnum,
|
|
7485
|
+
AutomatedRuleScopeEnum,
|
|
7486
|
+
AutomatedRuleTimeRangeEnum,
|
|
7487
|
+
ConversionLabelEnum,
|
|
7488
|
+
ConversionUrlTypeEnum,
|
|
6582
7489
|
MemoryZaloSessionStore,
|
|
6583
7490
|
RedisZaloSessionStore,
|
|
6584
7491
|
TieredZaloSessionStore,
|
|
6585
7492
|
VALID_AD_TYPES,
|
|
6586
7493
|
VALID_CAMPAIGN_TYPES,
|
|
7494
|
+
ZALO_NEW_REGION_PROVINCE_CODES,
|
|
7495
|
+
ZALO_PROVINCE_MERGE_MAPPING,
|
|
7496
|
+
ZALO_REGION_PROVINCE_CODES,
|
|
6587
7497
|
ZaloAccountService,
|
|
6588
7498
|
ZaloAdsAccountPool,
|
|
6589
7499
|
ZaloAdsActionType,
|
|
6590
7500
|
ZaloAdsAgeRangeId,
|
|
7501
|
+
ZaloAdsBudgetScheduleType,
|
|
7502
|
+
ZaloAdsCampaignStatus,
|
|
6591
7503
|
ZaloAdsCreateFlowRequest,
|
|
6592
7504
|
ZaloAdsCreateFlowResponse,
|
|
6593
7505
|
ZaloAdsCreatePostCampaignRequest,
|
|
@@ -6596,28 +7508,40 @@ var ZaloInstantPageBlockType = /* @__PURE__ */ ((ZaloInstantPageBlockType2) => {
|
|
|
6596
7508
|
ZaloAdsFlowButtonDto,
|
|
6597
7509
|
ZaloAdsFlowChildMessageDto,
|
|
6598
7510
|
ZaloAdsFlowMessageDto,
|
|
7511
|
+
ZaloAdsImageRatio,
|
|
6599
7512
|
ZaloAdsIntegrationManager,
|
|
6600
7513
|
ZaloAdsMessageAdUpdateDataDto,
|
|
6601
7514
|
ZaloAdsOsId,
|
|
7515
|
+
ZaloAdsPriceLimitType,
|
|
7516
|
+
ZaloAdsPriceType,
|
|
7517
|
+
ZaloAdsProvinceCode,
|
|
7518
|
+
ZaloAdsRegionId,
|
|
6602
7519
|
ZaloAdsSdk,
|
|
6603
7520
|
ZaloAdsService,
|
|
7521
|
+
ZaloAdsSpendingMethod,
|
|
6604
7522
|
ZaloAdsUpdateMessageAdRequest,
|
|
6605
7523
|
ZaloAdsUpdateMessageAdResponse,
|
|
6606
7524
|
ZaloAdsUpdateVideoAdRequest,
|
|
6607
7525
|
ZaloAdsUpdateVideoAdResponse,
|
|
7526
|
+
ZaloAdsUseConversion,
|
|
7527
|
+
ZaloAdsVideoSrc,
|
|
7528
|
+
ZaloAdsXTemplates,
|
|
6608
7529
|
ZaloAudiencesService,
|
|
6609
7530
|
ZaloAudiencesValidator,
|
|
6610
7531
|
ZaloAuthManager,
|
|
6611
7532
|
ZaloAutomatedRulesService,
|
|
7533
|
+
ZaloAutomatedRulesValidator,
|
|
6612
7534
|
ZaloCampaignsService,
|
|
6613
7535
|
ZaloCampaignsValidator,
|
|
6614
7536
|
ZaloChatWidgetService,
|
|
6615
7537
|
ZaloConversionsService,
|
|
7538
|
+
ZaloConversionsValidator,
|
|
6616
7539
|
ZaloFlowsService,
|
|
6617
7540
|
ZaloFlowsValidator,
|
|
6618
7541
|
ZaloFormsService,
|
|
6619
7542
|
ZaloFormsValidator,
|
|
6620
7543
|
ZaloInstantPageBlockType,
|
|
7544
|
+
ZaloInstantPageSharePermission,
|
|
6621
7545
|
ZaloInstantPagesService,
|
|
6622
7546
|
ZaloInstantPagesValidator,
|
|
6623
7547
|
ZaloMediaService,
|
|
@@ -6638,6 +7562,7 @@ var ZaloInstantPageBlockType = /* @__PURE__ */ ((ZaloInstantPageBlockType2) => {
|
|
|
6638
7562
|
validateCreateFlowRequest,
|
|
6639
7563
|
validateCreateFormEventAudienceRequest,
|
|
6640
7564
|
validateCreateFormRequest,
|
|
7565
|
+
validateCreateInstantPageRequest,
|
|
6641
7566
|
validateCreateLookalikeAudienceRequest,
|
|
6642
7567
|
validateCreateMessageOaEventAudienceRequest,
|
|
6643
7568
|
validateCreateMessagePersonalEventAudienceRequest,
|