181 lines
6.5 KiB
Python
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()
|