updated webhook module
This commit is contained in:
@@ -136,8 +136,10 @@ class PasswordResetSerializer(BasePasswordSerializer, serializers.ModelSerialize
|
||||
model = IAmPrincipal
|
||||
fields = ["password", "confirm_password"]
|
||||
|
||||
|
||||
from phonenumbers import parse, phonenumberutil, NumberParseException
|
||||
|
||||
|
||||
class ProfileSerializer(serializers.ModelSerializer):
|
||||
profile_photo = serializers.ImageField(required=False)
|
||||
email = serializers.CharField(read_only=True)
|
||||
@@ -227,6 +229,7 @@ class ProfileSerializer(serializers.ModelSerializer):
|
||||
"has_active_subscription": False,
|
||||
"in_grace_period": False,
|
||||
"grace_period_end_date": None,
|
||||
"subscription_id": None,
|
||||
}
|
||||
today = timezone.now().date()
|
||||
|
||||
@@ -245,6 +248,9 @@ class ProfileSerializer(serializers.ModelSerializer):
|
||||
) # Order by descending grace_period_end_date and take the first
|
||||
|
||||
if latest_subscription:
|
||||
subscription_status["subscription_id"] = (
|
||||
latest_subscription.stripe_subscription_id
|
||||
)
|
||||
# Check if we're within the grace period
|
||||
if today <= latest_subscription.grace_period_end_date:
|
||||
subscription_status["has_active_subscription"] = (
|
||||
@@ -369,4 +375,4 @@ class AppVersionSerializer(serializers.ModelSerializer):
|
||||
class IAmPrincipalExtendedDataSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = IAmPrincipalExtendedData
|
||||
fields = "__all__"
|
||||
fields = "__all__"
|
||||
|
||||
@@ -27,35 +27,40 @@ class PaymentProcessingService:
|
||||
self.stripe_subscription = stripe_subscription
|
||||
self.current_period_start = current_period_start
|
||||
self.current_period_end = current_period_end
|
||||
self.principal_subscription = None
|
||||
|
||||
@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 webhook service."""
|
||||
return self.webhook_service.get_order_id()
|
||||
|
||||
@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(
|
||||
return Transaction.objects.create(
|
||||
principal=self.principal,
|
||||
principal_subscription=None,
|
||||
transaction_type=TransactionType.PAYMENT,
|
||||
@@ -65,69 +70,92 @@ class PaymentProcessingService:
|
||||
order_id=self.order_id,
|
||||
comment="Principal Subscription Initiated",
|
||||
)
|
||||
return transaction
|
||||
|
||||
def process_event(self):
|
||||
event_type = self.webhook_service.event_type
|
||||
if event_type == "checkout.session.completed":
|
||||
self.handle_success()
|
||||
elif event_type == "invoice.payment_succeeded":
|
||||
if self.charge_data.get("billing_reason") != "subscription_create":
|
||||
self.handle_success()
|
||||
else:
|
||||
self.handle_failure()
|
||||
|
||||
def handle_success(self):
|
||||
"""Process the webhook event."""
|
||||
with transaction.atomic():
|
||||
# Create or update the principal subscription
|
||||
transactio = self.create_transaction()
|
||||
event_type = self.webhook_service.event_type
|
||||
txn = self.create_transaction()
|
||||
try:
|
||||
self.principal_subscription = (
|
||||
self.subscription_service.create_principal_subscription(
|
||||
principal=self.principal,
|
||||
subscription=self.subscription,
|
||||
stripe_subscription=self.stripe_subscription,
|
||||
order_id=self.order_id,
|
||||
current_period_start=self.current_period_start,
|
||||
current_period_end=self.current_period_end,
|
||||
coupon=self.coupon,
|
||||
)
|
||||
)
|
||||
print("First Part Done....!!!!!")
|
||||
|
||||
# Update transaction status to success
|
||||
self.subscription_service.update_transaction_success(
|
||||
transactio, self.principal_subscription
|
||||
)
|
||||
print("Second Part Done....!!!!!")
|
||||
|
||||
# Handle referral rewards
|
||||
referral_service = ReferralRewardService(
|
||||
self.principal, self.principal_subscription, self.subscription
|
||||
)
|
||||
print("Third Part Done...!!!!!!!!!!!")
|
||||
referral_service.credit_referral_reward_if_applicable()
|
||||
print("Fourth Part Done....!!!!!")
|
||||
|
||||
# Send payment success notification
|
||||
self.notification_service.payment_success_notification(
|
||||
self.principal,
|
||||
self.subscription,
|
||||
self.principal_subscription,
|
||||
transactio.amount,
|
||||
)
|
||||
if event_type == "checkout.session.completed":
|
||||
self.handle_success(txn)
|
||||
elif event_type == "invoice.payment_succeeded":
|
||||
if self.charge_data.get("billing_reason") != "subscription_create":
|
||||
self.handle_success(txn)
|
||||
else:
|
||||
self.handle_failure(txn)
|
||||
except Exception as e:
|
||||
transactio.transaction_status = TransactionStatus.FAIL
|
||||
transactio.error_message = str(e)
|
||||
logger.error(f"Transaction Error: {str(e)}")
|
||||
transactio.save()
|
||||
raise e
|
||||
else:
|
||||
transactio.transaction_status = TransactionStatus.SUCCESS
|
||||
transactio.save()
|
||||
|
||||
def handle_failure(self, transactio):
|
||||
self.subscription_service.update_transaction_failure(transactio)
|
||||
# self.notification_service.payment_failed_notification(
|
||||
# self.principal, self.subscription, self.transaction.amount
|
||||
# )
|
||||
def handle_success(self, transaction):
|
||||
"""Handle a successful payment."""
|
||||
try:
|
||||
self.create_principal_subscription()
|
||||
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):
|
||||
"""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=self.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
|
||||
)
|
||||
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()
|
||||
|
||||
@@ -2,7 +2,6 @@ from datetime import timedelta
|
||||
from django.utils import timezone
|
||||
import datetime
|
||||
from manage_subscriptions.models import PrincipalSubscription
|
||||
from manage_wallets.models import TransactionStatus
|
||||
|
||||
|
||||
class SubscriptionService:
|
||||
@@ -11,10 +10,12 @@ class SubscriptionService:
|
||||
|
||||
@property
|
||||
def principal_subscription(self):
|
||||
"""Get the current principal subscription."""
|
||||
return self._principal_subscription
|
||||
|
||||
@principal_subscription.setter
|
||||
def principal_subscription(self, value):
|
||||
"""Set the current principal subscription."""
|
||||
self._principal_subscription = value
|
||||
|
||||
def create_principal_subscription(
|
||||
@@ -51,16 +52,6 @@ class SubscriptionService:
|
||||
self.principal_subscription = principal_subscription
|
||||
return principal_subscription
|
||||
|
||||
def update_transaction_success(self, principal_transaction, principal_subscription):
|
||||
"""Update transaction status to success and associate with a subscription."""
|
||||
self._update_transaction_status(
|
||||
principal_transaction, TransactionStatus.SUCCESS, principal_subscription
|
||||
)
|
||||
|
||||
def update_transaction_failure(self, principal_transaction):
|
||||
"""Update transaction status to failure."""
|
||||
self._update_transaction_status(principal_transaction, TransactionStatus.FAIL)
|
||||
|
||||
def _calculate_dates(
|
||||
self, current_period_start, current_period_end, subscription_days
|
||||
):
|
||||
@@ -83,12 +74,3 @@ class SubscriptionService:
|
||||
coupon.no_of_redeems += 1
|
||||
coupon.save()
|
||||
print("Coupon Saved Successfully!!!")
|
||||
|
||||
def _update_transaction_status(
|
||||
self, transaction, status, principal_subscription=None
|
||||
):
|
||||
"""Update the transaction status and associate with a subscription if provided."""
|
||||
transaction.transaction_status = status
|
||||
if principal_subscription:
|
||||
transaction.principal_subscription = principal_subscription
|
||||
transaction.save()
|
||||
|
||||
@@ -293,3 +293,47 @@ class LastActiveSubscriptionView(APIView):
|
||||
message="No Active Subscription Found",
|
||||
errors="No Active Subscription Found",
|
||||
)
|
||||
|
||||
|
||||
class CancelSubscription(APIView):
|
||||
authentication_classes = [JWTAuthentication]
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def post(self, request):
|
||||
data = json.loads(request.body)
|
||||
subscription_id = data.get("subscription_id")
|
||||
|
||||
try:
|
||||
subscription = PrincipalSubscription.objects.get(
|
||||
id=subscription_id, principal=request.user
|
||||
)
|
||||
except PrincipalSubscription.DoesNotExist:
|
||||
return ApiResponse(
|
||||
message=constants.FAILURE,
|
||||
errors="Subscription not found.",
|
||||
status=status.HTTP_404_NOT_FOUND,
|
||||
)
|
||||
|
||||
with transaction.atomic():
|
||||
if subscription.is_stripe_subscription:
|
||||
# Cancel Stripe subscription
|
||||
try:
|
||||
stripe.Subscription.modify(subscription.stripe_subscription_id, cancel_at_period_end=True)
|
||||
except stripe.error.InvalidRequestError as e:
|
||||
return ApiResponse(
|
||||
message=constants.FAILURE,
|
||||
errors=f"Stripe error: {str(e)}",
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
# Updating subscription status in the local database
|
||||
subscription.status = SubscriptionStatus.INACTIVE
|
||||
subscription.cancelled = True
|
||||
subscription.cancelled_date_time = timezone.now()
|
||||
subscription.save()
|
||||
|
||||
return ApiResponse(
|
||||
message=constants.SUCCESS,
|
||||
data="Subscription cancelled successfully.",
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
@@ -727,7 +727,6 @@ def create_checkout_session(request):
|
||||
order_id = f"order_{timezone.localtime().timestamp()}_{request.user.email}"
|
||||
|
||||
# Default transaction amount based on subscription amount
|
||||
final_amount = subscription.amount
|
||||
print("Before Session Data")
|
||||
session_data = {
|
||||
"payment_method_types": ["card"],
|
||||
|
||||
Reference in New Issue
Block a user