# Обработчики платежей import logging from aiogram import Router from aiogram.types import Message, CallbackQuery, LabeledPrice, PreCheckoutQuery from aiogram.utils.keyboard import InlineKeyboardBuilder from database import DatabaseManager from config.settings import PRICES, BOT_TOKEN from utils.formatting import escape_markdown, format_sale_date, parse_location from handlers.vin_handlers import send_vehicle_photos router = Router() @router.callback_query(lambda c: c.data and c.data.startswith("pay_detailed_info:")) async def pay_detailed_info_callback(callback: CallbackQuery, db: DatabaseManager = None): """Оплата детальной информации через платёжную форму""" vin = callback.data.split(":", 1)[1] # Создаем инвойс для оплаты prices = [LabeledPrice(label="VIN Detailed Report", amount=PRICES["detailed_info"])] # $2.99 в копейках await callback.message.answer_invoice( title="VIN Detailed Report", description=f"Comprehensive salvage report for VIN: {vin}", payload=f"detailed_info:{vin}", provider_token="", # Для Telegram Stars не нужен currency="XTR", # Telegram Stars prices=prices, start_parameter="detailed_info" ) await callback.answer() @router.callback_query(lambda c: c.data and c.data.startswith("pay_check_detailed:")) async def pay_check_detailed_callback(callback: CallbackQuery, db: DatabaseManager = None): """Оплата детального отчета через платёжную форму""" vin = callback.data.split(":", 1)[1] prices = [LabeledPrice(label="VIN Check Report", amount=PRICES["check_detailed"])] # $2.99 await callback.message.answer_invoice( title="VIN Check - Detailed Report", description=f"Complete salvage and auction history for VIN: {vin}", payload=f"check_detailed:{vin}", provider_token="", currency="XTR", prices=prices, start_parameter="check_detailed" ) await callback.answer() @router.callback_query(lambda c: c.data and c.data.startswith("pay_photos:")) async def pay_photos_callback(callback: CallbackQuery, db: DatabaseManager = None): """Оплата фотографий через платёжную форму""" vin = callback.data.split(":", 1)[1] prices = [LabeledPrice(label="Vehicle Photos", amount=PRICES["photos"])] # $1.99 await callback.message.answer_invoice( title="Vehicle Photos", description=f"High-quality auction photos for VIN: {vin}", payload=f"photos:{vin}", provider_token="", currency="XTR", prices=prices, start_parameter="photos" ) await callback.answer() @router.pre_checkout_query() async def pre_checkout_handler(pre_checkout_query: PreCheckoutQuery, db: DatabaseManager = None): """Подтверждение предварительной проверки платежа""" await pre_checkout_query.answer(ok=True) @router.message(lambda message: message.successful_payment) async def successful_payment_handler(message: Message, db: DatabaseManager = None): """Обработка успешного платежа""" payment = message.successful_payment payload_parts = payment.invoice_payload.split(":", 1) if len(payload_parts) != 2: logging.error(f"Invalid payment payload: {payment.invoice_payload}") await message.answer("❌ **Payment Error**\n\nInvalid payment data. Please contact support.") return service_type, vin = payload_parts user_id = message.from_user.id amount = payment.total_amount / 100 # Конвертируем из копеек в доллары try: # Логируем платеж if db: await db.log_payment(user_id, vin, service_type, amount, payment.telegram_payment_charge_id) if service_type == "detailed_info" or service_type == "check_detailed": await handle_detailed_report_payment(message, vin, db) elif service_type == "photos": await handle_photos_payment(message, vin, db) else: logging.error(f"Unknown service type: {service_type}") await message.answer("❌ **Payment Error**\n\nUnknown service type. Please contact support.") except Exception as e: logging.error(f"Error in successful_payment_handler: {e}") await message.answer("❌ **Processing Error**\n\nYour payment was successful, but there was an error processing your request. Please contact support.") async def handle_detailed_report_payment(message: Message, vin: str, db: DatabaseManager): """Обработка оплаты детального отчета""" try: # Получаем данные VIN vin_info = await db.get_vin_info(vin) if not vin_info: await message.answer(f"❌ **Data Error**\n\nVIN `{escape_markdown(vin)}` not found in database.") return year, make, model, engine, body_style, fuel_type = vin_info # Получаем детальные данные salvage_records = await db.get_salvage_records(vin) nhtsa_data = await db.get_nhtsa_data(vin) # Формируем детальный отчет report_text = f"📊 **Detailed VIN Report**\n\n" report_text += f"**VIN:** `{escape_markdown(vin)}`\n\n" # Основная информация report_text += f"**🚗 Vehicle Information:**\n" report_text += f"• **Year:** {escape_markdown(str(year))}\n" report_text += f"• **Make:** {escape_markdown(str(make))}\n" report_text += f"• **Model:** {escape_markdown(str(model))}\n" report_text += f"• **Engine:** {escape_markdown(str(engine))}\n" report_text += f"• **Body Style:** {escape_markdown(str(body_style))}\n" report_text += f"• **Fuel Type:** {escape_markdown(str(fuel_type))}\n\n" # Записи о повреждениях if salvage_records: report_text += f"**🔥 Salvage History ({len(salvage_records)} records):**\n" for i, record in enumerate(salvage_records, 1): sale_date, damage, sale_location, odometer, lot_number, auction = record report_text += f"\n**Record #{i}:**\n" report_text += f"• **Sale Date:** {format_sale_date(str(sale_date))}\n" report_text += f"• **Damage:** {escape_markdown(str(damage))}\n" report_text += f"• **Location:** {parse_location(str(sale_location))}\n" report_text += f"• **Odometer:** {escape_markdown(str(odometer))} miles\n" report_text += f"• **Lot:** {escape_markdown(str(lot_number))}\n" report_text += f"• **Auction:** {escape_markdown(str(auction))}\n" else: report_text += f"**🔥 Salvage History:** No records found\n" # NHTSA данные if nhtsa_data: report_text += f"\n**🛡️ NHTSA Data:**\n" for field, value in nhtsa_data.items(): if value and str(value) != 'None': report_text += f"• **{field}:** {escape_markdown(str(value))}\n" # Создаем кнопки builder = InlineKeyboardBuilder() builder.button(text="📸 Get Photos ($1.99)", callback_data=f"pay_photos:{vin}") builder.button(text="🔍 Check Another VIN", callback_data="check_vin") builder.button(text="🏠 Main Menu", callback_data="main_menu") builder.adjust(1) # Отправляем отчет (может быть длинным, делим на части если нужно) if len(report_text) > 4000: # Разделяем на части parts = [report_text[i:i+4000] for i in range(0, len(report_text), 4000)] for i, part in enumerate(parts): if i == len(parts) - 1: # Последняя часть с кнопками await message.answer(part, reply_markup=builder.as_markup(), parse_mode="Markdown") else: await message.answer(part, parse_mode="Markdown") else: await message.answer(report_text, reply_markup=builder.as_markup(), parse_mode="Markdown") logging.info(f"Detailed report sent for VIN {vin} to user {message.from_user.id}") except Exception as e: logging.error(f"Error in handle_detailed_report_payment: {e}") await message.answer("❌ **Report Error**\n\nThere was an error generating your report. Please contact support.") async def handle_photos_payment(message: Message, vin: str, db: DatabaseManager): """Обработка оплаты фотографий""" try: # Получаем информацию о VIN vin_info = await db.get_vin_info(vin) if not vin_info: await message.answer(f"❌ **Data Error**\n\nVIN `{escape_markdown(vin)}` not found in database.") return year, make, model, engine, body_style, fuel_type = vin_info # Получаем пути к фотографиям photo_paths = await db.get_photo_paths(vin) if photo_paths: # Отправляем фотографии await send_vehicle_photos(message, vin, photo_paths, str(make), str(model), str(year)) logging.info(f"Photos sent for VIN {vin} to user {message.from_user.id}") else: builder = InlineKeyboardBuilder() builder.button(text="🚗 Get Detailed Report", callback_data=f"pay_check_detailed:{vin}") builder.button(text="📸 Search Another VIN", callback_data="search_car_photo") builder.button(text="🏠 Main Menu", callback_data="main_menu") builder.adjust(1) await message.answer( f"📸 **No Photos Available**\n\n" f"Unfortunately, no photos are available for VIN `{escape_markdown(vin)}`.\n\n" f"Your payment has been processed. Please contact support if you believe this is an error.", reply_markup=builder.as_markup(), parse_mode="Markdown" ) except Exception as e: logging.error(f"Error in handle_photos_payment: {e}") await message.answer("❌ **Photo Error**\n\nThere was an error retrieving your photos. Please contact support.")