Какой аргумент нужно поставить первым? (aiosend + aiogram + crypto handler)
Делаю бота для покупки звезд через aiogram + aiosend. В handle_payment() принимаю 3 аргумента: invoice, state (FSM) и message. Жалуется, что пропускаю аргумент state. Ставлю такой порядок: state, invoice, message. Теперь жалуется, что пропускаю аргумент invoice. Ставлю порядок invoice, state, message - выскакивает первая ошибка.
В чем может быть проблема? Может ли быть это из-за того, что тип state - FSMContext?
Код:
import asyncio, os, requests, aiosend
from aiogram import (
Dispatcher,
Bot,
Router,
F
)
from aiogram.filters import CommandStart
from aiogram.fsm.state import (
StatesGroup,
State
)
from aiogram.types import (
Message,
InlineKeyboardButton,
InlineKeyboardMarkup, CallbackQuery
)
from dotenv import load_dotenv
from aiogram.fsm.context import FSMContext
from aiogram.utils.chat_action import ChatActionSender
from aiosend import CryptoPay
from aiosend.types import Invoice
load_dotenv()
TOKEN = os.getenv("TOKEN")
CRYPTO_TOKEN = os.getenv("CRYPTO_TOKEN")
CRYPTOTEST_TOKEN = os.getenv("CRYPTOTEST_TOKEN")
bot = Bot(TOKEN)
dp = Dispatcher()
cp = CryptoPay(CRYPTOTEST_TOKEN, network=aiosend.TESTNET)
"""For test network"""
#cp = CryptoPay(CRYPTO_TOKEN)
"""For main network"""
router = Router()
class Form(StatesGroup):
quantity = State()
username = State()
@router.message(CommandStart())
async def start(message: Message):
msg = """
Приветствуем вас в магазине ...!
На данный момент, у нас одни из самых низких цен на наши товары, так что мы с уверенностью
можем вам сказать, что вы остановились в правильном месте.
Пожалуйста, выберите категорию ?
"""
keyboard = [
[InlineKeyboardButton(text="Звёзды", callback_data="stars"),
InlineKeyboardButton(text="Premium", callback_data="premium")],
[InlineKeyboardButton(text="Поддержка", url="https://t.me/MYTELEGRAM")]
]
reply_markup = InlineKeyboardMarkup(inline_keyboard=keyboard)
await message.answer(msg, reply_markup=reply_markup)
@router.callback_query(F.data == "stars")
async def stars(message: CallbackQuery, state: FSMContext):
async with ChatActionSender.typing(bot=bot, chat_id=message.message.chat.id):
msg = """
*Введите количество звезд, которое хотите купить\.*
"""
await message.message.answer(msg, parse_mode="markdownv2")
await state.set_state(Form.quantity)
@router.message(F.text, Form.quantity)
async def recepient(message: Message, state: FSMContext):
await state.update_data(quantity=int(message.text))
async with ChatActionSender.typing(bot=bot, chat_id=message.chat.id):
msg = """
Теперь давайте определимся, *кому* вы хотите купить звезды\?
>Вы можете купить звезды как *себе*, так и своим *друзьям* или *близким\!*"""
reply_markup=InlineKeyboardMarkup(inline_keyboard=
[[InlineKeyboardButton(text="Себе", callback_data="buyMe"),
InlineKeyboardButton(text="Другу", callback_data="buyFriend")]]
)
await message.answer(msg, parse_mode="markdownv2", reply_markup=reply_markup)
@router.message(F.text, Form.username)
@router.callback_query(F.data == "buyMe")
async def pay(message: Message, state: FSMContext):
#req = requests.get("https://api.coinbase.com/v2/exchange-rates?currency=TON")
#data = req.json()
invoice: Invoice = await cp.create_invoice(5, "TRX")
reply_markup = InlineKeyboardMarkup(inline_keyboard=[[InlineKeyboardButton(text="Оплатить ✅", url=f"{invoice.bot_invoice_url}")]])
data = await state.get_data()
msg = f"""
*Новый заказ \#{invoice.invoice_id}*
? *Получатель\:* \@{message.message.chat.username if F.data == "buyMe" else data.get("username")}
? *Количество звёзд\:* {data.get("quantity")}
? *Сумма в ₽\:* {str(int(float(data["quantity"])) * 1.35).replace(".", "\.")}₽
Кнопка на оплату находится ниже ?
"""
await message.message.answer(msg, reply_markup=reply_markup, parse_mode="markdownv2")
invoice.poll(message=message)
await state.clear()
# todo: меню звезд
@router.callback_query(F.data == "buyFriend")
async def buyFriend(message: Message, state: FSMContext):
async with ChatActionSender.typing(bot=bot, chat_id=message.chat.id):
msg = """
*Пожалуйста, введите \@username аккаунта, которому будут отправлены звёзды\.*
> _Внимание\! Магазин не несёт ответственности за неправильно указанные данные\._
"""
await message.answer(msg, parse_mode="markdownv2")
await state.set_state(Form.username)
@router.message(F.text, Form.username)
async def starsF(message: Message, state: FSMContext):
await state.update_data(username=message.text)
async with ChatActionSender.typing(bot=bot, chat_id=message.chat.id):
msg = """
*Введите количество звезд, которое хотите купить\.*
"""
await message.message.answer(msg, parse_mode="markdownv2")
await state.set_state(Form.quantity)
@cp.invoice_polling()
async def handle_payment(state: FSMContext, invoice: Invoice, message: Message):
global status
if invoice.status == "paid":
status = "Успешно ✅"
elif invoice.status == "expired":
status = "Просрочено ⏰"
elif invoice.status == "active":
status = "Ждет оплаты ?"
data = await state.get_data()
msg = f"""
? *Оплата заказа \#{invoice.invoice_id}*
? *Получатель\:* \@{data.get("username")}
? *Количество звёзд\:* {data.get("quantity")}
? *Сумма в ₽\:* {str(int(float(data.get("quantity"))) * 1.35).replace(".", "\.")}₽
? *Сумма в криптовалюте\:* {invoice.amount} {invoice.asset}
? *Комиссия\:* {invoice.fee_amount} {invoice.fee_asset}
? *Итого\:* {invoice.amount - invoice.fee_amount} {invoice.asset}
? *Статус\:* {status}
Звезды в скором времени будут начислены!
"""
print(msg)
print(f"invoice #{invoice.invoice_id} has been paid")
await message.message.reply(msg, parse_mode="markdownv2")
await state.clear()
#todo: выдача звезд
async def main():
dp.include_router(router)
await bot.delete_webhook(True)
await asyncio.gather(
dp.start_polling(bot),
cp.start_polling()
)
if __name__ == '__main__':
asyncio.run(main())
Ответы (1 шт):
Автор решения: VoVcHiC
→ Ссылка
На связи автор aiosend.
Чтобы в handle_payment передался state, нужно передать его в метод poll следующим образом:
invoice.poll(message=message, state=state)
Порядок аргументов при этом - invoice, state, message.