Permalink
Browse files

Fixed encoding problem for parameters sent in PayPal IPN POST data

  • Loading branch information...
1 parent d09a50b commit 270b7d5147ea7d8261a464fb8af0267dcb13cfe5 @spookylukey committed Jun 11, 2012
Showing with 37 additions and 18 deletions.
  1. +5 −2 paypal/standard/ipn/tests/test_ipn.py
  2. +32 −16 paypal/standard/ipn/views.py
@@ -29,7 +29,7 @@
"txn_type": "express_checkout",
"handling_amount": "0.00",
"payment_date": "23:04:06 Feb 02, 2009 PST",
- "first_name": "Test",
+ "first_name": "J\xF6rg",
"item_name": "",
"charset": "windows-1252",
"custom": "website_id=13&user_id=21",
@@ -119,9 +119,12 @@ def handle_signal(sender, **kwargs):
self.assertTrue(self.got_signal)
self.assertEqual(self.signal_obj, ipn_obj)
+ return ipn_obj
def test_correct_ipn(self):
- self.assertGotSignal(payment_was_successful, False)
+ ipn_obj = self.assertGotSignal(payment_was_successful, False)
+ # Check some encoding issues:
+ self.assertEqual(ipn_obj.first_name, u"J\u00f6rg")
def test_failed_ipn(self):
PayPalIPN._postback = lambda self: "INVALID"
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from django.http import HttpResponse
+from django.http import HttpResponse, QueryDict
from django.views.decorators.http import require_POST
from django.views.decorators.csrf import csrf_exempt
from paypal.standard.ipn.forms import PayPalIPNForm
@@ -24,23 +24,39 @@ def ipn(request, item_check_callable=None):
ipn_obj = None
# Clean up the data as PayPal sends some weird values such as "N/A"
- data = request.POST.copy()
- date_fields = ('time_created', 'payment_date', 'next_payment_date',
- 'subscr_date', 'subscr_effective')
- for date_field in date_fields:
- if data.get(date_field) == 'N/A':
- del data[date_field]
+ # Also, need to cope with custom encoding, which is stored in the body (!).
+ # Assuming the tolerate parsing of QueryDict and an ASCII-like encoding,
+ # such as windows-1252, latin1 or UTF8, the following will work:
- form = PayPalIPNForm(data)
- if form.is_valid():
- try:
- #When commit = False, object is returned without saving to DB.
- ipn_obj = form.save(commit = False)
- except Exception, e:
- flag = "Exception while processing. (%s)" % e
+ encoding = request.POST.get('charset', None)
+
+ if encoding is None:
+ flag = "Invalid form - no charset passed, can't decode"
+ data = None
else:
- flag = "Invalid form. (%s)" % form.errors
-
+ try:
+ data = QueryDict(request.raw_post_data, encoding=encoding)
+ except LookupError:
+ data = None
+ flag = "Invalid form - invalid charset"
+
+ if data is not None:
+ date_fields = ('time_created', 'payment_date', 'next_payment_date',
+ 'subscr_date', 'subscr_effective')
+ for date_field in date_fields:
+ if data.get(date_field) == 'N/A':
+ del data[date_field]
+
+ form = PayPalIPNForm(data)
+ if form.is_valid():
+ try:
+ #When commit = False, object is returned without saving to DB.
+ ipn_obj = form.save(commit = False)
+ except Exception, e:
+ flag = "Exception while processing. (%s)" % e
+ else:
+ flag = "Invalid form. (%s)" % form.errors
+
if ipn_obj is None:
ipn_obj = PayPalIPN()

2 comments on commit 270b7d5

I hadn't seen a value of N/A come through but I have been getting these messages with a subscr_failed message:

Invalid form. (<ul class="errorlist"><li>retry_at<ul class="errorlist"><li>Enter a valid date/time.</li></ul></li></ul>)

Has this branch been working well for you? I was looking at merging it into mine. I've had some issues where the date formatting from paypal causes IPN messages to break and I have to add the following DATETIME_INPUT_FORMATS formatting to support the paypal IPN handling:

"%H:%M:%S %b %e, %Y %Z" # 03:00:00 Aug 15, 2012 PDT

A bit of a pain because it means if you have USE_L10N turned on you have to set up a whole formats package. I was thinking maybe it makes sense to explicitly switch into the datetime format parsing here rather than rely on the user having set up correctly.

Owner

spookylukey replied Aug 26, 2012

My branch is working well for me. What you are describing sounds like a completely different issue, it needs it's own ticket.

Please sign in to comment.