Tribute/ Robokassa

This commit is contained in:
Vladless
2025-08-12 01:18:24 +03:00
parent 83d93a833d
commit b61c3daca8
7 changed files with 62 additions and 25 deletions
+1
View File
@@ -96,6 +96,7 @@ WATA_SBP = "🏦 WATA: СБП"
WATA_INT = "🌍 WATA: Международные карты"
KASSAI_CARDS = "💳 KassaAI: Карты РФ"
KASSAI_SBP = "🏦 KassaAI: СБП"
TRIBUTE = "💳 Tribute"
# Кнопки Heleket
HELEKET_CRYPTO = "₿ Heleket: Crypto"
+13
View File
@@ -22,6 +22,8 @@ from config import (
WATA_SBP_ENABLE,
YOOKASSA_ENABLE,
YOOMONEY_ENABLE,
TRIBUTE_ENABLE,
TRIBUTE_LINK
)
from database import get_last_payments
from database.models import User
@@ -42,6 +44,7 @@ from handlers.buttons import (
WATA_SBP,
YOOKASSA,
YOOMONEY,
TRIBUTE,
)
from handlers.payments.cryprobot_pay import process_callback_pay_cryptobot
from handlers.payments.freekassa_pay import process_callback_pay_freekassa
@@ -52,6 +55,7 @@ from handlers.payments.stars_pay import process_callback_pay_stars
from handlers.payments.wata import process_callback_pay_wata
from handlers.payments.yookassa_pay import process_callback_pay_yookassa
from handlers.payments.yoomoney_pay import process_callback_pay_yoomoney
from handlers.payments.tribute_pay import process_callback_pay_tribute
from handlers.texts import BALANCE_MANAGEMENT_TEXT, PAYMENT_METHODS_MSG
from hooks.hook_buttons import insert_hook_buttons
from hooks.hooks import run_hooks
@@ -84,6 +88,8 @@ async def handle_pay(callback_query: CallbackQuery, state: FSMContext, session:
payment_handlers.append(process_callback_pay_robokassa)
if FREEKASSA_ENABLE:
payment_handlers.append(process_callback_pay_freekassa)
if TRIBUTE_ENABLE:
payment_handlers.append(process_callback_pay_tribute)
if len(payment_handlers) == 1:
await callback_query.answer()
@@ -114,6 +120,8 @@ async def handle_pay(callback_query: CallbackQuery, state: FSMContext, session:
builder.row(InlineKeyboardButton(text=WATA_SBP, callback_data="pay_wata_sbp"))
if WATA_INT_ENABLE:
builder.row(InlineKeyboardButton(text=WATA_INT, callback_data="pay_wata_int"))
if TRIBUTE_ENABLE:
builder.row(InlineKeyboardButton(text=TRIBUTE, url=TRIBUTE_LINK))
if DONATIONS_ENABLE:
builder.row(InlineKeyboardButton(text="💰 Поддержать проект", callback_data="donate"))
@@ -211,3 +219,8 @@ async def handle_pay_kassai_sbp(callback_query: CallbackQuery, state: FSMContext
@router.callback_query(F.data == "pay_heleket_crypto")
async def handle_pay_heleket_crypto(callback_query: CallbackQuery, state: FSMContext, session: AsyncSession):
await process_callback_pay_heleket(callback_query, state, session, method_name="crypto")
@router.callback_query(F.data == "pay_tribute")
async def handle_pay_tribute(callback_query: CallbackQuery, state: FSMContext, session: AsyncSession):
await process_callback_pay_tribute(callback_query, state, session)
+4
View File
@@ -11,6 +11,7 @@ from config import (
YOOKASSA_ENABLE,
YOOMONEY_ENABLE,
HELEKET_ENABLE,
TRIBUTE_ENABLE
)
from .cryprobot_pay import router as cryprobot_router
@@ -23,6 +24,7 @@ from .yookassa_pay import router as yookassa_router
from .yoomoney_pay import router as yoomoney_router
from .wata import router as wata_router
from .heleket import router as heleket_router
from .tribute_pay import router as tribute_router
router = Router(name="payments_main_router")
@@ -42,6 +44,8 @@ if KASSAI_ENABLE:
router.include_router(kassai_router)
if HELEKET_ENABLE:
router.include_router(heleket_router)
if TRIBUTE_ENABLE:
router.include_router(tribute_router)
router.include_router(wata_router)
router.include_router(gift_router)
+42 -23
View File
@@ -12,8 +12,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from datetime import datetime, timedelta
from sqlalchemy import select, and_
from pytz import timezone
from typing import Optional
from urllib.parse import urlencode, quote_plus
from config import (
ROBOKASSA_ENABLE,
ROBOKASSA_LOGIN,
@@ -31,6 +30,8 @@ from database import (
update_balance,
Payment
)
import json
from decimal import Decimal, ROUND_DOWN
from handlers.buttons import BACK, PAY_2
from handlers.payments.utils import send_payment_success_notification
from handlers.texts import DEFAULT_PAYMENT_MESSAGE, ENTER_SUM, PAYMENT_OPTIONS
@@ -59,7 +60,7 @@ if ROBOKASSA_ENABLE:
logger.info("Robokassa initialized with login: {}", ROBOKASSA_LOGIN)
def _build_receipt(amount: float, *, sno: Optional[str] = None) -> dict:
def _build_receipt(amount: float, *, sno: str = "usn_income") -> dict:
receipt = {
"items": [{
"name": "Пополнение баланса",
@@ -67,30 +68,48 @@ def _build_receipt(amount: float, *, sno: Optional[str] = None) -> dict:
"sum": float(amount),
"payment_method": "full_payment",
"payment_object": "payment",
"tax": "none",
}]
"tax": "none",
}],
"sno": sno,
}
if sno:
receipt["sno"] = sno
return receipt
def generate_payment_link(amount, inv_id, description, tg_id):
"""Генерация ссылки на оплату с номенклатурой (Receipt)."""
logger.debug(
f"Generating payment link for amount: {amount}, inv_id: {inv_id}, description: {description}"
)
receipt = _build_receipt(amount)
def _format_amount(amount: float | int) -> str:
s = str(Decimal(str(amount)).quantize(Decimal("0.01"), rounding=ROUND_DOWN))
if "." in s:
s = s.rstrip("0").rstrip(".")
return s
payment_link = robokassa._payment.link.generate_by_script(
out_sum=float(amount),
inv_id=inv_id,
description=f"Пополнение баланса (tg_id: {tg_id})",
id=str(tg_id),
receipt=receipt
)
logger.info(f"Generated payment link: {payment_link}")
return payment_link
def generate_payment_link(amount, inv_id, description, tg_id):
out_sum = _format_amount(amount)
receipt = _build_receipt(amount)
receipt_json = json.dumps(receipt, ensure_ascii=False, separators=(",", ":"))
receipt_enc1 = quote_plus(receipt_json, safe="")
shp = {"Shp_id": str(tg_id)}
base = f"{ROBOKASSA_LOGIN}:{out_sum}:{inv_id}:{receipt_enc1}:{ROBOKASSA_PASSWORD1}"
for k in sorted(shp.keys(), key=str.lower):
base += f":{k}={shp[k]}"
signature = hashlib.md5(base.encode("utf-8")).hexdigest().upper()
query = {
"MrchLogin": ROBOKASSA_LOGIN,
"OutSum": out_sum,
"InvId": inv_id,
"Description": description,
"Receipt": receipt_enc1,
"SignatureValue": signature,
**shp,
}
if ROBOKASSA_TEST_MODE:
query["IsTest"] = 1
return "https://auth.robokassa.ru/Merchant/Index.aspx?" + urlencode(query)
@router.callback_query(F.data == "pay_robokassa")
@@ -217,7 +236,7 @@ async def robokassa_webhook(request: web.Request):
amount = params.get("OutSum")
inv_id = params.get("InvId")
shp_id = params.get("shp_id")
shp_id = params.get("Shp_id") or params.get("shp_id") or params.get("id")
signature_value = params.get("SignatureValue")
logger.info(
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -92,4 +92,4 @@ def get_git_commit_number() -> str:
def get_version() -> str:
return f"dev-mod{get_git_commit_number()}"
return f"b110820{get_git_commit_number()}"