# Payment Integration & Token System Plan

## Overview
Add YooKassa payment integration to the Telegram bot via Telegram Payments API, allowing any user to purchase generation tokens. Each token = 1 video generation.

## Current State Analysis

### Bot Structure
- **File**: [telegram_bot.py](../../scripts/telegram_bot.py)
- **Framework**: python-telegram-bot with async/await
- **Persistence**: PicklePersistence (`/mnt/video/bot_data_{source}.pickle`)
- **Access Control**: Whitelist via `ALLOWED_USERS` env var (lines 60-71)
- **No database** - all data in files (activity.log, metadata.json, product_feedback.json)

### Key Integration Points
- `is_user_allowed()` (line 63) - Currently checks whitelist, will check token balance
- `run_video_pipeline()` (line 286) - Main generation function, need to deduct tokens here
- `handle_url()` (line 473) - Entry point for generation requests

---

## Architecture

### 1. Separate Databases (Dev/Prod)

```
/mnt/video/
├── videobot_dev.db      # Dev bot database
├── videobot_prod.db     # Prod bot database
├── bot_data_dev.pickle  # Dev bot state (existing)
└── bot_data_prod.pickle # Prod bot state (existing)
```

Database path determined by `BUILD_SOURCE` env var (already used in bot).

### 2. Database Schema (SQLite)

```sql
-- Users table
CREATE TABLE users (
    user_id INTEGER PRIMARY KEY,      -- Telegram user ID
    username TEXT,                     -- @username (optional)
    first_name TEXT,
    last_name TEXT,
    balance INTEGER DEFAULT 0,         -- Token balance
    total_purchased INTEGER DEFAULT 0, -- Lifetime tokens purchased
    total_spent INTEGER DEFAULT 0,     -- Lifetime tokens used
    is_promo_eligible INTEGER DEFAULT 0, -- 1 if user can buy at promo price
    promo_purchases INTEGER DEFAULT 0, -- Number of promo purchases made
    is_blocked INTEGER DEFAULT 0,      -- Admin can block users
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Promo tracking (global counter)
CREATE TABLE promo_config (
    key TEXT PRIMARY KEY,
    value TEXT NOT NULL
);
-- INSERT INTO promo_config VALUES ('promo_users_remaining', '100');

-- Comprehensive transaction log (audit trail)
CREATE TABLE transactions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL,
    amount INTEGER NOT NULL,           -- Positive = credit, negative = debit
    balance_before INTEGER NOT NULL,   -- Balance before this transaction
    balance_after INTEGER NOT NULL,    -- Balance after this transaction
    type TEXT NOT NULL,                -- 'purchase', 'generation', 'admin_grant', 'admin_revoke', 'refund', 'migration'
    description TEXT,                  -- Human-readable description

    -- Payment details (for purchases)
    telegram_payment_charge_id TEXT,   -- Telegram's payment ID
    provider_payment_charge_id TEXT,   -- CloudPayments transaction ID
    amount_rub INTEGER,                -- Price in kopecks
    currency TEXT,                     -- 'RUB'

    -- Generation details (for token usage)
    task_id TEXT,                      -- Video generation task ID
    product_id TEXT,                   -- WB product ID

    -- Metadata
    initiated_by INTEGER,              -- Admin user_id if admin action
    ip_address TEXT,                   -- For fraud detection (future)
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    FOREIGN KEY (user_id) REFERENCES users(user_id)
);

-- Index for fast lookups
CREATE INDEX idx_transactions_user_id ON transactions(user_id);
CREATE INDEX idx_transactions_type ON transactions(type);
CREATE INDEX idx_transactions_created_at ON transactions(created_at);
CREATE INDEX idx_transactions_task_id ON transactions(task_id);
```

### 3. Bot Architecture (Separate Admin Bot)

```
┌─────────────────────────────────────┐
│  Main Bots (2 instances)            │
│  ├── videobot-dev  (dev token)      │
│  │   └── Uses: videobot_dev.db      │
│  └── videobot-prod (prod token)     │
│      └── Uses: videobot_prod.db     │
│  Commands: /start, /buy, /balance   │
│  Accept WB URLs, generate videos    │
└─────────────────────────────────────┘

┌─────────────────────────────────────┐
│  Admin Bot (ONE for both envs)      │
│  Location: ~/viewer (existing)      │
│  - /dev  - Switch to DEV database   │
│  - /prod - Switch to PROD database  │
│  - /users - List all users          │
│  - /user <id> - User details        │
│  - /grant <id> <amount> - Add tokens│
│  - /revoke <id> <amount> - Remove   │
│  - /block <id> - Block user         │
│  - /stats - Overall statistics      │
│  - /transactions - Recent activity  │
│  - /search <query> - Search users   │
│  Status shows: "🔧 DEV" or "🚀 PROD"│
└─────────────────────────────────────┘
```

### 4. New Files

```
scripts/
├── database.py           # SQLite connection, migrations, CRUD
├── token_manager.py      # Token balance operations
├── payment_handlers.py   # Telegram payment handlers for main bot
└── (viewer/ uses shared database.py and token_manager.py)

viewer/                   # In this repo, pulled to ~/viewer
├── viewer_bot.py         # Extend with admin commands
├── data_reader.py        # Existing
├── search.py             # Existing
└── session.py            # Existing
```

### 5. Payment Flow

```
User: /buy
    ↓
Check if user is promo-eligible:
  - First N users (PROMO_USER_LIMIT) get promo pricing
  - Tracked via promo_config table
    ↓
Bot: Shows token packages with prices
    │
    ├─[PROMO USER]→ "🎁 Промо-цены для первых пользователей!"
    │               1 token = 99₽, 5 = 499₽, 10 = 999₽
    │
    └─[REGULAR]→    1 token = 699₽, 5 = 2499₽, 10 = 3999₽
    ↓
User: Selects package
    ↓
Bot: Sends invoice via Telegram Payments API (YooKassa provider)
    ↓
User: Pays in Telegram interface
    ↓
Telegram: pre_checkout_query → Bot: answer(ok=True)
    ↓
Telegram: successful_payment message
    ↓
Bot:
  1. Create transaction record (with balance_before/after, promo flag)
  2. Credit tokens to user
  3. Update user totals
  4. If promo: decrement promo_users_remaining
  5. Send confirmation
    ↓
User: Can now generate videos
```

### 6. Generation Flow Changes

```
User sends WB URL
    ↓
[DEV BOT ONLY] Check ALLOWED_USERS whitelist
    │
    ├─[NOT IN WHITELIST]→ "Доступ запрещён"
    │
    └─[OK]
        ↓
Check user exists in DB (auto-create if not)
    ↓
Check is_blocked == 0
    │
    ├─[BLOCKED]→ "Ваш аккаунт заблокирован"
    │
    └─[OK]
        ↓
Check balance >= 1 token
    │
    ├─[NO]→ "Недостаточно токенов. /buy для покупки"
    │
    └─[YES]
        ↓
    Create transaction: type='generation', amount=-1
    Record balance_before, balance_after
        ↓
    Run pipeline...
        │
        ├─[SUCCESS]→ Keep transaction, update description with task_id
        │
        └─[ERROR]→ Create refund transaction: type='refund', amount=+1
                   Record error in description
```

**Dev Bot Access Control:**
- Keep `ALLOWED_USERS` whitelist (100000001, 100000002, 100000003)
- Whitelisted users can buy tokens and generate videos

**Prod Bot Access Control (future):**
- Remove whitelist - open to anyone
- Anyone can buy tokens and generate videos

---

## Implementation Steps

### Phase 1: Database Layer
1. Create `scripts/database.py`:
   - `get_db_path()` - Returns path based on BUILD_SOURCE
   - `init_db()` - Create tables if not exist
   - `get_connection()` - Context manager for connections
   - User CRUD operations
   - Transaction logging with full audit trail

2. Create `scripts/token_manager.py`:
   - `get_or_create_user(user_id, username, first_name)` → User dict
   - `get_balance(user_id)` → int
   - `has_tokens(user_id, count=1)` → bool
   - `is_blocked(user_id)` → bool
   - `deduct_token(user_id, task_id, product_id)` → transaction_id
   - `refund_token(user_id, original_txn_id, reason)` → bool
   - `credit_tokens(user_id, amount, type, description, payment_info=None, admin_id=None)` → bool
   - `get_user_transactions(user_id, limit=20)` → list
   - `get_user_stats(user_id)` → dict

### Phase 2: Payment Handlers
1. Create `scripts/payment_handlers.py`:
   - Token package definitions (1/5/10 tokens with prices)
   - `buy_command()` - Show package selection buttons
   - `handle_buy_callback()` - Send invoice via `bot.send_invoice()`
   - `precheckout_callback()` - Validate pre-checkout (answer within 10 sec)
   - `successful_payment_callback()` - Credit tokens, log transaction

2. YooKassa already configured:
   - Dev test token: `YOUR_PAYMENT_PROVIDER_TOKEN`
   - Add `PAYMENT_PROVIDER_TOKEN` to .env

### Phase 3: Main Bot Integration
1. Modify `telegram_bot.py`:
   - Import database and token_manager
   - Remove `ALLOWED_USERS` whitelist logic
   - Replace `is_user_allowed()` with balance + blocked check
   - Add token deduction in `run_video_pipeline()`
   - Add refund on generation failure
   - Register payment handlers

2. Add user commands:
   - `/buy` - Purchase tokens
   - `/balance` - Check token balance + recent transactions

### Phase 4: Extend Viewer Bot with Admin Features
1. Copy viewer bot into this repo:
   ```bash
   cp -r ~/viewer /home/videobot/dev/viewer
   rm -rf /home/videobot/dev/viewer/.git  # Remove separate git history
   ```
   - Import shared `database.py` and `token_manager.py` from `../scripts/`
   - Add database switching (dev/prod)
   - Restricted to ALLOWED_USERS only (already has this)

2. Add new admin commands:
   - `/dev` / `/prod` - Switch active database (shows current in status)
   - `/users [page]` - Paginated user list with balances
   - `/user <id>` - Full user info + transaction history
   - `/grant <id> <amount> [reason]` - Grant tokens
   - `/revoke <id> <amount> [reason]` - Remove tokens
   - `/block <id> [reason]` - Block user
   - `/unblock <id>` - Unblock user
   - `/transactions [limit]` - Recent transactions across all users
   - `/promo` - Show promo status (remaining slots, users)
   - `/promo_add <id>` - Make user promo-eligible
   - `/promo_set <count>` - Set remaining promo slots
   - `/export` - Export transactions to CSV

3. Deployment:
   - Code in `/home/videobot/dev/viewer/`
   - Symlink or `git pull` to `~/viewer/`
   - Existing service: `viewer-bot.service`

### Phase 5: Migration & Testing
1. Migration script:
   - Read `ALLOWED_USERS` from .env (100000001, 100000002)
   - Create user records for each
   - Grant 1000 tokens to each
   - Log as "migration" transaction with balance_before=0, balance_after=1000

2. Testing:
   - YooKassa test mode (test token already set)
   - Test card: `4242 4242 4242 4242` (expiry: any future, CVV: any 3 digits)
   - Full purchase → generation flow
   - Refund on failed generation
   - Admin bot commands

---

## Configuration

### New .env Variables (Main Bot)
```bash
# Database (auto-determined by BUILD_SOURCE, but can override)
# DB_PATH=/mnt/video/videobot_dev.db

# YooKassa provider token (from BotFather → Payments → YooKassa)
# TEST token for dev bot:
PAYMENT_PROVIDER_TOKEN=YOUR_PAYMENT_PROVIDER_TOKEN
# For production: get LIVE token from BotFather

# Token pricing - REGULAR (in kopecks, 1 RUB = 100 kopecks)
TOKEN_PRICE_1=69900      # 1 token = 699 RUB
TOKEN_PRICE_5=249900     # 5 tokens = 2499 RUB
TOKEN_PRICE_10=399900    # 10 tokens = 3999 RUB

# Token pricing - PROMO (reduced for first N users)
PROMO_PRICE_1=9900       # 1 token = 99 RUB
PROMO_PRICE_5=49900      # 5 tokens = 499 RUB
PROMO_PRICE_10=99900     # 10 tokens = 999 RUB
PROMO_USER_LIMIT=100     # Number of users who can buy at promo price
```

### Admin Bot .env
```bash
# Admin bot token (existing viewer bot)
ADMIN_BOT_TOKEN=<existing_viewer_bot_token>

# Admin users (comma-separated Telegram IDs)
ADMIN_USERS=100000001

# Database paths (admin bot can access both)
DB_PATH_DEV=/mnt/video/videobot_dev.db
DB_PATH_PROD=/mnt/video/videobot_prod.db
```

### YooKassa Setup (Already Done)
- Test token for dev bot: `YOUR_PAYMENT_PROVIDER_TOKEN`
- For production: In @BotFather → /mybots → prod bot → Payments → YooKassa → get LIVE token

---

## Files Summary

| File | Purpose |
|------|---------|
| [telegram_bot.py](../../scripts/telegram_bot.py) | Modify: Add token checks, payment handlers (keep whitelist for dev) |
| `.env` | Add: YooKassa token, pricing config |
| NEW: [database.py](../../scripts/database.py) | SQLite layer with full audit logging |
| NEW: [token_manager.py](../../scripts/token_manager.py) | Token balance operations |
| NEW: [payment_handlers.py](../../scripts/payment_handlers.py) | Payment command handlers |
| COPY: [viewer/](../../viewer/) | Copy viewer bot code into this repo |
| [viewer/viewer_bot.py](../../viewer/viewer_bot.py) | Extend: Add admin commands for token management |
| `viewer/.env` | Add: DB paths for dev/prod |
| NEW: [docs/plans/payment-integration.md](payment-integration.md) | This plan (for reference) |
| NEW: `docs/payments.md` | Payment system documentation |

**Deployment**: `git pull` in ~/viewer to get updated viewer bot code

---

## Documentation

After implementation, update the following:
1. **docs/payments.md** - Payment system documentation (pricing, promo, admin commands)
2. **CLAUDE.md** - Add payment system section
3. **README.md** (if exists) - Add setup instructions for payments

Plan saved to: `docs/plans/payment-integration.md`

---

## Verification Plan

1. **Database**:
   - Run init script, verify schema created
   - Check separate DBs for dev/prod

2. **Token operations**:
   - Test credit/debit/balance functions
   - Verify transaction log captures all fields
   - Test balance_before/after correctness

3. **Payment flow** (test mode):
   - `/buy` shows packages
   - Select package → invoice appears
   - Pay with test card `4242 4242 4242 4242`
   - Verify tokens credited
   - Verify transaction logged with payment IDs

4. **Generation flow**:
   - Send WB URL with 0 balance → "Insufficient tokens" message
   - Grant token via admin → generation works
   - Verify token deducted, transaction logged with task_id
   - Force error → verify refund transaction created

5. **Admin bot**:
   - Test all admin commands
   - Verify can switch between dev/prod DBs
   - Test grant/revoke with transaction logging

6. **Edge cases**:
   - Generation fails → token refunded
   - Double-click protection on payments
   - Blocked user cannot generate

---

## Decisions

1. **Payment method**: YooKassa via Telegram Payments API
   - Test token: `YOUR_PAYMENT_PROVIDER_TOKEN`
   - Production: Get LIVE token from BotFather
2. **Token pricing** (regular):
   - 1 token = 699 RUB
   - 5 tokens = 2499 RUB
   - 10 tokens = 3999 RUB
3. **Promo pricing** (limited users):
   - 1 token = 99 RUB
   - 5 tokens = 499 RUB
   - 10 tokens = 999 RUB
   - Limited to first N users (configurable)
4. **Free trial**: No free tokens for new users
5. **Migration**: Grant 1000 tokens to existing whitelisted users
6. **Refund policy**: Auto-refund on generation failure
7. **Admin**: Viewer bot in this repo (`dev/viewer/`), deployed to `~/viewer`
8. **Database**: Separate SQLite files for dev/prod (`videobot_dev.db`, `videobot_prod.db`)
9. **Audit**: Full transaction log with balance_before/after, initiated_by, task_id, product_id
10. **Access control**:
    - Dev bot: Keep `ALLOWED_USERS` whitelist (100000001, 100000002, 100000003)
    - Prod bot (future): Open to anyone with tokens
