Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ Paypal Payment Data Transfer (PDT) allows you to display transaction details to
...
)

1. You can set settings.IGNORE_INVALID_PDT to ignore invalid PDT requests and keep them from filling up your db, a potential attack.


Using PayPal Payments Standard with Subscriptions:
--------------------------------------------------

Expand Down
18 changes: 16 additions & 2 deletions paypal/standard/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,10 @@ def verify(self, item_check_callable=None):
"""
self.response = self._postback()
self._verify_postback()
if not self.flag:

invalid_paypal_obj = self.flag

if not invalid_paypal_obj:
if self.is_transaction():
if self.payment_status not in self.PAYMENT_STATUS_CHOICES:
self.set_flag("Invalid payment_status. (%s)" % self.payment_status)
Expand All @@ -256,7 +259,18 @@ def verify(self, item_check_callable=None):
# @@@ Run a different series of checks on recurring payments.
pass

self.save()
# If settings.IGNORE_INVALID_PDT is set, don't save an invalid paypal
# object to the db. Invalid paypal objects include non-validating
# PayPalPDTForms (see pdt.views.pdt()) or postbacks that don't verify
# Keeps bad PDT requests from filling up your db, a potential attack.
# Note this only effects PDT, since IPN objects get saved during
# ipn.views.ipn().

if not invalid_paypal_obj or \
not hasattr(settings, 'IGNORE_INVALID_PDT') or \
not settings.IGNORE_INVALID_PDT:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not simply if not invalid_paypal_obj or getattr(settings, 'IGNORE_INVALID_PDT', False)?

self.save()

self.send_signals()

def verify_secret(self, form_instance, secret):
Expand Down
11 changes: 6 additions & 5 deletions paypal/standard/pdt/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,12 @@ def _verify_postback(self):
except ValueError, e:
pass

qd = QueryDict('', mutable=True)
qd.update(response_dict)
qd.update(dict(ipaddress=self.ipaddress, st=self.st, flag_info=self.flag_info))
pdt_form = PayPalPDTForm(qd, instance=self)
pdt_form.save(commit=False)
if not self.flag:
qd = QueryDict('', mutable=True)
qd.update(response_dict)
qd.update(dict(ipaddress=self.ipaddress, st=self.st, flag_info=self.flag_info))
pdt_form = PayPalPDTForm(qd, instance=self)
pdt_form.save(commit=False)

def send_signals(self):
# Send the PDT signals...
Expand Down
17 changes: 14 additions & 3 deletions paypal/standard/pdt/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,19 @@
from django.views.decorators.http import require_GET
from paypal.standard.pdt.models import PayPalPDT
from paypal.standard.pdt.forms import PayPalPDTForm
from django.views.decorators.csrf import csrf_exempt


@require_GET
# 09/23/2011 - Cole Krumbholz
# Paypal has started POSTing to the return_url
# GET QueryDict still contains expected parameters
# POST QueryDict now includes:
# <QueryDict: {u'merchant_return_link': [u'click here'], u'form_charset': [u'UTF-8']}>
# Removing the require_GET decorator keeps a 405 error from hitting the user
# The view still operates as expected, albeit after limited testing
#
# @require_GET

@csrf_exempt
def pdt(request, item_check_callable=None, template="pdt/pdt.html", context=None):
"""Payment data transfer implementation: http://tinyurl.com/c9jjmw"""
context = context or {}
Expand Down Expand Up @@ -41,10 +51,11 @@ def pdt(request, item_check_callable=None, template="pdt/pdt.html", context=None
pdt_obj.initialize(request)

if not failed:
pdt_obj.txn_id = txn_id
# The PDT object gets saved during verify
pdt_obj.verify(item_check_callable)
else:
pass # we ignore any PDT requests that don't have a transaction id

context.update({"failed":failed, "pdt_obj":pdt_obj})
return render_to_response(template, context, RequestContext(request))
return render_to_response(template, context, RequestContext(request))