Tribute/ Robokassa
This commit is contained in:
@@ -96,6 +96,7 @@ WATA_SBP = "🏦 WATA: СБП"
|
||||
WATA_INT = "🌍 WATA: Международные карты"
|
||||
KASSAI_CARDS = "💳 KassaAI: Карты РФ"
|
||||
KASSAI_SBP = "🏦 KassaAI: СБП"
|
||||
TRIBUTE = "💳 Tribute"
|
||||
|
||||
# Кнопки Heleket
|
||||
HELEKET_CRYPTO = "₿ Heleket: Crypto"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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(
|
||||
|
||||
Binary file not shown.
+1
-1
@@ -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()}"
|
||||
|
||||
Reference in New Issue
Block a user