Files
goodtimes/goodtimes/webhook/payment_processing_service.py
2024-08-12 20:47:36 +05:30

181 lines
6.5 KiB
Python

from venv import logger
from django.db import transaction
from manage_wallets.models import (
PaymentMethod,
Transaction,
TransactionStatus,
TransactionType,
)
from .notification_service import NotificationService
from .referral_reward_service import ReferralRewardService
from .subscription_service import SubscriptionService
from .webhook_service import WebhookService
class PaymentProcessingService:
def __init__(
self,
webhook_data,
stripe_subscription,
current_period_start,
current_period_end,
):
self.webhook_service = WebhookService(webhook_data)
self._order_id = None
self.notification_service = NotificationService()
self.subscription_service = SubscriptionService()
self.stripe_subscription = stripe_subscription
self.current_period_start = current_period_start
self.current_period_end = current_period_end
@property
def charge_data(self):
"""Return charge data from the webhook service."""
return self.webhook_service.charge_data
@property
def principal(self):
"""Return the principal from the webhook service."""
return self.webhook_service.get_principal()
@property
def subscription(self):
"""Return the subscription from the webhook service."""
return self.webhook_service.get_subscription()
@property
def order_id(self):
"""Return the order ID from the created transaction."""
return self._order_id
@order_id.setter
def order_id(self, value):
"""Set the order ID."""
self._order_id = value
@property
def coupon(self):
"""Return the coupon from the webhook service."""
return self.webhook_service.get_coupon()
@property
def amount(self):
"""Return the final amount from the webhook service."""
return self.webhook_service.get_final_amount()
def create_transaction(self):
"""Create a transaction based on webhook data."""
transaction = Transaction.objects.create(
principal=self.principal,
principal_subscription=None,
transaction_type=TransactionType.PAYMENT,
payment_method=PaymentMethod.CARD,
transaction_status=TransactionStatus.INITIATE,
amount=self.amount,
# order_id=self.order_id,
comment="Principal Subscription Initiated",
)
# Save the transaction to auto-generate the order_id
transaction.save()
# Step 1: Update the order_id in PaymentProcessingService
self.order_id = transaction.order_id
return transaction
def process_event(self):
"""Process the webhook event."""
try:
with transaction.atomic():
event_type = self.webhook_service.event_type
if event_type == "invoice.payment_succeeded" and self.charge_data.get("billing_reason") == "subscription_create":
logger.info(f"Skipping event {event_type} with billing reason 'subscription_create'")
return
txn = self.create_transaction()
if event_type in ["checkout.session.completed", "invoice.payment_succeeded"]:
self.handle_success(txn)
elif event_type in ["checkout.session.expired", "invoice.payment_failed"]:
self.handle_failure(txn)
else:
logger.warning(f"Unknown event type {event_type}. Skipping.")
return
except Exception as e:
logger.error(f"Unexpected error: {str(e)}")
raise
def handle_success(self, transaction):
"""Handle a successful payment."""
try:
self.create_principal_subscription(transaction)
self.process_referral_rewards()
self.send_success_notification(transaction)
self.update_transaction_status(
transaction,
TransactionStatus.SUCCESS,
self.subscription_service.principal_subscription,
)
except Exception as e:
self.handle_failure(transaction, error_message=str(e))
logger.error(f"Transaction Error: {str(e)}")
raise e
def create_principal_subscription(self, transaction):
"""Create or update the principal subscription."""
self.subscription_service.principal_subscription = (
self.subscription_service.create_principal_subscription(
principal=self.principal,
subscription=self.subscription,
stripe_subscription=self.stripe_subscription,
order_id=transaction.order_id,
current_period_start=self.current_period_start,
current_period_end=self.current_period_end,
coupon=self.coupon,
)
)
print("Principal Subscription Created")
def process_referral_rewards(self):
"""Handle referral rewards."""
referral_service = ReferralRewardService(
self.principal,
self.subscription_service.principal_subscription,
self.subscription,
)
referral_service.credit_referral_reward_if_applicable()
print("Referral Rewards Processed")
def send_success_notification(self, transaction):
"""Send a payment success notification."""
self.notification_service.payment_success_notification(
self.principal,
self.subscription,
self.subscription_service.principal_subscription,
transaction.amount,
)
print("Payment Success Notification Sent")
def handle_failure(self, transaction, error_message=None):
"""Handle a failed payment."""
self.update_transaction_status(
transaction, TransactionStatus.FAIL, error_message=error_message
)
self.notification_service.payment_failed_notification(
self.principal, self.subscription, transaction.amount
)
print("Payment Failure Notification Sent")
def update_transaction_status(
self, transaction, status, principal_subscription=None, error_message=None
):
"""Update the transaction status and associate with a subscription if provided."""
transaction.transaction_status = status
if principal_subscription:
transaction.principal_subscription = principal_subscription
if error_message:
transaction.error_message = error_message
transaction.save()