getting webhook events into database

This commit is contained in:
rizwanisready
2024-04-19 13:00:41 +05:30
parent c0cf079748
commit 97f8209207
4 changed files with 119 additions and 12 deletions

View File

@@ -166,7 +166,7 @@ class CreateEventSerializer(serializers.ModelSerializer):
# Update fields if there is any change.
if tags is not None:
# Clear existing tags and add the new ones
# instance.tags.clear()
instance.tags.clear()
instance.tags.add(*tags)
if images_data is not None:

View File

@@ -14,6 +14,7 @@ from manage_subscriptions.models import (
Subscription,
PrincipalSubscription,
SubscriptionStatus,
WebhookEvent,
)
from goodtimes.utils import ApiResponse
from accounts.resource_action import (
@@ -174,6 +175,28 @@ class StripeWebhookTest(APIView):
event = None
try:
event = stripe.Event.construct_from(json.loads(payload), stripe.api_key)
event_id = event["id"]
# Check if the event has been processed already
if WebhookEvent.objects.filter(event_id=event_id, status="processed").exists():
return ApiResponse.success(
status=status.HTTP_208_ALREADY_REPORTED,
message="Event already processed",
)
# Log event processing
WebhookEvent.objects.create(
event_id=event_id,
event_payload=json.loads(payload), # optional
)
payment_service = services.PaymentProcessingService(webhook_data=event)
payment_service.process_event()
webhook_event = WebhookEvent.objects.get(event_id=event_id)
webhook_event.status = "processed"
return ApiResponse.success(
status=status.HTTP_200_OK, message="Event processed successfully"
)
except ValueError as e:
# Invalid payload
return ApiResponse.error(
@@ -188,16 +211,6 @@ class StripeWebhookTest(APIView):
message="Invalid signature",
errors=str(e),
)
# Initialize the PaymentProcessingService with the webhook data
payment_service = services.PaymentProcessingService(webhook_data=event)
try:
# Process the event (handle both successful and failed charges)
payment_service.process_event()
return ApiResponse.success(
status=status.HTTP_200_OK, message="Event processed successfully"
)
except Transaction.DoesNotExist:
# Handle case where the transaction does not exist
return ApiResponse.error(
@@ -205,10 +218,16 @@ class StripeWebhookTest(APIView):
)
except Exception as e:
# Handle any other exceptions
WebhookEvent.objects.create(
event_id=event_id,
status="failed",
error_message=str(e),
event_payload=json.loads(payload) # Optionally store payload for audit
)
return ApiResponse.error(
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
message="Error processing event",
errors=str(e),
errors=str(e)
)

View File

@@ -0,0 +1,69 @@
# Generated by Django 5.0.2 on 2024-04-19 07:29
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
(
"manage_subscriptions",
"0003_subscription_high_amount_subscription_image_and_more",
),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name="WebhookEvent",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("active", models.BooleanField(default=True)),
("deleted", models.BooleanField(default=False)),
("created_on", models.DateTimeField(auto_now_add=True)),
("modified_on", models.DateTimeField(auto_now=True)),
(
"event_id",
models.CharField(db_index=True, max_length=255, unique=True),
),
("received_at", models.DateTimeField(auto_now_add=True)),
("processed_at", models.DateTimeField(blank=True, null=True)),
("status", models.CharField(default="received", max_length=20)),
("error_message", models.TextField(blank=True, null=True)),
("event_payload", models.JSONField(blank=True, null=True)),
(
"created_by",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="%(class)s_created",
to=settings.AUTH_USER_MODEL,
),
),
(
"modified_by",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="%(class)s_modified",
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"db_table": "webhook_event",
},
),
]

View File

@@ -74,3 +74,22 @@ class PrincipalSubscription(BaseModel):
def __str__(self):
return f"{self.subscription} - {self.principal.first_name}"
class WebhookEvent(BaseModel):
event_id = models.CharField(max_length=255, unique=True, db_index=True)
received_at = models.DateTimeField(auto_now_add=True)
processed_at = models.DateTimeField(null=True, blank=True)
status = models.CharField(
max_length=20, default="received"
) # e.g., 'received', 'processed', 'failed'
error_message = models.TextField(null=True, blank=True)
event_payload = models.JSONField(
null=True, blank=True
) # Optional: Store the payload for debugging.
def __str__(self):
return f"Webhook Event {self.event_id} - Status: {self.status}"
class Meta:
db_table = "webhook_event"