I need some help to evaluate whether I am doing it right. The scenario is, a 3rd party application is sending a webhook request after a successful payment but the problem is that sometimes this application may send the same notification more than once. So it is recommended to ensure that implementation of the webhook is idempotent. So steps that I am implementing for this are if signature is correct (assume it is correct), find orders record in the database using orderId
in the request params. Please note: orderId
in request params is payment_gateway_order_identifier
in orders table. If txStatus
is 'SUCCESS'
AND haven't already processed COLLECTION payment for this same order, create payments record. 201 response with nothing in the response body. Otherwise, 201 response with nothing in the response body. Otherwise, 422 response with {message: "Signature is incorrect"}
in response body.
views.py
@api_view(['POST'])
def cashfree_request(request):
if request.method == 'POST':
data=request.POST.dict()
payment_gateway_order_identifier= data['orderId']
amount = data['orderAmount']
transaction_status = data['txStatus']
signature = data['signature']
if(computedsignature==signature): #assume it to be true
order=Orders.objects.get(
payment_gateway_order_identifier=payment_gateway_order_identifier)
if transaction_status=='SUCCESS':
try:
payment= Payments.objects.get(orders=order)
return Response({"Payment":"Done"},status=status.HTTP_200_OK)
except (Payments.DoesNotExist):
payment = Payments(orders=order,amount=amount,datetime=datetime)
payment.save()
return Response(status=status.HTTP_200_OK)
else:
return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY)
models.py
class Orders(models.Model):
id= models.AutoField(primary_key=True)
amount = models.DecimalField(max_digits=19, decimal_places=4)
payment_gateway_order_identifier = models.UUIDField(
primary_key=False,default=uuid.uuid4,editable=False,unique=True)
class Payments(models.Model):
id = models.AutoField(primary_key=True)
orders = models.ForeignKey(Orders, on_delete=models.CASCADE)
amount = models.DecimalField(max_digits=19, decimal_places=4, verbose_name='Price in INR')
datetime = models.DateTimeField(auto_now=False,auto_now_add=False)