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)
-
2\$\begingroup\$ Based on your wording, sometimes this application may send the same notification more than once is a little ambigious. Is this an issue you need help fixing (in which case this question is off-topic and needs to move to StackOverflow)? \$\endgroup\$Reinderien– Reinderien2021年05月20日 15:07:49 +00:00Commented May 20, 2021 at 15:07
-
1\$\begingroup\$ Otherwise, if it's true that I need help to evaluate whether I am doing it right or is there a better way and your code is already doing what it should, then this question is on-topic but you might want to revisit its wording to make that clear. \$\endgroup\$Reinderien– Reinderien2021年05月20日 15:08:45 +00:00Commented May 20, 2021 at 15:08
-
1\$\begingroup\$ No actually i just need an evaluation weather i have written the code in correct way though it is working fine. \$\endgroup\$Amit Yadav– Amit Yadav2021年05月20日 16:30:09 +00:00Commented May 20, 2021 at 16:30