Files
docs/03-BACKEND/CMS/chatika-integration.md
T
masoodafar-web e7d979117c feat: Add Chatika integration and Club Features system documentation
- Implement Chatika account activation via background job
- Create IChatikaApiService interface and its implementation
- Add Club Features system documentation detailing features and entities
- Introduce ClubFeatureType enum to replace hardcoded IDs
- Update SQL scripts for Club Membership migration
- Fix various bugs in BackOffice UI and improve Products page functionality
2025-12-24 01:07:49 +03:30

15 KiB

🤖 Chatika Integration Guide

آخرین بروزرسانی: ۳ دی ۱۴۰۴ (23 December 2025)
وضعیت: Production Ready


📋 فهرست

  1. معرفی
  2. معماری
  3. API چتیکا
  4. پیاده‌سازی
  5. تنظیمات
  6. نحوه کار Worker
  7. Troubleshooting

معرفی

چتیکا یک سرویس هوش مصنوعی است که به عنوان اولین فیچر باشگاه مشتریان به کاربران ارائه می‌شود. هنگام فعال‌سازی باشگاه، به صورت خودکار یک حساب در چتیکا برای کاربر ایجاد می‌شود.

ویژگی‌ها:

  • فعال‌سازی خودکار حساب
  • جلوگیری از ثبت تکراری
  • Retry با Exponential Backoff
  • Logging کامل

معماری

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│   User Activates │───▶│  ClubMembership  │───▶│ UserClubFeature │
│   Club Package   │    │  (IsActive=true) │    │  (Chatika, Id=1)│
└─────────────────┘    └──────────────────┘    │  Notes = NULL   │
                                                └────────┬────────┘
                                                         │
                                                         ▼
┌─────────────────────────────────────────────────────────────────┐
│                    Hangfire Scheduler                            │
│                   Cron: */5 * * * * (Every 5 minutes)            │
└─────────────────────────────┬───────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│               ChatikaAccountActivationJob                        │
│                                                                  │
│  Query: SELECT * FROM UserClubFeatures                           │
│         WHERE ClubFeatureId = 1 (Chatika)                        │
│         AND ClubMembership.IsActive = true                       │
│         AND Notes IS NULL                                        │
└─────────────────────────────┬───────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                    ChatikaApiService                             │
│  POST https://api.chatika.ir/api/v1/organizations/register-user  │
│  Header: X-API-Key: {ApiKey}                                     │
│  Body: { "mobile_number": "09123456789" }                        │
└─────────────────────────────┬───────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                    Update UserClubFeature                        │
│  Notes = "🎉 تبریک! حساب هوش مصنوعی چتیکا شما فعال شد..."        │
│  IsActive = true                                                 │
└─────────────────────────────────────────────────────────────────┘

API چتیکا

Endpoint

POST /api/v1/organizations/register-user

Headers

Header Value
X-API-Key Organization API Key
Content-Type application/json

Request Body

{
    "mobile_number": "09123456789"
}

Success Response (200 OK)

{
    "id": 1,
    "mobile_number": "09123456789",
    "organization_id": 1,
    "organization_title": "FourSat",
    "wallet_balance": 100.0,
    "is_new_user": true,
    "credit_charged": 100.0
}

Error Responses

Status Error Code Description
401 INVALID_API_KEY API Key نامعتبر
403 ORGANIZATION_DISABLED سازمان غیرفعال شده
403 ORGANIZATION_EXPIRED سازمان منقضی شده
400 INVALID_MOBILE_FORMAT فرمت شماره موبایل نامعتبر

پیاده‌سازی

1. Interface

فایل: CMSMicroservice.Application/Common/Interfaces/IChatikaApiService.cs

public interface IChatikaApiService
{
    Task<ChatikaAccountResult> CreateAccountAsync(
        string mobileNumber, 
        string fullName,
        CancellationToken cancellationToken = default);
}

public class ChatikaAccountResult
{
    public bool IsSuccess { get; set; }
    public string? ErrorMessage { get; set; }
    public string? ChatikaUserId { get; set; }
    public string? AccessUrl { get; set; }
    
    public static ChatikaAccountResult Success(...) => ...;
    public static ChatikaAccountResult Failure(string error) => ...;
}

2. Service Implementation

فایل: CMSMicroservice.Infrastructure/Services/ChatikaApiService.cs

public class ChatikaApiService : IChatikaApiService
{
    private readonly HttpClient _httpClient;
    private readonly ILogger<ChatikaApiService> _logger;

    public async Task<ChatikaAccountResult> CreateAccountAsync(
        string mobileNumber, 
        string fullName,
        CancellationToken cancellationToken = default)
    {
        var request = new { mobile_number = mobileNumber };
        
        var response = await _httpClient.PostAsJsonAsync(
            "/api/v1/organizations/register-user", 
            request, 
            cancellationToken);

        if (response.IsSuccessStatusCode)
        {
            var result = await response.Content.ReadFromJsonAsync<ChatikaRegisterResponse>();
            return ChatikaAccountResult.Success(result?.Id.ToString(), "https://chatika.ir");
        }
        
        return ChatikaAccountResult.Failure($"Error: {response.StatusCode}");
    }
}

3. Background Job

فایل: CMSMicroservice.Infrastructure/BackgroundJobs/ChatikaAccountActivationJob.cs

public class ChatikaAccountActivationJob
{
    private const string ChatikaFeatureDescription = 
        "🎉 تبریک! حساب هوش مصنوعی چتیکا شما فعال شد.\n\n" +
        "برای استفاده از امکانات رایگان چتیکا:\n" +
        "1️⃣ به وب‌سایت chatika.ir مراجعه کنید\n" +
        "2️⃣ شماره موبایل خود را وارد کنید\n" +
        "3️⃣ از دستیار هوشمند چتیکا لذت ببرید!\n\n" +
        "🔗 لینک ورود: https://chatika.ir";

    public async Task ExecuteAsync(CancellationToken cancellationToken = default)
    {
        // 1. پیدا کردن کاربران در انتظار
        var pendingUsers = await _context.UserClubFeatures
            .Include(ucf => ucf.User)
            .Include(ucf => ucf.ClubMembership)
            .Where(ucf => 
                ucf.ClubFeatureId == (long)ClubFeatureType.Chatika &&
                ucf.ClubMembership.IsActive &&
                !ucf.IsDeleted &&
                ucf.IsActive &&
                (ucf.Notes == null || ucf.Notes == ""))
            .ToListAsync(cancellationToken);

        // 2. پردازش هر کاربر
        foreach (var userFeature in pendingUsers)
        {
            var user = userFeature.User;
            var fullName = $"{user.FirstName} {user.LastName}".Trim();
            
            // 3. کال API با Retry
            var result = await _retryPipeline.ExecuteAsync(
                async ct => await _chatikaApiService.CreateAccountAsync(
                    user.Mobile, fullName, ct),
                cancellationToken);

            // 4. آپدیت فیچر
            if (result.IsSuccess)
            {
                userFeature.Notes = ChatikaFeatureDescription;
                userFeature.IsActive = true;
                await _context.SaveChangesAsync(cancellationToken);
            }
        }
    }
}

تنظیمات

appsettings.json

{
  "Chatika": {
    "BaseUrl": "https://api.chatika.ir",
    "ApiKey": "YOUR_ORGANIZATION_API_KEY"
  }
}

DI Registration

فایل: ConfigureServices.cs

// Chatika API Service
services.AddHttpClient<IChatikaApiService, ChatikaApiService>()
    .SetHandlerLifetime(TimeSpan.FromMinutes(5))
    .ConfigureHttpClient((sp, client) =>
    {
        client.Timeout = TimeSpan.FromSeconds(30);
    });

// Background Job
services.AddScoped<ChatikaAccountActivationJob>();

Hangfire Registration

فایل: Program.cs

// Chatika Account Activation: Every 5 minutes
recurringJobManager.AddOrUpdate<ChatikaAccountActivationJob>(
    recurringJobId: "chatika-account-activation",
    methodCall: job => job.ExecuteAsync(CancellationToken.None),
    cronExpression: "*/5 * * * *",
    options: new RecurringJobOptions { TimeZone = TimeZoneInfo.Utc });

نحوه کار Worker

Flowchart

┌──────────────────────────────────────────────────────────────┐
│                    START (Every 5 min)                        │
└──────────────────────────┬───────────────────────────────────┘
                           │
                           ▼
┌──────────────────────────────────────────────────────────────┐
│  Query: Users with Chatika feature & Notes = NULL             │
└──────────────────────────┬───────────────────────────────────┘
                           │
                           ▼
                    ┌─────────────┐
                    │ Any Users?  │
                    └──────┬──────┘
                           │
              ┌────────────┴────────────┐
              │ NO                      │ YES
              ▼                         ▼
        ┌──────────┐            ┌───────────────┐
        │   END    │            │ For each user │
        └──────────┘            └───────┬───────┘
                                        │
                                        ▼
                               ┌────────────────────┐
                               │ Call Chatika API   │
                               │ (with 3x Retry)    │
                               └────────┬───────────┘
                                        │
                              ┌─────────┴─────────┐
                              │ SUCCESS           │ FAILURE
                              ▼                   ▼
                      ┌───────────────┐   ┌───────────────┐
                      │ Update Notes  │   │ Log Warning   │
                      │ IsActive=true │   │ Continue      │
                      └───────────────┘   └───────────────┘
                                        │
                                        ▼
                               ┌────────────────┐
                               │  Next User     │
                               └────────────────┘

Retry Policy

// Polly Retry: 3 attempts with exponential backoff
_retryPipeline = new ResiliencePipelineBuilder()
    .AddRetry(new RetryStrategyOptions
    {
        MaxRetryAttempts = 3,
        Delay = TimeSpan.FromSeconds(30),
        BackoffType = DelayBackoffType.Exponential,
        UseJitter = true
    })
    .Build();

Retry Timeline:

  • Attempt 1: Immediate
  • Attempt 2: ~30 seconds later
  • Attempt 3: ~60 seconds later

Troubleshooting

1. API Key Invalid

خطا: INVALID_API_KEY

راه‌حل:

  1. بررسی appsettings.json
  2. تأیید API Key در داشبورد چتیکا
  3. چک کردن header name: باید X-API-Key باشد

2. Users Not Being Processed

علت احتمالی:

  1. ClubMembership.IsActive = false
  2. UserClubFeature.Notes قبلاً پر شده
  3. ClubFeatureId != 1

Debug Query:

SELECT ucf.*, u.Mobile, cm.IsActive
FROM UserClubFeatures ucf
JOIN Users u ON ucf.UserId = u.Id
JOIN ClubMemberships cm ON ucf.ClubMembershipId = cm.Id
WHERE ucf.ClubFeatureId = 1
  AND ucf.IsDeleted = 0
  AND (ucf.Notes IS NULL OR ucf.Notes = '')

3. Hangfire Job Not Running

راه‌حل:

  1. چک کردن Hangfire Dashboard: /hangfire
  2. بررسی لاگ‌ها در Seq
  3. تأیید ثبت Job در Program.cs

4. Network Timeout

علت: سرور چتیکا در دسترس نیست

راه‌حل:

  • Retry Policy خودکار 3 بار تلاش می‌کند
  • بررسی لاگ‌ها برای خطای دقیق
  • تماس با پشتیبانی چتیکا

📊 Monitoring

Logs to Watch

🚀 Starting Chatika account activation job
📋 Found {Count} users pending Chatika activation
🤖 Creating Chatika account for mobile: 0912***
✅ Chatika account activated for user {UserId}
⚠️ Failed to create Chatika account for user {UserId}: {Error}
❌ Network error calling Chatika API
🏁 Chatika activation job completed. Success: {X}, Failed: {Y}

Seq Query

ApplicationName = "CMSMicroservice" AND Message LIKE "%Chatika%"

📚 مستندات مرتبط