Commit Graph

60 Commits

Author SHA1 Message Date
Fringg afea054c8f feat: integrate Lava Business payment provider
- Lava Business via gate.lava.ru (HMAC-SHA256 signed JSON requests)
- Sub-methods: card and SBP via includeService filter
- Webhook signature verified from raw bytes with secret_key_2
- Sticky terminal-status guard (success after amount_mismatch escalates to ERROR)
- Order ID with full uuid4 hex (128-bit entropy)
- Cross-row contamination guard: order_id assertion on invoice_id fallback
- Warning when hook URL cannot be derived from webhook/web_api/cabinet bases
- Explicit failure when Lava response lacks payment_url (no orphan rows)
- Adds LAVA settings category, /lava-webhook endpoint, cabinet topup branch
- Mirrors existing Antilopay/Jupiter/Donut mixin pattern
2026-05-04 20:14:31 +03:00
Fringg f321ded9c0 feat: integrate Jupiter (FPGate P2P) and Donut payment providers
- Jupiter: SBP via app.juppiter.tech (FPGate P2P v2.1)
- Donut: CARD/SBP/SBP_QR via gw.donut.business (Donut P2P)
- HMAC-SHA256 signing verified against spec reference vectors
- Sticky terminal-status guard in callback (amount_mismatch/declined/cancelled
  cannot be re-credited by replayed webhook)
- Mirrors existing Antilopay/Etoplatezhi mixin pattern: service, mixin, CRUD,
  Alembic migration, handlers, keyboards, webhook, cabinet route, status mapping
- Adds JUPITER and DONUT settings categories with title/description/prefix
- Backfills missing ANTILOPAY and ETOPLATEZHI category metadata
2026-05-04 19:36:22 +03:00
Fringg a506c6be00 fix: add 5 missing payment providers to pending-payments model_map 2026-04-29 07:40:50 +03:00
Fringg 2c3ffc8c8a feat: integrate Overpay payment provider (pay.overpay.io)
Full integration across bot, cabinet, admin panel and landing pages:

- Config: 16 OVERPAY_* settings (API URL, credentials, P12 cert path,
  project ID, currency, amount limits, webhook path, payment methods)
- Service: overpay_service.py with httpx mTLS (P12 cert) + Basic Auth,
  create_payment, get_payment, refund_payment methods
- Payment mixin: OverpayPaymentMixin with create, webhook processing,
  finalize (balance credit + notifications), status check
- Model: OverpayPayment table + OVERPAY enum value
- CRUD: 9 standard operations (create, get_by_*, for_update, link)
- Bot handler: start_overpay_topup + process_overpay_payment_amount
- Handler registration: route_payment_by_method + callback registration
- Webhook: POST /overpay-webhook with DB-based anti-spoofing validation
- Cabinet: balance topup + guest payment dispatch
- Keyboard: payment method button in bot
- Admin: settings category + test payment button
- Infrastructure: payment_method_config_service, system_settings_service,
  payment_verification_service, payment_search_service
- Migration 0064: create overpay_payments table

Overpay API specifics: amount as string "100.00" (not kopeks),
success status "charged", HPP redirect via resultUrl
2026-04-23 04:36:56 +03:00
Fringg 97179360c0 feat: integrate AuraPay payment provider
Full integration following PayPear/RollyPay patterns:
- API client with X-ApiKey + X-ShopId auth, HMAC-SHA256 webhook verification
  (sorted keys, concatenated values, secret key #2)
- AuraPayPaymentMixin with create, webhook, finalize (all side effects), status check
- CRUD, model, migration (0060), PaymentMethod.AURAPAY enum
- Webhook endpoint, cabinet topup, bot handler with sub-options (card, sbp)
- Admin panel: AURAPAY category in bot_configuration + system_settings_service
- Config: AURAPAY_ENABLED, AURAPAY_API_KEY, AURAPAY_SHOP_ID, AURAPAY_SECRET_KEY
2026-04-18 00:02:49 +03:00
Fringg a59858227f fix: support payment_method selection for RollyPay (sbp/card/crypto)
- Mixin accepts payment_method_type parameter (None = show all on form)
- API service sends payment_method only when specified
- Cabinet route passes payment_option to mixin
- Config service has sub_options: sbp, card, crypto
- Keyboard label no longer hardcodes "СБП"
2026-04-16 06:03:33 +03:00
Fringg ccc2f4efec feat: integrate RollyPay payment provider (SBP via USDT)
Full integration following PayPear/SeverPay patterns:
- API client with X-API-Key + X-Nonce auth, HMAC-SHA256 webhook verification
- RollyPayPaymentMixin with create, webhook, finalize (all side effects), status check
- CRUD, model, migration (0059), PaymentMethod.ROLLYPAY enum
- Webhook endpoint, cabinet topup, bot handler
- Statuses: created, processing, paid, expired, canceled, chargeback
- Config: ROLLYPAY_ENABLED, ROLLYPAY_API_KEY, ROLLYPAY_SIGNING_SECRET, etc.
2026-04-16 05:52:25 +03:00
Fringg a18f6caa9b feat: integrate PayPear payment provider
Full integration following SeverPay patterns:
- API client with Basic Auth, idempotency, HMAC webhook verification
- PayPearPaymentMixin with create, webhook, finalize (all side effects), status check
- CRUD, model, migration (0058), PaymentMethod.PAYPEAR enum
- Webhook endpoint, cabinet topup, bot handler, payment verification
- Sub-options: bank_card, sbp, sberpay, tpay
- Config: PAYPEAR_ENABLED, PAYPEAR_SHOP_ID, PAYPEAR_SECRET_KEY, etc.
2026-04-16 05:36:48 +03:00
Fringg 9d63635502 feat: add SberPay as KassaAI sub-method (payment_system_id=43)
Adds SberPay alongside existing SBP (44) and Card (36) sub-methods.

Changes across all 8 required files:
- config.py: KASSA_AI_SBERPAY_ENABLED, display name, helper methods
- kassa_ai_service.py: payment_system_id=43 in KASSA_AI_SUB_METHODS
- kassa_ai.py handler: method config + start_kassa_ai_sberpay_topup
- main.py: route tuple, import, handler registration
- payment_service.py: guest purchase flow method check
- cabinet/balance.py: KASSA_AI_OPTION_MAP sberpay=43
- payment_method_config_service.py: sub_option for admin panel
- inline.py: keyboard button + fallback condition guard

Env vars: KASSA_AI_SBERPAY_ENABLED, KASSA_AI_SBERPAY_DISPLAY_NAME
2026-04-02 06:47:57 +03:00
Fringg 6713921887 fix: Pal24 card/sbp option not passed to API in cabinet balance topup
The payment_option (card/sbp) was parsed from the request but never
passed to create_pal24_payment as payment_method. Without it,
_normalize_payment_method(None) defaults to 'sbp', so both Card and
SBP buttons always created SBP payments.
2026-04-02 06:20:21 +03:00
Fringg 092b9f63b2 feat: add SeverPay support to cabinet balance top-up
SeverPay was missing from the cabinet create_topup() endpoint,
causing "This payment method is only available through the Telegram bot"
error when users tried to pay via SeverPay in the web cabinet.
2026-03-28 19:17:56 +03:00
Fringg 2f19c76357 fix: add user ID to payment descriptions for all providers and fix tuple bug
- Add telegram_user_id and user_db_id to get_balance_payment_description() across
  8 cabinet balance providers (heleket, mulenpay, pal24, wata, cloudpayments,
  freekassa, kassa_ai, riopay), all miniapp endpoints, and recurrent payments
- For email/OAuth users without telegram_id, fallback to DB ID with (U{id}) format
- Fix pre-existing tuple bug in bot_configuration.py (trailing comma created tuple)
- Fix typo in nalogo_queue_service.py log message ("Чек уже попыток")
2026-03-23 14:48:12 +03:00
Fringg 3875335cd7 fix: narrow exception handling and fix session leak in gift.py
- Replace broad `except Exception` with `except TelegramAPIError` in
  balance.py and wheel.py Stars invoice creation (prevents masking
  programming errors)
- Fix session leak in gift.py telegram_stars path: wrap PaymentService
  usage in try/finally to ensure bot.session.close() is called
2026-03-21 02:55:48 +03:00
Fringg 0a53b85b8a refactor: centralize Bot instantiation via create_bot() factory
Replace all ~45 direct Bot() calls across the codebase with a centralized
create_bot() factory function that automatically configures SOCKS5 proxy
session when PROXY_URL is set. This ensures proxy support applies uniformly
to all Telegram API traffic.

Key changes:
- Add app/bot_factory.py with create_bot() factory
- Replace direct Bot() instantiation in 33 files
- Fix session leaks in cloudpayments.py and auth.py (async with)
- Replace 2 direct httpx calls to api.telegram.org with
  bot.create_invoice_link() (balance.py, wheel.py)
- Remove now-unused imports (Bot, DefaultBotProperties, ParseMode, httpx)
2026-03-21 02:49:37 +03:00
Fringg dcff6947dd style: ruff format 2026-03-18 01:59:12 +03:00
Fringg 4abb8cb1a3 fix: исправлены проблемы RioPay интеграции после ревью
- Модель: user_id nullable=True + ondelete='SET NULL' (не применилось ранее)
- order_id для гостей: 'rpguest_xxx' вместо 'rpNone_xxx'
- Миграция: добавлено пересоздание FK с ON DELETE SET NULL
- get_latest_payment_by_method: добавлен RioPayPayment в model_map
2026-03-18 00:18:15 +03:00
Fringg 3d1fbc70f8 feat: добавлена поддержка RioPay в кабинете
- Добавлен RioPay в create_topup endpoint (cabinet balance)
- Добавлен маппинг статусов RioPay в _get_status_info
- Добавлена поддержка ручной проверки RioPay платежей
- Добавлена автопроверка RioPay в payment_verification_service
- Добавлены success_url/fail_url параметры в create_riopay_payment mixin
2026-03-18 00:05:07 +03:00
root 04419fdff7 feat: add SBP and Card sub-options to kassa_ai payment method
- kassa_ai shows single admin entry with СБП/Карта sub-option checkboxes
- SBP routes to payment_system_id=44, Card to payment_system_id=36
- Bot: added kassa_ai_sbp/card handlers and FSM flow (mirrors freekassa pattern)
- Cabinet: KASSA_AI_OPTION_MAP reads payment_option to select correct ps_id
- Config: KASSA_AI_SBP_ENABLED / KASSA_AI_CARD_ENABLED env vars + helpers
- Guest payments: kassa_ai_sbp/card supported in landing page checkout
- payment_method_config_service: kassa_ai has available_sub_options=[sbp,card]
2026-03-16 04:12:41 +00:00
Fringg 641ff86bf6 fix: stars rate rounding + device/traffic purchase stats
- Stars: ceil → round в rubles_to_stars, нормализация kopeks в cabinet invoice
- Устройства/трафик: добавлен transaction_type в subtract_user_balance,
  покупки устройств и трафика теперь создают SUBSCRIPTION_PAYMENT (не WITHDRAWAL),
  что исправляет отображение в статистике продаж
2026-03-10 21:50:20 +03:00
FireWookie 9ad684c8c9 Merge pull request #7 from FireWookie/dev
Dev
2026-03-10 14:42:53 +05:00
FireWookie d147be0316 Merge pull request #6 from FireWookie/dev
Dev
2026-03-10 14:42:05 +05:00
firewookie fd3466b75c fix PR problems 2026-03-10 14:29:29 +05:00
Fringg fcdeff1ee5 fix: migrate pricing to days-based proration, fix promo revenue leaks, fix admin panel bugs
- Migrate all addon pricing (devices, traffic, countries) from months-based to days-based proration
- Remove get_remaining_months() utility, use days_left / 30 consistently
- Fix promo/campaign balance bonuses counted as revenue in reports (add REAL_PAYMENT_METHODS filter)
- Fix partner stats, campaign stats, miniapp stats, referral fraud detection promo deposit leaks
- Fix admin balance history showing deductions with + sign (use -abs for expense types)
- Fix promo offer deactivation returning 400 for non-promocode offers
- Fix daily tariff renewal requesting 30-day renewal instead of 1-day purchase
2026-03-10 03:31:07 +03:00
Fringg 95a32e8574 fix: payment gateway issues — YooKassa polling, PAL24 card 500
- YooKassa: return local_payment_id instead of UUID for frontend polling
  (parseInt on UUID produced wrong ID → eternal spinner)
- PAL24: remove unsupported payment_method param from API call
  (cabinet and miniapp routes — URL selection is client-side)
2026-03-09 21:53:53 +03:00
firewookie be2ec091a6 Правки по замечаниям 2026-03-09 14:06:00 +05:00
Fringg 275f249bbd fix: encode payment status in provider return URLs and wire failed_url
- Add &status=success/failed to cabinet return URLs for instant UX feedback
  without needing API auth in external browser
- Platega: pass cabinet_failed_url (was hardcoded to server URL)
- Heleket: add success_url param, pass cabinet_success_url for url_success
- WATA: add failed_url param, pass cabinet_failed_url to failRedirectUrl
- CloudPayments: add failed_url param, pass cabinet_failed_url
- Strip trailing slash from CABINET_URL for safety
2026-03-09 04:59:56 +03:00
Fringg 7a9264b173 fix: latest-payment endpoint returns all payments, not just pending
The /latest endpoint was using list_recent_pending_payments which only
returns unpaid payments. By the time the user returns from the payment
provider, the webhook has already marked the payment as paid, so the
endpoint returned 404. Now queries the payment table directly without
filtering by is_paid status.
2026-03-09 04:41:25 +03:00
Fringg 32d58b04b9 fix: add method query param to return_url and latest-payment endpoint
Payment providers redirect to external browser where sessionStorage is
unavailable. Now includes method in return_url query params and adds
GET /pending-payments/{method}/latest endpoint so TopUpResult can poll
payment status without sessionStorage data.
2026-03-09 04:34:14 +03:00
Fringg 7ca96195a7 fix: pass cabinet return_url to payment providers for top-up redirects
Payment providers were redirecting users back to the bot after completing
cabinet top-up payments. Now passes CABINET_URL/balance/top-up/result as
return_url to YooKassa, Platega, Heleket, WATA, and CloudPayments.
2026-03-09 04:16:10 +03:00
FireWookie 26daf9f6c8 Merge pull request #4 from FireWookie/main
Merge as main project
2026-03-08 09:32:37 +05:00
firewookie aaffc26a90 - Интеграция рекурентов от Юкассы
- Багфикс личного кабинета
2026-03-06 09:47:58 +05:00
Fringg 4984f20e8f fix: устранение race conditions и атомарность платёжной системы
- SELECT FOR UPDATE блокировка во всех 9 провайдерах (кроме YooKassa — свой паттерн)
- create_transaction(commit=False) + единый db.commit() для атомарности
- emit_transaction_side_effects() для отложенных событий после коммита
- Все link_*_payment_to_transaction используют db.flush() вместо db.commit()
- Freekassa/KassaAI: прямое присвоение transaction_id + flush вместо update_status
- MulenPay: прямая мутация balance_kopeks вместо add_user_balance
- Platega: блокировка перед чтением metadata, инлайн обновления полей
- CloudPayments: int(round(amount * 100)) для корректного округления
- Heleket добавлен в SUPPORTED_AUTO_CHECK_METHODS
- Удалены PII из логов yookassa webhook (заголовки, IP)
- UniqueConstraint(external_id, payment_method) на транзакциях + миграция 0017
- Cabinet: PaymentService(bot=bot) внутри try блока
- verify_payment_amount утилита для проверки суммы webhook
2026-03-06 04:20:41 +03:00
Fringg faba3a8ed6 fix: enforce user restrictions in cabinet API and fix poll history crash
- Add restriction_topup check to POST /cabinet/balance/topup
- Add restriction_subscription check to 6 subscription endpoints:
  /renew, /purchase, /purchase-tariff, /traffic, /devices/purchase, /devices (legacy)
- All restricted endpoints return 403 Forbidden
- Fix TypeError in broadcast history when message_text is None (polls)
2026-03-01 20:59:06 +03:00
Fringg 1f0fef114b refactor: complete structlog migration with contextvars, kwargs, and logging hardening
- Add ContextVarsMiddleware for automatic user_id/chat_id/username binding
  via structlog contextvars (aiogram) and http_method/http_path (FastAPI)
- Use bound_contextvars() context manager instead of clear_contextvars()
  to safely restore previous state instead of wiping all context
- Register ContextVarsMiddleware as outermost middleware (before GlobalError)
  so all error logs include user context
- Replace structlog.get_logger() with structlog.get_logger(__name__) across
  270 calls in 265 files for meaningful logger names
- Switch wrapper_class from BoundLogger to make_filtering_bound_logger()
  for pre-processor level filtering (performance optimization)
- Migrate 1411 %-style positional arg logger calls to structlog kwargs
  style across 161 files via AST script
- Migrate log_rotation_service.py from stdlib logging to structlog
- Add payment module prefixes to TelegramNotifierProcessor.IGNORED_LOGGER_PREFIXES
  and ExcludePaymentFilter.PAYMENT_MODULES to prevent payment data leaking
  to Telegram notifications and general log files
- Fix LoggingMiddleware: add from_user null-safety for channel posts,
  switch time.time() to time.monotonic() for duration measurement
- Remove duplicate logger assignments in purchase.py, config.py,
  inline.py, and admin/payments.py
2026-02-16 09:18:12 +03:00
Fringg 3193ffbd1b fix: change CryptoBot URL priority to bot_invoice_url for Telegram opening 2026-02-11 05:50:43 +03:00
Fringg 2cb6d731e9 fix: stop CryptoBot webhook retry loop and save cabinet payments to DB
Cabinet was calling CryptoBotService.create_invoice() directly without
saving CryptoBotPayment to DB. When webhook arrived, payment lookup
failed and returned HTTP 400, causing infinite retries.

Now cabinet uses PaymentService.create_cryptobot_payment() (same as
miniapp) with proper USD conversion via currency_converter.

Also return HTTP 200 for unknown invoice_ids to stop retry spam.
2026-02-10 07:25:54 +03:00
Fringg ff5bba3fc5 fix: use PaymentService for cabinet YooKassa payments to save local DB record
Cabinet was calling YooKassaService.create_payment() directly, bypassing
PaymentService which saves the payment record to the local database.
When YooKassa webhook arrived, the payment was not found in the DB,
causing payment processing failures.

Now uses PaymentService.create_yookassa_payment() and
create_yookassa_sbp_payment() consistently with all other payment methods.
Also standardizes metadata key from 'type' to 'purpose' to match bot flow.
2026-02-07 10:35:08 +03:00
Egor 7000cd5bc2 Update balance.py 2026-01-30 21:04:46 +03:00
Mikhail 6551ac1fe9 Merge branch 'main' into main 2026-01-28 13:55:24 +03:00
Egor 0c3070a0cc Add Kassa AI payment method support 2026-01-28 11:56:02 +03:00
gy9vin 95b7152c05 касса и прочее 2026-01-27 23:47:39 +03:00
Egor 6ce42357c5 Add files via upload 2026-01-27 01:36:18 +03:00
Egor 7019799f4c Add files via upload 2026-01-26 22:37:32 +03:00
Egor 36acd7a66a Update balance.py 2026-01-26 20:34:18 +03:00
c0mrade 9a2aea038a chore: add uv package manager and ruff linter configuration
- Add pyproject.toml with uv and ruff configuration
- Pin Python version to 3.13 via .python-version
- Add Makefile commands: lint, format, fix
- Apply ruff formatting to entire codebase
- Remove unused imports (base64 in yookassa/simple_subscription)
- Update .gitignore for new config files
2026-01-24 17:45:27 +03:00
Egor 626c67a7a7 Update balance.py 2026-01-22 21:52:43 +03:00
Egor d9a4af341e Update balance.py 2026-01-21 09:31:43 +03:00
Egor a56daca368 Update balance.py 2026-01-21 07:34:25 +03:00
Egor 64fe45fcfc Update balance.py 2026-01-17 08:40:37 +03:00
Egor 5eec0aa1a0 Update balance.py 2026-01-16 18:13:25 +03:00