I am using Django-Paypal to receive payments for 3 different services. Each service has a separate model (say, ServiceA, ServiceB and ServiceC) but all are within the same app. I need to update the payment status of the correct model to ‘paid=True’ after receiving payment for the corresponding service.
I have 3 payment processing views (each per service) which are working well, as all payments are completed successfully. Similarly, I have created 3 signals/receiver functions (each per model) and placed them in signals.py. When I test one signal at a time, it works well. The payment status is successfully updated to ‘paid=True’. However, when I include all the three signals in signals.py, things stop working. I noted that each time a payment is received, the first 2 receiver functions are fired, leading to an error. See the code at the bottom
How do I specify which receiver function should be called when a payment is received from a specific model? Or which is the best way to implement the above successfully? When I am using inbuilt signals such as pre-save, it is possible to specify the model to be updated by adding the sender at the decorator e.g.
@receiver(pre-save, sender = MyModel)
As for the PayPal IPN signal, I am completely stuck and any assistance, including ideas, are welcome. Thanks in advance.
@receiver(valid_ipn_received)
def Servicea_order_item_paid(sender, **kwargs):
ipn_obj = sender
if ipn_obj.payment_status == ST_PP_COMPLETED:
servicea = ServiceA.objects.get(order_id =ipn_obj.invoice)
if (
ipn_obj.mc_gross == servicea.total_cost()
and ipn_obj.mc_currency == 'USD'
and ipn_obj.receiver_email == "xxxxxx@business.example.com"
):
servicea.paid = True
servicea.save()
@receiver(valid_ipn_received)
def serviceb_order_item_paid(sender, **kwargs):
ipn_obj = sender
if ipn_obj.payment_status == ST_PP_COMPLETED:
serviceb = ServiceB.objects.get(order_id =ipn_obj.invoice)
if (
ipn_obj.mc_gross == serviceb.total_cost()
and ipn_obj.mc_currency == 'USD'
and ipn_obj.receiver_email == "xxxxxx@business.example.com"
):
serviceb.paid = True
serviceb.save()
@receiver(valid_ipn_received)
def servicec_order_item_paid(sender, **kwargs):
ipn_obj = sender
if ipn_obj.payment_status == ST_PP_COMPLETED:
servicec = ServiceC.objects.get(order_id =ipn_obj.invoice)
if (
ipn_obj.mc_gross == servicec.total_cost()
and ipn_obj.mc_currency == 'USD'
and ipn_obj.receiver_email == "xxxxxx@business.example.com"
):
servicec.paid = True
servicec.save()
Though I wasn't able to get an answer here, I finally solved the problem. I did so by combining the three signals into a single 'compound' signal using:
The final code is lengthy but it's working well without any errors. Even the 'Duplicate txn_id' error finally disappeared. For the purposes of sharing code, I have replaced the actual services with ServiceA, B and C respectively. See the code below:
@receiver(valid_ipn_received)
def order_item_paid(sender, **kwargs):
ipn_obj = sender
if ipn_obj.payment_status == ST_PP_COMPLETED:
print('Payment was sucessful!!!!, pending other verifications')
if ServiceA.objects.filter(order_id =ipn_obj.invoice).exists():
print('!!!! ServiceA Oder object exists')
servicea = get_object_or_404(ServiceA, order_id =ipn_obj.invoice)
if (
ipn_obj.mc_gross == servicea.total_cost()
and ipn_obj.mc_currency == 'USD'
and ipn_obj.receiver_email == "xxxxxxx@business.example.com"
):
print('!!!. Amount, Currency and Email Verified')
servicea.paid = True
servicea.save()
else:
print('!!!! ServiceA order item does not exist')
if ServiceB.objects.filter(order_id =ipn_obj.invoice).exists():
print('!!!! ServiceB order item exists')
serviceb = get_object_or_404(ServiceB, order_id =ipn_obj.invoice)
if (
ipn_obj.mc_gross == serviceb.total_cost()
and ipn_obj.mc_currency == 'USD'
and ipn_obj.receiver_email == "xxxxxx@business.example.com"
):
print('!!!!!!. Amount, Currency and Email Verified')
serviceb.paid = True
serviceb.save()
else:
print('!!!!!!!!Service B Order object does not exist')
if ServiceC.objects.filter(order_id =ipn_obj.invoice).exists():
print('!!!!!!!!Service C order item exists')
servicec = get_object_or_404(ServiceC, order_id =ipn_obj.invoice)
if (
ipn_obj.mc_gross == servicec.total_cost()
and ipn_obj.mc_currency == 'USD'
and ipn_obj.receiver_email == "xxxxxxx@business.example.com"
):
print('!!!!!!. Amount, Currency and Email Verified')
servicec.paid = True
servicec.save()
else:
print('!!! Service C order object does not exist')