refactor: remove Yoomoney payment integration

This commit is contained in:
2026-07-15 16:55:53 +05:00
parent 572dc8d1b4
commit b7cd21bfc3
14 changed files with 231 additions and 677 deletions
-1
View File
@@ -7,4 +7,3 @@ BOT_USER_CACHE_TTL=300
BOT_THROTTLE_RATE=0.5 BOT_THROTTLE_RATE=0.5
PATH_DATABASE=tgbot/data/database.db PATH_DATABASE=tgbot/data/database.db
PATH_LOGS=tgbot/data/logs.log PATH_LOGS=tgbot/data/logs.log
YOOMONEY_CLIENT_ID=
-1
View File
@@ -22,7 +22,6 @@ cp .env.example .env
```env ```env
BOT_TOKEN= BOT_TOKEN=
BOT_ADMIN_IDS= BOT_ADMIN_IDS=
YOOMONEY_CLIENT_ID=
``` ```
Конфигурация читается только из `.env` или переменных окружения. Конфигурация читается только из `.env` или переменных окружения.
-3
View File
@@ -42,7 +42,6 @@ class Settings(BaseSettings):
throttle_rate: float = Field( throttle_rate: float = Field(
default=0.5, ge=0, validation_alias="BOT_THROTTLE_RATE" default=0.5, ge=0, validation_alias="BOT_THROTTLE_RATE"
) )
yoomoney_client_id: str = Field(default="", validation_alias="YOOMONEY_CLIENT_ID")
# Очистка строковых значений из окружения # Очистка строковых значений из окружения
@field_validator( @field_validator(
@@ -50,7 +49,6 @@ class Settings(BaseSettings):
"timezone", "timezone",
"database_path", "database_path",
"logs_path", "logs_path",
"yoomoney_client_id",
mode="before", mode="before",
) )
@classmethod @classmethod
@@ -151,7 +149,6 @@ BOT_DATABASE_EXPORT = settings.database_export
BOT_TIMEZONE = settings.timezone BOT_TIMEZONE = settings.timezone
BOT_USER_CACHE_TTL = settings.user_cache_ttl BOT_USER_CACHE_TTL = settings.user_cache_ttl
BOT_THROTTLE_RATE = settings.throttle_rate BOT_THROTTLE_RATE = settings.throttle_rate
YOOMONEY_CLIENT_ID = settings.yoomoney_client_id
BOT_SCHEDULER = AsyncIOScheduler(timezone=BOT_TIMEZONE) BOT_SCHEDULER = AsyncIOScheduler(timezone=BOT_TIMEZONE)
BOT_VERSION = 4.2 BOT_VERSION = 4.2
+6 -4
View File
@@ -14,11 +14,13 @@ class PaymentsModel(Base):
id: Mapped[int] = mapped_column(Integer, primary_key=True, default=1) id: Mapped[int] = mapped_column(Integer, primary_key=True, default=1)
cryptobot_token: Mapped[str] = mapped_column(String, nullable=False, default="None") cryptobot_token: Mapped[str] = mapped_column(String, nullable=False, default="None")
yoomoney_token: Mapped[str] = mapped_column(String, nullable=False, default="None")
stars_course: Mapped[float] = mapped_column(Float, nullable=False, default=1.5) stars_course: Mapped[float] = mapped_column(Float, nullable=False, default=1.5)
status_cryptobot: Mapped[str] = mapped_column(String(16), nullable=False, default="False") status_cryptobot: Mapped[str] = mapped_column(
status_yoomoney: Mapped[str] = mapped_column(String(16), nullable=False, default="False") String(16), nullable=False, default="False"
status_stars: Mapped[str] = mapped_column(String(16), nullable=False, default="False") )
status_stars: Mapped[str] = mapped_column(
String(16), nullable=False, default="False"
)
ModelBase = Payments ModelBase = Payments
-2
View File
@@ -36,10 +36,8 @@ class Item:
class Payments: class Payments:
id: int id: int
cryptobot_token: str cryptobot_token: str
yoomoney_token: str
stars_course: float stars_course: float
status_cryptobot: str status_cryptobot: str
status_yoomoney: str
status_stars: str status_stars: str
-37
View File
@@ -98,43 +98,6 @@ async def payment_cryptobot_finl() -> InlineKeyboardMarkup:
return keyboard.as_markup() return keyboard.as_markup()
# Управление - ЮMoney
async def payment_yoomoney_finl() -> InlineKeyboardMarkup:
keyboard = InlineKeyboardBuilder()
get_payments = await Paymentsx().get()
if get_payments.yoomoney_token == "None":
assets_symbol = ""
else:
assets_symbol = ""
if get_payments.status_yoomoney == "True":
status_kb = ikb(
f"{assets_symbol} | Статус: Включено ✅",
data="payment_yoomoney_status:False",
)
else:
status_kb = ikb(
f"{assets_symbol} | Статус: Выключено ❌",
data="payment_yoomoney_status:True",
)
keyboard.row(
ikb("Информация ♻️", data="payment_yoomoney_check"),
).row(
ikb("Баланс 💰", data="payment_yoomoney_balance"),
).row(
ikb("Изменить 🖍", data="payment_yoomoney_edit"),
).row(
ikb("", data="..."),
).row(
status_kb,
)
return keyboard.as_markup()
# Управление - Звёзды # Управление - Звёзды
async def payment_stars_finl() -> InlineKeyboardMarkup: async def payment_stars_finl() -> InlineKeyboardMarkup:
keyboard = InlineKeyboardBuilder() keyboard = InlineKeyboardBuilder()
+3 -5
View File
@@ -43,8 +43,6 @@ async def refill_method_finl() -> InlineKeyboardMarkup:
if get_payments.status_cryptobot == "True": if get_payments.status_cryptobot == "True":
keyboard.row(ikb("🔷 CryptoBot", data="user_refill_method:Cryptobot")) keyboard.row(ikb("🔷 CryptoBot", data="user_refill_method:Cryptobot"))
if get_payments.status_yoomoney == "True":
keyboard.row(ikb("🔮 ЮMoney", data="user_refill_method:Yoomoney"))
if get_payments.status_stars == "True": if get_payments.status_stars == "True":
keyboard.row(ikb("⭐️ Звёзды", data="user_refill_method:Stars")) keyboard.row(ikb("⭐️ Звёзды", data="user_refill_method:Stars"))
@@ -54,7 +52,9 @@ async def refill_method_finl() -> InlineKeyboardMarkup:
# Проверка платежа # Проверка платежа
def refill_bill_finl(pay_link: str, pay_receipt: Union[str, int], pay_method: str) -> InlineKeyboardMarkup: def refill_bill_finl(
pay_link: str, pay_receipt: Union[str, int], pay_method: str
) -> InlineKeyboardMarkup:
keyboard = InlineKeyboardBuilder() keyboard = InlineKeyboardBuilder()
keyboard.row( keyboard.row(
@@ -74,8 +74,6 @@ async def refill_method_buy_finl() -> InlineKeyboardMarkup:
if get_payments.status_cryptobot == "True": if get_payments.status_cryptobot == "True":
keyboard.row(ikb("🔷 CryptoBot", data="user_refill_method:Cryptobot")) keyboard.row(ikb("🔷 CryptoBot", data="user_refill_method:Cryptobot"))
if get_payments.status_yoomoney == "True":
keyboard.row(ikb("🔮 ЮMoney", data="user_refill_method:Yoomoney"))
if get_payments.status_stars == "True": if get_payments.status_stars == "True":
keyboard.row(ikb("⭐️ Звёзды", data="user_refill_method:Stars")) keyboard.row(ikb("⭐️ Звёзды", data="user_refill_method:Stars"))
+23 -10
View File
@@ -11,16 +11,22 @@ def menu_frep(user_id: int) -> ReplyKeyboardMarkup:
keyboard = ReplyKeyboardBuilder() keyboard = ReplyKeyboardBuilder()
keyboard.row( keyboard.row(
rkb("🎁 Купить"), rkb("👤 Профиль"), rkb("🧮 Наличие товаров"), rkb("🎁 Купить"),
rkb("👤 Профиль"),
rkb("🧮 Наличие товаров"),
).row( ).row(
rkb("☎️ Поддержка"), rkb("❔ FAQ"), rkb("☎️ Поддержка"),
rkb("❔ FAQ"),
) )
if user_id in get_admins(): if user_id in get_admins():
keyboard.row( keyboard.row(
rkb("🎁 Управление товарами"), rkb("📊 Статистика"), rkb("🎁 Управление товарами"),
rkb("📊 Статистика"),
).row( ).row(
rkb("⚙️ Настройки"), rkb("🔆 Общие функции"), rkb("🔑 Платежные системы"), rkb("⚙️ Настройки"),
rkb("🔆 Общие функции"),
rkb("🔑 Платежные системы"),
) )
return keyboard.as_markup(resize_keyboard=True) return keyboard.as_markup(resize_keyboard=True)
@@ -31,7 +37,8 @@ def payments_frep() -> ReplyKeyboardMarkup:
keyboard = ReplyKeyboardBuilder() keyboard = ReplyKeyboardBuilder()
keyboard.row( keyboard.row(
rkb("🔷 CryptoBot"), rkb("🔮 ЮMoney"), rkb("⭐️ Звёзды"), rkb("🔷 CryptoBot"),
rkb("⭐️ Звёзды"),
).row( ).row(
rkb("🔙 Главное меню"), rkb("🔙 Главное меню"),
) )
@@ -44,7 +51,8 @@ def functions_frep() -> ReplyKeyboardMarkup:
keyboard = ReplyKeyboardBuilder() keyboard = ReplyKeyboardBuilder()
keyboard.row( keyboard.row(
rkb("🔍 Поиск"), rkb("📢 Рассылка"), rkb("🔍 Поиск"),
rkb("📢 Рассылка"),
).row( ).row(
rkb("🔙 Главное меню"), rkb("🔙 Главное меню"),
) )
@@ -57,7 +65,8 @@ def settings_frep() -> ReplyKeyboardMarkup:
keyboard = ReplyKeyboardBuilder() keyboard = ReplyKeyboardBuilder()
keyboard.row( keyboard.row(
rkb("🖍 Изменить данные"), rkb("🕹 Выключатели"), rkb("🖍 Изменить данные"),
rkb("🕹 Выключатели"),
).row( ).row(
rkb("🔙 Главное меню"), rkb("🔙 Главное меню"),
) )
@@ -70,11 +79,15 @@ def items_frep() -> ReplyKeyboardMarkup:
keyboard = ReplyKeyboardBuilder() keyboard = ReplyKeyboardBuilder()
keyboard.row( keyboard.row(
rkb("📁 Создать позицию "), rkb("🗃 Создать категорию ➕"), rkb("📁 Создать позицию "),
rkb("🗃 Создать категорию ➕"),
).row( ).row(
rkb("📁 Изменить позицию 🖍"), rkb("🗃 Изменить категорию 🖍"), rkb("📁 Изменить позицию 🖍"),
rkb("🗃 Изменить категорию 🖍"),
).row( ).row(
rkb("🔙 Главное меню"), rkb("🎁 Добавить товары "), rkb("❌ Удаление"), rkb("🔙 Главное меню"),
rkb("🎁 Добавить товары "),
rkb("❌ Удаление"),
) )
return keyboard.as_markup(resize_keyboard=True) return keyboard.as_markup(resize_keyboard=True)
+50 -139
View File
@@ -4,12 +4,14 @@ from aiogram.filters import StateFilter
from aiogram.types import CallbackQuery, Message from aiogram.types import CallbackQuery, Message
from tgbot.database import Paymentsx from tgbot.database import Paymentsx
from tgbot.keyboards.inline_admin import payment_yoomoney_finl, close_finl, payment_cryptobot_finl, payment_stars_finl from tgbot.keyboards.inline_admin import (
close_finl,
payment_cryptobot_finl,
payment_stars_finl,
)
from tgbot.services.api_cryptobot import CryptobotAPI from tgbot.services.api_cryptobot import CryptobotAPI
from tgbot.services.api_stars import StarsAPI from tgbot.services.api_stars import StarsAPI
from tgbot.services.api_yoomoney import YoomoneyAPI
from tgbot.utils.const_functions import ded, is_number, to_number from tgbot.utils.const_functions import ded, is_number, to_number
from tgbot.utils.misc.bot_logging import bot_logger
from tgbot.utils.misc.bot_models import FSM, ARS from tgbot.utils.misc.bot_models import FSM, ARS
router = Router(name=__name__) router = Router(name=__name__)
@@ -17,7 +19,9 @@ router = Router(name=__name__)
# Управление - CryptoBot # Управление - CryptoBot
@router.message(F.text == "🔷 CryptoBot") @router.message(F.text == "🔷 CryptoBot")
async def payments_cryptobot_open(message: Message, bot: Bot, state: FSM, arSession: ARS): async def payments_cryptobot_open(
message: Message, bot: Bot, state: FSM, arSession: ARS
):
await state.clear() await state.clear()
await message.answer( await message.answer(
@@ -26,17 +30,6 @@ async def payments_cryptobot_open(message: Message, bot: Bot, state: FSM, arSess
) )
# Управление - ЮMoney
@router.message(F.text == "🔮 ЮMoney")
async def payments_yoomoney_open(message: Message, bot: Bot, state: FSM, arSession: ARS):
await state.clear()
await message.answer(
"<b>🔮 Управление - ЮMoney</b>",
reply_markup=await payment_yoomoney_finl(),
)
# Управление - Звёзды # Управление - Звёзды
@router.message(F.text == "⭐️ Звёзды") @router.message(F.text == "⭐️ Звёзды")
async def payments_stars_open(message: Message, bot: Bot, state: FSM, arSession: ARS): async def payments_stars_open(message: Message, bot: Bot, state: FSM, arSession: ARS):
@@ -52,7 +45,9 @@ async def payments_stars_open(message: Message, bot: Bot, state: FSM, arSession:
################################### CRYPTOBOT ################################## ################################### CRYPTOBOT ##################################
# Баланс - CryptoBot # Баланс - CryptoBot
@router.callback_query(F.data == "payment_cryptobot_balance") @router.callback_query(F.data == "payment_cryptobot_balance")
async def payments_cryptobot_balance(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def payments_cryptobot_balance(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
response = await ( response = await (
await CryptobotAPI.connect( await CryptobotAPI.connect(
bot=bot, bot=bot,
@@ -70,7 +65,9 @@ async def payments_cryptobot_balance(call: CallbackQuery, bot: Bot, state: FSM,
# Информация - CryptoBot # Информация - CryptoBot
@router.callback_query(F.data == "payment_cryptobot_check") @router.callback_query(F.data == "payment_cryptobot_check")
async def payments_cryptobot_check(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def payments_cryptobot_check(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
status, response = await ( status, response = await (
await CryptobotAPI.connect( await CryptobotAPI.connect(
bot=bot, bot=bot,
@@ -88,7 +85,9 @@ async def payments_cryptobot_check(call: CallbackQuery, bot: Bot, state: FSM, ar
# Изменение - CryptoBot # Изменение - CryptoBot
@router.callback_query(F.data == "payment_cryptobot_edit") @router.callback_query(F.data == "payment_cryptobot_edit")
async def payments_cryptobot_edit(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def payments_cryptobot_edit(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
await state.set_state("here_cryptobot_token") await state.set_state("here_cryptobot_token")
await call.message.edit_text( await call.message.edit_text(
ded(f""" ded(f"""
@@ -102,13 +101,17 @@ async def payments_cryptobot_edit(call: CallbackQuery, bot: Bot, state: FSM, arS
# Выключатель - CryptoBot # Выключатель - CryptoBot
@router.callback_query(F.data.startswith("payment_cryptobot_status:")) @router.callback_query(F.data.startswith("payment_cryptobot_status:"))
async def payments_cryptobot_status(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def payments_cryptobot_status(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
get_status = call.data.split(":")[1] get_status = call.data.split(":")[1]
get_payments = await Paymentsx().get() get_payments = await Paymentsx().get()
if get_status == "True" and get_payments.cryptobot_token == "None": if get_status == "True" and get_payments.cryptobot_token == "None":
return await call.answer("❌ Токен данной платежной системы не был добавлен", True) return await call.answer(
"❌ Токен данной платежной системы не был добавлен", True
)
await Paymentsx().update(status_cryptobot=get_status) await Paymentsx().update(status_cryptobot=get_status)
@@ -121,12 +124,16 @@ async def payments_cryptobot_status(call: CallbackQuery, bot: Bot, state: FSM, a
############################## ПРИНЯТИЕ CRYPTOBOT ############################## ############################## ПРИНЯТИЕ CRYPTOBOT ##############################
# Принятие токена Cryptobot # Принятие токена Cryptobot
@router.message(StateFilter("here_cryptobot_token")) @router.message(StateFilter("here_cryptobot_token"))
async def payments_cryptobot_get(message: Message, bot: Bot, state: FSM, arSession: ARS): async def payments_cryptobot_get(
message: Message, bot: Bot, state: FSM, arSession: ARS
):
get_token = message.text get_token = message.text
await state.clear() await state.clear()
cache_message = await message.answer("<b>🔷 Проверка введённых CryptoBot данных... 🔄</b>") cache_message = await message.answer(
"<b>🔷 Проверка введённых CryptoBot данных... 🔄</b>"
)
status, response = await ( status, response = await (
await CryptobotAPI.connect( await CryptobotAPI.connect(
@@ -140,9 +147,13 @@ async def payments_cryptobot_get(message: Message, bot: Bot, state: FSM, arSessi
if status: if status:
await Paymentsx().update(cryptobot_token=get_token) await Paymentsx().update(cryptobot_token=get_token)
await cache_message.edit_text("<b>🔷 CryptoBot кошелёк был успешно изменён ✅</b>") await cache_message.edit_text(
"<b>🔷 CryptoBot кошелёк был успешно изменён ✅</b>"
)
else: else:
await cache_message.edit_text("<b>🔷 Не удалось изменить CryptoBot кошелёк ❌</b>") await cache_message.edit_text(
"<b>🔷 Не удалось изменить CryptoBot кошелёк ❌</b>"
)
await message.answer( await message.answer(
"<b>🔷 Управление - CryptoBot</b>", "<b>🔷 Управление - CryptoBot</b>",
@@ -150,121 +161,13 @@ async def payments_cryptobot_get(message: Message, bot: Bot, state: FSM, arSessi
) )
################################################################################
#################################### ЮMoney ####################################
# Баланс - ЮMoney
@router.callback_query(F.data == "payment_yoomoney_balance")
async def payments_yoomoney_balance(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS):
response = await (
await YoomoneyAPI.connect(
bot=bot,
arSession=arSession,
update=call,
skipping_error=True,
)
).balance()
await call.message.answer(
response,
reply_markup=close_finl(),
)
# Информация - ЮMoney
@router.callback_query(F.data == "payment_yoomoney_check")
async def payments_yoomoney_check(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS):
response = await (
await YoomoneyAPI.connect(
bot=bot,
arSession=arSession,
update=call,
skipping_error=True,
)
).check()
await call.message.answer(
response,
reply_markup=close_finl(),
)
# Изменение - ЮMoney
@router.callback_query(F.data == "payment_yoomoney_edit")
async def payments_yoomoney_edit(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS):
response = await (
await YoomoneyAPI.connect(
bot=bot,
arSession=arSession,
)
).authorization_get()
await state.set_state("here_yoomoney_token")
await call.message.edit_text(
ded(f"""
<b>🔮 Изменение ЮMoney кошелька - <a href='https://teletype.in/@djimbox/djimboshop-yoomoney'>Инструкция</a></b>
➖➖➖➖➖➖➖➖➖➖
▪️ Отправьте ссылку/код из адресной строки
▪️ {response}
"""),
disable_web_page_preview=True,
)
# Выключатель - ЮMoney
@router.callback_query(F.data.startswith("payment_yoomoney_status:"))
async def payments_yoomoney_status(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS):
get_status = call.data.split(":")[1]
get_payments = await Paymentsx().get()
if get_status == "True" and get_payments.yoomoney_token == "None":
return await call.answer("❌ Токен данной платежной системы не был добавлен", True)
await Paymentsx().update(status_yoomoney=get_status)
await call.message.edit_text(
"<b>🔮 Управление - ЮMoney</b>",
reply_markup=await payment_yoomoney_finl(),
)
################################ ПРИНЯТИЕ ЮMONEY ###############################
# Принятие токена ЮMoney
@router.message(StateFilter("here_yoomoney_token"))
async def payments_yoomoney_get(message: Message, bot: Bot, state: FSM, arSession: ARS):
get_code = message.text
try:
get_code = get_code[get_code.index("code=") + 5:].replace(" ", "")
except Exception:
bot_logger.debug("ЮMoney code= не найден в сообщении, пробую использовать текст как код", exc_info=True)
cache_message = await message.answer("<b>🔮 Проверка введённых ЮMoney данных... 🔄</b>")
status, token, response = await (
await YoomoneyAPI.connect(
bot=bot,
arSession=arSession,
)
).authorization_enter(str(get_code))
if status:
await Paymentsx().update(yoomoney_token=token)
await cache_message.edit_text(response)
await state.clear()
await message.answer(
"<b>🔮 Управление - ЮMoney</b>",
reply_markup=await payment_yoomoney_finl(),
)
################################################################################ ################################################################################
#################################### ЗВЁЗДЫ #################################### #################################### ЗВЁЗДЫ ####################################
# Баланс - Звёзды # Баланс - Звёзды
@router.callback_query(F.data == "payment_stars_balance") @router.callback_query(F.data == "payment_stars_balance")
async def payments_stars_balance(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def payments_stars_balance(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
response = await ( response = await (
await StarsAPI.connect( await StarsAPI.connect(
bot=bot, bot=bot,
@@ -282,7 +185,9 @@ async def payments_stars_balance(call: CallbackQuery, bot: Bot, state: FSM, arSe
# Информация - Звёзды # Информация - Звёзды
@router.callback_query(F.data == "payment_stars_check") @router.callback_query(F.data == "payment_stars_check")
async def payments_stars_check(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def payments_stars_check(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
status, response = await ( status, response = await (
await StarsAPI.connect( await StarsAPI.connect(
bot=bot, bot=bot,
@@ -300,7 +205,9 @@ async def payments_stars_check(call: CallbackQuery, bot: Bot, state: FSM, arSess
# Изменение - Звёзды # Изменение - Звёзды
@router.callback_query(F.data == "payment_stars_edit") @router.callback_query(F.data == "payment_stars_edit")
async def payments_stars_edit(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def payments_stars_edit(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
get_payments = await Paymentsx().get() get_payments = await Paymentsx().get()
await state.set_state("here_stars_course") await state.set_state("here_stars_course")
@@ -317,7 +224,9 @@ async def payments_stars_edit(call: CallbackQuery, bot: Bot, state: FSM, arSessi
# Выключатель - Звёзды # Выключатель - Звёзды
@router.callback_query(F.data.startswith("payment_stars_status:")) @router.callback_query(F.data.startswith("payment_stars_status:"))
async def payments_stars_status(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def payments_stars_status(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
get_status = call.data.split(":")[1] get_status = call.data.split(":")[1]
await Paymentsx().update(status_stars=get_status) await Paymentsx().update(status_stars=get_status)
@@ -331,7 +240,9 @@ async def payments_stars_status(call: CallbackQuery, bot: Bot, state: FSM, arSes
############################# ПРИНЯТИЕ КУРСА ЗВЁЗД ############################# ############################# ПРИНЯТИЕ КУРСА ЗВЁЗД #############################
# Принятие курса Telegram Stars # Принятие курса Telegram Stars
@router.message(StateFilter("here_stars_course")) @router.message(StateFilter("here_stars_course"))
async def payments_stars_course_get(message: Message, bot: Bot, state: FSM, arSession: ARS): async def payments_stars_course_get(
message: Message, bot: Bot, state: FSM, arSession: ARS
):
if not is_number(message.text): if not is_number(message.text):
return await message.answer( return await message.answer(
"<b>❌ Введите число. Например: <code>1.5</code></b>" "<b>❌ Введите число. Например: <code>1.5</code></b>"
+23 -18
View File
@@ -14,21 +14,20 @@ from tgbot.utils.text_functions import position_open_user
# Игнор-колбэки покупок # Игнор-колбэки покупок
prohibit_buy = ( prohibit_buy = (
'buy_category_swipe', "buy_category_swipe",
'buy_category_open', "buy_category_open",
'buy_position_swipe', "buy_position_swipe",
'buy_position_open', "buy_position_open",
'buy_item_open', "buy_item_open",
'buy_item_confirm', "buy_item_confirm",
) )
# Игнор-колбэки пополнений # Игнор-колбэки пополнений
prohibit_refill = ( prohibit_refill = (
'user_refill', "user_refill",
'user_refill_method', "user_refill_method",
'Pay:Cryptobot', "Pay:Cryptobot",
'Pay:Yoomoney', "Pay:",
'Pay:',
) )
router = Router(name=__name__) router = Router(name=__name__)
@@ -54,7 +53,9 @@ async def filter_work_message(message: Message, bot: Bot, state: FSM, arSession:
# Фильтр на технические работы - колбэк # Фильтр на технические работы - колбэк
@router.callback_query(IsWork()) @router.callback_query(IsWork())
async def filter_work_callback(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def filter_work_callback(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
await state.clear() await state.clear()
await call.answer("⛔ Бот находится на технических работах.", True) await call.answer("⛔ Бот находится на технических работах.", True)
@@ -64,7 +65,7 @@ async def filter_work_callback(call: CallbackQuery, bot: Bot, state: FSM, arSess
################################# СТАТУС ПОКУПОК ############################### ################################# СТАТУС ПОКУПОК ###############################
# Фильтр на доступность покупок - сообщение # Фильтр на доступность покупок - сообщение
@router.message(IsBuy(), F.text == "🎁 Купить") @router.message(IsBuy(), F.text == "🎁 Купить")
@router.message(IsBuy(), StateFilter('here_item_count')) @router.message(IsBuy(), StateFilter("here_item_count"))
async def filter_buy_message(message: Message, bot: Bot, state: FSM, arSession: ARS): async def filter_buy_message(message: Message, bot: Bot, state: FSM, arSession: ARS):
await state.clear() await state.clear()
@@ -73,7 +74,9 @@ async def filter_buy_message(message: Message, bot: Bot, state: FSM, arSession:
# Фильтр на доступность покупок - колбэк # Фильтр на доступность покупок - колбэк
@router.callback_query(IsBuy(), F.data.startswith(prohibit_buy)) @router.callback_query(IsBuy(), F.data.startswith(prohibit_buy))
async def filter_buy_callback(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def filter_buy_callback(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
await state.clear() await state.clear()
await call.answer("⛔ Покупки временно отключены.", True) await call.answer("⛔ Покупки временно отключены.", True)
@@ -82,7 +85,7 @@ async def filter_buy_callback(call: CallbackQuery, bot: Bot, state: FSM, arSessi
################################################################################ ################################################################################
############################### СТАТУС ПОПОЛНЕНИЙ ############################## ############################### СТАТУС ПОПОЛНЕНИЙ ##############################
# Фильтр на доступность пополнения - сообщение # Фильтр на доступность пополнения - сообщение
@router.message(IsRefill(), StateFilter('here_refill_amount')) @router.message(IsRefill(), StateFilter("here_refill_amount"))
async def filter_refill_message(message: Message, bot: Bot, state: FSM, arSession: ARS): async def filter_refill_message(message: Message, bot: Bot, state: FSM, arSession: ARS):
await state.clear() await state.clear()
@@ -91,7 +94,9 @@ async def filter_refill_message(message: Message, bot: Bot, state: FSM, arSessio
# Фильтр на доступность пополнения - колбэк # Фильтр на доступность пополнения - колбэк
@router.callback_query(IsRefill(), F.data.startswith(prohibit_refill)) @router.callback_query(IsRefill(), F.data.startswith(prohibit_refill))
async def filter_refill_callback(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def filter_refill_callback(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
await state.clear() await state.clear()
await call.answer("⛔ Пополнение временно отключено.", True) await call.answer("⛔ Пополнение временно отключено.", True)
@@ -100,7 +105,7 @@ async def filter_refill_callback(call: CallbackQuery, bot: Bot, state: FSM, arSe
################################################################################ ################################################################################
#################################### ПРОЧЕЕ #################################### #################################### ПРОЧЕЕ ####################################
# Открытие главного меню # Открытие главного меню
@router.message(F.text.in_(('🔙 Главное меню', '/start'))) @router.message(F.text.in_(("🔙 Главное меню", "/start")))
async def main_start(message: Message, bot: Bot, state: FSM, arSession: ARS): async def main_start(message: Message, bot: Bot, state: FSM, arSession: ARS):
await state.clear() await state.clear()
@@ -115,7 +120,7 @@ async def main_start(message: Message, bot: Bot, state: FSM, arSession: ARS):
# Открытие диплинков # Открытие диплинков
@router.message(F.text.startswith('/start ')) @router.message(F.text.startswith("/start "))
async def main_start_deeplink(message: Message, bot: Bot, state: FSM, arSession: ARS): async def main_start_deeplink(message: Message, bot: Bot, state: FSM, arSession: ARS):
deepling_args = message.text[7:] deepling_args = message.text[7:]
+46 -15
View File
@@ -5,10 +5,21 @@ from aiogram import Router, Bot, F
from aiogram.filters import StateFilter from aiogram.filters import StateFilter
from aiogram.types import CallbackQuery, Message from aiogram.types import CallbackQuery, Message
from tgbot.database import Positionx, Userx, Categoryx, Itemx, Paymentsx, Purchasesx, Settingsx from tgbot.database import (
Positionx,
Userx,
Categoryx,
Itemx,
Paymentsx,
Purchasesx,
Settingsx,
)
from tgbot.keyboards.inline_user import refill_method_buy_finl from tgbot.keyboards.inline_user import refill_method_buy_finl
from tgbot.keyboards.inline_user_page import * from tgbot.keyboards.inline_user_page import *
from tgbot.keyboards.inline_user_products import products_buy_confirm_finl, products_return_finl from tgbot.keyboards.inline_user_products import (
products_buy_confirm_finl,
products_return_finl,
)
from tgbot.keyboards.reply_main import menu_frep from tgbot.keyboards.reply_main import menu_frep
from tgbot.utils.const_functions import ded, del_message, convert_date, send_admins from tgbot.utils.const_functions import ded, del_message, convert_date, send_admins
from tgbot.utils.misc.bot_models import FSM, ARS from tgbot.utils.misc.bot_models import FSM, ARS
@@ -20,7 +31,9 @@ router = Router(name=__name__)
# Страницы выбора категории для покупки товара # Страницы выбора категории для покупки товара
@router.callback_query(F.data.startswith("buy_category_swipe:")) @router.callback_query(F.data.startswith("buy_category_swipe:"))
async def user_buy_category_swipe(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def user_buy_category_swipe(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
remover = int(call.data.split(":")[1]) remover = int(call.data.split(":")[1])
await call.message.edit_text( await call.message.edit_text(
@@ -31,7 +44,9 @@ async def user_buy_category_swipe(call: CallbackQuery, bot: Bot, state: FSM, arS
# Открытие категории с выбором позиции для покупки товара # Открытие категории с выбором позиции для покупки товара
@router.callback_query(F.data.startswith("buy_category_open:")) @router.callback_query(F.data.startswith("buy_category_open:"))
async def user_buy_category_open(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def user_buy_category_open(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
category_id = int(call.data.split(":")[1]) category_id = int(call.data.split(":")[1])
remover = int(call.data.split(":")[2]) remover = int(call.data.split(":")[2])
@@ -55,7 +70,9 @@ async def user_buy_category_open(call: CallbackQuery, bot: Bot, state: FSM, arSe
# Страницы выбора позиции для покупки товара # Страницы выбора позиции для покупки товара
@router.callback_query(F.data.startswith("buy_position_swipe:")) @router.callback_query(F.data.startswith("buy_position_swipe:"))
async def user_buy_position_swipe(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def user_buy_position_swipe(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
category_id = int(call.data.split(":")[1]) category_id = int(call.data.split(":")[1])
remover = int(call.data.split(":")[2]) remover = int(call.data.split(":")[2])
@@ -70,7 +87,9 @@ async def user_buy_position_swipe(call: CallbackQuery, bot: Bot, state: FSM, arS
# Открытие позиции для покупки товара # Открытие позиции для покупки товара
@router.callback_query(F.data.startswith("buy_position_open:")) @router.callback_query(F.data.startswith("buy_position_open:"))
async def user_buy_position_open(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def user_buy_position_open(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
position_id = int(call.data.split(":")[1]) position_id = int(call.data.split(":")[1])
remover = int(call.data.split(":")[2]) remover = int(call.data.split(":")[2])
@@ -94,7 +113,7 @@ async def user_buy_open(call: CallbackQuery, bot: Bot, state: FSM, arSession: AR
# Проверка, имеется ли на балансе пользователя достаточно средств # Проверка, имеется ли на балансе пользователя достаточно средств
if get_user.user_balance < get_position.position_price: if get_user.user_balance < get_position.position_price:
if get_payments.status_cryptobot == "True" or get_payments.status_yoomoney == "True": if get_payments.status_cryptobot == "True":
await call.message.answer( await call.message.answer(
"<b>❗ На вашем счёте недостаточно средств</b>\n" "<b>❗ На вашем счёте недостаточно средств</b>\n"
"💰 Выберите способ пополнения баланса", "💰 Выберите способ пополнения баланса",
@@ -103,7 +122,9 @@ async def user_buy_open(call: CallbackQuery, bot: Bot, state: FSM, arSession: AR
return await call.answer(cache_time=5) return await call.answer(cache_time=5)
else: else:
return await call.answer("❗ У вас недостаточно средств. Пополните баланс", True) return await call.answer(
"❗ У вас недостаточно средств. Пополните баланс", True
)
if len(get_items) < 1: if len(get_items) < 1:
return await call.answer("❗ Товаров нет в наличии", True) return await call.answer("❗ Товаров нет в наличии", True)
@@ -133,7 +154,9 @@ async def user_buy_open(call: CallbackQuery, bot: Bot, state: FSM, arSession: AR
▪️ Количество: <code>1шт</code> ▪️ Количество: <code>1шт</code>
▪️ Сумма к покупке: <code>{get_position.position_price}₽</code> ▪️ Сумма к покупке: <code>{get_position.position_price}₽</code>
"""), """),
reply_markup=products_buy_confirm_finl(position_id, get_position.category_id, 1), reply_markup=products_buy_confirm_finl(
position_id, get_position.category_id, 1
),
) )
else: else:
await state.update_data(here_buy_position_id=position_id) await state.update_data(here_buy_position_id=position_id)
@@ -155,7 +178,7 @@ async def user_buy_open(call: CallbackQuery, bot: Bot, state: FSM, arSession: AR
# Принятие количества товаров для покупки # Принятие количества товаров для покупки
@router.message(F.text, StateFilter("here_item_count")) @router.message(F.text, StateFilter("here_item_count"))
async def user_buy_count(message: Message, bot: Bot, state: FSM, arSession: ARS): async def user_buy_count(message: Message, bot: Bot, state: FSM, arSession: ARS):
position_id = (await state.get_data())['here_buy_position_id'] position_id = (await state.get_data())["here_buy_position_id"]
get_position = await Positionx().get_required(position_id=position_id) get_position = await Positionx().get_required(position_id=position_id)
get_user = await Userx().get_required(user_id=message.from_user.id) get_user = await Userx().get_required(user_id=message.from_user.id)
@@ -191,7 +214,9 @@ async def user_buy_count(message: Message, bot: Bot, state: FSM, arSession: ARS)
# Если товаров нет в наличии # Если товаров нет в наличии
if len(get_items) < 1: if len(get_items) < 1:
await state.clear() await state.clear()
return await message.answer("<b>🎁 Товар который вы хотели купить, закончился</b>") return await message.answer(
"<b>🎁 Товар который вы хотели купить, закончился</b>"
)
# Если введено кол-во товаров меньше 1 или меньше кол-ва имеющегося в наличии # Если введено кол-во товаров меньше 1 или меньше кол-ва имеющегося в наличии
if get_count < 1 or get_count > len(get_items): if get_count < 1 or get_count > len(get_items):
@@ -217,7 +242,9 @@ async def user_buy_count(message: Message, bot: Bot, state: FSM, arSession: ARS)
▪️ Количество: <code>{get_count}шт</code> ▪️ Количество: <code>{get_count}шт</code>
▪️ Сумма к покупке: <code>{amount_pay}₽</code> ▪️ Сумма к покупке: <code>{amount_pay}₽</code>
"""), """),
reply_markup=products_buy_confirm_finl(position_id, get_position.category_id, get_count), reply_markup=products_buy_confirm_finl(
position_id, get_position.category_id, get_count
),
) )
@@ -240,9 +267,13 @@ async def user_buy_confirm(call: CallbackQuery, bot: Bot, state: FSM, arSession:
elif purchase_result == "POSITION_NOT_FOUND": elif purchase_result == "POSITION_NOT_FOUND":
return await call.message.edit_text("<b>❌ Позиция не была найдена</b>") return await call.message.edit_text("<b>❌ Позиция не была найдена</b>")
elif purchase_result == "NOT_ENOUGH_ITEMS": elif purchase_result == "NOT_ENOUGH_ITEMS":
return await call.message.edit_text("<b>❌ В наличии недостаточно товаров. Попробуйте другое кол-во</b>") return await call.message.edit_text(
"<b>❌ В наличии недостаточно товаров. Попробуйте другое кол-во</b>"
)
elif purchase_result == "NOT_ENOUGH_BALANCE": elif purchase_result == "NOT_ENOUGH_BALANCE":
return await call.message.edit_text("<b>❌ На вашем балансе недостаточно средств</b>") return await call.message.edit_text(
"<b>❌ На вашем балансе недостаточно средств</b>"
)
get_user = await Userx().get_required(user_id=call.from_user.id) get_user = await Userx().get_required(user_id=call.from_user.id)
get_settings = await Settingsx().get() get_settings = await Settingsx().get()
@@ -272,5 +303,5 @@ async def user_buy_confirm(call: CallbackQuery, bot: Bot, state: FSM, arSession:
▪️ Пользователь: <b>@{get_user.user_login}</b> | <a href='tg://user?id={get_user.user_id}'>{get_user.user_name}</a> | <code>{get_user.user_id}</code> ▪️ Пользователь: <b>@{get_user.user_login}</b> | <a href='tg://user?id={get_user.user_id}'>{get_user.user_name}</a> | <code>{get_user.user_id}</code>
▪️ Товар: <code>{purchase_result.position_name} | {purchase_result.purchase_count}шт | {purchase_result.purchase_price}₽</code> ▪️ Товар: <code>{purchase_result.position_name} | {purchase_result.purchase_count}шт | {purchase_result.purchase_price}₽</code>
▪️ Чек: <code>#{purchase_result.receipt}</code> ▪️ Чек: <code>#{purchase_result.receipt}</code>
""") """),
) )
+79 -95
View File
@@ -9,7 +9,6 @@ from tgbot.database import Paymentsx, Refillx, Userx, Settingsx
from tgbot.keyboards.inline_user import refill_bill_finl, refill_method_finl from tgbot.keyboards.inline_user import refill_bill_finl, refill_method_finl
from tgbot.services.api_cryptobot import CryptobotAPI from tgbot.services.api_cryptobot import CryptobotAPI
from tgbot.services.api_stars import StarsAPI from tgbot.services.api_stars import StarsAPI
from tgbot.services.api_yoomoney import YoomoneyAPI
from tgbot.utils.const_functions import is_number, to_number, gen_id, ded from tgbot.utils.const_functions import is_number, to_number, gen_id, ded
from tgbot.utils.misc.bot_logging import bot_logger from tgbot.utils.misc.bot_logging import bot_logger
from tgbot.utils.misc.bot_models import FSM, ARS from tgbot.utils.misc.bot_models import FSM, ARS
@@ -26,9 +25,8 @@ async def refill_method_list(call: CallbackQuery, bot: Bot, state: FSM, arSessio
get_payments = await Paymentsx().get() get_payments = await Paymentsx().get()
if ( if (
get_payments.status_cryptobot == "False" and get_payments.status_cryptobot == "False"
get_payments.status_yoomoney == "False" and and get_payments.status_stars == "False"
get_payments.status_stars == "False"
): ):
return await call.answer("❗️ Пополнения временно недоступны", True) return await call.answer("❗️ Пополнения временно недоступны", True)
@@ -40,17 +38,21 @@ async def refill_method_list(call: CallbackQuery, bot: Bot, state: FSM, arSessio
# Выбор способа пополнения # Выбор способа пополнения
@router.callback_query(F.data.startswith("user_refill_method:")) @router.callback_query(F.data.startswith("user_refill_method:"))
async def refill_method_select(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def refill_method_select(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
refill_method = call.data.split(":")[1] refill_method = call.data.split(":")[1]
get_payments = await Paymentsx().get() get_payments = await Paymentsx().get()
if refill_method == "Cryptobot" and get_payments.status_cryptobot == "False": if refill_method == "Cryptobot" and get_payments.status_cryptobot == "False":
return await call.answer("❌ Пополнение данным способом временно недоступно", True) return await call.answer(
elif refill_method == "Yoomoney" and get_payments.status_yoomoney == "False": "❌ Пополнение данным способом временно недоступно", True
return await call.answer("❌ Пополнение данным способом временно недоступно", True) )
elif refill_method == "Stars" and get_payments.status_stars == "False": elif refill_method == "Stars" and get_payments.status_stars == "False":
return await call.answer("❌ Пополнение данным способом временно недоступно", True) return await call.answer(
"❌ Пополнение данным способом временно недоступно", True
)
await state.update_data(here_refill_method=refill_method) await state.update_data(here_refill_method=refill_method)
@@ -83,7 +85,7 @@ async def refill_amount_get(message: Message, bot: Bot, state: FSM, arSession: A
cache_message = await message.answer("<b>♻️ Подождите, платёж генерируется..</b>") cache_message = await message.answer("<b>♻️ Подождите, платёж генерируется..</b>")
refill_amount = to_number(message.text) refill_amount = to_number(message.text)
refill_method = (await state.get_data())['here_refill_method'] refill_method = (await state.get_data())["here_refill_method"]
await state.clear() await state.clear()
# Генерация платежа # Генерация платежа
@@ -95,14 +97,7 @@ async def refill_amount_get(message: Message, bot: Bot, state: FSM, arSession: A
update=cache_message, update=cache_message,
) )
).bill(refill_amount) ).bill(refill_amount)
elif refill_method == "Yoomoney":
bill_message, bill_link, bill_receipt = await (
await YoomoneyAPI.connect(
bot=bot,
arSession=arSession,
update=cache_message,
)
).bill(refill_amount)
elif refill_method == "Stars": elif refill_method == "Stars":
bill_message, bill_link, bill_receipt = await ( bill_message, bill_link, bill_receipt = await (
await StarsAPI.connect( await StarsAPI.connect(
@@ -130,48 +125,13 @@ async def refill_amount_get(message: Message, bot: Bot, state: FSM, arSession: A
################################################################################ ################################################################################
############################### ПРОВЕРКА ПЛАТЕЖЕЙ ############################## ############################### ПРОВЕРКА ПЛАТЕЖЕЙ ##############################
# Проверка оплаты - ЮMoney
@router.callback_query(F.data.startswith('Pay:Yoomoney'))
async def refill_check_yoomoney(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS):
pay_method = call.data.split(":")[1]
pay_receipt = call.data.split(":")[2]
pay_status, pay_amount = await (
await YoomoneyAPI.connect(
bot=bot,
arSession=arSession,
update=call,
)
).bill_check(pay_receipt)
if pay_status == 0:
refill_status = await refill_success(
bot=bot,
call=call,
pay_method=pay_method,
pay_amount=pay_amount,
pay_receipt=int(pay_receipt),
pay_comment=pay_receipt,
)
if refill_status == "ALREADY":
await call.answer("❗ Ваше пополнение уже зачислено.", True, cache_time=60)
await delete_refill_message(bot, call.message.chat.id, call.message.message_id)
elif refill_status == "USER_NOT_FOUND":
await call.answer("❗ Пользователь не найден. Напишите в поддержку.", True, cache_time=30)
elif pay_status == 1:
await call.answer("❗️ Не удалось проверить платёж. Попробуйте позже", True, cache_time=30)
elif pay_status == 2:
await call.answer("❗️ Оплата не была найдена. Попробуйте позже", True, cache_time=5)
elif pay_status == 3:
await call.answer("❗️ Оплата была произведена не в рублях", True, cache_time=5)
else:
await call.answer(f"❗ Неизвестная ошибка {pay_status}. Обратитесь в поддержку.", True, cache_time=5)
# Проверка оплаты - Cryptobot # Проверка оплаты - Cryptobot
@router.callback_query(F.data.startswith('Pay:Cryptobot')) @router.callback_query(F.data.startswith("Pay:Cryptobot"))
async def refill_check_cryptobot(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def refill_check_cryptobot(
call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS
):
pay_method = call.data.split(":")[1] pay_method = call.data.split(":")[1]
pay_comment = call.data.split(":")[2] pay_comment = call.data.split(":")[2]
@@ -194,22 +154,34 @@ async def refill_check_cryptobot(call: CallbackQuery, bot: Bot, state: FSM, arSe
if refill_status == "ALREADY": if refill_status == "ALREADY":
await call.answer("❗ Ваше пополнение уже зачислено.", True, cache_time=60) await call.answer("❗ Ваше пополнение уже зачислено.", True, cache_time=60)
await delete_refill_message(bot, call.message.chat.id, call.message.message_id) await delete_refill_message(
bot, call.message.chat.id, call.message.message_id
)
elif refill_status == "USER_NOT_FOUND": elif refill_status == "USER_NOT_FOUND":
await call.answer("❗ Пользователь не найден. Напишите в поддержку.", True, cache_time=30) await call.answer(
"❗ Пользователь не найден. Напишите в поддержку.", True, cache_time=30
)
elif pay_status == 1: elif pay_status == 1:
await call.answer("❗️ Не удалось проверить платёж. Попробуйте позже", True, cache_time=30) await call.answer(
"❗️ Не удалось проверить платёж. Попробуйте позже", True, cache_time=30
)
elif pay_status == 2: elif pay_status == 2:
await call.answer("❗️ Оплата не была найдена. Попробуйте позже", True, cache_time=5) await call.answer(
"❗️ Оплата не была найдена. Попробуйте позже", True, cache_time=5
)
elif pay_status == 3: elif pay_status == 3:
await call.answer("❗️ Вы не успели оплатить счёт", True, cache_time=5) await call.answer("❗️ Вы не успели оплатить счёт", True, cache_time=5)
await call.message.edit_reply_markup() await call.message.edit_reply_markup()
else: else:
await call.answer(f"❗ Неизвестная ошибка {pay_status}. Обратитесь в поддержку.", True, cache_time=5) await call.answer(
f"❗ Неизвестная ошибка {pay_status}. Обратитесь в поддержку.",
True,
cache_time=5,
)
# Проверка оплаты - Звёзды # Проверка оплаты - Звёзды
@router.callback_query(F.data.startswith('Pay:Stars')) @router.callback_query(F.data.startswith("Pay:Stars"))
async def refill_check_stars(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): async def refill_check_stars(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS):
pay_method = call.data.split(":")[1] pay_method = call.data.split(":")[1]
pay_receipt = int(call.data.split(":")[2]) pay_receipt = int(call.data.split(":")[2])
@@ -233,22 +205,36 @@ async def refill_check_stars(call: CallbackQuery, bot: Bot, state: FSM, arSessio
if refill_status == "ALREADY": if refill_status == "ALREADY":
await call.answer("❗ Ваше пополнение уже зачислено.", True, cache_time=60) await call.answer("❗ Ваше пополнение уже зачислено.", True, cache_time=60)
await delete_refill_message(bot, call.message.chat.id, call.message.message_id) await delete_refill_message(
bot, call.message.chat.id, call.message.message_id
)
elif refill_status == "USER_NOT_FOUND": elif refill_status == "USER_NOT_FOUND":
await call.answer("❗ Пользователь не найден. Напишите в поддержку.", True, cache_time=30) await call.answer(
"❗ Пользователь не найден. Напишите в поддержку.", True, cache_time=30
)
elif pay_status == 1: elif pay_status == 1:
await call.answer("❗️ Не удалось проверить платёж. Попробуйте позже", True, cache_time=30) await call.answer(
"❗️ Не удалось проверить платёж. Попробуйте позже", True, cache_time=30
)
elif pay_status == 2: elif pay_status == 2:
await call.answer("❗️ Оплата не была найдена. Попробуйте позже", True, cache_time=5) await call.answer(
"❗️ Оплата не была найдена. Попробуйте позже", True, cache_time=5
)
else: else:
await call.answer(f"❗ Неизвестная ошибка {pay_status}. Обратитесь в поддержку.", True, cache_time=5) await call.answer(
f"❗ Неизвестная ошибка {pay_status}. Обратитесь в поддержку.",
True,
cache_time=5,
)
################################################################################ ################################################################################
#################################### ЗВЁЗДЫ #################################### #################################### ЗВЁЗДЫ ####################################
# Подтверждение платежа Telegram Stars # Подтверждение платежа Telegram Stars
@router.pre_checkout_query() @router.pre_checkout_query()
async def refill_stars_pre_checkout(query: PreCheckoutQuery, bot: Bot, state: FSM, arSession: ARS): async def refill_stars_pre_checkout(
query: PreCheckoutQuery, bot: Bot, state: FSM, arSession: ARS
):
await ( await (
await StarsAPI.connect( await StarsAPI.connect(
bot=bot, bot=bot,
@@ -277,7 +263,9 @@ async def refill_stars_success(message: Message, bot: Bot, state: FSM, arSession
stars_api.parse_successful_payment(payment) stars_api.parse_successful_payment(payment)
) )
except ValueError: except ValueError:
bot_logger.warning("Некорректная successful_payment для Telegram Stars", exc_info=True) bot_logger.warning(
"Некорректная successful_payment для Telegram Stars", exc_info=True
)
return return
refill_status, receipt = await save_refill_success( refill_status, receipt = await save_refill_success(
@@ -293,12 +281,10 @@ async def refill_stars_success(message: Message, bot: Bot, state: FSM, arSession
if bill_chat_id == message.chat.id: if bill_chat_id == message.chat.id:
await delete_refill_message(bot, bill_chat_id, bill_message_id) await delete_refill_message(bot, bill_chat_id, bill_message_id)
await message.answer( await message.answer(ded(f"""
ded(f"""
<b>💰 Вы пополнили баланс на сумму <code>{pay_amount}₽</code>. Удачи ❤️ <b>💰 Вы пополнили баланс на сумму <code>{pay_amount}₽</code>. Удачи ❤️
🧾 Чек: <code>#{receipt}</code></b> 🧾 Чек: <code>#{receipt}</code></b>
""") """))
)
elif refill_status == "ALREADY": elif refill_status == "ALREADY":
if bill_chat_id == message.chat.id: if bill_chat_id == message.chat.id:
await delete_refill_message(bot, bill_chat_id, bill_message_id) await delete_refill_message(bot, bill_chat_id, bill_message_id)
@@ -312,12 +298,12 @@ async def refill_stars_success(message: Message, bot: Bot, state: FSM, arSession
#################################### ПРОЧЕЕ #################################### #################################### ПРОЧЕЕ ####################################
# Зачисление средств # Зачисление средств
async def refill_success( async def refill_success(
bot: Bot, bot: Bot,
call: CallbackQuery, call: CallbackQuery,
pay_method: str, pay_method: str,
pay_amount: float, pay_amount: float,
pay_receipt: Optional[int] = None, pay_receipt: Optional[int] = None,
pay_comment: Optional[str] = None, pay_comment: Optional[str] = None,
): ):
user_id = call.from_user.id user_id = call.from_user.id
@@ -338,19 +324,19 @@ async def refill_success(
if response_success != "ok": if response_success != "ok":
return response_success return response_success
await call.message.answer( await call.message.answer(ded(f"""
ded(f"""
<b>💰 Вы пополнили баланс на сумму <code>{pay_amount}₽</code>. Удачи ❤️ <b>💰 Вы пополнили баланс на сумму <code>{pay_amount}₽</code>. Удачи ❤️
🧾 Чек: <code>#{receipt}</code></b> 🧾 Чек: <code>#{receipt}</code></b>
""") """))
)
await delete_refill_message(bot, call.message.chat.id, call.message.message_id) await delete_refill_message(bot, call.message.chat.id, call.message.message_id)
return response_success return response_success
# Удаление сообщения со счётом # Удаление сообщения со счётом
async def delete_refill_message(bot: Bot, chat_id: Optional[int], message_id: Optional[int]) -> None: async def delete_refill_message(
bot: Bot, chat_id: Optional[int], message_id: Optional[int]
) -> None:
if chat_id is None or message_id is None: if chat_id is None or message_id is None:
return return
@@ -362,16 +348,14 @@ async def delete_refill_message(bot: Bot, chat_id: Optional[int], message_id: Op
# Сохранение пополнения и уведомление админов # Сохранение пополнения и уведомление админов
async def save_refill_success( async def save_refill_success(
bot: Bot, bot: Bot,
user_id: int, user_id: int,
pay_method: str, pay_method: str,
pay_amount: float, pay_amount: float,
pay_receipt: int, pay_receipt: int,
pay_comment: str, pay_comment: str,
) -> Tuple[str, int]: ) -> Tuple[str, int]:
if pay_method == "Yoomoney": if pay_method == "Cryptobot":
text_method = "ЮMoney"
elif pay_method == "Cryptobot":
text_method = "CryptoBot" text_method = "CryptoBot"
elif pay_method == "Stars": elif pay_method == "Stars":
text_method = "Telegram Stars" text_method = "Telegram Stars"
@@ -401,7 +385,7 @@ async def save_refill_success(
▪️ Пользователь: <b>@{get_user.user_login}</b> | <a href='tg://user?id={user_id}'>{get_user.user_name}</a> | <code>{user_id}</code> ▪️ Пользователь: <b>@{get_user.user_login}</b> | <a href='tg://user?id={user_id}'>{get_user.user_name}</a> | <code>{user_id}</code>
▪️ Сумма пополнения: <code>{pay_amount}₽</code> <code>({text_method})</code> ▪️ Сумма пополнения: <code>{pay_amount}₽</code> <code>({text_method})</code>
▪️ Чек: <code>#{pay_receipt}</code> ▪️ Чек: <code>#{pay_receipt}</code>
""") """),
) )
return response_success, pay_receipt return response_success, pay_receipt
-339
View File
@@ -1,339 +0,0 @@
# - *- coding: utf- 8 - *-
import json
from typing import Any, Dict, Optional, Tuple, Union
from urllib.parse import urlencode
from aiogram import Bot
from aiogram.types import CallbackQuery, Message
from aiohttp import ClientConnectorCertificateError
from tgbot.data.config import YOOMONEY_CLIENT_ID
from tgbot.database import Paymentsx
from tgbot.utils.const_functions import ded, gen_id
from tgbot.utils.misc.bot_logging import bot_logger
from tgbot.utils.misc.bot_models import ARS
from tgbot.utils.misc_functions import send_admins
# АПИ для работы с ЮMoney
class YoomoneyAPI:
# Настройка клиента ЮMoney
def __init__(
self,
bot: Bot,
arSession: ARS,
update: Optional[Union[Message, CallbackQuery]] = None,
token: str = "None",
adding: bool = False,
skipping_error: bool = False,
):
self.token = token
self.adding = adding
self.base_url = 'https://yoomoney.ru/api/'
self.headers = {
'Authorization': f'Bearer {self.token}',
'Content-Type': 'application/x-www-form-urlencoded',
}
self.bot = bot
self.arSession = arSession
self.update = update
self.skipping_error = skipping_error
# Инициализация данных
@classmethod
async def connect(
cls,
bot: Bot,
arSession: ARS,
update: Optional[Union[Message, CallbackQuery]] = None,
token: Optional[str] = None,
skipping_error: bool = False,
) -> "YoomoneyAPI":
adding = token is not None
if token is None:
payments = await Paymentsx().get()
token = payments.yoomoney_token
adding = False
return cls(
bot=bot,
arSession=arSession,
update=update,
token=token,
adding=adding,
skipping_error=skipping_error,
)
# Уведомления о неработоспособности кассы/кошелька
async def error_notification(self, error_code: str = "Unknown"):
bot_logger.warning("ЮMoney недоступен: %s", error_code)
if not self.skipping_error:
if self.adding and self.update is not None:
await self.update.edit_text(
f"<b>🔮 Не удалось добавить ЮMoney кассу ❌</b>\n"
f"❗️ Ошибка: <code>{error_code}</code>"
)
else:
await send_admins(
self.bot,
f"<b>🔮 ЮMoney недоступен. Как можно быстрее его замените</b>\n"
f"❗️ Ошибка: <code>{error_code}</code>"
)
# Проверка кассы/кошелька
async def check(self) -> str:
status, response = await self._request("account-info")
if status:
if len(response) >= 1:
if response['identified']:
text_identified = "Присутствует"
else:
text_identified = "Отсутствует"
if response['account_status'] == "identified":
text_status = "Идентифицированный счет"
elif response['account_status'] == "anonymous":
text_status = "Анонимный счет"
elif response['account_status'] == "named":
text_status = "Именной счет"
else:
text_status = response['account_status']
if response['account_type'] == "personal":
text_type = "Пользовательский счет"
elif response['account_type'] == "professional":
text_type = "Профессиональный счет"
else:
text_type = response['account_type']
return ded(f"""
<b>🔮 ЮMoney кошелёк полностью функционирует ✅</b>
➖➖➖➖➖➖➖➖➖➖
▪️ Кошелёк: <code>{response['account']}</code>
▪️ Идентификация: <code>{text_identified}</code>
▪️ Статус аккаунта: <code>{text_status}</code>
▪️ Тип счета: <code>{text_type}</code>
""")
return "<b>🔮 Не удалось проверить ЮMoney кошелёк ❌</b>"
# Получение баланса
async def balance(self) -> str:
status, response = await self._request("account-info")
if status:
wallet_balance = response['balance']
wallet_status, wallet_number = await self.account_info()
if wallet_status:
return ded(f"""
<b>🔮 Баланс ЮMoney кошелька составляет</b>
➖➖➖➖➖➖➖➖➖➖
▪️ Кошелёк: <code>{wallet_number}</code>
▪️ Баланс: <code>{wallet_balance}₽</code>
""")
return "<b>🔮 Не удалось получить баланс ЮMoney кошелька ❌</b>"
# Информация об аккаунте
async def account_info(self) -> Tuple[bool, str]:
status, response = await self._request("account-info")
try:
return True, response['account']
except Exception:
bot_logger.warning("Не удалось получить номер ЮMoney", exc_info=True)
return False, ""
# Получение ссылки на авторизацию
async def authorization_get(self) -> str:
if not YOOMONEY_CLIENT_ID:
return "В .env не заполнен YOOMONEY_CLIENT_ID"
session = await self.arSession.get_session()
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
url = "https://yoomoney.ru/oauth/authorize?" + urlencode({
"client_id": YOOMONEY_CLIENT_ID,
"response_type": "code",
"redirect_uri": "https://yoomoney.ru",
"scope": "account-info operation-history operation-details",
})
response = await session.post(
url=url,
headers=headers,
)
return str(response.url)
# Принятие кода авторизации и получение токена
async def authorization_enter(self, get_code: str) -> Tuple[bool, str, str]:
if not YOOMONEY_CLIENT_ID:
return False, "", "<b>❌ В .env не заполнен YOOMONEY_CLIENT_ID</b>"
session = await self.arSession.get_session()
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
url = "https://yoomoney.ru/oauth/token?" + urlencode({
"code": get_code,
"client_id": YOOMONEY_CLIENT_ID,
"grant_type": "authorization_code",
"redirect_uri": "https://yoomoney.ru",
})
response = await session.post(
url=url,
headers=headers,
)
response_data = json.loads((await response.read()).decode())
if "error" in response_data:
error = response_data['error']
if error == "invalid_request":
return_message = ded(f"""
<b>❌ Требуемые параметры запроса отсутствуют или имеют неправильные или недопустимые значения</b>
""")
elif error == "unauthorized_client":
return_message = ded(f"""
<b>❌ Недопустимое значение параметра 'client_id' или 'client_secret', или приложение
не имеет права запрашивать авторизацию (например, ЮMoney заблокировал его 'client_id')</b>
""")
elif error == "invalid_grant":
return_message = ded(f"""
<b>❌ В выпуске 'access_token' отказано. ЮMoney не выпускал временный токен,
срок действия токена истек или этот временный токен уже выдан
'access_token' (повторный запрос токена авторизации с тем же временным токеном)</b>
""")
else:
return_message = f"Unknown error: {error}"
return False, "", return_message
elif response_data['access_token'] == "":
return False, "", "<b>❌ Не удалось получить токен. Попробуйте всё снова</b>"
return True, response_data['access_token'], "<b>🔮 ЮMoney кошелёк был успешно изменён ✅</b>"
# Создание счета на оплату
async def bill(self, pay_amount: Union[float, int]) -> Tuple[Union[str, bool], str, str]:
session = await self.arSession.get_session()
bill_receipt = str(gen_id(12))
url = "https://yoomoney.ru/quickpay/confirm.xml?"
wallet_status, wallet_number = await self.account_info()
if wallet_status:
pay_amount_bill = pay_amount + (pay_amount * 0.031)
if float(pay_amount_bill) < 2:
pay_amount_bill = 2.04
payload = {
'receiver': wallet_number,
'quickpay_form': 'button',
'targets': 'Добровольное пожертвование',
'paymentType': 'SB',
'sum': pay_amount_bill,
'label': bill_receipt,
}
for value in payload:
url += str(value).replace("_", "-") + "=" + str(payload[value])
url += "&"
bill_link = str((await session.post(url[:-1].replace(" ", "%20"))).url)
bill_message = ded(f"""
<b>💰 Пополнение баланса</b>
➖➖➖➖➖➖➖➖➖➖
▪️ Для пополнения баланса, нажмите на кнопку ниже
<code>Перейти к оплате</code> и оплатите выставленный вам счёт
▪️ У вас имеется 60 минут на оплату счета
▪️ Сумма пополнения: <code>{pay_amount}₽</code>
➖➖➖➖➖➖➖➖➖➖
❗️ После оплаты, нажмите на <code>Проверить оплату</code>
""")
return bill_message, bill_link, bill_receipt
return False, "", ""
# Проверка счета на оплату
async def bill_check(self, bill_receipt: Optional[Union[str, int]] = None, records: int = 1) -> Tuple[int, float]:
data = {
'type': 'deposition',
'details': 'true',
}
if bill_receipt is not None:
data['label'] = bill_receipt
if records is not None:
data['records'] = str(records)
status, response = await self._request("operation-history", data)
pay_status, pay_amount, pay_currency = 1, 0, 0
if status:
pay_status = 2
if len(response['operations']) >= 1:
pay_currency = response['operations'][0]['amount_currency']
pay_amount = response['operations'][0]['amount']
pay_status = 3
if pay_currency == "RUB":
pay_status = 0
return pay_status, pay_amount
# Генерация запроса
async def _request(
self,
method: str,
data: Optional[Dict[str, Any]] = None,
) -> Tuple[bool, Any]:
session = await self.arSession.get_session()
url = self.base_url + method
try:
response = await session.post(
url=url,
headers=self.headers,
data=data,
)
response_data = json.loads((await response.read()).decode())
if response.status == 200:
return True, response_data
else:
await self.error_notification(f"{response.status} - {str(response_data)}")
return False, response_data
except ClientConnectorCertificateError:
bot_logger.warning("Ошибка SSL при запросе ЮMoney", exc_info=True)
await self.error_notification("CERTIFICATE_VERIFY_FAILED")
return False, "CERTIFICATE_VERIFY_FAILED"
except Exception as ex:
bot_logger.warning("Ошибка запроса ЮMoney", exc_info=True)
await self.error_notification(str(ex))
return False, str(ex)
+1 -8
View File
@@ -119,8 +119,6 @@ async def refill_open_admin(bot: Bot, user_id: int, get_refill: ModelRefill):
if get_refill.refill_method in ["Form", "Nickname", "Number", "QIWI"]: if get_refill.refill_method in ["Form", "Nickname", "Number", "QIWI"]:
pay_method = "QIWI 🥝" pay_method = "QIWI 🥝"
elif get_refill.refill_method == "Yoomoney":
pay_method = "ЮMoney 🔮"
elif get_refill.refill_method == "Cryptobot": elif get_refill.refill_method == "Cryptobot":
pay_method = "CryptoBot 🔷" pay_method = "CryptoBot 🔷"
else: else:
@@ -353,7 +351,6 @@ async def get_statistics() -> str:
users_money_give, users_money_give,
) = (0, 0, 0, 0, 0, 0) ) = (0, 0, 0, 0, 0, 0)
refill_cryptobot_count, refill_cryptobot_amount = 0, 0 refill_cryptobot_count, refill_cryptobot_amount = 0, 0
refill_yoomoney_count, refill_yoomoney_amount = 0, 0
refill_stars_count, refill_stars_amount = 0, 0 refill_stars_count, refill_stars_amount = 0, 0
get_categories = await Categoryx().get_all() get_categories = await Categoryx().get_all()
@@ -384,10 +381,7 @@ async def get_statistics() -> str:
refill_amount_all += refill.refill_amount refill_amount_all += refill.refill_amount
refill_count_all += 1 refill_count_all += 1
if refill.refill_method == "Yoomoney": if refill.refill_method == "Cryptobot":
refill_yoomoney_count += 1
refill_yoomoney_amount += refill.refill_amount
elif refill.refill_method == "Cryptobot":
refill_cryptobot_count += 1 refill_cryptobot_count += 1
refill_cryptobot_amount += refill.refill_amount refill_cryptobot_amount += refill.refill_amount
elif refill.refill_method == "Stars": elif refill.refill_method == "Stars":
@@ -490,7 +484,6 @@ async def get_statistics() -> str:
┣‒ Платежные системы (всего) ┣‒ Платежные системы (всего)
┣ CryptoBot: <code>{refill_cryptobot_count}шт</code> - <code>{round(refill_cryptobot_amount, 2)}₽</code> ┣ CryptoBot: <code>{refill_cryptobot_count}шт</code> - <code>{round(refill_cryptobot_amount, 2)}₽</code>
┣ TG Stars: <code>{refill_stars_count}шт</code> - <code>{round(refill_stars_amount, 2)}₽</code> ┣ TG Stars: <code>{refill_stars_count}шт</code> - <code>{round(refill_stars_amount, 2)}₽</code>
┣ ЮMoney: <code>{refill_yoomoney_count}шт</code> - <code>{round(refill_yoomoney_amount, 2)}₽</code>
┣‒ Остальные ┣‒ Остальные
┣ Средств выдано: <code>{round(users_money_give, 2)}₽</code> ┣ Средств выдано: <code>{round(users_money_give, 2)}₽</code>