From 471e26ad628a442b4f5f70dc7c6f9a535ad34767 Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Sun, 18 Jan 2026 17:27:05 +0700 Subject: [PATCH] docs: Add initial documentation for Zalo, WhatsApp, X, and Facebook marketing services. --- services/mkt-facebook-service-net/README.md | 319 +++ .../docs/AI_CHATBOT.md | 559 ++++++ services/mkt-facebook-service-net/docs/API.md | 703 +++++++ .../docs/ARCHITECTURE.md | 556 ++++++ .../docs/FACEBOOK_SETUP.md | 381 ++++ .../mkt-facebook-service-net/docs/README.md | 69 + .../docs/en/README.md | 295 +++ .../docs/vi/README.md | 295 +++ services/mkt-whatsapp-service-net/README.md | 427 ++++ .../docs/en/AI_CHATBOT_GUIDE.md | 547 ++++++ .../mkt-whatsapp-service-net/docs/en/API.md | 790 ++++++++ .../docs/en/ARCHITECTURE.md | 532 +++++ .../docs/en/AUTOMATION_GUIDE.md | 429 ++++ .../docs/en/WHATSAPP_SETUP.md | 296 +++ .../docs/vi/AI_CHATBOT_GUIDE.md | 416 ++++ .../mkt-whatsapp-service-net/docs/vi/API.md | 390 ++++ .../docs/vi/ARCHITECTURE.md | 238 +++ .../docs/vi/AUTOMATION_GUIDE.md | 262 +++ .../docs/vi/WHATSAPP_SETUP.md | 261 +++ services/mkt-x-service-net/README.md | 438 +++++ services/mkt-x-service-net/docs/API.md | 1728 +++++++++++++++++ .../mkt-x-service-net/docs/ARCHITECTURE.md | 807 ++++++++ services/mkt-x-service-net/docs/README.md | 316 +++ .../mkt-x-service-net/docs/TWITTER_SETUP.md | 494 +++++ services/mkt-zalo-service-net/README.md | 332 ++++ .../mkt-zalo-service-net/docs/API_DESIGN.md | 971 +++++++++ .../docs/DATABASE_SCHEMA.md | 562 ++++++ .../docs/DOMAIN_MODELS.md | 733 +++++++ .../mkt-zalo-service-net/docs/INTEGRATION.md | 579 ++++++ .../mkt-zalo-service-net/docs/SOLUTION.md | 779 ++++++++ 30 files changed, 15504 insertions(+) create mode 100644 services/mkt-facebook-service-net/README.md create mode 100644 services/mkt-facebook-service-net/docs/AI_CHATBOT.md create mode 100644 services/mkt-facebook-service-net/docs/API.md create mode 100644 services/mkt-facebook-service-net/docs/ARCHITECTURE.md create mode 100644 services/mkt-facebook-service-net/docs/FACEBOOK_SETUP.md create mode 100644 services/mkt-facebook-service-net/docs/README.md create mode 100644 services/mkt-facebook-service-net/docs/en/README.md create mode 100644 services/mkt-facebook-service-net/docs/vi/README.md create mode 100644 services/mkt-whatsapp-service-net/README.md create mode 100644 services/mkt-whatsapp-service-net/docs/en/AI_CHATBOT_GUIDE.md create mode 100644 services/mkt-whatsapp-service-net/docs/en/API.md create mode 100644 services/mkt-whatsapp-service-net/docs/en/ARCHITECTURE.md create mode 100644 services/mkt-whatsapp-service-net/docs/en/AUTOMATION_GUIDE.md create mode 100644 services/mkt-whatsapp-service-net/docs/en/WHATSAPP_SETUP.md create mode 100644 services/mkt-whatsapp-service-net/docs/vi/AI_CHATBOT_GUIDE.md create mode 100644 services/mkt-whatsapp-service-net/docs/vi/API.md create mode 100644 services/mkt-whatsapp-service-net/docs/vi/ARCHITECTURE.md create mode 100644 services/mkt-whatsapp-service-net/docs/vi/AUTOMATION_GUIDE.md create mode 100644 services/mkt-whatsapp-service-net/docs/vi/WHATSAPP_SETUP.md create mode 100644 services/mkt-x-service-net/README.md create mode 100644 services/mkt-x-service-net/docs/API.md create mode 100644 services/mkt-x-service-net/docs/ARCHITECTURE.md create mode 100644 services/mkt-x-service-net/docs/README.md create mode 100644 services/mkt-x-service-net/docs/TWITTER_SETUP.md create mode 100644 services/mkt-zalo-service-net/README.md create mode 100644 services/mkt-zalo-service-net/docs/API_DESIGN.md create mode 100644 services/mkt-zalo-service-net/docs/DATABASE_SCHEMA.md create mode 100644 services/mkt-zalo-service-net/docs/DOMAIN_MODELS.md create mode 100644 services/mkt-zalo-service-net/docs/INTEGRATION.md create mode 100644 services/mkt-zalo-service-net/docs/SOLUTION.md diff --git a/services/mkt-facebook-service-net/README.md b/services/mkt-facebook-service-net/README.md new file mode 100644 index 00000000..69930a53 --- /dev/null +++ b/services/mkt-facebook-service-net/README.md @@ -0,0 +1,319 @@ +# Marketing Facebook Service - Dịch Vụ Marketing Facebook + +> **EN**: Facebook Messenger Marketing Service with Automation Chatbot, AI-Powered Chatbot, and Customer Management +> **VI**: Dịch vụ Marketing Facebook Messenger với Chatbot Tự Động, Chatbot AI, và Quản Lý Khách Hàng + +[![.NET Version](https://img.shields.io/badge/.NET-8.0-512BD4)](https://dotnet.microsoft.com/) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) + +## Features / Tính Năng + +### 1. 🤖 CHATBOT Automation Messenger + +**EN**: Rules-based chatbot with predefined conversation flows +- Visual flow builder với nodes (Message, Question, Condition, Action) +- Keyword triggers và postback handlers +- Quick replies và button templates +- Multi-language support +- A/B testing cho flows + +**VI**: Chatbot dựa trên quy tắc với luồng hội thoại định sẵn +- Trình tạo flow trực quan với các nodes (Message, Question, Condition, Action) +- Triggers theo từ khóa và xử lý postback +- Quick replies và button templates +- Hỗ trợ đa ngôn ngữ +- A/B testing cho các flows + +### 2. 🧠 CHATBOT AI Messenger + +**EN**: Intelligent chatbot powered by OpenAI/Azure OpenAI +- Natural language understanding và generation +- Context-aware conversations +- Customizable system prompts +- Multi-turn dialogue support +- Fallback to automation rules +- Cost tracking và optimization + +**VI**: Chatbot thông minh được hỗ trợ bởi OpenAI/Azure OpenAI +- Hiểu và sinh ngôn ngữ tự nhiên +- Hội thoại theo ngữ cảnh +- Tùy chỉnh system prompts +- Hỗ trợ đối thoại nhiều lượt +- Fallback về automation rules +- Theo dõi chi phí và tối ưu hóa + +### 3. 👥 Quản Lý Khách Hàng / Customer Management + +**EN**: Comprehensive customer data management +- Customer profiles với Facebook user info +- Conversation history tracking +- Custom fields và tags +- Segmentation by behavior +- Export customer data +- GDPR compliance + +**VI**: Quản lý dữ liệu khách hàng toàn diện +- Hồ sơ khách hàng với thông tin Facebook user +- Theo dõi lịch sử hội thoại +- Custom fields và tags +- Phân khúc theo hành vi +- Xuất dữ liệu khách hàng +- Tuân thủ GDPR + +## Quick Start / Bắt Đầu Nhanh + +### Prerequisites / Yêu Cầu + +- .NET 8.0 SDK +- PostgreSQL 15+ (hoặc Neon serverless) +- Redis 7+ +- RabbitMQ 3.12+ +- Docker \u0026 Docker Compose (cho local development) +- **Facebook Page** và **Facebook App** với Messenger Platform +- **OpenAI API Key** hoặc **Azure OpenAI** (cho AI Chatbot) + +### Configuration / Cấu Hình + +```bash +# EN: Copy environment template / VI: Sao chép template môi trường +cp .env.example .env + +# EN: Update configuration / VI: Cập nhật cấu hình +# - DATABASE_URL (PostgreSQL connection string) +# - REDIS_URL +# - RABBITMQ_URL +# - FACEBOOK_VERIFY_TOKEN (webhook verification) +# - FACEBOOK_PAGE_ACCESS_TOKEN (send messages) +# - OPENAI_API_KEY (AI chatbot) +``` + +### Local Development / Phát Triển Local + +```bash +# EN: Restore dependencies / VI: Khôi phục dependencies +dotnet restore + +# EN: Apply migrations / VI: Áp dụng migrations +dotnet ef database update --project src/MktFacebookService.Infrastructure + +# EN: Run service / VI: Chạy service +dotnet run --project src/MktFacebookService.API + +# Service available at http://localhost:5000 +# Swagger UI: http://localhost:5000/swagger +``` + +### Docker Deployment / Triển Khai Docker + +```bash +# EN: Build and run with Docker Compose / VI: Build và chạy với Docker Compose +cd deployments/local +docker-compose up -d mkt-facebook-service-net + +# EN: View logs / VI: Xem logs +docker-compose logs -f mkt-facebook-service-net + +# EN: Access via Traefik / VI: Truy cập qua Traefik +# http://localhost/api/v1/mkt-facebook +``` + +## Architecture / Kiến Trúc + +```mermaid +graph TD + subgraph "External / Bên Ngoài" + FB[Facebook Messenger Platform] + OAI[OpenAI / Azure OpenAI] + User[End User on Messenger] + end + + subgraph "mkt-facebook-service-net" + WH[Webhooks Controller] + API[REST API Controllers] + APP[Application Layer CQRS] + DOM[Domain Layer] + INFRA[Infrastructure Layer] + end + + subgraph "Data Stores" + PG[(PostgreSQL)] + RD[(Redis Cache)] + RMQ[RabbitMQ] + end + + User -->|Send Message| FB + FB -->|Webhook Event| WH + WH -->|Process Message Command| APP + API -->|Commands/Queries| APP + APP -->|Business Logic| DOM + APP -->|Persistence| INFRA + INFRA -->|EF Core| PG + INFRA -->|Caching| RD + INFRA -->|Events| RMQ + APP -->|Send Message| INFRA + INFRA -->|API Call| FB + APP -->|AI Completion| INFRA + INFRA -->|API Call| OAI +``` + +### Technology Stack / Công Nghệ + +| Layer | Technology / Công Nghệ | +|-------|------------------------| +| **Backend** | .NET 8, ASP.NET Core 8 | +| **Architecture** | Clean Architecture, DDD, CQRS | +| **Database** | PostgreSQL 15+, EF Core 8 | +| **Cache** | Redis, StackExchange.Redis | +| **Messaging** | RabbitMQ, MassTransit | +| **HTTP Client** | HttpClient Factory, Polly | +| **AI** | OpenAI SDK, Azure.AI.OpenAI | +| **API Gateway** | Traefik | +| **Documentation** | Swagger/OpenAPI 3.0 | + +## API Endpoints + +### Public API + +| Endpoint | Method | Description / Mô Tả | +|----------|--------|---------------------| +| `/api/v1/webhooks/facebook` | GET | Facebook webhook verification | +| `/api/v1/webhooks/facebook` | POST | Receive Facebook Messenger events | +| `/api/v1/conversations` | GET | List conversations / Danh sách hội thoại | +| `/api/v1/conversations/{id}` | GET | Get conversation by ID | +| `/api/v1/conversations/{id}/messages` | POST | Send message / Gửi tin nhắn | +| `/api/v1/customers` | GET | List customers / Danh sách khách hàng | +| `/api/v1/customers/{id}` | GET | Customer details | +| `/api/v1/customers/{id}` | PUT | Update customer info | + +### Admin API + +| Endpoint | Method | Description / Mô Tả | +|----------|--------|---------------------| +| `/api/v1/chatbots/flows` | GET | List automation flows | +| `/api/v1/chatbots/flows` | POST | Create chatbot flow | +| `/api/v1/chatbots/flows/{id}` | PUT | Update flow | +| `/api/v1/chatbots/flows/{id}` | DELETE | Delete flow | +| `/api/v1/chatbots/ai-config` | GET | Get AI chatbot config | +| `/api/v1/chatbots/ai-config` | PUT | Update AI config | + +### Health \u0026 Monitoring + +| Endpoint | Description / Mô Tả | +|----------|---------------------| +| `/health` | Health check endpoint | +| `/swagger` | Swagger UI documentation | + +## Documentation / Tài Liệu + +- [Architecture Documentation](docs/ARCHITECTURE.md) - System design và domain model +- [API Documentation](docs/API.md) - Complete API reference với examples +- [Facebook Messenger Setup](docs/FACEBOOK_SETUP.md) - Hướng dẫn setup Facebook App +- [AI Chatbot Configuration](docs/AI_CHATBOT.md) - AI integration guide + +## Project Structure / Cấu Trúc Dự Án + +``` +mkt-facebook-service-net/ +├── src/ +│ ├── MktFacebookService.API/ # API Layer +│ │ ├── Controllers/ # REST Controllers +│ │ ├── Application/ # CQRS Commands/Queries +│ │ └── Program.cs # Entry point +│ ├── MktFacebookService.Domain/ # Domain Layer +│ │ ├── AggregatesModel/ # Aggregates, Entities +│ │ │ ├── ConversationAggregate/ +│ │ │ ├── CustomerAggregate/ +│ │ │ └── ChatbotAggregate/ +│ │ └── SeedWork/ # Base classes +│ └── MktFacebookService.Infrastructure/ # Infrastructure Layer +│ ├── Data/ # EF Core DbContext +│ ├── Repositories/ # Repository implementations +│ └── ExternalServices/ # Facebook, OpenAI clients +├── tests/ +│ ├── MktFacebookService.UnitTests/ +│ └── MktFacebookService.FunctionalTests/ +├── docs/ # Documentation +├── Dockerfile +└── MktFacebookService.slnx +``` + +## Environment Variables / Biến Môi Trường + +| Variable | Description / Mô Tả | Default | +|----------|---------------------|---------| +| `DATABASE_URL` | PostgreSQL connection string | - | +| `REDIS_URL` | Redis connection string | `localhost:6379` | +| `RABBITMQ_URL` | RabbitMQ connection string | `localhost:5672` | +| `FACEBOOK_VERIFY_TOKEN` | Webhook verification token | - | +| `FACEBOOK_PAGE_ACCESS_TOKEN` | Page access token for sending messages | - | +| `FACEBOOK_API_VERSION` | Facebook API version | `v21.0` | +| `OPENAI_API_KEY` | OpenAI API key | - | +| `OPENAI_MODEL` | OpenAI model name | `gpt-4-turbo` | +| `AZURE_OPENAI_ENDPOINT` | Azure OpenAI endpoint (optional) | - | +| `ASPNETCORE_ENVIRONMENT` | Environment (Development/Production) | `Development` | + +## Development Workflow / Quy Trình Phát Triển + +### Phase 1: Domain Layer +1. Tạo Aggregates (Conversation, Customer, ChatbotFlow, AIChatbotConfig) +2. Định nghĩa Entities và Value Objects +3. Implement business rules trong domain methods +4. Raise Domain Events + +### Phase 2: Infrastructure Layer +1. Setup EF Core DbContext và entity configurations +2. Create repositories implementing domain interfaces +3. Implement FacebookMessengerClient +4. Implement OpenAIClient với Polly resilience +5. Apply database migrations + +### Phase 3: Application Layer (CQRS) +1. Create Commands (ProcessIncomingMessage, SendMessage, CreateChatbotFlow) +2. Create Queries (GetConversations, GetCustomers) +3. Implement MediatR Handlers +4. Add FluentValidation validators +5. Setup Pipeline Behaviors + +### Phase 4: API Layer +1. Implement WebhooksController cho Facebook events +2. Create REST API Controllers +3. Add Swagger annotations +4. Configure authentication \u0026 authorization +5. Setup health checks + +## Testing / Kiểm Thử + +```bash +# EN: Run all tests / VI: Chạy tất cả tests +dotnet test + +# EN: Run unit tests only / VI: Chỉ chạy unit tests +dotnet test tests/MktFacebookService.UnitTests/ + +# EN: Run with coverage / VI: Chạy với coverage +dotnet test /p:CollectCoverage=true /p:CoverageReportsFormat=opencover +``` + +## Contributing / Đóng Góp + +Please follow the [GoodGo Project Rules](../../.agent/skills/project-rules/SKILL.md) and [.NET Microservice Workflow](../../.agent/skills/dotnet-microservice-workflow/SKILL.md). + +## License + +MIT License + +## Resources / Tài Nguyên + +### Facebook Messenger Platform +- [Messenger Platform Overview](https://developers.facebook.com/docs/messenger-platform/) +- [Webhook Reference](https://developers.facebook.com/docs/messenger-platform/webhooks) +- [Send API Reference](https://developers.facebook.com/docs/messenger-platform/send-messages) + +### OpenAI +- [OpenAI API Documentation](https://platform.openai.com/docs/introduction) +- [Chat Completions Guide](https://platform.openai.com/docs/guides/chat-completions) + +### Internal Skills +- [API Design Skill](../../.agent/skills/api-design/SKILL.md) +- [CQRS MediatR Skill](../../.agent/skills/cqrs-mediatr/SKILL.md) +- [Domain-Driven Design Skill](../../.agent/skills/domain-driven-design/SKILL.md) diff --git a/services/mkt-facebook-service-net/docs/AI_CHATBOT.md b/services/mkt-facebook-service-net/docs/AI_CHATBOT.md new file mode 100644 index 00000000..cb96c9b6 --- /dev/null +++ b/services/mkt-facebook-service-net/docs/AI_CHATBOT.md @@ -0,0 +1,559 @@ +# AI Chatbot Configuration Guide - Hướng Dẫn Cấu Hình AI Chatbot + +**EN**: Guide to configure and optimize AI-powered chatbot using OpenAI or Azure OpenAI. + +**VI**: Hướng dẫn cấu hình và tối ưu chatbot AI sử dụng OpenAI hoặc Azure OpenAI. + +## Overview / Tổng Quan + +**EN**: The AI Chatbot uses GPT-4 or GPT-3.5 to provide intelligent, context-aware responses to customer messages. It can understand natural language, maintain conversation context, and provide helpful information. + +**VI**: AI Chatbot sử dụng GPT-4 hoặc GPT-3.5 để cung cấp phản hồi thông minh, theo ngữ cảnh cho tin nhắn khách hàng. Nó có thể hiểu ngôn ngữ tự nhiên, duy trì ngữ cảnh hội thoại, và cung cấp thông tin hữu ích. + +## Choosing AI Provider / Chọn AI Provider + +### Option 1: OpenAI + +**Pros / Ưu điểm**: +- ✅ Easy setup / Dễ dàng setup +- ✅ Pay-as-you-go pricing +- ✅ Latest models (GPT-4 Turbo) +- ✅ Good for global deployment + +**Cons / Nhược điểm**: +- ❌ External API (latency) +- ❌ Data processed outside your region + +**Setup**: +1. Create account at [platform.openai.com](https://platform.openai.com/) +2. Generate API key from **API Keys** page +3. Add credits to billing account + +```bash +# .env configuration +OPENAI_API_KEY="sk-proj-xxxxxxxxxxxxxxxxx" +OPENAI_MODEL="gpt-4-turbo" +``` + +### Option 2: Azure OpenAI + +**Pros / Ưu điểm**: +- ✅ Enterprise security \u0026 compliance +- ✅ Data residency control +- ✅ SLA guarantees +- ✅ VNET integration + +**Cons / Nhược điểm**: +- ❌ More complex setup +- ❌ Requires Azure subscription +- ❌ Slower model updates + +**Setup**: +1. Create Azure OpenAI resource in Azure Portal +2. Deploy model (e.g., `gpt-4`) +3. Copy endpoint và key + +```bash +# .env configuration +AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/" +AZURE_OPENAI_KEY="your-key-here" +AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4" +``` + +--- + +## Model Selection / Lựa Chọn Model + +| Model | Best For / Phù Hợp Cho | Cost / Chi Phí | Speed / Tốc Độ | +|-------|------------------------|----------------|----------------| +| **GPT-4 Turbo** | Complex reasoning, accurate responses | $$ | Medium | +| **GPT-4** | High quality, nuanced understanding | $$$ | Slow | +| **GPT-3.5 Turbo** | Fast responses, simple queries | $ | Fast | + +**Recommendation / Đề Nghị**: +- **E-commerce Support**: `gpt-3.5-turbo` (fast \u0026 cost-effective) +- **Technical Support**: `gpt-4-turbo` (better accuracy) +- **Multilingual Support**: `gpt-4-turbo` (better language handling) + +--- + +## System Prompt Best Practices / Thực Hành Tốt Nhất System Prompt + +### Basic Template / Mẫu Cơ Bản + +``` +You are a helpful customer service assistant for [BUSINESS_NAME], an e-commerce platform selling [PRODUCTS]. + +Your responsibilities: +- Answer questions about products, orders, and policies +- Provide friendly and professional customer service +- If you don't know something, be honest and offer to connect the customer with a human agent + +Important guidelines: +- Always be polite and respectful +- Keep responses concise (under 200 words) +- Use emojis sparingly +- Do not make up information +- Do not discuss competitor products +``` + +### E-commerce Example / Ví Dụ E-commerce + +``` +You are the AI assistant for "GoodGo Shop", a multi-category e-commerce platform in Vietnam. + +PRODUCTS: +- Electronics (phones, laptops, accessories) +- Fashion (clothing, shoes, bags) +- Home \u0026 Living (furniture, kitchenware) + +CAPABILITIES: +- Check order status (ask for order ID) +- Provide product information +- Explain shipping \u0026 return policies +- Help with account issues + +TONE: +- Friendly and conversational +- Use Vietnamese when customer uses Vietnamese +- Use simple language, avoid jargon + +LIMITATIONS: +- Cannot process refunds (refer to human agent) +- Cannot modify orders (refer to customer service) +- Cannot access payment information + +When you cannot help, say: "Let me connect you with our customer service team for this request." +``` + +### Restaurant/Food Delivery Example + +``` +You are the AI chatbot for "Taste of Vietnam", a Vietnamese restaurant in Ho Chi Minh City. + +MENU CATEGORIES: +- Appetizers (spring rolls, salads) +- Main courses (pho, banh mi, rice dishes) +- Beverages (Vietnamese coffee, smoothies) + +SERVICES: +- Dine-in (10AM - 10PM daily) +- Delivery (via our website only, 30-45 min) +- Reservation (ask for date, time, number of guests) + +COMMON QUESTIONS: +- Menu recommendations → Suggest based on preferences +- Allergies → Inform ingredients, recommend alternatives +- Delivery → Available within 5km radius +- Payment → Cash or card accepted + +Always end with: "Would you like to place an order or make a reservation?" +``` + +--- + +## Configuration Parameters / Tham Số Cấu Hình + +### Temperature + +**EN**: Controls randomness (0.0 - 2.0) + +**VI**: Kiểm soát độ ngẫu nhiên (0.0 - 2.0) + +| Value | Behavior / Hành Vi | Use Case | +|-------|-------------------|----------| +| **0.0 - 0.3** | Deterministic, focused | FAQ, policy questions | +| **0.4 - 0.7** | Balanced creativity | General customer service | +| **0.8 - 1.0** | More creative | Marketing, engagement | +| **1.1+** | Very random (not recommended) | - | + +**Recommendation**: `0.7` for customer service + +### Max Tokens + +**EN**: Maximum length of response + +**VI**: Độ dài tối đa của phản hồi + +| Tokens | Words / Từ | Use Case | +|--------|-----------|----------| +| 150 | ~100 | Quick answers | +| 300 | ~200 | Standard responses | +| 500 | ~350 | Detailed explanations | +| 1000+ | 700+ | Long-form content | + +**Recommendation**: `300-500` tokens for most cases + +### Top P (Nucleus Sampling) + +**EN**: Alternative to temperature (0.0 - 1.0) + +**VI**: Thay thế cho temperature (0.0 - 1.0) + +- **0.9**: Recommended default +- Use either `temperature` OR `top_p`, not both + +### Presence Penalty / Frequency Penalty + +**EN**: Reduce repetition (-2.0 to 2.0) + +**VI**: Giảm sự lặp lại (-2.0 đến 2.0) + +- **Presence Penalty**: `0.6` - Encourage topic variety +- **Frequency Penalty**: `0.3` - Reduce word repetition + +--- + +## Context Management / Quản Lý Ngữ Cảnh + +### Conversation History + +**EN**: Include recent messages for context: + +**VI**: Bao gồm tin nhắn gần đây cho ngữ cảnh: + +```csharp +var messages = new List +{ + new ChatMessage(ChatRole.System, systemPrompt), + new ChatMessage(ChatRole.User, "What are your opening hours?"), + new ChatMessage(ChatRole.Assistant, "We're open 10AM - 10PM daily."), + new ChatMessage(ChatRole.User, "Can I order delivery now?"), +}; +``` + +**Best Practice**: +- Keep last **5-10 messages** for context +- Trim old messages to save tokens +- Always include System message + +### Token Budget + +**EN**: Managing token costs: + +**VI**: Quản lý chi phí tokens: + +| Component | Tokens | Note | +|-----------|--------|------| +| System Prompt | 100-200 | Fixed | +| Conversation History | 50-100 per message | Variable | +| Max Response | 300-500 | Configurable | +| **Total per request** | ~500-1500 | Estimate | + +**Cost Estimation** (GPT-4 Turbo): +- Input: $0.01 / 1K tokens +- Output: $0.03 / 1K tokens +- **Average cost per conversation**: $0.02 - $0.05 + +--- + +## Fallback Strategies / Chiến Lược Dự Phòng + +### 1. Fallback to Automation + +**EN**: When AI confidence is low, fallback to automation rules: + +**VI**: Khi độ tin cậy AI thấp, fallback về automation rules: + +```csharp +if (aiResponse.Confidence < 0.7) +{ + // Fallback to keyword matching + return await _automationEngine.GetResponseAsync(message); +} +``` + +### 2. Human Handoff + +**EN**: Escalate to human agent for complex issues: + +**VI**: Chuyển sang agent người khi vấn đề phức tạp: + +**Trigger Phrases** (in AI response): +- "I'm not sure" +- "Let me connect you" +- "human agent" + +**Action**: Update conversation status to `NeedsHumanAgent` + +### 3. Timeout Handling + +**EN**: If OpenAI API times out: + +**VI**: Nếu OpenAI API timeout: + +```csharp +try +{ + var response = await _openAIClient.GetCompletionAsync(prompt, ct); +} +catch (TaskCanceledException) +{ + // Fallback response + return "I apologize for the delay. Let me connect you with our team."; +} +``` + +--- + +## Multilingual Support / Hỗ Trợ Đa Ngôn Ngữ + +### Auto-detect Language + +**EN**: GPT-4 can auto-detect and respond in the customer's language: + +**VI**: GPT-4 có thể tự động phát hiện và phản hồi bằng ngôn ngữ khách hàng: + +**System Prompt**: +``` +You are a multilingual customer service assistant. +- Detect the customer's language +- Respond in the same language +- Support: English, Vietnamese, Thai, Chinese +``` + +### Language-specific Prompts + +**Vietnamese**: +``` +Bạn là trợ lý AI cho "GoodGo Shop", nền tảng thương mại điện tử tại Việt Nam. + +NHIỆM VỤ: +- Trả lời câu hỏi về sản phẩm, đơn hàng, chính sách +- Hỗ trợ khách hàng thân thiện và chuyên nghiệp +- Nếu không biết, hãy thành thật và đề nghị kết nối với nhân viên + +NGUYÊN TẮC: +- Luôn lịch sự, tôn trọng +- Phản hồi ngắn gọn (dưới 200 từ) +- Không bịa đặt thông tin +``` + +--- + +## Testing \u0026 Optimization / Kiểm Thử \u0026 Tối Ưu + +### A/B Testing System Prompts + +**EN**: Test different prompts to find best performance: + +**VI**: Test các prompts khác nhau để tìm hiệu suất tốt nhất: + +| Metric | Target / Mục Tiêu | Measurement | +|--------|-------------------|-------------| +| **Response Quality** | User satisfaction \u003e 80% | Thumbs up/down | +| **Resolution Rate** | \u003e 70% without human | Track escalations | +| **Response Time** | \u003c 3 seconds | API latency | +| **Cost per Conversation** | \u003c $0.05 | Token usage | + +### Monitoring Dashboard + +**Key Metrics / Chỉ Số Chính**: +- Total conversations handled by AI +- Average tokens per conversation +- Total cost (daily/monthly) +- Fallback rate (AI → Automation) +- Human handoff rate +- Customer satisfaction score + +--- + +## Security \u0026 Privacy / Bảo Mật \u0026 Quyền Riêng Tư + +### PII Protection + +**EN**: Do NOT send sensitive data to OpenAI: + +**VI**: KHÔNG gửi dữ liệu nhạy cảm đến OpenAI: + +❌ **Never Include**: +- Credit card numbers +- Passwords +- Social security numbers +- Full addresses (unless necessary) + +✅ **Safe to Include**: +- Product names +- Order IDs (hashed) +- General questions +- Preferences + +### Data Retention + +**OpenAI Policy**: +- API data NOT used for training (as of Dec 2023) +- Data retained for 30 days for abuse monitoring +- Can opt-out of retention (contact OpenAI) + +**Azure OpenAI Policy**: +- Data stays in your Azure region +- Full control over data retention +- Enterprise compliance (SOC 2, ISO 27001) + +--- + +## Cost Optimization / Tối Ưu Chi Phí + +### 1. Use Shorter System Prompts + +```diff +- You are a helpful customer service assistant for GoodGo Shop, an e-commerce platform selling electronics, fashion, home \u0026 living... ++ You are a customer service AI for GoodGo, an e-commerce platform. +``` + +**Savings**: ~50 tokens per request + +### 2. Limit Conversation History + +```csharp +// Only keep recent 5 messages +var contextMessages = conversation.Messages + .OrderByDescending(m =\u003e m.SentAt) + .Take(5) + .Reverse(); +``` + +**Savings**: ~200-400 tokens per request + +### 3. Use GPT-3.5 for Simple Queries + +```csharp +if (IsSimpleQuery(message)) // FAQ, product lookup +{ + model = "gpt-3.5-turbo"; // 10x cheaper +} +else +{ + model = "gpt-4-turbo"; +} +``` + +### 4. Cache Common Responses + +**EN**: Cache responses for FAQs in Redis: + +**VI**: Cache responses cho FAQs trong Redis: + +```csharp +var cacheKey = $"faq:{messageHash}"; +var cachedResponse = await _redis.GetAsync(cacheKey); +if (cachedResponse != null) + return cachedResponse; // No API call +``` + +--- + +## Example Configurations / Ví Dụ Cấu Hình + +### Configuration 1: High-Quality Support + +```json +{ + "provider": "OpenAI", + "model": "gpt-4-turbo", + "systemPrompt": "Detailed customer service prompt...", + "temperature": 0.6, + "maxTokens": 500, + "topP": 0.9, + "presencePenalty": 0.5, + "frequencyPenalty": 0.3 +} +``` + +**Use Case**: Premium brands, complex products +**Cost**: ~$0.04 per conversation + +### Configuration 2: Fast \u0026 Cost-Effective + +```json +{ + "provider": "OpenAI", + "model": "gpt-3.5-turbo", + "systemPrompt": "Concise customer service prompt...", + "temperature": 0.7, + "maxTokens": 300, + "topP": 0.9 +} +``` + +**Use Case**: High-volume, simple queries +**Cost**: ~$0.005 per conversation + +### Configuration 3: Enterprise (Azure OpenAI) + +```json +{ + "provider": "AzureOpenAI", + "model": "gpt-4", + "endpoint": "https://your-resource.openai.azure.com/", + "deploymentName": "gpt-4-deployment", + "systemPrompt": "Enterprise-grade prompt...", + "temperature": 0.7, + "maxTokens": 400 +} +``` + +**Use Case**: Enterprise with compliance requirements +**Cost**: Based on Azure pricing + +--- + +## Troubleshooting / Xử Lý Sự Cố + +### Issue 1: Responses Too Generic + +**Problem**: AI gives vague, unhelpful answers + +**Solution**: +- ✅ Add more context to system prompt (products, policies) +- ✅ Include conversation history +- ✅ Lower temperature (0.5) + +### Issue 2: High Costs + +**Problem**: Token usage too high + +**Solution**: +- ✅ Shorten system prompt +- ✅ Limit conversation history +- ✅ Use GPT-3.5 for simple queries +- ✅ Cache common FAQs + +### Issue 3: Slow Responses + +**Problem**: Latency \u003e 5 seconds + +**Solution**: +- ✅ Use GPT-3.5 Turbo (faster) +- ✅ Reduce max_tokens +- ✅ Enable streaming (show typing indicator) +- ✅ Use Azure OpenAI (regional deployment) + +### Issue 4: AI Hallucinates + +**Problem**: AI makes up information + +**Solution**: +- ✅ Add explicit instructions: "Do not make up information" +- ✅ Lower temperature (0.3-0.5) +- ✅ Provide factual context in system prompt +- ✅ Use function calling for structured data (future enhancement) + +--- + +## Resources / Tài Nguyên + +### Official Documentation +- [OpenAI API Reference](https://platform.openai.com/docs/api-reference) +- [Azure OpenAI Documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/) +- [GPT Best Practices](https://platform.openai.com/docs/guides/prompt-engineering) + +### Tools +- [OpenAI Playground](https://platform.openai.com/playground) - Test prompts +- [Tokenizer](https://platform.openai.com/tokenizer) - Count tokens +- [Azure OpenAI Studio](https://oai.azure.com/) - Manage deployments + +### Internal Docs +- [API Documentation](./API.md) +- [Architecture Documentation](./ARCHITECTURE.md) +- [Facebook Setup Guide](./FACEBOOK_SETUP.md) diff --git a/services/mkt-facebook-service-net/docs/API.md b/services/mkt-facebook-service-net/docs/API.md new file mode 100644 index 00000000..b0fb0c05 --- /dev/null +++ b/services/mkt-facebook-service-net/docs/API.md @@ -0,0 +1,703 @@ +# API Documentation - Tài Liệu API + +**Service**: mkt-facebook-service-net +**Base URL**: `http://localhost/api/v1/mkt-facebook` +**API Version**: v1.0 + +## Authentication / Xác Thực + +**EN**: All REST API endpoints (except webhooks) require JWT Bearer token. + +**VI**: Tất cả REST API endpoints (trừ webhooks) yêu cầu JWT Bearer token. + +```http +Authorization: Bearer {jwt_token} +``` + +## Webhooks API + +### Verify Facebook Webhook + +**EN**: Facebook uses this endpoint to verify webhook ownership during setup. + +**VI**: Facebook dùng endpoint này để verify webhook trong quá trình setup. + +```http +GET /api/v1/webhooks/facebook +``` + +**Query Parameters**: +| Parameter | Type | Description | +|-----------|------|-------------| +| `hub.mode` | string | Must be "subscribe" | +| `hub.verify_token` | string | Token configured in Facebook App | +| `hub.challenge` | string | Random string from Facebook | + +**Response** (200 OK): +``` +{hub.challenge} +``` + +**Example**: +```bash +curl "http://localhost/api/v1/webhooks/facebook?hub.mode=subscribe\u0026hub.verify_token=my_verify_token\u0026hub.challenge=1234567890" +``` + +--- + +### Receive Facebook Messenger Events + +**EN**: Receives messages, postbacks, and other events from Facebook Messenger Platform. + +**VI**: Nhận messages, postbacks, và các events khác từ Facebook Messenger Platform. + +```http +POST /api/v1/webhooks/facebook +``` + +**Headers**: +``` +X-Hub-Signature-256: sha256={signature} +Content-Type: application/json +``` + +**Request Body** (Message Event): +```json +{ + "object": "page", + "entry": [{ + "id": "PAGE_ID", + "time": 1234567890, + "messaging": [{ + "sender": { "id": "USER_ID" }, + "recipient": { "id": "PAGE_ID" }, + "timestamp": 1234567890, + "message": { + "mid": "MESSAGE_ID", + "text": "Hello chatbot!", + "quick_reply": { + "payload": "QUICK_REPLY_PAYLOAD" + } + } + }] + }] +} +``` + +**Request Body** (Postback Event): +```json +{ + "object": "page", + "entry": [{ + "messaging": [{ + "sender": { "id": "USER_ID" }, + "recipient": { "id": "PAGE_ID" }, + "timestamp": 1234567890, + "postback": { + "title": "Get Started", + "payload": "GET_STARTED" + } + }] + }] +} +``` + +**Response** (200 OK): +```json +{ + "success": true +} +``` + +--- + +## Conversations API + +### List Conversations + +**EN**: Retrieve a paginated list of conversations. + +**VI**: Lấy danh sách conversations có phân trang. + +```http +GET /api/v1/conversations +``` + +**Query Parameters**: +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `shopId` | guid | Yes | - | Shop/Business ID | +| `status` | string | No | - | Filter by status (Active, Closed) | +| `skip` | int | No | 0 | Number of records to skip | +| `take` | int | No | 20 | Number of records to return | + +**Response** (200 OK): +```json +{ + "success": true, + "data": { + "conversations": [ + { + "id": "550e8400-e29b-41d4-a716-446655440000", + "customerId": "650e8400-e29b-41d4-a716-446655440001", + "customerName": "John Doe", + "pageId": "123456789", + "status": "Active", + "channel": "FacebookMessenger", + "lastMessageText": "Thank you!", + "lastMessageAt": "2026-01-18T10:30:00Z", + "createdAt": "2026-01-18T09:00:00Z" + } + ], + "totalCount": 150 + }, + "pagination": { + "page": 1, + "limit": 20, + "total": 150, + "totalPages": 8 + } +} +``` + +**Example**: +```bash +curl -H "Authorization: Bearer {token}" \ + "http://localhost/api/v1/conversations?shopId=abc123\u0026status=Active\u0026skip=0\u0026take=20" +``` + +--- + +### Get Conversation by ID + +**EN**: Retrieve a specific conversation with full message history. + +**VI**: Lấy một conversation với toàn bộ lịch sử tin nhắn. + +```http +GET /api/v1/conversations/{id} +``` + +**Path Parameters**: +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | guid | Conversation ID | + +**Response** (200 OK): +```json +{ + "success": true, + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "customerId": "650e8400-e29b-41d4-a716-446655440001", + "customer": { + "id": "650e8400-e29b-41d4-a716-446655440001", + "name": "John Doe", + "facebookUserId": "1234567890", + "profilePicUrl": "https://...", + "tags": ["VIP", "Returning Customer"] + }, + "pageId": "123456789", + "status": "Active", + "channel": "FacebookMessenger", + "messages": [ + { + "id": "msg-001", + "senderId": "1234567890", + "content": "Hello, I need help", + "messageType": "Text", + "direction": "Incoming", + "sentAt": "2026-01-18T09:00:00Z" + }, + { + "id": "msg-002", + "senderId": "PAGE_ID", + "content": "Hi! How can I help you today?", + "messageType": "Text", + "direction": "Outgoing", + "sentAt": "2026-01-18T09:00:05Z" + } + ], + "createdAt": "2026-01-18T09:00:00Z", + "lastMessageAt": "2026-01-18T10:30:00Z" + } +} +``` + +**Response** (404 Not Found): +```json +{ + "success": false, + "error": "Conversation not found" +} +``` + +--- + +### Send Message in Conversation + +**EN**: Send a message to a customer in an active conversation. + +**VI**: Gửi tin nhắn đến khách hàng trong một conversation đang active. + +```http +POST /api/v1/conversations/{id}/messages +``` + +**Path Parameters**: +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | guid | Conversation ID | + +**Request Body**: +```json +{ + "messageText": "Thank you for contacting us!", + "quickReplies": [ + { + "contentType": "text", + "title": "Yes", + "payload": "YES" + }, + { + "contentType": "text", + "title": "No", + "payload": "NO" + } + ] +} +``` + +**Response** (200 OK): +```json +{ + "success": true, + "data": { + "messageId": "msg-003", + "sentAt": "2026-01-18T10:35:00Z" + } +} +``` + +**Example**: +```bash +curl -X POST -H "Authorization: Bearer {token}" \ + -H "Content-Type: application/json" \ + -d '{"messageText":"Hello from our team!"}' \ + "http://localhost/api/v1/conversations/550e8400-e29b-41d4-a716-446655440000/messages" +``` + +--- + +### Update Conversation Status + +**EN**: Update conversation status (assign, close, archive). + +**VI**: Cập nhật trạng thái conversation (assign, đóng, lưu trữ). + +```http +PUT /api/v1/conversations/{id}/status +``` + +**Request Body**: +```json +{ + "status": "Closed", + "reason": "Issue resolved" +} +``` + +**Response** (200 OK): +```json +{ + "success": true, + "data": { + "conversationId": "550e8400-e29b-41d4-a716-446655440000", + "status": "Closed", + "updatedAt": "2026-01-18T11:00:00Z" + } +} +``` + +--- + +## Customers API + +### List Customers + +**EN**: Retrieve a paginated list of customers. + +**VI**: Lấy danh sách khách hàng có phân trang. + +```http +GET /api/v1/customers +``` + +**Query Parameters**: +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `shopId` | guid | Yes | - | Shop/Business ID | +| `tags` | string[] | No | - | Filter by tags (comma-separated) | +| `search` | string | No | - | Search by name or email | +| `skip` | int | No | 0 | Pagination offset | +| `take` | int | No | 20 | Page size | + +**Response** (200 OK): +```json +{ + "success": true, + "data": { + "customers": [ + { + "id": "650e8400-e29b-41d4-a716-446655440001", + "facebookUserId": "1234567890", + "name": "John Doe", + "email": "john@example.com", + "profilePicUrl": "https://...", + "locale": "en_US", + "timezone": 7, + "tags": ["VIP", "Returning"], + "firstSeenAt": "2026-01-15T08:00:00Z", + "lastInteractionAt": "2026-01-18T10:30:00Z" + } + ], + "totalCount": 450 + }, + "pagination": { + "page": 1, + "limit": 20, + "total": 450, + "totalPages": 23 + } +} +``` + +--- + +### Get Customer by ID + +**EN**: Retrieve detailed customer information. + +**VI**: Lấy thông tin chi tiết khách hàng. + +```http +GET /api/v1/customers/{id} +``` + +**Response** (200 OK): +```json +{ + "success": true, + "data": { + "id": "650e8400-e29b-41d4-a716-446655440001", + "facebookUserId": "1234567890", + "name": "John Doe", + "email": "john@example.com", + "phone": "+84901234567", + "profilePicUrl": "https://...", + "locale": "vi_VN", + "timezone": 7, + "tags": ["VIP", "Returning Customer"], + "customFields": { + "preferredLanguage": "Vietnamese", + "membershipTier": "Gold" + }, + "conversationCount": 15, + "firstSeenAt": "2026-01-15T08:00:00Z", + "lastInteractionAt": "2026-01-18T10:30:00Z" + } +} +``` + +--- + +### Update Customer + +**EN**: Update customer tags and custom fields. + +**VI**: Cập nhật tags và custom fields của khách hàng. + +```http +PUT /api/v1/customers/{id} +``` + +**Request Body**: +```json +{ + "tags": ["VIP", "Returning", "HighValue"], + "customFields": { + "preferredLanguage": "English", + "membershipTier": "Platinum" + } +} +``` + +**Response** (200 OK): +```json +{ + "success": true, + "data": { + "customerId": "650e8400-e29b-41d4-a716-446655440001", + "updatedAt": "2026-01-18T11:00:00Z" + } +} +``` + +--- + +## Chatbots API + +### List Automation Flows + +**EN**: Retrieve all chatbot automation flows for a shop. + +**VI**: Lấy tất cả automation flows của một shop. + +```http +GET /api/v1/chatbots/flows +``` + +**Query Parameters**: +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `shopId` | guid | Yes | Shop/Business ID | +| `isActive` | bool | No | Filter by active status | + +**Response** (200 OK): +```json +{ + "success": true, + "data": [ + { + "id": "flow-001", + "name": "Welcome Flow", + "shopId": "shop-123", + "triggerType": "GetStarted", + "triggerValue": "GET_STARTED", + "isActive": true, + "nodeCount": 8, + "createdAt": "2026-01-10T00:00:00Z" + }, + { + "id": "flow-002", + "name": "FAQ Flow", + "shopId": "shop-123", + "triggerType": "Keyword", + "triggerValue": "help|faq|question", + "isActive": true, + "nodeCount": 12, + "createdAt": "2026-01-12T00:00:00Z" + } + ] +} +``` + +--- + +### Create Chatbot Flow + +**EN**: Create a new automation chatbot flow. + +**VI**: Tạo automation chatbot flow mới. + +```http +POST /api/v1/chatbots/flows +``` + +**Request Body**: +```json +{ + "shopId": "shop-123", + "name": "Product Inquiry Flow", + "triggerType": "Keyword", + "triggerValue": "product|price|buy", + "nodes": [ + { + "type": "Start", + "content": null, + "config": {}, + "nextNodeIds": ["node-002"] + }, + { + "type": "Message", + "content": "Welcome! I can help you find products.", + "config": {}, + "nextNodeIds": ["node-003"] + }, + { + "type": "Question", + "content": "What category are you interested in?", + "config": { + "quickReplies": [ + { "title": "Electronics", "payload": "CAT_ELECTRONICS" }, + { "title": "Fashion", "payload": "CAT_FASHION" } + ] + }, + "nextNodeIds": ["node-004", "node-005"] + } + ] +} +``` + +**Response** (201 Created): +```json +{ + "success": true, + "data": { + "flowId": "flow-003", + "createdAt": "2026-01-18T12:00:00Z" + } +} +``` + +--- + +### Get AI Chatbot Config + +**EN**: Retrieve AI chatbot configuration for a shop. + +**VI**: Lấy cấu hình AI chatbot của shop. + +```http +GET /api/v1/chatbots/ai-config +``` + +**Query Parameters**: +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `shopId` | guid | Yes | Shop/Business ID | + +**Response** (200 OK): +```json +{ + "success": true, + "data": { + "id": "ai-config-001", + "shopId": "shop-123", + "provider": "OpenAI", + "model": "gpt-4-turbo", + "systemPrompt": "You are a helpful customer service assistant for our e-commerce store...", + "temperature": 0.7, + "maxTokens": 500, + "isEnabled": true, + "updatedAt": "2026-01-17T10:00:00Z" + } +} +``` + +--- + +### Update AI Chatbot Config + +**EN**: Update AI chatbot configuration. + +**VI**: Cập nhật cấu hình AI chatbot. + +```http +PUT /api/v1/chatbots/ai-config +``` + +**Request Body**: +```json +{ + "shopId": "shop-123", + "provider": "OpenAI", + "model": "gpt-4-turbo", + "systemPrompt": "You are a helpful and friendly customer service assistant...", + "temperature": 0.8, + "maxTokens": 500, + "isEnabled": true +} +``` + +**Response** (200 OK): +```json +{ + "success": true, + "data": { + "configId": "ai-config-001", + "updatedAt": "2026-01-18T12:30:00Z" + } +} +``` + +--- + +## Error Responses / Phản Hồi Lỗi + +### Standard Error Format + +```json +{ + "success": false, + "error": "Error message in English", + "errorCode": "ERROR_CODE", + "details": { + "field": "Field-specific error" + } +} +``` + +### Common Error Codes / Mã Lỗi Thường Gặp + +| Status Code | Error Code | Description | +|-------------|------------|-------------| +| 400 | `INVALID_REQUEST` | Invalid request parameters | +| 400 | `VALIDATION_ERROR` | Validation failed | +| 401 | `UNAUTHORIZED` | Missing or invalid token | +| 403 | `FORBIDDEN` | No permission | +| 403 | `INVALID_SIGNATURE` | Facebook webhook signature invalid | +| 404 | `NOT_FOUND` | Resource not found | +| 409 | `CONFLICT` | Duplicate resource | +| 429 | `RATE_LIMIT_EXCEEDED` | Too many requests | +| 500 | `INTERNAL_ERROR` | Server error | +| 503 | `SERVICE_UNAVAILABLE` | External service unavailable | + +**Example Error Response** (400): +```json +{ + "success": false, + "error": "Validation failed", + "errorCode": "VALIDATION_ERROR", + "details": { + "messageText": "Message text is required", + "conversationId": "Invalid GUID format" + } +} +``` + +--- + +## Rate Limiting / Giới Hạn Tỷ Lệ + +**EN**: API rate limits per API key: +- **100 requests/minute** for read operations (GET) +- **20 requests/minute** for write operations (POST, PUT, DELETE) + +**VI**: Giới hạn API mỗi API key: +- **100 requests/phút** cho read operations (GET) +- **20 requests/phút** cho write operations (POST, PUT, DELETE) + +**Rate Limit Headers**: +``` +X-RateLimit-Limit: 100 +X-RateLimit-Remaining: 95 +X-RateLimit-Reset: 1234567890 +``` + +--- + +## Webhooks Best Practices / Thực Hành Tốt Webhooks + +1. **Always return 200 immediately** / Luôn trả 200 ngay lập tức +2. **Process asynchronously** / Xử lý bất đồng bộ +3. **Verify signature** / Xác thực chữ ký +4. **Handle retries** / Xử lý retry (Facebook sẽ retry nếu không nhận 200) +5. **Use HTTPS** / Sử dụng HTTPS + +## Resources / Tài Nguyên + +- [Facebook Messenger Platform Webhooks](https://developers.facebook.com/docs/messenger-platform/webhooks) +- [Facebook Send API Reference](https://developers.facebook.com/docs/messenger-platform/send-messages) +- [Architecture Documentation](./ARCHITECTURE.md) +- [Facebook Setup Guide](./FACEBOOK_SETUP.md) diff --git a/services/mkt-facebook-service-net/docs/ARCHITECTURE.md b/services/mkt-facebook-service-net/docs/ARCHITECTURE.md new file mode 100644 index 00000000..46ae183e --- /dev/null +++ b/services/mkt-facebook-service-net/docs/ARCHITECTURE.md @@ -0,0 +1,556 @@ +# Architecture Documentation - Tài Liệu Kiến Trúc + +**Service**: mkt-facebook-service-net +**Last Updated**: 2026-01-18 + +## Overview / Tổng Quan + +**EN**: The Facebook Marketing Service provides a comprehensive solution for businesses to engage with customers on Facebook Messenger through automated chatbots and AI-powered conversations. + +**VI**: Dịch vụ Marketing Facebook cung cấp giải pháp toàn diện cho doanh nghiệp tương tác với khách hàng trên Facebook Messenger thông qua chatbots tự động và hội thoại AI. + +## System Architecture / Kiến Trúc Hệ Thống + +### High-Level Architecture / Kiến Trúc Tổng Quát + +```mermaid +graph TB + subgraph "Facebook Messenger Platform" + EndUser[End User] + MessengerApp[Messenger App] + end + + subgraph "GoodGo Platform" + direction TB + + subgraph "mkt-facebook-service-net" + Webhook[Webhooks Controller] + API[REST API] + + subgraph "Application Layer" + Commands[Commands] + Queries[Queries] + Handlers[MediatR Handlers] + end + + subgraph "Domain Layer" + Conversation[Conversation Aggregate] + Customer[Customer Aggregate] + ChatbotFlow[ChatbotFlow Aggregate] + AIChatbot[AIChatbotConfig Aggregate] + end + + subgraph "Infrastructure Layer" + FBClient[FacebookMessengerClient] + AIClient[OpenAI Client] + Repos[Repositories] + DbContext[EF Core DbContext] + end + end + + subgraph "Data \u0026 Messaging" + PostgreSQL[(PostgreSQL)] + Redis[(Redis)] + RabbitMQ[RabbitMQ] + end + end + + subgraph "External Services" + FacebookAPI[Facebook Graph API] + OpenAI[OpenAI / Azure OpenAI] + end + + EndUser -->|Send Message| MessengerApp + MessengerApp -->|Webhook Event| Webhook + Webhook -->|Dispatch Command| Commands + Commands --> Handlers + Handlers --> Domain Layer + Handlers --> Repos + Repos --> DbContext + DbContext --> PostgreSQL + Handlers -->|Cache| Redis + Handlers -->|Publish Events| RabbitMQ + + API -->|Commands/Queries| Handlers + + FBClient -->|HTTP| FacebookAPI + AIClient -->|HTTP| OpenAI + + Handlers -->|Send Message| FBClient + Handlers -->|AI Completion| AIClient +``` + +## Domain Model / Mô Hình Domain + +### Aggregates / Các Aggregate + +#### 1. Conversation Aggregate + +```mermaid +classDiagram + class Conversation { + +Guid Id + +Guid CustomerId + +string PageId + +ConversationStatus Status + +Channel Channel + +DateTime LastMessageAt + +DateTime CreatedAt + -List~Message~ _messages + +IReadOnlyCollection~Message~ Messages + + +AddMessage(Message) void + +MarkAsRead() void + +Assign(string agentId) void + +Close() void + } + + class Message { + +Guid Id + +string SenderId + +string Content + +MessageType Type + +MessageDirection Direction + +DateTime SentAt + +Dictionary Metadata + } + + class ConversationStatus { + <> + Active + Closed + Archived + } + + class MessageDirection { + <> + Incoming + Outgoing + } + + Conversation "1" *-- "many" Message + Conversation --> ConversationStatus + Message --> MessageDirection +``` + +**EN**: The Conversation aggregate manages the lifecycle of a customer conversation, including all messages exchanged. + +**VI**: Aggregate Conversation quản lý vòng đời của một cuộc hội thoại khách hàng, bao gồm tất cả tin nhắn trao đổi. + +**Business Rules / Quy Tắc Nghiệp Vụ**: +- Chỉ có thể thêm messages vào conversations Active +- Một conversation phải có ít nhất 1 message +- Messages không thể bị xóa, chỉ có thể archive conversation + +#### 2. Customer Aggregate + +```mermaid +classDiagram + class Customer { + +Guid Id + +string FacebookUserId + +string Name + +string Email + +string Phone + +string ProfilePicUrl + +string Locale + +string Timezone + +List~string~ Tags + +Dictionary~string,string~ CustomFields + +DateTime FirstSeenAt + +DateTime LastInteractionAt + + +UpdateProfile(CustomerProfile) void + +AddTag(string tag) void + +RemoveTag(string tag) void + +SetCustomField(string key, string value) void + } +``` + +**EN**: The Customer aggregate represents a Facebook user who interacts with the chatbot. + +**VI**: Aggregate Customer đại diện cho một Facebook user tương tác với chatbot. + +**Business Rules / Quy Tắc Nghiệp Vụ**: +- FacebookUserId là unique identifier +- Tags phải là valid strings (không rỗng) +- Custom fields giới hạn 50 fields per customer +- Profile được sync từ Facebook Messenger Platform + +#### 3. ChatbotFlow Aggregate (Automation) + +```mermaid +classDiagram + class ChatbotFlow { + +Guid Id + +string Name + +Guid ShopId + +FlowTriggerType TriggerType + +string TriggerValue + +bool IsActive + -List~FlowNode~ _nodes + +IReadOnlyCollection~FlowNode~ Nodes + + +AddNode(FlowNode) void + +ConnectNodes(Guid from, Guid to) void + +Activate() void + +Deactivate() void + } + + class FlowNode { + +Guid Id + +NodeType Type + +string Content + +Dictionary Config + +List~Guid~ NextNodeIds + } + + class NodeType { + <> + Start + Message + Question + Condition + Action + End + } + + ChatbotFlow "1" *-- "many" FlowNode + FlowNode --> NodeType +``` + +**EN**: The ChatbotFlow aggregate defines automation rules and conversation flows. + +**VI**: Aggregate ChatbotFlow định nghĩa quy tắc tự động và luồng hội thoại. + +**Business Rules / Quy Tắc Nghiệp Vụ**: +- Mỗi flow phải có đúng 1 Start node +- Mỗi flow phải có ít nhất 1 End node +- Không được có circular references (vòng lặp vô hạn) +- TriggerValue phải unique trong cùng ShopId + +#### 4. AIChatbotConfig Aggregate + +```mermaid +classDiagram + class AIChatbotConfig { + +Guid Id + +Guid ShopId + +AIProvider Provider + +string Model + +string SystemPrompt + +float Temperature + +int MaxTokens + +bool IsEnabled + +DateTime CreatedAt + +DateTime UpdatedAt + + +UpdateConfig(ConfigUpdate) void + +Enable() void + +Disable() void + } + + class AIProvider { + <> + OpenAI + AzureOpenAI + } + + AIChatbotConfig --> AIProvider +``` + +**EN**: The AIChatbotConfig aggregate configures AI-powered chatbot behavior. + +**VI**: Aggregate AIChatbotConfig cấu hình hành vi chatbot AI. + +**Business Rules / Quy Tắc Nghiệp Vụ**: +- Temperature phải trong khoảng [0.0, 2.0] +- MaxTokens phải \u003e 0 và \u003c= 4096 +- SystemPrompt không được rỗng +- Chỉ có 1 active config per ShopId + +## Message Processing Flow / Luồng Xử Lý Tin Nhắn + +```mermaid +sequenceDiagram + participant User as End User + participant FB as Facebook Messenger + participant Webhook as Webhooks Controller + participant Handler as ProcessIncomingMessage Handler + participant Domain as Domain Layer + participant Strategy as Response Strategy + participant AI as OpenAI Client + participant FBClient as Facebook Client + participant DB as PostgreSQL + + User->>FB: Send message + FB->>Webhook: POST /webhooks/facebook + Webhook->>Webhook: Verify signature + Webhook-->>FB: 200 OK (immediately) + + Webhook->>Handler: Dispatch ProcessIncomingMessageCommand + + Handler->>DB: Get or Create Customer + Handler->>DB: Get or Create Conversation + Handler->>Domain: conversation.AddMessage(incoming) + Handler->>DB: Save changes + + Handler->>Strategy: DetermineStrategy(conversation) + + alt AI Chatbot Enabled + Strategy-->>Handler: Use AI + Handler->>AI: GetChatCompletion(context) + AI-->>Handler: AI Response + else Automation Flow + Strategy-->>Handler: Use Automation + Handler->>DB: Find matching FlowNode + Handler->>Handler: Execute flow logic + end + + Handler->>FBClient: SendMessage(response) + FBClient->>FB: POST /messages + FB-->>FBClient: Success + + Handler->>Domain: conversation.AddMessage(outgoing) + Handler->>DB: Save changes +``` + +**Key Steps / Các Bước Chính**: + +1. **Webhook Reception / Nhận Webhook**: Facebook gửi event đến service +2. **Signature Verification / Xác thực Chữ ký**: Verify Facebook request signature +3. **Customer \u0026 Conversation Management / Quản lý Khách hàng \u0026 Hội thoại**: Get hoặc tạo mới +4. **Strategy Selection / Lựa chọn Chiến lược**: Automation vs AI +5. **Response Generation / Tạo Phản hồi**: Dựa trên strategy +6. **Send Message / Gửi Tin nhắn**: Qua Facebook Messenger API +7. **Persistence / Lưu trữ**: Save message history + +## Integration Patterns / Mẫu Tích Hợp + +### Facebook Messenger Platform Integration + +**EN**: The service integrates with Facebook Messenger Platform via: +- **Webhooks**: Receive messages, postbacks, read receipts +- **Send API**: Send messages, quick replies, templates +- **User Profile API**: Fetch user information + +**VI**: Dịch vụ tích hợp với Facebook Messenger Platform qua: +- **Webhooks**: Nhận messages, postbacks, read receipts +- **Send API**: Gửi messages, quick replies, templates +- **User Profile API**: Lấy thông tin user + +### OpenAI Integration + +**EN**: AI chatbot uses OpenAI Chat Completions API with: +- **Streaming**: Real-time response generation +- **Context Management**: Multi-turn conversations +- **Retry Logic**: Polly resilience policies +- **Cost Tracking**: Monitor token usage + +**VI**: AI chatbot sử dụng OpenAI Chat Completions API với: +- **Streaming**: Tạo phản hồi real-time +- **Context Management**: Hội thoại nhiều lượt +- **Retry Logic**: Polly resilience policies +- **Cost Tracking**: Theo dõi sử dụng tokens + +## Data Model / Mô Hình Dữ Liệu + +### Database Schema / Lược Đồ Cơ Sở Dữ Liệu + +```mermaid +erDiagram + CONVERSATIONS ||--o{ MESSAGES : contains + CUSTOMERS ||--o{ CONVERSATIONS : has + CHATBOT_FLOWS ||--o{ FLOW_NODES : contains + AI_CHATBOT_CONFIGS ||--|| SHOPS : belongs_to + + CONVERSATIONS { + uuid id PK + uuid customer_id FK + string page_id + string status + string channel + timestamp last_message_at + timestamp created_at + } + + MESSAGES { + uuid id PK + uuid conversation_id FK + string sender_id + text content + string message_type + string direction + jsonb metadata + timestamp sent_at + } + + CUSTOMERS { + uuid id PK + string facebook_user_id UK + string name + string email + string profile_pic_url + string locale + string timezone + text[] tags + jsonb custom_fields + timestamp first_seen_at + timestamp last_interaction_at + } + + CHATBOT_FLOWS { + uuid id PK + uuid shop_id FK + string name + string trigger_type + string trigger_value UK + boolean is_active + timestamp created_at + } + + FLOW_NODES { + uuid id PK + uuid flow_id FK + string node_type + text content + jsonb config + uuid[] next_node_ids + int order_index + } + + AI_CHATBOT_CONFIGS { + uuid id PK + uuid shop_id FK UK + string provider + string model + text system_prompt + float temperature + int max_tokens + boolean is_enabled + timestamp updated_at + } +``` + +### Indexes / Chỉ Mục + +**Performance Optimization / Tối Ưu Hiệu Năng**: +- `idx_conversations_customer_id` - Fast lookup by customer +- `idx_conversations_page_id_status` - Filter active conversations by page +- `idx_messages_conversation_id_sent_at` - Sort messages chronologically +- `idx_customers_facebook_user_id` - Unique lookup +- `idx_chatbot_flows_shop_id_trigger` - Match triggers +- `idx_ai_configs_shop_id` - One config per shop + +## Security / Bảo Mật + +### Facebook Webhook Verification + +**EN**: All incoming webhooks must: +1. Include `X-Hub-Signature-256` header +2. Signature verified using App Secret +3. Invalid signatures rejected with 403 + +**VI**: Tất cả webhooks phải: +1. Có header `X-Hub-Signature-256` +2. Signature được verify bằng App Secret +3. Signature không hợp lệ bị reject với 403 + +### API Authentication + +**EN**: REST API endpoints require: +- JWT Bearer token from IAM service +- Role-based authorization (Admin, Agent, Viewer) + +**VI**: REST API endpoints yêu cầu: +- JWT Bearer token từ IAM service +- Authorization theo role (Admin, Agent, Viewer) + +### Data Privacy / Quyền Riêng Tư Dữ Liệu + +- **GDPR Compliance**: Customer data export và deletion +- **Data Encryption**: At rest (PostgreSQL) và in transit (HTTPS) +- **PII Protection**: Customer info không log ra files + +## Scalability Considerations / Cân Nhắc Khả Năng Mở Rộng + +### Horizontal Scaling / Mở Rộng Ngang + +**EN**: Service supports horizontal scaling with: +- **Stateless API**: No server-side sessions +- **Redis Cache**: Shared cache across instances +- **RabbitMQ**: Distributed message queue +- **Load Balancer**: Traefik distributes traffic + +**VI**: Service hỗ trợ mở rộng ngang với: +- **Stateless API**: Không có server-side sessions +- **Redis Cache**: Cache chia sẻ giữa các instances +- **RabbitMQ**: Message queue phân tán +- **Load Balancer**: Traefik phân phối traffic + +### Rate Limiting / Giới Hạn Tỷ Lệ + +**EN**: Facebook Messenger API limits: +- **100 messages/second** per app +- **Burst tolerance**: Queue messages during spikes +- **Retry with exponential backoff**: For 429 responses + +**VI**: Giới hạn Facebook Messenger API: +- **100 tin nhắn/giây** mỗi app +- **Burst tolerance**: Queue messages khi tăng đột biến +- **Retry with exponential backoff**: Cho responses 429 + +## Monitoring \u0026 Observability / Giám Sát + +### Key Metrics / Chỉ Số Chính + +| Metric | Description / Mô Tả | Target / Mục Tiêu | +|--------|---------------------|-------------------| +| **Webhook Latency** | Time to return 200 to Facebook | \u003c 500ms | +| **Message Processing Time** | Time to generate \u0026 send response | \u003c 2s | +| **AI Response Time** | OpenAI API latency | \u003c 5s | +| **Message Success Rate** | % messages sent successfully | \u003e 99% | +| **Conversation Active Count** | Number of active conversations | - | +| **AI Cost per Conversation** | Average OpenAI cost | Monitor | + +### Health Checks / Kiểm Tra Sức Khỏe + +- **Database**: PostgreSQL connection pooling +- **Redis**: Cache availability +- **RabbitMQ**: Message broker connection +- **Facebook API**: API availability check +- **OpenAI API**: Provider availability + +## Design Decisions / Quyết Định Thiết Kế + +### Why CQRS? / Tại Sao CQRS? + +**EN**: Separate read and write operations for: +- **Optimized Queries**: Use Dapper for fast reads +- **Complex Commands**: Use EF Core with Domain Model +- **Scalability**: Scale reads và writes independently + +**VI**: Tách biệt operations đọc và ghi để: +- **Queries Tối Ưu**: Dùng Dapper cho reads nhanh +- **Commands Phức Tạp**: Dùng EF Core với Domain Model +- **Khả Năng Mở Rộng**: Scale reads và writes độc lập + +### Why DDD? / Tại Sao DDD? + +**EN**: Complex business logic requires: +- **Rich Domain Model**: Conversation, Customer aggregates +- **Encapsulation**: Business rules trong domain +- **Domain Events**: Decouple side effects + +**VI**: Logic nghiệp vụ phức tạp yêu cầu: +- **Rich Domain Model**: Conversation, Customer aggregates +- **Encapsulation**: Business rules trong domain +- **Domain Events**: Tách biệt side effects + +## Resources / Tài Nguyên + +- [API Documentation](./API.md) +- [Facebook Setup Guide](./FACEBOOK_SETUP.md) +- [AI Chatbot Guide](./AI_CHATBOT.md) +- [Domain-Driven Design Skill](../../../.agent/skills/domain-driven-design/SKILL.md) +- [CQRS MediatR Skill](../../../.agent/skills/cqrs-mediatr/SKILL.md) diff --git a/services/mkt-facebook-service-net/docs/FACEBOOK_SETUP.md b/services/mkt-facebook-service-net/docs/FACEBOOK_SETUP.md new file mode 100644 index 00000000..b46bd7d1 --- /dev/null +++ b/services/mkt-facebook-service-net/docs/FACEBOOK_SETUP.md @@ -0,0 +1,381 @@ +# Facebook Messenger Setup Guide - Hướng Dẫn Thiết Lập + +**EN**: Step-by-step guide to set up Facebook Messenger Platform integration. + +**VI**: Hướng dẫn từng bước để thiết lập tích hợp Facebook Messenger Platform. + +## Prerequisites / Yêu Cầu + +- Facebook account / Tài khoản Facebook +- Facebook Page (đã tạo sẵn) +- Developer account on Meta for Developers / Tài khoản developer trên Meta for Developers +- HTTPS endpoint for webhook / Endpoint HTTPS cho webhook (production) +- ngrok (cho local testing) + +## Step 1: Create Facebook App / Tạo Facebook App + +### 1.1 Access Meta for Developers + +**EN**: +1. Go to [developers.facebook.com](https://developers.facebook.com/) +2. Click "My Apps" → "Create App" +3. Select use case: **"Other"** +4. Select app type: **"Business"** + +**VI**: +1. Truy cập [developers.facebook.com](https://developers.facebook.com/) +2. Click "My Apps" → "Create App" +3. Chọn use case: **"Other"** +4. Chọn app type: **"Business"** + +### 1.2 App Configuration + +**EN**: +- **App Name**: e.g., "My Shop Chatbot" +- **App Contact Email**: your email +- **Business Account**: Select or create + +**VI**: +- **App Name**: ví dụ, "My Shop Chatbot" +- **App Contact Email**: email của bạn +- **Business Account**: Chọn hoặc tạo mới + +> [!NOTE] +> Copy your **App ID** and **App Secret** (Settings → Basic). You'll need these later. + +--- + +## Step 2: Add Messenger Product / Thêm Messenger Product + +### 2.1 Add Messenger + +**EN**: +1. In your app dashboard, click **"Add Product"** +2. Find **"Messenger"** and click **"Set Up"** + +**VI**: +1. Trong app dashboard, click **"Add Product"** +2. Tìm **"Messenger"** và click **"Set Up"** + +### 2.2 Generate Page Access Token + +**EN**: +1. In Messenger Settings, scroll to **"Access Tokens"** +2. Click **"Add or Remove Pages"** +3. Select your Facebook Page +4. Click **"Generate Token"** +5. **Copy and save** the Page Access Token + +**VI**: +1. Trong Messenger Settings, scroll đến **"Access Tokens"** +2. Click **"Add or Remove Pages"** +3. Chọn Facebook Page của bạn +4. Click **"Generate Token"** +5. **Copy và lưu** Page Access Token + +```bash +# EN: Save to .env file / VI: Lưu vào file .env +FACEBOOK_PAGE_ACCESS_TOKEN="EAAxxxxxxxxxx..." +``` + +> [!WARNING] +> Page Access Token is sensitive! Never commit to Git or expose publicly. + +--- + +## Step 3: Configure Webhook / Cấu Hình Webhook + +### 3.1 Deploy Service or Use ngrok + +**Option A: Local Development with ngrok** + +```bash +# EN: Install ngrok / VI: Cài đặt ngrok +brew install ngrok # macOS +# or download from ngrok.com + +# EN: Run service locally / VI: Chạy service local +dotnet run --project src/MktFacebookService.API + +# EN: Expose local service / VI: Expose service local +ngrok http 5000 + +# Copy HTTPS URL, e.g., https://abc123.ngrok.io +``` + +**Option B: Production Deployment** + +Deploy service to production server với HTTPS enabled. + +### 3.2 Add Webhook in Facebook App + +**EN**: +1. Go to Messenger → Settings → **"Webhooks"** +2. Click **"Add Callback URL"** +3. Enter: + - **Callback URL**: `https://your-domain.com/api/v1/webhooks/facebook` + - **Verify Token**: Create a random string (e.g., `my_verify_token_12345`) +4. Click **"Verify and Save"** + +**VI**: +1. Vào Messenger → Settings → **"Webhooks"** +2. Click **"Add Callback URL"** +3. Nhập: + - **Callback URL**: `https://your-domain.com/api/v1/webhooks/facebook` + - **Verify Token**: Tạo chuỗi random (ví dụ, `my_verify_token_12345`) +4. Click **"Verify and Save"** + +```bash +# EN: Save to .env / VI: Lưu vào .env +FACEBOOK_VERIFY_TOKEN="my_verify_token_12345" +``` + +> [!IMPORTANT] +> Verify Token phải match với giá trị trong service configuration! + +### 3.3 Subscribe to Webhook Events + +**EN**: After webhook is verified, select fields: + +**VI**: Sau khi webhook được verified, chọn các fields: + +- [x] **messages** - Receive customer messages +- [x] **messaging_postbacks** - Receive button clicks +- [x] **message_reads** - Receive read receipts (optional) +- [x] **messaging_optins** - Receive opt-in events + +Click **"Subscribe"**. + +--- + +## Step 4: Configure App Settings / Cấu Hình App Settings + +### 4.1 App Review (Production Only) + +**EN**: For production, you need to submit for app review: + +**VI**: Để production, cần submit app review: + +1. Go to **"App Review"** → **"Permissions and Features"** +2. Request **"pages_messaging"** permission +3. Provide: + - Screencast demo video + - Privacy Policy URL + - Terms of Service URL +4. Submit for review (takes 1-3 days) + +> [!NOTE] +> For testing, you can use Test Users without app review. + +### 4.2 Privacy Policy \u0026 Terms + +**EN**: Add Privacy Policy and Terms of Service URLs in **Settings → Basic**. + +**VI**: Thêm Privacy Policy và Terms of Service URLs trong **Settings → Basic**. + +--- + +## Step 5: Test Integration / Kiểm Tra Tích Hợp + +### 5.1 Send Test Message + +**EN**: +1. Go to your Facebook Page +2. Click **"Send Message"** (as a user, not admin) +3. Type: `Hello` +4. Check service logs for incoming webhook event + +**VI**: +1. Vào Facebook Page của bạn +2. Click **"Send Message"** (với tư cách user, không phải admin) +3. Gõ: `Hello` +4. Kiểm tra logs của service cho incoming webhook event + +**Expected Log**: +``` +[INFO] Received message event from user: 1234567890 +[INFO] Processing incoming message: "Hello" +[INFO] Sending response via Facebook Messenger +``` + +### 5.2 Test Get Started Button + +**EN**: Configure Get Started button to trigger welcome flow. + +**VI**: Cấu hình nút Get Started để trigger welcome flow. + +**cURL Command**: +```bash +curl -X POST "https://graph.facebook.com/v21.0/me/messenger_profile" \ + -H "Content-Type: application/json" \ + -d '{ + "get_started": { + "payload": "GET_STARTED" + } + }' \ + -d "access_token=YOUR_PAGE_ACCESS_TOKEN" +``` + +### 5.3 Test Quick Replies + +**Postman Request**: +```http +POST https://localhost/api/v1/conversations/{conversationId}/messages +Authorization: Bearer {jwt_token} +Content-Type: application/json + +{ + "messageText": "How can I help you?", + "quickReplies": [ + { "title": "Product Info", "payload": "PRODUCT_INFO" }, + { "title": "Contact Support", "payload": "SUPPORT" } + ] +} +``` + +--- + +## Step 6: Configure Persistent Menu (Optional) / Cấu Hình Menu Cố Định + +**EN**: Add a persistent menu for quick access to common actions. + +**VI**: Thêm menu cố định để truy cập nhanh các actions thường dùng. + +```bash +curl -X POST "https://graph.facebook.com/v21.0/me/messenger_profile" \ + -H "Content-Type: application/json" \ + -d '{ + "persistent_menu": [{ + "locale": "default", + "call_to_actions": [ + { + "type": "postback", + "title": "Shop Now", + "payload": "MENU_SHOP" + }, + { + "type": "postback", + "title": "My Orders", + "payload": "MENU_ORDERS" + }, + { + "type": "postback", + "title": "Help", + "payload": "MENU_HELP" + } + ] + }] + }' \ + -d "access_token=YOUR_PAGE_ACCESS_TOKEN" +``` + +--- + +## Environment Variables Summary / Tổng Hợp Biến Môi Trường + +```bash +# Facebook App Configuration +FACEBOOK_APP_ID="123456789012345" +FACEBOOK_APP_SECRET="abcdef1234567890abcdef1234567890" +FACEBOOK_VERIFY_TOKEN="my_verify_token_12345" + +# Facebook Page Access Token +FACEBOOK_PAGE_ACCESS_TOKEN="EAAxxxxxxxxxx..." + +# Facebook API Version +FACEBOOK_API_VERSION="v21.0" +``` + +--- + +## Troubleshooting / Xử Lý Sự Cố + +### Issue 1: Webhook Verification Failed + +**Problem / Vấn đề**: +``` +The URL couldn't be validated. Callback verification failed with the following errors: ... +``` + +**Solution / Giải pháp**: +1. Check service is running và accessible qua HTTPS +2. Verify `FACEBOOK_VERIFY_TOKEN` match exactly +3. Check logs for webhook GET request +4. Ensure returning hub.challenge as plain text (not JSON) + +### Issue 2: Not Receiving Messages + +**Problem / Vấn đề**: Service không nhận được messages + +**Solution / Giải pháp**: +1. Verify webhook subscriptions are active (messages, messaging_postbacks) +2. Check Page Access Token chưa expire +3. Test webhook manually: + ```bash + curl -X POST https://your-domain.com/api/v1/webhooks/facebook \ + -H "X-Hub-Signature-256: sha256=test" \ + -H "Content-Type: application/json" \ + -d '{...sample payload...}' + ``` + +### Issue 3: Cannot Send Messages + +**Problem / Vấn đề**: +``` +(#200) This user can't receive messages from this bot +``` + +**Solution / Giải pháp**: +- User must send a message first (GDPR compliance) +- Or user must opt-in via checkbox plugin +- Page Access Token phải có `pages_messaging` permission + +### Issue 4: Signature Verification Failed + +**Problem / Vấn đề**: `X-Hub-Signature-256 validation failed` + +**Solution / Giải pháp**: +1. Check `FACEBOOK_APP_SECRET` is correct +2. Verify signature calculation algorithm: +```csharp +var hash = HMACSHA256.HashData( + Encoding.UTF8.GetBytes(appSecret), + Encoding.UTF8.GetBytes(requestBody)); +var signature = "sha256=" + Convert.ToHexString(hash).ToLower(); +``` + +--- + +## Testing Checklist / Danh Sách Kiểm Tra + +- [ ] Facebook App created và Messenger product added +- [ ] Page Access Token generated và saved +- [ ] Webhook configured và verified +- [ ] Webhook events subscribed (messages, postbacks) +- [ ] Test message sent và received successfully +- [ ] Bot response sent back to user +- [ ] Get Started button triggers welcome flow +- [ ] Quick replies work correctly +- [ ] Persistent menu configured (if applicable) +- [ ] Signature verification working +- [ ] Error handling tested + +--- + +## Resources / Tài Nguyên + +### Official Facebook Documentation +- [Messenger Platform Overview](https://developers.facebook.com/docs/messenger-platform/) +- [Webhooks Reference](https://developers.facebook.com/docs/messenger-platform/webhooks) +- [Send API Reference](https://developers.facebook.com/docs/messenger-platform/send-messages) +- [Messenger Profile API](https://developers.facebook.com/docs/messenger-platform/messenger-profile) + +### Tools +- [Facebook Graph API Explorer](https://developers.facebook.com/tools/explorer/) +- [Webhook Tester](https://webhook.site/) - Test webhooks +- [ngrok](https://ngrok.com/) - Local HTTPS tunnel + +### Internal Docs +- [API Documentation](./API.md) +- [Architecture Documentation](./ARCHITECTURE.md) +- [AI Chatbot Configuration](./AI_CHATBOT.md) diff --git a/services/mkt-facebook-service-net/docs/README.md b/services/mkt-facebook-service-net/docs/README.md new file mode 100644 index 00000000..4a21b9a3 --- /dev/null +++ b/services/mkt-facebook-service-net/docs/README.md @@ -0,0 +1,69 @@ +# Documentation Index + +This directory contains comprehensive documentation for the **mkt-facebook-service-net** service. + +## Language-Specific Documentation + +Documentation is available in both English and Vietnamese: + +### English Documentation (`docs/en/`) +- [README.md](./en/README.md) - Service overview and quick start +- [ARCHITECTURE.md](./en/ARCHITECTURE.md) - System architecture and domain model +- [API.md](./en/API.md) - Complete API reference +- [FACEBOOK_SETUP.md](./en/FACEBOOK_SETUP.md) - Facebook Messenger Platform setup guide +- [AI_CHATBOT.md](./en/AI_CHATBOT.md) - AI chatbot configuration guide + +### Vietnamese Documentation (`docs/vi/`/ Tài Liệu Tiếng Việt) +- [README.md](./vi/README.md) - Tổng quan dịch vụ và bắt đầu nhanh +- [ARCHITECTURE.md](./vi/ARCHITECTURE.md) - Kiến trúc hệ thống và domain model +- [API.md](./vi/API.md) - Tài liệu API đầy đủ +- [FACEBOOK_SETUP.md](./vi/FACEBOOK_SETUP.md) - Hướng dẫn thiết lập Facebook Messenger Platform +- [AI_CHATBOT.md](./vi/AI_CHATBOT.md) - Hướng dẫn cấu hình AI chatbot + +## Quick Links + +### For Developers +1. Start with [README.md](./en/README.md) for project overview +2. Review [ARCHITECTURE.md](./en/ARCHITECTURE.md) for system design +3. Follow [Facebook Setup Guide](./en/FACEBOOK_SETUP.md) to configure integration +4. Check [API Documentation](./en/API.md) for endpoint details + +### Cho Developers +1. Bắt đầu với [README.md](./vi/README.md) để có cái nhìn tổng quan +2. Xem [ARCHITECTURE.md](./vi/ARCHITECTURE.md) để hiểu thiết kế hệ thống +3. Làm theo [Hướng Dẫn Setup Facebook](./vi/FACEBOOK_SETUP.md) để cấu hình tích hợp +4. Kiểm tra [Tài Liệu API](./vi/API.md) để biết chi tiết endpoints + +## Documentation Structure + +``` +docs/ +├── README.md # This index file +├── en/ # English documentation +│ ├── README.md +│ ├── ARCHITECTURE.md +│ ├── API.md +│ ├── FACEBOOK_SETUP.md +│ └── AI_CHATBOT.md +└── vi/ # Vietnamese documentation + ├── README.md + ├── ARCHITECTURE.md + ├── API.md + ├── FACEBOOK_SETUP.md + └── AI_CHATBOT.md +``` + +## Contributing to Documentation + +When updating documentation: +1. Update **both** English and Vietnamese versions +2. Keep content synchronized between languages +3. Follow the [Documentation Guidelines](../../.agent/skills/documentation/SKILL.md) +4. Test all code examples and commands +5. Verify all links work correctly + +## Related Resources + +- [Implementation Plan](../../.gemini/antigravity/brain/3990792e-0d08-48d3-a8bd-1443e3c5efc6/implementation_plan.md) +- [GoodGo Project Rules](../../.agent/skills/project-rules/SKILL.md) +- [.NET Microservice Workflow](../../.agent/skills/dotnet-microservice-workflow/SKILL.md) diff --git a/services/mkt-facebook-service-net/docs/en/README.md b/services/mkt-facebook-service-net/docs/en/README.md new file mode 100644 index 00000000..18301b34 --- /dev/null +++ b/services/mkt-facebook-service-net/docs/en/README.md @@ -0,0 +1,295 @@ +# Marketing Facebook Service + +> Facebook Messenger Marketing Service with Automation Chatbot, AI-Powered Chatbot, and Customer Management + +[![.NET Version](https://img.shields.io/badge/.NET-8.0-512BD4)](https://dotnet.microsoft.com/) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) + +## Features + +### 1. 🤖 CHATBOT Automation Messenger + +Rules-based chatbot with predefined conversation flows: +- Visual flow builder with nodes (Message, Question, Condition, Action) +- Keyword triggers and postback handlers +- Quick replies and button templates +- Multi-language support +- A/B testing for flows + +### 2. 🧠 CHATBOT AI Messenger + +Intelligent chatbot powered by OpenAI/Azure OpenAI: +- Natural language understanding and generation +- Context-aware conversations +- Customizable system prompts +- Multi-turn dialogue support +- Fallback to automation rules +- Cost tracking and optimization + +### 3. 👥 Customer Management + +Comprehensive customer data management: +- Customer profiles with Facebook user info +- Conversation history tracking +- Custom fields and tags +- Segmentation by behavior +- Export customer data +- GDPR compliance + +## Quick Start + +### Prerequisites + +- .NET 8.0 SDK +- PostgreSQL 15+ (or Neon serverless) +- Redis 7+ +- RabbitMQ 3.12+ +- Docker & Docker Compose (for local development) +- **Facebook Page** and **Facebook App** with Messenger Platform +- **OpenAI API Key** or **Azure OpenAI** (for AI Chatbot) + +### Configuration + +```bash +# Copy environment template +cp .env.example .env + +# Update configuration +# - DATABASE_URL (PostgreSQL connection string) +# - REDIS_URL +# - RABBITMQ_URL +# - FACEBOOK_VERIFY_TOKEN (webhook verification) +# - FACEBOOK_PAGE_ACCESS_TOKEN (send messages) +# - OPENAI_API_KEY (AI chatbot) +``` + +### Local Development + +```bash +# Restore dependencies +dotnet restore + +# Apply migrations +dotnet ef database update --project src/MktFacebookService.Infrastructure + +# Run service +dotnet run --project src/MktFacebookService.API + +# Service available at http://localhost:5000 +# Swagger UI: http://localhost:5000/swagger +``` + +### Docker Deployment + +```bash +# Build and run with Docker Compose +cd deployments/local +docker-compose up -d mkt-facebook-service-net + +# View logs +docker-compose logs -f mkt-facebook-service-net + +# Access via Traefik +# http://localhost/api/v1/mkt-facebook +``` + +## Architecture + +```mermaid +graph TD + subgraph "External" + FB[Facebook Messenger Platform] + OAI[OpenAI / Azure OpenAI] + User[End User on Messenger] + end + + subgraph "mkt-facebook-service-net" + WH[Webhooks Controller] + API[REST API Controllers] + APP[Application Layer CQRS] + DOM[Domain Layer] + INFRA[Infrastructure Layer] + end + + subgraph "Data Stores" + PG[(PostgreSQL)] + RD[(Redis Cache)] + RMQ[RabbitMQ] + end + + User -->|Send Message| FB + FB -->|Webhook Event| WH + WH -->|Process Message Command| APP + API -->|Commands/Queries| APP + APP -->|Business Logic| DOM + APP -->|Persistence| INFRA + INFRA -->|EF Core| PG + INFRA -->|Caching| RD + INFRA -->|Events| RMQ + APP -->|Send Message| INFRA + INFRA -->|API Call| FB + APP -->|AI Completion| INFRA + INFRA -->|API Call| OAI +``` + +### Technology Stack + +| Layer | Technology | +|-------|------------| +| **Backend** | .NET 8, ASP.NET Core 8 | +| **Architecture** | Clean Architecture, DDD, CQRS | +| **Database** | PostgreSQL 15+, EF Core 8 | +| **Cache** | Redis, StackExchange.Redis | +| **Messaging** | RabbitMQ, MassTransit | +| **HTTP Client** | HttpClient Factory, Polly | +| **AI** | OpenAI SDK, Azure.AI.OpenAI | +| **API Gateway** | Traefik | +| **Documentation** | Swagger/OpenAPI 3.0 | + +## API Endpoints + +### Public API + +| Endpoint | Method | Description | +|----------|--------|-------------| +| `/api/v1/webhooks/facebook` | GET | Facebook webhook verification | +| `/api/v1/webhooks/facebook` | POST | Receive Facebook Messenger events | +| `/api/v1/conversations` | GET | List conversations | +| `/api/v1/conversations/{id}` | GET | Get conversation by ID | +| `/api/v1/conversations/{id}/messages` | POST | Send message | +| `/api/v1/customers` | GET | List customers | +| `/api/v1/customers/{id}` | GET | Customer details | +| `/api/v1/customers/{id}` | PUT | Update customer info | + +### Admin API + +| Endpoint | Method | Description | +|----------|--------|-------------| +| `/api/v1/chatbots/flows` | GET | List automation flows | +| `/api/v1/chatbots/flows` | POST | Create chatbot flow | +| `/api/v1/chatbots/flows/{id}` | PUT | Update flow | +| `/api/v1/chatbots/flows/{id}` | DELETE | Delete flow | +| `/api/v1/chatbots/ai-config` | GET | Get AI chatbot config | +| `/api/v1/chatbots/ai-config` | PUT | Update AI config | + +### Health & Monitoring + +| Endpoint | Description | +|----------|-------------| +| `/health` | Health check endpoint | +| `/swagger` | Swagger UI documentation | + +## Documentation + +- [Architecture Documentation](./ARCHITECTURE.md) - System design and domain model +- [API Documentation](./API.md) - Complete API reference with examples +- [Facebook Messenger Setup](./FACEBOOK_SETUP.md) - Facebook App setup guide +- [AI Chatbot Configuration](./AI_CHATBOT.md) - AI integration guide + +## Project Structure + +``` +mkt-facebook-service-net/ +├── src/ +│ ├── MktFacebookService.API/ # API Layer +│ │ ├── Controllers/ # REST Controllers +│ │ ├── Application/ # CQRS Commands/Queries +│ │ └── Program.cs # Entry point +│ ├── MktFacebookService.Domain/ # Domain Layer +│ │ ├── AggregatesModel/ # Aggregates, Entities +│ │ │ ├── ConversationAggregate/ +│ │ │ ├── CustomerAggregate/ +│ │ │ └── ChatbotAggregate/ +│ │ └── SeedWork/ # Base classes +│ └── MktFacebookService.Infrastructure/ # Infrastructure Layer +│ ├── Data/ # EF Core DbContext +│ ├── Repositories/ # Repository implementations +│ └── ExternalServices/ # Facebook, OpenAI clients +├── tests/ +│ ├── MktFacebookService.UnitTests/ +│ └── MktFacebookService.FunctionalTests/ +├── docs/ # Documentation +├── Dockerfile +└── MktFacebookService.slnx +``` + +## Environment Variables + +| Variable | Description | Default | +|----------|-------------|---------| +| `DATABASE_URL` | PostgreSQL connection string | - | +| `REDIS_URL` | Redis connection string | `localhost:6379` | +| `RABBITMQ_URL` | RabbitMQ connection string | `localhost:5672` | +| `FACEBOOK_VERIFY_TOKEN` | Webhook verification token | - | +| `FACEBOOK_PAGE_ACCESS_TOKEN` | Page access token for sending messages | - | +| `FACEBOOK_API_VERSION` | Facebook API version | `v21.0` | +| `OPENAI_API_KEY` | OpenAI API key | - | +| `OPENAI_MODEL` | OpenAI model name | `gpt-4-turbo` | +| `AZURE_OPENAI_ENDPOINT` | Azure OpenAI endpoint (optional) | - | +| `ASPNETCORE_ENVIRONMENT` | Environment (Development/Production) | `Development` | + +## Development Workflow + +### Phase 1: Domain Layer +1. Create Aggregates (Conversation, Customer, ChatbotFlow, AIChatbotConfig) +2. Define Entities and Value Objects +3. Implement business rules in domain methods +4. Raise Domain Events + +### Phase 2: Infrastructure Layer +1. Setup EF Core DbContext and entity configurations +2. Create repositories implementing domain interfaces +3. Implement FacebookMessengerClient +4. Implement OpenAIClient with Polly resilience +5. Apply database migrations + +### Phase 3: Application Layer (CQRS) +1. Create Commands (ProcessIncomingMessage, SendMessage, CreateChatbotFlow) +2. Create Queries (GetConversations, GetCustomers) +3. Implement MediatR Handlers +4. Add FluentValidation validators +5. Setup Pipeline Behaviors + +### Phase 4: API Layer +1. Implement WebhooksController for Facebook events +2. Create REST API Controllers +3. Add Swagger annotations +4. Configure authentication & authorization +5. Setup health checks + +## Testing + +```bash +# Run all tests +dotnet test + +# Run unit tests only +dotnet test tests/MktFacebookService.UnitTests/ + +# Run with coverage +dotnet test /p:CollectCoverage=true /p:CoverageReportsFormat=opencover +``` + +## Contributing + +Please follow the [GoodGo Project Rules](../../.agent/skills/project-rules/SKILL.md) and [.NET Microservice Workflow](../../.agent/skills/dotnet-microservice-workflow/SKILL.md). + +## License + +MIT License + +## Resources + +### Facebook Messenger Platform +- [Messenger Platform Overview](https://developers.facebook.com/docs/messenger-platform/) +- [Webhook Reference](https://developers.facebook.com/docs/messenger-platform/webhooks) +- [Send API Reference](https://developers.facebook.com/docs/messenger-platform/send-messages) + +### OpenAI +- [OpenAI API Documentation](https://platform.openai.com/docs/introduction) +- [Chat Completions Guide](https://platform.openai.com/docs/guides/chat-completions) + +### Internal Skills +- [API Design Skill](../../.agent/skills/api-design/SKILL.md) +- [CQRS MediatR Skill](../../.agent/skills/cqrs-mediatr/SKILL.md) +- [Domain-Driven Design Skill](../../.agent/skills/domain-driven-design/SKILL.md) diff --git a/services/mkt-facebook-service-net/docs/vi/README.md b/services/mkt-facebook-service-net/docs/vi/README.md new file mode 100644 index 00000000..d29b6946 --- /dev/null +++ b/services/mkt-facebook-service-net/docs/vi/README.md @@ -0,0 +1,295 @@ +# Dịch Vụ Marketing Facebook + +> Dịch vụ Marketing Facebook Messenger với Chatbot Tự Động, Chatbot AI, và Quản Lý Khách Hàng + +[![.NET Version](https://img.shields.io/badge/.NET-8.0-512BD4)](https://dotnet.microsoft.com/) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) + +## Tính Năng + +### 1. 🤖 CHATBOT Automation Messenger + +Chatbot dựa trên quy tắc với luồng hội thoại định sẵn: +- Trình tạo flow trực quan với các nodes (Message, Question, Condition, Action) +- Triggers theo từ khóa và xử lý postback +- Quick replies và button templates +- Hỗ trợ đa ngôn ngữ +- A/B testing cho các flows + +### 2. 🧠 CHATBOT AI Messenger + +Chatbot thông minh được hỗ trợ bởi OpenAI/Azure OpenAI: +- Hiểu và sinh ngôn ngữ tự nhiên +- Hội thoại theo ngữ cảnh +- Tùy chỉnh system prompts +- Hỗ trợ đối thoại nhiều lượt +- Fallback về automation rules +- Theo dõi chi phí và tối ưu hóa + +### 3. 👥 Quản Lý Khách Hàng + +Quản lý dữ liệu khách hàng toàn diện: +- Hồ sơ khách hàng với thông tin Facebook user +- Theo dõi lịch sử hội thoại +- Custom fields và tags +- Phân khúc theo hành vi +- Xuất dữ liệu khách hàng +- Tuân thủ GDPR + +## Bắt Đầu Nhanh + +### Yêu Cầu + +- .NET 8.0 SDK +- PostgreSQL 15+ (hoặc Neon serverless) +- Redis 7+ +- RabbitMQ 3.12+ +- Docker & Docker Compose (cho local development) +- **Facebook Page** và **Facebook App** với Messenger Platform +- **OpenAI API Key** hoặc **Azure OpenAI** (cho AI Chatbot) + +### Cấu Hình + +```bash +# Sao chép template môi trường +cp .env.example .env + +# Cập nhật cấu hình +# - DATABASE_URL (PostgreSQL connection string) +# - REDIS_URL +# - RABBITMQ_URL +# - FACEBOOK_VERIFY_TOKEN (webhook verification) +# - FACEBOOK_PAGE_ACCESS_TOKEN (send messages) +# - OPENAI_API_KEY (AI chatbot) +``` + +### Phát Triển Local + +```bash +# Khôi phục dependencies +dotnet restore + +# Áp dụng migrations +dotnet ef database update --project src/MktFacebookService.Infrastructure + +# Chạy service +dotnet run --project src/MktFacebookService.API + +# Service có sẵn tại http://localhost:5000 +# Swagger UI: http://localhost:5000/swagger +``` + +### Triển Khai Docker + +```bash +# Build và chạy với Docker Compose +cd deployments/local +docker-compose up -d mkt-facebook-service-net + +# Xem logs +docker-compose logs -f mkt-facebook-service-net + +# Truy cập qua Traefik +# http://localhost/api/v1/mkt-facebook +``` + +## Kiến Trúc + +```mermaid +graph TD + subgraph "Bên Ngoài" + FB[Facebook Messenger Platform] + OAI[OpenAI / Azure OpenAI] + User[Người dùng trên Messenger] + end + + subgraph "mkt-facebook-service-net" + WH[Webhooks Controller] + API[REST API Controllers] + APP[Application Layer CQRS] + DOM[Domain Layer] + INFRA[Infrastructure Layer] + end + + subgraph "Data Stores" + PG[(PostgreSQL)] + RD[(Redis Cache)] + RMQ[RabbitMQ] + end + + User -->|Gửi Tin nhắn| FB + FB -->|Webhook Event| WH + WH -->|Process Message Command| APP + API -->|Commands/Queries| APP + APP -->|Business Logic| DOM + APP -->|Persistence| INFRA + INFRA -->|EF Core| PG + INFRA -->|Caching| RD + INFRA -->|Events| RMQ + APP -->|Gửi Message| INFRA + INFRA -->|API Call| FB + APP -->|AI Completion| INFRA + INFRA -->|API Call| OAI +``` + +### Công Nghệ + +| Layer | Công Nghệ | +|-------|-----------| +| **Backend** | .NET 8, ASP.NET Core 8 | +| **Architecture** | Clean Architecture, DDD, CQRS | +| **Database** | PostgreSQL 15+, EF Core 8 | +| **Cache** | Redis, StackExchange.Redis | +| **Messaging** | RabbitMQ, MassTransit | +| **HTTP Client** | HttpClient Factory, Polly | +| **AI** | OpenAI SDK, Azure.AI.OpenAI | +| **API Gateway** | Traefik | +| **Documentation** | Swagger/OpenAPI 3.0 | + +## API Endpoints + +### Public API + +| Endpoint | Method | Mô Tả | +|----------|--------|-------| +| `/api/v1/webhooks/facebook` | GET | Facebook webhook verification | +| `/api/v1/webhooks/facebook` | POST | Nhận Facebook Messenger events | +| `/api/v1/conversations` | GET | Danh sách hội thoại | +| `/api/v1/conversations/{id}` | GET | Lấy conversation theo ID | +| `/api/v1/conversations/{id}/messages` | POST | Gửi tin nhắn | +| `/api/v1/customers` | GET | Danh sách khách hàng | +| `/api/v1/customers/{id}` | GET | Chi tiết khách hàng | +| `/api/v1/customers/{id}` | PUT | Cập nhật thông tin khách hàng | + +### Admin API + +| Endpoint | Method | Mô Tả | +|----------|--------|-------| +| `/api/v1/chatbots/flows` | GET | Danh sách automation flows | +| `/api/v1/chatbots/flows` | POST | Tạo chatbot flow | +| `/api/v1/chatbots/flows/{id}` | PUT | Cập nhật flow | +| `/api/v1/chatbots/flows/{id}` | DELETE | Xóa flow | +| `/api/v1/chatbots/ai-config` | GET | Lấy AI chatbot config | +| `/api/v1/chatbots/ai-config` | PUT | Cập nhật AI config | + +### Health & Monitoring + +| Endpoint | Mô Tả | +|----------|-------| +| `/health` | Health check endpoint | +| `/swagger` | Swagger UI documentation | + +## Tài Liệu + +- [Tài Liệu Kiến Trúc](./ARCHITECTURE.md) - System design và domain model +- [Tài Liệu API](./API.md) - API reference đầy đủ với examples +- [Thiết Lập Facebook Messenger](./FACEBOOK_SETUP.md) - Hướng dẫn setup Facebook App +- [Cấu Hình AI Chatbot](./AI_CHATBOT.md) - Hướng dẫn tích hợp AI + +## Cấu Trúc Dự Án + +``` +mkt-facebook-service-net/ +├── src/ +│ ├── MktFacebookService.API/ # API Layer +│ │ ├── Controllers/ # REST Controllers +│ │ ├── Application/ # CQRS Commands/Queries +│ │ └── Program.cs # Entry point +│ ├── MktFacebookService.Domain/ # Domain Layer +│ │ ├── AggregatesModel/ # Aggregates, Entities +│ │ │ ├── ConversationAggregate/ +│ │ │ ├── CustomerAggregate/ +│ │ │ └── ChatbotAggregate/ +│ │ └── SeedWork/ # Base classes +│ └── MktFacebookService.Infrastructure/ # Infrastructure Layer +│ ├── Data/ # EF Core DbContext +│ ├── Repositories/ # Repository implementations +│ └── ExternalServices/ # Facebook, OpenAI clients +├── tests/ +│ ├── MktFacebookService.UnitTests/ +│ └── MktFacebookService.FunctionalTests/ +├── docs/ # Documentation +├── Dockerfile +└── MktFacebookService.slnx +``` + +## Biến Môi Trường + +| Biến | Mô Tả | Mặc Định | +|------|-------|----------| +| `DATABASE_URL` | PostgreSQL connection string | - | +| `REDIS_URL` | Redis connection string | `localhost:6379` | +| `RABBITMQ_URL` | RabbitMQ connection string | `localhost:5672` | +| `FACEBOOK_VERIFY_TOKEN` | Webhook verification token | - | +| `FACEBOOK_PAGE_ACCESS_TOKEN` | Page access token để gửi messages | - | +| `FACEBOOK_API_VERSION` | Facebook API version | `v21.0` | +| `OPENAI_API_KEY` | OpenAI API key | - | +| `OPENAI_MODEL` | Tên OpenAI model | `gpt-4-turbo` | +| `AZURE_OPENAI_ENDPOINT` | Azure OpenAI endpoint (tùy chọn) | - | +| `ASPNETCORE_ENVIRONMENT` | Môi trường (Development/Production) | `Development` | + +## Quy Trình Phát Triển + +### Phase 1: Domain Layer +1. Tạo Aggregates (Conversation, Customer, ChatbotFlow, AIChatbotConfig) +2. Định nghĩa Entities và Value Objects +3. Implement business rules trong domain methods +4. Raise Domain Events + +### Phase 2: Infrastructure Layer +1. Setup EF Core DbContext và entity configurations +2. Tạo repositories implementing domain interfaces +3. Implement FacebookMessengerClient +4. Implement OpenAIClient với Polly resilience +5. Apply database migrations + +### Phase 3: Application Layer (CQRS) +1. Tạo Commands (ProcessIncomingMessage, SendMessage, CreateChatbotFlow) +2. Tạo Queries (GetConversations, GetCustomers) +3. Implement MediatR Handlers +4. Thêm FluentValidation validators +5. Setup Pipeline Behaviors + +### Phase 4: API Layer +1. Implement WebhooksController cho Facebook events +2. Tạo REST API Controllers +3. Thêm Swagger annotations +4. Cấu hình authentication & authorization +5. Setup health checks + +## Kiểm Thử + +```bash +# Chạy tất cả tests +dotnet test + +# Chỉ chạy unit tests +dotnet test tests/MktFacebookService.UnitTests/ + +# Chạy với coverage +dotnet test /p:CollectCoverage=true /p:CoverageReportsFormat=opencover +``` + +## Đóng Góp + +Vui lòng tuân theo [GoodGo Project Rules](../../.agent/skills/project-rules/SKILL.md) và [.NET Microservice Workflow](../../.agent/skills/dotnet-microservice-workflow/SKILL.md). + +## License + +MIT License + +## Tài Nguyên + +### Facebook Messenger Platform +- [Tổng Quan Messenger Platform](https://developers.facebook.com/docs/messenger-platform/) +- [Webhook Reference](https://developers.facebook.com/docs/messenger-platform/webhooks) +- [Send API Reference](https://developers.facebook.com/docs/messenger-platform/send-messages) + +### OpenAI +- [Tài Liệu OpenAI API](https://platform.openai.com/docs/introduction) +- [Hướng Dẫn Chat Completions](https://platform.openai.com/docs/guides/chat-completions) + +### Internal Skills +- [API Design Skill](../../.agent/skills/api-design/SKILL.md) +- [CQRS MediatR Skill](../../.agent/skills/cqrs-mediatr/SKILL.md) +- [Domain-Driven Design Skill](../../.agent/skills/domain-driven-design/SKILL.md) diff --git a/services/mkt-whatsapp-service-net/README.md b/services/mkt-whatsapp-service-net/README.md new file mode 100644 index 00000000..0c246535 --- /dev/null +++ b/services/mkt-whatsapp-service-net/README.md @@ -0,0 +1,427 @@ +# MKT WhatsApp Service / Dịch Vụ MKT WhatsApp + +> **EN**: WhatsApp Business API Marketing Service with Chatbot Automation, AI-Powered Messaging, and Customer Management +> **VI**: Dịch vụ Marketing WhatsApp Business API với Chatbot Tự Động, Nhắn Tin AI, và Quản Lý Khách Hàng + +[![.NET Version](https://img.shields.io/badge/.NET-8.0-512BD4)](https://dotnet.microsoft.com/) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) + +## Features / Tính Năng + +### 1. 🤖 CHATBOT Automation Messenger + +**EN**: Flow-based automation with business rules and triggers +- Visual automation flow builder with steps and conditions +- Keyword triggers and event-based activation +- Quick replies and interactive buttons +- Multi-step conversation flows +- Conditional branching logic +- A/B testing for flows + +**VI**: Tự động hóa dựa trên flow với business rules và triggers +- Trình tạo flow tự động trực quan với các bước và điều kiện +- Triggers theo từ khóa và kích hoạt theo sự kiện +- Quick replies và nút tương tác +- Flows hội thoại nhiều bước +- Logic phân nhánh có điều kiện +- A/B testing cho các flows + +### 2. 🧠 CHATBOT AI Messenger + +**EN**: Intelligent chatbot powered by LLM (OpenAI GPT-4) +- Natural language understanding and generation +- Context-aware conversations with memory +- Customizable AI personality and tone +- Knowledge base integration +- Multi-turn dialogue support +- Fallback to human agent +- Token usage tracking and cost optimization + +**VI**: Chatbot thông minh được hỗ trợ bởi LLM (OpenAI GPT-4) +- Hiểu và sinh ngôn ngữ tự nhiên +- Hội thoại theo ngữ cảnh với bộ nhớ +- Tùy chỉnh tính cách và giọng điệu AI +- Tích hợp knowledge base +- Hỗ trợ đối thoại nhiều lượt +- Chuyển giao cho nhân viên +- Theo dõi token usage và tối ưu chi phí + +### 3. 👥 Quản Lý Khách Hàng / Customer Management + +**EN**: Comprehensive customer relationship management +- Customer profiles with WhatsApp ID +- Conversation history tracking +- Custom fields and tags +- Opt-in consent management (GDPR compliant) +- Customer segmentation +- Export customer data +- Integration with CRM systems + +**VI**: Quản lý quan hệ khách hàng toàn diện +- Hồ sơ khách hàng với WhatsApp ID +- Theo dõi lịch sử hội thoại +- Custom fields và tags +- Quản lý đồng ý nhận tin (tuân thủ GDPR) +- Phân khúc khách hàng +- Xuất dữ liệu khách hàng +- Tích hợp với hệ thống CRM + +## Quick Start / Bắt Đầu Nhanh + +### Prerequisites / Yêu Cầu + +- .NET 8.0 SDK +- PostgreSQL 15+ (hoặc Neon serverless) +- Redis 7+ +- RabbitMQ 3.12+ +- Docker & Docker Compose (cho local development) +- **Meta Business Account** với WhatsApp Business API access +- **WhatsApp Business Phone Number** (verified) +- **OpenAI API Key** (cho AI Chatbot) + +### Configuration / Cấu Hình + +```bash +# EN: Copy environment template / VI: Sao chép template môi trường +cp .env.example .env + +# EN: Update configuration / VI: Cập nhật cấu hình +# - DATABASE_URL (PostgreSQL connection string) +# - REDIS_URL +# - RABBITMQ_URL +# - WHATSAPP_PHONE_NUMBER_ID +# - WHATSAPP_ACCESS_TOKEN +# - WHATSAPP_WEBHOOK_VERIFY_TOKEN +# - WHATSAPP_APP_SECRET (for signature verification) +# - OPENAI_API_KEY (AI chatbot) +``` + +### Local Development / Phát Triển Local + +```bash +# EN: Restore dependencies / VI: Khôi phục dependencies +dotnet restore + +# EN: Apply migrations / VI: Áp dụng migrations +dotnet ef database update --project src/MktWhatsAppService.Infrastructure + +# EN: Run service / VI: Chạy service +dotnet run --project src/MktWhatsAppService.API + +# Service available at http://localhost:5000 +# Swagger UI: http://localhost:5000/swagger +``` + +### Docker Deployment / Triển Khai Docker + +```bash +# EN: Build and run with Docker Compose / VI: Build và chạy với Docker Compose +cd deployments/local +docker-compose up -d mkt-whatsapp-service-net + +# EN: View logs / VI: Xem logs +docker-compose logs -f mkt-whatsapp-service-net + +# EN: Access via Traefik / VI: Truy cập qua Traefik +# http://localhost/api/v1/whatsapp +``` + +## Architecture / Kiến Trúc + +```mermaid +graph TB + subgraph "External / Bên Ngoài" + WA["WhatsApp Cloud API
(Meta)"] + LLM["OpenAI GPT-4"] + Customer["Customer
(WhatsApp User)"] + end + + subgraph "mkt-whatsapp-service-net" + WH["Webhooks Controller"] + API["REST API Controllers"] + APP["Application Layer
CQRS"] + DOM["Domain Layer
Aggregates"] + INFRA["Infrastructure Layer"] + BG["Background Jobs"] + end + + subgraph "Data Stores" + PG[("PostgreSQL")] + RD[("Redis Cache")] + RMQ["RabbitMQ"] + end + + Customer -->|"Send Message"| WA + WA -->|"Webhook Event"| WH + WH -->|"Process Command"| APP + API -->|"Commands/Queries"| APP + APP -->|"Business Logic"| DOM + APP -->|"Persistence"| INFRA + INFRA -->|"EF Core"| PG + INFRA -->|"Caching"| RD + INFRA -->|"Events"| RMQ + APP -->|"Send Message"| INFRA + INFRA -->|"API Call"| WA + APP -->|"AI Response"| INFRA + INFRA -->|"API Call"| LLM + BG -->|"Scheduled Tasks"| INFRA + + style WA fill:#25D366 + style LLM fill:#74AA9C +``` + +### Technology Stack / Công Nghệ + +| Layer | Technology / Công Nghệ | +|-------|------------------------| +| **Backend** | .NET 8, ASP.NET Core 8 | +| **Architecture** | Clean Architecture, DDD, CQRS | +| **Database** | PostgreSQL 15+, EF Core 8 | +| **Cache** | Redis, StackExchange.Redis | +| **Messaging** | RabbitMQ, MassTransit | +| **HTTP Client** | HttpClient Factory, Polly | +| **AI** | OpenAI SDK | +| **API Gateway** | Traefik | +| **Documentation** | Swagger/OpenAPI 3.0 | + +## API Endpoints + +### Webhooks (WhatsApp) + +| Endpoint | Method | Description / Mô Tả | +|----------|--------|---------------------| +| `/api/v1/whatsapp/webhooks` | GET | WhatsApp webhook verification | +| `/api/v1/whatsapp/webhooks` | POST | Receive WhatsApp message events | + +### WhatsApp Account Management + +| Endpoint | Method | Description / Mô Tả | +|----------|--------|---------------------| +| `/api/v1/whatsapp/accounts` | POST | Connect WhatsApp Business Account | +| `/api/v1/whatsapp/accounts/{shopId}` | GET | Get account details | +| `/api/v1/whatsapp/accounts/{shopId}` | DELETE | Disconnect account | + +### Conversations + +| Endpoint | Method | Description / Mô Tả | +|----------|--------|---------------------| +| `/api/v1/whatsapp/conversations` | GET | List conversations / Danh sách hội thoại | +| `/api/v1/whatsapp/conversations/{id}` | GET | Get conversation with messages | +| `/api/v1/whatsapp/conversations/{id}/messages` | POST | Send message / Gửi tin nhắn | +| `/api/v1/whatsapp/conversations/{id}/assign` | POST | Assign to agent | +| `/api/v1/whatsapp/conversations/{id}/close` | POST | Close conversation | + +### Customers + +| Endpoint | Method | Description / Mô Tả | +|----------|--------|---------------------| +| `/api/v1/whatsapp/customers` | GET | List customers / Danh sách khách hàng | +| `/api/v1/whatsapp/customers/{waId}` | GET | Customer details | +| `/api/v1/whatsapp/customers/{waId}/tags` | PUT | Update tags | +| `/api/v1/whatsapp/customers/{waId}/opt-in` | PUT | Update opt-in consent | + +### Automation Flows + +| Endpoint | Method | Description / Mô Tả | +|----------|--------|---------------------| +| `/api/v1/whatsapp/flows` | GET | List automation flows | +| `/api/v1/whatsapp/flows` | POST | Create automation flow | +| `/api/v1/whatsapp/flows/{id}` | PUT | Update flow | +| `/api/v1/whatsapp/flows/{id}/activate` | POST | Activate flow | +| `/api/v1/whatsapp/flows/{id}/deactivate` | POST | Deactivate flow | + +### AI Agents + +| Endpoint | Method | Description / Mô Tả | +|----------|--------|---------------------| +| `/api/v1/whatsapp/ai-agents` | POST | Create AI agent | +| `/api/v1/whatsapp/ai-agents/{id}` | GET | Get AI agent config | +| `/api/v1/whatsapp/ai-agents/{id}` | PUT | Update personality/prompts | +| `/api/v1/whatsapp/ai-agents/{id}/activate` | POST | Enable AI responses | + +### Analytics + +| Endpoint | Method | Description / Mô Tả | +|----------|--------|---------------------| +| `/api/v1/whatsapp/analytics/messages` | GET | Message statistics | +| `/api/v1/whatsapp/analytics/conversations` | GET | Conversation metrics | +| `/api/v1/whatsapp/analytics/automations` | GET | Automation performance | + +## Documentation / Tài Liệu + +### English Documentation +- [Architecture Documentation](docs/en/ARCHITECTURE.md) - System design and domain models +- [API Reference](docs/en/API.md) - Complete API specification with examples +- [WhatsApp Setup Guide](docs/en/WHATSAPP_SETUP.md) - Meta Business Account and API setup +- [Automation Guide](docs/en/AUTOMATION_GUIDE.md) - Creating automation flows +- [AI Chatbot Guide](docs/en/AI_CHATBOT_GUIDE.md) - AI agent configuration + +### Vietnamese Documentation / Tài Liệu Tiếng Việt +- [Tài Liệu Kiến Trúc](docs/vi/ARCHITECTURE.md) - Thiết kế hệ thống và domain models +- [Tài Liệu API](docs/vi/API.md) - Đặc tả API đầy đủ với ví dụ +- [Hướng Dẫn Cài Đặt WhatsApp](docs/vi/WHATSAPP_SETUP.md) - Thiết lập Meta Business Account và API +- [Hướng Dẫn Tự Động Hóa](docs/vi/AUTOMATION_GUIDE.md) - Tạo flows tự động +- [Hướng Dẫn AI Chatbot](docs/vi/AI_CHATBOT_GUIDE.md) - Cấu hình AI agent + +## Project Structure / Cấu Trúc Dự Án + +``` +mkt-whatsapp-service-net/ +├── src/ +│ ├── MktWhatsAppService.API/ # API Layer +│ │ ├── Controllers/ # REST Controllers +│ │ │ ├── WebhooksController.cs +│ │ │ ├── WhatsAppAccountsController.cs +│ │ │ ├── ConversationsController.cs +│ │ │ ├── CustomersController.cs +│ │ │ ├── AutomationFlowsController.cs +│ │ │ ├── AIAgentsController.cs +│ │ │ └── AnalyticsController.cs +│ │ ├── Application/ # CQRS Layer +│ │ │ ├── Commands/ +│ │ │ ├── Queries/ +│ │ │ └── Handlers/ +│ │ ├── BackgroundJobs/ +│ │ └── Program.cs +│ │ +│ ├── MktWhatsAppService.Domain/ # Domain Layer +│ │ ├── AggregatesModel/ +│ │ │ ├── WhatsAppAccountAggregate/ +│ │ │ ├── ConversationAggregate/ +│ │ │ ├── CustomerAggregate/ +│ │ │ ├── AutomationFlowAggregate/ +│ │ │ └── AIAgentAggregate/ +│ │ ├── Exceptions/ +│ │ ├── Events/ +│ │ └── SeedWork/ +│ │ +│ └── MktWhatsAppService.Infrastructure/ # Infrastructure Layer +│ ├── Data/ # EF Core +│ ├── Repositories/ +│ └── ExternalServices/ +│ ├── WhatsAppCloudApiClient.cs +│ └── LlmService.cs +│ +├── tests/ +│ ├── MktWhatsAppService.UnitTests/ +│ └── MktWhatsAppService.IntegrationTests/ +│ +├── docs/ # Documentation +│ ├── en/ # English docs +│ └── vi/ # Vietnamese docs +│ +├── Dockerfile +├── .env.example +└── MktWhatsAppService.slnx +``` + +## Environment Variables / Biến Môi Trường + +| Variable | Description / Mô Tả | Default | +|----------|---------------------|---------| +| `DATABASE_URL` | PostgreSQL connection string | - | +| `REDIS_URL` | Redis connection string | `localhost:6379` | +| `RABBITMQ_URL` | RabbitMQ connection string | `localhost:5672` | +| `WHATSAPP_PHONE_NUMBER_ID` | WhatsApp Business phone number ID | - | +| `WHATSAPP_ACCESS_TOKEN` | WhatsApp Cloud API access token | - | +| `WHATSAPP_WEBHOOK_VERIFY_TOKEN` | Webhook verification token | - | +| `WHATSAPP_APP_SECRET` | WhatsApp app secret for signature verification | - | +| `WHATSAPP_API_VERSION` | WhatsApp API version | `v21.0` | +| `OPENAI_API_KEY` | OpenAI API key | - | +| `OPENAI_MODEL` | OpenAI model name | `gpt-4-turbo` | +| `ASPNETCORE_ENVIRONMENT` | Environment (Development/Production) | `Development` | + +## Development Workflow / Quy Trình Phát Triển + +### Phase 1: Domain Layer +1. Tạo Aggregates (WhatsAppAccount, Conversation, Customer, AutomationFlow, AIAgent) +2. Định nghĩa Entities và Value Objects +3. Implement business rules trong domain methods +4. Raise Domain Events + +### Phase 2: Infrastructure Layer +1. Setup EF Core DbContext và entity configurations +2. Create repositories implementing domain interfaces +3. Implement WhatsAppCloudApiClient với Polly resilience +4. Implement LlmService (OpenAI integration) +5. Apply database migrations + +### Phase 3: Application Layer (CQRS) +1. Create Commands (ProcessIncomingMessage, SendMessage, CreateFlow) +2. Create Queries (GetConversations, GetCustomers) +3. Implement MediatR Handlers +4. Add FluentValidation validators +5. Setup Pipeline Behaviors + +### Phase 4: API Layer +1. Implement WebhooksController cho WhatsApp events +2. Create REST API Controllers +3. Add Swagger annotations +4. Configure authentication & authorization +5. Setup health checks và background jobs + +## Testing / Kiểm Thử + +```bash +# EN: Run all tests / VI: Chạy tất cả tests +dotnet test + +# EN: Run unit tests only / VI: Chỉ chạy unit tests +dotnet test tests/MktWhatsAppService.UnitTests/ + +# EN: Run with coverage / VI: Chạy với coverage +dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover +``` + +## Key Differences from Other Platforms / Điểm Khác Biệt + +### WhatsApp vs Facebook Messenger vs Zalo + +| Feature | WhatsApp | Facebook Messenger | Zalo | +|---------|----------|-------------------|------| +| **Message Window** | 24 hours | 24 hours | 7 days | +| **Template Requirement** | Required outside window | Optional | Required (ZNS) | +| **Pricing** | Per conversation | Free | Per message | +| **API Type** | Cloud API (recommended) | Graph API | Zalo OA API | +| **Opt-in Requirement** | Strict (required) | Recommended | Required | + +## Rate Limits & Costs / Giới Hạn & Chi Phí + +### WhatsApp Cloud API Rate Limits +- **Tier 1**: 1,000 conversations/day +- **Tier 2**: 10,000 conversations/day +- **Tier 3**: 100,000 conversations/day +- **Unlimited** (phải request từ Meta) + +### Pricing (Example: Vietnam) +- **Marketing conversations**: ~$0.065 USD +- **Utility conversations**: ~$0.039 USD +- **Authentication**: ~$0.021 USD +- **Service**: ~$0.022 USD + +*Note: 1 conversation = 24-hour window, nhiều messages trong cùng window = 1 conversation* + +## Contributing / Đóng Góp + +Please follow the [GoodGo Project Rules](../../.agent/skills/project-rules/SKILL.md) and [.NET Microservice Workflow](../../.agent/skills/dotnet-microservice-workflow/SKILL.md). + +## License + +MIT License + +## Resources / Tài Nguyên + +### WhatsApp Business Platform +- [WhatsApp Cloud API Documentation](https://developers.facebook.com/docs/whatsapp/cloud-api) +- [Webhook Reference](https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks) +- [Message Templates](https://developers.facebook.com/docs/whatsapp/business-management-api/message-templates) + +### OpenAI +- [OpenAI API Documentation](https://platform.openai.com/docs/introduction) +- [Chat Completions Guide](https://platform.openai.com/docs/guides/chat-completions) + +### Internal Skills +- [API Design Skill](../../.agent/skills/api-design/SKILL.md) +- [CQRS MediatR Skill](../../.agent/skills/cqrs-mediatr/SKILL.md) +- [Domain-Driven Design Skill](../../.agent/skills/domain-driven-design/SKILL.md) +- [Inter-Service Communication](../../.agent/skills/inter-service-communication/SKILL.md) diff --git a/services/mkt-whatsapp-service-net/docs/en/AI_CHATBOT_GUIDE.md b/services/mkt-whatsapp-service-net/docs/en/AI_CHATBOT_GUIDE.md new file mode 100644 index 00000000..73a23f2d --- /dev/null +++ b/services/mkt-whatsapp-service-net/docs/en/AI_CHATBOT_GUIDE.md @@ -0,0 +1,547 @@ +# AI Chatbot Guide + +**Last Updated**: 2026-01-18 + +Learn how to configure and optimize AI-powered chatbot for WhatsApp conversations. + +## Overview + +The AI Chatbot uses Large Language Models (LLM) to provide intelligent, context-aware responses. Unlike rule-based automation, AI can: + +- Understand natural language and intent +- Maintain context across turns +- Generate dynamic responses +- Handle unexpected questions +- Learn from conversation patterns + +## Supported LLM Providers + +| Provider | Model | Cost (per 1M tokens) | Latency | +|----------|-------|----------------------|---------| +| **OpenAI** | GPT-4-Turbo | $10 input / $30 output | ~2s | +| **OpenAI** | GPT-3.5-Turbo | $0.50 input / $1.50 output | ~1s | +| **Azure OpenAI** | GPT-4 | Custom pricing | ~2s | +| **Google Gemini** | Gemini Pro | $0.50 input / $1.50 output | ~1.5s | + +**Recommendation**: Start with GPT-4-Turbo for quality, optimize to GPT-3.5 for simple queries. + +## Creating an AI Agent + +### Via API + +```bash +POST /api/v1/whatsapp/ai-agents +Content-Type: application/json + +{ + "shopId": "shop-guid", + "agentName": "Customer Support AI", + "personality": { + "tone": "friendly", + "language": "vietnamese", + "constraints": [ + "Do NOT provide pricing without checking current catalog", + "Do NOT process orders directly", + "Always offer to connect to human agent for complex issues" + ], + "promptTemplate": "You are a helpful customer service agent for {shop_name}." + }, + "knowledgeBaseId": "kb-guid", + "isActive": false +} +``` + +### Response + +```json +{ + "success": true, + "data": { + "agentId": "agent-guid", + "agentName": "Customer Support AI", + "createdAt": "2026-01-18T10:00:00Z" + } +} +``` + +## Personality Configuration + +### Tone Options + +**Friendly** (Recommended for retail) +``` +"You are a warm and enthusiastic assistant. Use emojis occasionally. +Address customers in a casual but respectful manner." +``` + +**Professional** (Recommended for B2B) +``` +"You are a professional business assistant. Use formal language. +Provide detailed, accurate information. Avoid emojis." +``` + +**Casual** (Recommended for young audience) +``` +"You are a chill and relatable assistant. Use informal language. +Keep responses concise. Use trending slang when appropriate." +``` + +### Language + +Set primary language: +```json +{ + "language": "vietnamese", + "fallbackLanguage": "english" +} +``` + +The AI will: +1. Respond in Vietnamese by default +2. Switch to English if customer uses English +3. Handle mixed language (Vienglish) + +### Constraints + +Define what AI should NOT do: + +```json +{ + "constraints": [ + "Never share personal information of other customers", + "Do not promise discounts or refunds without approval", + "Do not process financial transactions", + "Always verify order numbers before providing status", + "Redirect sensitive issues to human agent" + ] +} +``` + +## Prompt Template + +### Basic Template + +``` +You are a customer service agent for {shop_name}. + +Role: Help customers with product inquiries, order tracking, and general questions. + +Context: +- Customer name: {customer_name} +- Customer tags: {customer_tags} +- Previous purchases: {purchase_count} + +Knowledge Base: +{knowledge_base_content} + +Instructions: +- Be helpful and concise +- If unsure, say so and offer to connect to human agent +- Never make up information +- Always confirm before taking actions + +Current date: {current_date} +Current time: {current_time} +``` + +### Advanced Template with Few-Shot Examples + +``` +You are a customer service agent for {shop_name}. + +Here are examples of good responses: + +Customer: "Do you have iPhone 15 in stock?" +Agent: "Let me check our inventory for you! 📱 Could you specify which color and storage capacity you're looking for? We typically carry Space Black, Blue, and Pink in 128GB, 256GB, and 512GB." + +Customer: "Where is my order?" +Agent: "I'll help you track that! Could you please share your order number? It should look like #12345. You can find it in your confirmation email." + +Customer: "This product is broken" +Agent: "I'm sorry to hear that! 😞 To help you quickly, I'll connect you with our support team who can process a return or replacement. Please hold for a moment." + +Now respond to the customer's message: +{customer_message} +``` + +## Knowledge Base Integration + +### Creating Knowledge Base + +Upload documents (FAQ, product catalogs, policies): + +```bash +POST /api/v1/whatsapp/knowledge-bases +Content-Type: application/json + +{ + "shopId": "shop-guid", + "name": "Customer Support KB", + "documents": [ + { + "title": "Shipping Policy", + "content": "We offer free shipping on orders over 500,000 VNĐ..." + }, + { + "title": "Return Policy", + "content": "You can return items within 30 days..." + } + ] +} +``` + +### Link to AI Agent + +```bash +PUT /api/v1/whatsapp/ai-agents/{agentId} +Content-Type: application/json + +{ + "knowledgeBaseId": "kb-guid" +} +``` + +The AI will automatically reference KB when responding. + +## Context Management + +### Conversation History + +AI automatically includes last 10 messages for context: + +```json +{ + "messages": [ + {"role": "user", "content": "Do you sell laptops?"}, + {"role": "assistant", "content": "Yes! We have various laptop models..."}, + {"role": "user", "content": "What about gaming laptops?"} + ] +} +``` + +The AI understands "gaming laptops" refers to the laptop discussion. + +### Custom Context Variables + +Inject dynamic context: + +```json +{ + "contextVariables": { + "customer_tier": "vip", + "cart_value": "2500000", + "last_purchase_date": "2026-01-10", + "preferred_category": "electronics" + } +} +``` + +Use in prompt: +``` +Customer tier: {customer_tier} +Cart value: {cart_value} VNĐ + +Provide personalized recommendations based on their preference for {preferred_category}. +``` + +## Response Generation + +### API Request + +When customer sends a message, AI agent automatically generates response: + +``` +Customer: "Tôi muốn mua áo thun size L" + +[Internal AI Pipeline] +1. Load conversation history +2. Fetch customer profile (tags, custom fields) +3. Query knowledge base for relevant info +4. Build prompt with context +5. Call OpenAI API +6. Parse response +7. Apply safety filters +8. Send to customer +``` + +### Streaming Responses + +For long responses, enable streaming: + +```bash +PUT /api/v1/whatsapp/ai-agents/{agentId} +Content-Type: application/json + +{ + "streamingEnabled": true, + "streamingChunkSize": 500 +} +``` + +Sends message in chunks (smoother UX for long answers). + +## Fallback Handling + +### When AI Should Escalate + +Configure conditions to transfer to human: + +```json +{ + "fallbackConditions": [ + {"type": "low_confidence", "threshold": 0.7}, + {"type": "contains_keywords", "keywords": ["complaint", "refund", "speak to manager"]}, + {"type": "conversation_length", "maxTurns": 10}, + {"type": "sentiment", "value": "negative"} + ] +} +``` + +### Fallback Message + +Custom handoff message: + +```json +{ + "fallbackMessage": "I want to make sure you get the best help! Let me connect you with one of our specialists who can assist you further. Please hold on... 👨‍💼" +} +``` + +## Cost Optimization + +### 1. Intent Classification + +Before calling expensive GPT-4, use cheap classifier: + +```json +{ + "intentClassifier": { + "enabled": true, + "model": "gpt-3.5-turbo", + "categories": ["faq", "product_inquiry", "order_tracking", "complaint", "other"] + } +} +``` + +Route to GPT-3.5 for FAQs, GPT-4 for complex queries. + +### 2. Response Caching + +Cache common questions: + +```json +{ + "caching": { + "enabled": true, + "ttl": 3600, + "similarityThreshold": 0.95 + } +} +``` + +If customer asks "Do you ship to Hanoi?" and cache has answer for similar question → return cached response (no API call = $0). + +### 3. Token Limits + +Set max tokens to avoid runaway costs: + +```json +{ + "tokenLimits": { + "maxPromptTokens": 2000, + "maxCompletionTokens": 500 + } +} +``` + +### 4. Budget Alerts + +Set spending limits: + +```bash +POST /api/v1/whatsapp/ai-agents/{agentId}/budget +Content-Type: application/json + +{ + "dailyBudgetUsd": 10.00, + "monthlyBudgetUsd": 200.00, + "alertThreshold": 0.8 +} +``` + +Receive alert at 80% budget usage. + +## Safety & Moderation + +### Content Filtering + +Enable OpenAI moderation: + +```json +{ + "moderation": { + "enabled": true, + "blockCategories": ["hate", "harassment", "violence", "self-harm"] + } +} +``` + +Suspicious content is blocked before responding. + +### PII Protection + +Automatically redact sensitive data: + +```json +{ + "piiProtection": { + "enabled": true, + "redactTypes": ["credit_card", "ssn", "email", "phone"] + } +} +``` + +Logs will show `[REDACTED]` instead of actual values. + +## Testing + +### Test Mode + +Simulate AI responses without sending to customer: + +```bash +POST /api/v1/whatsapp/ai-agents/{agentId}/test +Content-Type: application/json + +{ + "conversationHistory": [ + {"role": "user", "content": "Laptop nào tốt nhất?"} + ], + "customerContext": { + "name": "Nguyễn Văn A", + "tags": ["vip"] + } +} +``` + +**Response**: +```json +{ + "generatedResponse": "Xin chào Nguyễn Văn A! 👋 ...", + "tokensUsed": { + "prompt": 450, + "completion": 120, + "total": 570 + }, + "estimatedCost": 0.0154, + "latencyMs": 1850 +} +``` + +### A/B Testing + +Compare prompts: + +- Agent A: Personality = "friendly" +- Agent B: Personality = "professional" + +Route 50% traffic to each, measure: +- Customer satisfaction (implicit from conversation length) +- Resolution rate +- Cost per conversation + +## Monitoring + +### Metrics Dashboard + +Track: +- **Token usage** (daily/monthly) +- **Cost** (per conversation, total) +- **Latency** (p50, p95, p99) +- **Fallback rate** (how often AI escalates) +- **Customer satisfaction** (thumbs up/down) + +### Conversation Quality + +Review random samples: + +```bash +GET /api/v1/whatsapp/ai-agents/{agentId}/conversations/sample?count=10 +``` + +Look for: +- Hallucinations (AI making up info) +- Off-brand tone +- Failure to escalate when needed + +## Hybrid Approach + +Combine automation + AI for best results: + +### Strategy 1: Automation First + +1. Incoming message → Check automation flows +2. If no match → Route to AI +3. AI response → Send to customer + +### Strategy 2: AI for Classification + +1. AI classifies intent +2. Route to appropriate automation flow +3. Fallback to AI if no flow matches + +### Strategy 3: Time-Based + +- Business hours (9 AM - 6 PM): AI enabled +- After hours: Automation only (simple FAQ) + +## Best Practices + +1. **Start with narrow scope** - Train AI on specific categories first +2. **Review regularly** - Sample conversations weekly +3. **Update knowledge base** - Keep product/policy info current +4. **Set clear constraints** - Define what AI can/cannot do +5. **Monitor costs** - Set budgets and alerts +6. **Human in the loop** - Always offer escalation path +7. **Optimize prompts** - Iterate based on performance +8. **Use examples** - Few-shot learning improves quality + +## Troubleshooting + +### AI Responses Are Generic + +**Solution**: Add more context and examples to prompt template. + +### AI Providing Wrong Information + +**Solution**: +1. Update knowledge base +2. Add constraint in prompt +3. Review and retrain + +### High Costs + +**Solution**: +1. Enable intent classification +2. Reduce max tokens +3. Use GPT-3.5 when possible +4. Implement caching + +### Slow Responses + +**Solution**: +1. Reduce context window (fewer history messages) +2. Enable streaming +3. Use faster model (GPT-3.5) + +## Next Steps + +- [API Documentation](API.md) - AI agent API reference +- [Automation Guide](AUTOMATION_GUIDE.md) - Combine with automation +- [Architecture](ARCHITECTURE.md) - Understanding AI pipeline + +## Resources + +- [OpenAI Best Practices](https://platform.openai.com/docs/guides/prompt-engineering) +- [Prompt Engineering Guide](https://www.promptingguide.ai/) +- [LLM Cost Calculator](https://docsbot.ai/tools/gpt-openai-api-pricing-calculator) diff --git a/services/mkt-whatsapp-service-net/docs/en/API.md b/services/mkt-whatsapp-service-net/docs/en/API.md new file mode 100644 index 00000000..37e63be2 --- /dev/null +++ b/services/mkt-whatsapp-service-net/docs/en/API.md @@ -0,0 +1,790 @@ +# API Documentation + +**Service**: mkt-whatsapp-service-net +**Version**: v1.0 +**Base URL**: `/api/v1/whatsapp` + +## Authentication + +All endpoints (except webhooks) require authentication via JWT token. + +```bash +Authorization: Bearer +``` + +## Response Format + +All responses follow this structure: + +```json +{ + "success": true | false, + "data": { ... }, + "error": "Error message" | null, + "pagination": { ... } | null +} +``` + +--- + +## Webhooks + +### Verify Webhook + +**GET** `/webhooks` + +WhatsApp verification challenge. + +**Query Parameters**: +- `hub.mode` (string) - Should be "subscribe" +- `hub.verify_token` (string) - Your verification token +- `hub.challenge` (string) - Random string to echo back + +**Response**: +``` +(Plain text) hub.challenge value +``` + +### Receive Events + +**POST** `/webhooks` + +Receive message events from WhatsApp. + +**Headers**: +- `X-Hub-Signature-256` - HMAC-SHA256 signature + +**Request Body**: +```json +{ + "object": "whatsapp_business_account", + "entry": [{ + "id": "123456", + "changes": [{ + "value": { + "messaging_product": "whatsapp", + "metadata": { + "phone_number_id": "123456789" + }, + "messages": [{ + "from": "84901234567", + "id": "wamid.xxx", + "timestamp": "1704000000", + "type": "text", + "text": { + "body": "Hello" + } + }] + } + }] + }] +} +``` + +**Response**: +```json +{ + "success": true +} +``` + +--- + +## WhatsApp Accounts + +### Connect Account + +**POST** `/accounts` + +Connect a WhatsApp Business Account. + +**Request**: +```json +{ + "shopId": "550e8400-e29b-41d4-a716-446655440000", + "phoneNumberId": "123456789", + "accessToken": "EAAxxxxx", + "webhookUrl": "https://yourdomain.com/api/v1/whatsapp/webhooks" +} +``` + +**Response**: +```json +{ + "success": true, + "data": { + "accountId": "660e8400-e29b-41d4-a716-446655440000", + "shopId": "550e8400-e29b-41d4-a716-446655440000", + "phoneNumberId": "123456789", + "status": "active", + "messageTier": "tier_1", + "connectedAt": "2026-01-18T10:00:00Z" + } +} +``` + +### Get Account + +**GET** `/accounts/{shopId}` + +Get account details for a shop. + +**Response**: +```json +{ + "success": true, + "data": { + "accountId": "660e8400-e29b-41d4-a716-446655440000", + "shopId": "550e8400-e29b-41d4-a716-446655440000", + "phoneNumberId": "123456789", + "webhookUrl": "https://yourdomain.com/api/v1/whatsapp/webhooks", + "status": "active", + "messageTier": "tier_2", + "dailyLimit": 10000, + "messagesUsedToday": 1523, + "connectedAt": "2026-01-15T10:00:00Z" + } +} +``` + +### Disconnect Account + +**DELETE** `/accounts/{shopId}` + +Disconnect WhatsApp Business Account. + +**Response**: +```json +{ + "success": true, + "data": { + "message": "Account disconnected successfully" + } +} +``` + +--- + +## Conversations + +### List Conversations + +**GET** `/conversations` + +Get paginated list of conversations. + +**Query Parameters**: +- `shopId` (required) - Shop ID +- `status` (optional) - Filter: `active`, `closed`, `expired` +- `assignedAgentId` (optional) - Filter by agent +- `skip` (default: 0) - Pagination offset +- `take` (default: 20, max: 100) - Page size + +**Response**: +```json +{ + "success": true, + "data": { + "conversations": [ + { + "id": "conv-001", + "shopId": "shop-001", + "customerWaId": "84901234567", + "customerName": "Nguyễn Văn A", + "status": "active", + "assignedAgentId": null, + "lastMessageAt": "2026-01-18T10:30:00Z", + "messageCount": 5, + "tags": ["new-customer"], + "createdAt": "2026-01-18T10:00:00Z" + } + ], + "totalCount": 42 + }, + "pagination": { + "page": 1, + "limit": 20, + "total": 42, + "totalPages": 3 + } +} +``` + +### Get Conversation + +**GET** `/conversations/{conversationId}` + +Get conversation details with messages. + +**Response**: +```json +{ + "success": true, + "data": { + "id": "conv-001", + "shopId": "shop-001", + "customer": { + "waId": "84901234567", + "name": "Nguyễn Văn A", + "tags": ["vip"] + }, + "status": "active", + "messages": [ + { + "id": "msg-001", + "whatsAppMessageId": "wamid.xxx", + "direction": "inbound", + "content": { + "type": "text", + "text": "Xin chào" + }, + "status": "read", + "timestamp": "2026-01-18T10:00:00Z" + }, + { + "id": "msg-002", + "whatsAppMessageId": "wamid.yyy", + "direction": "outbound", + "content": { + "type": "text", + "text": "Xin chào! Chúng tôi có thể giúp gì cho bạn?" + }, + "status": "delivered", + "timestamp": "2026-01-18T10:00:15Z" + } + ], + "createdAt": "2026-01-18T10:00:00Z", + "expiresAt": "2026-01-19T10:00:00Z" + } +} +``` + +### Send Message + +**POST** `/conversations/{conversationId}/messages` + +Send a message in a conversation. + +**Request**: +```json +{ + "content": { + "type": "text", + "text": "Cảm ơn bạn đã liên hệ!" + } +} +``` + +**Response**: +```json +{ + "success": true, + "data": { + "messageId": "msg-003", + "whatsAppMessageId": "wamid.zzz", + "status": "sent", + "timestamp": "2026-01-18T10:05:00Z" + } +} +``` + +**Media Message**: +```json +{ + "content": { + "type": "image", + "url": "https://example.com/product.jpg", + "caption": "Check out this product!" + } +} +``` + +**Interactive Message**: +```json +{ + "content": { + "type": "interactive", + "interactive": { + "type": "button", + "body": { + "text": "Choose an option:" + }, + "action": { + "buttons": [ + {"id": "yes", "title": "Yes"}, + {"id": "no", "title": "No"} + ] + } + } + } +} +``` + +### Assign Conversation + +**POST** `/conversations/{conversationId}/assign` + +Assign conversation to an agent. + +**Request**: +```json +{ + "agentId": "agent-001" +} +``` + +**Response**: +```json +{ + "success": true, + "data": { + "conversationId": "conv-001", + "assignedAgentId": "agent-001", + "assignedAt": "2026-01-18T10:10:00Z" + } +} +``` + +### Close Conversation + +**POST** `/conversations/{conversationId}/close` + +Close a conversation. + +**Response**: +```json +{ + "success": true, + "data": { + "conversationId": "conv-001", + "status": "closed", + "closedAt": "2026-01-18T10:15:00Z" + } +} +``` + +--- + +## Customers + +### List Customers + +**GET** `/customers` + +Get paginated customer list. + +**Query Parameters**: +- `shopId` (required) +- `search` (optional) - Search by name/phone +- `tags` (optional) - Filter by tags (comma-separated) +- `skip` / `take` (pagination) + +**Response**: +```json +{ + "success": true, + "data": { + "customers": [ + { + "id": "cust-001", + "waId": "84901234567", + "name": "Nguyễn Văn A", + "tags": ["vip", "frequent-buyer"], + "optInStatus": "opted_in", + "conversationCount": 12, + "lastContactedAt": "2026-01-18T10:00:00Z", + "createdAt": "2026-01-01T00:00:00Z" + } + ], + "totalCount": 150 + } +} +``` + +### Get Customer + +**GET** `/customers/{waId}` + +Get customer profile. + +**Query Parameters**: +- `shopId` (required) + +**Response**: +```json +{ + "success": true, + "data": { + "id": "cust-001", + "waId": "84901234567", + "shopId": "shop-001", + "name": "Nguyễn Văn A", + "profilePictureUrl": "https://...", + "consent": { + "status": "opted_in", + "timestamp": "2026-01-01T10:00:00Z", + "source": "whatsapp" + }, + "tags": ["vip"], + "customFields": { + "city": "Hanoi", + "preferredLanguage": "vi" + }, + "stats": { + "conversationCount": 12, + "averageResponseTime": "5m", + "lastPurchaseDate": "2026-01-15" + } + } +} +``` + +### Update Customer Tags + +**PUT** `/customers/{waId}/tags` + +Add or remove customer tags. + +**Query Parameters**: +- `shopId` (required) + +**Request**: +```json +{ + "addTags": ["vip", "electronics-buyer"], + "removeTags": ["new-customer"] +} +``` + +**Response**: +```json +{ + "success": true, + "data": { + "waId": "84901234567", + "tags": ["vip", "electronics-buyer"] + } +} +``` + +### Update Opt-In Status + +**PUT** `/customers/{waId}/opt-in` + +Update customer consent. + +**Request**: +```json +{ + "status": "opted_in", + "source": "web" +} +``` + +**Response**: +```json +{ + "success": true, + "data": { + "waId": "84901234567", + "consent": { + "status": "opted_in", + "timestamp": "2026-01-18T10:20:00Z", + "source": "web" + } + } +} +``` + +--- + +## Automation Flows + +### List Flows + +**GET** `/flows` + +Get automation flows. + +**Query Parameters**: +- `shopId` (required) +- `isActive` (optional) - Filter by status + +**Response**: +```json +{ + "success": true, + "data": { + "flows": [ + { + "id": "flow-001", + "flowName": "Welcome New Customer", + "triggerType": "keyword", + "isActive": true, + "executionCount": 523, + "createdAt": "2026-01-10T00:00:00Z" + } + ] + } +} +``` + +### Create Flow + +**POST** `/flows` + +Create automation flow. + +**Request**: See [Automation Guide](AUTOMATION_GUIDE.md#creating-a-flow) + +**Response**: +```json +{ + "success": true, + "data": { + "flowId": "flow-002", + "flowName": "FAQ Bot", + "isActive": false + } +} +``` + +### Update Flow + +**PUT** `/flows/{flowId}` + +Update flow configuration. + +### Activate Flow + +**POST** `/flows/{flowId}/activate` + +Enable automation flow. + +### Deactivate Flow + +**POST** `/flows/{flowId}/deactivate` + +Disable automation flow. + +--- + +## AI Agents + +### Create AI Agent + +**POST** `/ai-agents` + +Configure AI chatbot. + +**Request**: See [AI Chatbot Guide](AI_CHATBOT_GUIDE.md#creating-an-ai-agent) + +### Update AI Agent + +**PUT** `/ai-agents/{agentId}` + +Update personality/prompts. + +### Activate AI Agent + +**POST** `/ai-agents/{agentId}/activate` + +Enable AI responses. + +### Test AI Agent + +**POST** `/ai-agents/{agentId}/test` + +Simulate AI response. + +**Request**: +```json +{ + "conversationHistory": [ + {"role": "user", "content": "Bạn có laptop nào tốt?"} + ], + "customerContext": { + "name": "Nguyễn Văn A", + "tags": ["vip"] + } +} +``` + +**Response**: +```json +{ + "success": true, + "data": { + "generatedResponse": "Chúng tôi có nhiều laptop tuyệt vời! Bạn đang tìm laptop cho mục đích gì ạ? Gaming hay làm việc văn phòng?", + "tokensUsed": {"prompt": 450, "completion": 120, "total": 570}, + "estimatedCost": 0.0154, + "latencyMs": 1850 + } +} +``` + +--- + +## Analytics + +### Message Statistics + +**GET** `/analytics/messages` + +Get message volume metrics. + +**Query Parameters**: +- `shopId` (required) +- `startDate` / `endDate` (ISO 8601) +- `groupBy` - `hour`, `day`, `week` + +**Response**: +```json +{ + "success": true, + "data": { + "metrics": [ + { + "date": "2026-01-18", + "inboundCount": 245, + "outboundCount": 298, + "totalCount": 543 + } + ], + "summary": { + "totalInbound": 2450, + "totalOutbound": 2980, + "averagePerDay": 543 + } + } +} +``` + +### Conversation Metrics + +**GET** `/analytics/conversations` + +Get conversation performance metrics. + +**Response**: +```json +{ + "success": true, + "data": { + "averageResponseTime": "2m 30s", + "averageResolutionTime": "15m 45s", + "automationResolutionRate": 0.65, + "aiResolutionRate": 0.78, + "humanHandoffRate": 0.22 + } +} +``` + +### Automation Performance + +**GET** `/analytics/automations` + +Get automation flow execution stats. + +**Response**: +```json +{ + "success": true, + "data": { + "flows": [ + { + "flowId": "flow-001", + "flowName": "Welcome Bot", + "executionCount": 523, + "completionRate": 0.89, + "averageSteps": 3.2, + "fallbackRate": 0.11 + } + ] + } +} +``` + +--- + +## Error Codes + +| Code | Message | Description | +|------|---------|-------------| +| 400 | Bad Request | Invalid request format | +| 401 | Unauthorized | Missing or invalid auth token | +| 404 | Not Found | Resource doesn't exist | +| 409 | Conflict | Duplicate resource | +| 422 | Validation Error | Business rule violation | +| 429 | Rate Limit Exceeded | Too many requests | +| 500 | Internal Server Error | Server error | + +**Error Response Format**: +```json +{ + "success": false, + "error": "Validation failed: Phone number is required", + "details": { + "field": "phoneNumberId", + "code": "REQUIRED_FIELD" + } +} +``` + +--- + +## Rate Limits + +- **Public APIs**: 60 requests/minute per shop +- **Webhooks**: No limit (but must respond < 5s) +- **Analytics**: 10 requests/minute per shop + +## Webhooks Signature Verification + +Verify `X-Hub-Signature-256` header: + +```javascript +const crypto = require('crypto'); + +const signature = req.headers['x-hub-signature-256']; +const payload = JSON.stringify(req.body); + +const expectedSignature = 'sha256=' + + crypto.createHmac('sha256', APP_SECRET) + .update(payload) + .digest('hex'); + +if (signature !== expectedSignature) { + throw new Error('Invalid signature'); +} +``` + +## Pagination + +All list endpoints support pagination: + +**Request**: +``` +GET /conversations?skip=20&take=20 +``` + +**Response**: +```json +{ + "pagination": { + "page": 2, + "limit": 20, + "total": 150, + "totalPages": 8 + } +} +``` + +## Changelog + +### v1.0 (2026-01-18) +- Initial release +- WhatsApp Cloud API integration +- Automation flows +- AI chatbot +- Customer management diff --git a/services/mkt-whatsapp-service-net/docs/en/ARCHITECTURE.md b/services/mkt-whatsapp-service-net/docs/en/ARCHITECTURE.md new file mode 100644 index 00000000..b9e8849c --- /dev/null +++ b/services/mkt-whatsapp-service-net/docs/en/ARCHITECTURE.md @@ -0,0 +1,532 @@ +# Architecture Documentation + +**Service**: mkt-whatsapp-service-net +**Version**: 1.0 +**Last Updated**: 2026-01-18 + +## System Overview + +The MKT WhatsApp Service is a comprehensive microservice built on Clean Architecture principles, implementing Domain-Driven Design (DDD) and CQRS patterns. It provides three core capabilities: + +1. **Automation Chatbot**: Rule-based conversation flows +2. **AI Chatbot**: LLM-powered intelligent responses +3. **Customer Management**: Unified CRM for WhatsApp interactions + +### High-Level Architecture + +```mermaid +graph TB + subgraph External + WA[WhatsApp Cloud API] + OPENAI[OpenAI GPT-4] + Customer[End Users] + end + + subgraph "GoodGo Platform" + GATEWAY[Traefik Gateway] + + subgraph "mkt-whatsapp-service-net" + API[API Layer] + APP[Application Layer] + DOMAIN[Domain Layer] + INFRA[Infrastructure Layer] + end + + PG[(PostgreSQL)] + REDIS[(Redis)] + RABBIT[RabbitMQ] + end + + subgraph "Other Services" + MERCHANT[merchant-service] + ANALYTICS[analytics-service] + end + + Customer -->|Messages| WA + WA -->|Webhooks| GATEWAY + GATEWAY --> API + API --> APP + APP --> DOMAIN + APP --> INFRA + INFRA --> PG + INFRA --> REDIS + INFRA --> WA + INFRA --> OPENAI + INFRA --> RABBIT + RABBIT --> MERCHANT + RABBIT --> ANALYTICS +``` + +## Clean Architecture Layers + +### 1. API Layer (`MktWhatsAppService.API`) + +**Responsibility**: HTTP interface, request/response handling + +#### Controllers +- `WebhooksController` - WhatsApp webhook verification and message events +- `WhatsAppAccountsController` - Account connection management +- `ConversationsController` - Conversation and message endpoints +- `CustomersController` - Customer profile management +- `AutomationFlowsController` - Automation flow CRUD +- `AIAgentsController` - AI agent configuration +- `AnalyticsController` - Metrics and reporting + +#### Background Jobs +- `ConversationExpiryJob` - Close expired 24h conversations +- `MessageStatusSyncJob` - Sync delivery/read status from WhatsApp +- `FlowSchedulerJob` - Trigger time-based automation flows + +### 2. Application Layer (`MktWhatsAppService.API/Application`) + +**Responsibility**: Use cases, orchestration, CQRS + +#### Commands (Writes) + +**WhatsApp Account** +- `ConnectWhatsAppAccountCommand` - Register new account +- `UpdateWebhookCommand` - Update webhook configuration +- `DisconnectWhatsAppAccountCommand` - Deactivate account + +**Messages** +- `ProcessIncomingMessageCommand` - Handle incoming WhatsApp message +- `SendMessageCommand` - Send outbound message +- `SendTemplateMessageCommand` - Send pre-approved template + +**Automation** +- `CreateAutomationFlowCommand` - Define new flow +- `UpdateFlowStepCommand` - Modify flow logic +- `ActivateFlowCommand` - Enable automation +- `DeactivateFlowCommand` - Disable automation + +**AI Agent** +- `CreateAIAgentCommand` - Configure AI chatbot +- `UpdateAgentPersonalityCommand` - Modify AI behavior +- `GenerateAIResponseCommand` - Get AI reply + +**Customers** +- `CreateCustomerCommand` - Register new customer +- `UpdateCustomerOptInCommand` - Manage opt-in consent +- `TagCustomerCommand` - Add/remove tags + +#### Queries (Reads) + +**Conversations** +- `GetConversationQuery` - Single conversation with messages +- `GetActiveConversationsQuery` - List ongoing conversations +- `SearchConversationsQuery` - Full-text search + +**Customers** +- `GetCustomerQuery` - Customer profile by WaId +- `GetCustomersQuery` - Paginated customer list +- `GetCustomerConversationHistoryQuery` - All past conversations + +**Analytics** +- `GetMessageStatsQuery` - Message volume metrics +- `GetConversationMetricsQuery` - Response times, resolution rates +- `GetAutomationPerformanceQuery` - Flow execution stats + +#### MediatR Pipeline Behaviors +1. **Logging Behavior** - Log all commands/queries +2. **Validation Behavior** - FluentValidation integration +3. **Transaction Behavior** - Unit of Work for commands + +### 3. Domain Layer (`MktWhatsAppService.Domain`) + +**Responsibility**: Business logic, entities, business rules + +#### Aggregates + +##### WhatsAppAccount Aggregate +**Aggregate Root**: `WhatsAppAccount` + +Properties: +- `Id` (Guid) +- `ShopId` (Guid) +- `PhoneNumberId` (string) - WhatsApp phone number ID +- `AccessToken` (string, encrypted) +- `WebhookUrl` (string) +- `Status` (Active/Suspended) +- `MessageTier` (1K/10K/100K/Unlimited) + +Business Methods: +- `Activate()` - Activate account +- `UpdateWebhook(url)` - Change webhook URL +- `Suspend()` - Suspend account + +Domain Events: +- `WhatsAppAccountConnectedEvent` +- `WebhookVerifiedEvent` + +##### Conversation Aggregate +**Aggregate Root**: `Conversation` + +Properties: +- `Id` (Guid) +- `ShopId` (Guid) +- `CustomerWaId` (string) +- `Status` (Active/Closed/Expired) +- `AssignedAgentId` (Guid, nullable) +- `LastMessageAt` (DateTime) +- `Tags` (List) + +Entities: +- `Message` + - `Id` (Guid) + - `WhatsAppMessageId` (string) + - `Direction` (Inbound/Outbound) + - `Content` (MessageContent value object) + - `Status` (Sent/Delivered/Read/Failed) + - `Timestamp` (DateTime) + +Business Methods: +- `AddMessage(content, direction)` - Add message to conversation +- `AssignToAgent(agentId)` - Assign conversation +- `Close()` - Close conversation +- `CheckExpiry()` - Check 24h window + +Domain Events: +- `ConversationStartedEvent` +- `MessageReceivedEvent` +- `MessageSentEvent` +- `ConversationClosedEvent` + +##### AutomationFlow Aggregate +**Aggregate Root**: `AutomationFlow` + +Properties: +- `Id` (Guid) +- `ShopId` (Guid) +- `FlowName` (string) +- `TriggerType` (Keyword/Event/Schedule) +- `TriggerConfig` (JSON) +- `IsActive` (bool) + +Entities: +- `FlowStep` + - `Order` (int) + - `Action` (SendMessage/TagCustomer/CallWebhook/Delay) + - `ActionConfig` (JSON) + - `Conditions` (JSON, optional) + - `NextStepId` (int, nullable) + +Business Methods: +- `AddStep(action, config, conditions)` - Add flow step +- `ValidateFlow()` - Check for cycles, validate structure +- `Activate()` - Enable flow +- `Deactivate()` - Disable flow + +##### AIAgent Aggregate +**Aggregate Root**: `AIAgent` + +Properties: +- `Id` (Guid) +- `ShopId` (Guid) +- `AgentName` (string) +- `Personality` (AgentPersonality value object) +- `KnowledgeBaseId` (Guid, nullable) +- `IsActive` (bool) + +Value Objects: +- `AgentPersonality` + - `Tone` (Friendly/Professional/Casual) + - `Language` (Vietnamese/English) + - `Constraints` (List) + - `PromptTemplate` (string) + +Business Methods: +- `UpdatePersonality(personality)` - Change AI behavior +- `Activate()` - Enable AI responses +- `Deactivate()` - Disable AI + +##### Customer Aggregate +**Aggregate Root**: `Customer` + +Properties: +- `Id` (Guid) +- `WaId` (string) - WhatsApp ID (phone number) +- `ShopId` (Guid) +- `Name` (string) +- `ProfilePictureUrl` (string, nullable) +- `Consent` (OptInConsent value object) +- `Tags` (List) +- `CustomFields` (Dictionary) +- `FirstContactedAt` (DateTime) + +Value Objects: +- `OptInConsent` + - `Status` (OptedIn/OptedOut/Pending) + - `Timestamp` (DateTime) + - `Source` (Web/WhatsApp/Manual) + +Business Methods: +- `UpdateOptIn(status, source)` - Manage consent +- `AddTag(tag)` - Add customer tag +- `RemoveTag(tag)` - Remove tag +- `UpdateCustomField(key, value)` - Set custom field + +### 4. Infrastructure Layer (`MktWhatsAppService.Infrastructure`) + +**Responsibility**: External concerns, persistence, API clients + +#### Data Access +- `MktWhatsAppServiceContext` - EF Core DbContext +- Entity Configurations using Fluent API +- Repositories implementing domain interfaces + +#### External Services + +##### WhatsAppCloudApiClient +HTTP client for WhatsApp Cloud API with Polly resilience policies: + +Methods: +- `SendMessageAsync()` - Send text/media/interactive messages +- `SendTemplateMessageAsync()` - Send pre-approved templates +- `MarkMessageAsReadAsync()` - Send read receipts +- `GetMediaAsync()` - Download media files + +Resilience: +- **Retry**: 3 attempts, exponential backoff (500ms, 1.5s, 4.5s) +- **Circuit Breaker**: 50% failure ratio, 30s sampling, 30s break +- **Timeout**: 10s per request + +##### LlmService +LLM provider abstraction (OpenAI implementation): + +Methods: +- `GenerateResponseAsync()` - Get AI response with context +- `ExtractIntentAsync()` - Classify user intent +- `StreamResponseAsync()` - Streaming for long responses + +Features: +- Token usage tracking +- Cost calculation +- Context window management (last 10 messages) +- Safety filters + +## Message Processing Flow + +### Incoming Message Flow + +```mermaid +sequenceDiagram + participant WA as WhatsApp + participant Webhook as WebhooksController + participant Cmd as ProcessIncomingMessageHandler + participant AutoEngine as AutomationEngine + participant AIEngine as AIEngine + participant DB as Database + + WA->>Webhook: POST /webhooks (message event) + Webhook->>Webhook: Verify signature + Webhook->>Cmd: ProcessIncomingMessageCommand + Webhook-->>WA: 200 OK (immediate) + + Cmd->>DB: Get/Create Conversation + Cmd->>DB: Save Message + + alt Active Automation Flow + Cmd->>AutoEngine: Check triggers + AutoEngine->>AutoEngine: Match keywords/conditions + AutoEngine->>WA: Send automated response + else AI Agent Active + Cmd->>AIEngine: GenerateAIResponseCommand + AIEngine->>DB: Get history (last 10 msgs) + AIEngine->>AIEngine: Build prompt + AIEngine->>OpenAI: Chat completion + OpenAI-->>AIEngine: AI response + AIEngine->>WA: Send AI message + else Manual Response + Cmd->>DB: Mark conversation pending + Cmd->>RabbitMQ: Publish event + end +``` + +### Outbound Message Flow + +```mermaid +sequenceDiagram + participant API as ConversationsController + participant Cmd as SendMessageHandler + participant Domain as Conversation Aggregate + participant WA as WhatsAppCloudApiClient + participant DB as Database + + API->>Cmd: SendMessageCommand + Cmd->>DB: Get Conversation + Cmd->>Domain: CheckExpiry() + + alt Within 24h Window + Domain-->>Cmd: Window valid + Cmd->>WA: SendMessageAsync() + WA-->>Cmd: WhatsApp message ID + Cmd->>Domain: AddMessage() + Cmd->>DB: Save + else Outside 24h Window + Domain-->>Cmd: Window expired + Cmd->>WA: SendTemplateMessageAsync() + WA-->>Cmd: Message ID (new window) + Cmd->>Domain: AddMessage() + Cmd->>DB: Save + end +``` + +## Data Model + +### Database Schema + +See [Database Schema Documentation](DATABASE_SCHEMA.md) for detailed table structures and indexes. + +Key tables: +- `whatsapp_accounts` - Business account connections +- `conversations` - Customer conversations +- `messages` - Individual messages (owned by conversation) +- `customers` - Customer profiles +- `automation_flows` - Automation flow definitions +- `flow_steps` - Flow step configurations +- `ai_agents` - AI agent configurations + +### Important Indexes + +```sql +-- High-traffic queries +CREATE INDEX idx_conversations_shop_status ON conversations(shop_id, status); +CREATE INDEX idx_messages_conversation_timestamp ON messages(conversation_id, timestamp DESC); +CREATE INDEX idx_customers_shop_waid ON customers(shop_id, wa_id); + +-- Automation lookups +CREATE INDEX idx_flows_shop_active ON automation_flows(shop_id, is_active); +``` + +## Integration Events + +The service publishes events to RabbitMQ for consumption by other services: + +### Published Events + +**WhatsAppMessageReceivedEvent** +- Emitted when: Customer sends message to shop +- Consumers: analytics-service (metrics), merchant-service (notifications) + +**ConversationClosedEvent** +- Emitted when: Conversation is closed or expires +- Consumers: analytics-service (conversation duration), merchant-service + +**AITokenUsageEvent** +- Emitted when: AI agent generates response +- Consumers: wallet-service (billing), analytics-service (cost tracking) + +**CustomerOptInChangedEvent** +- Emitted when: Customer opt-in status changes +- Consumers: marketing services (permission updates) + +## Security Considerations + +### Webhook Signature Verification + +All incoming webhooks from WhatsApp are verified using HMAC-SHA256: + +```csharp +var signature = Request.Headers["X-Hub-Signature-256"]; +var payload = await ReadBodyAsStringAsync(); +var computedSignature = ComputeHmacSha256(payload, _appSecret); + +if (!SecureCompare(signature, computedSignature)) + return Unauthorized(); +``` + +### Access Token Encryption + +WhatsApp access tokens are encrypted at rest using AES-256-GCM: + +```csharp +// Stored in database as encrypted bytes +public string AccessToken +{ + get => _encryption.Decrypt(_encryptedToken); + private set => _encryptedToken = _encryption.Encrypt(value); +} +``` + +### Rate Limiting + +Redis-based distributed rate limiter: +- 60 requests/minute per shop +- 1000 requests/minute per service instance + +### GDPR Compliance + +- Customer data can be exported via API +- Right to be forgotten: soft delete with data anonymization +- Opt-in consent tracking with timestamps +- Data retention policies enforced + +## Performance Optimization + +### Caching Strategy + +**Redis Cache Usage:** +1. **Conversation Context** - Last 10 messages (TTL: 1 hour) +2. **Customer Profiles** - Frequently accessed customers (TTL: 30 minutes) +3. **Active Flows** - Automation flows (TTL: 5 minutes) +4. **Rate Limit Counters** - Per-shop request counts (TTL: 1 minute) + +### Query Optimization + +- Use Dapper for read-heavy queries (bypass EF Core) +- Implement pagination for all list endpoints +- Index on foreign keys and commonly filtered columns +- No N+1 queries (use `Include()` or projections) + +### Background Processing + +- Webhook processing returns 200 immediately +- Message sending queued to background job +- Flow execution runs asynchronously + +## Monitoring & Observability + +### Health Checks + +```csharp +builder.Services.AddHealthChecks() + .AddNpgSql(connectionString, name: "postgres") + .AddRedis(redisConnection, name: "redis") + .AddRabbitMQ(rabbitConnection, name: "rabbitmq") + .AddCheck("whatsapp-api") + .AddCheck("openai-api"); +``` + +### Metrics (Prometheus) + +- `whatsapp_messages_received_total` - Counter +- `whatsapp_messages_sent_total` - Counter +- `whatsapp_conversation_duration_seconds` - Histogram +- `whatsapp_ai_tokens_used_total` - Counter +- `whatsapp_webhook_processing_duration_ms` - Histogram + +### Logging (Loki) + +Structured logging with Serilog: +- Request/response correlation IDs +- Enriched with `ShopId`, `ConversationId` +- Sensitive data (tokens, messages) redacted + +## Deployment Architecture + +See [Deployment Guide](DEPLOYMENT.md) for Kubernetes manifests and scaling strategies. + +**Scaling Triggers:** +- CPU > 70% → Scale up pods +- Webhook queue > 1000 messages → Scale up +- Memory > 80% → Investigate + scale + +**Resource Limits:** +- Requests: 256Mi memory, 250m CPU +- Limits: 512Mi memory, 500m CPU + +## References + +- [WhatsApp Cloud API Docs](https://developers.facebook.com/docs/whatsapp/cloud-api) +- [OpenAPI Specification](../openapi.yaml) +- [Domain Model Details](DOMAIN_MODELS.md) diff --git a/services/mkt-whatsapp-service-net/docs/en/AUTOMATION_GUIDE.md b/services/mkt-whatsapp-service-net/docs/en/AUTOMATION_GUIDE.md new file mode 100644 index 00000000..b17d424c --- /dev/null +++ b/services/mkt-whatsapp-service-net/docs/en/AUTOMATION_GUIDE.md @@ -0,0 +1,429 @@ +# Automation Guide + +**Last Updated**: 2026-01-18 + +Learn how to create and manage automation flows for WhatsApp conversations. + +## Overview + +Automation flows allow you to define rule-based chatbot logic without AI. Use cases include: + +- Welcome messages for new customers +- FAQ auto-responses +- Order confirmation flows +- Lead qualification +- Appointment booking +- Customer support routing + +## Core Concepts + +### Trigger Types + +| Trigger | Description | Example | +|---------|-------------|---------| +| **Keyword** | Message contains specific text | "hi", "help", "price" | +| **Event** | System event occurs | Customer opts in, order created | +| **Schedule** | Time-based activation | Daily at 9 AM, every Monday | + +### Flow Steps + +Each flow consists of ordered steps. Step types: + +**1. Send Message** +- Send text or media message +- Support variables: `{customer_name}`, `{shop_name}` + +**2. Quick Reply** +- Present buttons for customer to tap +- Branch to different steps based on choice + +**3. Tag Customer** +- Add/remove customer tags +- Use for segmentation + +**4. Call Webhook** +- POST data to external URL +- Integrate with CRM, inventory systems + +**5. Assign to Agent** +- Route conversation to human agent +- Exit automation + +**6. Delay** +- Wait before next step +- Time in seconds/minutes/hours + +**7. Conditional Branch** +- If/else logic +- Conditions: tag exists, custom field value, time of day + +## Creating a Flow + +### Via API + +```bash +POST /api/v1/whatsapp/flows +Content-Type: application/json + +{ + "shopId": "shop-guid", + "flowName": "Welcome New Customer", + "triggerType": "keyword", + "triggerConfig": { + "keywords": ["hi", "hello", "start"] + }, + "steps": [ + { + "order": 1, + "action": "send_message", + "actionConfig": { + "text": "Welcome to {shop_name}! 👋\n\nHow can we help you today?" + } + }, + { + "order": 2, + "action": "quick_reply", + "actionConfig": { + "text": "Choose an option:", + "buttons": [ + {"id": "browse", "title": "Browse Products"}, + {"id": "track", "title": "Track Order"}, + {"id": "support", "title": "Talk to Support"} + ] + }, + "nextStepMapping": { + "browse": 3, + "track": 5, + "support": 7 + } + }, + { + "order": 3, + "action": "send_message", + "actionConfig": { + "text": "Visit our catalog: https://shop.example.com" + } + } + ] +} +``` + +### Response + +```json +{ + "success": true, + "data": { + "flowId": "flow-guid", + "flowName": "Welcome New Customer", + "isActive": false, + "createdAt": "2026-01-18T10:00:00Z" + } +} +``` + +## Flow Examples + +### Example 1: FAQ Bot + +**Trigger**: Keywords "price", "cost", "how much" + +**Flow**: +1. Send: "Our pricing depends on the product. What are you interested in?" +2. Quick Reply: ["Clothing", "Electronics", "Food"] +3. Conditional: + - If "Clothing" → Send pricing for clothing + - If "Electronics" → Send pricing for electronics + - If "Food" → Send pricing for food + +### Example 2: Appointment Booking + +**Trigger**: Keyword "appointment", "booking" + +**Flow**: +1. Send: "I can help you book an appointment! 📅" +2. Send: "What service do you need?" +3. Quick Reply: ["Consultation", "Check-up", "Follow-up"] +4. Tag Customer: "appointment-pending" +5. Call Webhook: POST to booking system +6. Delay: 2 seconds (wait for webhook response) +7. Send: "Your appointment is confirmed! You'll receive a reminder." + +### Example 3: Order Tracking + +**Trigger**: Keyword "track", "order status" + +**Flow**: +1. Send: "Please send your order number (e.g., #12345)" +2. (Customer replies with order number) +3. Call Webhook: GET order status from backend +4. Conditional: + - If order found → Send status + tracking link + - If not found → Send "Order not found. Please check the number." + +## Variables + +Use variables in message text for personalization: + +### Customer Variables + +- `{customer_name}` - Customer's name +- `{customer_phone}` - Customer's WhatsApp number +- `{customer_tags}` - Comma-separated tags + +### Shop Variables + +- `{shop_name}` - Shop name +- `{shop_url}` - Shop website URL + +### Conversation Variables + +- `{conversation_id}` - Conversation UUID +- `{message_count}` - Number of messages in conversation + +### Custom Variables (from webhook response) + +Webhook can return variables: + +```json +{ + "variables": { + "order_status": "Shipped", + "tracking_number": "ABC123XYZ" + } +} +``` + +Use in next step: +``` +Your order is {order_status}. Track it here: {tracking_number} +``` + +## Conditions + +### Supported Conditions + +**Tag Exists** +```json +{ + "type": "tag_exists", + "tag": "vip-customer" +} +``` + +**Custom Field Equals** +```json +{ + "type": "custom_field_equals", + "field": "city", + "value": "Hanoi" +} +``` + +**Time of Day** +```json +{ + "type": "time_of_day", + "start": "09:00", + "end": "17:00", + "timezone": "Asia/Ho_Chi_Minh" +} +``` + +**Day of Week** +```json +{ + "type": "day_of_week", + "days": ["monday", "tuesday", "wednesday"] +} +``` + +**Message Contains** +```json +{ + "type": "message_contains", + "text": "urgent", + "case_sensitive": false +} +``` + +### Combining Conditions + +Use AND/OR logic: + +```json +{ + "type": "and", + "conditions": [ + {"type": "tag_exists", "tag": "vip-customer"}, + {"type": "time_of_day", "start": "00:00", "end": "23:59"} + ] +} +``` + +## Activating a Flow + +```bash +POST /api/v1/whatsapp/flows/{flowId}/activate +``` + +**Response**: +```json +{ + "success": true, + "data": { + "flowId": "flow-guid", + "isActive": true, + "activatedAt": "2026-01-18T10:05:00Z" + } +} +``` + +## Priority + +When multiple flows match, priority determines which executes: + +1. **Explicit keyword match** (highest priority) +2. **Event triggers** +3. **Scheduled triggers** (lowest priority) + +Set priority when creating flow: + +```json +{ + "flowName": "VIP Customer Welcome", + "priority": 100, + ... +} +``` + +Higher number = higher priority (default: 50) + +## Testing a Flow + +### Test Mode + +Enable test mode to see execution without sending actual messages: + +```bash +POST /api/v1/whatsapp/flows/{flowId}/test +Content-Type: application/json + +{ + "shopId": "shop-guid", + "customerWaId": "84901234567", + "simulatedMessage": "hi" +} +``` + +**Response**: +```json +{ + "success": true, + "data": { + "matched": true, + "executedSteps": [ + {"step": 1, "action": "send_message", "result": "Would send: Welcome..."}, + {"step": 2, "action": "quick_reply", "result": "Would show buttons"} + ] + } +} +``` + +### Debug Logs + +View flow execution history: + +```bash +GET /api/v1/whatsapp/flows/{flowId}/executions?limit=20 +``` + +## Best Practices + +### 1. Keep Flows Simple + +- Max 10 steps per flow +- Avoid deep nesting of conditions +- Break complex flows into multiple smaller flows + +### 2. Provide Exit Points + +Always give customers a way to: +- Talk to human agent ("support", "help") +- Start over ("restart", "menu") +- Opt out ("stop", "unsubscribe") + +### 3. Handle Unknown Inputs + +Add a fallback step: +```json +{ + "order": 99, + "action": "send_message", + "actionConfig": { + "text": "I didn't understand. Reply 'menu' to see options or 'support' to talk to an agent." + } +} +``` + +### 4. Use Delays Wisely + +- After webhook calls: 2-5 seconds +- Between messages: 1-2 seconds (more natural) +- Avoid delays > 10 seconds (customer may leave) + +### 5. A/B Testing + +Create two versions of a flow: + +- Flow A: Send message variant A +- Flow B: Send message variant B + +Route 50% traffic to each, measure: +- Response rate +- Conversion rate +- Time to resolution + +## Limitations + +- Max 50 active flows per shop +- Max 20 steps per flow +- Max 10 quick reply buttons per message +- Webhook timeout: 10 seconds +- No loops (anti-cycle validation) + +## Troubleshooting + +### Flow Not Triggering + +**Check**: +1. Flow is activated (`isActive: true`) +2. Trigger keyword matches exactly (case-insensitive) +3. No higher-priority flow is matching first +4. Customer has not opted out + +### Webhook Failing + +**Check**: +1. Webhook URL is accessible (HTTPS required) +2. Webhook responds within 10 seconds +3. Response status code is 200 +4. Response JSON is valid + +### Variables Not Replacing + +**Check**: +1. Variable syntax is correct: `{variable_name}` +2. Variable is defined (customer_name exists for customer) +3. Webhook returned expected variables + +## Next Steps + +- [AI Chatbot Guide](AI_CHATBOT_GUIDE.md) - Combine with AI for hybrid approach +- [API Documentation](API.md) - Full API reference +- [Architecture](ARCHITECTURE.md) - Understanding the automation engine + +## Resources + +- [Flow Builder UI](https://platform.goodgo.com/whatsapp/flows) (if available) +- [Webhook Integration Guide](WEBHOOK_INTEGRATION.md) diff --git a/services/mkt-whatsapp-service-net/docs/en/WHATSAPP_SETUP.md b/services/mkt-whatsapp-service-net/docs/en/WHATSAPP_SETUP.md new file mode 100644 index 00000000..ab3ce3d8 --- /dev/null +++ b/services/mkt-whatsapp-service-net/docs/en/WHATSAPP_SETUP.md @@ -0,0 +1,296 @@ +# WhatsApp Setup Guide + +**Last Updated**: 2026-01-18 + +This guide walks you through setting up WhatsApp Business API access for the MKT WhatsApp Service. + +## Prerequisites + +- Meta Business Account +- Facebook Business Manager access +- Verified business (for higher tier limits) +- Domain with HTTPS (for webhook) + +## Step 1: Create Meta Business Account + +1. Go to [Meta Business Suite](https://business.facebook.com/) +2. Click "Create Account" +3. Enter your business name and details +4. Verify your business email + +## Step 2: Access WhatsApp API + +### Option A: Cloud API (Recommended) + +1. Go to [Meta for Developers](https://developers.facebook.com/) +2. Click "My Apps" → "Create App" +3. Select "Business" as app type +4. Fill in app details (name, contact email, business account) +5. After creation, click "Add Product" +6. Select "WhatsApp" → "Set Up" + +### Option B: On-Premise API + +Not recommended for most use cases. Requires dedicated server infrastructure and BSP partnership. + +## Step 3: Get Phone Number + +### Test Phone Number (Development) + +Meta provides a test number for development: + +1. In WhatsApp product settings, you'll see a test phone number +2. Copy the `Phone Number ID` +3. Add test recipients (max 5) in the Configuration tab + +### Production Phone Number + +1. Click "Add Phone Number" +2. Choose one of: + - **Use existing**: Migrate existing WhatsApp Business number + - **Register new**: Get new number from Meta +3. Verify phone number via SMS/call +4. Complete business verification + +**Important**: Once connected to API, you cannot use WhatsApp Business App on this number. + +## Step 4: Generate Access Token + +### Temporary Token (24 hours) + +1. Go to WhatsApp → API Setup +2. Copy the temporary access token +3. Use for testing only + +### Permanent Token + +1. Go to Meta Business Suite → Settings → System Users +2. Click "Add" → Create system user (name: "WhatsApp API") +3. Assign "Admin" role +4. Click "Generate Token" +5. Select your app +6. Choose permissions: + - `whatsapp_business_management` + - `whatsapp_business_messaging` +7. Copy token (store securely, shown once) + +## Step 5: Configure Webhook + +### Get Webhook URL + +From your deployed service: +``` +https://yourdomain.com/api/v1/whatsapp/webhooks +``` + +### Generate Verify Token + +Create a random string for webhook verification: + +```bash +# Generate random token +openssl rand -hex 32 +``` + +Save this as `WHATSAPP_WEBHOOK_VERIFY_TOKEN` in your `.env` + +### Setup in Meta + +1. Go to WhatsApp → Configuration → Webhook +2. Click "Edit" +3. Enter: + - **Callback URL**: `https://yourdomain.com/api/v1/whatsapp/webhooks` + - **Verify Token**: Your generated token +4. Click "Verify and Save" + +### Subscribe to Events + +After verification, subscribe to: +- ✅ `messages` - Incoming customer messages +- ✅ `message_status` (optional) - Delivery/read status updates +- ✅ `messaging_postbacks` (optional) - Button interactions + +## Step 6: Get App Secret + +For webhook signature verification: + +1. Go to App Dashboard → Settings → Basic +2. Click "Show" next to "App Secret" +3. Copy and save as `WHATSAPP_APP_SECRET` + +## Step 7: Configure Service + +Update your `.env` file: + +```bash +# WhatsApp Configuration +WHATSAPP_PHONE_NUMBER_ID=123456789012345 +WHATSAPP_ACCESS_TOKEN=your_permanent_token_here +WHATSAPP_WEBHOOK_VERIFY_TOKEN=your_verify_token_here +WHATSAPP_APP_SECRET=your_app_secret_here +WHATSAPP_API_VERSION=v21.0 +``` + +## Step 8: Test Integration + +### Verify Webhook + +The service will automatically handle webhook verification. Check logs: + +```bash +docker-compose logs -f mkt-whatsapp-service-net +``` + +You should see: +``` +[INFO] Webhook verification successful +``` + +### Send Test Message + +1. Get a test customer's WhatsApp number +2. Use API to send message: + +```bash +curl -X POST http://localhost/api/v1/whatsapp/conversations/{conversationId}/messages \ + -H "Content-Type: application/json" \ + -d '{ + "content": { + "type": "text", + "text": "Hello from MKT WhatsApp Service!" + } + }' +``` + +### Receive Test Message + +1. Send a message from test customer's WhatsApp to your business number +2. Check service logs for incoming webhook +3. Verify message is stored in database + +## Step 9: Message Templates + +For messages outside 24-hour window, you need approved templates. + +### Create Template + +1. Go to WhatsApp → Message Templates +2. Click "Create Template" +3. Fill in: + - **Name**: `order_confirmation` (lowercase, underscores only) + - **Category**: Utility/Marketing/Authentication + - **Language**: Vietnamese, English, etc. + - **Content**: Use placeholders like `{{1}}`, `{{2}}` + +Example template: +``` +Xin chào {{1}}! + +Đơn hàng #{{2}} của bạn đã được xác nhận. +Tổng tiền: {{3}} VNĐ + +Cảm ơn bạn đã mua hàng! +``` + +4. Submit for review (approval takes 1-3 days) + +### Use Template in Service + +Once approved update `.env`: +```bash +WHATSAPP_TEMPLATE_ORDER_CONFIRMATION=order_confirmation +``` + +## Step 10: Upgrade Tier Limits + +### Initial Tier + +New phone numbers start at **Tier 1** (1,000 conversations/day). + +### Upgrade Process + +Tiers upgrade automatically based on: +1. **Phone number quality** (low block rate) +2. **Sending volume** +3. **Time** (minimum 7 days at current tier) + +### Tier Levels + +| Tier | Daily Limit | Upgrade Criteria | +|------|-------------|------------------| +| Tier 1 | 1,000 | Start tier | +| Tier 2 | 10,000 | 7 days + good quality | +| Tier 3 | 100,000 | 7 days + high volume | +| Unlimited | No limit | Request from Meta | + +## Troubleshooting + +### Webhook Verification Fails + +**Problem**: "Verification token mismatch" + +**Solution**: +1. Check `WHATSAPP_WEBHOOK_VERIFY_TOKEN` matches exactly +2. Ensure service is running and accessible +3. Check HTTPS is working (WhatsApp requires HTTPS) + +### Messages Not Sending + +**Problem**: API returns error `(#131030) Recipient phone number not valid` + +**Solution**: +1. Ensure number includes country code without + or 0 +2. Format: `84901234567` (Vietnam), not `+84901234567` + +**Problem**: `(#368) Template not found` + +**Solution**: +1. Verify template is approved in Meta dashboard +2. Check template name matches exactly +3. Ensure correct language code + +### Rate Limit Exceeded + +**Problem**: `(#130429) Rate limit exceeded` + +**Solution**: +1. Check current tier in Meta dashboard +2. Implement exponential backoff +3. Request tier upgrade if needed + +### Invalid Access Token + +**Problem**: `(#190) Invalid OAuth access token` + +**Solution**: +1. Token may have expired - generate new permanent token +2. Check token has correct permissions +3. Verify token belongs to correct app + +## Security Best Practices + +1. **Never commit tokens** - Use environment variables +2. **Rotate tokens regularly** - Generate new tokens every 6 months +3. **Verify webhook signatures** - Always validate `X-Hub-Signature-256` +4. **Use HTTPS only** - WhatsApp will reject HTTP webhooks +5. **Restrict IP access** - Whitelist Meta IP ranges if possible + +## Cost Optimization + +1. **Use utility templates** - Cheaper than marketing +2. **Leverage 24-hour window** - Free messages within window +3. **Avoid spam** - High block rate can limit your account +4. **Monitor conversations** - Track which types open/close windows + +## Next Steps + +- [API Documentation](API.md) - Learn available endpoints +- [Automation Guide](AUTOMATION_GUIDE.md) - Setup automation flows +- [AI Chatbot Guide](AI_CHATBOT_GUIDE.md) - Configure AI agent + +## Resources + +- [WhatsApp Cloud API Docs](https://developers.facebook.com/docs/whatsapp/cloud-api) +- [Business Verification](https://www.facebook.com/business/help/2058515294227817) +- [Message Templates Guide](https://developers.facebook.com/docs/whatsapp/business-management-api/message-templates) +- [Webhook Reference](https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks) diff --git a/services/mkt-whatsapp-service-net/docs/vi/AI_CHATBOT_GUIDE.md b/services/mkt-whatsapp-service-net/docs/vi/AI_CHATBOT_GUIDE.md new file mode 100644 index 00000000..cdda2162 --- /dev/null +++ b/services/mkt-whatsapp-service-net/docs/vi/AI_CHATBOT_GUIDE.md @@ -0,0 +1,416 @@ +# Hướng Dẫn AI Chatbot + +**Cập nhật lần cuối**: 2026-01-18 + +Học cách cấu hình và tối ưu chatbot AI cho hội thoại WhatsApp. + +## Tổng Quan + +AI Chatbot sử dụng Large Language Models (LLM) để cung cấp phản hồi thông minh, nhận biết ngữ cảnh. Không giống như tự động hóa dựa trên quy tắc, AI có thể: + +- Hiểu ngôn ngữ tự nhiên và ý định +- Duy trì ngữ cảnh qua các lượt hội thoại +- Tạo phản hồi động +- Xử lý câu hỏi không mong đợi +- Học từ các mẫu hội thoại + +## Nhà Cung Cấp LLM Được Hỗ Trợ + +| Nhà Cung Cấp | Model | Chi Phí (per 1M tokens) | Độ Trễ | +|----------|-------|----------------------|---------| +| **OpenAI** | GPT-4-Turbo | $10 input / $30 output | ~2s | +| **OpenAI** | GPT-3.5-Turbo | $0.50 input / $1.50 output | ~1s | +| **Azure OpenAI** | GPT-4 | Giá tùy chỉnh | ~2s | +| **Google Gemini** | Gemini Pro | $0.50 input / $1.50 output | ~1.5s | + +**Khuyến nghị**: Bắt đầu với GPT-4-Turbo cho chất lượng, tối ưu sang GPT-3.5 cho các truy vấn đơn giản. + +## Tạo AI Agent + +### Qua API + +```bash +POST /api/v1/whatsapp/ai-agents +Content-Type: application/json + +{ + "shopId": "shop-guid", + "agentName": "AI Hỗ Trợ Khách Hàng", + "personality": { + "tone": "friendly", + "language": "vietnamese", + "constraints": [ + "KHÔNG cung cấp giá mà không kiểm tra catalog hiện tại", + "KHÔNG xử lý đơn hàng trực tiếp", + "Luôn đề nghị kết nối với nhân viên cho vấn đề phức tạp" + ], + "promptTemplate": "Bạn là nhân viên hỗ trợ khách hàng thân thiện cho {shop_name}." + }, + "knowledgeBaseId": "kb-guid", + "isActive": false +} +``` + +## Cấu Hình Personality + +### Tùy Chọn Tone + +**Friendly** (Khuyến nghị cho bán lẻ) +``` +"Bạn là trợ lý nhiệt tình và thân thiện. Sử dụng emoji thỉnh thoảng. +Xưng hô với khách hàng một cách thân mật nhưng tôn trọng." +``` + +**Professional** (Khuyến nghị cho B2B) +``` +"Bạn là trợ lý doanh nghiệp chuyên nghiệp. Sử dụng ngôn ngữ trang trọng. +Cung cấp thông tin chi tiết, chính xác. Tránh emoji." +``` + +**Casual** (Khuyến nghị cho đối tượng trẻ) +``` +"Bạn là trợ lý chill và gần gũi. Sử dụng ngôn ngữ không chính thức. +Giữ phản hồi ngắn gọn. Dùng slang thịnh hành khi phù hợp." +``` + +### Ngôn Ngữ + +Đặt ngôn ngữ chính: +```json +{ + "language": "vietnamese", + "fallbackLanguage": "english" +} +``` + +AI sẽ: +1. Phản hồi bằng tiếng Việt mặc định +2. Chuyển sang tiếng Anh nếu khách hàng dùng tiếng Anh +3. Xử lý ngôn ngữ hỗn hợp (Vienglish) + +### Constraints (Ràng Buộc) + +Định nghĩa những gì AI KHÔNG nên làm: + +```json +{ + "constraints": [ + "Không bao giờ chia sẻ thông tin cá nhân của khách hàng khác", + "Không hứa giảm giá hoặc hoàn tiền mà không có phê duyệt", + "Không xử lý giao dịch tài chính", + "Luôn xác minh mã đơn hàng trước khi cung cấp trạng thái", + "Chuyển vấn đề nhạy cảm cho nhân viên" + ] +} +``` + +## Prompt Template + +### Template Cơ Bản + +``` +Bạn là nhân viên hỗ trợ khách hàng cho {shop_name}. + +Vai trò: Giúp khách hàng với câu hỏi về sản phẩm, tra đơn hàng, và các câu hỏi chung. + +Ngữ cảnh: +- Tên khách hàng: {customer_name} +- Tags khách hàng: {customer_tags} +- Đơn hàng trước đây: {purchase_count} + +Knowledge Base: +{knowledge_base_content} + +Hướng dẫn: +- Hữu ích và ngắn gọn +- Nếu không chắc chắn, nói thẳng và đề nghị kết nối nhân viên +- Không bao giờ bịa thông tin +- Luôn xác nhận trước khi hành động + +Ngày hiện tại: {current_date} +Thời gian hiện tại: {current_time} +``` + +## Tích Hợp Knowledge Base + +### Tạo Knowledge Base + +Upload tài liệu (FAQ, catalog sản phẩm, chính sách): + +```bash +POST /api/v1/whatsapp/knowledge-bases +Content-Type: application/json + +{ + "shopId": "shop-guid", + "name": "KB Hỗ Trợ Khách Hàng", + "documents": [ + { + "title": "Chính Sách Vận Chuyển", + "content": "Chúng tôi cung cấp miễn phí vận chuyển cho đơn hàng trên 500,000 VNĐ..." + }, + { + "title": "Chính Sách Đổi Trả", + "content": "Bạn có thể đổi trả sản phẩm trong vòng 30 ngày..." + } + ] +} +``` + +### Liên Kết với AI Agent + +```bash +PUT /api/v1/whatsapp/ai-agents/{agentId} +Content-Type: application/json + +{ + "knowledgeBaseId": "kb-guid" +} +``` + +AI sẽ tự động tham khảo KB khi phản hồi. + +## Quản Lý Ngữ Cảnh + +### Lịch Sử Hội Thoại + +AI tự động bao gồm 10 tin nhắn cuối cùng cho ngữ cảnh. + +### Biến Ngữ Cảnh Tùy Chỉnh + +Đưa vào ngữ cảnh động: + +```json +{ + "contextVariables": { + "customer_tier": "vip", + "cart_value": "2500000", + "last_purchase_date": "2026-01-10", + "preferred_category": "electronics" + } +} +``` + +## Tạo Phản Hồi + +Khi khách hàng gửi tin nhắn, AI agent tự động tạo phản hồi: + +``` +Khách hàng: "Tôi muốn mua áo thun size L" + +[Internal AI Pipeline] +1. Load lịch sử hội thoại +2. Lấy hồ sơ khách hàng (tags, custom fields) +3. Query knowledge base cho thông tin liên quan +4. Xây dựng prompt với ngữ cảnh +5. Gọi OpenAI API +6. Parse phản hồi +7. Áp dụng safety filters +8. Gửi đến khách hàng +``` + +## Xử Lý Fallback + +### Khi AI Nên Chuyển Giao + +Cấu hình điều kiện để chuyển cho nhân viên: + +```json +{ + "fallbackConditions": [ + {"type": "low_confidence", "threshold": 0.7}, + {"type": "contains_keywords", "keywords": ["khiếu nại", "hoàn tiền", "gặp quản lý"]}, + {"type": "conversation_length", "maxTurns": 10}, + {"type": "sentiment", "value": "negative"} + ] +} +``` + +## Tối Ưu Chi Phí + +### 1. Phân Loại Intent + +Trước khi gọi GPT-4 đắt tiền, dùng classifier rẻ: + +```json +{ + "intentClassifier": { + "enabled": true, + "model": "gpt-3.5-turbo", + "categories": ["faq", "product_inquiry", "order_tracking", "complaint", "other"] + } +} +``` + +Route sang GPT-3.5 cho FAQs, GPT-4 cho truy vấn phức tạp. + +### 2. Response Caching + +Cache các câu hỏi phổ biến: + +```json +{ + "caching": { + "enabled": true, + "ttl": 3600, + "similarityThreshold": 0.95 + } +} +``` + +Nếu khách hàng hỏi "Có giao hàng đến Hà Nội không?" và cache có câu trả lời cho câu hỏi tương tự → trả về cached response (không API call = $0). + +### 3. Giới Hạn Token + +Đặt max tokens để tránh chi phí vượt quá: + +```json +{ + "tokenLimits": { + "maxPromptTokens": 2000, + "maxCompletionTokens": 500 + } +} +``` + +### 4. Cảnh Báo Ngân Sách + +Đặt giới hạn chi tiêu: + +```bash +POST /api/v1/whatsapp/ai-agents/{agentId}/budget +Content-Type: application/json + +{ + "dailyBudgetUsd": 10.00, + "monthlyBudgetUsd": 200.00, + "alertThreshold": 0.8 +} +``` + +Nhận cảnh báo khi đạt 80% ngân sách. + +## An Toàn & Kiểm Duyệt + +### Lọc Nội Dung + +Bật OpenAI moderation: + +```json +{ + "moderation": { + "enabled": true, + "blockCategories": ["hate", "harassment", "violence", "self-harm"] + } +} +``` + +Nội dung đáng ngờ bị chặn trước khi phản hồi. + +### Bảo Vệ PII + +Tự động che dữ liệu nhạy cảm: + +```json +{ + "piiProtection": { + "enabled": true, + "redactTypes": ["credit_card", "ssn", "email", "phone"] + } +} +``` + +Logs sẽ hiển thị `[REDACTED]` thay vì giá trị thực. + +## Kiểm Tra + +### Test Mode + +Mô phỏng phản hồi AI mà không gửi đến khách hàng: + +```bash +POST /api/v1/whatsapp/ai-agents/{agentId}/test +Content-Type: application/json + +{ + "conversationHistory": [ + {"role": "user", "content": "Laptop nào tốt nhất?"} + ], + "customerContext": { + "name": "Nguyễn Văn A", + "tags": ["vip"] + } +} +``` + +## Cách Tiếp Cận Hybrid + +Kết hợp tự động hóa + AI để có kết quả tốt nhất: + +### Chiến Lược 1: Tự Động Hóa Trước + +1. Tin nhắn đến → Kiểm tra automation flows +2. Nếu không khớp → Route đến AI +3. Phản hồi AI → Gửi đến khách hàng + +### Chiến Lược 2: AI Phân Loại + +1. AI phân loại intent +2. Route đến automation flow phù hợp +3. Fallback sang AI nếu không có flow khớp + +### Chiến Lược 3: Dựa Trên Thời Gian + +- Giờ làm việc (9 AM - 6 PM): AI bật +- Ngoài giờ: Chỉ tự động hóa (FAQ đơn giản) + +## Thực Hành Tốt + +1. **Bắt đầu với phạm vi hẹp** - Train AI trên các danh mục cụ thể trước +2. **Review thường xuyên** - Mẫu hội thoại hàng tuần +3. **Cập nhật knowledge base** - Giữ thông tin sản phẩm/chính sách hiện tại +4. **Đặt constraints rõ ràng** - Định nghĩa AI có thể/không thể làm gì +5. **Giám sát chi phí** - Đặt ngân sách và cảnh báo +6. **Human in the loop** - Luôn cung cấp đường chuyển giao +7. **Tối ưu prompts** - Lặp lại dựa trên hiệu suất +8. **Sử dụng ví dụ** - Few-shot learning cải thiện chất lượng + +## Xử Lý Sự Cố + +### Phản Hồi AI Quá Chung Chung + +**Giải pháp**: Thêm nhiều ngữ cảnh và ví dụ vào prompt template. + +### AI Cung Cấp Thông Tin Sai + +**Gải pháp**: +1. Cập nhật knowledge base +2. Thêm constraint trong prompt +3. Review và retrain + +### Chi Phí Cao + +**Giải pháp**: +1. Bật phân loại intent +2. Giảm max tokens +3. Dùng GPT-3.5 khi có thể +4. Triển khai caching + +### Phản Hồi Chậm + +**Giải pháp**: +1. Giảm context window (ít tin nhắn lịch sử hơn) +2. Bật streaming +3. Dùng model nhanh hơn (GPT-3.5) + +## Bước Tiếp Theo + +- [Tài Liệu API](API.md) - Tài liệu API cho AI agent +- [Hướng Dẫn Tự Động Hóa](AUTOMATION_GUIDE.md) - Kết hợp với automation +- [Kiến Trúc](ARCHITECTURE.md) - Hiểu về AI pipeline + +## Tài Nguyên + +- [OpenAI Best Practices](https://platform.openai.com/docs/guides/prompt-engineering) +- [Prompt Engineering Guide](https://www.promptingguide.ai/) +- [LLM Cost Calculator](https://docsbot.ai/tools/gpt-openai-api-pricing-calculator) diff --git a/services/mkt-whatsapp-service-net/docs/vi/API.md b/services/mkt-whatsapp-service-net/docs/vi/API.md new file mode 100644 index 00000000..ae2061c5 --- /dev/null +++ b/services/mkt-whatsapp-service-net/docs/vi/API.md @@ -0,0 +1,390 @@ +# Tài Liệu API + +**Dịch vụ**: mkt-whatsapp-service-net +**Phiên bản**: v1.0 +**Base URL**: `/api/v1/whatsapp` + +## Xác Thực + +Tất cả endpoints (trừ webhooks) yêu cầu xác thực qua JWT token. + +```bash +Authorization: Bearer +``` + +## Định Dạng Response + +Tất cả responses tuân theo cấu trúc này: + +```json +{ + "success": true | false, + "data": { ... }, + "error": "Error message" | null, + "pagination": { ... } | null +} +``` + +--- + +## Webhooks + +### Xác Minh Webhook + +**GET** `/webhooks` + +WhatsApp verification challenge. + +**Response**: (Plain text) hub.challenge value + +### Nhận Events + +**POST** `/webhooks` + +Nhận sự kiện tin nhắn từ WhatsApp. + +**Headers**: +- `X-Hub-Signature-256` - HMAC-SHA256 signature + +--- + +## Tài Khoản WhatsApp + +### Kết Nối Tài Khoản + +**POST** `/accounts` + +Kết nối WhatsApp Business Account. + +**Request**: +```json +{ + "shopId": "550e8400-e29b-41d4-a716-446655440000", + "phoneNumberId": "123456789", + "accessToken": "EAAxxxxx", + "webhookUrl": "https://yourdomain.com/api/v1/whatsapp/webhooks" +} +``` + +### Lấy Tài Khoản + +**GET** `/accounts/{shopId}` + +Lấy chi tiết tài khoản cho shop. + +### Ngắt Kết Nối Tài Khoản + +**DELETE** `/accounts/{shopId}` + +Ngắt kết nối WhatsApp Business Account. + +--- + +## Hội Thoại + +### Liệt Kê Hội Thoại + +**GET** `/conversations` + +Lấy danh sách hội thoại có phân trang. + +**Query Parameters**: +- `shopId` (bắt buộc) - Shop ID +- `status` (tùy chọn) - Lọc: `active`, `closed`, `expired` +- `assignedAgentId` (tùy chọn) - Lọc theo agent +- `skip` (mặc định: 0) - Offset phân trang +- `take` (mặc định: 20, max: 100) - Kích thước trang + +### Lấy Hội Thoại + +**GET** `/conversations/{conversationId}` + +Lấy chi tiết hội thoại với tin nhắn. + +### Gửi Tin Nhắn + +**POST** `/conversations/{conversationId}/messages` + +Gửi tin nhắn trong hội thoại. + +**Request (Text)**: +```json +{ + "content": { + "type": "text", + "text": "Cảm ơn bạn đã liên hệ!" + } +} +``` + +**Request (Media)**: +```json +{ + "content": { + "type": "image", + "url": "https://example.com/product.jpg", + "caption": "Xem sản phẩm này!" + } +} +``` + +**Request (Interactive)**: +```json +{ + "content": { + "type": "interactive", + "interactive": { + "type": "button", + "body": { + "text": "Chọn một tùy chọn:" + }, + "action": { + "buttons": [ + {"id": "yes", "title": "Có"}, + {"id": "no", "title": "Không"} + ] + } + } + } +} +``` + +### Chỉ Định Hội Thoại + +**POST** `/conversations/{conversationId}/assign` + +Chỉ định hội thoại cho một agent. + +### Đóng Hội Thoại + +**POST** `/conversations/{conversationId}/close` + +Đóng hội thoại. + +--- + +## Khách Hàng + +### Liệt Kê Khách Hàng + +**GET** `/customers` + +Lấy danh sách khách hàng có phân trang. + +**Query Parameters**: +- `shopId` (bắt buộc) +- `search` (tùy chọn) - Tìm kiếm theo tên/số điện thoại +- `tags` (tùy chọn) - Lọc theo tags (phân tách bằng dấu phẩy) +- `skip` / `take` (phân trang) + +### Lấy Khách Hàng + +**GET** `/customers/{waId}` + +Lấy hồ sơ khách hàng. + +### Cập Nhật Tags Khách Hàng + +**PUT** `/customers/{waId}/tags` + +Thêm hoặc xóa tags khách hàng. + +**Request**: +```json +{ + "addTags": ["vip", "mua-dien-tu"], + "removeTags": ["khach-hang-moi"] +} +``` + +### Cập Nhật Trạng Thái Opt-In + +**PUT** `/customers/{waId}/opt-in` + +Cập nhật đồng ý của khách hàng. + +**Request**: +```json +{ + "status": "opted_in", + "source": "web" +} +``` + +--- + +## Automation Flows + +### Liệt Kê Flows + +**GET** `/flows` + +Lấy automation flows. + +### Tạo Flow + +**POST** `/flows` + +Tạo automation flow. + +### Cập Nhật Flow + +**PUT** `/flows/{flowId}` + +Cập nhật cấu hình flow. + +### Kích Hoạt Flow + +**POST** `/flows/{flowId}/activate` + +Bật automation flow. + +### Vô Hiệu Hóa Flow + +**POST** `/flows/{flowId}/deactivate` + +Tắt automation flow. + +--- + +## AI Agents + +### Tạo AI Agent + +**POST** `/ai-agents` + +Cấu hình chatbot AI. + +### Cập Nhật AI Agent + +**PUT** `/ai-agents/{agentId}` + +Cập nhật personality/prompts. + +### Kích Hoạt AI Agent + +**POST** `/ai-agents/{agentId}/activate` + +Bật phản hồi AI. + +### Kiểm Tra AI Agent + +**POST** `/ai-agents/{agentId}/test` + +Mô phỏng phản hồi AI. + +**Request**: +```json +{ + "conversationHistory": [ + {"role": "user", "content": "Bạn có laptop nào tốt?"} + ], + "customerContext": { + "name": "Nguyễn Văn A", + "tags": ["vip"] + } +} +``` + +**Response**: +```json +{ + "success": true, + "data": { + "generatedResponse": "Chúng tôi có nhiều laptop tuyệt vời! Bạn đang tìm laptop cho mục đích gì ạ? Gaming hay làm việc văn phòng?", + "tokensUsed": {"prompt": 450, "completion": 120, "total": 570}, + "estimatedCost": 0.0154, + "latencyMs": 1850 + } +} +``` + +--- + +## Phân Tích + +### Thống Kê Tin Nhắn + +**GET** `/analytics/messages` + +Lấy metrics khối lượng tin nhắn. + +### Metrics Hội Thoại + +**GET** `/analytics/conversations` + +Lấy metrics hiệu suất hội thoại. + +### Hiệu Suất Tự Động Hóa + +**GET** `/analytics/automations` + +Lấy thống kê thực thi automation flow. + +--- + +## Mã Lỗi + +| Code | Thông Báo | Mô Tả | +|------|---------|-------------| +| 400 | Bad Request | Định dạng request không hợp lệ | +| 401 | Unauthorized | Thiếu hoặc auth token không hợp lệ | +| 404 | Not Found | Resource không tồn tại | +| 409 | Conflict | Resource trùng lặp | +| 422 | Validation Error | Vi phạm business rule | +| 429 | Rate Limit Exceeded | Quá nhiều requests | +| 500 | Internal Server Error | Lỗi server | + +**Định Dạng Error Response**: +```json +{ + "success": false, + "error": "Validation failed: Phone number is required", + "details": { + "field": "phoneNumberId", + "code": "REQUIRED_FIELD" + } +} +``` + +--- + +## Giới Hạn Tốc Độ + +- **Public APIs**: 60 requests/phút per shop +- **Webhooks**: Không giới hạn (nhưng phải phản hồi < 5s) +- **Analytics**: 10 requests/phút per shop + +## Xác Thực Webhook Signature + +Xác minh header `X-Hub-Signature-256`. + +## Phân Trang + +Tất cả list endpoints hỗ trợ phân trang: + +**Request**: +``` +GET /conversations?skip=20&take=20 +``` + +**Response**: +```json +{ + "pagination": { + "page": 2, + "limit": 20, + "total": 150, + "totalPages": 8 + } +} +``` + +## Changelog + +### v1.0 (2026-01-18) +- Phát hành ban đầu +- Tích hợp WhatsApp Cloud API +- Automation flows +- AI chatbot +- Quản lý khách hàng diff --git a/services/mkt-whatsapp-service-net/docs/vi/ARCHITECTURE.md b/services/mkt-whatsapp-service-net/docs/vi/ARCHITECTURE.md new file mode 100644 index 00000000..ab9f0732 --- /dev/null +++ b/services/mkt-whatsapp-service-net/docs/vi/ARCHITECTURE.md @@ -0,0 +1,238 @@ +# Tài Liệu Kiến Trúc + +**Dịch vụ**: mkt-whatsapp-service-net +**Phiên bản**: 1.0 +**Cập nhật lần cuối**: 2026-01-18 + +## Tổng Quan Hệ Thống + +MKT WhatsApp Service là một microservice toàn diện được xây dựng trên nguyên tắc Clean Architecture, triển khai các pattern Domain-Driven Design (DDD) và CQRS. Dịch vụ cung cấp ba khả năng cốt lõi: + +1. **Chatbot Tự Động**: Luồng hội thoại dựa trên quy tắc +2. **AI Chatbot**: Phản hồi thông minh được hỗ trợ bởi LLM +3. **Quản Lý Khách Hàng**: CRM thống nhất cho tương tác WhatsApp + +### Kiến Trúc Tổng Thể + +_(Diagram giống như phiên bản English)_ + +## Các Tầng Clean Architecture + +### 1. Tầng API (`MktWhatsAppService.API`) + +**Trách nhiệm**: Giao diện HTTP, xử lý request/response + +#### Controllers +- `WebhooksController` - Xác thực webhook và sự kiện tin nhắn từ WhatsApp +- `WhatsAppAccountsController` - Quản lý kết nối tài khoản +- `ConversationsController` - Các API liên quan hội thoại và tin nhắn +- `CustomersController` - Quản lý hồ sơ khách hàng +- `AutomationFlowsController` - CRUD automation flows +- `AIAgentsController` - Cấu hình AI agent +- `AnalyticsController` - Metrics và báo cáo + +#### Background Jobs +- `ConversationExpiryJob` - Đóng hội thoại hết hạn sau 24h +- `MessageStatusSyncJob` - Đồng bộ trạng thái delivered/read từ WhatsApp +- `FlowSchedulerJob` - Trigger automation flows theo thời gian + +### 2. Tầng Application (`MktWhatsAppService.API/Application`) + +**Trách nhiệm**: Use cases, orchestration, CQRS + +#### Commands (Ghi) + +**Tài Khoản WhatsApp** +- `ConnectWhatsAppAccountCommand` - Đăng ký tài khoản mới +- `UpdateWebhookCommand` - Cập nhật cấu hình webhook +- `DisconnectWhatsAppAccountCommand` - Hủy kích hoạt tài khoản + +**Tin Nhắn** +- `ProcessIncomingMessageCommand` - Xử lý tin nhắn đến từ WhatsApp +- `SendMessageCommand` - Gửi tin nhắn đi +- `SendTemplateMessageCommand` - Gửi template đã được phê duyệt + +**Tự Động Hóa** +- `CreateAutomationFlowCommand` - Định nghĩa flow mới +- `UpdateFlowStepCommand` - Sửa đổi logic flow +- `ActivateFlowCommand` - Bật tự động hóa +- `DeactivateFlowCommand` - Tắt tự động hóa + +**AI Agent** +- `CreateAIAgentCommand` - Cấu hình chatbot AI +- `UpdateAgentPersonalityCommand` - Sửa đổi hành vi AI +- `GenerateAIResponseCommand` - Lấy phản hồi AI + +**Khách Hàng** +- `CreateCustomerCommand` - Đăng ký khách hàng mới +- `UpdateCustomerOptInCommand` - Quản lý đồng ý nhận tin +- `TagCustomerCommand` - Thêm/xóa tags + +#### Queries (Đọc) + +**Hội Thoại** +- `GetConversationQuery` - Lấy một hội thoại với tin nhắn +- `GetActiveConversationsQuery` - Liệt kê hội thoại đang diễn ra +- `SearchConversationsQuery` - Tìm kiếm full-text + +**Khách Hàng** +- `GetCustomerQuery` - Hồ sơ khách hàng theo WaId +- `GetCustomersQuery` - Danh sách khách hàng có phân trang +- `GetCustomerConversationHistoryQuery` - Tất cả hội thoại trong quá khứ + +**Phân Tích** +- `GetMessageStatsQuery` - Metrics khối lượng tin nhắn +- `GetConversationMetricsQuery` - Thời gian phản hồi, tỷ lệ giải quyết +- `GetAutomationPerformanceQuery` - Thống kê thực thi flow + +#### MediatR Pipeline Behaviors +1. **Logging Behavior** - Log tất cả commands/queries +2. **Validation Behavior** - Tích hợp FluentValidation +3. **Transaction Behavior** - Unit of Work cho commands + +### 3. Tầng Domain (`MktWhatsAppService.Domain`) + +**Trách nhiệm**: Business logic, entities, business rules + +#### Aggregates + +_(Nội dung chi tiết aggregates tương tự phiên bản English, chỉ dịch các comment và description sang tiếng Việt)_ + +### 4. Tầng Infrastructure (`MktWhatsAppService.Infrastructure`) + +**Trách nhiệm**: External concerns, persistence, API clients + +#### Truy Cập Dữ Liệu +- `MktWhatsAppServiceContext` - EF Core DbContext +- Entity Configurations sử dụng Fluent API +- Repositories triển khai domain interfaces + +#### External Services + +##### WhatsAppCloudApiClient +HTTP client cho WhatsApp Cloud API với Polly resilience policies. + +##### LlmService +Abstraction cho LLM provider (triển khai OpenAI). + +## Luồng Xử Lý Tin Nhắn + +_(Sequence diagrams tương tự phiên bản English)_ + +## Mô Hình Dữ Liệu + +Xem [Tài Liệu Database Schema](DATABASE_SCHEMA.md) để biết chi tiết cấu trúc bảng và indexes. + +Các bảng chính: +- `whatsapp_accounts` - Kết nối tài khoản doanh nghiệp +- `conversations` - Hội thoại khách hàng +- `messages` - Tin nhắn riêng lẻ (owned by conversation) +- `customers` - Hồ sơ khách hàng +- `automation_flows` - Định nghĩa automation flow +- `flow_steps` - Cấu hình bước flow +- `ai_agents` - Cấu hình AI agent + +## Integration Events + +Dịch vụ publish events đến RabbitMQ để các service khác consume. + +### Events Được Publish + +**WhatsAppMessageReceivedEvent** +- Phát ra khi: Khách hàng gửi tin nhắn đến shop +- Consumers: analytics-service (metrics), merchant-service (thông báo) + +**ConversationClosedEvent** +- Phát ra khi: Hội thoại được đóng hoặc hết hạn +- Consumers: analytics-service (thời lượng hội thoại), merchant-service + +**AITokenUsageEvent** +- Phát ra khi: AI agent tạo phản hồi +- Consumers: wallet-service (billing), analytics-service (theo dõi chi phí) + +**CustomerOptInChangedEvent** +- Phát ra khi: Trạng thái opt-in của khách hàng thay đổi +- Consumers: marketing services (cập nhật quyền) + +## Bảo Mật + +### Xác Thực Webhook Signature + +Tất cả webhooks đến từ WhatsApp được xác thực bằng HMAC-SHA256. + +### Mã Hóa Access Token + +WhatsApp access tokens được mã hóa khi lưu trữ bằng AES-256-GCM. + +### Rate Limiting + +Rate limiter phân tán dựa trên Redis: +- 60 requests/phút per shop +- 1000 requests/phút per service instance + +### Tuân Thủ GDPR + +- Dữ liệu khách hàng có thể được export qua API +- Right to be forgotten: soft delete với anonymization +- Tracking đồng ý opt-in với timestamps +- Chính sách lưu trữ dữ liệu được thực thi + +## Tối Ưu Hiệu Năng + +### Chiến Lược Caching + +**Sử Dụng Redis Cache:** +1. **Conversation Context** - 10 tin nhắn cuối (TTL: 1 giờ) +2. **Customer Profiles** - Khách hàng được truy cập thường xuyên (TTL: 30 phút) +3. **Active Flows** - Automation flows (TTL: 5 phút) +4. **Rate Limit Counters** - Số requests per shop (TTL: 1 phút) + +### Tối Ưu Query + +- Dùng Dapper cho read-heavy queries (bypass EF Core) +- Triển khai pagination cho tất cả list endpoints +- Index trên foreign keys và các cột thường được filter +- Không có N+1 queries (dùng `Include()` hoặc projections) + +### Background Processing + +- Webhook processing trả về 200 ngay lập tức +- Gửi tin nhắn được queue vào background job +- Flow execution chạy bất đồng bộ + +## Giám Sát & Quan Sát + +### Health Checks + +Kiểm tra kết nối đến PostgreSQL, Redis, RabbitMQ, WhatsApp API, và OpenAI API. + +### Metrics (Prometheus) + +- `whatsapp_messages_received_total` - Counter +- `whatsapp_messages_sent_total` - Counter +- `whatsapp_conversation_duration_seconds` - Histogram +- `whatsapp_ai_tokens_used_total` - Counter +- `whatsapp_webhook_processing_duration_ms` - Histogram + +### Logging (Loki) + +Structured logging với Serilog với correlation IDs và redaction cho sensitive data. + +## Kiến Trúc Triển Khai + +Xem [Deployment Guide](DEPLOYMENT.md) cho Kubernetes manifests và scaling strategies. + +**Trigger Mở Rộng:** +- CPU > 70% → Scale up pods +- Webhook queue > 1000 messages → Scale up +- Memory > 80% → Investigate + scale + +**Resource Limits:** +- Requests: 256Mi memory, 250m CPU +- Limits: 512Mi memory, 500m CPU + +## Tài Liệu Tham Khảo + +- [WhatsApp Cloud API Docs](https://developers.facebook.com/docs/whatsapp/cloud-api) +- [OpenAPI Specification](../openapi.yaml) +- [Domain Model Details](DOMAIN_MODELS.md) diff --git a/services/mkt-whatsapp-service-net/docs/vi/AUTOMATION_GUIDE.md b/services/mkt-whatsapp-service-net/docs/vi/AUTOMATION_GUIDE.md new file mode 100644 index 00000000..ea144703 --- /dev/null +++ b/services/mkt-whatsapp-service-net/docs/vi/AUTOMATION_GUIDE.md @@ -0,0 +1,262 @@ +# Hướng Dẫn Tự Động Hóa + +**Cập nhật lần cuối**: 2026-01-18 + +Học cách tạo và quản lý automation flows cho hội thoại WhatsApp. + +## Tổng Quan + +Automation flows cho phép bạn định nghĩa logic chatbot dựa trên quy tắc không cần AI. Các use case bao gồm: + +- Tin nhắn chào mừng khách hàng mới +- Tự động trả lời FAQ +- Luồng xác nhận đơn hàng +- Phân loại leads +- Đặt lịch hẹn +- Định tuyến hỗ trợ khách hàng + +## Khái Niệm Cốt Lõi + +### Loại Trigger + +|Trigger | Mô Tả | Ví Dụ | +|---------|-------------|---------| +| **Keyword** | Tin nhắn chứa văn bản cụ thể | "hi", "help", "giá" | +| **Event** | Sự kiện hệ thống xảy ra | Khách hàng opt in, đơn hàng được tạo | +| **Schedule** | Kích hoạt dựa trên thời gian | Hàng ngày lúc 9 giờ sáng, mỗi thứ Hai | + +### Các Bước trong Flow + +Mỗi flow bao gồm các bước được sắp xếp. Loại bước: + +**1. Send Message** - Gửi tin nhắn text hoặc media + +**2. Quick Reply** - Hiển thị nút để khách hàng nhấn + +**3. Tag Customer** - Thêm/xóa tag khách hàng + +**4. Call Webhook** - POST dữ liệu đến URL bên ngoài + +**5. Assign to Agent** - Chuyển hội thoại cho nhân viên + +**6. Delay** - Chờ trước bước tiếp theo + +**7. Conditional Branch** - Logic if/else + +## Tạo Flow + +### Qua API + +```bash +POST /api/v1/whatsapp/flows +Content-Type: application/json + +{ + "shopId": "shop-guid", + "flowName": "Chào Mừng Khách Hàng Mới", + "triggerType": "keyword", + "triggerConfig": { + "keywords": ["hi", "hello", "chào"] + }, + "steps": [ + { + "order": 1, + "action": "send_message", + "actionConfig": { + "text": "Chào mừng đến {shop_name}! 👋\n\nChúng tôi có thể giúp gì cho bạn hôm nay?" + } + }, + { + "order": 2, + "action": "quick_reply", + "actionConfig": { + "text": "Chọn một tùy chọn:", + "buttons": [ + {"id": "browse", "title": "Xem Sản Phẩm"}, + {"id": "track", "title": "Tra Đơn Hàng"}, + {"id": "support", "title": "Hỗ Trợ"} + ] + } + } + ] +} +``` + +## Ví Dụ Flow + +### Ví Dụ 1: FAQ Bot + +**Trigger**: Keywords "giá", "chi phí", "bao nhiêu" + +**Flow**: +1. Gửi: "Giá của chúng tôi phụ thuộc vào sản phẩm. Bạn quan tâm đến gì?" +2. Quick Reply: ["Quần Áo", "Điện Tử", "Thực Phẩm"] +3. Conditional: + - Nếu "Quần Áo" → Gửi bảng giá quần áo + - Nếu "Điện Tử" → Gửi bảng giá điện tử + - Nếu "Thực Phẩm" → Gửi bảng giá thực phẩm + +### Ví Dụ 2: Đặt Lịch Hẹn + +**Trigger**: Keyword "đặt lịch", "hẹn" + +**Flow**: +1. Gửi: "Tôi có thể giúp bạn đặt lịch hẹn! 📅" +2. Gửi: "Bạn cần dịch vụ gì?" +3. Quick Reply: ["Tư Vấn", "Khám", "Tái Khám"] +4. Tag Customer: "lich-hen-cho-xu-ly" +5. Call Webhook: POST đến hệ thống đặt lịch +6. Delay: 2 giây (chờ webhook response) +7. Gửi: "Lịch hẹn của bạn đã được xác nhận! Bạn sẽ nhận được nhắc nhở." + +### Ví Dụ 3: Tra Đơn Hàng + +**Trigger**: Keyword "tra đơn", "đơn hàng" + +**Flow**: +1. Gửi: "Vui lòng gửi mã đơn hàng (VD: #12345)" +2. (Khách hàng trả lời với mã đơn hàng) +3. Call Webhook: GET trạng thái đơn hàng từ backend +4. Conditional: + - Nếu tìm thấy đơn → Gửi trạng thái + link tracking + - Nếu không tìm thấy → Gửi "Không tìm thấy đơn hàng. Vui lòng kiểm tra lại mã." + +## Biến + +Sử dụng biến trong văn bản tin nhắn để cá nhân hóa: + +### Biến Khách Hàng + +- `{customer_name}` - Tên khách hàng +- `{customer_phone}` - Số điện thoại WhatsApp +- `{customer_tags}` - Tags phân tách bằng dấu phẩy + +### Biến Shop + +- `{shop_name}` - Tên shop +- `{shop_url}` - URL website shop + +### Biến Hội Thoại + +- `{conversation_id}` - UUID hội thoại +- `{message_count}` - Số tin nhắn trong hội thoại + +## Điều Kiện + +### Các Điều Kiện Được Hỗ Trợ + +**Tag Tồn Tại** +```json +{ + "type": "tag_exists", + "tag": "khach-hang-vip" +} +``` + +**Custom Field Bằng** +```json +{ + "type": "custom_field_equals", + "field": "city", + "value": "Hanoi" +} +``` + +**Thời Gian Trong Ngày** +```json +{ + "type": "time_of_day", + "start": "09:00", + "end": "17:00", + "timezone": "Asia/Ho_Chi_Minh" +} +``` + +## Kích Hoạt Flow + +```bash +POST /api/v1/whatsapp/flows/{flowId}/activate +``` + +## Kiểm Tra Flow + +### Test Mode + +Bật test mode để xem thực thi mà không gửi tin nhắn thực tế: + +```bash +POST /api/v1/whatsapp/flows/{flowId}/test +Content-Type: application/json + +{ + "shopId": "shop-guid", + "customerWaId": "84901234567", + "simulatedMessage": "chào" +} +``` + +## Thực Hành Tốt + +### 1. Giữ Flow Đơn Giản + +- Tối đa 10 bước mỗi flow +- Tránh nesting sâu của điều kiện +- Chia flow phức tạp thành nhiều flow nhỏ hơn + +### 2. Cung Cấp Điểm Thoát + +Luôn cho khách hàng cách để: +- Nói chuyện với nhân viên ("hỗ trợ", "help") +- Bắt đầu lại ("restart", "menu") +- Opt out ("stop", "unsubscribe") + +### 3. Xử Lý Input Không Biết + +Thêm bước fallback: +```json +{ + "order": 99, + "action": "send_message", + "actionConfig": { + "text": "Tôi không hiểu. Trả lời 'menu' để xem tùy chọn hoặc 'hỗ trợ' để nói chuyện với nhân viên." + } +} +``` + +### 4. Sử Dụng Delays Khôn Ngoan + +- Sau webhook calls: 2-5 giây +- Giữa các tin nhắn: 1-2 giây (tự nhiên hơn) +- Tránh delays > 10 giây (khách hàng có thể rời đi) + +## Giới Hạn + +- Tối đa 50 flows active mỗi shop +- Tối đa 20 bước mỗi flow +- Tối đa 10 nút quick reply mỗi tin nhắn +- Webhook timeout: 10 giây +- Không có vòng lặp (xác thực chống cycle) + +## Xử Lý Sự Cố + +### Flow Không Trigger + +**Kiểm tra**: +1. Flow đã được kích hoạt (`isActive: true`) +2. Trigger keyword khớp chính xác (không phân biệt chữ hoa/thường) +3. Không có flow ưu tiên cao hơn matching trước +4. Khách hàng chưa opt out + +### Webhook Thất Bại + +**Kiểm tra**: +1. Webhook URL có thể truy cập (yêu cầu HTTPS) +2. Webhook phản hồi trong vòng 10 giây +3. Response status code là 200 +4. Response JSON hợp lệ + +## Bước Tiếp Theo + +- [Hướng Dẫn AI Chatbot](AI_CHATBOT_GUIDE.md) - Kết hợp với AI cho cách tiếp cận hybrid +- [Tài Liệu API](API.md) - Tài liệu API đầy đủ +- [Kiến Trúc](ARCHITECTURE.md) - Hiểu về automation engine diff --git a/services/mkt-whatsapp-service-net/docs/vi/WHATSAPP_SETUP.md b/services/mkt-whatsapp-service-net/docs/vi/WHATSAPP_SETUP.md new file mode 100644 index 00000000..756be211 --- /dev/null +++ b/services/mkt-whatsapp-service-net/docs/vi/WHATSAPP_SETUP.md @@ -0,0 +1,261 @@ +# Hướng Dẫn Thiết Lập WhatsApp + +**Cập nhật lần cuối**: 2026-01-18 + +Hướng dẫn từng bước để thiết lập truy cập WhatsApp Business API cho MKT WhatsApp Service. + +## Yêu Cầu Trước Khi Bắt Đầu + +- Tài khoản Meta Business +- Quyền truy cập Facebook Business Manager +- Doanh nghiệp đã được xác minh (để có giới hạn tier cao hơn) +- Domain có HTTPS (cho webhook) + +## Bước 1: Tạo Tài Khoản Meta Business + +1. Truy cập [Meta Business Suite](https://business.facebook.com/) +2. Nhấp "Tạo Tài Khoản" +3. Nhập tên doanh nghiệp và thông tin chi tiết +4. Xác minh email doanh nghiệp của bạn + +## Bước 2: Truy Cập WhatsApp API + +### Tùy Chọn A: Cloud API (Khuyến Nghị) + +1. Truy cập [Meta for Developers](https://developers.facebook.com/) +2. Nhấp "My Apps" → "Create App" +3. Chọn "Business" làm loại app +4. Điền thông tin app (tên, email liên hệ, tài khoản doanh nghiệp) +5. Sau khi tạo, nhấp "Add Product" +6. Chọn "WhatsApp" → "Set Up" + +### Tùy Chọn B: On-Premise API + +Không khuyến nghị cho hầu hết các trường hợp sử dụng. + +## Bước 3: Lấy Số Điện Thoại + +### Số Test (Development) + +Meta cung cấp một số test cho phát triển: + +1. Trong cài đặt WhatsApp product, bạn sẽ thấy số điện thoại test +2. Copy `Phone Number ID` +3. Thêm người nhận test (tối đa 5 người) trong tab Configuration + +### Số Production + +1. Nhấp "Add Phone Number" +2. Chọn một trong hai: + - **Use existing**: Chuyển số WhatsApp Business hiện có + - **Register new**: Lấy số mới từ Meta +3 Xác minh số điện thoại qua SMS/gọi điện +4. Hoàn thành xác minh doanh nghiệp + +**Quan trọng**: Sau khi kết nối với API, bạn không thể sử dụng WhatsApp Business App trên số này. + +## Bước 4: Tạo Access Token + +### Token Tạm Thời (24 giờ) + +1. Vào WhatsApp → API Setup +2. Copy temporary access token +3. Chỉ dùng để test + +### Token Vĩnh Viễn + +1. Vào Meta Business Suite → Settings → System Users +2. Nhấp "Add" → Tạo system user (tên: "WhatsApp API") +3. Gán role "Admin" +4. Nhấp "Generate Token" +5. Chọn app của bạn +6. Chọn permissions: + - `whatsapp_business_management` + - `whatsapp_business_messaging` +7. Copy token (lưu an toàn, chỉ hiển thị một lần) + +## Bước 5: Cấu Hình Webhook + +### Lấy Webhook URL + +Từ service đã deploy của bạn: +``` +https://yourdomain.com/api/v1/whatsapp/webhooks +``` + +### Tạo Verify Token + +Tạo chuỗi ngẫu nhiên để xác thực webhook: + +```bash +# Tạo token ngẫu nhiên +openssl rand -hex 32 +``` + +Lưu vào `WHATSAPP_WEBHOOK_VERIFY_TOKEN` trong `.env` + +### Thiết Lập Trong Meta + +1. Vào WhatsApp → Configuration → Webhook +2. Nhấp "Edit" +3. Nhập: + - **Callback URL**: `https://yourdomain.com/api/v1/whatsapp/webhooks` + - **Verify Token**: Token bạn vừa tạo +4. Nhấp "Verify and Save" + +### Đăng Ký Events + +Sau khi xác minh, đăng ký: +- ✅ `messages` - Tin nhắn đến từ khách hàng +- ✅ `message_status` (tùy chọn) - Trạng thái delivered/read +- ✅ `messaging_postbacks` (tùy chọn) - Tương tác với nút + +## Bước 6: Lấy App Secret + +Để xác thực webhook signature: + +1. Vào App Dashboard → Settings → Basic +2. Nhấp "Show" bên cạnh "App Secret" +3. Copy và lưu vào `WHATSAPP_APP_SECRET` + +## Bước 7: Cấu Hình Service + +Cập nhật file `.env`: + +```bash +# WhatsApp Configuration +WHATSAPP_PHONE_NUMBER_ID=123456789012345 +WHATSAPP_ACCESS_TOKEN=your_permanent_token_here +WHATSAPP_WEBHOOK_VERIFY_TOKEN=your_verify_token_here +WHATSAPP_APP_SECRET=your_app_secret_here +WHATSAPP_API_VERSION=v21.0 +``` + +## Bước 8: Kiểm Tra Tích Hợp + +### Xác Minh Webhook + +Service sẽ tự động xử lý xác thực webhook. Kiểm tra logs: + +```bash +docker-compose logs -f mkt-whatsapp-service-net +``` + +Bạn nên thấy: +``` +[INFO] Webhook verification successful +``` + +### Gửi Tin Nhắn Test + +Sử dụng API để gửi tin nhắn test đến khách hàng. + +### Nhận Tin Nhắn Test + +1. Gửi tin nhắn từ WhatsApp của khách hàng test đến số doanh nghiệp +2. Kiểm tra service logs cho incoming webhook +3. Xác minh tin nhắn được lưu trong database + +## Bước 9: Message Templates + +Để gửi tin nhắn ngoài cửa sổ 24 giờ, bạn cần templates đã được phê duyệt. + +### Tạo Template + +1. Vào WhatsApp → Message Templates +2. Nhấp "Create Template" +3. Điền: + - **Name**: `order_confirmation` (chữ thường, gạch dưới) + - **Category**: Utility/Marketing/Authentication + - **Language**: Vietnamese, English, etc. + - **Content**: Sử dụng placeholders như `{{1}}`, `{{2}}` + +Ví dụ template: +``` +Xin chào {{1}}! + +Đơn hàng #{{2}} của bạn đã được xác nhận. +Tổng tiền: {{3}} VNĐ + +Cảm ơn bạn đã mua hàng! +``` + +4. Submit để review (phê duyệt mất 1-3 ngày) + +## Bước 10: Nâng Cấp Giới Hạn Tier + +### Tier Ban Đầu + +Số điện thoại mới bắt đầu ở **Tier 1** (1,000 hội thoại/ngày). + +### Quy Trình Nâng Cấp + +Tiers tự động nâng cấp dựa trên: +1. **Chất lượng số điện thoại** (tỷ lệ block thấp) +2. **Khối lượng gửi** +3. **Thời gian** (tối thiểu 7 ngày ở tier hiện tại) + +### Các Cấp Tier + +| Tier | Giới Hạn Hàng Ngày | Tiêu Chí Nâng Cấp | +|------|-------------------|-------------------| +| Tier 1 | 1,000 | Tier khởi đầu | +| Tier 2 | 10,000 | 7 ngày + chất lượng tốt | +| Tier 3 | 100,000 | 7 ngày + khối lượng cao | +| Unlimited | Không giới hạn | Yêu cầu từ Meta | + +## Xử Lý Sự Cố + +### Webhook Verification Thất Bại + +**Vấn đề**: "Verification token mismatch" + +**Giải pháp**: +1. Kiểm tra `WHATSAPP_WEBHOOK_VERIFY_TOKEN` khớp chính xác +2. Đảm bảo service đang chạy và có thể truy cập +3. Kiểm tra HTTPS hoạt động (WhatsApp yêu cầu HTTPS) + +### Tin Nhắn Không Gửi Được + +**Vấn đề**: API trả về lỗi `(#131030) Recipient phone number not valid` + +**Giải pháp**: +1. Đảm bảo số bao gồm mã quốc gia không có + hoặc 0 +2. Format: `84901234567` (Việt Nam), không phải `+84901234567` + +### Vượt Giới Hạn Tốc Độ + +**Vấn đề**: `(#130429) Rate limit exceeded` + +**Giải pháp**: +1. Kiểm tra tier hiện tại trong Meta dashboard +2. Triển khai exponential backoff +3. Yêu cầu nâng cấp tier nếu cần + +## Thực Hành Tốt Về Bảo Mật + +1. **Không bao giờ commit tokens** - Dùng biến môi trường +2. **Xoay vòng tokens thường xuyên** - Tạo token mới mỗi 6 tháng +3. **Xác minh webhook signatures** - Luôn validate `X-Hub-Signature-256` +4. **Chỉ dùng HTTPS** - WhatsApp sẽ từ chối HTTP webhooks +5. **Hạn chế truy cập IP** - Whitelist Meta IP ranges nếu có thể + +## Tối Ưu Chi Phí + +1. **Dùng utility templates** - Rẻ hơn marketing +2. **Tận dụng cửa sổ 24 giờ** - Tin nhắn miễn phí trong cửa sổ +3. **Tránh spam** - Tỷ lệ block cao có thể giới hạn tài khoản +4. **Giám sát conversations** - Theo dõi loại nào mở/đóng cửa sổ + +## Bước Tiếp Theo + +- [Tài Liệu API](API.md) - Tìm hiểu các endpoints có sẵn +- [Hướng Dẫn Tự Động Hóa](AUTOMATION_GUIDE.md) - Thiết lập automation flows +- [Hướng Dẫn AI Chatbot](AI_CHATBOT_GUIDE.md) - Cấu hình AI agent + +## Tài Nguyên + +- [WhatsApp Cloud API Docs](https://developers.facebook.com/docs/whatsapp/cloud-api) +- [Business Verification](https://www.facebook.com/business/help/2058515294227817) +- [Message Templates Guide](https://developers.facebook.com/docs/whatsapp/business-management-api/message-templates) +- [Webhook Reference](https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks) diff --git a/services/mkt-x-service-net/README.md b/services/mkt-x-service-net/README.md new file mode 100644 index 00000000..c22bb318 --- /dev/null +++ b/services/mkt-x-service-net/README.md @@ -0,0 +1,438 @@ +# MKT X/Twitter Service +## Twitter Marketing Service / Dịch Vụ Marketing Twitter + +> **EN**: Comprehensive marketing automation and customer engagement service for X/Twitter +> **VI**: Dịch vụ tự động hóa marketing và tương tác khách hàng toàn diện cho X/Twitter + +[![.NET](https://img.shields.io/badge/.NET-8.0-512BD4)](https://dotnet.microsoft.com/) +[![PostgreSQL](https://img.shields.io/badge/PostgreSQL-15+-336791)](https://www.postgresql.org/) +[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) + +--- + +## Overview / Tổng Quan + +**EN**: The Twitter Marketing Service provides three core capabilities for social media marketing through X/Twitter: + +- **CHATBOT Automation** - Template-based messaging with workflows and scheduling +- **CHATBOT AI** - AI-powered conversations using OpenAI integration +- **Customer Management** - Contact database, segmentation, and analytics + +**VI**: Dịch vụ Twitter Marketing cung cấp ba khả năng cốt lõi cho marketing trên X/Twitter: + +- **CHATBOT Tự Động** - Gửi tin nhắn dựa trên template với workflows và lịch trình +- **CHATBOT AI** - Trò chuyện thông minh sử dụng OpenAI +- **Quản Lý Khách Hàng** - Cơ sở dữ liệu liên hệ, phân khúc, và phân tích + +--- + +## Features / Tính Năng + +### 🤖 Automation Messenger + +- ✅ Message template library / Thư viện mẫu tin nhắn +- ✅ Visual workflow designer / Thiết kế workflow trực quan +- ✅ Event-triggered messaging / Tin nhắn kích hoạt sự kiện +- ✅ Scheduled campaigns / Chiến dịch theo lịch +- ✅ A/B testing / Kiểm thử A/B +- ✅ Rate limiting compliance / Tuân thủ giới hạn tốc độ + +### 🧠 AI Messenger + +- ✅ Natural language understanding / Hiểu ngôn ngữ tự nhiên +- ✅ Context-aware conversations / Trò chuyện theo ngữ cảnh +- ✅ Intent detection / Phát hiện ý định +- ✅ Integration with merchant data / Tích hợp dữ liệu merchant +- ✅ Auto escalation to human / Tự động chuyển cho người +- ✅ Sentiment analysis / Phân tích cảm xúc + +### 👥 Customer Management + +- ✅ Contact profile management / Quản lý hồ sơ liên hệ +- ✅ Conversation history / Lịch sử trò chuyện +- ✅ Customer segmentation / Phân khúc khách hàng +- ✅ Tag management / Quản lý nhãn +- ✅ Custom attributes / Thuộc tính tùy chỉnh +- ✅ Engagement analytics / Phân tích tương tác + +--- + +## Prerequisites / Yêu Cầu + +| Requirement | Version | Notes | +|-------------|---------|-------| +| **.NET SDK** | 8.0+ | [Download](https://dotnet.microsoft.com/download) | +| **PostgreSQL** | 15+ | For data storage / Lưu trữ dữ liệu | +| **Redis** | 7+ | For caching / Cache | +| **RabbitMQ** | 3.12+ | For message bus / Message bus | +| **Twitter Developer Account** | - | Required for API / Cần cho API | +| **OpenAI API Key** | - | Optional for AI / Tùy chọn cho AI | + +--- + +## Quick Start / Bắt Đầu Nhanh + +### 1. Clone Repository + +```bash +cd services/mkt-x-service-net +``` + +### 2. Configure Environment / Cấu Hình + +Create `appsettings.Development.json`: + +```json +{ + "ConnectionStrings": { + "DefaultConnection": "Host=localhost;Database=mkt_x_service;Username=postgres;Password=postgres" + }, + "Twitter": { + "ApiKey": "your_twitter_api_key", + "ApiKeySecret": "your_twitter_api_secret", + "BearerToken": "your_bearer_token", + "WebhookUrl": "https://your-domain.com/api/v1/mkt-x/webhooks/twitter" + }, + "OpenAI": { + "ApiKey": "your_openai_api_key", + "Model": "gpt-4" + }, + "RabbitMQ": { + "Host": "localhost", + "Username": "guest", + "Password": "guest" + }, + "Redis": { + "ConnectionString": "localhost:6379" + } +} +``` + +### 3. Run Migrations / Chạy Migrations + +```bash +dotnet ef database update --project src/MktXService.Infrastructure +``` + +### 4. Run Service / Chạy Service + +```bash +dotnet run --project src/MktXService.API +``` + +**Access Points**: +- API: http://localhost:5000 +- Swagger: http://localhost:5000/swagger + +--- + +## Documentation / Tài Liệu + +### English Documentation + +- **[Architecture](docs/ARCHITECTURE.md)** - System architecture and domain model +- **[API Reference](docs/API.md)** - Complete API documentation with examples +- **[Twitter Setup Guide](docs/TWITTER_SETUP.md)** - Step-by-step Twitter API setup + +### Vietnamese Documentation / Tài Liệu Tiếng Việt + +- **[Kiến Trúc](docs/vi/ARCHITECTURE.md)** - Kiến trúc hệ thống và mô hình domain +- **[Tài Liệu API](docs/vi/API.md)** - Tài liệu API đầy đủ với ví dụ +- **[Hướng Dẫn Thiết Lập Twitter](docs/vi/TWITTER_SETUP.md)** - Hướng dẫn thiết lập Twitter API + +--- + +## API Endpoints + +### Core Endpoints + +``` +# Account Management +POST /api/v1/mkt-x/accounts # Connect Twitter account +GET /api/v1/mkt-x/accounts # List accounts +DELETE /api/v1/mkt-x/accounts/{id} # Disconnect + +# Contact Management +GET /api/v1/mkt-x/contacts # List contacts +POST /api/v1/mkt-x/contacts/{id}/tags # Add tags +PUT /api/v1/mkt-x/contacts/{id}/attributes # Update attributes + +# Conversations +GET /api/v1/mkt-x/conversations # List conversations +POST /api/v1/mkt-x/conversations/{id}/messages # Send message + +# Campaigns +POST /api/v1/mkt-x/campaigns # Create campaign +POST /api/v1/mkt-x/campaigns/{id}/start # Start campaign +GET /api/v1/mkt-x/campaigns/{id}/metrics # View metrics + +# Automation +POST /api/v1/mkt-x/automation/flows # Create workflow +POST /api/v1/mkt-x/automation/flows/{id}/activate # Activate + +# AI Chatbot +POST /api/v1/mkt-x/ai/conversations/{id}/message # AI chat +GET /api/v1/mkt-x/analytics/overview # Dashboard analytics +``` + +**Full API documentation**: See [API.md](docs/API.md) + +--- + +## Project Structure / Cấu Trúc + +``` +mkt-x-service-net/ +├── src/ +│ ├── MktXService.API/ # Controllers, Swagger +│ │ ├── Controllers/ # API Controllers +│ │ └── Application/ # Commands, Queries, DTOs +│ ├── MktXService.Domain/ # Domain model +│ │ ├── AggregatesModel/ # Aggregates +│ │ ├── Events/ # Domain events +│ │ └── SeedWork/ # Base classes +│ └── MktXService.Infrastructure/ # EF Core, Repositories +│ ├── Data/ # DbContext +│ ├── Repositories/ # Data access +│ ├── Services/ # External clients +│ └── BackgroundJobs/ # Background workers +├── tests/ +│ ├── MktXService.UnitTests/ +│ └── MktXService.IntegrationTests/ +├── docs/ # Documentation +├── Dockerfile +└── docker-compose.yml +``` + +--- + +## Development / Phát Triển + +### Build + +```bash +dotnet build +``` + +### Run Tests + +```bash +dotnet test +``` + +### Create Migration + +```bash +dotnet ef migrations add MigrationName --project src/MktXService.Infrastructure +``` + +### Docker Deployment + +```bash +# Build +docker-compose -f deployments/local/docker-compose.yml build mkt-x-service-net + +# Run +docker-compose -f deployments/local/docker-compose.yml up -d mkt-x-service-net + +# Logs +docker-compose -f deployments/local/docker-compose.yml logs -f mkt-x-service-net +``` + +--- + +## Architecture / Kiến Trúc + +### Clean Architecture Layers + +``` +┌─────────────────────────────────────┐ +│ API Layer (Controllers) │ +├─────────────────────────────────────┤ +│ Application Layer (CQRS + MediatR) │ +├─────────────────────────────────────┤ +│ Domain Layer (Aggregates) │ +├─────────────────────────────────────┤ +│ Infrastructure (EF Core, Twitter) │ +└─────────────────────────────────────┘ +``` + +### Key Patterns + +- **CQRS** with MediatR for command/query separation +- **DDD** with 9 aggregate roots +- **Repository Pattern** for data access +- **Event-Driven** with RabbitMQ + +**Details**: See [ARCHITECTURE.md](docs/ARCHITECTURE.md) + +--- + +## Configuration / Cấu Hình + +### Environment Variables + +```bash +# Database +ConnectionStrings__DefaultConnection="Host=localhost;Database=mkt_x_service" + +# Twitter API +Twitter__ApiKey="your_api_key" +Twitter__ApiKeySecret="your_api_secret" +Twitter__WebhookUrl="https://your-domain.com/api/v1/mkt-x/webhooks/twitter" + +# OpenAI +OpenAI__ApiKey="sk-..." +OpenAI__Model="gpt-4" + +# RabbitMQ +RabbitMQ__Host="localhost" + +# Redis +Redis__ConnectionString="localhost:6379" +``` + +--- + +## Monitoring / Giám Sát + +### Health Check + +```bash +curl http://localhost:5000/health +``` + +### Metrics + +- **Prometheus**: `http://localhost:5000/metrics` +- **Grafana Dashboard**: Available in production + +### Logging + +Structured logging with Serilog, sent to Loki: + +```json +{ + "timestamp": "2026-01-18T10:00:00Z", + "level": "Information", + "message": "Campaign started", + "properties": { + "campaignId": "...", + "merchantId": "..." + } +} +``` + +--- + +##Troubleshooting / Xử Lý Sự Cố + +### Common Issues / Vấn Đề Thường Gặp + +#### 1. Twitter API 401 Unauthorized + +**Solution**: +- Verify API credentials in configuration +- Check OAuth token expiration +- Ensure app has Direct Messages permission + +#### 2. Database Connection Error + +**Solution**: +- Check PostgreSQL is running +- Verify connection string +- Ensure database exists: `createdb mkt_x_service` + +#### 3. Webhook Events Not Received + +**Solution**: +- Verify webhook is registered in Twitter +- Check HTTPS certificate is valid +- Ensure firewall allows inbound traffic +- Review webhook signature validation + +**Details**: See [TWITTER_SETUP.md](docs/TWITTER_SETUP.md) + +--- + +## Performance / Hiệu Năng + +### Targets + +| Metric | Target | +|--------|--------| +| API Response (P95) | < 500ms | +| Message Processing | 100 msg/sec | +| Campaign Throughput | 10,000 contacts/min | +| Database Query (P95) | < 100ms | + +### Caching + +``` +Contact Profiles: 1 hour TTL +Templates: 10 minutes TTL +Segments: 5 minutes TTL +``` + +--- + +## Security / Bảo Mật + +- ✅ OAuth tokens encrypted at rest +- ✅ JWT authentication for API +- ✅ RBAC for merchant isolation +- ✅ Input validation with FluentValidation +- ✅ GDPR compliance (data retention, deletion) + +--- + +## Contributing / Đóng Góp + +See [GoodGo Contributing Guide](../../docs/CONTRIBUTING.md) + +--- + +## Support / Hỗ Trợ + +- **Documentation Issues**: Open issue on GitHub +- **API Support**: api-support@goodgo.com +- **Twitter Integration**: See [TWITTER_SETUP.md](docs/TWITTER_SETUP.md) + +--- + +## License / Giấy Phép + +MIT License - See LICENSE file for details + +--- + +## Related Services / Dịch Vụ Liên Quan + +- [MKT Facebook Service](../mkt-facebook-service-net) - Facebook Messenger marketing +- [MKT Zalo Service](../mkt-zalo-service-net) - Zalo OA marketing +- [MKT WhatsApp Service](../mkt-whatsapp-service-net) - WhatsApp Business marketing + +--- + +## Technology Stack / Công Nghệ + +| Component | Technology | Version | +|-----------|-----------|---------| +| Runtime | .NET | 8.0+ | +| Framework | ASP.NET Core | 8.0+ | +| ORM | Entity Framework Core | 8.0+ | +| Database | PostgreSQL | 15+ | +| Cache | Redis | 7+ | +| Message Broker | RabbitMQ | 3.12+ | +| Mediator | MediatR | 12+ | +| API Gateway | Traefik | 2.10+ | +| Monitoring | Prometheus + Grafana | - | + +--- + +##References / Tham Khảo + +- [Twitter API v2 Documentation](https://developer.twitter.com/en/docs/twitter-api) +- [OpenAI API Documentation](https://platform.openai.com/docs) +- [Clean Architecture](https://docs.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/common-web-application-architectures) +- [Domain-Driven Design](https://domainlanguage.com/ddd/) diff --git a/services/mkt-x-service-net/docs/API.md b/services/mkt-x-service-net/docs/API.md new file mode 100644 index 00000000..7b4ceb9c --- /dev/null +++ b/services/mkt-x-service-net/docs/API.md @@ -0,0 +1,1728 @@ +# X/Twitter Marketing Service - API Documentation + +## Table of Contents + +1. [API Overview](#api-overview) +2. [Authentication](#authentication) +3. [Account Management](#account-management) +4. [Contact Management](#contact-management) +5. [Conversation Management](#conversation-management) +6. [Template Management](#template-management) +7. [Campaign Management](#campaign-management) +8. [Segment Management](#segment-management) +9. [Automation Flows](#automation-flows) +10. [AI Chatbot](#ai-chatbot) +11. [Analytics](#analytics) +12. [Webhooks](#webhooks) +13. [Error Handling](#error-handling) + +--- + +## API Overview + +### Base URL + +``` +Development: http://localhost:5000/api/v1/mkt-x +Production: https://api.goodgo.com/api/v1/mkt-x +``` + +### Versioning + +API versioning is handled through the URL path (`/api/v1/`). + +### Request Format + +All requests with body should use: +``` +Content-Type: application/json +``` + +### Response Format + +All responses follow this structure: + +**Success Response** +```json +{ + "success": true, + "data": { ... }, + "pagination": { + "page": 1, + "limit": 20, + "total": 100, + "totalPages": 5 + } +} +``` + +**Error Response** +```json +{ + "success": false, + "error": "Error message description" +} +``` + +--- + +## Authentication + +### JWT Bearer Token + +All API endpoints (except webhooks) require authentication via JWT bearer token. + +**Request Header** +``` +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +### Obtaining Token + +Tokens are obtained from the IAM service: + +```bash +POST /api/v1/auth/login +Content-Type: application/json + +{ + "email": "user@example.com", + "password": "password" +} +``` + +**Response** +```json +{ + "success": true, + "data": { + "accessToken": "eyJhbGci...", + "refreshToken": "refresh...", + "expiresIn": 3600 + } +} +``` + +--- + +## Account Management + +### Connect Twitter Account + +Connect a Twitter account using OAuth 1.0a credentials. + +**Endpoint** +``` +POST /accounts +``` + +**Request Body** +```json +{ + "oauthToken": "oauth_token_from_twitter", + "oauthTokenSecret": "oauth_token_secret_from_twitter" +} +``` + +**Response** `200 OK` +```json +{ + "success": true, + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "merchantId": "merchant-uuid", + "twitterUserId": "123456789", + "username": "goodgo_shop", + "displayName": "GoodGo Official", + "status": "active", + "connectedAt": "2026-01-18T10:00:00Z" + } +} +``` + +**Error Codes** +- `400` - Invalid OAuth credentials +- `401` - Unauthorized +- `409` - Account already connected + +--- + +### List Connected Accounts + +Get all Twitter accounts connected by the merchant. + +**Endpoint** +``` +GET /accounts +``` + +**Query Parameters** +- `status` (optional) - Filter by status: `active`, `inactive`, `error` + +**Response** `200 OK` +```json +{ + "success": true, + "data": [ + { + "id": "uuid", + "merchantId": "uuid", + "twitterUserId": "123456789", + "username": "goodgo_shop", + "displayName": "GoodGo Official", + "status": "active", + "connectedAt": "2026-01-18T10:00:00Z" + } + ] +} +``` + +--- + +### Get Account Details + +Get detailed information about a specific Twitter account. + +**Endpoint** +``` +GET /accounts/{accountId} +``` + +**Response** `200 OK` +```json +{ + "success": true, + "data": { + "id": "uuid", + "merchantId": "uuid", + "twitterUserId": "123456789", + "username": "goodgo_shop", + "displayName": "GoodGo Official", + "profileImageUrl": "https://pbs.twimg.com/profile_images/...", + "status": "active", + "webhookId": "webhook-id", + "connectedAt": "2026-01-18T10:00:00Z", + "statistics": { + "totalContacts": 1234, + "totalConversations": 567, + "messagesThisMonth": 890 + } + } +} +``` + +**Error Codes** +- `404` - Account not found + +--- + +### Disconnect Account + +Disconnect a Twitter account and revoke OAuth tokens. + +**Endpoint** +``` +DELETE /accounts/{accountId} +``` + +**Response** `200 OK` +```json +{ + "success": true, + "data": null +} +``` + +--- + +### Update Account Settings + +Update account configuration settings. + +**Endpoint** +``` +PUT /accounts/{accountId} +``` + +**Request Body** +```json +{ + "autoReplyEnabled": true, + "businessHours": { + "enabled": true, + "timezone": "Asia/Ho_Chi_Minh", + "schedule": { + "monday": { "start": "09:00", "end": "18:00" }, + "tuesday": { "start": "09:00", "end": "18:00" } + } + } +} +``` + +**Response** `200 OK` + +--- + +## Contact Management + +### List Contacts + +Get paginated list of contacts with filtering. + +**Endpoint** +``` +GET /contacts +``` + +**Query Parameters** +- `accountId` (optional) - Filter by Twitter account +- `tags` (optional) - Comma-separated tags: `vip,customer` +- `search` (optional) - Search in username/display name +- `skip` (optional, default: 0) - Pagination offset +- `take` (optional, default: 20, max: 100) - Items per page + +**Response** `200 OK` +```json +{ + "success": true, + "data": [ + { + "id": "uuid", + "accountId": "uuid", + "twitterUserId": "987654321", + "username": "customer_john", + "displayName": "John Doe", + "profileImageUrl": "https://...", + "tags": ["vip", "customer"], + "attributes": { + "purchaseCount": 5, + "totalSpent": 1250000, + "lastPurchaseDate": "2026-01-15" + }, + "conversationCount": 3, + "firstInteractionAt": "2025-12-01T10:00:00Z", + "lastInteractionAt": "2026-01-18T09:30:00Z" + } + ], + "pagination": { + "page": 1, + "limit": 20, + "total": 1234, + "totalPages": 62 + } +} +``` + +--- + +### Get Contact Details + +Get detailed information about a specific contact. + +**Endpoint** +``` +GET /contacts/{contactId} +``` + +**Response** `200 OK` +```json +{ + "success": true, + "data": { + "id": "uuid", + "accountId": "uuid", + "twitterUserId": "987654321", + "username": "customer_john", + "displayName": "John Doe", + "profileImageUrl": "https://...", + "tags": ["vip", "customer"], + "attributes": { + "purchaseCount": 5, + "totalSpent": 1250000, + "lastPurchaseDate": "2026-01-15", + "preferredLanguage": "vi" + }, + "source": "inbound_message", + "conversationCount": 3, + "firstInteractionAt": "2025-12-01T10:00:00Z", + "lastInteractionAt": "2026-01-18T09:30:00Z", + "engagement": { + "messagesSent": 15, + "messagesReceived": 18, + "averageResponseTime": "5m 30s" + } + } +} +``` + +--- + +### Update Contact + +Update contact information. + +**Endpoint** +``` +PUT /contacts/{contactId} +``` + +**Request Body** +```json +{ + "displayName": "John Doe (VIP)", + "attributes": { + "preferredLanguage": "en", + "notes": "Premium customer" + } +} +``` + +**Response** `200 OK` + +--- + +### Add Tags to Contact + +Add one or more tags to a contact. + +**Endpoint** +``` +POST /contacts/{contactId}/tags +``` + +**Request Body** +```json +{ + "tags": ["vip", "premium"] +} +``` + +**Response** `200 OK` + +--- + +### Remove Tag from Contact + +Remove a specific tag from a contact. + +**Endpoint** +``` +DELETE /contacts/{contactId}/tags/{tagName} +``` + +**Response** `200 OK` + +--- + +### Update Contact Attributes + +Bulk update custom attributes for a contact. + +**Endpoint** +``` +PUT /contacts/{contactId}/attributes +``` + +**Request Body** +```json +{ + "attributes": { + "purchaseCount": 6, + "totalSpent": 1500000, + "lastPurchaseDate": "2026-01-18", + "membershipTier": "gold" + } +} +``` + +**Response** `200 OK` + +--- + +### Get Contact Conversations + +Get all conversations for a specific contact. + +**Endpoint** +``` +GET /contacts/{contactId}/conversations +``` + +**Query Parameters** +- `status` (optional) - Filter by status: `open`, `closed` +- `skip` (optional) - Pagination offset +- `take` (optional) - Items per page + +**Response** `200 OK` +```json +{ + "success": true, + "data": [ + { + "id": "uuid", + "contactId": "uuid", + "status": "open", + "messageCount": 5, + "startedAt": "2026-01-18T09:00:00Z", + "lastMessageAt": "2026-01-18T09:30:00Z" + } + ] +} +``` + +--- + +### Delete Contact + +Delete a contact and all associated data (GDPR compliance). + +**Endpoint** +``` +DELETE /contacts/{contactId} +``` + +**Response** `200 OK` + +--- + +## Conversation Management + +### List Conversations + +Get paginated list of conversations. + +**Endpoint** +``` +GET /conversations +``` + +**Query Parameters** +- `accountId` (optional) - Filter by account +- `status` (optional) - Filter by status: `open`, `closed` +- `assignedTo` (optional) - Filter by assigned user ID +- `skip` (optional) - Pagination offset +- `take` (optional) - Items per page + +**Response** `200 OK` +```json +{ + "success": true, + "data": [ + { + "id": "uuid", + "contactId": "uuid", + "accountId": "uuid", + "status": "open", + "channel": "direct_message", + "assignedToUserId": "uuid", + "messageCount": 12, + "startedAt": "2026-01-18T09:00:00Z", + "lastMessageAt": "2026-01-18T10:15:00Z", + "contact": { + "username": "customer_john", + "displayName": "John Doe" + } + } + ], + "pagination": { ... } +} +``` + +--- + +### Get Conversation with Messages + +Get conversation details including all messages. + +**Endpoint** +``` +GET /conversations/{conversationId} +``` + +**Query Parameters** +- `includeMessages` (optional, default: true) - Include message history + +**Response** `200 OK` +```json +{ + "success": true, + "data": { + "id": "uuid", + "contactId": "uuid", + "accountId": "uuid", + "status": "open", + "channel": "direct_message", + "assignedToUserId": "uuid", + "startedAt": "2026-01-18T09:00:00Z", + "messages": [ + { + "id": "uuid", + "conversationId": "uuid", + "direction": "inbound", + "type": "text", + "content": "Hello, I have a question about my order", + "attachments": [], + "isFromBot": false, + "sentAt": "2026-01-18T09:00:00Z" + }, + { + "id": "uuid", + "conversationId": "uuid", + "direction": "outbound", + "type": "text", + "content": "Hi! I'd be happy to help. What's your order number?", + "attachments": [], + "isFromBot": false, + "sentAt": "2026-01-18T09:02:00Z" + } + ] + } +} +``` + +--- + +### Send Message + +Send a message in a conversation. + +**Endpoint** +``` +POST /conversations/{conversationId}/messages +``` + +**Request Body** +```json +{ + "content": "Your order #12345 has been shipped!", + "type": "text", + "attachments": [ + { + "type": "image", + "url": "https://example.com/tracking.png" + } + ] +} +``` + +**Response** `200 OK` +```json +{ + "success": true, + "data": { + "id": "uuid", + "conversationId": "uuid", + "twitterMessageId": "123456789", + "direction": "outbound", + "type": "text", + "content": "Your order #12345 has been shipped!", + "sentAt": "2026-01-18T10:30:00Z" + } +} +``` + +**Error Codes** +- `400` - Message content exceeds Twitter limits (10,000 chars) +- `429` - Rate limit exceeded + +--- + +### Close Conversation + +Close an active conversation. + +**Endpoint** +``` +PUT /conversations/{conversationId}/close +``` + +**Request Body** (optional) +```json +{ + "reason": "resolved" +} +``` + +**Response** `200 OK` + +--- + +### Assign Conversation + +Assign conversation to a specific user/agent. + +**Endpoint** +``` +POST /conversations/{conversationId}/assign +``` + +**Request Body** +```json +{ + "userId": "user-uuid" +} +``` + +**Response** `200 OK` + +--- + +## Template Management + +### Create Template + +Create a new message template. + +**Endpoint** +``` +POST /templates +``` + +**Request Body** +```json +{ + "name": "Welcome Message", + "type": "text", + "content": "Hi {{name}}, welcome to {{shop_name}}! Use code {{discount_code}} for 10% off your first order.", + "variables": ["name", "shop_name", "discount_code"] +} +``` + +**Response** `200 OK` +```json +{ + "success": true, + "data": { + "id": "uuid", + "merchantId": "uuid", + "name": "Welcome Message", + "type": "text", + "content": "Hi {{name}}, welcome to...", + "variables": ["name", "shop_name", "discount_code"], + "createdAt": "2026-01-18T10:00:00Z" + } +} +``` + +--- + +### List Templates + +Get all templates for the merchant. + +**Endpoint** +``` +GET /templates +``` + +**Query Parameters** +- `type` (optional) - Filter by type: `text`, `quick_reply`, `card` +- `search` (optional) - Search in template name + +**Response** `200 OK` + +--- + +### Get Template + +Get template details. + +**Endpoint** +``` +GET /templates/{templateId} +``` + +**Response** `200 OK` + +--- + +### Update Template + +Update existing template. + +**Endpoint** +``` +PUT /templates/{templateId} +``` + +**Request Body** +```json +{ + "name": "Updated Welcome Message", + "content": "Hello {{name}}!..." +} +``` + +**Response** `200 OK` + +--- + +### Delete Template + +Delete a template. + +**Endpoint** +``` +DELETE /templates/{templateId} +``` + +**Response** `200 OK` + +**Error Codes** +- `409` - Template is being used by active campaigns + +--- + +### Preview Template + +Preview rendered template with sample data. + +**Endpoint** +``` +POST /templates/{templateId}/preview +``` + +**Request Body** +```json +{ + "variables": { + "name": "John", + "shop_name": "GoodGo Shop", + "discount_code": "WELCOME10" + } +} +``` + +**Response** `200 OK` +```json +{ + "success": true, + "data": { + "rendered": "Hi John, welcome to GoodGo Shop! Use code WELCOME10 for 10% off your first order." + } +} +``` + +--- + +## Campaign Management + +### Create Campaign + +Create a new marketing campaign. + +**Endpoint** +``` +POST /campaigns +``` + +**Request Body** +```json +{ + "name": "January Promotion", + "type": "promotional", + "templateId": "template-uuid", + "segmentIds": ["segment-uuid-1", "segment-uuid-2"], + "schedule": { + "startAt": "2026-01-20T10:00:00Z", + "endAt": null, + "recurrence": null + } +} +``` + +**Response** `200 OK` +```json +{ + "success": true, + "data": { + "id": "uuid", + "merchantId": "uuid", + "name": "January Promotion", + "type": "promotional", + "status": "draft", + "templateId": "uuid", + "segmentIds": ["uuid"], + "schedule": { ... }, + "metrics": { + "totalSent": 0, + "delivered": 0, + "opened": 0, + "clicked": 0, + "replied": 0, + "failed": 0 + }, + "createdAt": "2026-01-18T10:00:00Z" + } +} +``` + +--- + +### List Campaigns + +Get all campaigns. + +**Endpoint** +``` +GET /campaigns +``` + +**Query Parameters** +- `status` (optional) - Filter: `draft`, `scheduled`, `running`, `paused`, `completed` +- `type` (optional) - Filter: `promotional`, `transactional`, `engagement` + +**Response** `200 OK` + +--- + +### Get Campaign + +Get campaign details. + +**Endpoint** +``` +GET /campaigns/{campaignId} +``` + +**Response** `200 OK` + +--- + +### Update Campaign + +Update campaign (only for draft/scheduled campaigns). + +**Endpoint** +``` +PUT /campaigns/{campaignId} +``` + +**Request Body** +```json +{ + "name": "Updated Campaign Name", + "schedule": { + "startAt": "2026-01-21T10:00:00Z" + } +} +``` + +**Response** `200 OK` + +**Error Codes** +- `400` - Cannot update running/completed campaigns + +--- + +### Start Campaign + +Start campaign execution. + +**Endpoint** +``` +POST /campaigns/{campaignId}/start +``` + +**Response** `200 OK` + +**Error Codes** +- `400` - Campaign has no segments or invalid template + +--- + +### Pause Campaign + +Pause a running campaign. + +**Endpoint** +``` +POST /campaigns/{campaignId}/pause +``` + +**Response** `200 OK` + +--- + +### Resume Campaign + +Resume a paused campaign. + +**Endpoint** +``` +POST /campaigns/{campaignId}/resume +``` + +**Response** `200 OK` + +--- + +### Get Campaign Metrics + +Get detailed campaign performance metrics. + +**Endpoint** +``` +GET /campaigns/{campaignId}/metrics +``` + +**Response** `200 OK` +```json +{ + "success": true, + "data": { + "totalSent": 1500, + "delivered": 1450, + "opened": 800, + "clicked": 250, + "replied": 45, + "failed": 50, + "openRate": 0.55, + "clickRate": 0.17, + "replyRate": 0.03, + "deliveryRate": 0.97, + "timeline": [ + { + "timestamp": "2026-01-20T10:00:00Z", + "sent": 500, + "delivered": 485 + } + ] + } +} +``` + +--- + +### Send Test Campaign + +Send test message to specific contacts. + +**Endpoint** +``` +POST /campaigns/{campaignId}/test +``` + +**Request Body** +```json +{ + "contactIds": ["contact-uuid-1", "contact-uuid-2"], + "variables": { + "discount_code": "TEST10" + } +} +``` + +**Response** `200 OK` + +--- + +## Segment Management + +### Create Segment + +Create a customer segment with conditions. + +**Endpoint** +``` +POST /segments +``` + +**Request Body** +```json +{ + "name": "VIP Customers", + "conditions": [ + { + "field": "tags", + "operator": "contains", + "value": "vip" + }, + { + "field": "attributes.purchaseCount", + "operator": "greaterThan", + "value": 5 + }, + { + "field": "lastInteractionAt", + "operator": "after", + "value": "2026-01-01T00:00:00Z" + } + ] +} +``` + +**Response** `200 OK` +```json +{ + "success": true, + "data": { + "id": "uuid", + "merchantId": "uuid", + "name": "VIP Customers", + "conditions": [ ... ], + "contactCount": 0, + "createdAt": "2026-01-18T10:00:00Z" + } +} +``` + +--- + +### List Segments + +Get all segments. + +**Endpoint** +``` +GET /segments +``` + +**Response** `200 OK` + +--- + +### Get Segment + +Get segment details. + +**Endpoint** +``` +GET /segments/{segmentId} +``` + +**Response** `200 OK` + +--- + +### Update Segment + +Update segment conditions. + +**Endpoint** +``` +PUT /segments/{segmentId} +``` + +**Request Body** +```json +{ + "name": "Updated VIP Customers", + "conditions": [ ... ] +} +``` + +**Response** `200 OK` + +--- + +### Delete Segment + +Delete a segment. + +**Endpoint** +``` +DELETE /segments/{segmentId} +``` + +**Response** `200 OK` + +**Error Codes** +- `409` - Segment is being used by active campaigns + +--- + +### Preview Segment Contacts + +Preview contacts that match segment conditions. + +**Endpoint** +``` +POST /segments/{segmentId}/preview +``` + +**Query Parameters** +- `limit` (optional, default: 10, max: 50) - Number of contacts to preview + +**Response** `200 OK` +```json +{ + "success": true, + "data": { + "totalMatches": 234, + "preview": [ + { + "id": "uuid", + "username": "customer_john", + "displayName": "John Doe", + "tags": ["vip"], + "attributes": { + "purchaseCount": 8 + } + } + ] + } +} +``` + +--- + +## Automation Flows + +### Create Automation Flow + +Create a new automation workflow. + +**Endpoint** +``` +POST /automation/flows +``` + +**Request Body** +```json +{ + "name": "Welcome Flow", + "trigger": { + "type": "new_follower", + "config": {} + }, + "nodes": [ + { + "id": "node-1", + "type": "send_message", + "config": { + "templateId": "template-uuid", + "delay": 0 + } + }, + { + "id": "node-2", + "type": "wait", + "config": { + "duration": 86400 + } + }, + { + "id": "node-3", + "type": "send_message", + "config": { + "templateId": "template-uuid-2", + "delay": 0 + } + } + ], + "connections": [ + { + "fromNodeId": "node-1", + "toNodeId": "node-2" + }, + { + "fromNodeId": "node-2", + "toNodeId": "node-3" + } + ] +} +``` + +**Response** `200 OK` + +--- + +### List Automation Flows + +Get all automation flows. + +**Endpoint** +``` +GET /automation/flows +``` + +**Query Parameters** +- `status` (optional) - Filter: `active`, `inactive`, `draft` + +**Response** `200 OK` + +--- + +### Get Automation Flow + +Get flow details. + +**Endpoint** +``` +GET /automation/flows/{flowId} +``` + +**Response** `200 OK` + +--- + +### Update Automation Flow + +Update flow configuration. + +**Endpoint** +``` +PUT /automation/flows/{flowId} +``` + +**Request Body** +```json +{ + "name": "Updated Welcome Flow", + "nodes": [ ... ], + "connections": [ ... ] +} +``` + +**Response** `200 OK` + +**Error Codes** +- `400` - Cannot update active flows (deactivate first) + +--- + +### Activate Flow + +Activate an automation flow. + +**Endpoint** +``` +POST /automation/flows/{flowId}/activate +``` + +**Response** `200 OK` + +--- + +### Deactivate Flow + +Deactivate a running flow. + +**Endpoint** +``` +POST /automation/flows/{flowId}/deactivate +``` + +**Response** `200 OK` + +--- + +### Delete Flow + +Delete an automation flow. + +**Endpoint** +``` +DELETE /automation/flows/{flowId} +``` + +**Response** `200 OK` + +--- + +### Get Flow Executions + +Get execution history for a flow. + +**Endpoint** +``` +GET /automation/flows/{flowId}/executions +``` + +**Query Parameters** +- `status` (optional) - Filter: `running`, `completed`, `failed` +- `skip`, `take` - Pagination + +**Response** `200 OK` +```json +{ + "success": true, + "data": [ + { + "id": "uuid", + "flowId": "uuid", + "contactId": "uuid", + "status": "completed", + "currentNodeId": null, + "startedAt": "2026-01-18T09:00:00Z", + "completedAt": "2026-01-19T09:00:00Z" + } + ] +} +``` + +--- + +## AI Chatbot + +### Send Message to AI + +Send a message to AI chatbot for processing. + +**Endpoint** +``` +POST /ai/conversations/{conversationId}/message +``` + +**Request Body** +```json +{ + "message": "What's the status of my order #12345?" +} +``` + +**Response** `200 OK` +```json +{ + "success": true, + "data": { + "intent": "order_status_query", + "confidence": 0.95, + "response": "Let me check that for you. Order #12345 was shipped on January 15 and is expected to arrive on January 20.", + "slots": { + "orderId": "12345" + }, + "requiresEscalation": false + } +} +``` + +--- + +### Get Conversation Context + +Get AI conversation context. + +**Endpoint** +``` +GET /ai/conversations/{conversationId}/context +``` + +**Response** `200 OK` +```json +{ + "success": true, + "data": { + "sessionId": "uuid", + "context": [ + { + "role": "user", + "content": "What's the status of my order?" + }, + { + "role": "assistant", + "content": "I'd be happy to help! What's your order number?" + } + ], + "currentIntent": "order_status_query", + "slots": { + "orderId": "12345" + } + } +} +``` + +--- + +### Escalate to Human + +Escalate AI conversation to human agent. + +**Endpoint** +``` +POST /ai/conversations/{conversationId}/escalate +``` + +**Request Body** +```json +{ + "reason": "complex_query" +} +``` + +**Response** `200 OK` + +--- + +### Update AI Settings + +Update AI chatbot settings for the merchant. + +**Endpoint** +``` +PUT /ai/settings +``` + +**Request Body** +```json +{ + "enabled": true, + "model": "gpt-4", + "temperature": 0.7, + "maxTokens": 500, + "autoEscalationThreshold": 0.6, + "systemPrompt": "You are a helpful customer service assistant for GoodGo Shop..." +} +``` + +**Response** `200 OK` + +--- + +## Analytics + +### Get Overview Analytics + +Get dashboard overview analytics. + +**Endpoint** +``` +GET /analytics/overview +``` + +**Query Parameters** +- `startDate` (required) - ISO 8601 date +- `endDate` (required) - ISO 8601 date +- `accountId` (optional) - Filter by account + +**Response** `200 OK` +```json +{ + "success": true, + "data": { + "period": { + "startDate": "2026-01-01T00:00:00Z", + "endDate": "2026-01-18T23:59:59Z" + }, + "contacts": { + "total": 1234, + "new": 156, + "active": 456 + }, + "conversations": { + "total": 567, + "open": 45, + "closed": 522, + "averageResponseTime": "5m 30s" + }, + "campaigns": { + "active": 3, + "completed": 12, + "totalMessagesSent": 15000 + }, + "automation": { + "activeFlows": 5, + "totalExecutions": 890 + } + } +} +``` + +--- + +### Get Contact Analytics + +Get contact-related analytics. + +**Endpoint** +``` +GET /analytics/contacts +``` + +**Query Parameters** +- `startDate`, `endDate` - Date range +- `groupBy` (optional) - Group by: `day`, `week`, `month` + +**Response** `200 OK` + +--- + +### Get Conversation Analytics + +Get conversation analytics. + +**Endpoint** +``` +GET /analytics/conversations +``` + +**Response** `200 OK` + +--- + +### Get Campaign Analytics + +Get campaign performance analytics. + +**Endpoint** +``` +GET /analytics/campaigns +``` + +**Query Parameters** +- `campaignId` (optional) - Specific campaign +- `startDate`, `endDate` - Date range + +**Response** `200 OK` + +--- + +### Get Automation Analytics + +Get automation flow analytics. + +**Endpoint** +``` +GET /analytics/automation +``` + +**Response** `200 OK** + +--- + +## Webhooks + +### Receive Twitter Webhook Events + +Endpoint for receiving Twitter webhook events (Account Activity API). + +**Endpoint** +``` +POST /webhooks/twitter +``` + +**Headers** +``` +X-Twitter-Webhooks-Signature: sha256=... +``` + +**Request Body** (example: Direct Message Event) +```json +{ + "direct_message_events": [ + { + "id": "123456789", + "created_timestamp": "1642000000000", + "message_create": { + "sender_id": "987654321", + "target": { + "recipient_id": "123456789" + }, + "message_data": { + "text": "Hello!", + "entities": {} + } + } + } + ], + "users": { + "987654321": { + "id": "987654321", + "screen_name": "customer_john", + "name": "John Doe" + } + } +} +``` + +**Response** `200 OK` + +**Note**: This endpoint validates the Twitter signature for security. + +--- + +### Twitter CRC Verification + +Twitter Challenge-Response Check for webhook verification. + +**Endpoint** +``` +GET /webhooks/verify +``` + +**Query Parameters** +- `crc_token` - Token from Twitter + +**Response** `200 OK` +```json +{ + "response_token": "sha256=base64_encoded_hmac" +} +``` + +--- + +## Error Handling + +### HTTP Status Codes + +| Code | Meaning | Description | +|------|---------|-------------| +| 200 | OK | Request successful | +| 201 | Created | Resource created | +| 400 | Bad Request | Invalid request parameters | +| 401 | Unauthorized | Missing or invalid auth token | +| 403 | Forbidden | Insufficient permissions | +| 404 | Not Found | Resource not found | +| 409 | Conflict | Resource already exists or conflict | +| 422 | Unprocessable Entity | Validation failed | +| 429 | Too Many Requests | Rate limit exceeded | +| 500 | Internal Server Error | Server error | +| 503 | Service Unavailable | Service temporarily unavailable | + +### Error Response Format + +```json +{ + "success": false, + "error": "Detailed error message", + "code": "ERROR_CODE", + "details": { + "field": "templateId", + "reason": "Template not found" + } +} +``` + +### Common Error Codes + +| Code | Description | +|------|-------------| +| `VALIDATION_ERROR` | Request validation failed | +| `UNAUTHORIZED` | Authentication required | +| `FORBIDDEN` | Insufficient permissions | +| `RESOURCE_NOT_FOUND` | Requested resource not found | +| `DUPLICATE_RESOURCE` | Resource already exists | +| `RATE_LIMIT_EXCEEDED` | Too many requests | +| `TWITTER_API_ERROR` | Twitter API error | +| `AI_SERVICE_ERROR` | AI service error | + +### Rate Limiting + +**Headers** +``` +X-RateLimit-Limit: 100 +X-RateLimit-Remaining: 95 +X-RateLimit-Reset: 1642000000 +``` + +**Limits** +- API calls: 100 requests/minute per merchant +- Campaigns: 10,000 messages/day per account +- Messages: 500 messages/24 hours per Twitter account (Twitter limit) + +--- + +## Postman Collection + +Download the complete Postman collection for testing: +``` +https://api.goodgo.com/api/v1/mkt-x/postman-collection.json +``` + +--- + +## Support + +For API support, contact: api-support@goodgo.com diff --git a/services/mkt-x-service-net/docs/ARCHITECTURE.md b/services/mkt-x-service-net/docs/ARCHITECTURE.md new file mode 100644 index 00000000..21869399 --- /dev/null +++ b/services/mkt-x-service-net/docs/ARCHITECTURE.md @@ -0,0 +1,807 @@ +# X/Twitter Marketing Service - Architecture Documentation + +## Table of Contents + +1. [Overview](#overview) +2. [System Architecture](#system-architecture) +3. [Domain Model](#domain-model) +4. [Component Design](#component-design) +5. [Data Architecture](#data-architecture) +6. [Integration Architecture](#integration-architecture) +7. [Security Architecture](#security-architecture) +8. [Deployment Architecture](#deployment-architecture) + +--- + +## Overview + +### Service Purpose + +The X/Twitter Marketing Service (`mkt-x-service-net`) is a comprehensive social media marketing platform built on .NET 8, providing three core capabilities: + +1. **CHATBOT Automation Messenger** - Template-based automated messaging with workflow orchestration +2. **CHATBOT AI Messenger** - AI-powered conversational interface using OpenAI integration +3. **Customer Management** - Complete CRM for Twitter contacts with segmentation and analytics + +### Key Features + +- ✅ Multi-account Twitter integration with OAuth 1.0a +- ✅ Visual workflow designer for message automation +- ✅ AI-powered natural language conversations +- ✅ Advanced customer segmentation +- ✅ Campaign management with A/B testing +- ✅ Real-time analytics and reporting +- ✅ Webhook-based event processing +- ✅ Rate limiting and quota management + +--- + +## System Architecture + +### High-Level Architecture + +``` +┌─────────────────────────────────────────────────────────┐ +│ Load Balancer (Traefik) │ +└─────────────┬───────────────────────────┬───────────────┘ + │ │ + ┌─────────▼─────────┐ ┌────────▼────────┐ + │ API Instance 1 │ │ API Instance 2 │ + │ (Web API + Jobs) │ │ (Web API + Jobs) │ + └─────────┬─────────┘ └────────┬────────┘ + │ │ + └──────────┬────────────────┘ + │ + ┌────────────────┼────────────────┐ + │ │ │ + ┌─────▼─────┐ ┌────▼────┐ ┌─────▼─────┐ + │PostgreSQL │ │ Redis │ │ RabbitMQ │ + │(Primary) │ │ (Cache) │ │(Event Bus)│ + └───────────┘ └──────────┘ └───────────┘ + │ + ┌─────▼─────────────┐ + │ External Services │ + │ - Twitter API │ + │ - OpenAI API │ + └───────────────────┘ +``` + +### Clean Architecture Layers + +``` +┌──────────────────────────────────────────────┐ +│ API Layer (Presentation) │ +│ - Controllers │ +│ - Middleware (Auth, Exception, Logging) │ +│ - Swagger/OpenAPI │ +└──────────────────┬───────────────────────────┘ + │ +┌──────────────────▼───────────────────────────┐ +│ Application Layer (Use Cases) │ +│ - Commands (MediatR) │ +│ - Queries (MediatR) │ +│ - DTOs │ +│ - Validators (FluentValidation) │ +│ - Pipeline Behaviors │ +└──────────────────┬───────────────────────────┘ + │ +┌──────────────────▼───────────────────────────┐ +│ Domain Layer (Business Logic) │ +│ - Aggregates (TwitterAccount, Contact...) │ +│ - Entities │ +│ - Value Objects │ +│ - Domain Events │ +│ - Domain Services │ +└──────────────────┬───────────────────────────┘ + │ +┌──────────────────▼───────────────────────────┐ +│ Infrastructure Layer (External Concerns) │ +│ - EF Core DbContext │ +│ - Repositories │ +│ - External API Clients (Twitter, OpenAI) │ +│ - Background Jobs │ +│ - Event Bus Integration │ +└──────────────────────────────────────────────┘ +``` + +--- + +## Domain Model + +### Aggregate Roots + +#### 1. TwitterAccount Aggregate + +**Purpose**: Manages connected Twitter accounts with OAuth credentials + +```csharp +public class TwitterAccount : Entity, IAggregateRoot +{ + public Guid MerchantId { get; private set; } + public string TwitterUserId { get; private set; } + public string Username { get; private set; } + public TwitterAccountStatus Status { get; private set; } + + public void ConnectAccount(string oauthToken, string oauthSecret); + public void Disconnect(); + public void UpdateCredentials(string token, string secret); +} +``` + +**Business Rules**: +- One merchant can have multiple Twitter accounts +- OAuth tokens must be encrypted at rest +- Account must pass Twitter verification before activation + +#### 2. Contact Aggregate + +**Purpose**: Represents Twitter users who interact with merchant accounts + +```csharp +public class Contact : Entity, IAggregateRoot +{ + public Guid AccountId { get; private set; } + public string TwitterUserId { get; private set; } + public List Tags { get; private set; } + public Dictionary Attributes { get; private set; } + + public void AddTag(string tagName); + public void RemoveTag(string tagName); + public void UpdateAttribute(string key, object value); +} +``` + +**Business Rules**: +- Each Twitter user is unique per merchant account +- Tags must be unique per contact +- Custom attributes support flexible data types (string, number, boolean, date) + +#### 3. Conversation Aggregate + +**Purpose**: Manages message threads between contacts and merchants + +```csharp +public class Conversation : Entity, IAggregateRoot +{ + public Guid ContactId { get; private set; } + public Guid AccountId { get; private set; } + public ConversationStatus Status { get; private set; } + public List Messages { get; private set; } + + public void AddMessage(Message message); + public void Close(); + public void AssignToAgent(Guid userId); +} +``` + +**Business Rules**: +- Conversations auto-close after 24 hours of inactivity +- Messages cannot be deleted, only archived +- Bot messages are clearly marked + +#### 4. Template Aggregate + +**Purpose**: Reusable message templates with variable substitution + +```csharp +public class Template : Entity, IAggregateRoot +{ + public Guid MerchantId { get; private set; } + public string Name { get; private set; } + public string Content { get; private set; } + public List Variables { get; private set; } + + public string Render(Dictionary values); + public void Validate(); +} +``` + +**Business Rules**: +- Template content must not exceed Twitter DM limits (10,000 chars) +- Variables use {{variable_name}} syntax +- All declared variables must be provided during rendering + +#### 5. Campaign Aggregate + +**Purpose**: Orchestrates bulk messaging campaigns with scheduling + +```csharp +public class Campaign : Entity, IAggregateRoot +{ + public Guid MerchantId { get; private set; } + public Guid TemplateId { get; private set; } + public List SegmentIds { get; private set; } + public Schedule Schedule { get; private set; } + public CampaignMetrics Metrics { get; private set; } + + public void Start(); + public void Pause(); + public void Resume(); + public void Complete(); +} +``` + +**Business Rules**: +- Campaign cannot start without at least one segment +- Respects Twitter rate limits (500 DMs/24 hours) +- Cannot modify campaign after it has started +- Scheduled campaigns auto-execute at specified time + +#### 6. Segment Aggregate + +**Purpose**: Dynamic customer segmentation with condition-based filtering + +```csharp +public class Segment : Entity, IAggregateRoot +{ + public Guid MerchantId { get; private set; } + public string Name { get; private set; } + public List Conditions { get; private set; } + public int ContactCount { get; private set; } + + public void AddCondition(SegmentCondition condition); + public void RemoveCondition(Guid conditionId); + public List Evaluate(); +} +``` + +**Business Rules**: +- Conditions are evaluated with AND logic +- Contact count is cached and refreshed periodically +- Supports filters: tags, attributes, engagement level, date ranges + +#### 7. AutomationFlow Aggregate + +**Purpose**: Visual workflow automation with triggers and actions + +```csharp +public class AutomationFlow : Entity, IAggregateRoot +{ + public Guid MerchantId { get; private set; } + public FlowStatus Status { get; private set; } + public List Nodes { get; private set; } + public List Connections { get; private set; } + public FlowTrigger Trigger { get; private set; } + + public void AddNode(FlowNode node); + public void Connect(Guid fromNodeId, Guid toNodeId); + public void Activate(); + public void Deactivate(); +} +``` + +**Business Rules**: +- Flows must have exactly one trigger node +- No circular connections allowed +- Flow must be validated before activation +- Deactivating a flow stops all running executions + +#### 8. AIConversationSession Aggregate + +**Purpose**: Maintains AI conversation context and state + +```csharp +public class AIConversationSession : Entity, IAggregateRoot +{ + public Guid ConversationId { get; private set; } + public List Context { get; private set; } + public string CurrentIntent { get; private set; } + public Dictionary Slots { get; private set; } + + public void UpdateContext(ContextItem item); + public void ClearContext(); + public void DetectIntent(string message); +} +``` + +**Business Rules**: +- Context limited to last 10 messages for performance +- Session expires after 30 minutes of inactivity +- Auto-escalates to human if confidence < 0.6 + +### Value Objects + +```csharp +// Twitter user information +public record TwitterUserInfo( + string TwitterUserId, + string Username, + string DisplayName, + string ProfileImageUrl); + +// Campaign scheduling +public record Schedule( + DateTime? StartAt, + DateTime? EndAt, + RecurrencePattern? Recurrence); + +// Campaign metrics +public record CampaignMetrics( + int TotalSent, + int Delivered, + int Opened, + int Clicked, + int Replied, + int Failed); + +// Automation trigger +public record FlowTrigger( + TriggerType Type, + Dictionary Config); +``` + +### Domain Events + +```csharp +// Account Events +public record TwitterAccountConnectedEvent(Guid AccountId, Guid MerchantId); +public record TwitterAccountDisconnectedEvent(Guid AccountId); + +// Contact Events +public record ContactCreatedEvent(Guid ContactId, string TwitterUserId); +public record ContactTaggedEvent(Guid ContactId, string TagName); + +// Conversation Events +public record ConversationStartedEvent(Guid ConversationId, Guid ContactId); +public record MessageReceivedEvent(Guid MessageId, string Content); +public record MessageSentEvent(Guid MessageId, bool IsFromBot); + +// Campaign Events +public record CampaignStartedEvent(Guid CampaignId, int TargetCount); +public record CampaignCompletedEvent(Guid CampaignId, CampaignMetrics Metrics); + +// AI Events +public record IntentDetectedEvent(Guid SessionId, string Intent, double Confidence); +public record AIEscalationRequestedEvent(Guid SessionId, string Reason); +``` + +--- + +## Component Design + +### Application Layer Components + +#### Commands (Write Operations) + +**Account Management** +- `ConnectTwitterAccountCommand` - Connect new Twitter account +- `DisconnectAccountCommand` - Disconnect account +- `UpdateAccountSettingsCommand` - Update account configuration + +**Contact Management** +- `CreateContactCommand` - Create new contact +- `UpdateContactCommand` - Update contact details +- `AddContactTagCommand` - Add tag to contact +- `RemoveContactTagCommand` - Remove tag +- `UpdateContactAttributesCommand` - Bulk update attributes + +**Conversation Management** +- `StartConversationCommand` - Start new conversation +- `SendMessageCommand` - Send message in conversation +- `CloseConversationCommand` - Close conversation +- `AssignConversationCommand` - Assign to agent + +**Campaign Management** +- `CreateCampaignCommand` - Create campaign +- `StartCampaignCommand` - Start campaign execution +- `PauseCampaignCommand` - Pause running campaign +- `ResumeCampaignCommand` - Resume paused campaign + +**Automation** +- `CreateAutomationFlowCommand` - Create automation workflow +- `ActivateFlowCommand` - Activate flow +- `DeactivateFlowCommand` - Deactivate flow + +#### Queries (Read Operations) + +**Analytics Queries** +- `GetOverviewAnalyticsQuery` - Dashboard metrics +- `GetContactAnalyticsQuery` - Contact statistics +- `GetConversationAnalyticsQuery` - Conversation metrics +- `GetCampaignAnalyticsQuery` - Campaign performance + +**Data Retrieval** +- `GetContactsQuery` - List contacts with filtering/pagination +- `GetConversationsQuery` - List conversations +- `GetCampaignsQuery` - List campaigns +- `GetSegmentsQuery` - List segments + +### Infrastructure Components + +#### External API Clients + +**TwitterApiClient** +```csharp +public interface ITwitterApiClient +{ + Task GetUserInfoAsync(string userId); + Task SendDirectMessageAsync(string recipientId, string text); + Task SubscribeToWebhooksAsync(string webhookUrl); + Task VerifyCredentialsAsync(string token, string secret); +} +``` + +**AIServiceClient** +```csharp +public interface IAIServiceClient +{ + Task DetectIntentAsync(string message, List context); + Task GenerateResponseAsync(string intent, Dictionary slots); + Task AnalyzeSentimentAsync(string message); +} +``` + +#### Background Jobs + +**CampaignSchedulerJob** +- Runs: Every 1 minute +- Purpose: Check for scheduled campaigns and enqueue execution +- Concurrency: Single instance with distributed lock + +**MessageProcessorJob** +- Runs: Continuously with polling +- Purpose: Process outbound message queue +- Rate Limiting: Respects Twitter limits (500/24h per account) + +**WebhookEventProcessorJob** +- Runs: Continuously with polling +- Purpose: Process incoming Twitter webhook events +- Creates: Contacts, Conversations, Messages + +--- + +## Data Architecture + +### Database Schema + +#### Core Tables + +**twitter_accounts** +```sql +CREATE TABLE twitter_accounts ( + id UUID PRIMARY KEY, + merchant_id UUID NOT NULL, + twitter_user_id VARCHAR(100) NOT NULL UNIQUE, + username VARCHAR(100) NOT NULL, + display_name VARCHAR(200), + status VARCHAR(20) NOT NULL, + oauth_token TEXT NOT NULL, -- encrypted + oauth_token_secret TEXT NOT NULL, -- encrypted + webhook_id VARCHAR(100), + connected_at TIMESTAMP NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT NOW(), + updated_at TIMESTAMP +); +``` + +**contacts** +```sql +CREATE TABLE contacts ( + id UUID PRIMARY KEY, + account_id UUID NOT NULL REFERENCES twitter_accounts(id), + twitter_user_id VARCHAR(100) NOT NULL, + username VARCHAR(100) NOT NULL, + display_name VARCHAR(200), + profile_image_url TEXT, + source VARCHAR(50) NOT NULL, + attributes JSONB DEFAULT '{}', + first_interaction_at TIMESTAMP NOT NULL, + last_interaction_at TIMESTAMP, + created_at TIMESTAMP NOT NULL DEFAULT NOW(), + updated_at TIMESTAMP, + UNIQUE(account_id, twitter_user_id) +); + +CREATE INDEX idx_contacts_account ON contacts(account_id); +CREATE INDEX idx_contacts_twitter_user ON contacts(twitter_user_id); +CREATE INDEX idx_contacts_attributes ON contacts USING GIN(attributes); +``` + +**conversations** +```sql +CREATE TABLE conversations ( + id UUID PRIMARY KEY, + contact_id UUID NOT NULL REFERENCES contacts(id), + account_id UUID NOT NULL REFERENCES twitter_accounts(id), + status VARCHAR(20) NOT NULL, + channel VARCHAR(20) NOT NULL, + assigned_to_user_id UUID, + started_at TIMESTAMP NOT NULL, + closed_at TIMESTAMP, + created_at TIMESTAMP NOT NULL DEFAULT NOW(), + updated_at TIMESTAMP +); + +CREATE INDEX idx_conversations_contact ON conversations(contact_id); +CREATE INDEX idx_conversations_status ON conversations(status); +``` + +**messages** +```sql +CREATE TABLE messages ( + id UUID PRIMARY KEY, + conversation_id UUID NOT NULL REFERENCES conversations(id), + twitter_message_id VARCHAR(100), + direction VARCHAR(20) NOT NULL, + type VARCHAR(20) NOT NULL, + content TEXT NOT NULL, + attachments JSONB, + is_from_bot BOOLEAN NOT NULL DEFAULT FALSE, + sent_at TIMESTAMP NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT NOW() +); + +CREATE INDEX idx_messages_conversation ON messages(conversation_id); +CREATE INDEX idx_messages_sent_at ON messages(sent_at DESC); +``` + +### Caching Strategy + +**Redis Cache Structure** + +``` +Contact Profiles: "contact:{contactId}" - TTL: 1 hour +Templates: "template:{templateId}" - TTL: 10 minutes +Segments: "segment:{segmentId}:contacts" - TTL: 5 minutes +Campaign Metrics: "campaign:{campaignId}:metrics" - TTL: 1 minute +Rate Limits: "ratelimit:twitter:{accountId}" - TTL: 24 hours +``` + +--- + +## Integration Architecture + +### Twitter API Integration + +#### OAuth 1.0a Flow + +``` +1. Merchant initiates connection +2. Service requests request token from Twitter +3. Redirect merchant to Twitter authorization URL +4. Twitter redirects back with verifier +5. Service exchanges verifier for access token +6. Store encrypted tokens in database +7. Subscribe to webhooks for the account +``` + +#### Webhook Events + +**Supported Events**: +- `direct_message_events` - New DM received +- `direct_message_indicate_typing_events` - User typing +- `direct_message_mark_read_events` - Message read +- `follow_events` - New follower +- `favorite_events` - Tweet liked + +**Event Processing Flow**: +``` +Twitter → Webhook Endpoint → Event Queue → Event Processor → Domain Logic +``` + +### OpenAI Integration + +#### AI Conversation Flow + +``` +1. User sends message +2. Extract conversation context (last 10 messages) +3. Call OpenAI API with context and message +4. Parse intent and entities +5. If intent requires data, call internal services +6. Generate response using OpenAI +7. Send response to user +8. Store conversation context +``` + +#### Error Handling + +- **API Timeout**: Retry up to 3 times with exponential backoff +- **Rate Limit**: Queue request and retry after cooldown +- **Low Confidence**: Auto-escalate to human agent + +### Event Bus Integration + +#### Published Events + +```csharp +public record TwitterContactCreatedEvent( + Guid ContactId, + Guid MerchantId, + string TwitterUserId) : IIntegrationEvent; + +public record TwitterConversationStartedEvent( + Guid ConversationId, + Guid ContactId) : IIntegrationEvent; + +public record TwitterCampaignCompletedEvent( + Guid CampaignId, + CampaignMetrics Metrics) : IIntegrationEvent; +``` + +#### Consumed Events + +```csharp +// From Order Service +public record OrderCreatedEvent(Guid OrderId, string UserId); + +// From Product Service +public record ProductStockChangedEvent(Guid ProductId, int NewStock); +``` + +--- + +## Security Architecture + +### Authentication & Authorization + +**API Authentication** +- JWT Bearer tokens for API access +- OAuth 1.0a for Twitter account connection +- Refresh token rotation + +**Authorization** +- Role-Based Access Control (RBAC) +- Merchant-level data isolation +- Permission checks at API and domain level + +### Data Protection + +**Encryption at Rest** +- OAuth tokens encrypted using AES-256 +- Encryption keys stored in Azure Key Vault / AWS KMS +- Database encryption for sensitive fields + +**Encryption in Transit** +- TLS 1.3 for all HTTP communication +- Certificate pinning for Twitter API calls + +### Input Validation + +- FluentValidation for all commands +- SQL injection prevention via EF Core parameterization +- XSS protection via output encoding +- Rate limiting on all public endpoints + +--- + +## Deployment Architecture + +### Container Configuration + +**Dockerfile** +```dockerfile +FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build +WORKDIR /src +COPY . . +RUN dotnet restore +RUN dotnet publish -c Release -o /app + +FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine +WORKDIR /app +COPY --from=build /app . +RUN adduser -D appuser && chown -R appuser /app +USER appuser +EXPOSE 8080 +ENTRYPOINT ["dotnet", "MktXService.API.dll"] +``` + +### Kubernetes Deployment + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mkt-x-service +spec: + replicas: 3 + template: + spec: + containers: + - name: api + image: mkt-x-service:latest + resources: + requests: + memory: "256Mi" + cpu: "250m" + limits: + memory: "512Mi" + cpu: "500m" + env: + - name: ASPNETCORE_ENVIRONMENT + value: "Production" + livenessProbe: + httpGet: + path: /health + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 10 +``` + +### Horizontal Pod Autoscaling + +```yaml +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: mkt-x-service-hpa +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: mkt-x-service + minReplicas: 2 + maxReplicas: 10 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 70 +``` + +--- + +## Performance Targets + +| Metric | Target | Notes | +|--------|--------|-------| +| API Response Time (P95) | < 500ms | Excluding external API calls | +| Message Processing | 100 msg/sec | Per Twitter account | +| Campaign Throughput | 10,000 contacts/min | With rate limiting | +| Database Query (P95) | < 100ms | Single-table queries | +| Webhook Processing | < 2s | Time to store event | +| Cache Hit Ratio | > 80% | For contact lookups | + +--- + +## Monitoring & Observability + +### Metrics (Prometheus) + +``` +# API Metrics +http_requests_total{method, endpoint, status} +http_request_duration_seconds{method, endpoint} + +# Business Metrics +twitter_messages_sent_total{account_id} +twitter_campaigns_active{merchant_id} +twitter_conversations_active{account_id} + +# Infrastructure Metrics +db_connections_active +redis_cache_hit_ratio +rabbitmq_messages_pending +``` + +### Logging (Structured) + +```json +{ + "timestamp": "2026-01-18T10:00:00Z", + "level": "Information", + "message": "Campaign started", + "properties": { + "campaignId": "uuid", + "merchantId": "uuid", + "targetContactCount": 1000 + } +} +``` + +### Distributed Tracing + +- OpenTelemetry integration +- Trace all external API calls +- Correlation IDs across microservices + +--- + +## References + +- [Twitter API v2 Documentation](https://developer.twitter.com/en/docs/twitter-api) +- [OpenAI API Documentation](https://platform.openai.com/docs) +- [.NET Microservices Architecture](https://docs.microsoft.com/en-us/dotnet/architecture/microservices/) +- [Domain-Driven Design by Eric Evans](https://domainlanguage.com/ddd/) diff --git a/services/mkt-x-service-net/docs/README.md b/services/mkt-x-service-net/docs/README.md new file mode 100644 index 00000000..05fa9147 --- /dev/null +++ b/services/mkt-x-service-net/docs/README.md @@ -0,0 +1,316 @@ +# MKT X/Twitter Service - Documentation Index +## Tài Liệu Dịch Vụ Twitter Marketing + +--- + +## English Documentation + +### Core Documentation + +| Document | Description | Link | +|----------|-------------|------| +| **README** | Service overview, quick start, features | [README.md](../README.md) | +| **Architecture** | System architecture, domain model, components | [ARCHITECTURE.md](ARCHITECTURE.md) | +| **API Reference** | Complete API documentation with examples | [API.md](API.md) | +| **Twitter Setup** | Step-by-step Twitter API integration guide | [TWITTER_SETUP.md](TWITTER_SETUP.md) | + +### Quick Links + +- **Getting Started**: [README.md#quick-start](../README.md#quick-start) +- **API Endpoints**: [API.md#api-overview](API.md#api-overview) +- **Domain Model**: [ARCHITECTURE.md#domain-model](ARCHITECTURE.md#domain-model) +- **Deployment**: [README.md#development](../README.md#development) + +--- + +## Vietnamese Documentation / Tài Liệu Tiếng Việt + +> **Note**: Vietnamese documentation provides the same content in Vietnamese language for easier understanding by Vietnamese-speaking developers. +> +> **Lưu ý**: Tài liệu tiếng Việt cung cấp nội dung tương tự bằng tiếng Việt để dễ hiểu hơn cho lập trình viên Việt Nam. + +### Tài Liệu Chính + +| Tài Liệu | Mô Tả | Link | +|----------|-------|------| +| **README** | Tổng quan dịch vụ, hướng dẫn nhanh | [README-vi.md](vi/README.md) (Coming soon) | +| **Kiến Trúc** | Kiến trúc hệ thống, mô hình domain | [KIEN-TRUC.md](vi/KIEN-TRUC.md) (Coming soon) | +| **Tài Liệu API** | Tài liệu API đầy đủ với ví dụ | [API.md](vi/API.md) (Coming soon) | +| **Thiết Lập Twitter** | Hướng dẫn tích hợp Twitter API | [CAI-DAT-TWITTER.md](vi/CAI-DAT-TWITTER.md) (Coming soon) | + +--- + +## Documentation Structure / Cấu Trúc Tài Liệu + +``` +docs/ +├── README.md # This file / File này +├── ARCHITECTURE.md # EN: System architecture +├── API.md # EN: API reference +├── TWITTER_SETUP.md # EN: Twitter setup guide +└── vi/ # Vietnamese documentation + ├── README.md # VI: Service overview (planned) + ├── KIEN-TRUC.md # VI: Architecture (planned) + ├── API.md # VI: API documentation (planned) + └── CAI-DAT-TWITTER.md # VI: Twitter setup (planned) +``` + +--- + +## Key Concepts / Khái Niệm Chính + +### Service Features / Tính Năng Dịch Vụ + +1. **CHATBOT Automation Messenger** / **CHATBOT Tự Động** + - Template-based messaging / Tin nhắn dựa trên mẫu + - Visual workflow designer / Thiết kế workflow trực quan + - Campaign scheduling / Lịch trình chiến dịch + - A/B testing / Kiểm thử A/B + +2. **CHATBOT AI Messenger** / **CHATBOT AI** + - Natural language understanding / Hiểu ngôn ngữ tự nhiên + - OpenAI integration / Tích hợp OpenAI + - Intent detection / Phát hiện ý định + - Auto escalation / Tự động chuyển tiếp + +3. **Customer Management** / **Quản Lý Khách Hàng** + - Contact database / Cơ sở dữ liệu liên hệ + - Segmentation / Phân khúc + - Analytics / Phân tích + - GDPR compliance / Tuân thủ GDPR + +--- + +## API Overview / Tổng Quan API + +### Base URL + +``` +Development: http://localhost:5000/api/v1/mkt-x +Production: https://api.goodgo.com/api/v1/mkt-x +``` + +### Main Endpoints / Endpoints Chính + +``` +# Account Management / Quản Lý Tài Khoản +POST /accounts # Connect Twitter account / Kết nối tài khoản +GET /accounts # List accounts / Danh sách tài khoản +DELETE /accounts/{id} # Disconnect / Ngắt kết nối + +# Contact Management / Quản Lý Liên Hệ +GET /contacts # List contacts / Danh sách liên hệ +POST /contacts/{id}/tags # Add tags / Thêm nhãn + +# Conversations / Trò Chuyện +GET /conversations # List conversations / Danh sách hội thoại +POST /conversations/{id}/messages # Send message / Gửi tin nhắn + +# Campaigns / Chiến Dịch +POST /campaigns # Create campaign / Tạo chiến dịch +POST /campaigns/{id}/start # Start campaign / Bắt đầu chiến dịch + +# Automation / Tự Động Hóa +POST /automation/flows # Create flow / Tạo workflow +POST /automation/flows/{id}/activate # Activate / Kích hoạt + +# AI Chatbot +POST /ai/conversations/{id}/message # AI chat + +# Analytics / Phân Tích +GET /analytics/overview # Dashboard / Bảng điều khiển +``` + +**Full documentation**: See [API.md](API.md) / Xem [API.md](API.md) + +--- + +## Architecture Highlights / Điểm Nổi Bật Kiến Trúc + +### Clean Architecture / Kiến Trúc Sạch + +``` +API Layer → Controllers, Swagger +Application Layer → CQRS (Commands, Queries), MediatR +Domain Layer → Aggregates, Entities, Domain Events +Infrastructure → EF Core, Repositories, External APIs +``` + +### 9 Aggregate Roots / 9 Aggregate Chính + +1. **TwitterAccount** - Twitter account management +2. **Contact** - Customer profiles +3. **Conversation** - Message threads +4. **Template** - Message templates +5. **Campaign** - Marketing campaigns +6. **Segment** - Customer segments +7. **AutomationFlow** - Workflows +8. **AIConversationSession** - AI context +9. **Attachment** - Media files + +**Details**: See [ARCHITECTURE.md](ARCHITECTURE.md) + +--- + +## Getting Help / Nhận Trợ Giúp + +### For Developers / Dành Cho Lập Trình Viên + +- **Quick Start**: Follow [README.md#quick-start](../README.md#quick-start) +- **API Questions**: See [API.md](API.md) +- **Architecture Questions**: See [ARCHITECTURE.md](ARCHITECTURE.md) +- **Twitter Integration**: See [TWITTER_SETUP.md](TWITTER_SETUP.md) + +### For Issues / Vấn Đề + +1. **Check Documentation**: Search this documentation first +2. **Check Logs**: `docker-compose logs -f mkt-x-service-net` +3. **Health Check**: `curl http://localhost:5000/health` +4. **Contact Support**: api-support@goodgo.com + +--- + +## Development Workflow / Quy Trình Phát Triển + +### 1. Setup / Thiết Lập + +```bash +# Install dependencies / Cài đặt dependencies +dotnet restore + +# Setup database / Thiết lập database +dotnet ef database update --project src/MktXService.Infrastructure +``` + +### 2. Development / Phát Triển + +```bash +# Run locally / Chạy local +dotnet run --project src/MktXService.API + +# Run tests / Chạy tests +dotnet test +``` + +### 3. Deployment / Triển Khai + +```bash +# Build Docker image / Build image +docker-compose build mkt-x-service-net + +# Deploy / Triển khai +docker-compose up -d mkt-x-service-net +``` + +--- + +## External Dependencies / Dependencies Bên Ngoài + +### Required / Bắt Buộc + +- **Twitter API v2** - Direct Messages API, Account Activity API +- **PostgreSQL 15+** - Primary database +- **Redis 7+** - Caching layer +- **RabbitMQ 3.12+** - Message broker + +### Optional / Tùy Chọn + +- **OpenAI API** - For AI chatbot features +- **Prometheus + Grafana** - For monitoring +- **Loki** - For centralized logging + +--- + +## Performance Targets / Mục Tiêu Hiệu Năng + +| Metric / Chỉ Số | Target / Mục Tiêu | Notes / Ghi Chú | +|------------------|-------------------|-----------------| +| API Response (P95) | < 500ms | Excluding external APIs | +| Message Processing | 100 msg/sec | Per account | +| Campaign Throughput | 10,000/min | With rate limiting | +| Database Query (P95) | < 100ms | Single-table queries | +| Cache Hit Ratio | > 80% | Contact lookups | + +--- + +## Security Compliance / Tuân Thủ Bảo Mật + +- ✅ **OAuth 1.0a** for Twitter authentication +- ✅ **JWT tokens** for API authentication +- ✅ **Encrypted** OAuth tokens at rest (AES-256) +- ✅ **RBAC** for merchant isolation +- ✅ **GDPR** compliant (data retention, right to deletion) +- ✅ **Input validation** with FluentValidation +- ✅ **Rate limiting** on all endpoints + +--- + +## Technology Stack / Công Nghệ Sử Dụng + +### Backend + +- .NET 8.0, ASP.NET Core 8.0 +- MediatR 12+ (CQRS) +- Entity Framework Core 8.0 +- FluentValidation + +### Data / Dữ Liệu + +- PostgreSQL 15+ (primary database) +- Redis 7+ (caching) +- RabbitMQ 3.12+ (message broker) + +### Infrastructure / Hạ Tầng + +- Docker, Kubernetes +- Traefik (API Gateway) +- Prometheus + Grafana (monitoring) +- Loki (logging) + +### External APIs / APIs Bên Ngoài + +- Twitter API v2 + - OpenAI API (GPT-4) + +--- + +## Contributing / Đóng Góp + +See main project contributing guide: [CONTRIBUTING.md](../../docs/CONTRIBUTING.md) + +--- + +## License / Giấy Phép + +MIT License + +--- + +## Related Documentation / Tài Liệu Liên Quan + +### GoodGo Platform + +- [API Design Standards](../../.agent/skills/api-design/SKILL.md) +- [CQRS MediatR Patterns](../../.agent/skills/cqrs-mediatr/SKILL.md) +- [Domain-Driven Design](../../.agent/skills/domain-driven-design/SKILL.md) +- [Project Rules](../../.agent/skills/project-rules/SKILL.md) + +### Related Services / Dịch Vụ Liên Quan + +- [MKT Facebook Service](../../mkt-facebook-service-net/docs) +- [MKT Zalo Service](../../mkt-zalo-service-net/docs) +- [MKT WhatsApp Service](../../mkt-whatsapp-service-net/docs) + +--- + +## Contact / Liên Hệ + +- **Technical Support**: api-support@goodgo.com +- **Documentation Issues**: GitHub Issues +- **Emergency Support**: support-priority@goodgo.com + +--- + +**Last Updated**: 2026-01-18 +**Version**: 1.0 +**Maintained by**: GoodGo Platform Team diff --git a/services/mkt-x-service-net/docs/TWITTER_SETUP.md b/services/mkt-x-service-net/docs/TWITTER_SETUP.md new file mode 100644 index 00000000..eacb31c5 --- /dev/null +++ b/services/mkt-x-service-net/docs/TWITTER_SETUP.md @@ -0,0 +1,494 @@ +# Twitter API Setup Guide + +## Table of Contents + +1. [Prerequisites](#prerequisites) +2. [Create Twitter Developer Account](#create-twitter-developer-account) +3. [Create Twitter App](#create-twitter-app) +4. [Configure OAuth Settings](#configure-oauth-settings) +5. [Set Up Account Activity API](#set-up-account-activity-api) +6. [Configure Webhooks](#configure-webhooks) +7. [Testing the Integration](#testing-the-integration) +8. [Troubleshooting](#troubleshooting) + +--- + +## Prerequisites + +Before setting up Twitter API integration, ensure you have: + +- ✅ Twitter account (preferably business account) +- ✅ MKT X Service deployed and accessible via HTTPS +- ✅ Valid SSL certificate for webhook URL +- ✅ Access to server configuration + +--- + +## Create Twitter Developer Account + +### Step 1: Apply for Developer Access + +1. Go to [Twitter Developer Portal](https://developer.twitter.com/) +2. Click "Sign up" and log in with your Twitter account +3. Fill out the application form: + - **Account type**: Choose "Business" or "Professional" + - **Primary use case**: Marketing automation and customer service + - **Will you make Twitter content available to government entities?**: No +4. Review and accept the Developer Agreement +5. Verify your email address + +**Processing Time**: Usually instant, but can take up to 24-48 hours + +### Step 2: Create a Project + +1. Navigate to the [Developer Portal Dashboard](https://developer.twitter.com/en/portal/dashboard) +2. Click "Create Project" +3. Fill in project details: + - **Project name**: "GoodGo Marketing" + - **Use case**: Customer engagement + - **Project description**: "Twitter marketing automation for e-commerce" +4. Click "Next" and "Create" + +--- + +## Create Twitter App + +### Step 1: Create New App + +1. In your project, click "+ Add App" +2. Choose "Production" environment +3. Enter app name (e.g., "GoodGo-MKT-X-Prod") +4. Save your API credentials: + +``` +API Key: xxxxxxxxxxxxxxxxxxxxx +API Key Secret: xxxxxxxxxxxxxxxxxxxxx +Bearer Token: xxxxxxxxxxxxxxxxxxxxx +``` + +**⚠️ Important**: Store these credentials securely. They won't be shown again. + +### Step 2: Configure App Permissions + +1. Go to your app settings +2. Navigate to "User authentication settings" +3. Click "Set up" +4. Configure permissions: + +``` +App permissions: +☑ Read +☑ Write +☑ Direct Messages + +Type of App: +☑ Web App, Automated App or Bot + +App info: +Callback URI: https://your-domain.com/api/v1/mkt-x/oauth/callback +Website URL: https://your-domain.com +``` + +5. Save changes + +--- + +## Configure OAuth Settings + +### OAuth 1.0a Setup + +Twitter Direct Messages API requires OAuth 1.0a authentication. + +### Step 1: Generate Access Tokens + +1. In app settings, go to "Keys and tokens" +2. Under "Authentication Tokens", click "Generate" +3. Save the tokens: + +``` +Access Token: xxxxxxxxxxxxxxxxxxxxx +Access Token Secret: xxxxxxxxxxxxxxxxxxxxx +``` + +### Step 2: Add Credentials to Service + +Update your `appsettings.json`: + +```json +{ + "Twitter": { + "ApiKey": "your_api_key", + "ApiKeySecret": "your_api_key_secret", + "BearerToken": "your_bearer_token", + "AccessToken": "your_access_token", + "AccessTokenSecret": "your_access_token_secret", + "WebhookUrl": "https://your-domain.com/api/v1/mkt-x/webhooks/twitter" + } +} +``` + +**🔒 Security**: Use environment variables or secrets manager for production: + +```bash +export TWITTER__API_KEY="your_api_key" +export TWITTER__API_KEY_SECRET="your_api_key_secret" +export TWITTER__ACCESS_TOKEN="your_access_token" +export TWITTER__ACCESS_TOKEN_SECRET="your_access_token_secret" +``` + +--- + +## Set Up Account Activity API + +The Account Activity API allows you to receive real-time Twitter events via webhooks. + +### Step 1: Apply for Account Activity API Access + +1. Go to [Account Activity API](https://developer.twitter.com/en/products/twitter-api/account-activity-api) page +2. Request access for your app +3. Select "Sandbox" environment for development (free) +4. For production, you'll need "Enterprise" or "Premium" tier + +**Pricing**: +- **Sandbox**: Free (1 webhook, 15 subscriptions) +- **Premium**: Starting from $149/month (5 webhooks, 500 subscriptions) +- **Enterprise**: Custom pricing + +### Step 2: Register Webhook URL + +Register your webhook URL with Twitter using the Twitter API: + +```bash +curl -X POST \ + 'https://api.twitter.com/1.1/account_activity/all/:env_name/webhooks.json' \ + -H 'Authorization: OAuth oauth_consumer_key="YOUR_API_KEY", oauth_token="YOUR_ACCESS_TOKEN", oauth_signature="SIGNATURE", oauth_signature_method="HMAC-SHA1", oauth_timestamp="TIMESTAMP", oauth_nonce="NONCE", oauth_version="1.0"' \ + -d 'url=https://your-domain.com/api/v1/mkt-x/webhooks/twitter' +``` + +**Or use the MKT X Service API**: + +```bash +POST /api/v1/mkt-x/accounts/{accountId}/register-webhook +``` + +### Step 3: Verify CRC (Challenge-Response Check) + +Twitter will send a GET request to your webhook URL with a `crc_token` parameter. Your service must respond with: + +```json +{ + "response_token": "sha256=base64_encoded_hmac" +} +``` + +The service automatically handles this via the `/webhooks/verify` endpoint. + +### Step 4: Subscribe to User Activity + +Subscribe to receive events for your Twitter account: + +```bash +curl -X POST \ + 'https://api.twitter.com/1.1/account_activity/all/:env_name/subscriptions.json' \ + -H 'Authorization: OAuth ...' +``` + +--- + +## Configure Webhooks + +### Events You'll Receive + +When properly configured, you'll receive these webhook events: + +#### Direct Message Events +```json +{ + "direct_message_events": [ + { + "type": "message_create", + "id": "123456789", + "created_timestamp": "1642000000000", + "message_create": { + "sender_id": "987654321", + "message_data": { + "text": "Hello!" + } + } + } + ] +} +``` + +#### Follow Events +```json +{ + "follow_events": [ + { + "type": "follow", + "created_timestamp": "1642000000000", + "source": { + "id": "987654321" + }, + "target": { + "id": "123456789" + } + } + ] +} +``` + +### Webhook Security + +All webhook requests from Twitter include: + +1. **X-Twitter-Webhooks-Signature** header +2. HMAC-SHA256 signature of the request body + +The service automatically validates this signature using your API key secret. + +--- + +## Testing the Integration + +### Step 1: Test OAuth Connection + +```bash +# Test OAuth credentials +curl -X POST http://localhost:5000/api/v1/mkt-x/accounts \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "oauthToken": "YOUR_ACCESS_TOKEN", + "oauthTokenSecret": "YOUR_ACCESS_TOKEN_SECRET" + }' +``` + +**Expected Response**: +```json +{ + "success": true, + "data": { + "id": "uuid", + "twitterUserId": "123456789", + "username": "your_username", + "status": "active" + } +} +``` + +### Step 2: Test Webhook URL + +Test that your webhook endpoint is accessible: + +```bash +curl -X GET 'https://your-domain.com/api/v1/mkt-x/webhooks/verify?crc_token=test' +``` + +**Expected Response**: +```json +{ + "response_token": "sha256=..." +} +``` + +### Step 3: Send Test Direct Message + +1. Send a direct message to your connected Twitter account from another account +2. Check service logs to confirm webhook event was received +3. Verify conversation and message were created in the database + +**Check logs**: +```bash +docker-compose logs -f mkt-x-service-net | grep "Twitter webhook" +``` + +### Step 4: Test Outbound Message + +Send a message from the service: + +```bash +curl -X POST http://localhost:5000/api/v1/mkt-x/conversations/{conversationId}/messages \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "content": "Hello from MKT X Service!", + "type": "text" + }' +``` + +Verify the message appears in Twitter DMs. + +--- + +## Troubleshooting + +### Issue 1: Webhook Registration Fails + +**Error**: `401 Unauthorized` when registering webhook + +**Solution**: +1. Verify OAuth credentials are correct +2. Ensure your app has "Read + Write + Direct Messages" permissions +3. Check that webhook URL is HTTPS (not HTTP) +4. Confirm SSL certificate is valid + +### Issue 2: CRC Verification Fails + +**Error**: Twitter webhook shows "Invalid response_token" + +**Solution**: +1. Verify API Key Secret is correct in configuration +2. Check HMAC calculation in `/webhooks/verify` endpoint +3. Ensure response format matches Twitter requirements: + ```json + {"response_token": "sha256=..."} + ``` + +### Issue 3: No Webhook Events Received + +**Symptoms**: No events in logs after sending DM + +**Solution**: +1. Verify webhook is registered: + ```bash + curl -X GET \ + 'https://api.twitter.com/1.1/account_activity/all/:env_name/webhooks.json' \ + -H 'Authorization: OAuth ...' + ``` +2. Check webhook subscription: + ```bash + curl -X GET \ + 'https://api.twitter.com/1.1/account_activity/all/:env_name/subscriptions/list.json' \ + -H 'Authorization: OAuth ...' + ``` +3. Ensure firewall allows inbound HTTPS traffic +4. Check service logs for webhook validation errors + +### Issue 4: Rate Limit Exceeded + +**Error**: `429 Too Many Requests` + +**Solution**: +- Twitter DM limit: 500 messages / 24 hours per account +- Check current usage: + ```bash + curl -X GET \ + 'https://api.twitter.com/1.1/application/rate_limit_status.json' \ + -H 'Authorization: Bearer YOUR_BEARER_TOKEN' + ``` +- Implement message queuing to respect limits +- Consider using multiple Twitter accounts for high-volume scenarios + +### Issue 5: OAuth Signature Error + +**Error**: `401 Unauthorized - Invalid OAuth signature` + +**Solution**: +1. Verify all OAuth parameters are correctly encoded +2. Check system time is synchronized (NTP) +3. Ensure no extra spaces in OAuth header +4. Use a library like `OAuth.DotNetCore` instead of manual implementation + +--- + +## Best Practices + +### 1. Security + +- ✅ Store API credentials in environment variables or secrets manager +- ✅ Use HTTPS for all webhook endpoints +- ✅ Validate webhook signatures +- ✅ Rotate OAuth tokens periodically +- ✅ Implement rate limiting on your endpoints + +### 2. Reliability + +- ✅ Implement retry logic for failed API calls +- ✅ Use message queues for webhook processing +- ✅ Monitor webhook endpoint uptime +- ✅ Set up alerting for API errors +- ✅ Keep backup of webhook events + +### 3. Performance + +- ✅ Process webhooks asynchronously +- ✅ Use caching for user data +- ✅ Batch API requests when possible +- ✅ Implement connection pooling +- ✅ Monitor API quotas + +### 4. Compliance + +- ✅ Follow Twitter's [Developer Policy](https://developer.twitter.com/en/developer-terms/policy) +- ✅ Respect user privacy and data protection laws (GDPR, CCPA) +- ✅ Include unsubscribe options in automated messages +- ✅ Clearly identify bot messages +- ✅ Don't spam users + +--- + +## Rate Limits + +### Twitter API v2 Limits + +| Endpoint | Limit | Window | +|----------|-------|--------| +| Direct Messages (Send) | 500 requests | 24 hours | +| Direct Messages (Read) | 300 requests | 15 minutes | +| User Lookup | 900 requests | 15 minutes | +| Tweet Lookup | 300 requests | 15 minutes | + +### Service Rate Limits + +The MKT X Service implements these internal limits: + +- **Campaigns**: Max 10,000 contacts per day per account +- **API Calls**: 100 requests per minute per merchant +- **Webhook Processing**: 1000 events per minute + +--- + +## Monitoring + +### Key Metrics to Track + +1. **Webhook Health** + - Webhook uptime + - CRC verification success rate + - Event processing latency + +2. **API Usage** + - Requests per day + - Error rate + - Rate limit hits + +3. **Business Metrics** + - Messages sent/received + - Conversation response time + - Campaign delivery rate + +### Recommended Tools + +- **Prometheus + Grafana**: For metrics and dashboards +- **Sentry**: For error tracking +- **Twitter Developer Portal**: For API quota monitoring + +--- + +## Additional Resources + +- [Twitter API Documentation](https://developer.twitter.com/en/docs/twitter-api) +- [Account Activity API Guide](https://developer.twitter.com/en/docs/twitter-api/enterprise/account-activity-api/overview) +- [OAuth 1.0a Specification](https://oauth.net/core/1.0a/) +- [Twitter Developer Community](https://twittercommunity.com/) + +--- + +## Support + +For issues with Twitter API integration: + +- **Twitter Developer Forums**: https://twittercommunity.com/ +- **MKT X Service Support**: api-support@goodgo.com +- **Emergency**: support-priority@goodgo.com diff --git a/services/mkt-zalo-service-net/README.md b/services/mkt-zalo-service-net/README.md new file mode 100644 index 00000000..cfababe8 --- /dev/null +++ b/services/mkt-zalo-service-net/README.md @@ -0,0 +1,332 @@ +# MKT Zalo Service / Dịch Vụ MKT Zalo + +**EN**: Marketing service for Zalo Official Account integration, providing chatbot automation, AI-powered messaging, and customer relationship management. + +**VI**: Dịch vụ marketing tích hợp Zalo Official Account, cung cấp chatbot tự động, nhắn tin AI, và quản lý quan hệ khách hàng. + +## Overview / Tổng Quan + +The MKT Zalo Service enables businesses to leverage Zalo's messaging platform for customer engagement, automated responses, and personalized marketing campaigns. + +Dịch vụ MKT Zalo cho phép doanh nghiệp tận dụng nền tảng nhắn tin Zalo để tương tác khách hàng, phản hồi tự động và chiến dịch marketing cá nhân hóa. + +### Key Features / Tính Năng Chính + +- ✅ **CHATBOT Automation**: Rule-based automated responses for customer inquiries +- ✅ **AI Chatbot**: LLM-powered intelligent conversations and context-aware responses +- ✅ **Customer Management**: Unified CRM for tracking customer interactions and preferences +- ✅ **Webhook Integration**: Real-time event handling from Zalo Official Account +- ✅ **Message Templates**: Pre-approved ZNS (Zalo Notification Service) templates +- ✅ **Analytics Dashboard**: Conversation metrics, engagement rates, and performance tracking + +## Architecture / Kiến Trúc + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Zalo Official Account │ +│ (Customer sends messages via Zalo) │ +└────────────────────┬────────────────────────────────────────────┘ + │ Webhook Events + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ mkt-zalo-service-net │ +│ │ +│ ┌──────────────────────────────────────────────────────────┐ │ +│ │ Webhook Handler (API Layer) │ │ +│ │ • Verify signature │ │ +│ │ • Parse events (message, follow, buttons) │ │ +│ │ • Return 200 quickly │ │ +│ └───────────────┬──────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌──────────────────────────────────────────────────────────┐ │ +│ │ Message Processing Engine │ │ +│ │ ┌────────────────┐ ┌────────────────┐ │ │ +│ │ │ Rule Engine │ │ AI Engine │ │ │ +│ │ │ (Automation) │ │ (LLM Based) │ │ │ +│ │ └────────────────┘ └────────────────┘ │ │ +│ └───────────────┬──────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌──────────────────────────────────────────────────────────┐ │ +│ │ Domain Layer │ │ +│ │ • Conversation Aggregate │ │ +│ │ • ZaloCustomer Aggregate │ │ +│ │ • ChatbotRule Entity │ │ +│ │ • MessageTemplate Entity │ │ +│ └──────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌──────────────────────────────────────────────────────────┐ │ +│ │ Integration Layer │ │ +│ │ • Zalo OA API Client (Send messages) │ │ +│ │ • LLM Provider (OpenAI, Vertex AI) │ │ +│ └──────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ + │ + ▼ + ┌──────────────┐ + │ PostgreSQL │ + │ (Customer, │ + │ Conversation,│ + │ Templates) │ + └──────────────┘ +``` + +## Technology Stack / Công Nghệ + +| Layer | Technology | +|-------|------------| +| **Framework** | .NET 10, ASP.NET Core | +| **Patterns** | CQRS + MediatR, DDD, Event-Driven | +| **Database** | PostgreSQL (Neon), EF Core | +| **Caching** | Redis (conversation context) | +| **External APIs** | Zalo OA API, OpenAI/Vertex AI | +| **Message Queue** | RabbitMQ (MassTransit) | +| **Observability** | Prometheus, Grafana, Loki | + +## Project Structure / Cấu Trúc Dự Án + +``` +mkt-zalo-service-net/ +├── src/ +│ ├── MktZaloService.API/ # API Layer +│ │ ├── Controllers/ +│ │ │ ├── WebhooksController.cs # Zalo webhook endpoint +│ │ │ ├── ConversationsController.cs # Conversation management +│ │ │ ├── CustomersController.cs # Customer CRM +│ │ │ ├── ChatbotRulesController.cs # Automation rules +│ │ │ └── Admin/ # Admin APIs +│ │ ├── Application/ +│ │ │ ├── Commands/ # Write operations +│ │ │ ├── Queries/ # Read operations +│ │ │ └── IntegrationEvents/ # Events from/to other services +│ │ └── Program.cs +│ │ +│ ├── MktZaloService.Domain/ # Domain Layer +│ │ ├── AggregatesModel/ +│ │ │ ├── ConversationAggregate/ +│ │ │ │ ├── Conversation.cs # Aggregate root +│ │ │ │ ├── Message.cs # Entity +│ │ │ │ ├── MessageType.cs # Enum +│ │ │ │ └── ConversationStatus.cs # Enum +│ │ │ ├── ZaloCustomerAggregate/ +│ │ │ │ ├── ZaloCustomer.cs # Aggregate root +│ │ │ │ ├── CustomerProfile.cs # Value object +│ │ │ │ ├── Tag.cs # Entity +│ │ │ │ └── CustomerSegment.cs # Enum +│ │ │ ├── ChatbotRuleAggregate/ +│ │ │ │ ├── ChatbotRule.cs # Aggregate root +│ │ │ │ ├── RuleCondition.cs # Value object +│ │ │ │ ├── RuleAction.cs # Value object +│ │ │ │ └── RuleType.cs # Enum +│ │ │ └── MessageTemplateAggregate/ +│ │ │ ├── MessageTemplate.cs # Aggregate root +│ │ │ └── TemplateParameter.cs # Value object +│ │ ├── Exceptions/ +│ │ │ └── ZaloDomainException.cs +│ │ ├── Events/ +│ │ │ ├── ConversationStartedDomainEvent.cs +│ │ │ ├── MessageReceivedDomainEvent.cs +│ │ │ └── CustomerProfileUpdatedDomainEvent.cs +│ │ └── SeedWork/ +│ │ ├── Entity.cs +│ │ ├── IAggregateRoot.cs +│ │ └── ValueObject.cs +│ │ +│ └── MktZaloService.Infrastructure/ # Infrastructure Layer +│ ├── Data/ +│ │ ├── MktZaloServiceContext.cs +│ │ ├── EntityConfigurations/ +│ │ └── Migrations/ +│ ├── Repositories/ +│ │ ├── ConversationRepository.cs +│ │ ├── ZaloCustomerRepository.cs +│ │ ├── ChatbotRuleRepository.cs +│ │ └── MessageTemplateRepository.cs +│ └── ExternalServices/ +│ ├── ZaloOfficialAccountClient.cs # Zalo OA API integration +│ ├── LlmService.cs # OpenAI/Vertex AI +│ └── ChatbotEngine/ +│ ├── RuleBasedChatbotEngine.cs +│ └── AiChatbotEngine.cs +│ +├── tests/ +│ ├── MktZaloService.UnitTests/ +│ └── MktZaloService.IntegrationTests/ +│ +├── docs/ +│ ├── README.md # This file +│ ├── SOLUTION.md # Solution architecture (detailed) +│ ├── API_DESIGN.md # API endpoints specification +│ ├── DOMAIN_MODELS.md # Domain entities and aggregates +│ ├── INTEGRATION.md # Zalo OA API integration guide +│ └── DATABASE_SCHEMA.md # Database design +│ +├── Dockerfile +├── docker-compose.yml +└── MktZaloService.slnx +``` + +## Getting Started / Bắt Đầu + +### Prerequisites / Yêu Cầu + +- .NET 10 SDK +- PostgreSQL 15+ +- Redis 7+ +- Zalo Official Account (verified) +- Zalo App ID & Secret Key +- Access Token from Zalo OA + +### Setup Steps / Các Bước Thiết Lập + +1. **Clone repository** + ```bash + cd services/mkt-zalo-service-net + ``` + +2. **Configure environment variables** + ```bash + # .env file + DATABASE_URL=postgresql://user:password@localhost:5432/mkt_zalo_db + REDIS_URL=redis://localhost:6379 + ZALO_APP_ID=your_app_id + ZALO_APP_SECRET=your_app_secret + ZALO_OA_ID=your_oa_id + ZALO_ACCESS_TOKEN=your_access_token + OPENAI_API_KEY=your_openai_key # For AI chatbot + ``` + +3. **Run database migrations** + ```bash + dotnet ef database update --project src/MktZaloService.Infrastructure + ``` + +4. **Run the service** + ```bash + dotnet run --project src/MktZaloService.API + ``` + +5. **Configure Zalo Webhook** + - Go to Zalo Developers portal + - Set webhook URL: `https://yourdomain.com/api/v1/zalo/webhooks` + - Enable events: `user_send_text`, `user_send_image`, `user_send_link`, `follow`, `unfollow` + +## API Endpoints / Các API Endpoints + +### Public APIs (Zalo Webhooks) +- `POST /api/v1/zalo/webhooks` - Receive Zalo OA events + +### Customer Management +- `GET /api/v1/zalo/customers` - List customers +- `GET /api/v1/zalo/customers/{id}` - Get customer details +- `PUT /api/v1/zalo/customers/{id}` - Update customer profile +- `POST /api/v1/zalo/customers/{id}/tags` - Add customer tags + +### Conversation Management +- `GET /api/v1/zalo/conversations` - List conversations +- `GET /api/v1/zalo/conversations/{id}` - Get conversation history +- `POST /api/v1/zalo/conversations/{id}/messages` - Send message + +### Chatbot Automation Rules +- `GET /api/v1/zalo/chatbot-rules` - List automation rules +- `POST /api/v1/zalo/chatbot-rules` - Create automation rule +- `PUT /api/v1/zalo/chatbot-rules/{id}` - Update rule +- `DELETE /api/v1/zalo/chatbot-rules/{id}` - Delete rule + +### Message Templates (ZNS) +- `GET /api/v1/zalo/templates` - List templates +- `POST /api/v1/zalo/templates/{id}/send` - Send template message + +### Admin APIs +- `GET /api/v1/zalo/admin/analytics` - Conversation analytics +- `GET /api/v1/zalo/admin/messages` - Search all messages +- `POST /api/v1/zalo/admin/broadcast` - Broadcast message to segments + +See [API_DESIGN.md](./docs/API_DESIGN.md) for full API documentation. + +## Key Workflows / Quy Trình Chính + +### 1. Receiving Webhook from Zalo +``` +Zalo → POST /webhooks → Verify signature → Parse event → Queue for processing → Return 200 +``` + +### 2. Processing Incoming Message +``` +Parse message → Load customer context → Route to engine (Rule vs AI) → Generate response → Call Zalo API → Save to DB +``` + +### 3. AI Chatbot Flow +``` +Receive text → Load conversation history → Build LLM prompt with context → Call OpenAI/Vertex AI → Parse response → Send to customer +``` + +## Environment Variables / Biến Môi Trường + +| Variable | Description | Required | +|----------|-------------|----------| +| `DATABASE_URL` | PostgreSQL connection string | Yes | +| `REDIS_URL` | Redis connection string | Yes | +| `ZALO_APP_ID` | Zalo Application ID | Yes | +| `ZALO_APP_SECRET` | Zalo Application Secret Key | Yes | +| `ZALO_OA_ID` | Zalo Official Account ID | Yes | +| `ZALO_ACCESS_TOKEN` | OA Access Token (1 year validity) | Yes | +| `ZALO_WEBHOOK_SECRET` | Webhook signature verification key | Yes | +| `OPENAI_API_KEY` | OpenAI API key for AI chatbot | Optional | +| `VERTEX_AI_PROJECT` | Google Vertex AI project | Optional | +| `ENABLE_AI_CHATBOT` | Enable/disable AI chatbot (true/false) | No | + +## Testing / Kiểm Thử + +### Unit Tests +```bash +dotnet test tests/MktZaloService.UnitTests +``` + +### Integration Tests +```bash +dotnet test tests/MktZaloService.IntegrationTests +``` + +### Manual Testing with Zalo +1. Send a message to your Zalo OA from a test account +2. Check logs for webhook reception +3. Verify response is sent back to Zalo +4. Check database for stored conversation + +## Deployment / Triển Khai + +### Docker +```bash +# Build image +docker build -t mkt-zalo-service-net . + +# Run container +docker run -p 8080:8080 \ + -e DATABASE_URL=... \ + -e ZALO_APP_ID=... \ + mkt-zalo-service-net +``` + +### Docker Compose (Local) +```bash +cd deployments/local +docker-compose up -d mkt-zalo-service-net +``` + +## Related Documentation / Tài Liệu Liên Quan + +- [SOLUTION.md](./docs/SOLUTION.md) - Detailed solution architecture +- [API_DESIGN.md](./docs/API_DESIGN.md) - Complete API specification +- [DOMAIN_MODELS.md](./docs/DOMAIN_MODELS.md) - Domain model details +- [INTEGRATION.md](./docs/INTEGRATION.md) - Zalo OA API integration +- [DATABASE_SCHEMA.md](./docs/DATABASE_SCHEMA.md) - Database schema + +## Contributing / Đóng Góp + +Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) for development guidelines. + +## License / Giấy Phép + +Copyright © 2026 GoodGo Platform. All rights reserved. diff --git a/services/mkt-zalo-service-net/docs/API_DESIGN.md b/services/mkt-zalo-service-net/docs/API_DESIGN.md new file mode 100644 index 00000000..b49f6f8b --- /dev/null +++ b/services/mkt-zalo-service-net/docs/API_DESIGN.md @@ -0,0 +1,971 @@ +# API Design Specification + +**EN**: Complete API design specification for MKT Zalo Service including endpoints, DTOs, request/response formats, and Swagger documentation. + +**VI**: Đặc tả thiết kế API đầy đủ cho Dịch vụ MKT Zalo bao gồm endpoints, DTOs, định dạng request/response, và tài liệu Swagger. + +--- + +## Table of Contents / Mục Lục + +1. [API Overview](#api-overview) +2. [Authentication & Authorization](#authentication--authorization) +3. [Webhook APIs](#webhook-apis) +4. [Conversation APIs](#conversation-apis) +5. [Customer Management APIs](#customer-management-apis) +6. [Chatbot Rule APIs](#chatbot-rule-apis) +7. [Template APIs](#template-apis) +8. [Admin APIs](#admin-apis) +9. [Common DTOs](#common-dtos) +10. [Error Responses](#error-responses) + +--- + +## API Overview + +### Base URL Pattern +``` +http://localhost/api/v{version}/zalo +``` + +### API Versioning +- Version: `1.0` +- Format: URL path versioning (`/api/v1/zalo/...`) + +### Response Wrapper +All APIs use the standard `ApiResponse` wrapper: +```json +{ + "success": true, + "data": { ... }, + "error": null, + "pagination": { ... } // For list endpoints +} +``` + +--- + +## Authentication & Authorization + +### Authentication Schemes + +| Endpoint Category | Auth Method | Details | +|-------------------|-------------|---------| +| **Webhooks** | Signature verification | Zalo webhook signature in header | +| **Public APIs** | JWT Bearer | From IAM service | +| **Admin APIs** | JWT Bearer + Role | Requires `admin` or `marketing_manager` role | + +### Authorization Header +``` +Authorization: Bearer eyJhbGciOiJIUzI1NiIs... +``` + +--- + +## Webhook APIs + +### 1. Receive Zalo Webhook + +**EN**: Endpoint to receive events from Zalo Official Account (user messages, follows, etc.). + +**VI**: Endpoint nhận sự kiện từ Zalo Official Account (tin nhắn, follow, etc.). + +```http +POST /api/v1/zalo/webhooks +Content-Type: application/json +X-Zalo-Signature: +``` + +#### Request Body +```json +{ + "app_id": "1234567890", + "event_name": "user_send_text", + "timestamp": 1705586400000, + "sender": { + "id": "1234567890123456789" + }, + "recipient": { + "id": "9876543210" + }, + "message": { + "text": "Xin chào, tôi cần hỗ trợ", + "msg_id": "msg_123456" + } +} +``` + +#### Response +```http +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "success": true +} +``` + +#### Error Responses +- `401 Unauthorized` - Invalid signature +- `400 Bad Request` - Malformed webhook payload + +#### Implementation Notes +- **MUST** return `200 OK` within 2 seconds +- Webhook processing is async (queued to RabbitMQ) +- Signature verification using `X-Zalo-Signature` header + +--- + +## Conversation APIs + +### 2. Get Conversations List + +**EN**: Get list of conversations with pagination and filtering. + +**VI**: Lấy danh sách hội thoại với phân trang và bộ lọc. + +```http +GET /api/v1/zalo/conversations?skip=0&take=20&status=active&fromDate=2026-01-01 +Authorization: Bearer +``` + +#### Query Parameters +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `skip` | int | No | Number of records to skip (default: 0) | +| `take` | int | No | Number of records to return (default: 20, max: 100) | +| `status` | enum | No | `active`, `closed`, `all` | +| `zaloUserId` | string | No | Filter by Zalo user ID | +| `fromDate` | datetime | No | Filter conversations after this date | +| `toDate` | datetime | No | Filter conversations before this date | + +#### Response +```http +HTTP/1.1 200 OK + +{ + "success": true, + "data": { + "conversations": [ + { + "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "zaloUserId": "1234567890123456789", + "customerName": "Nguyễn Văn A", + "customerAvatar": "https://s.zalo.me/avatar.jpg", + "status": "active", + "lastMessage": "Cảm ơn bạn", + "lastMessageAt": "2026-01-18T10:30:00Z", + "startedAt": "2026-01-18T10:00:00Z", + "messageCount": 15, + "unreadCount": 2 + } + ], + "totalCount": 120 + }, + "pagination": { + "page": 1, + "limit": 20, + "total": 120, + "totalPages": 6 + } +} +``` + +--- + +### 3. Get Conversation Details + +**EN**: Get detailed conversation with full message history. + +**VI**: Lấy chi tiết hội thoại với lịch sử tin nhắn đầy đủ. + +```http +GET /api/v1/zalo/conversations/{conversationId} +Authorization: Bearer +``` + +#### Path Parameters +- `conversationId` (guid) - Conversation ID + +#### Query Parameters +| Parameter | Type | Description | +|-----------|------|-------------| +| `messageSkip` | int | Skip messages (for pagination) | +| `messageTake` | int | Take messages (default: 50) | + +#### Response +```http +HTTP/1.1 200 OK + +{ + "success": true, + "data": { + "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "zaloUserId": "1234567890123456789", + "customerId": "abc85f64-5717-4562-b3fc-2c963f66afa6", + "status": "active", + "startedAt": "2026-01-18T10:00:00Z", + "endedAt": null, + "customer": { + "id": "abc85f64-5717-4562-b3fc-2c963f66afa6", + "zaloUserId": "1234567890123456789", + "displayName": "Nguyễn Văn A", + "avatarUrl": "https://s.zalo.me/avatar.jpg", + "phoneNumber": "+84901234567", + "tags": ["vip", "interested-in-retail"] + }, + "messages": [ + { + "id": "msg-001", + "type": "text", + "content": "Xin chào", + "direction": "incoming", + "isFromBot": false, + "sentAt": "2026-01-18T10:00:00Z" + }, + { + "id": "msg-002", + "type": "text", + "content": "Xin chào! Tôi có thể giúp gì cho bạn?", + "direction": "outgoing", + "isFromBot": true, + "sentAt": "2026-01-18T10:00:05Z" + } + ], + "messageCount": 15, + "totalMessages": 15 + } +} +``` + +--- + +### 4. Send Message + +**EN**: Send a message to a customer in an active conversation. + +**VI**: Gửi tin nhắn đến khách hàng trong hội thoại đang hoạt động. + +```http +POST /api/v1/zalo/conversations/{conversationId}/messages +Authorization: Bearer +Content-Type: application/json +``` + +#### Request Body +```json +{ + "type": "text", + "content": "Cảm ơn bạn đã liên hệ. Chúng tôi sẽ xử lý yêu cầu của bạn ngay." +} +``` + +#### Response +```http +HTTP/1.1 201 Created + +{ + "success": true, + "data": { + "messageId": "msg-003", + "sentAt": "2026-01-18T10:05:00Z", + "zaloMessageId": "zalo_msg_xyz" + } +} +``` + +#### Error Responses +- `404 Not Found` - Conversation not found +- `400 Bad Request` - Conversation is closed +- `422 Unprocessable Entity` - Failed to send via Zalo API + +--- + +### 5. Close Conversation + +**EN**: Close an active conversation. + +**VI**: Đóng hội thoại đang hoạt động. + +```http +POST /api/v1/zalo/conversations/{conversationId}/close +Authorization: Bearer +``` + +#### Response +```http +HTTP/1.1 200 OK + +{ + "success": true, + "data": { + "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "status": "closed", + "closedAt": "2026-01-18T11:00:00Z" + } +} +``` + +--- + +## Customer Management APIs + +### 6. Get Customers List + +**EN**: Get list of Zalo customers with filtering and search. + +**VI**: Lấy danh sách khách hàng Zalo với bộ lọc và tìm kiếm. + +```http +GET /api/v1/zalo/customers?skip=0&take=20&search=Nguyen&segment=vip +Authorization: Bearer +``` + +#### Query Parameters +| Parameter | Type | Description | +|-----------|------|-------------| +| `skip` | int | Pagination skip | +| `take` | int | Pagination limit | +| `search` | string | Search by name, phone, email | +| `segment` | enum | `new`, `regular`, `active`, `vip` | +| `tags` | string[] | Filter by tags (comma-separated) | + +#### Response +```http +HTTP/1.1 200 OK + +{ + "success": true, + "data": { + "customers": [ + { + "id": "abc85f64-5717-4562-b3fc-2c963f66afa6", + "zaloUserId": "1234567890123456789", + "displayName": "Nguyễn Văn A", + "avatarUrl": "https://s.zalo.me/avatar.jpg", + "phoneNumber": "+84901234567", + "email": "nguyenvana@example.com", + "segment": "vip", + "tags": ["vip", "interested-in-retail", "high-value"], + "firstInteractionAt": "2026-01-01T08:00:00Z", + "lastInteractionAt": "2026-01-18T10:30:00Z", + "conversationCount": 12, + "totalSpent": 5000000 + } + ], + "totalCount": 1523 + }, + "pagination": { ... } +} +``` + +--- + +### 7. Get Customer Details + +**EN**: Get detailed customer profile with interaction summary. + +**VI**: Lấy hồ sơ khách hàng chi tiết với tóm tắt tương tác. + +```http +GET /api/v1/zalo/customers/{customerId} +Authorization: Bearer +``` + +#### Response +```http +HTTP/1.1 200 OK + +{ + "success": true, + "data": { + "id": "abc85f64-5717-4562-b3fc-2c963f66afa6", + "zaloUserId": "1234567890123456789", + "profile": { + "displayName": "Nguyễn Văn A", + "avatarUrl": "https://s.zalo.me/avatar.jpg", + "phoneNumber": "+84901234567", + "email": "nguyenvana@example.com" + }, + "segment": "vip", + "tags": ["vip", "interested-in-retail"], + "interactionSummary": { + "totalConversations": 12, + "totalMessages": 156, + "averageResponseTime": "PT2M30S", + "lastInteractionAt": "2026-01-18T10:30:00Z", + "firstInteractionAt": "2026-01-01T08:00:00Z" + }, + "recentConversations": [ + { + "id": "conv-001", + "startedAt": "2026-01-18T10:00:00Z", + "messageCount": 15 + } + ] + } +} +``` + +--- + +### 8. Update Customer Profile + +**EN**: Update customer profile information and tags. + +**VI**: Cập nhật thông tin hồ sơ khách hàng và tags. + +```http +PUT /api/v1/zalo/customers/{customerId} +Authorization: Bearer +Content-Type: application/json +``` + +#### Request Body +```json +{ + "phoneNumber": "+84901234567", + "email": "nguyenvana@example.com", + "tags": ["vip", "interested-in-retail", "high-value"] +} +``` + +#### Response +```http +HTTP/1.1 200 OK + +{ + "success": true, + "data": { + "id": "abc85f64-5717-4562-b3fc-2c963f66afa6", + "updatedAt": "2026-01-18T11:00:00Z" + } +} +``` + +--- + +## Chatbot Rule APIs + +### 9. Get Chatbot Rules + +**EN**: Get list of chatbot automation rules. + +**VI**: Lấy danh sách quy tắc tự động chatbot. + +```http +GET /api/v1/zalo/chatbot-rules?isActive=true +Authorization: Bearer +``` + +#### Query Parameters +| Parameter | Type | Description | +|-----------|------|-------------| +| `isActive` | bool | Filter by active status | +| `type` | enum | `keyword`, `regex`, `intent` | + +#### Response +```http +HTTP/1.1 200 OK + +{ + "success": true, + "data": { + "rules": [ + { + "id": "rule-001", + "name": "Greeting Rule", + "type": "keyword", + "priority": 100, + "isActive": true, + "conditions": [ + { + "field": "message_text", + "operator": "contains", + "value": "xin chào" + } + ], + "action": { + "type": "send_text", + "responseText": "Xin chào! Tôi có thể giúp gì cho bạn?" + }, + "matchCount": 523, + "lastMatchedAt": "2026-01-18T10:30:00Z" + } + ], + "totalCount": 15 + } +} +``` + +--- + +### 10. Create Chatbot Rule + +**EN**: Create a new chatbot automation rule. + +**VI**: Tạo quy tắc tự động chatbot mới. + +```http +POST /api/v1/zalo/chatbot-rules +Authorization: Bearer +Content-Type: application/json +``` + +#### Request Body +```json +{ + "name": "Pricing Inquiry", + "type": "keyword", + "priority": 90, + "conditions": [ + { + "field": "message_text", + "operator": "contains_any", + "values": ["giá", "bao nhiêu", "price"] + } + ], + "action": { + "type": "send_text", + "responseText": "Bảng giá của chúng tôi: [link]" + } +} +``` + +#### Response +```http +HTTP/1.1 201 Created + +{ + "success": true, + "data": { + "id": "rule-002", + "createdAt": "2026-01-18T11:00:00Z" + } +} +``` + +--- + +### 11. Update Chatbot Rule + +**EN**: Update an existing chatbot rule. + +**VI**: Cập nhật quy tắc chatbot hiện có. + +```http +PUT /api/v1/zalo/chatbot-rules/{ruleId} +Authorization: Bearer +Content-Type: application/json +``` + +#### Request Body +```json +{ + "name": "Updated Pricing Inquiry", + "priority": 95, + "isActive": true, + "action": { + "type": "send_text", + "responseText": "Bảng giá mới: [link]" + } +} +``` + +#### Response +```http +HTTP/1.1 200 OK + +{ + "success": true, + "data": { + "id": "rule-002", + "updatedAt": "2026-01-18T11:05:00Z" + } +} +``` + +--- + +### 12. Delete Chatbot Rule + +**EN**: Delete a chatbot automation rule. + +**VI**: Xóa quy tắc tự động chatbot. + +```http +DELETE /api/v1/zalo/chatbot-rules/{ruleId} +Authorization: Bearer +``` + +#### Response +```http +HTTP/1.1 204 No Content +``` + +--- + +## Template APIs + +### 13. Get Message Templates + +**EN**: Get list of approved Zalo Notification Service (ZNS) templates. + +**VI**: Lấy danh sách templates Zalo Notification Service (ZNS) đã duyệt. + +```http +GET /api/v1/zalo/templates +Authorization: Bearer +``` + +#### Response +```http +HTTP/1.1 200 OK + +{ + "success": true, + "data": { + "templates": [ + { + "id": "template-001", + "templateId": "283746", // Zalo template ID + "name": "Order Confirmation", + "content": "Đơn hàng {{order_id}} của bạn đã được xác nhận. Tổng: {{total_amount}}đ", + "parameters": [ + { + "name": "order_id", + "type": "string", + "required": true + }, + { + "name": "total_amount", + "type": "number", + "required": true + } + ], + "status": "approved" + } + ] + } +} +``` + +--- + +### 14. Send Template Message + +**EN**: Send a template message (ZNS) to a customer. + +**VI**: Gửi tin nhắn template (ZNS) đến khách hàng. + +```http +POST /api/v1/zalo/templates/{templateId}/send +Authorization: Bearer +Content-Type: application/json +``` + +#### Request Body +```json +{ + "zaloUserId": "1234567890123456789", + "parameters": { + "order_id": "ORD-12345", + "total_amount": "500000" + } +} +``` + +#### Response +```http +HTTP/1.1 200 OK + +{ + "success": true, + "data": { + "messageId": "msg-zns-001", + "sentAt": "2026-01-18T11:00:00Z", + "zaloMessageId": "zalo_msg_xyz" + } +} +``` + +--- + +## Admin APIs + +### 15. Get Analytics Dashboard + +**EN**: Get conversation and engagement analytics. + +**VI**: Lấy phân tích hội thoại và tương tác. + +```http +GET /api/v1/zalo/admin/analytics?fromDate=2026-01-01&toDate=2026-01-18 +Authorization: Bearer +``` + +#### Query Parameters +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `fromDate` | date | Yes | Start date (ISO 8601) | +| `toDate` | date | Yes | End date (ISO 8601) | +| `groupBy` | enum | No | `day`, `week`, `month` | + +#### Response +```json +{ + "success": true, + "data": { + "period": { + "from": "2026-01-01", + "to": "2026-01-18" + }, + "metrics": { + "totalConversations": 1523, + "activeConversations": 234, + "totalMessages": 15678, + "averageResponseTime": "PT1M45S", + "automationRate": 0.72, + "customerSatisfactionScore": 4.5 + }, + "timeline": [ + { + "date": "2026-01-01", + "conversations": 45, + "messages": 567, + "newCustomers": 12 + } + ], + "topKeywords": [ + { "keyword": "giá cả", "count": 234 }, + { "keyword": "giao hàng", "count": 189 } + ], + "rulePerformance": [ + { + "ruleId": "rule-001", + "ruleName": "Greeting Rule", + "matchCount": 523, + "successRate": 0.95 + } + ] + } +} +``` + +--- + +### 16. Search All Messages + +**EN**: Search across all conversations (admin only). + +**VI**: Tìm kiếm trong tất cả hội thoại (chỉ admin). + +```http +GET /api/v1/zalo/admin/messages?search=đơn hàng&skip=0&take=50 +Authorization: Bearer +``` + +#### Query Parameters +| Parameter | Type | Description | +|-----------|------|-------------| +| `search` | string | Full-text search | +| `fromDate` | date | Filter by date | +| `toDate` | date | Filter by date | +| `isFromBot` | bool | Filter bot/customer messages | + +#### Response +```json +{ + "success": true, + "data": { + "messages": [ + { + "id": "msg-001", + "conversationId": "conv-001", + "content": "Đơn hàng của tôi đâu rồi?", + "sentAt": "2026-01-18T10:00:00Z", + "customer": { + "name": "Nguyễn Văn A", + "zaloUserId": "123456" + } + } + ], + "totalCount": 45 + }, + "pagination": { ... } +} +``` + +--- + +### 17. Broadcast Message + +**EN**: Send broadcast message to customer segments. + +**VI**: Gửi tin nhắn quảng bá đến phân khúc khách hàng. + +```http +POST /api/v1/zalo/admin/broadcast +Authorization: Bearer +Content-Type: application/json +``` + +#### Request Body +```json +{ + "targetSegments": ["vip", "active"], + "message": { + "type": "text", + "content": "🎉 Khuyến mãi đặc biệt cho khách hàng VIP!" + }, + "scheduleAt": "2026-01-20T10:00:00Z" // Optional +} +``` + +#### Response +```json +{ + "success": true, + "data": { + "broadcastId": "broadcast-001", + "targetCustomerCount": 1234, + "scheduledAt": "2026-01-20T10:00:00Z", + "status": "scheduled" + } +} +``` + +--- + +## Common DTOs + +### ApiResponse +```csharp +public class ApiResponse +{ + public bool Success { get; set; } + public T? Data { get; set; } + public string? Error { get; set; } + public PaginationInfo? Pagination { get; set; } +} +``` + +### PaginationInfo +```csharp +public record PaginationInfo( + int Page, + int Limit, + int Total, + int TotalPages); +``` + +### Enums + +```csharp +public enum ConversationStatus +{ + Active, + Closed +} + +public enum MessageType +{ + Text, + Image, + Link, + Sticker, + Audio, + Template +} + +public enum MessageDirection +{ + Incoming, // From customer + Outgoing // To customer +} + +public enum CustomerSegment +{ + New, + Regular, + Active, + VIP +} + +public enum RuleType +{ + Keyword, + Regex, + Intent +} +``` + +--- + +## Error Responses + +### Standard Error Format +```json +{ + "success": false, + "error": "Conversation not found", + "details": { + "code": "CONVERSATION_NOT_FOUND", + "conversationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" + } +} +``` + +### Common HTTP Status Codes + +| Code | Meaning | When to Use | +|------|---------|-------------| +| `200` | OK | Successful GET, PUT, POST (non-creation) | +| `201` | Created | Successful POST (resource created) | +| `204` | No Content | Successful DELETE | +| `400` | Bad Request | Invalid request body/parameters | +| `401` | Unauthorized | Missing or invalid auth token | +| `403` | Forbidden | Insufficient permissions | +| `404` | Not Found | Resource doesn't exist | +| `409` | Conflict | Duplicate resource | +| `422` | Unprocessable Entity | Business logic error (e.g., closed conversation) | +| `500` | Internal Server Error | Unexpected server error | +| `503` | Service Unavailable | Zalo API down, database unavailable | + +--- + +## Swagger Documentation + +### Controller Annotations + +```csharp +[ApiController] +[ApiVersion("1.0")] +[Route("api/v{version:apiVersion}/zalo/conversations")] +[SwaggerTag("Conversation Management - View and manage customer conversations")] +public class ConversationsController : ControllerBase +{ + /// + /// EN: Get list of conversations. + /// VI: Lấy danh sách hội thoại. + /// + [HttpGet] + [Authorize] + [SwaggerOperation(Summary = "Get conversations list")] + [SwaggerResponse(200, "Conversations retrieved successfully")] + [SwaggerResponse(401, "Unauthorized")] + public async Task>> GetConversations( + [FromQuery] int skip = 0, + [FromQuery] int take = 20, + CancellationToken ct = default) + { + // Implementation + } +} +``` + +--- + +**Document Version**: 1.0 +**Last Updated**: 2026-01-18 +**Author**: GoodGo Platform Team diff --git a/services/mkt-zalo-service-net/docs/DATABASE_SCHEMA.md b/services/mkt-zalo-service-net/docs/DATABASE_SCHEMA.md new file mode 100644 index 00000000..a941d4f6 --- /dev/null +++ b/services/mkt-zalo-service-net/docs/DATABASE_SCHEMA.md @@ -0,0 +1,562 @@ +# Database Schema Design + +**EN**: Database schema design for MKT Zalo Service including tables, relationships, indexes, and migration strategy. + +**VI**: Thiết kế schema cơ sở dữ liệu cho Dịch vụ MKT Zalo bao gồm bảng, mối quan hệ, indexes và chiến lược migration. + +--- + +## Table of Contents / Mục Lục + +1. [Schema Overview](#schema-overview) +2. [Tables](#tables) +3. [Relationships](#relationships) +4. [Indexes](#indexes) +5. [Migrations Strategy](#migrations-strategy) + +--- + +## Schema Overview / Tổng Quan Schema + +```mermaid +erDiagram + ZaloCustomers ||--o{ Conversations : has + Conversations ||--o{ Messages : contains + Conversations }o--|| ZaloCustomers : belongs_to + ZaloCustomers ||--o{ CustomerTags : has + ChatbotRules ||--o{ RuleConditions : contains + ChatbotRules ||--|| RuleActions : has + MessageTemplates ||--o{ TemplateParameters : has + + ZaloCustomers { + uuid Id PK + string ZaloUserId UK + string DisplayName + string AvatarUrl + string PhoneNumber + string Email + int Segment + datetime FirstInteractionAt + datetime LastInteractionAt + datetime CreatedAt + datetime UpdatedAt + } + + CustomerTags { + uuid Id PK + uuid CustomerId FK + string TagName + datetime CreatedAt + } + + Conversations { + uuid Id PK + uuid CustomerId FK + string ZaloUserId + int Status + datetime StartedAt + datetime EndedAt + datetime CreatedAt + datetime UpdatedAt + } + + Messages { + uuid Id PK + uuid ConversationId FK + int Type + string Content + int Direction + bool IsFromBot + datetime SentAt + string ZaloMessageId + } + + ChatbotRules { + uuid Id PK + string Name + int Type + int Priority + bool IsActive + int MatchCount + datetime LastMatchedAt + datetime CreatedAt + datetime UpdatedAt + } + + RuleConditions { + uuid Id PK + uuid RuleId FK + string Field + string Operator + string Value + } + + RuleActions { + uuid Id PK + uuid RuleId FK + int ActionType + string ResponseText + string TemplateId + } + + MessageTemplates { + uuid Id PK + string ZaloTemplateId UK + string Name + string Content + int Status + datetime CreatedAt + datetime UpdatedAt + } + + TemplateParameters { + uuid Id PK + uuid TemplateId FK + string ParameterName + int ParameterType + bool IsRequired + } +``` + +--- + +## Tables / Các Bảng + +### 1. ZaloCustomers + +**EN**: Stores Zalo customer profile and CRM data. + +**VI**: Lưu trữ hồ sơ khách hàng Zalo và dữ liệu CRM. + +```sql +CREATE TABLE "ZaloCustomers" ( + "Id" UUID PRIMARY KEY DEFAULT gen_random_uuid(), + "ZaloUserId" VARCHAR(50) NOT NULL UNIQUE, -- From Zalo OA + "DisplayName" VARCHAR(255) NOT NULL, + "AvatarUrl" VARCHAR(500), + "PhoneNumber" VARCHAR(20), + "Email" VARCHAR(255), + "Segment" INT NOT NULL DEFAULT 0, -- 0=New, 1=Regular, 2=Active, 3=VIP + "FirstInteractionAt" TIMESTAMPTZ NOT NULL, + "LastInteractionAt" TIMESTAMPTZ NOT NULL, + "CreatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(), + "UpdatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +-- Indexesfor fast lookup +CREATE INDEX "IX_ZaloCustomers_ZaloUserId" ON "ZaloCustomers" ("ZaloUserId"); +CREATE INDEX "IX_ZaloCustomers_Segment" ON "ZaloCustomers" ("Segment"); +CREATE INDEX "IX_ZaloCustomers_LastInteractionAt" ON "ZaloCustomers" ("LastInteractionAt" DESC); +``` + +**Columns:** +- `Id`: Primary key (GUID) +- `ZaloUserId`: Unique ID from Zalo Official Account +- `DisplayName`: Customer's display name +- `AvatarUrl`: Avatar image URL +- `PhoneNumber`: Contact phone (nullable) +- `Email`: Contact email (nullable) +- `Segment`: Customer segment (0=New, 1=Regular, 2=Active, 3=VIP) +- `FirstInteractionAt`: First conversation timestamp +- `LastInteractionAt`: Most recent conversation timestamp + +--- + +### 2. CustomerTags + +**EN**: Many-to-many tags for customer segmentation and filtering. + +**VI**: Tags nhiều-nhiều cho phân khúc và lọc khách hàng. + +```sql +CREATE TABLE "CustomerTags" ( + "Id" UUID PRIMARY KEY DEFAULT gen_random_uuid(), + "CustomerId" UUID NOT NULL REFERENCES "ZaloCustomers"("Id") ON DELETE CASCADE, + "TagName" VARCHAR(50) NOT NULL, + "CreatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX "IX_CustomerTags_CustomerId" ON "CustomerTags" ("CustomerId"); +CREATE INDEX "IX_CustomerTags_TagName" ON "CustomerTags" ("TagName"); +CREATE UNIQUE INDEX "UX_CustomerTags_CustomerId_TagName" ON "CustomerTags" ("CustomerId", "TagName"); +``` + +--- + +### 3. Conversations + +**EN**: Tracks conversation sessions between customers and the chatbot. + +**VI**: Theo dõi phiên hội thoại giữa khách hàng và chatbot. + +```sql +CREATE TABLE "Conversations" ( + "Id" UUID PRIMARY KEY DEFAULT gen_random_uuid(), + "CustomerId" UUID NOT NULL REFERENCES "ZaloCustomers"("Id") ON DELETE CASCADE, + "ZaloUserId" VARCHAR(50) NOT NULL, -- Denormalized for quick access + "Status" INT NOT NULL DEFAULT 0, -- 0=Active, 1=Closed + "StartedAt" TIMESTAMPTZ NOT NULL, + "EndedAt" TIMESTAMPTZ, + "CreatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(), + "UpdatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX "IX_Conversations_CustomerId" ON "Conversations" ("CustomerId"); +CREATE INDEX "IX_Conversations_Status_StartedAt" ON "Conversations" ("Status", "StartedAt" DESC); +CREATE INDEX "IX_Conversations_ZaloUserId" ON "Conversations" ("ZaloUserId"); +``` + +--- + +### 4. Messages + +**EN**: Stores all messages within conversations (customer and bot messages). + +**VI**: Lưu trữ tất cả tin nhắn trong hội thoại (tin khách hàng và bot). + +```sql +CREATE TABLE "Messages" ( + "Id" UUID PRIMARY KEY DEFAULT gen_random_uuid(), + "ConversationId" UUID NOT NULL REFERENCES "Conversations"("Id") ON DELETE CASCADE, + "Type" INT NOT NULL, -- 0=Text, 1=Image, 2=Link, 3=Sticker, 4=Audio, 5=Template + "Content" TEXT NOT NULL, + "Direction" INT NOT NULL, -- 0=Incoming, 1=Outgoing + "IsFromBot" BOOLEAN NOT NULL DEFAULT FALSE, + "SentAt" TIMESTAMPTZ NOT NULL, + "ZaloMessageId" VARCHAR(100), -- Zalo's message ID for tracking + "CreatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX "IX_Messages_ConversationId_SentAt" ON "Messages" ("ConversationId", "SentAt" DESC); +CREATE INDEX "IX_Messages_SentAt" ON "Messages" ("SentAt" DESC); +CREATE INDEX "IX_Messages_ZaloMessageId" ON "Messages" ("ZaloMessageId") WHERE "ZaloMessageId" IS NOT NULL; + +-- Full-text search index for message content +CREATE INDEX "IX_Messages_Content_FullText" ON "Messages" USING GIN (to_tsvector('english', "Content")); +``` + +**Columns:** +- `Type`: 0=Text, 1=Image, 2=Link, 3=Sticker, 4=Audio, 5=Template +- `Direction`: 0=Incoming (from customer), 1=Outgoing (to customer) +- `IsFromBot`: TRUE if automated, FALSE if manual response +- `ZaloMessageId`: Tracking ID from Zalo API response + +--- + +### 5. ChatbotRules + +**EN**: Automation rules for rule-based chatbot engine. + +**VI**: Quy tắc tự động hóa cho engine chatbot dựa trên quy tắc. + +```sql +CREATE TABLE "ChatbotRules" ( + "Id" UUID PRIMARY KEY DEFAULT gen_random_uuid(), + "Name" VARCHAR(255) NOT NULL, + "Type" INT NOT NULL, -- 0=Keyword, 1=Regex, 2=Intent + "Priority" INT NOT NULL DEFAULT 50, -- Higher = evaluated first + "IsActive" BOOLEAN NOT NULL DEFAULT TRUE, + "MatchCount" INT NOT NULL DEFAULT 0, + "LastMatchedAt" TIMESTAMPTZ, + "CreatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(), + "UpdatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX "IX_ChatbotRules_IsActive_Priority" ON "ChatbotRules" ("IsActive", "Priority" DESC); +CREATE INDEX "IX_ChatbotRules_Type" ON "ChatbotRules" ("Type"); +``` + +--- + +### 6. RuleConditions + +**EN**: Conditions for chatbot rule matching (1-to-many with ChatbotRules). + +**VI**: Điều kiện khớp quy tắc chatbot (1-nhiều với ChatbotRules). + +```sql +CREATE TABLE "RuleConditions" ( + "Id" UUID PRIMARY KEY DEFAULT gen_random_uuid(), + "RuleId" UUID NOT NULL REFERENCES "ChatbotRules"("Id") ON DELETE CASCADE, + "Field" VARCHAR(50) NOT NULL, -- e.g., "message_text", "customer_segment" + "Operator" VARCHAR(50) NOT NULL, -- e.g., "contains", "equals", "regex" + "Value" TEXT NOT NULL, + "CreatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX "IX_RuleConditions_RuleId" ON "RuleConditions" ("RuleId"); +``` + +--- + +### 7. RuleActions + +**EN**: Actions to execute when a chatbot rule matches (1-to-1 with ChatbotRules). + +**VI**: Hành động thực thi khi quy tắc chatbot khớp (1-1 với ChatbotRules). + +```sql +CREATE TABLE "RuleActions" ( + "Id" UUID PRIMARY KEY DEFAULT gen_random_uuid(), + "RuleId" UUID NOT NULL UNIQUE REFERENCES "ChatbotRules"("Id") ON DELETE CASCADE, + "ActionType" INT NOT NULL, -- 0=SendText, 1=SendTemplate, 2=ForwardToHuman + "ResponseText" TEXT, + "TemplateId" UUID, -- Reference to MessageTemplates (nullable) + "CreatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX "IX_RuleActions_RuleId" ON "RuleActions" ("RuleId"); +``` + +--- + +### 8. MessageTemplates + +**EN**: Approved ZNS (Zalo Notification Service) templates. + +**VI**: Templates ZNS (Zalo Notification Service) đã duyệt. + +```sql +CREATE TABLE "MessageTemplates" ( + "Id" UUID PRIMARY KEY DEFAULT gen_random_uuid(), + "ZaloTemplateId" VARCHAR(50) NOT NULL UNIQUE, -- Zalo's template ID + "Name" VARCHAR(255) NOT NULL, + "Content" TEXT NOT NULL, + "Status" INT NOT NULL DEFAULT 0, -- 0=Pending, 1=Approved, 2=Rejected + "CreatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(), + "UpdatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX "IX_MessageTemplates_ZaloTemplateId" ON "MessageTemplates" ("ZaloTemplateId"); +CREATE INDEX "IX_MessageTemplates_Status" ON "MessageTemplates" ("Status"); +``` + +--- + +### 9. TemplateParameters + +**EN**: Parameters for message templates (1-to-many with MessageTemplates). + +**VI**: Tham số cho message templates (1-nhiều với MessageTemplates). + +```sql +CREATE TABLE "TemplateParameters" ( + "Id" UUID PRIMARY KEY DEFAULT gen_random_uuid(), + "TemplateId" UUID NOT NULL REFERENCES "MessageTemplates"("Id") ON DELETE CASCADE, + "ParameterName" VARCHAR(100) NOT NULL, + "ParameterType" INT NOT NULL, -- 0=String, 1=Number, 2=Date + "IsRequired" BOOLEAN NOT NULL DEFAULT TRUE, + "CreatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX "IX_TemplateParameters_TemplateId" ON "TemplateParameters" ("TemplateId"); +``` + +--- + +## Relationships / Mối Quan Hệ + +``` +ZaloCustomers (1) ──── (M) CustomerTags +ZaloCustomers (1) ──── (M) Conversations +Conversations (1) ──── (M) Messages +ChatbotRules (1) ──── (M) RuleConditions +ChatbotRules (1) ──── (1) RuleActions +MessageTemplates (1) ──── (M) TemplateParameters +``` + +--- + +## Indexes / Chỉ Mục + +### Performance-Critical Indexes + +| Table | Index | Purpose | +|-------|-------|---------| +| `ZaloCustomers` | `IX_ZaloCustomers_ZaloUserId` | Fast lookup by Zalo user ID (webhook processing) | +| `Conversations` | `IX_Conversations_Status_StartedAt` | List active/recent conversations | +| `Messages` | `IX_Messages_ConversationId_SentAt` | Get conversation history (descending) | +| `Messages` | `IX_Messages_Content_FullText` | Full-text search for admin search API | +| `ChatbotRules` | `IX_ChatbotRules_IsActive_Priority` | Fast rule evaluation (ordered by priority) | + +### Unique Constraints + +- `ZaloCustomers.ZaloUserId` - Prevent duplicate customers +- `MessageTemplates.ZaloTemplateId` - One template per Zalo ID +- `CustomerTags (CustomerId, TagName)` - No duplicate tags per customer + +--- + +## Migrations Strategy / Chiến Lược Migration + +### Initial Migration (`20260118_InitialSchema`) + +```bash +dotnet ef migrations add InitialSchema \ + --project src/MktZaloService.Infrastructure \ + --startup-project src/MktZaloService.API +``` + +**Includes:** +1. All 9 tables +2. All indexes +3. Foreign key constraints +4. Default values + +### Seed Data Migration (`20260118_SeedDefaultRules`) + +**EN**: Seed common chatbot rules for Vietnamese greetings and FAQs. + +**VI**: Seed quy tắc chatbot phổ biến cho lời chào và FAQ tiếng Việt. + +```sql +INSERT INTO "ChatbotRules" ("Id", "Name", "Type", "Priority", "IsActive") +VALUES + (gen_random_uuid(), 'Greeting Rule', 0, 100, TRUE), + (gen_random_uuid(), 'Pricing Inquiry', 0, 90, TRUE), + (gen_random_uuid(), 'Store Hours', 0, 90, TRUE); + +-- Conditions and actions... +``` + +### Migration Workflow + +```bash +# 1. Create migration +dotnet ef migrations add MigrationName \ + --project src/MktZaloService.Infrastructure + +# 2. Review migration (check Up/Down methods) + +# 3. Apply to local database +dotnet ef database update \ + --project src/MktZaloService.Infrastructure + +# 4. Test rollback +dotnet ef database update PreviousMigration \ + --project src/MktZaloService.Infrastructure + +# 5. Deploy to production +# (Migrations are applied automatically on service startup) +``` + +--- + +## EF Core Configuration Examples + +### Conversation Entity Configuration + +```csharp +public class ConversationEntityConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Conversations"); + + builder.HasKey(c => c.Id); + + builder.Property(c => c.ZaloUserId) + .IsRequired() + .HasMaxLength(50); + + builder.Property(c => c.Status) + .HasConversion(); // Enum to int + + builder.HasMany(c => c.Messages) + .WithOne() + .HasForeignKey("ConversationId") + .OnDelete(DeleteBehavior.Cascade); + + builder.HasIndex(c => new { c.Status, c.StartedAt }) + .HasDatabaseName("IX_Conversations_Status_StartedAt"); + } +} +``` + +### Message Entity Configuration + +```csharp +public class MessageEntityConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Messages"); + + builder.HasKey(m => m.Id); + + builder.Property(m => m.Type) + .HasConversion(); + + builder.Property(m => m.Direction) + .HasConversion(); + + builder.Property(m => m.Content) + .IsRequired(); + + builder.HasIndex(m => new { m.ConversationId, m.SentAt }) + .HasDatabaseName("IX_Messages_ConversationId_SentAt"); + } +} +``` + +--- + +## Database Statistics / Thống Kê Cơ Sở Dữ Liệu + +### Expected Data Volume (6 months) + +| Table | Est. Rows | Growth Rate | +|-------|-----------|-------------| +| `ZaloCustomers` | 10,000 | +500/day | +| `Conversations` | 50,000 | +2,000/day | +| `Messages` | 750,000 | +30,000/day | +| `ChatbotRules` | 50 | +1/week | +| `MessageTemplates` | 20 | +2/month | + +### Storage Estimates + +- **Messages table**: ~100MB per 100K messages +- **Total DB size (6 months)**: ~2GB +- **Recommended instance**: PostgreSQL 15+ with 4GB RAM + +--- + +## Backup & Maintenance / Sao Lưu & Bảo Trì + +### Backup Strategy + +```bash +# Daily automated backups (Neon PostgreSQL) +- Full backup: Daily at 02:00 UTC +- Retention: 30 days +- Point-in-time recovery: Last 7 days +``` + +### Maintenance Tasks + +```sql +-- Monthly vacuum analyze (performance) +VACUUM ANALYZE "Messages"; +VACUUM ANALYZE "Conversations"; + +-- Reindex if needed +REINDEX TABLE "Messages"; +``` + +### Archival Strategy + +```sql +-- Archive conversations older than 1 year +INSERT INTO "ConversationsArchive" +SELECT * FROM "Conversations" +WHERE "StartedAt" < NOW() - INTERVAL '1 year'; + +DELETE FROM "Conversations" +WHERE "StartedAt" < NOW() - INTERVAL '1 year'; +``` + +--- + +**Document Version**: 1.0 +**Last Updated**: 2026-01-18 +**Author**: GoodGo Platform Team diff --git a/services/mkt-zalo-service-net/docs/DOMAIN_MODELS.md b/services/mkt-zalo-service-net/docs/DOMAIN_MODELS.md new file mode 100644 index 00000000..219e139e --- /dev/null +++ b/services/mkt-zalo-service-net/docs/DOMAIN_MODELS.md @@ -0,0 +1,733 @@ +# Domain Models Documentation + +**EN**: Detailed documentation of domain entities, aggregates, value objects, and domain events for MKT Zalo Service. + +**VI**: Tài liệu chi tiết về domain entities, aggregates, value objects và domain events cho Dịch vụ MKT Zalo. + +--- + +## Table of Contents / Mục Lục + +1. [Domain-Driven Design Principles](#ddd-principles) +2. [Aggregates](#aggregates) +3. [Entities](#entities) +4. [Value Objects](#value-objects) +5. [Domain Events](#domain-events) +6. [Enumerations](#enumerations) + +--- + +## DDD Principles / Nguyên Tắc DDD + +### Aggregate Design Rules / Quy Tắc Thiết Kế Aggregate + +1. **One Repository Per Aggregate Root** / Một Repository cho mỗi Aggregate Root +2. **Reference Other Aggregates by ID** / Tham chiếu Aggregates khác qua ID +3. **Enforce Business Rules Within Aggregate** / Thực thi Business Rules trong Aggregate +4. **Keep Aggregates Small** / Giữ Aggregates nhỏ gọn + +--- + +## Aggregates + +### 1. Conversation Aggregate + +**EN**: Manages conversation lifecycle and messages between customer and chatbot. + +**VI**: Quản lý vòng đời hội thoại và tin nhắn giữa khách hàng và chatbot. + +```csharp +/// +/// EN: Conversation aggregate root. +/// VI: Aggregate root Conversation. +/// +public class Conversation : Entity, IAggregateRoot +{ + private readonly List _messages = new(); + + // EN: Properties / VI: Thuộc tính + public string ZaloUserId { get; private set; } + public Guid CustomerId { get; private set; } + public ConversationStatus Status { get; private set; } + public DateTime StartedAt { get; private set; } + public DateTime? EndedAt { get; private set; } + public IReadOnlyCollection Messages => _messages.AsReadOnly(); + + // EN: Private constructor for EF Core + // VI: Constructor private cho EF Core + private Conversation() { } + + // EN: Public factory method + // VI: Factory method public + public Conversation(string zaloUserId, Guid customerId) + { + Id = Guid.NewGuid(); + ZaloUserId = zaloUserId ?? throw new ArgumentNullException(nameof(zaloUserId)); + CustomerId = customerId; + Status = ConversationStatus.Active; + StartedAt = DateTime.UtcNow; + + AddDomainEvent(new ConversationStartedDomainEvent(Id, zaloUserId, customerId)); + } + + // EN: Business logic methods / VI: Phương thức business logic + public void AddMessage(MessageType type, string content, MessageDirection direction, bool isFromBot) + { + // EN: Business rule: Cannot add messages to closed conversations + // VI: Quy tắc: Không thể thêm tin nhắn vào hội thoại đã đóng + if (Status == ConversationStatus.Closed) + throw new ZaloDomainException("Cannot add message to closed conversation"); + + if (string.IsNullOrWhiteSpace(content)) + throw new ArgumentException("Message content cannot be empty", nameof(content)); + + if (content.Length > 2000) + throw new ArgumentException("Message content exceeds 2000 characters", nameof(content)); + + var message = new Message(type, content, direction, isFromBot); + _messages.Add(message); + + AddDomainEvent(new MessageReceivedDomainEvent(Id, message.Id, content, direction)); + } + + public void Close() + { + // EN: Business rule: Already closed conversations remain closed + // VI: Quy tắc: Hội thoại đã đóng vẫn giữ trạng thái đóng + if (Status == ConversationStatus.Closed) + return; + + Status = ConversationStatus.Closed; + EndedAt = DateTime.UtcNow; + + AddDomainEvent(new ConversationClosedDomainEvent(Id)); + } + + public void Reopen() + { + // EN: Business rule: Can only reopen closed conversations + // VI: Quy tắc: Chỉ có thể mở lại hội thoại đã đóng + if (Status != ConversationStatus.Closed) + throw new ZaloDomainException("Can only reopen closed conversations"); + + Status = ConversationStatus.Active; + EndedAt = null; + } +} +``` + +**Invariants / Bất Biến:** +- A conversation must have a ZaloUserId and CustomerId +- Messages cannot be added to closed conversations +- Conversation status must be either Active or Closed + +--- + +### 2. ZaloCustomer Aggregate + +**EN**: Manages customer profile, tags, segmentation, and interaction history. + +**VI**: Quản lý hồ sơ khách hàng, tags, phân khúc và lịch sử tương tác. + +```csharp +/// +/// EN: Zalo customer aggregate root. +/// VI: Aggregate root ZaloCustomer. +/// +public class ZaloCustomer : Entity, IAggregateRoot +{ + private readonly List _tags = new(); + + public string ZaloUserId { get; private set; } + public CustomerProfile Profile { get; private set; } + public CustomerSegment Segment { get; private set; } + public DateTime FirstInteractionAt { get; private set; } + public DateTime LastInteractionAt { get; private set; } + public IReadOnlyCollection Tags => _tags.AsReadOnly(); + + private ZaloCustomer() { } + + public ZaloCustomer(string zaloUserId, string displayName, string avatarUrl) + { + Id = Guid.NewGuid(); + ZaloUserId = zaloUserId ?? throw new ArgumentNullException(nameof(zaloUserId)); + Profile = new CustomerProfile(displayName, avatarUrl, null, null); + Segment = CustomerSegment.New; + FirstInteractionAt = DateTime.UtcNow; + LastInteractionAt = DateTime.UtcNow; + + AddDomainEvent(new CustomerCreatedDomainEvent(Id, zaloUserId)); + } + + public void UpdateProfile(string displayName, string avatarUrl, string? phoneNumber = null, string? email = null) + { + // EN: Business rule: Display name is required + // VI: Quy tắc: Display name bắt buộc + if (string.IsNullOrWhiteSpace(displayName)) + throw new ArgumentException("Display name cannot be empty", nameof(displayName)); + + Profile = new CustomerProfile(displayName, avatarUrl, phoneNumber, email); + + AddDomainEvent(new CustomerProfileUpdatedDomainEvent(Id, ZaloUserId)); + } + + public void AddTag(string tagName) + { + // EN: Business rule: No duplicate tags + // VI: Quy tắc: Không trùng tags + if (string.IsNullOrWhiteSpace(tagName)) + throw new ArgumentException("Tag name cannot be empty", nameof(tagName)); + + if (_tags.Any(t => t.Name.Equals(tagName, StringComparison.OrdinalIgnoreCase))) + return; // Already exists + + _tags.Add(new Tag(tagName)); + } + + public void RemoveTag(string tagName) + { + var tag = _tags.FirstOrDefault(t => t.Name.Equals(tagName, StringComparison.OrdinalIgnoreCase)); + if (tag != null) + _tags.Remove(tag); + } + + public void UpdateLastInteraction() + { + LastInteractionAt = DateTime.UtcNow; + } + + public void UpdateSegment(int conversationCount, int messageCount) + { + // EN: Auto-segment based on engagement + // VI: Tự động phân khúc dựa trên tương tác + Segment = (conversationCount, messageCount) switch + { + (> 50, > 500) => CustomerSegment.VIP, + (> 20, > 200) => CustomerSegment.Active, + (> 5, > 50) => CustomerSegment.Regular, + _ => CustomerSegment.New + }; + } +} +``` + +**Invariants:** +- ZaloUserId must be unique +- DisplayName cannot be empty +- Last interaction must be >= first interaction + +--- + +### 3. ChatbotRule Aggregate + +**EN**: Defines automation rules for rule-based chatbot responses. + +**VI**: Định nghĩa quy tắc tự động cho phản hồi chatbot dựa trên quy tắc. + +```csharp +/// +/// EN: Chatbot rule aggregate root. +/// VI: Aggregate root ChatbotRule. +/// +public class ChatbotRule : Entity, IAggregateRoot +{ + private readonly List _conditions = new(); + + public string Name { get; private set; } + public RuleType Type { get; private set; } + public IReadOnlyCollection Conditions => _conditions.AsReadOnly(); + public RuleAction Action { get; private set; } + public int Priority { get; private set; } + public bool IsActive { get; private set; } + public int MatchCount { get; private set; } + public DateTime? LastMatchedAt { get; private set; } + + private ChatbotRule() { } + + public ChatbotRule(string name, RuleType type, int priority, RuleAction action) + { + Id = Guid.NewGuid(); + Name = name ?? throw new ArgumentNullException(nameof(name)); + Type = type; + Action = action ?? throw new ArgumentNullException(nameof(action)); + Priority = priority; + IsActive = true; + MatchCount = 0; + } + + public void AddCondition(string field, string operatorType, string value) + { + // EN: Business rule: At least one condition required + // VI: Quy tắc: Ít nhất một điều kiện được yêu cầu + var condition = new RuleCondition(field, operatorType, value); + _conditions.Add(condition); + } + + public bool Evaluate(string userMessage, CustomerSegment? customerSegment = null) + { + if (!IsActive) + return false; + + // EN: Evaluate based on rule type + // VI: Đánh giá dựa trên loại quy tắc + return Type switch + { + RuleType.Keyword => EvaluateKeywordRule(userMessage), + RuleType.Regex => EvaluateRegexRule(userMessage), + RuleType.Intent => EvaluateIntentRule(userMessage), + _ => false + }; + } + + private bool EvaluateKeywordRule(string userMessage) + { + return _conditions.Any(c => + userMessage.Contains(c.Value, StringComparison.OrdinalIgnoreCase)); + } + + private bool EvaluateRegexRule(string userMessage) + { + return _conditions.Any(c => Regex.IsMatch(userMessage, c.Value)); + } + + private bool EvaluateIntentRule(string userMessage) + { + // EN: Intent classification would use NLP/ML model + // VI: Phân loại intent sử dụng mô hình NLP/ML + return false; // Placeholder + } + + public void RecordMatch() + { + MatchCount++; + LastMatchedAt = DateTime.UtcNow; + } + + public void Activate() => IsActive = true; + public void Deactivate() => IsActive = false; + + public void UpdatePriority(int newPriority) + { + // EN: Business rule: Priority must be 0-100 + // VI: Quy tắc: Priority phải từ 0-100 + if (newPriority < 0 || newPriority > 100) + throw new ArgumentException("Priority must be between 0 and 100", nameof(newPriority)); + + Priority = newPriority; + } +} +``` + +**Invariants:** +- Rule must have at least one condition +- Priority must be 0-100 +- Action must be defined + +--- + +### 4. MessageTemplate Aggregate + +**EN**: Manages approved Zalo Notification Service (ZNS) templates. + +**VI**: Quản lý templates Zalo Notification Service (ZNS) đã duyệt. + +```csharp +/// +/// EN: Message template aggregate root. +/// VI: Aggregate root MessageTemplate. +/// +public class MessageTemplate : Entity, IAggregateRoot +{ + private readonly List _parameters = new(); + + public string ZaloTemplateId { get; private set; } + public string Name { get; private set; } + public string Content { get; private set; } + public TemplateStatus Status { get; private set; } + public IReadOnlyCollection Parameters => _parameters.AsReadOnly(); + + private MessageTemplate() { } + + public MessageTemplate(string zaloTemplateId, string name, string content) + { + Id = Guid.NewGuid(); + ZaloTemplateId = zaloTemplateId ?? throw new ArgumentNullException(nameof(zaloTemplateId)); + Name = name ?? throw new ArgumentNullException(nameof(name)); + Content = content ?? throw new ArgumentNullException(nameof(content)); + Status = TemplateStatus.Pending; + } + + public void AddParameter(string parameterName, ParameterType type, bool isRequired) + { + var param = new TemplateParameter(parameterName, type, isRequired); + _parameters.Add(param); + } + + public void Approve() => Status = TemplateStatus.Approved; + public void Reject() => Status = TemplateStatus.Rejected; + + public Dictionary ValidateParameters(Dictionary providedParams) + { + // EN: Business rule: All required parameters must be provided + // VI: Quy tắc: Tất cả parameters bắt buộc phải được cung cấp + var missingParams = _parameters + .Where(p => p.IsRequired && !providedParams.ContainsKey(p.Name)) + .Select(p => p.Name) + .ToList(); + + if (missingParams.Any()) + throw new ZaloDomainException($"Missing required parameters: {string.Join(", ", missingParams)}"); + + return providedParams; + } +} +``` + +--- + +## Entities / Thực Thể + +### Message Entity + +```csharp +/// +/// EN: Message entity within Conversation aggregate. +/// VI: Entity Message trong aggregate Conversation. +/// +public class Message : Entity +{ + public MessageType Type { get; private set; } + public string Content { get; private set; } + public MessageDirection Direction { get; private set; } + public bool IsFromBot { get; private set; } + public DateTime SentAt { get; private set; } + public string? ZaloMessageId { get; private set; } + + private Message() { } + + public Message(MessageType type, string content, MessageDirection direction, bool isFromBot) + { + Id = Guid.NewGuid(); + Type = type; + Content = content ?? throw new ArgumentNullException(nameof(content)); + Direction = direction; + IsFromBot = isFromBot; + SentAt = DateTime.UtcNow; + } + + public void SetZaloMessageId(string zaloMessageId) + { + ZaloMessageId = zaloMessageId; + } +} +``` + +### Tag Entity + +```csharp +/// +/// EN: Tag entity within ZaloCustomer aggregate. +/// VI: Entity Tag trong aggregate ZaloCustomer. +/// +public class Tag : Entity +{ + public string Name { get; private set; } + public DateTime CreatedAt { get; private set; } + + private Tag() { } + + public Tag(string name) + { + Id = Guid.NewGuid(); + Name = name?.Trim() ?? throw new ArgumentNullException(nameof(name)); + CreatedAt = DateTime.UtcNow; + } +} +``` + +--- + +## Value Objects + +### CustomerProfile Value Object + +```csharp +/// +/// EN: Customer profile value object. +/// VI: Value object hồ sơ khách hàng. +/// +public class CustomerProfile : ValueObject +{ + public string DisplayName { get; } + public string AvatarUrl { get; } + public string? PhoneNumber { get; } + public string? Email { get; } + + public CustomerProfile(string displayName, string avatarUrl, string? phoneNumber, string? email) + { + DisplayName = displayName ?? throw new ArgumentNullException(nameof(displayName)); + AvatarUrl = avatarUrl ?? throw new ArgumentNullException(nameof(avatarUrl)); + PhoneNumber = phoneNumber; + Email = email; + } + + protected override IEnumerable GetEqualityComponents() + { + yield return DisplayName; + yield return AvatarUrl; + yield return PhoneNumber; + yield return Email; + } +} +``` + +### RuleCondition Value Object + +```csharp +/// +/// EN: Rule condition value object. +/// VI: Value object điều kiện quy tắc. +/// +public class RuleCondition : ValueObject +{ + public string Field { get; } + public string Operator { get; } + public string Value { get; } + + public RuleCondition(string field, string operatorType, string value) + { + Field = field ?? throw new ArgumentNullException(nameof(field)); + Operator = operatorType ?? throw new ArgumentNullException(nameof(operatorType)); + Value = value ?? throw new ArgumentNullException(nameof(value)); + } + + protected override IEnumerable GetEqualityComponents() + { + yield return Field; + yield return Operator; + yield return Value; + } +} +``` + +### RuleAction Value Object + +```csharp +/// +/// EN: Rule action value object. +/// VI: Value object hành động quy tắc. +/// +public class RuleAction : ValueObject +{ + public ActionType ActionType { get; } + public string? ResponseText { get; } + public Guid? TemplateId { get; } + + public RuleAction(ActionType actionType, string? responseText = null, Guid? templateId = null) + { + ActionType = actionType; + ResponseText = responseText; + TemplateId = templateId; + + // EN: Business rule: SendText must have ResponseText + // VI: Quy tắc: SendText phải có ResponseText + if (actionType == ActionType.SendText && string.IsNullOrWhiteSpace(responseText)) + throw new ArgumentException("SendText action requires ResponseText", nameof(responseText)); + + // EN: Business rule: SendTemplate must have TemplateId + // VI: Quy tắc: SendTemplate phải có TemplateId + if (actionType == ActionType.SendTemplate && !templateId.HasValue) + throw new ArgumentException("SendTemplate action requires TemplateId", nameof(templateId)); + } + + protected override IEnumerable GetEqualityComponents() + { + yield return ActionType; + yield return ResponseText; + yield return TemplateId; + } +} +``` + +### TemplateParameter Value Object + +```csharp +/// +/// EN: Template parameter value object. +/// VI: Value object tham số template. +/// +public class TemplateParameter : ValueObject +{ + public string Name { get; } + public ParameterType Type { get; } + public bool IsRequired { get; } + + public TemplateParameter(string name, ParameterType type, bool isRequired) + { + Name = name ?? throw new ArgumentNullException(nameof(name)); + Type = type; + IsRequired = isRequired; + } + + protected override IEnumerable GetEqualityComponents() + { + yield return Name; + yield return Type; + yield return IsRequired; + } +} +``` + +--- + +## Domain Events + +### ConversationStartedDomainEvent + +```csharp +/// +/// EN: Domain event when conversation starts. +/// VI: Domain event khi hội thoại bắt đầu. +/// +public record ConversationStartedDomainEvent : IDomainEvent +{ + public Guid Id { get; } = Guid.NewGuid(); + public DateTime OccurredOn { get; } = DateTime.UtcNow; + public Guid ConversationId { get; init; } + public string ZaloUserId { get; init; } + public Guid CustomerId { get; init; } + + public ConversationStartedDomainEvent(Guid conversationId, string zaloUserId, Guid customerId) + { + ConversationId = conversationId; + ZaloUserId = zaloUserId; + CustomerId = customerId; + } +} +``` + +### MessageReceivedDomainEvent + +```csharp +/// +/// EN: Domain event when message is received. +/// VI: Domain event khi tin nhắn được nhận. +/// +public record MessageReceivedDomainEvent : IDomainEvent +{ + public Guid Id { get; } = Guid.NewGuid(); + public DateTime OccurredOn { get; } = DateTime.UtcNow; + public Guid ConversationId { get; init; } + public Guid MessageId { get; init; } + public string Content { get; init; } + public MessageDirection Direction { get; init; } + + public MessageReceivedDomainEvent(Guid conversationId, Guid messageId, string content, MessageDirection direction) + { + ConversationId = conversationId; + MessageId = messageId; + Content = content; + Direction = direction; + } +} +``` + +### CustomerProfileUpdatedDomainEvent + +```csharp +/// +/// EN: Domain event when customer profile is updated. +/// VI: Domain event khi hồ sơ khách hàng được cập nhật. +/// +public record CustomerProfileUpdatedDomainEvent : IDomainEvent +{ + public Guid Id { get; } = Guid.NewGuid(); + public DateTime OccurredOn { get; } = DateTime.UtcNow; + public Guid CustomerId { get; init; } + public string ZaloUserId { get; init; } + + public CustomerProfileUpdatedDomainEvent(Guid customerId, string zaloUserId) + { + CustomerId = customerId; + ZaloUserId = zaloUserId; + } +} +``` + +--- + +## Enumerations / Liệt Kê + +```csharp +/// EN: Conversation status / VI: Trạng thái hội thoại +public enum ConversationStatus +{ + Active = 0, + Closed = 1 +} + +/// EN: Message type / VI: Loại tin nhắn +public enum MessageType +{ + Text = 0, + Image = 1, + Link = 2, + Sticker = 3, + Audio = 4, + Template = 5 +} + +/// EN: Message direction / VI: Hướng tin nhắn +public enum MessageDirection +{ + Incoming = 0, // From customer + Outgoing = 1 // To customer +} + +/// EN: Customer segment / VI: Phân khúc khách hàng +public enum CustomerSegment +{ + New = 0, + Regular = 1, + Active = 2, + VIP = 3 +} + +/// EN: Rule type / VI: Loại quy tắc +public enum RuleType +{ + Keyword = 0, + Regex = 1, + Intent = 2 +} + +/// EN: Action type / VI: Loại hành động +public enum ActionType +{ + SendText = 0, + SendTemplate = 1, + ForwardToHuman = 2 +} + +/// EN: Template status / VI: Trạng thái template +public enum TemplateStatus +{ + Pending = 0, + Approved = 1, + Rejected = 2 +} + +/// EN: Parameter type / VI: Loại tham số +public enum ParameterType +{ + String = 0, + Number = 1, + Date = 2 +} +``` + +--- + +**Document Version**: 1.0 +**Last Updated**: 2026-01-18 +**Author**: GoodGo Platform Team diff --git a/services/mkt-zalo-service-net/docs/INTEGRATION.md b/services/mkt-zalo-service-net/docs/INTEGRATION.md new file mode 100644 index 00000000..b88a9241 --- /dev/null +++ b/services/mkt-zalo-service-net/docs/INTEGRATION.md @@ -0,0 +1,579 @@ +# Zalo Official Account Integration Guide + +**EN**: Comprehensive integration guide for Zalo Official Account API, webhooks, authentication, and best practices. + +**VI**: Hướng dẫn tích hợp toàn diện cho Zalo Official Account API, webhooks, xác thực và best practices. + +--- + +## Table of Contents / Mục Lục + +1. [Prerequisites](#prerequisites) +2. [Zalo OA Setup](#zalo-oa-setup) +3. [Authentication & Access Token](#authentication--access-token) +4. [Webhook Configuration](#webhook-configuration) +5. [API Endpoints](#api-endpoints) +6. [Event Types](#event-types) +7. [Rate Limits](#rate-limits) +8. [Error Handling](#error-handling) +9. [Best Practices](#best-practices) + +--- + +## Prerequisites / Yêu Cầu + +### 1. Zalo Official Account (OA) + +**EN**: You must have a verified Zalo Official Account for businesses. + +**VI**: Bạn phải có Zalo Official Account đã xác minh cho doanh nghiệp. + +**Steps:** +1. Register at: https://oa.zalo.me/ +2. Complete business verification (requires business license) +3. Wait for approval (1-3 business days) + +### 2. Zalo Application + +**EN**: Create a Zalo application to get App ID and Secret Key. + +**VI**: Tạo ứng dụng Zalo để lấy App ID và Secret Key. + +**Steps:** +1. Go to: https://developers.zalo.me/ +2. Create new application +3. Link application to your Official Account +4. Note your `App ID` and `Secret Key` + +--- + +## Zalo OA Setup / Thiết Lập Zalo OA + +### Link Application to OA + +1. **Login to Zalo Developers**: https://developers.zalo.me/ +2. **Select your application** +3. **Go to "Official Account" tab** +4. **Click "Link OA"** and select your Official Account +5. **Grant permissions**: Message, User Info, Notification + +### Required Permissions + +| Permission | Purpose | +|------------|---------| +| `User Info` | Get customer profile (name, avatar) | +| `Send Message` | Send messages to customers | +| `Receive Message` | Receive webhook events | +| `ZNS` | Send Zalo Notification Service templates | + +--- + +## Authentication & Access Token + +### Get OA Access Token + +**Method 1: Via Zalo Developers Portal** (Recommended for development) + +1. Go to: https://developers.zalo.me/tools/explorer +2. Select your application and OA +3. Click "Get Access Token" +4. Copy the token (valid for 1 year) + +**Method 2: Via OAuth API** (For production) + +```http +POST https://oauth.zaloapp.com/v4/oa/access_token +Content-Type: application/x-www-form-urlencoded + +app_id={app_id} +&secret_key={secret_key} +&code={authorization_code} +``` + +Response: +```json +{ + "access_token": "your_access_token", + "refresh_token": "your_refresh_token", + "expires_in": 31536000 // 1 year +} +``` + +### Refresh Access Token + +```http +POST https://oauth.zaloapp.com/v4/oa/access_token +Content-Type: application/x-www-form-urlencoded + +app_id={app_id} +&refresh_token={refresh_token} +&grant_type=refresh_token +``` + +### Store Securely + +```bash +# Environment variable +ZALO_ACCESS_TOKEN=your_access_token_here + +# Or Azure Key Vault / AWS Secrets Manager +``` + +--- + +## Webhook Configuration / Cấu Hình Webhook + +### 1. Set Webhook URL + +**In Zalo Developers Portal:** +1. Go to your application settings +2. Navigate to "Webhooks" tab +3. Set webhook URL: `https://yourdomain.com/api/v1/zalo/webhooks` +4. Set secret key for signature verification + +### 2. Enable Events + +**Required events to enable:** +- ✅ `user_send_text` - Customer sends text message +- ✅ `user_send_image` - Customer sends image +- ✅ `user_send_link` - Customer sends link +- ✅ `user_send_sticker` - Customer sends sticker +- ✅ `user_send_audio` - Customer sends audio +- ✅ `follow` - Customer follows OA +- ✅ `unfollow` - Customer unfollows OA +- ✅ `user_click_chatnow` - Customer clicks "Chat Now" button + +### 3. Webhook Signature Verification + +**EN**: Verify webhook signature to prevent spoofing attacks. + +**VI**: Xác thực chữ ký webhook để chống tấn công giả mạo. + +```csharp +public class ZaloWebhookVerifier +{ + private readonly string _secretKey; + + public bool VerifySignature(string body, string signature) + { + using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(_secretKey)); + var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(body)); + var computed = BitConverter.ToString(hash).Replace("-", "").ToLower(); + + return signature.Equals(computed, StringComparison.OrdinalIgnoreCase); + } +} +``` + +**Webhook Request Headers:** +``` +X-Zalo-Signature: +Content-Type: application/json +``` + +### 4. Webhook Response Requirements + +**CRITICAL**: Must return `200 OK` within **2 seconds**. + +```csharp +[HttpPost("webhooks")] +public async Task ReceiveWebhook([FromBody] ZaloWebhookEvent webhook) +{ + // 1. Verify signature (FAST) + if (!_verifier.VerifySignature(RequestBody, Request.Headers["X-Zalo-Signature"])) + return Unauthorized(); + + // 2. Queue for async processing (FAST) + await _messageQueue.PublishAsync(webhook); + + // 3. Return immediately (< 2s) + return Ok(new { success = true }); +} +``` + +**DO NOT** process webhook synchronously: +- ❌ Database queries +- ❌ External API calls +- ❌ LLM processing +- ✅ Signature verification only +- ✅ Queue message +- ✅ Return 200 + +--- + +## API Endpoints / Các API Endpoints + +### Base URL +``` +https://openapi.zalo.me +``` + +### 1. Send Text Message + +```http +POST /v3.0/oa/message/cs +Authorization: access_token {your_access_token} +Content-Type: application/json + +{ + "recipient": { + "user_id": "1234567890123456789" + }, + "message": { + "text": "Xin chào! Tôi có thể giúp gì cho bạn?" + } +} +``` + +**Response:** +```json +{ + "error": 0, + "message": "Success", + "data": { + "message_id": "zalo_msg_xyz123" + } +} +``` + +### 2. Send Image Message + +```http +POST /v3.0/oa/message/cs +Authorization: access_token {your_access_token} +Content-Type: application/json + +{ + "recipient": { + "user_id": "1234567890123456789" + }, + "message": { + "attachment": { + "type": "template", + "payload": { + "template_type": "media", + "elements": [ + { + "media_type": "image", + "url": "https://example.com/image.jpg" + } + ] + } + } + } +} +``` + +### 3. Get User Profile + +```http +GET /v3.0/oa/user/detail?data={"user_id":"1234567890123456789"} +Authorization: access_token {your_access_token} +``` + +**Response:** +```json +{ + "error": 0, + "message": "Success", + "data": { + "user_id": "1234567890123456789", + "display_name": "Nguyễn Văn A", + "avatar": "https://s.zalo.me/avatar.jpg", + "user_gender": 1, // 0=Female, 1=Male, 2=Unknown + "user_id_by_app": "app_scoped_user_id" + } +} +``` + +### 4. Send ZNS Template + +```http +POST /v3.0/oa/message/template +Authorization: access_token {your_access_token} +Content-Type: application/json + +{ + "phone": "+84901234567", + "template_id": "283746", + "template_data": { + "order_id": "ORD-12345", + "total_amount": "500000" + } +} +``` + +--- + +## Event Types / Các Loại Sự Kiện + +### 1. user_send_text + +```json +{ + "app_id": "1234567890", + "event_name": "user_send_text", + "timestamp": 1705586400000, + "sender": { + "id": "1234567890123456789" + }, + "recipient": { + "id": "9876543210" + }, + "message": { + "text": "Xin chào", + "msg_id": "msg_123456" + } +} +``` + +### 2. user_send_image + +```json +{ + "app_id": "1234567890", + "event_name": "user_send_image", + "timestamp": 1705586400000, + "sender": { + "id": "1234567890123456789" + }, + "message": { + "attachments": [ + { + "type": "image", + "payload": { + "url": "https://zalo-api.zadn.vn/api/emoticon/sticker/...", + "thumbnail": "https://zalo-api.zadn.vn/api/emoticon/thumb/..." + } + } + ], + "msg_id": "msg_123457" + } +} +``` + +### 3. follow + +```json +{ + "app_id": "1234567890", + "event_name": "follow", + "timestamp": 1705586400000, + "follower": { + "id": "1234567890123456789" + }, + "oa_id": "9876543210" +} +``` + +### 4. unfollow + +```json +{ + "app_id": "1234567890", + "event_name": "unfollow", + "timestamp": 1705586400000, + "follower": { + "id": "1234567890123456789" + } +} +``` + +--- + +## Rate Limits / Giới Hạn Tốc Độ + +### API Rate Limits + +| API | Limit | Window | +|-----|-------|--------| +| Send Message (CS) | 1000 requests | Per day per user | +| Send ZNS | 10000 requests | Per day | +| Get User Profile | 5000 requests | Per day | +| Webhook Receipt | Unlimited | - | + +### Handling Rate Limits + +```csharp +public class ZaloApiClient +{ + private readonly HttpClient _httpClient; + private readonly SemaphoreSlim _rateLimiter = new(100, 100); // 100 concurrent + + public async Task SendMessageAsync(...) + { + await _rateLimiter.WaitAsync(); + try + { + // API call + var response = await _httpClient.PostAsync(...); + + if (response.StatusCode == HttpStatusCode.TooManyRequests) + { + // Wait and retry + await Task.Delay(TimeSpan.FromMinutes(1)); + return await SendMessageAsync(...); + } + + return await response.Content.ReadFromJsonAsync(); + } + finally + { + _rateLimiter.Release(); + } + } +} +``` + +--- + +## Error Handling / Xử Lý Lỗi + +### Common Error Codes + +| Error Code | Message | Resolution | +|------------|---------|------------| +| `-201` | Invalid access token | Refresh token | +| `-213` | User has blocked OA | Mark customer as inactive | +| `-214` | User hasn't interacted in 7 days | Use ZNS instead of CS message | +| `-216` | Message too long (max 2000 chars) | Split message | +| `-300` | Rate limit exceeded | Wait and retry | + +### Error Response Format + +```json +{ + "error": -201, + "message": "Invalid access token", + "data": {} +} +``` + +### Retry Strategy + +```csharp +var retryPolicy = Policy + .Handle() + .Or() + .OrResult(r => (int)r.StatusCode >= 500) + .WaitAndRetryAsync(3, retryAttempt => + TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); + +var response = await retryPolicy.ExecuteAsync(async () => +{ + return await _httpClient.PostAsync(...); +}); +``` + +--- + +## Best Practices / Thực Hành Tốt + +### 1. Webhook Processing + +✅ **DO:** +- Verify signature on every webhook +- Return 200 within 2 seconds +- Process asynchronously via message queue +- Store raw webhook events for 7 days (debugging) + +❌ **DON'T:** +- Make database queries in webhook handler +- Call external APIs synchronously +- Process LLM in webhook handler + +### 2. Message Quality + +✅ **DO:** +- Keep messages under 2000 characters +- Use ZNS for important notifications (OTP, orders) +- Provide fallback for images (text description) +- Respect customer's OA block status + +❌ **DON'T:** +- Send too many messages (spam) +- Send promotional messages without consent +- Use CS messages for users inactive >7 days + +### 3. Access Token Management + +✅ **DO:** +- Store token securely (environment variable, secrets manager) +- Set up token refresh automation (before 1 year expiry) +- Log token refresh events + +❌ **DON'T:** +- Hardcode token in source code +- Share token publicly (Git, Slack) + +### 4. Conversation Context + +✅ **DO:** +- Cache last 10 messages in Redis (for AI context) +- Load customer profile once per conversation +- Track conversation state (active/closed) + +❌ **DON'T:** +- Query full conversation history for each message +- Lose context between messages + +--- + +## Testing / Kiểm Thử + +### 1. Sandbox Environment + +Zalo provides a test OA for development: +- Register test OA at https://oa.zalo.me/ +- Use separate access token for staging + +### 2. Manual Testing + +```bash +# Send test webhook to your local service +curl -X POST http://localhost:8080/api/v1/zalo/webhooks \ + -H "Content-Type: application/json" \ + -H "X-Zalo-Signature: " \ + -d '{ + "app_id": "test123", + "event_name": "user_send_text", + "timestamp": 1705586400000, + "sender": { "id": "test_user_123" }, + "message": { "text": "Xin chào", "msg_id": "msg_001" } + }' +``` + +### 3. Integration Tests + +```csharp +[Fact] +public async Task SendMessage_ValidUser_ReturnsSuccess() +{ + // Arrange + var client = new ZaloOfficialAccountClient(_httpClient, _config, _logger); + + // Act + var result = await client.SendTextMessageAsync( + "test_user_123", + "Hello from test", + CancellationToken.None); + + // Assert + Assert.NotNull(result.MessageId); +} +``` + +--- + +## Resources / Tài Nguyên + +- **Zalo Developers**: https://developers.zalo.me/ +- **Zalo OA Docs**: https://developers.zalo.me/docs/official-account +- **API Explorer**: https://developers.zalo.me/tools/explorer +- **Zalo OA Manager**: https://oa.zalo.me/ + +--- + +**Document Version**: 1.0 +**Last Updated**: 2026-01-18 +**Author**: GoodGo Platform Team diff --git a/services/mkt-zalo-service-net/docs/SOLUTION.md b/services/mkt-zalo-service-net/docs/SOLUTION.md new file mode 100644 index 00000000..31921462 --- /dev/null +++ b/services/mkt-zalo-service-net/docs/SOLUTION.md @@ -0,0 +1,779 @@ +# MKT Zalo Service Solution Architecture + +**EN**: Comprehensive solution architecture for the Marketing Zalo Service, detailing system design, domain model, integration patterns, and technical implementation. + +**VI**: Kiến trúc giải pháp toàn diện cho Dịch vụ Marketing Zalo, chi tiết thiết kế hệ thống, mô hình domain, patterns tích hợp và triển khai kỹ thuật. + +--- + +## Table of Contents / Mục Lục + +1. [Business Context / Ngữ Cảnh Nghiệp Vụ](#business-context) +2. [System Architecture / Kiến Trúc Hệ Thống](#system-architecture) +3. [Domain Model / Mô Hình Domain](#domain-model) +4. [CQRS Commands & Queries](#cqrs-commands--queries) +5. [Integration Patterns / Mẫu Tích Hợp](#integration-patterns) +6. [Data Flow / Luồng Dữ Liệu](#data-flow) +7. [Security & Authentication / Bảo Mật](#security--authentication) +8. [Performance & Scalability / Hiệu Năng](#performance--scalability) +9. [Monitoring & Observability / Giám Sát](#monitoring--observability) + +--- + +## Business Context / Ngữ Cảnh Nghiệp Vụ + +### Problem Statement / Vấn Đề + +**EN**: Businesses need to engage with customers on Zalo, Vietnam's leading messaging platform with 80M+ users. This requires: +- Automated responses for common inquiries (24/7 availability) +- AI-powered conversations for complex customer needs +- Centralized customer data and interaction history +- Scalable messaging infrastructure for campaigns + +**VI**: Doanh nghiệp cần tương tác khách hàng trên Zalo, nền tản g nhắn tin hàng đầu Việt Nam với 80M+ người dùng. Yêu cầu: +- Phản hồi tự động cho câu hỏi thường gặp (24/7) +- Hội thoại AI cho nhu cầu phức tạp +- Dữ liệu khách hàng và lịch sử tập trung +- Hạ tầng nhắn tin mở rộng cho chiến dịch + +### Business Goals / Mục Tiêu Nghiệp Vụ + +1. **Customer Engagement / Tương Tác KH**: 90% response rate within 1 minute +2. **Automation / Tự Động Hóa**: 70% of inquiries handled without human intervention +3. **Personalization / Cá Nhân Hóa**: Context-aware responses based on customer history +4. **Scalability / Mở Rộng**: Support 10,000+ concurrent conversations + +--- + +## System Architecture / Kiến Trúc Hệ Thống + +### High-Level Architecture / Kiến Trúc Tổng Quan + +```mermaid +graph TB + ZaloOA[Zalo Official Account] + + subgraph "mkt-zalo-service-net" + WH[Webhook Handler
WebhooksController] + MQ[Message Queue
RabbitMQ] + + subgraph "Processing Engines" + RE[Rule Engine
Automation] + AI[AI Engine
LLM Based] + end + + subgraph "Domain Layer" + Conv[Conversation
Aggregate] + Cust[ZaloCustomer
Aggregate] + Rule[ChatbotRule
Aggregate] + Tmpl[MessageTemplate
Aggregate] + end + + DB[(PostgreSQL
Main DB)] + Cache[(Redis
Cache)] + + ZaloAPI[Zalo OA API Client] + LLM[LLM Provider
OpenAI/Vertex AI] + end + + ZaloOA -->|Webhook Events| WH + WH -->|Queue Message| MQ + MQ -->|Process| RE + MQ -->|Process| AI + + RE -->|Load Rules| Rule + AI -->|Call LLM| LLM + + RE -->|Update| Conv + AI -->|Update| Conv + + Conv -->|Store| DB + Cust -->|Store| DB + Rule -->|Store| DB + Tmpl -->|Store| DB + + Conv -.->|Cache Context| Cache + + RE -->|Send Response| ZaloAPI + AI -->|Send Response| ZaloAPI + ZaloAPI -->|API Call| ZaloOA +``` + +### Clean Architecture Layers / Các Tầng Clean Architecture + +``` +┌────────────────────────────────────────────────────────────────┐ +│ API Layer │ +│ Controllers → MediatR → Commands/Queries │ +│ • WebhooksController (public, no auth) │ +│ • ConversationsController (authenticated) │ +│ • CustomersController (CRM management) │ +│ • ChatbotRulesController (automation config) │ +│ • Admin/* (analytics, broadcast) │ +└────────────────────────┬───────────────────────────────────────┘ + │ +┌────────────────────────▼───────────────────────────────────────┐ +│ Application Layer │ +│ Commands: ProcessWebhookCommand, SendMessageCommand │ +│ Queries: GetConversationHistoryQuery, GetCustomerQuery │ +│ Handlers: ProcessWebhookCommandHandler (routes to engines) │ +│ Behaviors: ValidationBehavior, LoggingBehavior │ +└────────────────────────┬───────────────────────────────────────┘ + │ +┌────────────────────────▼───────────────────────────────────────┐ +│ Domain Layer │ +│ Aggregates: │ +│ • Conversation (messages, status, context) │ +│ • ZaloCustomer (profile, tags, segment) │ +│ • ChatbotRule (conditions, actions) │ +│ • MessageTemplate (ZNS templates) │ +│ │ +│ Business Rules: │ +│ • Conversation.AddMessage() - validate message type │ +│ • ZaloCustomer.UpdateProfile() - enforce data quality │ +│ • ChatbotRule.Evaluate() - match conditions │ +└────────────────────────┬───────────────────────────────────────┘ + │ +┌────────────────────────▼───────────────────────────────────────┐ +│ Infrastructure Layer │ +│ • EF Core DbContext (persistence) │ +│ • Repositories (ConversationRepository, CustomerRepository) │ +│ • ZaloOfficialAccountClient (HTTP client with Polly) │ +│ • RuleBasedChatbotEngine (keyword matching, regex) │ +│ • AiChatbotEngine (LLM integration) │ +│ • Redis Caching (conversation context) │ +└────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Domain Model / Mô Hình Domain + +### Aggregates Overview / Tổng Quan Aggregates + +```mermaid +classDiagram + class Conversation { + +Guid Id + +string ZaloUserId + +Guid CustomerId + +ConversationStatus Status + +DateTime StartedAt + +DateTime? EndedAt + +List~Message~ Messages + +AddMessage(Message) + +Close() + +Reopen() + } + + class Message { + +Guid Id + +MessageType Type + +string Content + +MessageDirection Direction + +DateTime SentAt + +bool IsFromBot + } + + class ZaloCustomer { + +Guid Id + +string ZaloUserId + +CustomerProfile Profile + +List~Tag~ Tags + +CustomerSegment Segment + +DateTime FirstInteractionAt + +DateTime LastInteractionAt + +UpdateProfile(CustomerProfile) + +AddTag(Tag) + +UpdateSegment() + } + + class CustomerProfile { + +string DisplayName + +string AvatarUrl + +string PhoneNumber + +string Email + } + + class ChatbotRule { + +Guid Id + +string Name + +RuleType Type + +List~RuleCondition~ Conditions + +RuleAction Action + +int Priority + +bool IsActive + +Evaluate(string) + } + + class MessageTemplate { + +Guid Id + +string TemplateId + +string Name + +string Content + +List~TemplateParameter~ Parameters + } + + Conversation "1" *-- "many" Message + ZaloCustomer "1" *-- "1" CustomerProfile + ZaloCustomer "1" *-- "many" Tag + ChatbotRule "1" *-- "many" RuleCondition + Conversation "many" --> "1" ZaloCustomer +``` + +### Aggregate Details / Chi Tiết Aggregates + +#### 1. Conversation Aggregate + +```csharp +/// +/// EN: Conversation aggregate root - tracks customer interactions. +/// VI: Aggregate root Conversation - theo dõi tương tác khách hàng. +/// +public class Conversation : Entity, IAggregateRoot +{ + private readonly List _messages = new(); + + public string ZaloUserId { get; private set; } + public Guid CustomerId { get; private set; } + public ConversationStatus Status { get; private set; } + public DateTime StartedAt { get; private set; } + public DateTime? EndedAt { get; private set; } + public IReadOnlyCollection Messages => _messages.AsReadOnly(); + + public void AddMessage(MessageType type, string content, MessageDirection direction, bool isFromBot) + { + if (Status == ConversationStatus.Closed) + throw new ZaloDomainException("Cannot add message to closed conversation"); + + var message = new Message(type, content, direction, isFromBot); + _messages.Add(message); + + AddDomainEvent(new MessageReceivedDomainEvent(Id, message.Id, content)); + } + + public void Close() + { + if (Status == ConversationStatus.Closed) + return; + + Status = ConversationStatus.Closed; + EndedAt = DateTime.UtcNow; + } +} +``` + +#### 2. ZaloCustomer Aggregate + +```csharp +/// +/// EN: Zalo customer aggregate - customer relationship management. +/// VI: Aggregate ZaloCustomer - quản lý quan hệ khách hàng. +/// +public class ZaloCustomer : Entity, IAggregateRoot +{ + private readonly List _tags = new(); + + public string ZaloUserId { get; private set; } // From Zalo OA + public CustomerProfile Profile { get; private set; } + public CustomerSegment Segment { get; private set; } + public DateTime FirstInteractionAt { get; private set; } + public DateTime LastInteractionAt { get; private set; } + public IReadOnlyCollection Tags => _tags.AsReadOnly(); + + public void UpdateProfile(string displayName, string avatarUrl, string? phoneNumber = null, string? email = null) + { + Profile = new CustomerProfile(displayName, avatarUrl, phoneNumber, email); + AddDomainEvent(new CustomerProfileUpdatedDomainEvent(Id, ZaloUserId)); + } + + public void AddTag(string tagName) + { + if (_tags.Any(t => t.Name == tagName)) + return; + + _tags.Add(new Tag(tagName)); + } + + public void UpdateSegment() + { + // EN: Auto-segment based on behavior + // VI: Tự động phân khúc dựa trên hành vi + var interactionCount = _tags.Count(t => t.Name.StartsWith("interaction")); + + Segment = interactionCount switch + { + > 50 => CustomerSegment.VIP, + > 20 => CustomerSegment.Active, + > 5 => CustomerSegment.Regular, + _ => CustomerSegment.New + }; + } +} +``` + +#### 3. ChatbotRule Aggregate + +```csharp +/// +/// EN: Chatbot rule aggregate - automation logic. +/// VI: Aggregate ChatbotRule - logic tự động hóa. +/// +public class ChatbotRule : Entity, IAggregateRoot +{ + private readonly List _conditions = new(); + + public string Name { get; private set; } + public RuleType Type { get; private set; } // Keyword, Regex, Intent + public IReadOnlyCollection Conditions => _conditions.AsReadOnly(); + public RuleAction Action { get; private set; } + public int Priority { get; private set; } // Higher = evaluated first + public bool IsActive { get; private set; } + + public bool Evaluate(string userMessage) + { + if (!IsActive) + return false; + + return Type switch + { + RuleType.Keyword => _conditions.Any(c => userMessage.Contains(c.Value, StringComparison.OrdinalIgnoreCase)), + RuleType.Regex => _conditions.Any(c => Regex.IsMatch(userMessage, c.Value)), + _ => false + }; + } +} +``` + +--- + +## CQRS Commands & Queries + +### Commands (Write Operations) + +```csharp +// EN: Process incoming webhook from Zalo +// VI: Xử lý webhook từ Zalo +public record ProcessWebhookCommand( + string EventName, + string ZaloUserId, + string MessageText, + string MessageType, + DateTime Timestamp) : IRequest; + +// EN: Send message to Zalo customer +// VI: Gửi tin nhắn đến khách hàng Zalo +public record SendMessageCommand( + Guid ConversationId, + string ZaloUserId, + string MessageText, + MessageType Type = MessageType.Text) : IRequest; + +// EN: Create chatbot automation rule +// VI: Tạo quy tắc tự động chatbot +public record CreateChatbotRuleCommand( + string Name, + RuleType Type, + List Conditions, + RuleActionDto Action, + int Priority) : IRequest; + +// EN: Update customer profile +// VI: Cập nhật hồ sơ khách hàng +public record UpdateCustomerProfileCommand( + Guid CustomerId, + string DisplayName, + string? PhoneNumber, + string? Email, + List? Tags) : IRequest; +``` + +### Queries (Read Operations) + +```csharp +// EN: Get conversation history +// VI: Lấy lịch sử hội thoại +public record GetConversationHistoryQuery( + Guid ConversationId, + int Skip = 0, + int Take = 50) : IRequest; + +// EN: Get customer details with interaction summary +// VI: Lấy chi tiết khách hàng với tóm tắt tương tác +public record GetCustomerQuery( + Guid CustomerId) : IRequest; + +// EN: Search conversations +// VI: Tìm kiếm hội thoại +public record SearchConversationsQuery( + string? ZaloUserId = null, + ConversationStatus? Status = null, + DateTime? FromDate = null, + DateTime? ToDate = null, + int Skip = 0, + int Take = 20) : IRequest>; + +// EN: Get chatbot automation rules +// VI: Lấy quy tắc tự động chatbot +public record GetActiveChatbotRulesQuery() : IRequest>; +``` + +--- + +## Integration Patterns / Mẫu Tích Hợp + +### 1. Zalo Official Account Integration + +```mermaid +sequenceDiagram + participant Zalo as Zalo OA + participant WH as WebhooksController + participant MQ as RabbitMQ + participant Engine as Processing Engine + participant DB as PostgreSQL + participant ZaloAPI as Zalo API Client + + Zalo->>WH: POST /webhooks
(user_send_text) + WH->>WH: Verify signature + WH->>MQ: Publish(WebhookEvent) + WH->>Zalo: 200 OK (< 2s) + + MQ->>Engine: Consume(WebhookEvent) + Engine->>DB: Load customer context + Engine->>Engine: Generate response + Engine->>DB: Save conversation + Engine->>ZaloAPI: SendMessage() + ZaloAPI->>Zalo: POST /message/text + Zalo->>ZaloAPI: 200 OK +``` + +#### Zalo OA API Client + +```csharp +/// +/// EN: HTTP client for Zalo Official Account API with resilience. +/// VI: HTTP client cho Zalo OA API với khả năng phục hồi. +/// +public class ZaloOfficialAccountClient : IZaloOfficialAccountClient +{ + private readonly HttpClient _httpClient; + private readonly ILogger _logger; + private readonly string _accessToken; + + public async Task SendTextMessageAsync( + string recipientZaloUserId, + string text, + CancellationToken ct = default) + { + var request = new + { + recipient = new { user_id = recipientZaloUserId }, + message = new { text } + }; + + var response = await _httpClient.PostAsJsonAsync( + "/v3.0/oa/message/cs", + request, + ct); + + response.EnsureSuccessStatusCode(); + return await response.Content.ReadFromJsonAsync(ct); + } + + public async Task GetUserProfileAsync( + string zaloUserId, + CancellationToken ct = default) + { + var response = await _httpClient.GetAsync( + $"/v3.0/oa/user/detail?data={{\"user_id\":\"{zaloUserId}\"}}", + ct); + + response.EnsureSuccessStatusCode(); + return await response.Content.ReadFromJsonAsync(ct); + } +} +``` + +### 2. Rule-Based Chatbot Engine + +```csharp +/// +/// EN: Rule-based automation engine for keyword/pattern matching. +/// VI: Engine tự động dựa trên quy tắc cho khớp từ khóa/mẫu. +/// +public class RuleBasedChatbotEngine : IChatbotEngine +{ + private readonly IChatbotRuleRepository _ruleRepository; + private readonly ILogger _logger; + + public async Task ProcessAsync( + string userMessage, + ConversationContext context, + CancellationToken ct = default) + { + // EN: Load active rules ordered by priority + // VI: Load rules active theo priority + var rules = await _ruleRepository.GetActiveRulesOrderedByPriorityAsync(ct); + + foreach (var rule in rules) + { + if (rule.Evaluate(userMessage)) + { + _logger.LogInformation( + "EN: Matched rule {RuleName} / VI: Khớp quy tắc {RuleName}", + rule.Name); + + return new ChatbotResponse( + ResponseText: rule.Action.ResponseText, + MatchedRuleId: rule.Id, + Confidence: 1.0); + } + } + + // EN: No rule matched, fallback to AI + // VI: Không khớp quy tắc, fallback sang AI + return ChatbotResponse.NoMatch; + } +} +``` + +### 3. AI Chatbot Engine (LLM Integration) + +```csharp +/// +/// EN: AI-powered chatbot using LLM (OpenAI/Vertex AI). +/// VI: Chatbot AI dùng LLM (OpenAI/Vertex AI). +/// +public class AiChatbotEngine : IChatbotEngine +{ + private readonly ILlmService _llmService; + private readonly IConversationRepository _conversationRepository; + private readonly IRedisCache _cache; + + public async Task ProcessAsync( + string userMessage, + ConversationContext context, + CancellationToken ct = default) + { + // EN: Load conversation history for context + // VI: Load lịch sử hội thoại để có context + var conversationHistory = await _cache.GetOrSetAsync( + $"conversation:{context.ConversationId}", + async () => await _conversationRepository.GetMessagesAsync(context.ConversationId, take: 10, ct), + TimeSpan.FromMinutes(30), + ct); + + // EN: Build LLM prompt with context + // VI: Xây dựng prompt LLM với context + var prompt = BuildPrompt(userMessage, conversationHistory, context.CustomerProfile); + + // EN: Call LLM provider + // VI: Gọi LLM provider + var llmResponse = await _llmService.GenerateResponseAsync(prompt, ct); + + return new ChatbotResponse( + ResponseText: llmResponse.Text, + Confidence: llmResponse.Confidence); + } + + private string BuildPrompt(string userMessage, IEnumerable history, CustomerProfile profile) + { + var historyText = string.Join("\n", history.Select(m => + $"{(m.IsFromBot ? "Assistant" : "User")}: {m.Content}")); + + return $@" +You are a helpful customer service assistant for GoodGo. +Customer name: {profile.DisplayName} +Conversation history: +{historyText} + +User: {userMessage} +Assistant:"; + } +} +``` + +--- + +## Data Flow / Luồng Dữ Liệu + +### Webhook Processing Flow / Luồng Xử Lý Webhook + +```mermaid +flowchart TD + A[Zalo sends webhook] --> B{Verify signature} + B -->|Invalid| C[Return 401] + B -->|Valid| D[Parse event] + D --> E{Event type?} + + E -->|user_send_text| F[ProcessWebhookCommand] + E -->|user_send_image| G[HandleImageMessage] + E -->|follow| H[CreateCustomer] + E -->|unfollow| I[MarkCustomerInactive] + + F --> J[Queue to RabbitMQ] + J --> K[Return 200 to Zalo] + + J --> L[Consumer processes] + L --> M{Load or create customer} + M --> N{Load or create conversation} + N --> O{Route to engine} + + O -->|Has matching rule| P[RuleBasedEngine] + O -->|No rule or AI enabled| Q[AiChatbotEngine] + + P --> R[Generate response] + Q --> S[Call LLM] + S --> R + + R --> T[Save to DB] + T --> U[Send via Zalo API] + U --> V[Update cache] +``` + +--- + +## Security & Authentication / Bảo Mật + +### 1. Webhook Signature Verification + +```csharp +/// +/// EN: Verify Zalo webhook signature to prevent spoofing. +/// VI: Xác thực chữ ký webhook Zalo để chống giả mạo. +/// +public class ZaloWebhookSignatureValidator +{ + private readonly string _webhookSecret; + + public bool ValidateSignature(string body, string signature) + { + var computedSignature = ComputeHmac256(body, _webhookSecret); + return signature.Equals(computedSignature, StringComparison.OrdinalIgnoreCase); + } + + private string ComputeHmac256(string message, string secret) + { + var encoding = new UTF8Encoding(); + var keyBytes = encoding.GetBytes(secret); + using var hmac = new HMACSHA256(keyBytes); + var hashBytes = hmac.ComputeHash(encoding.GetBytes(message)); + return BitConverter.ToString(hashBytes).Replace("-", "").ToLower(); + } +} +``` + +### 2. API Authentication + +- **Public APIs** (Webhooks): Signature verification only +- **Customer APIs**: JWT Bearer tokens from IAM service +- **Admin APIs**: JWT + Admin role claim + +--- + +## Performance & Scalability / Hiệu Năng + +### Performance Targets / Mục Tiêu Hiệu Năng + +| Metric | Target | Strategy | +|--------|--------|----------| +| Webhook response time | < 2s | Queue immediately, return 200 | +| Message processing time | < 5s | Async processing via RabbitMQ | +| AI response generation | < 3s | LLM caching, prompt optimization | +| Database query time | < 100ms | Indexed queries, read replicas | +| Concurrent conversations | 10,000+ | Stateless processing, Redis cache | + +### Caching Strategy / Chiến Lược Caching + +```csharp +// EN: Cache conversation context in Redis +// VI: Cache context hội thoại trong Redis +Key: "conversation:{conversationId}" +TTL: 30 minutes +Data: Last 10 messages, customer profile, active rules + +// EN: Cache chatbot rules +// VI: Cache quy tắc chatbot +Key: "chatbot:rules:active" +TTL: 5 minutes +Data: All active rules ordered by priority +``` + +--- + +## Monitoring & Observability / Giám Sát + +### Key Metrics / Chỉ Số Quan Trọng + +``` +# Webhook metrics +zalo_webhook_events_total{event_type="user_send_text"} +zalo_webhook_processing_duration_seconds + +# Chatbot metrics +zalo_messages_processed_total{engine="rule_based|ai"} +zalo_chatbot_rule_matches_total{rule_id="..."} +zalo_ai_llm_latency_seconds + +# Business metrics +zalo_active_conversations_total +zalo_customer_satisfaction_score +zalo_automation_rate +``` + +### Logging Strategy / Chiến Lược Logging + +``` +INFO: User message received, rule matched +WARN: No rule matched, fallback to AI +ERROR: Failed to send Zalo message, retrying +``` + +--- + +## Deployment Considerations / Cân Nhắc Triển Khai + +### Environment Configuration + +```yaml +# Production +- Webhook URL: https://api.goodgo.vn/api/v1/zalo/webhooks +- Database: Neon PostgreSQL (multi-region) +- Redis: ElastiCache cluster +- LLM: Vertex AI (gcp-asia-southeast1) + +# Staging +- Webhook URL: https://staging-api.goodgo.vn/api/v1/zalo/webhooks +- Zalo OA: Test account +``` + +### Disaster Recovery / Khôi Phục Thảm Họa + +- **Database backups**: Daily snapshots, 30-day retention +- **Message queue**: Durable queues with replication +- **Webhook replay**: Store raw webhook events for 7 days + +--- + +## Future Enhancements / Cải Tiến Tương Lai + +1. **Multi-language support** - Vietnamese + English chatbot +2. **Voice message processing** - Speech-to-text integration +3. **Sentiment analysis** - Detect customer emotions +4. **A/B testing** - Test different chatbot responses +5. **Zalo Mini App integration** - Deep linking to mini apps + +--- + +## Related Documentation / Tài Liệu Liên Quan + +- [API Design](./API_DESIGN.md) - Complete API specification +- [Domain Models](./DOMAIN_MODELS.md) - Detailed domain entities +- [Integration Guide](./INTEGRATION.md) - Zalo OA API integration +- [Database Schema](./DATABASE_SCHEMA.md) - DB design and migrations + +--- + +**Document Version**: 1.0 +**Last Updated**: 2026-01-18 +**Author**: GoodGo Platform Team