@warriorteam/redai-zalo-sdk
Version:
Comprehensive TypeScript/JavaScript SDK for Zalo APIs - Official Account, ZNS, Consultation Service, Group Messaging, and Social APIs
247 lines • 10.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.PromotionService = void 0;
const common_1 = require("../types/common");
/**
* Service xử lý các API tin nhắn truyền thông/quảng cáo của Zalo Official Account
*
* ĐIỀU KIỆN GỬI TIN TRUYỀN THÔNG:
*
* 1. THỜI GIAN GỬI:
* - Chỉ được gửi trong khung giờ từ 8:00 - 22:00 hàng ngày
* - Không được gửi vào các ngày lễ, tết theo quy định
*
* 2. NỘI DUNG TIN NHẮN:
* - Phải là nội dung quảng cáo, khuyến mãi, tin tức
* - Không được chứa nội dung vi phạm pháp luật
* - Phải tuân thủ quy định về quảng cáo của Việt Nam
*
* 3. TẦN SUẤT GỬI:
* - Tối đa 1 tin nhắn truyền thông/ngày cho mỗi người dùng
* - Người dùng có thể từ chối nhận tin truyền thông
*
* 4. ĐỊNH DẠNG:
* - Phải sử dụng template được Zalo phê duyệt trước
* - Template phải tuân thủ format chuẩn của tin truyền thông
*
* 5. NGƯỜI DÙNG:
* - Người dùng phải đã follow OA
* - Người dùng không được block OA
* - Người dùng không được từ chối nhận tin truyền thông
*
* 6. OFFICIAL ACCOUNT:
* - OA phải được xác minh (verified)
* - OA phải có quyền gửi tin truyền thông được Zalo cấp phép
* - OA không được vi phạm chính sách về quảng cáo
*
* LỖI THƯỜNG GẶP:
* - 2001: Ngoài khung giờ cho phép (8:00-22:00)
* - 2002: Người dùng đã từ chối nhận tin truyền thông
* - 2003: Vượt quá giới hạn 1 tin/ngày
* - 2004: Template chưa được phê duyệt
* - 2005: Nội dung vi phạm chính sách quảng cáo
* - 2006: OA chưa có quyền gửi tin truyền thông
*/
class PromotionService {
constructor(client) {
this.client = client;
this.promotionApiUrl = "https://openapi.zalo.me/v2.0/oa/message/promotion";
}
/**
* Gửi tin nhắn truyền thông/quảng cáo
* @param accessToken Access token của Official Account
* @param recipient Thông tin người nhận
* @param message Nội dung tin nhắn truyền thông
* @returns Thông tin tin nhắn đã gửi
*/
async sendPromotionMessage(accessToken, recipient, message) {
try {
// Validate promotion message
this.validatePromotionMessage(message);
// Check sending time (8:00 - 22:00)
this.validateSendingTime();
const request = {
recipient,
message,
};
const result = await this.client.apiPost(this.promotionApiUrl, accessToken, request);
if (result.error !== 0) {
throw new common_1.ZaloSDKError(result.message || "Failed to send promotion message", result.error, result);
}
if (!result.data) {
throw new common_1.ZaloSDKError("No response data received", -1);
}
return result.data;
}
catch (error) {
if (error instanceof common_1.ZaloSDKError) {
throw error;
}
throw new common_1.ZaloSDKError(`Failed to send promotion message: ${error.message}`, -1, error);
}
}
/**
* Gửi tin nhắn khuyến mãi sản phẩm
* @param accessToken Access token của Official Account
* @param recipient Thông tin người nhận
* @param promotionInfo Thông tin khuyến mãi
* @returns Thông tin tin nhắn đã gửi
*/
async sendProductPromotion(accessToken, recipient, promotionInfo) {
try {
const message = {
type: "promotion",
attachment: {
type: "template",
payload: {
template_type: "promotion",
elements: [
{
title: promotionInfo.title,
subtitle: promotionInfo.description,
image_url: promotionInfo.imageUrl,
default_action: {
type: "web_url",
url: promotionInfo.productUrl,
},
buttons: [
{
type: "web_url",
title: "Mua ngay",
url: promotionInfo.productUrl,
},
{
type: "postback",
title: "Xem thêm",
payload: `VIEW_PRODUCT_${Date.now()}`,
},
],
},
],
},
},
};
return this.sendPromotionMessage(accessToken, recipient, message);
}
catch (error) {
throw new common_1.ZaloSDKError(`Failed to send product promotion: ${error.message}`, -1, error);
}
}
/**
* Gửi tin nhắn thông báo sự kiện
* @param accessToken Access token của Official Account
* @param recipient Thông tin người nhận
* @param eventInfo Thông tin sự kiện
* @returns Thông tin tin nhắn đã gửi
*/
async sendEventNotification(accessToken, recipient, eventInfo) {
try {
const message = {
type: "promotion",
attachment: {
type: "template",
payload: {
template_type: "promotion",
elements: [
{
title: eventInfo.title,
subtitle: `${eventInfo.description}\n📅 ${eventInfo.eventDate}\n📍 ${eventInfo.location}`,
image_url: eventInfo.imageUrl,
default_action: {
type: "web_url",
url: eventInfo.registrationUrl,
},
buttons: [
{
type: "web_url",
title: "Đăng ký tham gia",
url: eventInfo.registrationUrl,
},
{
type: "postback",
title: "Chia sẻ",
payload: `SHARE_EVENT_${Date.now()}`,
},
],
},
],
},
},
};
return this.sendPromotionMessage(accessToken, recipient, message);
}
catch (error) {
throw new common_1.ZaloSDKError(`Failed to send event notification: ${error.message}`, -1, error);
}
}
/**
* Gửi tin nhắn newsletter
* @param accessToken Access token của Official Account
* @param recipient Thông tin người nhận
* @param newsletterInfo Thông tin newsletter
* @returns Thông tin tin nhắn đã gửi
*/
async sendNewsletter(accessToken, recipient, newsletterInfo) {
try {
const message = {
type: "promotion",
attachment: {
type: "template",
payload: {
template_type: "promotion",
elements: [
{
title: newsletterInfo.title,
subtitle: newsletterInfo.summary,
image_url: newsletterInfo.imageUrl,
buttons: [
{
type: "web_url",
title: "Đọc toàn bộ",
url: newsletterInfo.articles[0]?.url || "#",
},
{
type: "web_url",
title: "Hủy đăng ký",
url: newsletterInfo.unsubscribeUrl,
},
],
},
],
},
},
};
return this.sendPromotionMessage(accessToken, recipient, message);
}
catch (error) {
throw new common_1.ZaloSDKError(`Failed to send newsletter: ${error.message}`, -1, error);
}
}
/**
* Validate promotion message format
* @param message Promotion message to validate
*/
validatePromotionMessage(message) {
if (!message.attachment) {
throw new common_1.ZaloSDKError("Promotion message must have attachment", -1);
}
if (!message.attachment.payload) {
throw new common_1.ZaloSDKError("Promotion message attachment must have payload", -1);
}
if (message.attachment.payload.template_type !== "promotion") {
throw new common_1.ZaloSDKError("Promotion message must use promotion template type", -1);
}
}
/**
* Validate sending time (8:00 - 22:00)
*/
validateSendingTime() {
const now = new Date();
const hour = now.getHours();
if (hour < 8 || hour >= 22) {
throw new common_1.ZaloSDKError("Tin nhắn truyền thông chỉ được gửi trong khung giờ từ 8:00 - 22:00", 2001);
}
}
}
exports.PromotionService = PromotionService;
//# sourceMappingURL=promotion.service.js.map