@warriorteam/redai-zalo-sdk
Version:
Comprehensive TypeScript/JavaScript SDK for Zalo APIs - Official Account, ZNS, Consultation Service, Group Messaging, and Social APIs
605 lines (467 loc) β’ 16.9 kB
Markdown
# RedAI Zalo SDK
A comprehensive TypeScript/JavaScript SDK for Zalo APIs, providing easy-to-use interfaces for:
- **Official Account (OA) API** - Manage your Zalo Official Account
- **Consultation Service** - Send customer support messages within 48-hour window
- **Zalo Notification Service (ZNS)** - Send template-based notification messages
- **Social API** - Access user social information and authentication
- **Group Message Framework (GMF)** - Send messages to Zalo groups
- **User Management** - Comprehensive user profile and tag management
- **Content Management** - Upload and manage media content (images, files, articles)
- **Video Upload** - Upload and manage video content with processing
- **Tag Management** - User tagging and segmentation
- **Webhook handling** - Process Zalo webhook events
## Features
- π **TypeScript Support** - Full type safety and IntelliSense
- π **OAuth 2.0 Flow** - Complete authentication handling
- π **Auto Retry** - Built-in retry mechanism for failed requests
- π **Comprehensive Logging** - Debug and monitor API calls
- π‘οΈ **Error Handling** - Detailed error information and handling
- π¦ **Zero Dependencies** - Only requires axios and form-data
- π― **Promise-based** - Modern async/await support
## Installation
```bash
npm install @warriorteam/redai-zalo-sdk
```
## π¨ Version 1.9.0 - Breaking Changes
**ZNS Template API has been completely restructured to match Zalo API 100%**
### What Changed:
- β
**Fixed**: All ZNS template interfaces now match official Zalo API docs
- β
**Added**: Proper `layout` structure with header/body/footer components
- β
**Added**: Complete enum support for template types, tags, buttons, and params
- β
**Added**: Validation helpers and constants
- β **Removed**: Non-existent fields like `templateContent`, `timeout`, `previewUrl`
- π **Changed**: Field names from camelCase to snake_case (e.g., `templateId` β `template_id`)
### Migration Required:
```typescript
// β Before v1.9.0 (BROKEN)
const templateData = {
templateId: "123",
templateContent: "Hello" // Field doesn't exist in Zalo API
};
// β
After v1.9.0 (CORRECT)
import { ZNSTemplateType, ZNSTemplateTag } from '@warriorteam/redai-zalo-sdk';
const templateData = {
template_id: "123",
template_name: "My Template",
template_type: ZNSTemplateType.CUSTOM,
tag: ZNSTemplateTag.TRANSACTION,
layout: {
body: {
components: [{ TITLE: { value: "Hello" } }]
}
},
tracking_id: "track_001"
};
```
See [CHANGELOG.md](./CHANGELOG.md) for complete migration guide.
## π Documentation
### π Getting Started
- **[API Reference](./docs/API_REFERENCE.md)** - Complete API documentation and method reference
- **[Authentication Guide](./docs/AUTHENTICATION.md)** - OAuth 2.0 flows for OA and Social APIs
- **[Architecture Overview](./ARCHITECTURE.md)** - SDK architecture and design patterns
- **[Services Added](./SERVICES_ADDED.md)** - Detailed breakdown of all services and features
### π¨ Messaging & Communication
- **[Message Services](./docs/MESSAGE_SERVICES.md)** - Complete guide for all message types and services
- **[Consultation Service](./docs/CONSULTATION_SERVICE.md)** - Customer service messaging guide
- **[ZNS Service](./docs/ZNS_SERVICE.md)** - Zalo Notification Service for template messages
- **[Group Management](./docs/GROUP_MANAGEMENT.md)** - Group messaging and management
### π₯ User & Content Management
- **[User Management](./docs/USER_MANAGEMENT.md)** - User profiles, followers, and management
- **[Tag Management](./docs/TAG_MANAGEMENT.md)** - User tagging and segmentation system
- **[Article Management](./docs/ARTICLE_MANAGEMENT.md)** - Content and article management
- **[Webhook Types (Source of Truth)](./src/types/webhook.ts)** - Strongly-typed webhook event definitions
### π Events & Integration
- **[Webhook Events Guide](./docs/WEBHOOK_EVENTS.md)** - Complete guide for all 70+ webhook event types
## Development
### Build from source
```bash
# Clone the repository
git clone https://github.com/redai/redai-zalo-sdk.git
cd redai-zalo-sdk
# Install dependencies
npm install
# Build the SDK
npm run build
# Run examples
npm run dev
```
## Quick Start
### Initialize the SDK
```typescript
import { ZaloSDK } from "@warriorteam/redai-zalo-sdk";
const zalo = new ZaloSDK({
appId: "your-app-id",
appSecret: "your-app-secret",
debug: true, // Enable debug logging
});
```
### Authentication Flow
#### Official Account (OA) Authentication
```typescript
// 1. Create authorization URL
const authUrl = zalo.createOAAuthUrl("https://your-app.com/callback");
console.log("Visit:", authUrl);
// 2. Exchange authorization code for access token
const accessToken = await zalo.getOAAccessToken(
"authorization-code-from-callback",
"https://your-app.com/callback"
);
console.log("Access Token:", accessToken.access_token);
```
#### Social API Authentication
```typescript
// 1. Generate PKCE for security (recommended)
const pkce = zalo.generatePKCE();
// 2. Create authorization URL
const authUrl = zalo.createSocialAuthUrl("https://your-app.com/callback");
// 3. Exchange code for access token
const accessToken = await zalo.getSocialAccessToken(
"authorization-code",
"https://your-app.com/callback",
pkce.code_verifier
);
```
### Official Account Operations
```typescript
// Get OA information
const oaInfo = await zalo.getOAInfo(accessToken.access_token);
console.log("OA Name:", oaInfo.name);
console.log("Followers:", oaInfo.num_follower);
// Check message quota
const quota = await zalo.getMessageQuota(accessToken.access_token);
console.log("Daily Quota:", quota.daily_quota);
console.log("Remaining:", quota.remaining_quota);
// Get detailed quota information
const detailedQuota = await zalo.oa.getQuotaSummary(accessToken.access_token);
console.log("Consultation Quota:", detailedQuota.consultation);
console.log("Transaction Quota:", detailedQuota.transaction);
```
### Social API Operations
```typescript
// Get user information
const userInfo = await zalo.getSocialUserInfo(
accessToken.access_token,
"id,name,picture,birthday"
);
console.log("User ID:", userInfo.id);
console.log("Name:", userInfo.name);
console.log("Avatar:", userInfo.picture?.data.url);
```
### Token Management
```typescript
// Refresh OA access token
const newOAToken = await zalo.refreshOAAccessToken(refreshToken);
// Refresh Social access token
const newSocialToken = await zalo.refreshSocialAccessToken(refreshToken);
// Validate token
const isValid = await zalo.validateAccessToken(accessToken.access_token, "oa");
```
## Advanced Usage
### Custom API Requests
```typescript
// Make custom API calls
const customData = await zalo.customRequest(
"POST",
"/v3.0/oa/message/cs",
accessToken.access_token,
{
recipient: { user_id: "user-id" },
message: { text: "Hello from SDK!" },
}
);
```
### File Upload
```typescript
import fs from "fs";
// Upload image
const fileBuffer = fs.readFileSync("image.jpg");
const uploadResult = await zalo.uploadFile(
"/v2.0/oa/upload/image",
accessToken.access_token,
fileBuffer,
"image.jpg"
);
console.log("Uploaded URL:", uploadResult.data.url);
```
### Error Handling
```typescript
import { ZaloSDKError } from "redai-zalo-sdk";
try {
const oaInfo = await zalo.getOAInfo(accessToken.access_token);
} catch (error) {
if (error instanceof ZaloSDKError) {
console.error("Zalo API Error:", error.message);
console.error("Error Code:", error.code);
console.error("Details:", error.details);
} else {
console.error("Unexpected error:", error);
}
}
```
## Configuration Options
```typescript
const zalo = new ZaloSDK({
appId: "your-app-id",
appSecret: "your-app-secret",
// Optional configurations
timeout: 30000, // Request timeout in ms (default: 30000)
debug: false, // Enable debug logging (default: false)
apiBaseUrl: "https://openapi.zalo.me", // Custom API base URL
// Retry configuration
retry: {
attempts: 3, // Number of retry attempts (default: 3)
delay: 1000, // Delay between retries in ms (default: 1000)
},
});
```
## API Reference
### ZaloSDK Class
#### Constructor
- `new ZaloSDK(config: ZaloSDKConfig)`
#### Authentication Methods
- `createOAAuthUrl(redirectUri: string, state?: string): string`
- `createSocialAuthUrl(redirectUri: string, state?: string): string`
- `getOAAccessToken(code: string, redirectUri: string): Promise<AccessToken>`
- `getSocialAccessToken(code: string, redirectUri: string, codeVerifier?: string): Promise<AccessToken>`
- `refreshOAAccessToken(refreshToken: string): Promise<AccessToken>`
- `refreshSocialAccessToken(refreshToken: string): Promise<AccessToken>`
#### OA Methods
- `getOAInfo(accessToken: string): Promise<OAInfo>`
- `getMessageQuota(accessToken: string): Promise<MessageQuota>`
#### Social Methods
- `getSocialUserInfo(accessToken: string, fields?: string): Promise<SocialUserInfo>`
#### Utility Methods
- `validateAccessToken(accessToken: string, scope?: 'oa' | 'social'): Promise<boolean>`
- `generatePKCE(): PKCEConfig`
- `testConnection(): Promise<boolean>`
### Services
#### AuthService
- Complete OAuth 2.0 flow handling
- PKCE support for Social API
- Token validation and refresh
#### OAService
- Official Account information management
- Quota monitoring and management
- Profile updates
## Error Handling
The SDK throws `ZaloSDKError` for all Zalo API related errors:
```typescript
class ZaloSDKError extends Error {
code: number; // Zalo API error code
details?: any; // Additional error details
}
```
Common error codes:
- `-216`: Invalid access token
- `-201`: Invalid parameters
- `-223`: Quota exceeded
## TypeScript Support
The SDK is written in TypeScript and provides comprehensive type definitions:
```typescript
import {
ZaloSDK,
ZaloSDKConfig,
AccessToken,
OAInfo,
SocialUserInfo,
ZaloSDKError,
} from "redai-zalo-sdk";
```
## Contributing
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Support
For support and questions:
- Create an issue on GitHub
- Contact RedAI team
### Consultation Service (Customer Support)
```typescript
// Send consultation text message
await zalo.consultation.sendTextMessage(accessToken,
{ user_id: "user-id" },
{
type: "text",
text: "Xin chà o! Tôi có thỠhỠtrợ gì cho bẑn?"
}
);
// Send consultation image with guide
await zalo.consultation.sendImageMessage(accessToken,
{ user_id: "user-id" },
{
type: "image",
attachment: {
type: "image",
payload: {
url: "https://example.com/support-guide.jpg"
}
}
}
);
// Send file attachment for support
await zalo.consultation.sendFileMessage(accessToken,
{ user_id: "user-id" },
{
type: "file",
url: "https://example.com/manual.pdf",
filename: "User Manual.pdf",
attachment: {
type: "file",
payload: {
url: "https://example.com/manual.pdf"
}
}
}
);
```
### ZNS (Zalo Notification Service)
```typescript
// Send ZNS notification
await zalo.zns.sendMessage(accessToken, {
phone: "0123456789",
template_id: "your-template-id",
template_data: {
customer_name: "John Doe",
order_id: "12345",
},
});
// Get ZNS quota
const quota = await zalo.zns.getQuotaInfo(accessToken);
// Manage ZNS templates
const templates = await zalo.zns.getTemplateList(accessToken);
const template = await zalo.zns.createTemplate(accessToken, {
templateName: "Order Confirmation",
templateContent:
"Hello {{customer_name}}, your order {{order_id}} is confirmed.",
templateType: 3, // Confirmation type
});
```
### Group Messaging
```typescript
// Send text message to group
await zalo.groupMessage.sendTextMessage(accessToken, groupId, {
type: "text",
text: "Hello everyone!",
});
// Send image to group
await zalo.groupMessage.sendImageMessage(accessToken, groupId, {
type: "image",
imageUrl: "https://example.com/image.jpg",
caption: "Check this out!",
});
// Get group information
const groupInfo = await zalo.groupMessage.getGroupInfo(accessToken, groupId);
const members = await zalo.groupMessage.getGroupMembers(accessToken, groupId);
```
### User Management
```typescript
// Get user profile
const profile = await zalo.userManagement.getUserProfile(accessToken, userId);
// Tag management
await zalo.tag.createTag(accessToken, "VIP Customer");
await zalo.tag.tagUser(accessToken, userId, ["VIP Customer", "Premium"]);
const userTags = await zalo.tag.getUserTags(accessToken, userId);
// Get followers list
const followers = await zalo.userManagement.getFollowersList(accessToken);
```
### Content Management
```typescript
// Upload image
const imageResult = await zalo.content.uploadImage(accessToken, imageBuffer);
// Create article
const article = await zalo.content.createArticle(accessToken, {
title: "Welcome to our service",
body: "Article content here...",
cover_photo_id: imageResult.data.attachment_id,
});
// Share article to user
await zalo.content.shareArticle(accessToken, userId, article.data.id);
```
### Video Upload
```typescript
// Upload video
const uploadResult = await zalo.videoUpload.uploadVideo(
accessToken,
videoBuffer,
"video.mp4"
);
// Wait for processing completion
const finalResult = await zalo.videoUpload.waitForUploadCompletion(
accessToken,
uploadResult.data.token
);
if (finalResult.status === "ready") {
// Send video message
await zalo.videoUpload.sendVideoMessage(
accessToken,
userId,
finalResult.attachment_id,
"Check out this video!"
);
}
```
### Social API
```typescript
// Get user social information
const userInfo = await zalo.social.getUserInfo(accessToken);
// Get friends list
const friends = await zalo.social.getFriendsList(accessToken);
// Post to timeline
await zalo.social.postToTimeline(accessToken, "Hello from Zalo SDK!");
```
## π Webhook Events
The SDK provides comprehensive webhook event handling with **70+ event types**:
```typescript
import { WebhookHandlers } from "@warriorteam/redai-zalo-sdk";
const handlers: WebhookHandlers = {
// User message events
user_send_text: async (event) => {
console.log("User sent:", event.message.text);
},
// Group events
user_send_group_audio: async (event) => {
console.log("Audio in group:", event.message.attachments[0].payload.url);
},
// ZNS events
change_template_status: async (event) => {
console.log("Template status:", event.status);
},
// Widget events
widget_interaction_accepted: async (event) => {
console.log("Widget accepted:", event.data.user_external_id);
},
// System events
permission_revoked: async (event) => {
console.log("Permission revoked by:", event.data.action_by);
},
};
```
### Event Categories:
- **User Message Events** (11 types): text, image, video, audio, file, sticker, gif, location, link, business card, reaction
- **OA Message Events** (11 types): All message types + anonymous + template
- **Group Events** (22 types): Create, join, admin, leave + all message types for both user and OA
- **ZNS Events** (8 types): Quota, template, journey, delivery, status changes
- **Widget Events** (2 types): Interaction accepted, sync failures
- **System Events** (4 types): Permission, extension, user info, tags
- **Call Events** (2 types): OA call user, user call OA
- **Anonymous Events** (4 types): Anonymous chat support
- **Shop Events** (1 type): Order management
For complete webhook documentation, see [Webhook Events Guide](./docs/WEBHOOK_EVENTS.md).
## Changelog
### v1.0.0
- Initial release
- Official Account API support
- ZNS (Zalo Notification Service) support
- Group Message Framework (GMF) support
- Social API support
- User Management features
- Content and Video Upload capabilities
- Tag Management system
- Comprehensive webhook handling
- Social API support
- Authentication flow
- TypeScript support