Tác giả: Backend Engineer với 5 năm kinh nghiệm xây dựng hệ thống API Gateway cho SaaS đa tenant — đã triển khai thành công rate limiting cho 50+ dự án production.

Kết luận trước — Bạn có nên đọc tiếp?

Nếu bạn đang xây dựng SaaS multi-tenant và cần:

HolySheep API Gateway là giải pháp tối ưu về chi phí và độ trễ. Với mức giá từ $0.42/MTok (DeepSeek V3.2), tiết kiệm 85%+ so với API chính thức, độ trễ trung bình <50ms, và hỗ trợ thanh toán qua WeChat/Alipay — đây là lựa chọn số một cho thị trường Châu Á.

Nếu bạn chỉ cần rate limiting đơn giản hoặc budget không phải ưu tiên hàng đầu → có thể skip phần so sánh chi tiết.

Bảng so sánh: HolySheep vs API chính thức vs Đối thủ

Tiêu chí HolySheep AI OpenAI API Anthropic API Google Gemini
Giá GPT-4.1 $8/MTok $8/MTok - -
Giá Claude Sonnet 4.5 $15/MTok - $15/MTok -
Giá Gemini 2.5 Flash $2.50/MTok - - $2.50/MTok
Giá DeepSeek V3.2 $0.42/MTok - - -
Độ trễ trung bình <50ms 100-300ms 150-400ms 80-200ms
Thanh toán WeChat, Alipay, USD Credit Card (quốc tế khó) Credit Card Credit Card
Tín dụng miễn phí Có — khi đăng ký $5 trial Hạn chế
User-level rate limiting Tích hợp sẵn Cần tự xây Cần tự xây Cần tự xây
Billing isolation Hỗ trợ native qua Usage-based billing qua Projects qua Vertex AI
Phù hợp SaaS Châu Á, startup tiết kiệm Enterprise Mỹ Enterprise cao cấp Google ecosystem

Kiến trúc tổng quan: User-Level Rate Limiting + Billing Isolation

Trước khi đi vào code, mình muốn chia sẻ bài học xương máu từ dự án đầu tiên: ban đầu mình nghĩ chỉ cần rate limit theo API key là đủ. Sai lầm! Một tenant spam request khiến toàn bộ user khác bị ảnh hưởng. Giải pháp đúng là 2-tier rate limiting: layer 1 cho tenant, layer 2 cho end-user.

Sơ đồ luồng request

+-------------------+     +--------------------+     +------------------+
|   Client (User)   | --> |   SaaS Gateway     | --> | HolySheep API    |
|                   |     |                    |     |                  |
| Header:           |     | 1. Validate tenant |     | Base URL:        |
| X-Tenant-ID: abc  |     | 2. Check user quota|     | api.holysheep.ai |
| X-User-ID: 12345  |     | 3. Track usage     |     | /v1/chat/complet-|
| Authorization:    |     | 4. Route request   |     | ions             |
| Bearer <user_key>|     | 5. Calculate cost  |     |                  |
+-------------------+     +--------------------+     +------------------+
                                    |
                                    v
                          +--------------------+
                          |  Billing Database  |
                          |  - tenant_id       |
                          |  - user_id         |
                          |  - model_used      |
                          |  - tokens_consumed |
                          |  - cost_usd        |
                          |  - rate_limit_reset|
                          +--------------------+

Triển khai chi tiết với Python

1. Cấu hình kết nối HolySheep API

# config.py
import os
from dataclasses import dataclass
from typing import Dict, List

@dataclass
class RateLimitConfig:
    """Cấu hình rate limit cho từng tier"""
    requests_per_minute: int
    tokens_per_minute: int
    daily_limit_tokens: int

@dataclass  
class TenantConfig:
    """Cấu hình tenant trên HolySheep"""
    tenant_id: str
    holysheep_api_key: str  # API key riêng cho tenant
    tier: str  # 'free', 'pro', 'enterprise'
    models: List[str]

Bảng giá HolySheep 2026 (USD/MTok)

HOLYSHEEP_PRICING = { 'gpt-4.1': 8.00, 'claude-sonnet-4.5': 15.00, 'gemini-2.5-flash': 2.50, 'deepseek-v3.2': 0.42, }

Rate limit theo tier

RATE_LIMITS = { 'free': RateLimitConfig( requests_per_minute=10, tokens_per_minute=10000, daily_limit_tokens=100000 ), 'pro': RateLimitConfig( requests_per_minute=60, tokens_per_minute=100000, daily_limit_tokens=1000000 ), 'enterprise': RateLimitConfig( requests_per_minute=300, tokens_per_minute=500000, daily_limit_tokens=10000000 ), }

HolySheep API Configuration

HOLYSHEEP_CONFIG = { 'base_url': 'https://api.holysheep.ai/v1', # LUÔN dùng endpoint này 'default_model': 'deepseek-v3.2', 'timeout': 30, 'max_retries': 3, }

Mapping model name chuẩn hóa

MODEL_ALIASES = { 'gpt4': 'gpt-4.1', 'gpt-4': 'gpt-4.1', 'claude': 'claude-sonnet-4.5', 'claude-4': 'claude-sonnet-4.5', 'gemini': 'gemini-2.5-flash', 'deepseek': 'deepseek-v3.2', }

2. Core Rate Limiter với Redis

# rate_limiter.py
import redis
import time
import json
from typing import Tuple, Optional
from dataclasses import dataclass
from config import RATE_LIMITS, HOLYSHEEP_PRICING

class RateLimiter:
    """
    User-level rate limiter với sliding window algorithm.
    Triển khai 2-tier: tenant-level + user-level
    """
    
    def __init__(self, redis_url: str = 'redis://localhost:6379'):
        self.redis = redis.from_url(redis_url, decode_responses=True)
        self.window_size = 60  # 1 phút sliding window
        
    def _get_rate_limit_key(self, tenant_id: str, user_id: str, 
                           limit_type: str) -> str:
        """Tạo Redis key cho rate limit tracking"""
        return f"ratelimit:{tenant_id}:{user_id}:{limit_type}"
    
    def check_and_increment(
        self, 
        tenant_id: str, 
        user_id: str, 
        tier: str,
        tokens_requested: int
    ) -> Tuple[bool, dict]:
        """
        Kiểm tra và tăng counter cho request.
        Returns: (allowed, limit_info)
        """
        config = RATE_LIMITS.get(tier, RATE_LIMITS['free'])
        current_time = int(time.time())
        
        # Key cho requests/giây
        req_key = self._get_rate_limit_key(tenant_id, user_id, 'requests')
        # Key cho tokens/phút
        token_key = self._get_rate_limit_key(tenant_id, user_id, 'tokens')
        # Key cho daily limit
        daily_key = self._get_rate_limit_key(tenant_id, user_id, 'daily')
        
        # Atomic transaction với Redis pipeline
        pipe = self.redis.pipeline()
        
        # 1. Clean old entries trong sliding window
        window_start = current_time - self.window_size
        pipe.zremrangebyscore(req_key, 0, window_start)
        pipe.zremrangebyscore(token_key, 0, window_start)
        
        # 2. Count current requests trong window
        pipe.zcard(req_key)
        pipe.zrangebyscore(token_key, window_start, current_time)
        
        results = pipe.execute()
        current_requests = results[2]
        current_tokens_list = results[3]
        current_tokens = sum(int(t) for t in current_tokens_list)
        
        # 3. Check daily limit
        daily_tokens = self._get_daily_usage(tenant_id, user_id)
        
        # 4. Evaluate limits
        allowed = True
        reasons = []
        
        if current_requests >= config.requests_per_minute:
            allowed = False
            reasons.append(f"RPM limit: {config.requests_per_minute}")
            
        if current_tokens + tokens_requested > config.tokens_per_minute:
            allowed = False
            reasons.append(f"TPM limit: {config.tokens_per_minute}")
            
        if daily_tokens + tokens_requested > config.daily_limit_tokens:
            allowed = False
            reasons.append(f"Daily limit: {config.daily_limit_tokens}")
        
        # 5. Nếu allowed, increment counters
        if allowed:
            pipe = self.redis.pipeline()
            pipe.zadd(req_key, {str(current_time): current_time})
            pipe.zadd(token_key, {str(current_time): tokens_requested})
            pipe.expire(req_key, self.window_size * 2)
            pipe.expire(token_key, self.window_size * 2)
            pipe.execute()
        
        # 6. Get remaining quota
        remaining_rpm = max(0, config.requests_per_minute - current_requests - 1)
        remaining_tpm = max(0, config.tokens_per_minute - current_tokens - tokens_requested)
        remaining_daily = max(0, config.daily_limit_tokens - daily_tokens - tokens_requested)
        
        return allowed, {
            'allowed': allowed,
            'remaining_rpm': remaining_rpm,
            'remaining_tpm': remaining_tpm,
            'remaining_daily': remaining_daily,
            'reset_in_seconds': self.window_size,
            'reasons': reasons if not allowed else []
        }
    
    def _get_daily_usage(self, tenant_id: str, user_id: str) -> int:
        """Lấy tổng tokens đã dùng trong ngày"""
        key = f"usage:daily:{tenant_id}:{user_id}:{time.strftime('%Y%m%d')}"
        usage = self.redis.get(key)
        return int(usage) if usage else 0
    
    def record_usage(self, tenant_id: str, user_id: str, 
                     tokens_used: int, model: str) -> float:
        """
        Ghi nhận usage và tính chi phí.
        Returns: cost in USD
        """
        # Tính cost
        price_per_mtok = HOLYSHEEP_PRICING.get(model, 0.42)
        cost = (tokens_used / 1_000_000) * price_per_mtok
        
        # Cập nhật daily counter
        daily_key = f"usage:daily:{tenant_id}:{user_id}:{time.strftime('%Y%m%d')}"
        pipe = self.redis.pipeline()
        pipe.incrby(daily_key, tokens_used)
        pipe.expire(daily_key, 86400 * 2)  # 2 days TTL
        pipe.execute()
        
        # Ghi log chi tiết cho billing
        billing_key = f"billing:{tenant_id}:{user_id}"
        billing_entry = {
            'timestamp': time.time(),
            'tokens': tokens_used,
            'model': model,
            'cost_usd': round(cost, 6)
        }
        self.redis.lpush(billing_key, json.dumps(billing_entry))
        self.redis.ltrim(billing_key, 0, 9999)  # Keep last 10k entries
        
        return cost

Singleton instance

rate_limiter = RateLimiter()

3. HolySheep API Client với Billing Tracking

# holysheep_client.py
import httpx
import time
from typing import Dict, List, Optional, AsyncIterator
from dataclasses import dataclass
import json

@dataclass
class UsageInfo:
    """Thông tin usage từ API response"""
    prompt_tokens: int
    completion_tokens: int
    total_tokens: int
    cost_usd: float
    model: str
    latency_ms: float

class HolySheepClient:
    """
    Client cho HolySheep API Gateway.
    Tự động track usage và billing per user/tenant.
    """
    
    def __init__(self, base_url: str = 'https://api.holysheep.ai/v1'):
        self.base_url = base_url
        self.client = httpx.AsyncClient(
            timeout=30.0,
            limits=httpx.Limits(max_connections=100)
        )
    
    async def chat_completion(
        self,
        api_key: str,
        model: str,
        messages: List[Dict],
        tenant_id: str,
        user_id: str,
        temperature: float = 0.7,
        max_tokens: Optional[int] = None,
        stream: bool = False,
    ) -> Dict:
        """
        Gọi HolySheep chat completion API với usage tracking.
        
        Args:
            api_key: HolySheep API key của tenant
            model: Model name (chuẩn hóa)
            messages: Chat messages
            tenant_id: Tenant identifier
            user_id: User identifier
            temperature, max_tokens: Generation params
            stream: Enable streaming
            
        Returns:
            API response với usage metadata
        """
        start_time = time.time()
        
        headers = {
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json',
            'X-Tenant-ID': tenant_id,      # Custom header cho multi-tenant
            'X-User-ID': user_id,          # Custom header cho billing
        }
        
        payload = {
            'model': model,
            'messages': messages,
            'temperature': temperature,
            'stream': stream,
        }
        if max_tokens:
            payload['max_tokens'] = max_tokens
        
        # Estimate tokens cho rate limit check
        estimated_tokens = self._estimate_tokens(messages)
        
        # Gọi API
        response = await self.client.post(
            f'{self.base_url}/chat/completions',
            headers=headers,
            json=payload
        )
        
        latency_ms = (time.time() - start_time) * 1000
        
        if response.status_code != 200:
            raise HolySheepAPIError(
                status_code=response.status_code,
                message=response.text
            )
        
        result = response.json()
        
        # Extract usage từ response
        usage = result.get('usage', {})
        usage_info = UsageInfo(
            prompt_tokens=usage.get('prompt_tokens', 0),
            completion_tokens=usage.get('completion_tokens', 0),
            total_tokens=usage.get('total_tokens', estimated_tokens),
            cost_usd=0.0,  # Sẽ tính sau
            model=model,
            latency_ms=round(latency_ms, 2)
        )
        
        # Tính cost dựa trên pricing
        from config import HOLYSHEEP_PRICING
        price = HOLYSHEEP_PRICING.get(model, 0.42)
        usage_info.cost_usd = round(
            (usage_info.total_tokens / 1_000_000) * price, 
            6
        )
        
        # Attach usage info vào response
        result['_usage_info'] = usage_info
        
        return result
    
    async def chat_completion_stream(
        self,
        api_key: str,
        model: str,
        messages: List[Dict],
        tenant_id: str,
        user_id: str,
        temperature: float = 0.7,
        max_tokens: Optional[int] = None,
    ) -> AsyncIterator[Dict]:
        """
        Streaming version với token counting.
        """
        headers = {
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json',
            'X-Tenant-ID': tenant_id,
            'X-User-ID': user_id,
        }
        
        payload = {
            'model': model,
            'messages': messages,
            'temperature': temperature,
            'stream': True,
        }
        if max_tokens:
            payload['max_tokens'] = max_tokens
        
        async with self.client.stream(
            'POST',
            f'{self.base_url}/chat/completions',
            headers=headers,
            json=payload
        ) as response:
            if response.status_code != 200:
                raise HolySheepAPIError(
                    status_code=response.status_code,
                    message=await response.text()
                )
            
            total_tokens = 0
            async for line in response.aiter_lines():
                if line.startswith('data: '):
                    data = line[6:]  # Remove 'data: ' prefix
                    if data == '[DONE]':
                        break
                    
                    chunk = json.loads(data)
                    yield chunk
                    
                    # Count tokens từ chunk
                    if 'usage' in chunk:
                        total_tokens = chunk['usage'].get('total_tokens', 0)
            
            # Yield usage info cuối cùng
            yield {'_final_usage': {
                'total_tokens': total_tokens,
                'cost_usd': round((total_tokens / 1_000_000) * 
                    HOLYSHEEP_PRICING.get(model, 0.42), 6)
            }}
    
    def _estimate_tokens(self, messages: List[Dict]) -> int:
        """Ước tính tokens cho rate limit check sơ bộ"""
        # Rough estimate: ~4 chars = 1 token
        total_chars = sum(len(str(m.get('content', ''))) for m in messages)
        return total_chars // 4
    
    async def close(self):
        await self.client.aclose()


class HolySheepAPIError(Exception):
    def __init__(self, status_code: int, message: str):
        self.status_code = status_code
        self.message = message
        super().__init__(f"HolySheep API Error {status_code}: {message}")

4. FastAPI Gateway cho Multi-Tenant SaaS

# main.py
from fastapi import FastAPI, HTTPException, Header, Request
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
from typing import List, Optional
import asyncio

from rate_limiter import rate_limiter
from holysheep_client import HolySheepClient, HolySheepAPIError
from config import HOLYSHEEP_CONFIG, MODEL_ALIASES, HOLYSHEEP_PRICING

app = FastAPI(title="Multi-Tenant AI Gateway")
client = HolySheepClient(HOLYSHEEP_CONFIG['base_url'])

Database giả lập - thay bằng DB thực

TENANT_DB = { 'tenant_abc': { 'api_key': 'YOUR_HOLYSHEEP_API_KEY', # API key HolySheep của tenant 'tier': 'pro', 'models': ['deepseek-v3.2', 'gpt-4.1', 'gemini-2.5-flash'] }, 'tenant_xyz': { 'api_key': 'YOUR_HOLYSHEEP_API_KEY', 'tier': 'free', 'models': ['deepseek-v3.2'] } } class ChatRequest(BaseModel): model: str messages: List[dict] temperature: float = 0.7 max_tokens: Optional[int] = None stream: bool = False @app.post("/v1/chat/completions") async def chat_completions( request: ChatRequest, tenant_id: str = Header(..., alias='X-Tenant-ID'), user_id: str = Header(..., alias='X-User-ID'), ): """Endpoint chính cho chat completions với rate limiting""" # 1. Validate tenant tenant = TENANT_DB.get(tenant_id) if not tenant: raise HTTPException(status_code=401, detail="Invalid tenant") # 2. Normalize model name model = MODEL_ALIASES.get(request.model, request.model) if model not in HOLYSHEEP_PRICING: raise HTTPException( status_code=400, detail=f"Model {model} not supported. Available: {list(HOLYSHEEP_PRICING.keys())}" ) if model not in tenant['models']: raise HTTPException( status_code=403, detail=f"Tenant không có quyền truy cập model {model}" ) # 3. Estimate tokens cho rate limit check estimated_tokens = sum( len(str(m.get('content', ''))) // 4 for m in request.messages ) # 4. Check rate limit allowed, limit_info = rate_limiter.check_and_increment( tenant_id=tenant_id, user_id=user_id, tier=tenant['tier'], tokens_requested=estimated_tokens ) if not allowed: raise HTTPException( status_code=429, detail={ 'error': 'Rate limit exceeded', 'retry_after_seconds': limit_info['reset_in_seconds'], 'limits': { 'rpm_remaining': limit_info['remaining_rpm'], 'tpm_remaining': limit_info['remaining_tpm'], 'daily_remaining': limit_info['remaining_daily'] }, 'reasons': limit_info['reasons'] } ) # 5. Add rate limit headers response_headers = { 'X-RateLimit-Remaining-RPM': str(limit_info['remaining_rpm']), 'X-RateLimit-Remaining-TPM': str(limit_info['remaining_tpm']), 'X-RateLimit-Reset': str(limit_info['reset_in_seconds']), } try: # 6. Gọi HolySheep API if request.stream: return StreamingResponse( _stream_wrapper( client.chat_completion_stream( api_key=tenant['api_key'], model=model, messages=request.messages, tenant_id=tenant_id, user_id=user_id, temperature=request.temperature, max_tokens=request.max_tokens ), tenant_id, user_id, model ), media_type='text/event-stream', headers=response_headers ) else: result = await client.chat_completion( api_key=tenant['api_key'], model=model, messages=request.messages, tenant_id=tenant_id, user_id=user_id, temperature=request.temperature, max_tokens=request.max_tokens ) # 7. Record usage cho billing usage_info = result['_usage_info'] cost = rate_limiter.record_usage( tenant_id=tenant_id, user_id=user_id, tokens_used=usage_info.total_tokens, model=model ) # Add billing info to response result['usage']['cost_usd'] = cost result['usage']['billing'] = { 'tenant_id': tenant_id, 'user_id': user_id, 'model': model, 'latency_ms': usage_info.latency_ms } return result except HolySheepAPIError as e: raise HTTPException(status_code=502, detail=str(e)) async def _stream_wrapper(stream, tenant_id: str, user_id: str, model: str): """Wrapper cho streaming response để track usage""" total_tokens = 0 async for chunk in stream: if '_final_usage' in chunk: # Ghi nhận usage cuối cùng usage = chunk['_final_usage'] rate_limiter.record_usage( tenant_id, user_id, usage['total_tokens'], model ) # Yield usage info yield f"data: {json.dumps({'_usage': usage})}\n\n" else: yield f"data: {json.dumps(chunk)}\n\n" if 'usage' in chunk: total_tokens = chunk['usage'].get('total_tokens', 0)

=== Billing Endpoints ===

@app.get("/v1/billing/usage") async def get_usage( tenant_id: str = Header(..., alias='X-Tenant-ID'), user_id: str = Header(..., alias='X-User-ID'), period: str = 'daily' # 'daily', 'weekly', 'monthly' ): """Lấy usage statistics cho user""" from billing_service import BillingService billing = BillingService() return await billing.get_usage_report(tenant_id, user_id, period) @app.get("/v1/billing/invoice/{tenant_id}") async def get_invoice(tenant_id: str): """Generate invoice cho tenant""" from billing_service import BillingService billing = BillingService() return await billing.generate_invoice(tenant_id) if __name__ == '__main__': import uvicorn uvicorn.run(app, host='0.0.0.0', port=8000)

5. Billing Service cho Usage Tracking và Invoicing

# billing_service.py
import redis
import json
import time
from typing import Dict, List, Optional
from datetime import datetime, timedelta
from dataclasses import dataclass
from config import HOLYSHEEP_PRICING

@dataclass
class UsageRecord:
    timestamp: float
    tokens: int
    model: str
    cost_usd: float

@dataclass
class BillingReport:
    tenant_id: str
    user_id: str
    period_start: datetime
    period_end: datetime
    total_tokens: int
    total_cost_usd: float
    by_model: Dict[str, int]
    by_day: Dict[str, int]
    average_latency_ms: float

class BillingService:
    """
    Service xử lý billing và usage reporting.
    Sử dụng Redis cho real-time tracking.
    """
    
    def __init__(self, redis_url: str = 'redis://localhost:6379'):
        self.redis = redis.from_url(redis_url, decode_responses=True)
    
    def get_usage_report(
        self, 
        tenant_id: str, 
        user_id: str, 
        period: str = 'daily'
    ) -> Dict:
        """Lấy usage report cho user trong period"""
        
        # Xác định thời gian
        now = datetime.now()
        if period == 'daily':
            start_date = now - timedelta(days=1)
        elif period == 'weekly':
            start_date = now - timedelta(days=7)
        else:  # monthly
            start_date = now - timedelta(days=30)
        
        # Get billing entries từ Redis
        billing_key = f"billing:{tenant_id}:{user_id}"
        entries = self.redis.lrange(billing_key, 0, -1)
        
        # Aggregate
        total_tokens = 0
        total_cost = 0.0
        by_model = {}
        by_day = {}
        
        for entry in entries:
            data = json.loads(entry)
            timestamp = data['timestamp']
            
            # Filter by period
            if timestamp < start_date.timestamp():
                continue
            
            total_tokens += data['tokens']
            total_cost += data['cost_usd']
            
            # By model
            model = data['model']
            by_model[model] = by_model.get(model, 0) + data['tokens']
            
            # By day
            day = datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d')
            by_day[day] = by_day.get(day, 0) + data['tokens']
        
        # Build response
        return {
            'tenant_id': tenant_id,
            'user_id': user_id,
            'period': period,
            'period_start': start_date.isoformat(),
            'period_end': now.isoformat(),
            'summary': {
                'total_tokens': total_tokens,
                'total_cost_usd': round(total_cost, 6),
                'average_cost_per_mtok': round(
                    (total_cost / total_tokens * 1_000_000) if total_tokens > 0 else 0, 
                    4
                )
            },
            'by_model': by_model,
            'by_day': by_day,
            'pricing_reference': HOLYSHEEP_PRICING
        }
    
    def generate_invoice(self, tenant_id: str) -> Dict:
        """Generate invoice summary cho tenant (tất cả users)"""
        
        # Lấy tất cả users của tenant
        # Trong thực tế query từ database
        user_ids = self._get_tenant_users(tenant_id)
        
        invoice_items = []
        grand_total_tokens = 0
        grand_total_cost = 0.0
        
        for user_id in user_ids:
            report = self.get_usage_report(tenant_id, user_id, 'monthly')
            if report['summary']['total_tokens'] > 0:
                invoice_items.append({
                    'user_id': user_id,
                    'tokens': report['summary']['total_tokens'],
                    'cost_usd': report['summary']['total_cost_usd'],
                    'breakdown': report['by_model']
                })
                grand_total_tokens += report['summary']['total_tokens']
                grand_total_cost += report['summary']['total_cost_usd']
        
        return {
            'invoice_id': f"INV-{tenant_id}-{int(time.time())}",
            'tenant_id': tenant_id,
            'billing_period': {
                'start': (datetime.now() - timedelta(days=30)).strftime('%Y-%m-%d'),
                'end': datetime.now().strftime('%Y-%m-%d')
            },
            'generated_at': datetime.now().isoformat(),
            'items': invoice_items,
            'subtotal_usd': round(grand_total_cost, 2),
            'tax_usd': 0,  # Tùy business model
            'total_usd': round(grand_total_cost, 2),
            'payment_methods': ['WeChat Pay', 'Alipay', 'Wire Transfer'],
            'currency': 'USD',
            'due_date': (datetime.now() + timedelta(days=30)).strftime('%Y-%m-%d')
        }
    
    def _get_tenant_users(self, tenant_id: str) -> List[str]:
        """Lấy danh sách user IDs của tenant"""
        # Scan Redis keys
        pattern = f"billing:{tenant_id}:*"
        keys = list(self.redis.scan_iter(match=pattern))
        
        users = []
        for key in keys:
            # Key format: billing:tenant_id:user_id
            parts = key.split(':')
            if len(parts) >= 3:
                users.append(parts[2])
        
        return list(set(users)) if users else []
    
    def export_csv(self, tenant_id: str, start_date: str, end_date: str) -> str:
        """Export usage data as CSV cho accounting"""
        
        start = datetime.fromisoformat(start_date)
        end = datetime.fromisoformat(end_date)
        
        rows = ['timestamp,user_id,model,tokens,cost_usd']
        
        user_ids = self._get_tenant_users(tenant_id)
        for user_id in user_ids:
            billing_key = f"billing:{tenant_id}:{user_id}"
            entries = self.redis.lrange(billing_key, 0, -1)
            
            for entry in entries:
                data = json.loads(entry