Code Monkey home page Code Monkey logo

Comments (3)

newearthmartin avatar newearthmartin commented on July 18, 2024

I manually executed the verify() method on the unflagged, second IPN and now it is correctly marked as duplicate txn_id.
I also manually executed that on the original IPN and it correctly remains unflagged.

So a workaround would be to call verify() again on every IPN received and check if it remains unflagged.

from django-paypal.

spookylukey avatar spookylukey commented on July 18, 2024

This sounds like a valid issue. The code here looks buggy for the case when you have out-of-order notification of IPNs:

def duplicate_txn_id(ipn_obj):
"""
Returns True if a record with this transaction id exists and its
payment_status has not changed.
This function has been completely changed from its previous implementation
where it used to specifically only check for a Pending->Completed
transition.
"""
# get latest similar transaction(s)
similars = (ipn_obj.__class__._default_manager
.filter(txn_id=ipn_obj.txn_id)
.exclude(id=ipn_obj.id)
.exclude(flag=True)
.order_by('-created_at')[:1])
if len(similars) > 0:
# we have a similar transaction, has the payment_status changed?
return similars[0].payment_status == ipn_obj.payment_status
return False

Could you check for your case that there were other IPNs with the same txn_id but different payment_status? Otherwise, we have to look further for the cause.

We should probably be instead checking for duplicate (txn_id, payment_status). I say "probably*, because that would involve trusting that PayPal are doing something sensible with how they send IPNs, or at least documented. Based on experience it's possible that neither are true...

from django-paypal.

newearthmartin avatar newearthmartin commented on July 18, 2024

Clearly, the code above checks only if the latest similar IPN has the same payment status. If the latest has a different status but the previous has the same, it doesn't recognize it as duplicate.

So the question is why we make this difference and not just this?:

duplicates = (ipn_obj.__class__._default_manager 
    .filter(txn_id=ipn_obj.txn_id) 
    .exclude(id=ipn_obj.id) 
    .exclude(flag=True)
    .exclude(payment_status=ipn_obj.payment_status)                 
return duplicates.exists()

Still, it doesn't seem that that's what's going on here. If you look at the picture above, those are the only IPNs with that txn_id and all have the same payment_status. There are no other IPNs. After I ran verify() again (which calls duplicate_txn_id()) one that was unflagged (3:01 am) became flagged as duplicate.

So maybe it happened that the first two (3 am and 3:01 am) arrived concurrently?

Here is the picture after running verify() on them again:

Screen Shot 2021-11-04 at 13 17 09

from django-paypal.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.