Урок 4.3 — Изображения и QR для чеков
Научимся генерировать QR-коды и изображения чеков, получать ссылки для шеринга и интегрировать визуальное представление чеков в свои приложения.
Крипто-чеки — это не только цифровые активы, но и их визуальное представление. aiosend позволяет получить QR-код для любого чека, сгенерировать изображение-превью (с конвертацией в фиат) и создать ссылки для отправки в мессенджеры. В этом уроке мы разберём все способы визуализации чеков.
check.qr — QR-код чека
Свойство check.qr возвращает URL-ссылку на QR-код чека. Это синхронное свойство (не async), потому что оно просто формирует URL на основе bot_check_url. Никакого HTTP-запроса не происходит.
from aiosend import CryptoPay
cp = CryptoPay(token="YOUR_TOKEN")
# Создаём чек
check = await cp.create_check(amount=50, asset="USDT")
# Получаем QR-код (синхронно, не await!)
qr_url = check.qr
print(f"QR-код: {qr_url}")
# → https://qr.crypt.bot/?url=https://pay.crypt.bot/check/...
# Используем в HTML или Telegram
html = f'
'
# Отправляем в Telegram
# await bot.send_photo(chat_id, photo=qr_url)
🔍 Как формируется QR-URL?
Свойство check.qr использует метод network.get_qr(), который формирует URL вида: https://qr.crypt.bot/?url={bot_check_url}. Это официальный QR-генератор от Crypto Pay. Если тебе нужен кастомный QR-код (другого размера, цвета), ты можешь взять check.bot_check_url и передать его в любой сторонний генератор QR.
Свойство qr доступно у любого объекта Check — как только что созданного, так и полученного через get_check() или get_checks().
# Получаем существующий чек и его QR
check = await cp.get_check(check_id=42)
# QR-код для активного чека (можно активировать)
if check.status == "active":
print(f"QR для активации: {check.qr}")
# QR-код для уже активированного чека (просто информация)
if check.status == "activated":
print(f"QR (история): {check.qr}")
# Свойство работает для любого статуса
print(f"Ссылка на чек: {check.bot_check_url}")
print(f"QR URL: {check.qr}")
check.get_image() — изображение чека с конвертацией
Метод check.get_image(fiat) возвращает URL на изображение-превью чека. Изображение показывает сумму в криптовалюте и (опционально) эквивалент в фиатной валюте. Это идеально для встраивания в веб-страницы, Telegram-сообщения или email-рассылки.
async def get_image(self, fiat: str | None = None) -> str
# Параметры:
# fiat: str | None — фиатная валюта для отображения
# эквивалентной суммы (USD, EUR, RUB и т.д.)
# Если None — показывается только крипто-сумма.
#
# Возвращает: str — URL на сгенерированное изображение
from aiosend import CryptoPay
cp = CryptoPay(token="YOUR_TOKEN")
check = await cp.create_check(amount=100, asset="USDT")
# Без фиата — только крипто-сумма
image_url = await check.get_image()
print(f"Изображение: {image_url}")
# → https://imggen.send.tg/check/...?lang=en
# С фиатом — покажет эквивалент в USD
image_url_usd = await check.get_image(fiat="USD")
print(f"С USD: {image_url_usd}")
# С EUR
image_url_eur = await check.get_image(fiat="EUR")
print(f"С EUR: {image_url_eur}")
# С RUB
image_url_rub = await check.get_image(fiat="RUB")
print(f"С RUB: {image_url_rub}")
💡 Как работает генерация изображения?
Метод get_image() обращается к сервису imggen.send.tg, который генерирует PNG-изображение чека. Если указан параметр fiat, сервис конвертирует сумму по текущему курсу и показывает оба значения. Изображение кешируется — повторные запросы с теми же параметрами возвращают тот же URL.
Метод является асинхронным, потому что он делает HTTP-запрос к сервису генерации изображений. Результат — строка с URL.
from aiosend import CryptoPay
async def send_check_to_user(cp: CryptoPay, check_id: int, chat_id: int):
"""Отправляет изображение чека пользователю в Telegram."""
check = await cp.get_check(check_id=check_id)
# Получаем изображение с конвертацией в USD
image_url = await check.get_image(fiat="USD")
# Здесь используй Telegram Bot API для отправки
# await bot.send_photo(
# chat_id=chat_id,
# photo=image_url,
# caption=f"🎁 Чек на {check.amount} {check.asset}\n"
# f"Статус: {check.status}\n"
# f"Ссылка: {check.bot_check_url}",
# )
print(f"Изображение чека: {image_url}")
print(f"Ссылка для активации: {check.bot_check_url}")
print(f"QR: {check.qr}")
return image_url
bot_check_url — ссылка на чек в CryptoBot
Поле bot_check_url — это прямая ссылка на чек в @CryptoBot. По этой ссылке пользователь может активировать чек (получить средства). Ссылка имеет формат: https://pay.crypt.bot/check/UNIQUE_ID.
Эта ссылка используется в паре с QR-кодом и изображением. Ты можешь:
- Отправить её текстом в Telegram
- Закодировать в QR-код (через
check.qr) - Встроить в HTML-страницу как ссылку
- Использовать в кнопках Telegram-бота
from aiosend import CryptoPay
cp = CryptoPay(token="YOUR_TOKEN")
check = await cp.create_check(amount=25, asset="USDT")
# Прямая ссылка для активации
url = check.bot_check_url
print(f"Отправьте пользователю: {url}")
# Ссылка в HTML
html_link = f'Активировать чек на {check.amount} {check.asset}'
# Ссылка в Telegram-разметке
tg_link = f'[{check.amount} {check.asset}]({url})'
# Кнопка в Telegram-боте (aiogram)
# from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
# keyboard = InlineKeyboardMarkup(inline_keyboard=[
# [InlineKeyboardButton(text=f"🎁 Получить {check.amount} {check.asset}", url=url)]
# ])
Методы Network: get_check_image() и get_qr()
Класс Network (доступный через cp.session.network) предоставляет низкоуровневые методы для генерации изображений и QR-кодов. Метод check.get_image() внутри вызывает network.get_check_image(), а check.qr — network.get_qr().
Network.get_check_image()
- Принимает
check_idиfiat - Возвращает URL изображения
- Асинхронный метод
Network.get_qr()
- Принимает
link(URL) - Возвращает URL QR-кода
- Синхронный метод
from aiosend import CryptoPay
cp = CryptoPay(token="YOUR_TOKEN")
network = cp.session.network
# Используем network.get_qr() для произвольной ссылки
check = await cp.get_check(check_id=42)
qr_url = network.get_qr(check.bot_check_url)
print(f"QR: {qr_url}")
# Это эквивалентно check.qr:
print(f"check.qr: {check.qr}") # то же самое
# Используем network.get_check_image() напрямую
image_url = await network.get_check_image(
check_id=check.check_id,
fiat="USD",
)
print(f"Изображение: {image_url}")
# Эквивалентно check.get_image(fiat="USD"):
print(f"check.get_image: {await check.get_image(fiat='USD')}")
💡 Когда использовать Network напрямую?
Используй Network.get_qr(), когда тебе нужно получить QR-код для произвольной ссылки, а не только для чека. Например, для инвойсов (invoice.bot_invoice_url). Метод Network.get_check_image() полезен, когда у тебя нет объекта Check, а есть только check_id.
from aiosend import CryptoPay
cp = CryptoPay(token="YOUR_TOKEN")
invoice = await cp.create_invoice(amount=10, asset="USDT")
# QR для инвойса — используем Network.get_qr()
qr_url = cp.session.network.get_qr(invoice.bot_invoice_url)
# QR для чека — используем check.qr
check = await cp.create_check(amount=10, asset="USDT")
qr_url_check = check.qr # то же самое: network.get_qr(check.bot_check_url)
print(f"QR инвойса: {qr_url}")
print(f"QR чека: {qr_url_check}")
Генерация URL для шеринга чека
Комбинируя bot_check_url, QR-код и изображение, ты можешь создать полноценный блок для отправки чека пользователю. Вот несколько сценариев шеринга:
from aiosend import CryptoPay
class CheckShareKit:
"""Генерирует все URL для шеринга чека."""
def __init__(self, cp: CryptoPay):
self.cp = cp
self.network = cp.session.network
async def generate(self, check_id: int, fiat: str = "USD") -> dict:
"""Генерирует все URL для чека."""
check = await self.cp.get_check(check_id=check_id)
return {
"check_id": check.check_id,
"amount": check.amount,
"asset": check.asset,
"status": check.status,
"bot_url": check.bot_check_url,
"qr_url": check.qr,
"image_url": await check.get_image(fiat=fiat),
"image_no_fiat": await check.get_image(),
"share_text": (
f"🎁 Я дарю тебе {check.amount} {check.asset}!\n"
f"Активируй чек: {check.bot_check_url}"
),
}
async def share_to_telegram(self, check_id: int, chat_id: int):
"""Отправляет чек в Telegram (пример)."""
kit = await self.generate(check_id)
# Отправляем изображение с подписью
# await bot.send_photo(
# chat_id=chat_id,
# photo=kit["image_url"],
# caption=kit["share_text"],
# )
# Или отправляем как кнопку
# from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
# keyboard = InlineKeyboardMarkup(inline_keyboard=[
# [InlineKeyboardButton(
# text=f"🎁 Получить {kit['amount']} {kit['asset']}",
# url=kit["bot_url"],
# )]
# ])
# await bot.send_message(
# chat_id=chat_id,
# text=f"Вам подарок! 🎉",
# reply_markup=keyboard,
# )
print(f"Шеринг готов:")
print(f" Ссылка: {kit['bot_url']}")
print(f" QR: {kit['qr_url']}")
print(f" Изображение: {kit['image_url']}")
async def main():
cp = CryptoPay(token="YOUR_TOKEN")
kit = CheckShareKit(cp)
# Проверяем — генерируем URL для чека #42
urls = await kit.generate(check_id=42, fiat="USD")
print(f"Ссылка для активации: {urls['bot_url']}")
print(f"QR: {urls['qr_url']}")
print(f"Изображение: {urls['image_url']}")
# Отправляем пользователю
# await kit.share_to_telegram(check_id=42, chat_id=123456789)
if __name__ == "__main__":
import asyncio
asyncio.run(main())
🔍 Структура URL изображения
URL изображения формируется сервисом imggen.send.tg и выглядит так: https://imggen.send.tg/check/CHECK_ID?lang=en&fiat=USD. Параметр fiat опционален. Если его нет — на изображении будет только крипто-сумма. Если есть — добавится эквивалент в фиате.
Пример: визуальный просмотрщик чеков
Давай напишем функцию, которая выводит все активные чеки в виде ссылок с изображениями и QR. Это может быть основа для панели управления или отчёта.
from aiosend import CryptoPay, CheckStatus
async def visualize_checks(cp: CryptoPay, fiat: str = "USD"):
"""Выводит все активные чеки с изображениями и QR."""
checks = await cp.get_checks(status=CheckStatus.ACTIVE)
if not checks:
print("Нет активных чеков.")
return
print(f"📋 Найдено активных чеков: {len(checks)}")
print()
for i, check in enumerate(checks, 1):
image_url = await check.get_image(fiat=fiat) if fiat else await check.get_image()
print(f"{'='*60}")
print(f" Чек #{i}")
print(f" ID: {check.check_id}")
print(f" Сумма: {check.amount} {check.asset}")
print(f" Статус: {check.status}")
print(f" Создан: {check.created_at}")
print(f" Ссылка: {check.bot_check_url}")
print(f" QR: {check.qr}")
print(f" Изображение: {image_url}")
if check.payload:
print(f" Payload: {check.payload}")
print()
# Выводим таблицу в HTML-формате
html_rows = []
for check in checks:
img = await check.get_image(fiat=fiat)
html_rows.append(f"""
{check.check_id}
{check.amount} {check.asset}
{check.status}


Активировать
""")
html = f"""
ID Сумма Статус QR Изображение Ссылка
{''.join(html_rows)}
"""
with open("checks_report.html", "w") as f:
f.write(html)
print("✅ HTML-отчёт сохранён: checks_report.html")
async def main():
cp = CryptoPay(token="YOUR_TOKEN")
await visualize_checks(cp, fiat="USD")
if __name__ == "__main__":
import asyncio
asyncio.run(main())
💡 Практическое применение
Эта функция генерирует HTML-отчёт со всеми активными чеками, где каждый чек показан с QR-кодом и изображением. Это может быть полезно для: бухгалтерского отчёта, панели администратора, рассылки пользователям или просто для визуального контроля.
Массовая генерация изображений и бот-check-url
Если тебе нужно сгенерировать изображения для всех чеков определённого типа — например, для рассылки или отчёта — используй комбинацию get_checks() и get_image().
from aiosend import CryptoPay, CheckStatus
async def batch_check_images(
cp: CryptoPay,
asset: str = "USDT",
fiat: str = "USD",
) -> list[dict]:
"""Генерирует изображения для всех чеков в указанном активе."""
checks = await cp.get_checks(asset=asset, status=CheckStatus.ACTIVE)
results = []
for check in checks:
image_url = await check.get_image(fiat=fiat)
results.append({
"check_id": check.check_id,
"amount": check.amount,
"asset": check.asset,
"bot_url": check.bot_check_url,
"qr_url": check.qr,
"image_url": image_url,
})
print(f"✅ Чек #{check.check_id}: {check.amount} {check.asset}")
print(f" Ссылка: {check.bot_check_url}")
print(f" Изображение: {image_url}")
print()
return results
async def main():
cp = CryptoPay(token="YOUR_TOKEN")
images = await batch_check_images(cp, asset="USDT", fiat="USD")
print(f"Сгенерировано изображений: {len(images)}")
if __name__ == "__main__":
import asyncio
asyncio.run(main())
Граничные случаи и ограничения
Неверный фиат в get_image()
Если передать неподдерживаемую фиатную валюту в check.get_image(fiat), сервис imggen.send.tg может вернуть ошибку или изображение без конвертации. Используй только поддерживаемые фиаты: USD, EUR, RUB, BYN, UAH, GBP, CNY, KZT, UZS, GEL, TRY, AED.
QR-код для активированного чека
Свойство check.qr работает для любого чека — как активного, так и активированного. Однако QR-код активированного чека ведёт на страницу, где чек уже использован. Пользователь не сможет его активировать повторно. Учитывай это при отправке QR — убедись, что чек ещё активен.
Кеширование изображений
Сервис imggen.send.tg кеширует сгенерированные изображения. Если ты вызываешь get_image() с теми же параметрами повторно, URL может быть одинаковым. Это нормально — изображение обновится, если изменится курс валюты (для изображений с fiat).
Доступность сервиса imggen
Генерация изображений зависит от внешнего сервиса imggen.send.tg. Если сервис временно недоступен, get_image() может выбросить исключение или вернуть битый URL. Всегда обрабатывай эту ситуацию и имей запасной вариант — например, отправку простой текстовой ссылки вместо изображения.
Что важно запомнить
Практическое задание
Задание: Создай генератор визитки чека
Напиши функцию generate_check_card(), которая создаёт «визитку» чека — набор всех визуальных элементов для отправки пользователю. Функция должна:
- Принимать
check_idи опциональноfiat - Возвращать словарь с: bot_check_url, qr_url, image_url (с fiat), image_url (без fiat)
- Генерировать готовый текст для Telegram-сообщения со всеми ссылками
- Генерировать HTML-код для встраивания на веб-страницу
- Проверять статус чека: если активирован — добавлять предупреждение
- Обрабатывать возможные ошибки (чек не найден, сервис недоступен)
Подсказка:
import asyncio
from aiosend import CryptoPay
from aiosend.exceptions import APIError
async def generate_check_card(
cp: CryptoPay,
check_id: int,
fiat: str | None = "USD",
) -> dict | None:
try:
check = await cp.get_check(check_id=check_id)
card = {
"check_id": check.check_id,
"amount": check.amount,
"asset": check.asset,
"status": check.status,
"bot_check_url": check.bot_check_url,
"qr_url": check.qr,
"image_url_with_fiat": await check.get_image(fiat=fiat) if fiat else None,
"image_url_no_fiat": await check.get_image(),
"is_activated": check.status == "activated",
}
# Предупреждение для активированного чека
if card["is_activated"]:
card["warning"] = "⚠️ Этот чек уже активирован!"
else:
card["warning"] = None
# Telegram-сообщение
card["telegram_message"] = (
f"🎁 Крипто-чек!\n"
f"Сумма: {card['amount']} {card['asset']}\n"
f"Статус: {card['status']}\n"
f"Ссылка: {card['bot_check_url']}\n"
f"QR: {card['qr_url']}"
)
# HTML-код
card["html_code"] = (
f''
)
return card
except APIError as e:
print(f"Ошибка API: {e}")
except Exception as e:
print(f"Неизвестная ошибка: {e}")
return None
async def main():
cp = CryptoPay(token="YOUR_TOKEN")
card = await generate_check_card(cp, check_id=42, fiat="USD")
if card:
print(card["telegram_message"])
if __name__ == "__main__":
asyncio.run(main())
Интеграция в веб-приложения
Изображения и QR-коды чеков отлично интегрируются в веб-приложения. Вот несколько примеров использования в различных фреймворках.
FastAPI — эндпоинт для получения данных чека
from fastapi import FastAPI, HTTPException
from aiosend import CryptoPay
app = FastAPI()
cp = CryptoPay(token="YOUR_TOKEN")
@app.get("/api/check/{check_id}")
async def get_check_info(check_id: int, fiat: str = "USD"):
"""Возвращает JSON с данными чека и ссылками."""
try:
check = await cp.get_check(check_id=check_id)
image_url = await check.get_image(fiat=fiat)
return {
"check_id": check.check_id,
"amount": check.amount,
"asset": check.asset,
"status": check.status,
"bot_url": check.bot_check_url,
"qr_url": check.qr,
"image_url": image_url,
"created_at": check.created_at,
}
except Exception as e:
raise HTTPException(status_code=404, detail=str(e))
@app.get("/api/check/{check_id}/qr")
async def get_check_qr(check_id: int):
"""Перенаправляет на QR-код чека."""
check = await cp.get_check(check_id=check_id)
from fastapi.responses import RedirectResponse
return RedirectResponse(url=check.qr)
HTML-шаблон для отображения чека
{% if check %}
🎁 Крипто-чек
{{ check.amount }} {{ check.asset }}
Статус: {{ check.status }}
Получить {{ check.amount }} {{ check.asset }}
{% endif %}
Telegram Bot — отправка чека в сообщении
from aiogram import Bot, Dispatcher, types
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
from aiosend import CryptoPay
bot = Bot(token="TELEGRAM_BOT_TOKEN")
dp = Dispatcher()
cp = CryptoPay(token="CRYPTOPAY_TOKEN")
async def send_check(chat_id: int, check_id: int):
"""Отправляет чек пользователю в Telegram."""
check = await cp.get_check(check_id=check_id)
image_url = await check.get_image(fiat="USD")
keyboard = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(
text=f"🎁 Получить {check.amount} {check.asset}",
url=check.bot_check_url,
)],
])
await bot.send_photo(
chat_id=chat_id,
photo=image_url,
caption=(
f"🎉 Вам подарок!\n"
f"Сумма: {check.amount} {check.asset}\n"
f"[QR]({check.qr})"
),
parse_mode="Markdown",
reply_markup=keyboard,
)
# Пример хендлера:
# @dp.message(Command("bonus"))
# async def bonus_handler(message: types.Message):
# check = await cp.create_check(amount=10, asset="USDT")
# await send_check(message.chat.id, check.check_id)
💡 Все 3 способа визуализации
Для одного чека ты можешь использовать: 1) QR-код (check.qr) — быстрый доступ через камеру; 2) Изображение (check.get_image) — для встраивания в сообщения и web; 3) Текстовую ссылку (check.bot_check_url) — для отправки текстом. Комбинируй эти три способа для максимального удобства пользователей.
Полный lifecycle: от создания до активации
Давай посмотрим на полный цикл работы с чеком: создание, генерация визуальных элементов, отправка пользователю, проверка статуса и обработка активации.
import asyncio
from aiosend import CryptoPay, CheckStatus
async def check_lifecycle_demo(cp: CryptoPay):
"""Демонстрирует полный lifecycle чека с визуализацией."""
# Шаг 1: Создаём чек
print("Шаг 1: Создание чека")
check = await cp.create_check(amount=15, asset="USDT")
print(f" Чек #{check.check_id} создан")
# Шаг 2: Получаем визуальные элементы
print("\nШаг 2: Визуальные элементы")
print(f" bot_check_url: {check.bot_check_url}")
print(f" QR: {check.qr}")
image_usd = await check.get_image(fiat="USD")
print(f" Image (USD): {image_usd}")
image_raw = await check.get_image()
print(f" Image (raw): {image_raw}")
# Шаг 3: Отправляем пользователю (симуляция)
print("\nШаг 3: Отправка пользователю")
print(f" Отправляем изображение: {image_usd}")
print(f" И кнопку со ссылкой: {check.bot_check_url}")
# Шаг 4: Ожидаем активации (polling)
print("\nШаг 4: Ожидание активации...")
while True:
check = await cp.get_check(check_id=check.check_id)
if check.status == CheckStatus.ACTIVATED:
print(f" ✅ Чек активирован!")
print(f" Кем: user #{check.activated_by}")
print(f" Когда: {check.activated_at}")
break
await asyncio.sleep(2)
# Шаг 5: Пост-обработка
print("\nШаг 5: Пост-обработка")
print(f" Финальный статус: {check.status}")
print(f" Чек активирован, QR больше не актуален")
print(f" QR (история): {check.qr}")
return check
async def main():
cp = CryptoPay(token="YOUR_TOKEN")
await check_lifecycle_demo(cp)
if __name__ == "__main__":
asyncio.run(main())
💡 Важный нюанс: QR после активации
Помни, что QR-код (check.qr) остаётся доступным даже после активации чека. Но он ведёт на страницу, где чек уже использован. Если ты отправляешь QR пользователю — убедись, что чек ещё активен (check.status == "active"). Используй статус для проверки перед отправкой.
Урок 4.3: Изображения и QR для чеков
10 вопросов