@warriorteam/redai-zalo-sdk
Version:
Comprehensive TypeScript/JavaScript SDK for Zalo APIs - Official Account, ZNS, Consultation Service, Group Messaging, and Social APIs
482 lines (384 loc) • 13.7 kB
Markdown
# User Management - Hướng Dẫn Sử Dụng
## Tổng Quan
`UserService` cung cấp các công cụ toàn diện để quản lý người dùng Zalo Official Account, bao gồm:
- 👥 **User Information** - Lấy thông tin chi tiết người dùng
- 📋 **User Lists** - Quản lý danh sách người dùng với phân trang
- 🏷️ **Tag Management** - Gắn và quản lý tags cho users
- 📊 **Custom Info** - Quản lý thông tin tùy chỉnh
- 🔄 **Bulk Operations** - Xử lý hàng loạt users
**Endpoints sử dụng:**
- User Info: `https://openapi.zalo.me/v3.0/oa/user/detail`
- User List: `https://openapi.zalo.me/v3.0/oa/user/getlist`
- Update User: `https://openapi.zalo.me/v3.0/oa/user/update`
- Custom Info: `https://openapi.zalo.me/v3.0/oa/user/getcustominfo`
- Tags: `https://openapi.zalo.me/v3.0/oa/tag/gettagsofoa`
## Khởi Tạo Service
```typescript
import { UserService } from "@warriorteam/redai-zalo-sdk";
import { ZaloClient } from "@warriorteam/redai-zalo-sdk";
const client = new ZaloClient();
const userService = new UserService(client);
```
## Các Phương Thức Chính
### 1. Lấy Thông Tin User Chi Tiết
```typescript
// Lấy thông tin chi tiết của một user
const userInfo = await userService.getUserInfo(
accessToken,
"user-id-here"
);
console.log("User Info:", {
userId: userInfo.user_id,
displayName: userInfo.display_name,
avatar: userInfo.avatar,
userGender: userInfo.user_gender,
userAlias: userInfo.user_alias,
isFollower: userInfo.is_follower,
sharedInfo: userInfo.shared_info
});
```
**Tham số:**
- `accessToken`: Access token của OA
- `userId`: ID người dùng cần lấy thông tin
### 2. Lấy Danh Sách Users
```typescript
// Lấy danh sách users với filter
const userList = await userService.getUserList(accessToken, {
offset: 0,
count: 50,
tag_name: "VIP_CUSTOMER", // Lọc theo tag (tùy chọn)
is_follower: true, // Chỉ lấy followers (tùy chọn)
last_interaction_period: "L7D" // Tương tác trong 7 ngày qua
});
console.log("Total users:", userList.total);
console.log("Count:", userList.count);
console.log("Offset:", userList.offset);
userList.users.forEach(user => {
console.log(`${user.display_name} - ${user.user_id}`);
});
```
**Tham số:**
- `offset`: Vị trí bắt đầu (0-based)
- `count`: Số lượng users mỗi page (tối đa 50)
- `tag_name`: Lọc theo tag (tùy chọn)
- `is_follower`: true/false để lọc followers
- `last_interaction_period`: "TODAY", "YESTERDAY", "L7D", "L30D"
### 3. Lấy Tất Cả Users (Auto Pagination)
```typescript
// Lấy tất cả users với phân trang tự động
const allUsers = await userService.getAllUsers(accessToken, {
is_follower: true,
tag_name: "PREMIUM"
});
console.log(`Total users fetched: ${allUsers.length}`);
```
**Lưu ý:**
- Zalo giới hạn max offset = 9951 (tương ứng ~10000 users)
- Method này tự động handle pagination và warning khi vượt giới hạn
### 4. Lấy Danh Sách User IDs (Tối Ưu)
```typescript
// Chỉ lấy user IDs, không lấy thông tin chi tiết (nhanh hơn)
const userIds = await userService.getAllUserIds(accessToken, {
is_follower: true
});
console.log(`Total user IDs: ${userIds.length}`);
```
### 5. Helper Methods
```typescript
// Lấy chỉ followers
const followers = await userService.getFollowers(accessToken, 0, 50);
// Lấy users theo tag
const vipUsers = await userService.getUsersByTag(accessToken, "VIP", 0, 50);
// Lấy users theo thời gian tương tác
const recentUsers = await userService.getUsersByInteraction(
accessToken,
"L7D", // 7 ngày qua
0,
50
);
```
## User Management Operations
### 6. Cập Nhật Thông Tin User
```typescript
// Cập nhật thông tin user
const success = await userService.updateUser(accessToken, {
user_id: "user-id-here",
notes: "Customer quan tâm sản phẩm cao cấp",
// Các field khác có thể cập nhật
});
console.log("Update success:", success);
```
### 7. Xóa Thông Tin User
```typescript
// Xóa thông tin user khỏi OA (không ảnh hưởng tài khoản Zalo)
const success = await userService.deleteUserInfo(accessToken, "user-id-here");
console.log("Delete success:", success);
```
### 8. Quản Lý Custom Info
```typescript
// Lấy custom info của user
const customInfo = await userService.getUserCustomInfo(accessToken, {
user_id: "user-id-here",
fields_to_export: ["customer_tier", "total_spent"] // Tùy chọn
});
console.log("Custom Info:", customInfo.custom_info);
// Cập nhật custom info
const updateSuccess = await userService.updateUserCustomInfo(accessToken, {
user_id: "user-id-here",
custom_info: {
customer_tier: "VIP",
total_spent: "10000000",
last_purchase: "2024-12-01"
}
});
```
**Lưu ý:** Cấu trúc `custom_info` phụ thuộc vào thiết lập OA
## Tag Management
### 9. Quản Lý Tags
```typescript
// Lấy danh sách tất cả tags của OA
const tags = await userService.getLabels(accessToken);
console.log("Available tags:", tags);
// Thêm tag cho user
const addSuccess = await userService.addTagToUser(accessToken, {
user_id: "user-id-here",
tag_name: "VIP_CUSTOMER"
});
// Xóa tag khỏi user
const removeSuccess = await userService.removeTagFromUser(accessToken, {
user_id: "user-id-here",
tag_name: "OLD_TAG"
});
// Xóa tag khỏi OA (xóa hoàn toàn)
const deleteSuccess = await userService.deleteLabel(accessToken, "UNUSED_TAG");
```
### 10. Bulk Operations
```typescript
// Bulk add tag cho nhiều users
const bulkAddResult = await userService.bulkAddTag(
accessToken,
["user1", "user2", "user3"],
"FLASH_SALE_2024"
);
console.log("Success:", bulkAddResult.success);
console.log("Failed:", bulkAddResult.failed);
// Bulk remove tag
const bulkRemoveResult = await userService.bulkRemoveTag(
accessToken,
["user1", "user2", "user3"],
"OLD_CAMPAIGN"
);
```
## API Methods Summary
| Method | Description | Parameters |
|--------|-------------|------------|
| `getUserInfo` | Lấy thông tin chi tiết user | `accessToken`, `userId` |
| `getUserList` | Lấy danh sách users với pagination | `accessToken`, `request` |
| `getAllUsers` | Lấy tất cả users (auto pagination) | `accessToken`, `filters?` |
| `getAllUserIds` | Lấy tất cả user IDs (tối ưu) | `accessToken`, `filters?` |
| `updateUser` | Cập nhật thông tin user | `accessToken`, `request` |
| `deleteUserInfo` | Xóa thông tin user | `accessToken`, `userId` |
| `getUserCustomInfo` | Lấy custom info | `accessToken`, `request` |
| `updateUserCustomInfo` | Cập nhật custom info | `accessToken`, `request` |
| `getLabels` | Lấy danh sách tags | `accessToken` |
| `addTagToUser` | Thêm tag cho user | `accessToken`, `request` |
| `removeTagFromUser` | Xóa tag khỏi user | `accessToken`, `request` |
| `deleteLabel` | Xóa tag khỏi OA | `accessToken`, `tagName` |
| `getUsersByTag` | Lấy users theo tag | `accessToken`, `tagName`, `offset?`, `count?` |
| `getFollowers` | Lấy chỉ followers | `accessToken`, `offset?`, `count?` |
| `getUsersByInteraction` | Lấy users theo thời gian tương tác | `accessToken`, `period`, `offset?`, `count?` |
| `bulkAddTag` | Bulk add tag | `accessToken`, `userIds`, `tagName` |
| `bulkRemoveTag` | Bulk remove tag | `accessToken`, `userIds`, `tagName` |
## Ví Dụ Thực Tế
### 1. Customer Support System
```typescript
class CustomerSupportSystem {
constructor(private userService: UserService, private accessToken: string) {}
async handleNewCustomer(userId: string) {
// Lấy thông tin customer
const userInfo = await this.userService.getUserInfo(this.accessToken, userId);
// Thêm tag "NEW_CUSTOMER"
await this.userService.addTagToUser(this.accessToken, {
user_id: userId,
tag_name: "NEW_CUSTOMER"
});
// Cập nhật custom info
await this.userService.updateUserCustomInfo(this.accessToken, {
user_id: userId,
custom_info: {
registration_date: new Date().toISOString(),
customer_tier: "STANDARD",
total_interactions: "1"
}
});
console.log(`New customer ${userInfo.display_name} processed`);
}
async promoteToVIP(userId: string) {
// Remove old tags
await this.userService.removeTagFromUser(this.accessToken, {
user_id: userId,
tag_name: "STANDARD"
});
// Add VIP tag
await this.userService.addTagToUser(this.accessToken, {
user_id: userId,
tag_name: "VIP"
});
// Update custom info
await this.userService.updateUserCustomInfo(this.accessToken, {
user_id: userId,
custom_info: {
customer_tier: "VIP",
promotion_date: new Date().toISOString()
}
});
}
}
}
```
### 2. Bulk Campaign System
```typescript
class BulkCampaignSystem {
constructor(private userService: UserService, private accessToken: string) {}
async runSegmentedCampaign(campaignConfig: {
segments: string[];
message: string;
batchSize?: number;
}) {
const results = {
totalSent: 0,
totalFailed: 0,
segmentResults: new Map<string, any>()
};
for (const segment of campaignConfig.segments) {
console.log(`Processing segment: ${segment}`);
// Get users by tag
const users = await this.userService.getUsersByTag(
this.accessToken,
segment,
0,
1000
);
// Bulk add campaign tag
const userIds = users.users.map(u => u.user_id);
const bulkResult = await this.userService.bulkAddTag(
this.accessToken,
userIds,
`CAMPAIGN_${Date.now()}`
);
results.segmentResults.set(segment, {
totalUsers: users.total,
tagged: bulkResult.success.length,
failed: bulkResult.failed.length
});
results.totalSent += bulkResult.success.length;
results.totalFailed += bulkResult.failed.length;
}
return results;
}
}
```
## Error Handling
```typescript
import { ZaloSDKError } from "@warriorteam/redai-zalo-sdk";
try {
const userInfo = await userService.getUserInfo(accessToken, "user-id");
console.log("User found:", userInfo.display_name);
} catch (error) {
if (error instanceof ZaloSDKError) {
switch (error.code) {
case -216:
console.error("Access token không hợp lệ");
break;
case -233:
console.error("User không tồn tại hoặc đã unfollow");
break;
case -201:
console.error("Tham số không hợp lệ");
break;
default:
console.error("Lỗi khác:", error.message);
}
} else {
console.error("Unexpected error:", error);
}
}
```
## Giới Hạn API
### Zalo API Limits
1. **User List Pagination**:
- Max offset: 9951
- Max count per request: 50
- Tối đa ~10000 users có thể lấy được
2. **Rate Limiting**:
- Nên có delay giữa các requests
- Sử dụng batch operations khi có thể
3. **Custom Info**:
- Cấu trúc phụ thuộc vào thiết lập OA
- Tất cả giá trị đều là string
## Best Practices
### 1. Performance Optimization
```typescript
// ✅ Sử dụng getAllUserIds cho performance tốt hơn
const userIds = await userService.getAllUserIds(accessToken);
// ✅ Batch operations
const bulkResult = await userService.bulkAddTag(
accessToken,
userIds.slice(0, 100),
"NEW_TAG"
);
// ✅ Pagination với reasonable page size
const users = await userService.getUserList(accessToken, {
offset: 0,
count: 50 // Không quá 50
});
```
### 2. Error Handling
```typescript
// ✅ Validate user ID format
function validateUserId(userId: string): boolean {
return /^[0-9]+$/.test(userId) && userId.length > 0;
}
// ✅ Safe operations
async function safeGetUser(userId: string) {
if (!validateUserId(userId)) {
throw new Error("Invalid user ID format");
}
try {
return await userService.getUserInfo(accessToken, userId);
} catch (error) {
if (error.code === -233) {
return null; // User not found
}
throw error;
}
}
```
## Troubleshooting
### Common Issues
**Q: "User not found" error**
```
A: User có thể đã unfollow OA hoặc chặn OA.
Kiểm tra is_follower field trước.
```
**Q: Không lấy được phone number**
```
A: Phone chỉ có khi user đã share với OA.
Sử dụng request_user_info để yêu cầu.
```
**Q: getAllUsers không lấy hết**
```
A: Zalo giới hạn max offset = 9951.
Chỉ lấy được ~10000 users đầu tiên.
```
**Q: Custom info không cập nhật**
```
A: Kiểm tra cấu trúc custom_info trong OA settings.
Tất cả values phải là string.
```
## Tài Liệu Liên Quan
- [Zalo Official Account API](https://developers.zalo.me/docs/api/official-account-api)
- [User Management API](https://developers.zalo.me/docs/api/official-account-api/quan-ly-nguoi-dung)
- [Tag Management API](https://developers.zalo.me/docs/api/official-account-api/quan-ly-nhan)
- [Consultation Service](./CONSULTATION_SERVICE.md)
- [Tag Management](./TAG_MANAGEMENT.md)