Notify users after Tribute payment
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
import logging
|
||||
import hmac
|
||||
import hashlib
|
||||
import json
|
||||
from aiohttp import web
|
||||
from aiogram import Bot
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from config.settings import Settings
|
||||
from bot.middlewares.i18n import JsonI18n
|
||||
from bot.services.subscription_service import SubscriptionService
|
||||
from bot.services.panel_api_service import PanelApiService
|
||||
from bot.services.referral_service import ReferralService
|
||||
from db.dal import payment_dal, user_dal, subscription_dal
|
||||
|
||||
async def tribute_webhook_route(request: web.Request):
|
||||
bot: Bot = request.app['bot']
|
||||
settings: Settings = request.app['settings']
|
||||
i18n: JsonI18n = request.app['i18n']
|
||||
async_session_factory: sessionmaker = request.app['async_session_factory']
|
||||
panel_service: PanelApiService = request.app['panel_service']
|
||||
subscription_service: SubscriptionService = request.app['subscription_service']
|
||||
referral_service: ReferralService = request.app['referral_service']
|
||||
|
||||
raw_body = await request.read()
|
||||
signature_header = request.headers.get('trbt-signature')
|
||||
if settings.TRIBUTE_API_KEY:
|
||||
if not signature_header:
|
||||
return web.Response(status=403, text="no_signature")
|
||||
expected_sig = hmac.new(
|
||||
settings.TRIBUTE_API_KEY.encode(), raw_body, hashlib.sha256
|
||||
).hexdigest()
|
||||
if not hmac.compare_digest(expected_sig, signature_header):
|
||||
return web.Response(status=403, text="invalid_signature")
|
||||
|
||||
try:
|
||||
payload = json.loads(raw_body.decode())
|
||||
except Exception:
|
||||
return web.Response(status=400, text="bad_request")
|
||||
|
||||
event_name = payload.get('name')
|
||||
data = payload.get('payload', {})
|
||||
user_id = data.get('telegram_user_id')
|
||||
price_val = data.get('price')
|
||||
|
||||
if not user_id or price_val is None:
|
||||
return web.Response(status=200, text="ok_missing_fields")
|
||||
|
||||
months_map = {int(v): m for m, v in settings.subscription_options.items()}
|
||||
price_rub = price_val / 100
|
||||
months = months_map.get(int(price_rub))
|
||||
if not months:
|
||||
logging.warning(f"Tribute webhook: price {price_val} not mapped to months")
|
||||
return web.Response(status=200, text="ok_price_unmapped")
|
||||
|
||||
async with async_session_factory() as session:
|
||||
if event_name == 'new_subscription':
|
||||
payment_record = await payment_dal.create_payment_record(
|
||||
session,
|
||||
{
|
||||
'user_id': user_id,
|
||||
'amount': float(price_rub),
|
||||
'currency': 'RUB',
|
||||
'status': 'succeeded',
|
||||
'description': 'Tribute subscription',
|
||||
'subscription_duration_months': months,
|
||||
'provider_payment_id': str(data.get('subscription_id')),
|
||||
'provider': 'tribute',
|
||||
},
|
||||
)
|
||||
activation_details = await subscription_service.activate_subscription(
|
||||
session,
|
||||
user_id,
|
||||
months,
|
||||
float(price_rub),
|
||||
payment_record.payment_id,
|
||||
provider='tribute',
|
||||
)
|
||||
referral_bonus = await referral_service.apply_referral_bonuses_for_payment(
|
||||
session, user_id, months
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
db_user = await user_dal.get_user_by_id(session, user_id)
|
||||
lang = db_user.language_code if db_user and db_user.language_code else settings.DEFAULT_LANGUAGE
|
||||
_ = lambda k, **kw: i18n.gettext(lang, k, **kw)
|
||||
|
||||
applied_ref_days = referral_bonus.get('referee_bonus_applied_days') if referral_bonus else None
|
||||
final_end = referral_bonus.get('referee_new_end_date') if referral_bonus else activation_details.get('end_date')
|
||||
|
||||
if final_end:
|
||||
if applied_ref_days:
|
||||
inviter_name_display = _('friend_placeholder')
|
||||
if db_user and db_user.referred_by_id:
|
||||
inviter = await user_dal.get_user_by_id(session, db_user.referred_by_id)
|
||||
if inviter and inviter.first_name:
|
||||
inviter_name_display = inviter.first_name
|
||||
elif inviter and inviter.username:
|
||||
inviter_name_display = f"@{inviter.username}"
|
||||
success_msg = _("payment_successful_with_referral_bonus",
|
||||
months=months,
|
||||
base_end_date=activation_details["end_date"].strftime('%Y-%m-%d'),
|
||||
bonus_days=applied_ref_days,
|
||||
final_end_date=final_end.strftime('%Y-%m-%d'),
|
||||
inviter_name=inviter_name_display)
|
||||
else:
|
||||
success_msg = _("payment_successful", months=months,
|
||||
end_date=final_end.strftime('%Y-%m-%d'))
|
||||
|
||||
try:
|
||||
await bot.send_message(user_id, success_msg)
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to send Tribute payment success message to user {user_id}: {e}")
|
||||
elif event_name == 'cancelled_subscription':
|
||||
db_user = await user_dal.get_user_by_id(session, user_id)
|
||||
lang = db_user.language_code if db_user and db_user.language_code else settings.DEFAULT_LANGUAGE
|
||||
_ = lambda k, **kw: i18n.gettext(lang, k, **kw)
|
||||
try:
|
||||
await bot.send_message(user_id, _("subscription_cancelled_notification"))
|
||||
except Exception as e:
|
||||
logging.warning(f"Failed to notify user {user_id} about cancellation: {e}")
|
||||
await subscription_dal.set_skip_notifications_for_provider(
|
||||
session, user_id, 'tribute', False)
|
||||
await session.commit()
|
||||
else:
|
||||
await session.commit()
|
||||
return web.Response(status=200, text="ok")
|
||||
Reference in New Issue
Block a user