From 0d2a99add6b7119c939394117e374399f294c135 Mon Sep 17 00:00:00 2001 From: Johannes Hoppe Date: Thu, 2 Jan 2014 16:40:39 +0100 Subject: [PATCH 1/3] https://code.djangoproject.com/ticket/17323 Django renamed raw_post_data to body --- .gitignore | 2 ++ paypal/standard/models.py | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 905e09e..a902c62 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ /build /django_paypal.egg-info *.swp + +.idea/ diff --git a/paypal/standard/models.py b/paypal/standard/models.py index 12dbc8a..71ca700 100644 --- a/paypal/standard/models.py +++ b/paypal/standard/models.py @@ -321,7 +321,6 @@ def send_signals(self): elif self.is_subscription_modified(): subscription_modify.send(sender=self) - def initialize(self, request): """Store the data we'll need to make the postback from the request object.""" if request.method == 'GET': @@ -329,7 +328,7 @@ def initialize(self, request): self.query = request.META.get('QUERY_STRING', '') elif request.method == 'POST': # The following works if paypal sends an ASCII bytestring, which it does. - self.query = request.raw_post_data + self.query = request.body self.ipaddress = request.META.get('REMOTE_ADDR', '') def _postback(self): From c0f9f4d67d11c537cce9a7cb25d6c7f35fe0e6cb Mon Sep 17 00:00:00 2001 From: Johannes Hoppe Date: Thu, 2 Jan 2014 17:44:50 +0100 Subject: [PATCH 2/3] renames: raw_post_data to body https://code.djangoproject.com/ticket/17323 --- paypal/standard/ipn/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paypal/standard/ipn/views.py b/paypal/standard/ipn/views.py index 610d6af..7772067 100644 --- a/paypal/standard/ipn/views.py +++ b/paypal/standard/ipn/views.py @@ -35,7 +35,7 @@ def ipn(request, item_check_callable=None): data = None else: try: - data = QueryDict(request.raw_post_data, encoding=encoding) + data = QueryDict(request.body, encoding=encoding) except LookupError: data = None flag = "Invalid form - invalid charset" From 121d108edc6dca3cdfd769c49eb6c9aeab3c7bc7 Mon Sep 17 00:00:00 2001 From: Johannes Hoppe Date: Thu, 2 Jan 2014 18:18:05 +0100 Subject: [PATCH 3/3] PEP8 cleanup --- paypal/pro/admin.py | 3 +- paypal/pro/creditcard.py | 4 +- paypal/pro/fields.py | 13 +- paypal/pro/forms.py | 5 +- paypal/pro/helpers.py | 36 +++--- paypal/pro/models.py | 25 ++-- paypal/pro/templates/pro/confirm.html | 4 +- paypal/pro/templates/pro/payment.html | 18 ++- paypal/pro/tests.py | 21 ++-- paypal/pro/views.py | 27 ++-- paypal/standard/conf.py | 16 ++- paypal/standard/forms.py | 47 +++---- paypal/standard/helpers.py | 5 +- paypal/standard/ipn/admin.py | 18 +-- paypal/standard/ipn/forms.py | 3 +- .../ipn/migrations/0001_first_migration.py | 108 +++++++++++----- ...d__chg_field_paypalipn_payment_status__.py | 116 +++++++++++------ paypal/standard/ipn/templates/ipn/ipn.html | 4 +- .../standard/ipn/templates/ipn/ipn_test.html | 68 +++++----- paypal/standard/ipn/templates/ipn/paypal.html | 2 +- paypal/standard/ipn/tests/test_ipn.py | 12 +- paypal/standard/ipn/tests/test_urls.py | 2 +- paypal/standard/ipn/urls.py | 2 +- paypal/standard/ipn/views.py | 10 +- paypal/standard/models.py | 21 ++-- paypal/standard/pdt/admin.py | 14 ++- .../pdt/migrations/0001_first_migration.py | 119 ++++++++++++------ ...d__chg_field_paypalpdt_payment_status__.py | 117 +++++++++++------ paypal/standard/pdt/models.py | 8 +- paypal/standard/pdt/templates/pdt/pdt.html | 36 ++++-- .../pdt/templates/pdt/test_pdt_response.html | 2 +- .../standard/pdt/tests/templates/pdt/pdt.html | 34 +++-- paypal/standard/pdt/tests/test_pdt.py | 67 +++++----- paypal/standard/pdt/tests/test_urls.py | 2 +- paypal/standard/pdt/urls.py | 2 +- paypal/standard/pdt/views.py | 3 +- paypal/standard/widgets.py | 3 + 37 files changed, 623 insertions(+), 374 deletions(-) diff --git a/paypal/pro/admin.py b/paypal/pro/admin.py index 5a9dc28..09b687a 100644 --- a/paypal/pro/admin.py +++ b/paypal/pro/admin.py @@ -1,6 +1,5 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -from string import split as L from django.contrib import admin from paypal.pro.models import PayPalNVP @@ -9,4 +8,6 @@ class PayPalNVPAdmin(admin.ModelAdmin): list_display = ('user', 'ipaddress', 'method', 'flag', 'flag_code', 'created_at') list_filter = ('flag', 'created_at') search_fields = ('user__email', 'ip_address', 'flag', 'firstname', 'lastname') + + admin.site.register(PayPalNVP, PayPalNVPAdmin) diff --git a/paypal/pro/creditcard.py b/paypal/pro/creditcard.py index d709c93..fbe7941 100644 --- a/paypal/pro/creditcard.py +++ b/paypal/pro/creditcard.py @@ -25,14 +25,16 @@ "5105105105105100", "4111111111111111", "4012888888881881", "4222222222222" ] + def verify_credit_card(number): """Returns the card type for given card number or None if invalid.""" return CreditCard(number).verify() + class CreditCard(object): def __init__(self, number): self.number = number - + def is_number(self): """True if there is at least one digit in number.""" self.number = re.sub(r'[^\d]', '', self.number) diff --git a/paypal/pro/fields.py b/paypal/pro/fields.py index 8b577a1..a65c695 100644 --- a/paypal/pro/fields.py +++ b/paypal/pro/fields.py @@ -3,7 +3,6 @@ from calendar import monthrange from datetime import date -from django.db import models from django import forms from django.utils.translation import ugettext as _ @@ -12,10 +11,11 @@ class CreditCardField(forms.CharField): """Form field for checking out a credit card.""" + def __init__(self, *args, **kwargs): kwargs.setdefault('max_length', 20) super(CreditCardField, self).__init__(*args, **kwargs) - + def clean(self, value): """Raises a ValidationError if the card is not valid and stashes card type.""" if value: @@ -30,6 +30,7 @@ def clean(self, value): # http://www.djangosnippets.org/snippets/907/ class CreditCardExpiryWidget(forms.MultiWidget): """MultiWidget for representing credit card expiry date.""" + def decompress(self, value): if isinstance(value, date): return [value.month, value.year] @@ -42,6 +43,7 @@ def format_output(self, rendered_widgets): html = u' / '.join(rendered_widgets) return u'%s' % html + class CreditCardExpiryField(forms.MultiValueField): EXP_MONTH = [(x, x) for x in xrange(1, 13)] EXP_YEAR = [(x, x) for x in xrange(date.today().year, date.today().year + 15)] @@ -55,12 +57,12 @@ def __init__(self, *args, **kwargs): errors = self.default_error_messages.copy() if 'error_messages' in kwargs: errors.update(kwargs['error_messages']) - + fields = ( forms.ChoiceField(choices=self.EXP_MONTH, error_messages={'invalid': errors['invalid_month']}), forms.ChoiceField(choices=self.EXP_YEAR, error_messages={'invalid': errors['invalid_year']}), ) - + super(CreditCardExpiryField, self).__init__(fields, *args, **kwargs) self.widget = CreditCardExpiryWidget(widgets=[fields[0].widget, fields[1].widget]) @@ -90,7 +92,7 @@ class CreditCardCVV2Field(forms.CharField): def __init__(self, *args, **kwargs): kwargs.setdefault('max_length', 4) super(CreditCardCVV2Field, self).__init__(*args, **kwargs) - + # Country Field from: # http://www.djangosnippets.org/snippets/494/ @@ -337,6 +339,7 @@ def __init__(self, *args, **kwargs): ('ZW', _('Zimbabwe')), ) + class CountryField(forms.ChoiceField): def __init__(self, *args, **kwargs): kwargs.setdefault('choices', COUNTRIES) diff --git a/paypal/pro/forms.py b/paypal/pro/forms.py index 42418f3..e2a2374 100644 --- a/paypal/pro/forms.py +++ b/paypal/pro/forms.py @@ -5,6 +5,7 @@ from paypal.pro.fields import CreditCardField, CreditCardExpiryField, CreditCardCVV2Field, CountryField from paypal.pro.exceptions import PayPalFailure + class PaymentForm(forms.Form): """Form used to process direct payments.""" firstname = forms.CharField(255, label="First Name") @@ -21,7 +22,8 @@ class PaymentForm(forms.Form): def process(self, request, item): """Process a PayPal direct payment.""" from paypal.pro.helpers import PayPalWPP - wpp = PayPalWPP(request) + + wpp = PayPalWPP(request) params = self.cleaned_data params['creditcardtype'] = self.fields['acct'].card_type params['expdate'] = self.cleaned_data['expdate'].strftime("%m%Y") @@ -39,6 +41,7 @@ def process(self, request, item): return False return True + class ConfirmForm(forms.Form): """Hidden form used by ExpressPay flow to keep track of payer information.""" token = forms.CharField(max_length=255, widget=forms.HiddenInput()) diff --git a/paypal/pro/helpers.py b/paypal/pro/helpers.py index 4942bf2..44e73d3 100644 --- a/paypal/pro/helpers.py +++ b/paypal/pro/helpers.py @@ -17,11 +17,11 @@ from paypal.pro.exceptions import PayPalFailure TEST = settings.PAYPAL_TEST -USER = settings.PAYPAL_WPP_USER +USER = settings.PAYPAL_WPP_USER PASSWORD = settings.PAYPAL_WPP_PASSWORD SIGNATURE = settings.PAYPAL_WPP_SIGNATURE VERSION = 54.0 -BASE_PARAMS = dict(USER=USER , PWD=PASSWORD, SIGNATURE=SIGNATURE, VERSION=VERSION) +BASE_PARAMS = dict(USER=USER, PWD=PASSWORD, SIGNATURE=SIGNATURE, VERSION=VERSION) ENDPOINT = "https://api-3t.paypal.com/nvp" SANDBOX_ENDPOINT = "https://api-3t.sandbox.paypal.com/nvp" NVP_FIELDS = fields_for_model(PayPalNVP).keys() @@ -32,7 +32,8 @@ def paypal_time(time_obj=None): if time_obj is None: time_obj = time.gmtime() return time.strftime(PayPalNVP.TIMESTAMP_FORMAT, time_obj) - + + def paypaltime2datetime(s): """Convert a PayPal time string to a DateTime.""" return datetime.datetime(*(time.strptime(s, PayPalNVP.TIMESTAMP_FORMAT)[:6])) @@ -40,7 +41,7 @@ def paypaltime2datetime(s): class PayPalError(TypeError): """Error thrown when something be wrong.""" - + class PayPalWPP(object): """ @@ -52,6 +53,7 @@ class PayPalWPP(object): Name-Value Pair API Developer Guide and Reference: https://cms.paypal.com/cms_content/US/en_US/files/developer/PP_NVPAPI_DeveloperGuide.pdf """ + def __init__(self, request, params=BASE_PARAMS): """Required - USER / PWD / SIGNATURE / VERSION""" self.request = request @@ -65,7 +67,8 @@ def __init__(self, request, params=BASE_PARAMS): def doDirectPayment(self, params): """Call PayPal DoDirectPayment method.""" defaults = {"method": "DoDirectPayment", "paymentaction": "Sale"} - required = L("creditcardtype acct expdate cvv2 ipaddress firstname lastname street city state countrycode zip amt") + required = L( + "creditcardtype acct expdate cvv2 ipaddress firstname lastname street city state countrycode zip amt") nvp_obj = self._fetch(params, required, defaults) if nvp_obj.flag: raise PayPalFailure(nvp_obj.flag_info) @@ -106,7 +109,7 @@ def doExpressCheckoutPayment(self, params): raise PayPalFailure(nvp_obj.flag_info) payment_was_successful.send(params) return nvp_obj - + def createRecurringPaymentsProfile(self, params, direct=False): """ Set direct to True to indicate that this is being called as a directPayment. @@ -122,7 +125,7 @@ def createRecurringPaymentsProfile(self, params, direct=False): required + L("token payerid") nvp_obj = self._fetch(params, required, defaults) - + # Flag if profile_type != ActiveProfile if nvp_obj.flag: raise PayPalFailure(nvp_obj.flag_info) @@ -163,10 +166,10 @@ def updateRecurringPaymentsProfile(self, params): if nvp_obj.flag: raise PayPalFailure(nvp_obj.flag_info) return nvp_obj - + def billOutstandingAmount(self, params): raise NotImplementedError - + def manangeRecurringPaymentsProfileStatus(self, params, fail_silently=False): """ Requires `profileid` and `action` params. @@ -178,7 +181,8 @@ def manangeRecurringPaymentsProfileStatus(self, params, fail_silently=False): nvp_obj = self._fetch(params, required, defaults) # TODO: This fail silently check should be using the error code, but its not easy to access - if not nvp_obj.flag or (fail_silently and nvp_obj.flag_info == 'Invalid profile status for cancel action; profile should be active or suspended'): + if not nvp_obj.flag or ( + fail_silently and nvp_obj.flag_info == 'Invalid profile status for cancel action; profile should be active or suspended'): if params['action'] == 'Cancel': recurring_cancel.send(sender=nvp_obj) elif params['action'] == 'Suspend': @@ -188,7 +192,7 @@ def manangeRecurringPaymentsProfileStatus(self, params, fail_silently=False): else: raise PayPalFailure(nvp_obj.flag_info) return nvp_obj - + def refundTransaction(self, params): raise NotImplementedError @@ -208,7 +212,7 @@ def _recurring_setExpressCheckout_adapter(self, params): for k in params.keys(): if k in REMOVE: del params[k] - + return params def _fetch(self, params, required, defaults): @@ -218,7 +222,7 @@ def _fetch(self, params, required, defaults): pp_string = self.signature + urlencode(pp_params) response = self._request(pp_string) response_params = self._parse_response(response) - + if getattr(settings, 'PAYPAL_DEBUG', settings.DEBUG): print 'PayPal Request:' pprint.pprint(defaults) @@ -239,7 +243,7 @@ def _fetch(self, params, required, defaults): nvp_obj.init(self.request, params, response_params) nvp_obj.save() return nvp_obj - + def _request(self, data): """Moved out to make testing easier.""" return urllib2.urlopen(self.endpoint, data).read() @@ -251,9 +255,9 @@ def _check_and_update_params(self, required, params): """ for r in required: if r not in params: - raise PayPalError("Missing required param: %s" % r) + raise PayPalError("Missing required param: %s" % r) - # Upper case all the parameters for PayPal. + # Upper case all the parameters for PayPal. return (dict((k.upper(), v) for k, v in params.iteritems())) def _parse_response(self, response): diff --git a/paypal/pro/models.py b/paypal/pro/models.py index 9359887..5f2b270 100644 --- a/paypal/pro/models.py +++ b/paypal/pro/models.py @@ -5,11 +5,13 @@ from django.utils.http import urlencode from django.forms.models import model_to_dict from django.contrib.auth.models import User + try: from idmapper.models import SharedMemoryModel as Model except ImportError: Model = models.Model + class PayPalNVP(Model): """Record of a NVP interaction with PayPal.""" TIMESTAMP_FORMAT = "%Y-%m-%dT%H:%M:%SZ" # 2009-02-03T17:47:41Z @@ -20,7 +22,7 @@ class PayPalNVP(Model): # Response fields method = models.CharField(max_length=64, blank=True) - ack = models.CharField(max_length=32, blank=True) + ack = models.CharField(max_length=32, blank=True) profilestatus = models.CharField(max_length=32, blank=True) timestamp = models.DateTimeField(blank=True, null=True) profileid = models.CharField(max_length=32, blank=True) # I-E596DFUSD882 @@ -28,35 +30,35 @@ class PayPalNVP(Model): correlationid = models.CharField(max_length=32, blank=True) # 25b380cda7a21 token = models.CharField(max_length=64, blank=True) payerid = models.CharField(max_length=64, blank=True) - + # Transaction Fields firstname = models.CharField("First Name", max_length=255, blank=True) lastname = models.CharField("Last Name", max_length=255, blank=True) street = models.CharField("Street Address", max_length=255, blank=True) city = models.CharField("City", max_length=255, blank=True) state = models.CharField("State", max_length=255, blank=True) - countrycode = models.CharField("Country", max_length=2,blank=True) + countrycode = models.CharField("Country", max_length=2, blank=True) zip = models.CharField("Postal / Zip Code", max_length=32, blank=True) - + # Custom fields invnum = models.CharField(max_length=255, blank=True) - custom = models.CharField(max_length=255, blank=True) - + custom = models.CharField(max_length=255, blank=True) + # Admin fields user = models.ForeignKey(User, blank=True, null=True) flag = models.BooleanField(default=False, blank=True) flag_code = models.CharField(max_length=32, blank=True) - flag_info = models.TextField(blank=True) + flag_info = models.TextField(blank=True) ipaddress = models.IPAddressField(blank=True) query = models.TextField(blank=True) response = models.TextField(blank=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) - + class Meta: db_table = "paypal_nvp" verbose_name = "PayPal NVP" - + def init(self, request, paypal_request, paypal_response): """Initialize a PayPalNVP instance from a HttpRequest.""" self.ipaddress = request.META.get('REMOTE_ADDR', '').split(':')[0] @@ -64,7 +66,7 @@ def init(self, request, paypal_request, paypal_response): self.user = request.user # No storing credit card info. - query_data = dict((k,v) for k, v in paypal_request.iteritems() if k not in self.RESTRICTED_FIELDS) + query_data = dict((k, v) for k, v in paypal_request.iteritems() if k not in self.RESTRICTED_FIELDS) self.query = urlencode(query_data) self.response = urlencode(paypal_response) @@ -86,6 +88,7 @@ def set_flag(self, info, code=None): def process(self, request, item): """Do a direct payment.""" from paypal.pro.helpers import PayPalWPP + wpp = PayPalWPP(request) # Change the model information into a dict that PayPal can understand. @@ -94,7 +97,7 @@ def process(self, request, item): params['creditcardtype'] = self.creditcardtype params['expdate'] = self.expdate params['cvv2'] = self.cvv2 - params.update(item) + params.update(item) # Create recurring payment: if 'billingperiod' in params: diff --git a/paypal/pro/templates/pro/confirm.html b/paypal/pro/templates/pro/confirm.html index 4ea1e05..9731a35 100644 --- a/paypal/pro/templates/pro/confirm.html +++ b/paypal/pro/templates/pro/confirm.html @@ -1,7 +1,7 @@ - + @@ -9,7 +9,7 @@ {{ form.as_table }} - +
diff --git a/paypal/pro/templates/pro/payment.html b/paypal/pro/templates/pro/payment.html index 434f9c9..8bc2a04 100644 --- a/paypal/pro/templates/pro/payment.html +++ b/paypal/pro/templates/pro/payment.html @@ -1,17 +1,25 @@ - +
- {% if errors %}{% endif %} - - {{ form.as_table }} - + {% if errors %} + + + + {% endif %} + + + + {{ form.as_table }} + + +
{{ errors }}
Pay by PayPal
{{ errors }}
Pay by PayPal
diff --git a/paypal/pro/tests.py b/paypal/pro/tests.py index ab32656..241a488 100644 --- a/paypal/pro/tests.py +++ b/paypal/pro/tests.py @@ -1,11 +1,9 @@ #!/usr/bin/python # -*- coding: utf-8 -*- from django.conf import settings -from django.core.handlers.wsgi import WSGIRequest from django.forms import ValidationError -from django.http import QueryDict from django.test import TestCase -from django.test.client import Client, RequestFactory +from django.test.client import RequestFactory from paypal.pro.fields import CreditCardField from paypal.pro.helpers import PayPalWPP, PayPalError @@ -18,6 +16,7 @@ class DummyPayPalWPP(PayPalWPP): pass + # """Dummy class for testing PayPalWPP.""" # responses = { # # @@@ Need some reals data here. @@ -37,14 +36,14 @@ def test_CreditCardField(self): def test_invalidCreditCards(self): self.assertEquals(CreditCardField().clean('4797-5034-2987-9309'), '4797503429879309') - + + class PayPalWPPTest(TestCase): def setUp(self): - # Avoding blasting real requests at PayPal. self.old_debug = settings.DEBUG settings.DEBUG = True - + self.item = { 'amt': '9.95', 'inv': 'inv', @@ -52,9 +51,9 @@ def setUp(self): 'next': 'http://www.example.com/next/', 'returnurl': 'http://www.example.com/pay/', 'cancelurl': 'http://www.example.com/cancel/' - } + } self.wpp = DummyPayPalWPP(REQUEST) - + def tearDown(self): settings.DEBUG = self.old_debug @@ -75,10 +74,10 @@ def test_doDirectPayment_valid(self): 'cvv2': '037', 'acct': '4797503429879309', 'creditcardtype': 'visa', - 'ipaddress': '10.0.1.199',} + 'ipaddress': '10.0.1.199', } data.update(self.item) self.assertTrue(self.wpp.doDirectPayment(data)) - + def test_doDirectPayment_invalid(self): data = { 'firstname': 'Epic', @@ -92,7 +91,7 @@ def test_doDirectPayment_invalid(self): 'cvv2': '999', 'acct': '1234567890', 'creditcardtype': 'visa', - 'ipaddress': '10.0.1.199',} + 'ipaddress': '10.0.1.199', } data.update(self.item) self.assertRaises(PayPalFailure, self.wpp.doDirectPayment, data) diff --git a/paypal/pro/views.py b/paypal/pro/views.py index e28978f..2b78c25 100644 --- a/paypal/pro/views.py +++ b/paypal/pro/views.py @@ -6,7 +6,6 @@ from django.utils.http import urlencode from paypal.pro.forms import PaymentForm, ConfirmForm -from paypal.pro.models import PayPalNVP from paypal.pro.helpers import PayPalWPP, TEST from paypal.pro.exceptions import PayPalFailure @@ -75,10 +74,10 @@ class PayPalPro(object): "form": "Please correct the errors below and try again.", "paypal": "There was a problem contacting PayPal. Please try again later." } - + def __init__(self, item=None, payment_form_cls=PaymentForm, - payment_template="pro/payment.html", confirm_form_cls=ConfirmForm, - confirm_template="pro/confirm.html", success_url="?success", + payment_template="pro/payment.html", confirm_form_cls=ConfirmForm, + confirm_template="pro/confirm.html", success_url="?success", fail_url=None, context=None, form_context_name="form"): self.item = item self.payment_form_cls = payment_form_cls @@ -99,13 +98,13 @@ def __call__(self, request): elif self.should_render_confirm_form(): return self.render_confirm_form() elif self.should_render_payment_form(): - return self.render_payment_form() + return self.render_payment_form() else: if self.should_validate_confirm_form(): return self.validate_confirm_form() elif self.should_validate_payment_form(): return self.validate_payment_form() - + # Default to the rendering the payment form. return self.render_payment_form() @@ -114,16 +113,16 @@ def is_recurring(self): def should_redirect_to_express(self): return 'express' in self.request.GET - + def should_render_confirm_form(self): return 'token' in self.request.GET and 'PayerID' in self.request.GET - + def should_render_payment_form(self): return True def should_validate_confirm_form(self): - return 'token' in self.request.POST and 'PayerID' in self.request.POST - + return 'token' in self.request.POST and 'PayerID' in self.request.POST + def should_validate_payment_form(self): return True @@ -134,7 +133,7 @@ def render_payment_form(self): def validate_payment_form(self): """Try to validate and then process the DirectPayment form.""" - form = self.payment_form_cls(self.request.POST) + form = self.payment_form_cls(self.request.POST) if form.is_valid(): success = form.process(self.request, self.item) if success: @@ -164,8 +163,8 @@ def redirect_to_express(self): self.context['errors'] = self.errors['paypal'] return self.render_payment_form() else: - pp_params = dict(token=nvp_obj.token, AMT=self.item['amt'], - RETURNURL=self.item['returnurl'], + pp_params = dict(token=nvp_obj.token, AMT=self.item['amt'], + RETURNURL=self.item['returnurl'], CANCELURL=self.item['cancelurl']) pp_url = self.get_endpoint() % urlencode(pp_params) return HttpResponseRedirect(pp_url) @@ -187,7 +186,7 @@ def validate_confirm_form(self): wpp = PayPalWPP(self.request) pp_data = dict(token=self.request.POST['token'], payerid=self.request.POST['PayerID']) self.item.update(pp_data) - + # @@@ This check and call could be moved into PayPalWPP. try: if self.is_recurring(): diff --git a/paypal/standard/conf.py b/paypal/standard/conf.py index 5c5fd45..748e3f0 100644 --- a/paypal/standard/conf.py +++ b/paypal/standard/conf.py @@ -1,11 +1,11 @@ from django.conf import settings + class PayPalSettingsError(Exception): """Raised when settings be bad.""" - -TEST = getattr(settings, "PAYPAL_TEST", True) +TEST = getattr(settings, "PAYPAL_TEST", True) RECEIVER_EMAIL = settings.PAYPAL_RECEIVER_EMAIL @@ -16,9 +16,13 @@ class PayPalSettingsError(Exception): # Images IMAGE = getattr(settings, "PAYPAL_IMAGE", "http://images.paypal.com/images/x-click-but01.gif") -SUBSCRIPTION_IMAGE = getattr(settings, "PAYPAL_SUBSCRIPTION_IMAGE", "https://www.paypal.com/en_US/i/btn/btn_subscribeCC_LG.gif") +SUBSCRIPTION_IMAGE = getattr(settings, "PAYPAL_SUBSCRIPTION_IMAGE", + "https://www.paypal.com/en_US/i/btn/btn_subscribeCC_LG.gif") DONATION_IMAGE = getattr(settings, "PAYPAL_DONATION_IMAGE", "https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif") -SANDBOX_IMAGE = getattr(settings, "PAYPAL_SANDBOX_IMAGE", "https://www.sandbox.paypal.com/en_US/i/btn/btn_buynowCC_LG.gif") -SUBSCRIPTION_SANDBOX_IMAGE = getattr(settings, "PAYPAL_SUBSCRIPTION_SANDBOX_IMAGE", "https://www.sandbox.paypal.com/en_US/i/btn/btn_subscribeCC_LG.gif") -DONATION_SANDBOX_IMAGE = getattr(settings, "PAYPAL_DONATION_SANDBOX_IMAGE", "https://www.sandbox.paypal.com/en_US/i/btn/btn_donateCC_LG.gif") +SANDBOX_IMAGE = getattr(settings, "PAYPAL_SANDBOX_IMAGE", + "https://www.sandbox.paypal.com/en_US/i/btn/btn_buynowCC_LG.gif") +SUBSCRIPTION_SANDBOX_IMAGE = getattr(settings, "PAYPAL_SUBSCRIPTION_SANDBOX_IMAGE", + "https://www.sandbox.paypal.com/en_US/i/btn/btn_subscribeCC_LG.gif") +DONATION_SANDBOX_IMAGE = getattr(settings, "PAYPAL_DONATION_SANDBOX_IMAGE", + "https://www.sandbox.paypal.com/en_US/i/btn/btn_donateCC_LG.gif") diff --git a/paypal/standard/forms.py b/paypal/standard/forms.py index e9992a5..3789aac 100644 --- a/paypal/standard/forms.py +++ b/paypal/standard/forms.py @@ -1,12 +1,11 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- from django import forms -from django.conf import settings from django.utils.safestring import mark_safe from paypal.standard.conf import * from paypal.standard.widgets import ValueHiddenInput, ReservedValueHiddenInput -from paypal.standard.conf import (POSTBACK_ENDPOINT, SANDBOX_POSTBACK_ENDPOINT, - RECEIVER_EMAIL) +from paypal.standard.conf import (POSTBACK_ENDPOINT, SANDBOX_POSTBACK_ENDPOINT, + RECEIVER_EMAIL) # 20:18:05 Jan 30, 2009 PST - PST timezone support is not included out of the box. @@ -17,6 +16,7 @@ "%H:%M:%S %b %d, %Y PST", "%H:%M:%S %b %d, %Y PDT",) + class PayPalPaymentsForm(forms.Form): """ Creates a PayPal Payments Standard "Buy It Now" button, configured for a @@ -30,20 +30,20 @@ class PayPalPaymentsForm(forms.Form): >>> f.render() u'
...' - """ + """ CMD_CHOICES = ( - ("_xclick", "Buy now or Donations"), - ("_cart", "Shopping cart"), + ("_xclick", "Buy now or Donations"), + ("_cart", "Shopping cart"), ("_xclick-subscriptions", "Subscribe") ) SHIPPING_CHOICES = ((1, "No shipping"), (0, "Shipping")) NO_NOTE_CHOICES = ((1, "No Note"), (0, "Include Note")) RECURRING_PAYMENT_CHOICES = ( - (1, "Subscription Payments Recur"), + (1, "Subscription Payments Recur"), (0, "Subscription payments do not recur") ) REATTEMPT_ON_FAIL_CHOICES = ( - (1, "reattempt billing on Failure"), + (1, "reattempt billing on Failure"), (0, "Do Not reattempt on failure") ) @@ -53,13 +53,13 @@ class PayPalPaymentsForm(forms.Form): # Where the money goes. business = forms.CharField(widget=ValueHiddenInput(), initial=RECEIVER_EMAIL) - + # Item information. amount = forms.IntegerField(widget=ValueHiddenInput()) item_name = forms.CharField(widget=ValueHiddenInput()) item_number = forms.CharField(widget=ValueHiddenInput()) quantity = forms.CharField(widget=ValueHiddenInput()) - + # Subscription Related. a1 = forms.CharField(widget=ValueHiddenInput()) # Trial 1 Price p1 = forms.CharField(widget=ValueHiddenInput()) # Trial 1 Duration @@ -72,28 +72,28 @@ class PayPalPaymentsForm(forms.Form): t3 = forms.CharField(widget=ValueHiddenInput()) # Subscription unit of Duration, default to Month src = forms.CharField(widget=ValueHiddenInput()) # Is billing recurring? default to yes sra = forms.CharField(widget=ValueHiddenInput()) # Reattempt billing on failed cc transaction - no_note = forms.CharField(widget=ValueHiddenInput()) + no_note = forms.CharField(widget=ValueHiddenInput()) # Can be either 1 or 2. 1 = modify or allow new subscription creation, 2 = modify only modify = forms.IntegerField(widget=ValueHiddenInput()) # Are we modifying an existing subscription? - + # Localization / PayPal Setup lc = forms.CharField(widget=ValueHiddenInput()) page_style = forms.CharField(widget=ValueHiddenInput()) cbt = forms.CharField(widget=ValueHiddenInput()) - + # IPN control. notify_url = forms.CharField(widget=ValueHiddenInput()) cancel_return = forms.CharField(widget=ValueHiddenInput()) - return_url = forms.CharField(widget=ReservedValueHiddenInput(attrs={"name":"return"})) + return_url = forms.CharField(widget=ReservedValueHiddenInput(attrs={"name": "return"})) custom = forms.CharField(widget=ValueHiddenInput()) invoice = forms.CharField(widget=ValueHiddenInput()) - + # Default fields. cmd = forms.ChoiceField(widget=forms.HiddenInput(), initial=CMD_CHOICES[0][0]) charset = forms.CharField(widget=forms.HiddenInput(), initial="utf-8") currency_code = forms.CharField(widget=forms.HiddenInput(), initial="USD") - no_shipping = forms.ChoiceField(widget=forms.HiddenInput(), choices=SHIPPING_CHOICES, - initial=SHIPPING_CHOICES[0][0]) + no_shipping = forms.ChoiceField(widget=forms.HiddenInput(), choices=SHIPPING_CHOICES, + initial=SHIPPING_CHOICES[0][0]) def __init__(self, button_type="buy", *args, **kwargs): super(PayPalPaymentsForm, self).__init__(*args, **kwargs) @@ -104,14 +104,14 @@ def render(self): %s
""" % (POSTBACK_ENDPOINT, self.as_p(), self.get_image())) - - + + def sandbox(self): return mark_safe(u"""
%s
""" % (SANDBOX_POSTBACK_ENDPOINT, self.as_p(), self.get_image())) - + def get_image(self): return { (True, self.SUBSCRIBE): SUBSCRIPTION_SANDBOX_IMAGE, @@ -141,6 +141,7 @@ class PayPalEncryptedPaymentsForm(PayPalPaymentsForm): http://blog.mauveweb.co.uk/2007/10/10/paypal-with-django/ """ + def _encrypt(self): """Use your key thing to encrypt things.""" from M2Crypto import BIO, SMIME, X509 @@ -164,7 +165,7 @@ def _encrypt(self): name = "return" plaintext += u'%s=%s\n' % (name, value) plaintext = plaintext.encode('utf-8') - + # Begin crypto weirdness. s = SMIME.SMIME() s.load_key_bio(BIO.openfile(CERT), BIO.openfile(PUB_CERT)) @@ -180,7 +181,7 @@ def _encrypt(self): out = BIO.MemoryBuffer() p7.write(out) return out.read() - + def as_p(self): return mark_safe(u""" @@ -196,9 +197,11 @@ class PayPalSharedSecretEncryptedPaymentsForm(PayPalEncryptedPaymentsForm): Adds a secret to the notify_url based on the contents of the form. """ + def __init__(self, *args, **kwargs): "Make the secret from the form initial data and slip it into the form." from paypal.standard.helpers import make_secret + super(PayPalSharedSecretEncryptedPaymentsForm, self).__init__(*args, **kwargs) # @@@ Attach the secret parameter in a way that is safe for other query params. secret_param = "?secret=%s" % make_secret(self) diff --git a/paypal/standard/helpers.py b/paypal/standard/helpers.py index 7b1af70..9678376 100644 --- a/paypal/standard/helpers.py +++ b/paypal/standard/helpers.py @@ -9,6 +9,7 @@ def get_sha1_hexdigest(salt, raw_password): return hashlib.sha1(smart_str(salt) + smart_str(raw_password)).hexdigest() + def duplicate_txn_id(ipn_obj): """ Returns True if a record with this transaction id exists and its @@ -20,7 +21,7 @@ def duplicate_txn_id(ipn_obj): """ # get latest similar transaction(s) - similars = ipn_obj._default_manager.filter(txn_id = ipn_obj.txn_id).order_by('-created_at')[:1] + similars = ipn_obj._default_manager.filter(txn_id=ipn_obj.txn_id).order_by('-created_at')[:1] if len(similars) > 0: # we have a similar transaction, has the payment_status changed? @@ -28,6 +29,7 @@ def duplicate_txn_id(ipn_obj): return False + def make_secret(form_instance, secret_fields=None): """ Returns a secret for use in a EWP form or an IPN verification based on a @@ -58,6 +60,7 @@ def make_secret(form_instance, secret_fields=None): secret = get_sha1_hexdigest(settings.SECRET_KEY, data) return secret + def check_secret(form_instance, secret): """ Returns true if received `secret` matches expected secret for form_instance. diff --git a/paypal/standard/ipn/admin.py b/paypal/standard/ipn/admin.py index 173c97c..bc382c0 100644 --- a/paypal/standard/ipn/admin.py +++ b/paypal/standard/ipn/admin.py @@ -10,8 +10,8 @@ class PayPalIPNAdmin(admin.ModelAdmin): (None, { "fields": [ "flag", "txn_id", "txn_type", "payment_status", "payment_date", - "transaction_entity", "reason_code", "pending_reason", - "mc_gross", "mc_fee", "auth_status", "auth_amount", "auth_exp", + "transaction_entity", "reason_code", "pending_reason", + "mc_gross", "mc_fee", "auth_status", "auth_amount", "auth_exp", "auth_id" ] }), @@ -20,7 +20,7 @@ class PayPalIPNAdmin(admin.ModelAdmin): 'classes': ('collapse',), "fields": [ "address_city", "address_country", "address_country_code", - "address_name", "address_state", "address_status", + "address_name", "address_state", "address_status", "address_street", "address_zip" ] }), @@ -36,7 +36,7 @@ class PayPalIPNAdmin(admin.ModelAdmin): "description": "The information about the Seller.", 'classes': ('collapse',), "fields": [ - "business", "item_name", "item_number", "quantity", + "business", "item_name", "item_number", "quantity", "receiver_email", "receiver_id", "custom", "invoice", "memo" ] }), @@ -44,9 +44,9 @@ class PayPalIPNAdmin(admin.ModelAdmin): "description": "Information about recurring Payments.", "classes": ("collapse",), "fields": [ - "profile_status", "initial_payment_amount", "amount_per_cycle", - "outstanding_balance", "period_type", "product_name", - "product_type", "recurring_payment_id", "receipt_id", + "profile_status", "initial_payment_amount", "amount_per_cycle", + "outstanding_balance", "period_type", "product_name", + "product_type", "recurring_payment_id", "receipt_id", "next_payment_date" ] }), @@ -54,13 +54,13 @@ class PayPalIPNAdmin(admin.ModelAdmin): "description": "Additional Info.", "classes": ('collapse',), "fields": [ - "test_ipn", "ipaddress", "query", "response", "flag_code", + "test_ipn", "ipaddress", "query", "response", "flag_code", "flag_info" ] }), ) list_display = [ - "__unicode__", "flag", "flag_info", "invoice", "custom", + "__unicode__", "flag", "flag_info", "invoice", "custom", "payment_status", "created_at" ] search_fields = ["txn_id", "recurring_payment_id"] diff --git a/paypal/standard/ipn/forms.py b/paypal/standard/ipn/forms.py index 9da1aad..f30a22a 100644 --- a/paypal/standard/ipn/forms.py +++ b/paypal/standard/ipn/forms.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -from paypal.standard.forms import PayPalStandardBaseForm +from paypal.standard.forms import PayPalStandardBaseForm from paypal.standard.ipn.models import PayPalIPN @@ -11,6 +11,7 @@ class PayPalIPNForm(PayPalStandardBaseForm): PayPal IPN test tool: https://developer.paypal.com/us/cgi-bin/devscr?cmd=_tools-session """ + class Meta: model = PayPalIPN exclude = [] diff --git a/paypal/standard/ipn/migrations/0001_first_migration.py b/paypal/standard/ipn/migrations/0001_first_migration.py index 54da912..8a90716 100644 --- a/paypal/standard/ipn/migrations/0001_first_migration.py +++ b/paypal/standard/ipn/migrations/0001_first_migration.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- from django.db import models from south.db import db -from paypal.standard.ipn.models import * -class Migration: + +class Migration: def forwards(self, orm): # Adding model 'PayPalIPN' db.create_table('paypal_ipn', ( @@ -60,7 +60,8 @@ def forwards(self, orm): ('protection_eligibility', models.CharField(max_length=32, blank=True)), ('quantity', models.IntegerField(default=1, null=True, blank=True)), ('reason_code', models.CharField(max_length=15, blank=True)), - ('remaining_settle', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), + ( + 'remaining_settle', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), ('settle_amount', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), ('settle_currency', models.CharField(max_length=32, blank=True)), ('shipping', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), @@ -72,10 +73,13 @@ def forwards(self, orm): ('auction_multi_item', models.IntegerField(default=0, null=True, blank=True)), ('for_auction', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), ('amount', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), - ('amount_per_cycle', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), - ('initial_payment_amount', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), + ( + 'amount_per_cycle', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), + ('initial_payment_amount', + models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), ('next_payment_date', models.DateTimeField(null=True, blank=True)), - ('outstanding_balance', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), + ('outstanding_balance', + models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), ('payment_cycle', models.CharField(max_length=32, blank=True)), ('period_type', models.CharField(max_length=32, blank=True)), ('product_name', models.CharField(max_length=128, blank=True)), @@ -121,8 +125,8 @@ def forwards(self, orm): )) db.send_create_signal('ipn', ['PayPalIPN']) - def backwards(self, orm): - # Deleting model 'PayPalIPN' + def backwards(self, orm): + # Deleting model 'PayPalIPN' db.delete_table('paypal_ipn') models = { @@ -136,15 +140,23 @@ def backwards(self, orm): 'address_status': ('models.CharField', [], {'max_length': '11', 'blank': 'True'}), 'address_street': ('models.CharField', [], {'max_length': '200', 'blank': 'True'}), 'address_zip': ('models.CharField', [], {'max_length': '20', 'blank': 'True'}), - 'amount': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amount1': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amount2': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amount3': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amount_per_cycle': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount1': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount2': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount3': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount_per_cycle': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'auction_buyer_id': ('models.CharField', [], {'max_length': '64', 'blank': 'True'}), 'auction_closing_date': ('models.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'auction_multi_item': ('models.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), - 'auth_amount': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'auth_amount': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'auth_exp': ('models.CharField', [], {'max_length': '28', 'blank': 'True'}), 'auth_id': ('models.CharField', [], {'max_length': '19', 'blank': 'True'}), 'auth_status': ('models.CharField', [], {'max_length': '9', 'blank': 'True'}), @@ -157,36 +169,60 @@ def backwards(self, orm): 'created_at': ('models.DateTimeField', [], {'auto_now_add': 'True'}), 'currency_code': ('models.CharField', [], {'default': "'USD'", 'max_length': '32', 'blank': 'True'}), 'custom': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'exchange_rate': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '16', 'blank': 'True'}), + 'exchange_rate': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '16', + 'blank': 'True'}), 'first_name': ('models.CharField', [], {'max_length': '64', 'blank': 'True'}), 'flag': ('models.BooleanField', [], {'default': 'False', 'blank': 'True'}), 'flag_code': ('models.CharField', [], {'max_length': '16', 'blank': 'True'}), 'flag_info': ('models.TextField', [], {'blank': 'True'}), - 'for_auction': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'for_auction': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'from_view': ('models.CharField', [], {'max_length': '6', 'null': 'True', 'blank': 'True'}), - 'handling_amount': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'handling_amount': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'id': ('models.AutoField', [], {'primary_key': 'True'}), - 'initial_payment_amount': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'initial_payment_amount': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'invoice': ('models.CharField', [], {'max_length': '127', 'blank': 'True'}), 'ipaddress': ('models.IPAddressField', [], {'blank': 'True'}), 'item_name': ('models.CharField', [], {'max_length': '127', 'blank': 'True'}), 'item_number': ('models.CharField', [], {'max_length': '127', 'blank': 'True'}), 'last_name': ('models.CharField', [], {'max_length': '64', 'blank': 'True'}), - 'mc_amount1': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_amount2': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_amount3': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'mc_amount1': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'mc_amount2': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'mc_amount3': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'mc_currency': ('models.CharField', [], {'default': "'USD'", 'max_length': '32', 'blank': 'True'}), - 'mc_fee': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_gross': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_handling': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_shipping': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'mc_fee': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'mc_gross': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'mc_handling': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'mc_shipping': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'memo': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}), 'next_payment_date': ('models.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'notify_version': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'notify_version': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'num_cart_items': ('models.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), 'option_name1': ('models.CharField', [], {'max_length': '64', 'blank': 'True'}), 'option_name2': ('models.CharField', [], {'max_length': '64', 'blank': 'True'}), - 'outstanding_balance': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'outstanding_balance': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'parent_txn_id': ('models.CharField', ['"Parent Transaction ID"'], {'max_length': '19', 'blank': 'True'}), 'password': ('models.CharField', [], {'max_length': '24', 'blank': 'True'}), 'payer_business_name': ('models.CharField', [], {'max_length': '127', 'blank': 'True'}), @@ -195,7 +231,9 @@ def backwards(self, orm): 'payer_status': ('models.CharField', [], {'max_length': '10', 'blank': 'True'}), 'payment_cycle': ('models.CharField', [], {'max_length': '32', 'blank': 'True'}), 'payment_date': ('models.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'payment_gross': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'payment_gross': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'payment_status': ('models.CharField', [], {'max_length': '9', 'blank': 'True'}), 'payment_type': ('models.CharField', [], {'max_length': '7', 'blank': 'True'}), 'pending_reason': ('models.CharField', [], {'max_length': '14', 'blank': 'True'}), @@ -217,19 +255,25 @@ def backwards(self, orm): 'recur_times': ('models.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), 'recurring': ('models.CharField', [], {'max_length': '1', 'blank': 'True'}), 'recurring_payment_id': ('models.CharField', [], {'max_length': '128', 'blank': 'True'}), - 'remaining_settle': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'remaining_settle': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'residence_country': ('models.CharField', [], {'max_length': '2', 'blank': 'True'}), 'response': ('models.TextField', [], {'blank': 'True'}), 'retry_at': ('models.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'rp_invoice_id': ('models.CharField', [], {'max_length': '127', 'blank': 'True'}), - 'settle_amount': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'settle_amount': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'settle_currency': ('models.CharField', [], {'max_length': '32', 'blank': 'True'}), - 'shipping': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'shipping': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), 'shipping_method': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}), 'subscr_date': ('models.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'subscr_effective': ('models.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'subscr_id': ('models.CharField', [], {'max_length': '19', 'blank': 'True'}), - 'tax': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'tax': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), 'test_ipn': ('models.BooleanField', [], {'default': 'False', 'blank': 'True'}), 'time_created': ('models.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'transaction_entity': ('models.CharField', [], {'max_length': '7', 'blank': 'True'}), diff --git a/paypal/standard/ipn/migrations/0002_auto__chg_field_paypalipn_txn_id__chg_field_paypalipn_payment_status__.py b/paypal/standard/ipn/migrations/0002_auto__chg_field_paypalipn_txn_id__chg_field_paypalipn_payment_status__.py index 8dfe677..b73905a 100644 --- a/paypal/standard/ipn/migrations/0002_auto__chg_field_paypalipn_txn_id__chg_field_paypalipn_payment_status__.py +++ b/paypal/standard/ipn/migrations/0002_auto__chg_field_paypalipn_txn_id__chg_field_paypalipn_payment_status__.py @@ -1,14 +1,10 @@ # -*- coding: utf-8 -*- -import datetime from south.db import db from south.v2 import SchemaMigration -from django.db import models class Migration(SchemaMigration): - def forwards(self, orm): - # Changing field 'PayPalIPN.txn_id' db.alter_column('paypal_ipn', 'txn_id', self.gf('django.db.models.fields.CharField')(max_length=19)) # Adding index on 'PayPalIPN', fields ['txn_id'] @@ -42,7 +38,8 @@ def backwards(self, orm): db.alter_column('paypal_ipn', 'txn_type', self.gf('models.CharField')("Transaction Type", max_length=128)) # Changing field 'PayPalIPN.parent_txn_id' - db.alter_column('paypal_ipn', 'parent_txn_id', self.gf('models.CharField')("Parent Transaction ID", max_length=19)) + db.alter_column('paypal_ipn', 'parent_txn_id', + self.gf('models.CharField')("Parent Transaction ID", max_length=19)) # Changing field 'PayPalIPN.ipaddress' db.alter_column('paypal_ipn', 'ipaddress', self.gf('models.IPAddressField')()) @@ -58,15 +55,24 @@ def backwards(self, orm): 'address_status': ('django.db.models.fields.CharField', [], {'max_length': '11', 'blank': 'True'}), 'address_street': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), 'address_zip': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}), - 'amount': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amount1': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amount2': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amount3': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amount_per_cycle': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount1': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount2': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount3': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount_per_cycle': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'auction_buyer_id': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), 'auction_closing_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'auction_multi_item': ('django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), - 'auth_amount': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'auction_multi_item': ( + 'django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), + 'auth_amount': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'auth_exp': ('django.db.models.fields.CharField', [], {'max_length': '28', 'blank': 'True'}), 'auth_id': ('django.db.models.fields.CharField', [], {'max_length': '19', 'blank': 'True'}), 'auth_status': ('django.db.models.fields.CharField', [], {'max_length': '9', 'blank': 'True'}), @@ -77,38 +83,66 @@ def backwards(self, orm): 'charset': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), 'contact_phone': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}), 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'currency_code': ('django.db.models.fields.CharField', [], {'default': "'USD'", 'max_length': '32', 'blank': 'True'}), + 'currency_code': ( + 'django.db.models.fields.CharField', [], {'default': "'USD'", 'max_length': '32', 'blank': 'True'}), 'custom': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'exchange_rate': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '16', 'blank': 'True'}), + 'exchange_rate': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '16', + 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), 'flag': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'flag_code': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), 'flag_info': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'for_auction': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'from_view': ('django.db.models.fields.CharField', [], {'max_length': '6', 'null': 'True', 'blank': 'True'}), - 'handling_amount': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'for_auction': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'from_view': ( + 'django.db.models.fields.CharField', [], {'max_length': '6', 'null': 'True', 'blank': 'True'}), + 'handling_amount': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'initial_payment_amount': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'initial_payment_amount': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'invoice': ('django.db.models.fields.CharField', [], {'max_length': '127', 'blank': 'True'}), 'ipaddress': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'blank': 'True'}), 'item_name': ('django.db.models.fields.CharField', [], {'max_length': '127', 'blank': 'True'}), 'item_number': ('django.db.models.fields.CharField', [], {'max_length': '127', 'blank': 'True'}), 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), - 'mc_amount1': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_amount2': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_amount3': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_currency': ('django.db.models.fields.CharField', [], {'default': "'USD'", 'max_length': '32', 'blank': 'True'}), - 'mc_fee': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_gross': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_handling': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_shipping': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'mc_amount1': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'mc_amount2': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'mc_amount3': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'mc_currency': ( + 'django.db.models.fields.CharField', [], {'default': "'USD'", 'max_length': '32', 'blank': 'True'}), + 'mc_fee': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'mc_gross': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'mc_handling': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'mc_shipping': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'memo': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'next_payment_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'notify_version': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'num_cart_items': ('django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), + 'notify_version': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'num_cart_items': ( + 'django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), 'option_name1': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), 'option_name2': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), - 'outstanding_balance': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'outstanding_balance': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'parent_txn_id': ('django.db.models.fields.CharField', [], {'max_length': '19', 'blank': 'True'}), 'password': ('django.db.models.fields.CharField', [], {'max_length': '24', 'blank': 'True'}), 'payer_business_name': ('django.db.models.fields.CharField', [], {'max_length': '127', 'blank': 'True'}), @@ -117,7 +151,9 @@ def backwards(self, orm): 'payer_status': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'}), 'payment_cycle': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), 'payment_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'payment_gross': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'payment_gross': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'payment_status': ('django.db.models.fields.CharField', [], {'max_length': '17', 'blank': 'True'}), 'payment_type': ('django.db.models.fields.CharField', [], {'max_length': '7', 'blank': 'True'}), 'pending_reason': ('django.db.models.fields.CharField', [], {'max_length': '14', 'blank': 'True'}), @@ -136,27 +172,35 @@ def backwards(self, orm): 'receipt_id': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), 'receiver_email': ('django.db.models.fields.EmailField', [], {'max_length': '127', 'blank': 'True'}), 'receiver_id': ('django.db.models.fields.CharField', [], {'max_length': '127', 'blank': 'True'}), - 'recur_times': ('django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), + 'recur_times': ( + 'django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), 'recurring': ('django.db.models.fields.CharField', [], {'max_length': '1', 'blank': 'True'}), 'recurring_payment_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}), - 'remaining_settle': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'remaining_settle': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'residence_country': ('django.db.models.fields.CharField', [], {'max_length': '2', 'blank': 'True'}), 'response': ('django.db.models.fields.TextField', [], {'blank': 'True'}), 'retry_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'rp_invoice_id': ('django.db.models.fields.CharField', [], {'max_length': '127', 'blank': 'True'}), - 'settle_amount': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'settle_amount': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'settle_currency': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), - 'shipping': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'shipping': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), 'shipping_method': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'subscr_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'subscr_effective': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'subscr_id': ('django.db.models.fields.CharField', [], {'max_length': '19', 'blank': 'True'}), - 'tax': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'tax': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), 'test_ipn': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'time_created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'transaction_entity': ('django.db.models.fields.CharField', [], {'max_length': '7', 'blank': 'True'}), 'transaction_subject': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'txn_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '19', 'blank': 'True'}), + 'txn_id': ( + 'django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '19', 'blank': 'True'}), 'txn_type': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}), 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), 'username': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), diff --git a/paypal/standard/ipn/templates/ipn/ipn.html b/paypal/standard/ipn/templates/ipn/ipn.html index cd07c1e..ac74394 100644 --- a/paypal/standard/ipn/templates/ipn/ipn.html +++ b/paypal/standard/ipn/templates/ipn/ipn.html @@ -1,7 +1,7 @@ - + @@ -10,7 +10,7 @@ {{ form.as_p }} - + diff --git a/paypal/standard/ipn/templates/ipn/ipn_test.html b/paypal/standard/ipn/templates/ipn/ipn_test.html index 6d90062..0705ae9 100644 --- a/paypal/standard/ipn/templates/ipn/ipn_test.html +++ b/paypal/standard/ipn/templates/ipn/ipn_test.html @@ -1,43 +1,43 @@ - +
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/paypal/standard/ipn/templates/ipn/paypal.html b/paypal/standard/ipn/templates/ipn/paypal.html index 695b241..73a53d9 100644 --- a/paypal/standard/ipn/templates/ipn/paypal.html +++ b/paypal/standard/ipn/templates/ipn/paypal.html @@ -1,7 +1,7 @@ - + diff --git a/paypal/standard/ipn/tests/test_ipn.py b/paypal/standard/ipn/tests/test_ipn.py index 7fbca66..1c196b6 100644 --- a/paypal/standard/ipn/tests/test_ipn.py +++ b/paypal/standard/ipn/tests/test_ipn.py @@ -1,16 +1,14 @@ import urllib from django.conf import settings -from django.http import HttpResponse from django.test import TestCase -from django.test.client import Client from paypal.standard.models import ST_PP_CANCELLED from paypal.standard.ipn.models import PayPalIPN from paypal.standard.ipn.signals import (payment_was_successful, - payment_was_flagged, payment_was_refunded, payment_was_reversed, - recurring_skipped, recurring_failed, - recurring_create, recurring_payment, recurring_cancel) + payment_was_flagged, payment_was_refunded, payment_was_reversed, + recurring_skipped, recurring_failed, + recurring_create, recurring_payment, recurring_cancel) # Parameters are all bytestrings, so we can construct a bytestring @@ -88,7 +86,7 @@ def tearDown(self): settings.DEBUG = self.old_debug PayPalIPN._postback = self.old_postback - payment_was_successful.receivers =self.payment_was_successful_receivers + payment_was_successful.receivers = self.payment_was_successful_receivers payment_was_flagged.receivers = self.payment_was_flagged_receivers payment_was_refunded.receivers = self.payment_was_refunded_receivers payment_was_reversed.receivers = self.payment_was_reversed_receivers @@ -115,6 +113,7 @@ def assertGotSignal(self, signal, flagged, params=IPN_POST_PARAMS): def handle_signal(sender, **kwargs): self.got_signal = True self.signal_obj = sender + signal.connect(handle_signal) response = self.paypal_post(params) self.assertEqual(response.status_code, 200) @@ -255,6 +254,7 @@ def test_recurring_payment_ipn(self): def handle_signal(sender, **kwargs): self.got_signal = True self.signal_obj = sender + recurring_payment.connect(handle_signal) response = self.paypal_post(params) self.assertEqual(response.status_code, 200) diff --git a/paypal/standard/ipn/tests/test_urls.py b/paypal/standard/ipn/tests/test_urls.py index 9c4f005..0ab29d9 100644 --- a/paypal/standard/ipn/tests/test_urls.py +++ b/paypal/standard/ipn/tests/test_urls.py @@ -1,5 +1,5 @@ from django.conf.urls import patterns urlpatterns = patterns('paypal.standard.ipn.views', - (r'^ipn/$', 'ipn'), + (r'^ipn/$', 'ipn'), ) diff --git a/paypal/standard/ipn/urls.py b/paypal/standard/ipn/urls.py index ba2d4bb..16bd59a 100644 --- a/paypal/standard/ipn/urls.py +++ b/paypal/standard/ipn/urls.py @@ -1,5 +1,5 @@ from django.conf.urls import patterns, url urlpatterns = patterns('paypal.standard.ipn.views', - url(r'^$', 'ipn', name="paypal-ipn"), + url(r'^$', 'ipn', name="paypal-ipn"), ) diff --git a/paypal/standard/ipn/views.py b/paypal/standard/ipn/views.py index 7772067..9327c09 100644 --- a/paypal/standard/ipn/views.py +++ b/paypal/standard/ipn/views.py @@ -5,8 +5,8 @@ from django.views.decorators.csrf import csrf_exempt from paypal.standard.ipn.forms import PayPalIPNForm from paypal.standard.ipn.models import PayPalIPN - - + + @require_POST @csrf_exempt def ipn(request, item_check_callable=None): @@ -22,7 +22,7 @@ def ipn(request, item_check_callable=None): # of if checks just to determine if flag is set. flag = None ipn_obj = None - + # Clean up the data as PayPal sends some weird values such as "N/A" # Also, need to cope with custom encoding, which is stored in the body (!). # Assuming the tolerate parsing of QueryDict and an ASCII-like encoding, @@ -51,7 +51,7 @@ def ipn(request, item_check_callable=None): if form.is_valid(): try: #When commit = False, object is returned without saving to DB. - ipn_obj = form.save(commit = False) + ipn_obj = form.save(commit=False) except Exception, e: flag = "Exception while processing. (%s)" % e else: @@ -59,7 +59,7 @@ def ipn(request, item_check_callable=None): if ipn_obj is None: ipn_obj = PayPalIPN() - + #Set query params and sender's IP address ipn_obj.initialize(request) diff --git a/paypal/standard/models.py b/paypal/standard/models.py index 71ca700..03a488d 100644 --- a/paypal/standard/models.py +++ b/paypal/standard/models.py @@ -1,7 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- from django.db import models -from django.conf import settings from paypal.standard.helpers import duplicate_txn_id, check_secret from paypal.standard.conf import RECEIVER_EMAIL, POSTBACK_ENDPOINT, SANDBOX_POSTBACK_ENDPOINT @@ -30,6 +29,7 @@ except ImportError: Model = models.Model + class PayPalStandardBase(Model): """Meta class for common variables shared by IPN and PDT: http://tinyurl.com/cuq6sj""" # @@@ Might want to add all these one distant day. @@ -39,9 +39,9 @@ class PayPalStandardBase(Model): ST_PP_CLEARED, ST_PP_COMPLETED, ST_PP_CREATED, ST_PP_DENIED, ST_PP_EXPIRED, ST_PP_FAILED, ST_PP_PAID, - ST_PP_PENDING, ST_PP_PROCESSED, ST_PP_REFUNDED, + ST_PP_PENDING, ST_PP_PROCESSED, ST_PP_REFUNDED, ST_PP_REFUSED, ST_PP_REVERSED, ST_PP_REWARDED, - ST_PP_UNCLAIMED, ST_PP_UNCLEARED,ST_PP_VOIDED,) + ST_PP_UNCLAIMED, ST_PP_UNCLEARED, ST_PP_VOIDED,) # AUTH_STATUS_CHOICES = "Completed Pending Voided".split() # ADDRESS_STATUS_CHOICES = "confirmed unconfirmed".split() # PAYER_STATUS_CHOICES = "verified / unverified".split() @@ -52,7 +52,7 @@ class PayPalStandardBase(Model): # Transaction and Notification-Related Variables business = models.CharField(max_length=127, blank=True, help_text="Email where the money was sent.") - charset=models.CharField(max_length=32, blank=True) + charset = models.CharField(max_length=32, blank=True) custom = models.CharField(max_length=255, blank=True) notify_version = models.DecimalField(max_digits=64, decimal_places=2, default=0, blank=True, null=True) parent_txn_id = models.CharField("Parent Transaction ID", max_length=19, blank=True) @@ -60,7 +60,8 @@ class PayPalStandardBase(Model): receiver_id = models.CharField(max_length=127, blank=True) # 258DLEHY2BDK6 residence_country = models.CharField(max_length=2, blank=True) test_ipn = models.BooleanField(default=False, blank=True) - txn_id = models.CharField("Transaction ID", max_length=19, blank=True, help_text="PayPal transaction ID.", db_index=True) + txn_id = models.CharField("Transaction ID", max_length=19, blank=True, help_text="PayPal transaction ID.", + db_index=True) txn_type = models.CharField("Transaction Type", max_length=128, blank=True, help_text="PayPal transaction type.") verify_sign = models.CharField(max_length=255, blank=True) @@ -104,7 +105,7 @@ class PayPalStandardBase(Model): payment_status = models.CharField(max_length=17, blank=True) payment_type = models.CharField(max_length=7, blank=True) pending_reason = models.CharField(max_length=14, blank=True) - protection_eligibility=models.CharField(max_length=32, blank=True) + protection_eligibility = models.CharField(max_length=32, blank=True) quantity = models.IntegerField(blank=True, default=1, null=True) reason_code = models.CharField(max_length=15, blank=True) remaining_settle = models.DecimalField(max_digits=64, decimal_places=2, default=0, blank=True, null=True) @@ -127,13 +128,13 @@ class PayPalStandardBase(Model): initial_payment_amount = models.DecimalField(max_digits=64, decimal_places=2, default=0, blank=True, null=True) next_payment_date = models.DateTimeField(blank=True, null=True, help_text="HH:MM:SS DD Mmm YY, YYYY PST") outstanding_balance = models.DecimalField(max_digits=64, decimal_places=2, default=0, blank=True, null=True) - payment_cycle= models.CharField(max_length=32, blank=True) #Monthly + payment_cycle = models.CharField(max_length=32, blank=True) #Monthly period_type = models.CharField(max_length=32, blank=True) product_name = models.CharField(max_length=128, blank=True) - product_type= models.CharField(max_length=128, blank=True) + product_type = models.CharField(max_length=128, blank=True) profile_status = models.CharField(max_length=32, blank=True) recurring_payment_id = models.CharField(max_length=128, blank=True) # I-FA4XVST722B9 - rp_invoice_id= models.CharField(max_length=127, blank=True) # 1335-7816-2936-1451 + rp_invoice_id = models.CharField(max_length=127, blank=True) # 1335-7816-2936-1451 time_created = models.DateTimeField(blank=True, null=True, help_text="HH:MM:SS DD Mmm YY, YYYY PST") # Subscription Variables @@ -162,7 +163,7 @@ class PayPalStandardBase(Model): case_type = models.CharField(max_length=24, blank=True) # Variables not categorized - receipt_id= models.CharField(max_length=64, blank=True) # 1335-7816-2936-1451 + receipt_id = models.CharField(max_length=64, blank=True) # 1335-7816-2936-1451 currency_code = models.CharField(max_length=32, default="USD", blank=True) handling_amount = models.DecimalField(max_digits=64, decimal_places=2, default=0, blank=True, null=True) transaction_subject = models.CharField(max_length=255, blank=True) diff --git a/paypal/standard/pdt/admin.py b/paypal/standard/pdt/admin.py index d7f16cb..4c452b3 100644 --- a/paypal/standard/pdt/admin.py +++ b/paypal/standard/pdt/admin.py @@ -10,17 +10,20 @@ class PayPalPDTAdmin(admin.ModelAdmin): date_hierarchy = 'payment_date' fieldsets = ( (None, { - "fields": L("flag txn_id txn_type payment_status payment_date transaction_entity reason_code pending_reason mc_gross mc_fee auth_status auth_amount auth_exp auth_id") + "fields": L( + "flag txn_id txn_type payment_status payment_date transaction_entity reason_code pending_reason mc_gross mc_fee auth_status auth_amount auth_exp auth_id") }), ("Address", { "description": "The address of the Buyer.", 'classes': ('collapse',), - "fields": L("address_city address_country address_country_code address_name address_state address_status address_street address_zip") + "fields": L( + "address_city address_country address_country_code address_name address_state address_status address_street address_zip") }), ("Buyer", { "description": "The information about the Buyer.", 'classes': ('collapse',), - "fields": L("first_name last_name payer_business_name payer_email payer_id payer_status contact_phone residence_country") + "fields": L( + "first_name last_name payer_business_name payer_email payer_id payer_status contact_phone residence_country") }), ("Seller", { "description": "The information about the Seller.", @@ -35,7 +38,8 @@ class PayPalPDTAdmin(admin.ModelAdmin): ("Recurring", { "description": "Information about recurring Payments.", "classes": ("collapse",), - "fields": L("profile_status initial_payment_amount amount_per_cycle outstanding_balance period_type product_name product_type recurring_payment_id receipt_id next_payment_date") + "fields": L( + "profile_status initial_payment_amount amount_per_cycle outstanding_balance period_type product_name product_type recurring_payment_id receipt_id next_payment_date") }), ("Admin", { "description": "Additional Info.", @@ -45,4 +49,6 @@ class PayPalPDTAdmin(admin.ModelAdmin): ) list_display = L("__unicode__ flag invoice custom payment_status created_at") search_fields = L("txn_id recurring_payment_id") + + admin.site.register(PayPalPDT, PayPalPDTAdmin) \ No newline at end of file diff --git a/paypal/standard/pdt/migrations/0001_first_migration.py b/paypal/standard/pdt/migrations/0001_first_migration.py index ab7b921..3f7d92b 100644 --- a/paypal/standard/pdt/migrations/0001_first_migration.py +++ b/paypal/standard/pdt/migrations/0001_first_migration.py @@ -4,10 +4,9 @@ from django.db import models from paypal.standard.pdt.models import * + class Migration: - def forwards(self, orm): - # Adding model 'PayPalPDT' db.create_table('paypal_pdt', ( ('id', models.AutoField(primary_key=True)), @@ -63,7 +62,8 @@ def forwards(self, orm): ('protection_eligibility', models.CharField(max_length=32, blank=True)), ('quantity', models.IntegerField(default=1, null=True, blank=True)), ('reason_code', models.CharField(max_length=15, blank=True)), - ('remaining_settle', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), + ( + 'remaining_settle', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), ('settle_amount', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), ('settle_currency', models.CharField(max_length=32, blank=True)), ('shipping', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), @@ -75,10 +75,13 @@ def forwards(self, orm): ('auction_multi_item', models.IntegerField(default=0, null=True, blank=True)), ('for_auction', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), ('amount', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), - ('amount_per_cycle', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), - ('initial_payment_amount', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), + ( + 'amount_per_cycle', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), + ('initial_payment_amount', + models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), ('next_payment_date', models.DateTimeField(null=True, blank=True)), - ('outstanding_balance', models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), + ('outstanding_balance', + models.DecimalField(default=0, null=True, max_digits=64, decimal_places=2, blank=True)), ('payment_cycle', models.CharField(max_length=32, blank=True)), ('period_type', models.CharField(max_length=32, blank=True)), ('product_name', models.CharField(max_length=128, blank=True)), @@ -128,16 +131,13 @@ def forwards(self, orm): ('st', models.CharField(max_length=32, blank=True)), )) db.send_create_signal('pdt', ['PayPalPDT']) - - - + + def backwards(self, orm): - # Deleting model 'PayPalPDT' db.delete_table('paypal_pdt') - - - + + models = { 'pdt.paypalpdt': { 'Meta': {'db_table': '"paypal_pdt"'}, @@ -149,16 +149,25 @@ def backwards(self, orm): 'address_status': ('models.CharField', [], {'max_length': '11', 'blank': 'True'}), 'address_street': ('models.CharField', [], {'max_length': '200', 'blank': 'True'}), 'address_zip': ('models.CharField', [], {'max_length': '20', 'blank': 'True'}), - 'amount': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amount1': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amount2': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amount3': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amount_per_cycle': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amt': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount1': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount2': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount3': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount_per_cycle': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'amt': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), 'auction_buyer_id': ('models.CharField', [], {'max_length': '64', 'blank': 'True'}), 'auction_closing_date': ('models.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'auction_multi_item': ('models.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), - 'auth_amount': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'auth_amount': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'auth_exp': ('models.CharField', [], {'max_length': '28', 'blank': 'True'}), 'auth_id': ('models.CharField', [], {'max_length': '19', 'blank': 'True'}), 'auth_status': ('models.CharField', [], {'max_length': '9', 'blank': 'True'}), @@ -172,36 +181,60 @@ def backwards(self, orm): 'created_at': ('models.DateTimeField', [], {'auto_now_add': 'True'}), 'currency_code': ('models.CharField', [], {'default': "'USD'", 'max_length': '32', 'blank': 'True'}), 'custom': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'exchange_rate': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '16', 'blank': 'True'}), + 'exchange_rate': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '16', + 'blank': 'True'}), 'first_name': ('models.CharField', [], {'max_length': '64', 'blank': 'True'}), 'flag': ('models.BooleanField', [], {'default': 'False', 'blank': 'True'}), 'flag_code': ('models.CharField', [], {'max_length': '16', 'blank': 'True'}), 'flag_info': ('models.TextField', [], {'blank': 'True'}), - 'for_auction': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'for_auction': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'from_view': ('models.CharField', [], {'max_length': '6', 'null': 'True', 'blank': 'True'}), - 'handling_amount': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'handling_amount': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'id': ('models.AutoField', [], {'primary_key': 'True'}), - 'initial_payment_amount': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'initial_payment_amount': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'invoice': ('models.CharField', [], {'max_length': '127', 'blank': 'True'}), 'ipaddress': ('models.IPAddressField', [], {'blank': 'True'}), 'item_name': ('models.CharField', [], {'max_length': '127', 'blank': 'True'}), 'item_number': ('models.CharField', [], {'max_length': '127', 'blank': 'True'}), 'last_name': ('models.CharField', [], {'max_length': '64', 'blank': 'True'}), - 'mc_amount1': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_amount2': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_amount3': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'mc_amount1': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'mc_amount2': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'mc_amount3': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'mc_currency': ('models.CharField', [], {'default': "'USD'", 'max_length': '32', 'blank': 'True'}), - 'mc_fee': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_gross': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_handling': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_shipping': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'mc_fee': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'mc_gross': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'mc_handling': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'mc_shipping': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'memo': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}), 'next_payment_date': ('models.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'notify_version': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'notify_version': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'num_cart_items': ('models.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), 'option_name1': ('models.CharField', [], {'max_length': '64', 'blank': 'True'}), 'option_name2': ('models.CharField', [], {'max_length': '64', 'blank': 'True'}), - 'outstanding_balance': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'outstanding_balance': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'parent_txn_id': ('models.CharField', ['"Parent Transaction ID"'], {'max_length': '19', 'blank': 'True'}), 'password': ('models.CharField', [], {'max_length': '24', 'blank': 'True'}), 'payer_business_name': ('models.CharField', [], {'max_length': '127', 'blank': 'True'}), @@ -210,7 +243,9 @@ def backwards(self, orm): 'payer_status': ('models.CharField', [], {'max_length': '10', 'blank': 'True'}), 'payment_cycle': ('models.CharField', [], {'max_length': '32', 'blank': 'True'}), 'payment_date': ('models.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'payment_gross': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'payment_gross': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'payment_status': ('models.CharField', [], {'max_length': '9', 'blank': 'True'}), 'payment_type': ('models.CharField', [], {'max_length': '7', 'blank': 'True'}), 'pending_reason': ('models.CharField', [], {'max_length': '14', 'blank': 'True'}), @@ -232,21 +267,27 @@ def backwards(self, orm): 'recur_times': ('models.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), 'recurring': ('models.CharField', [], {'max_length': '1', 'blank': 'True'}), 'recurring_payment_id': ('models.CharField', [], {'max_length': '128', 'blank': 'True'}), - 'remaining_settle': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'remaining_settle': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'residence_country': ('models.CharField', [], {'max_length': '2', 'blank': 'True'}), 'response': ('models.TextField', [], {'blank': 'True'}), 'retry_at': ('models.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'rp_invoice_id': ('models.CharField', [], {'max_length': '127', 'blank': 'True'}), - 'settle_amount': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'settle_amount': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'settle_currency': ('models.CharField', [], {'max_length': '32', 'blank': 'True'}), - 'shipping': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'shipping': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), 'shipping_method': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}), 'sig': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}), 'st': ('models.CharField', [], {'max_length': '32', 'blank': 'True'}), 'subscr_date': ('models.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'subscr_effective': ('models.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'subscr_id': ('models.CharField', [], {'max_length': '19', 'blank': 'True'}), - 'tax': ('models.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'tax': ('models.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), 'test_ipn': ('models.BooleanField', [], {'default': 'False', 'blank': 'True'}), 'time_created': ('models.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'transaction_entity': ('models.CharField', [], {'max_length': '7', 'blank': 'True'}), @@ -259,5 +300,5 @@ def backwards(self, orm): 'verify_sign': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}) } } - + complete_apps = ['pdt'] diff --git a/paypal/standard/pdt/migrations/0002_auto__chg_field_paypalpdt_txn_id__chg_field_paypalpdt_payment_status__.py b/paypal/standard/pdt/migrations/0002_auto__chg_field_paypalpdt_txn_id__chg_field_paypalpdt_payment_status__.py index f8eaa71..5bf6714 100644 --- a/paypal/standard/pdt/migrations/0002_auto__chg_field_paypalpdt_txn_id__chg_field_paypalpdt_payment_status__.py +++ b/paypal/standard/pdt/migrations/0002_auto__chg_field_paypalpdt_txn_id__chg_field_paypalpdt_payment_status__.py @@ -6,9 +6,7 @@ class Migration(SchemaMigration): - def forwards(self, orm): - # Changing field 'PayPalPDT.txn_id' db.alter_column('paypal_pdt', 'txn_id', self.gf('django.db.models.fields.CharField')(max_length=19)) # Adding index on 'PayPalPDT', fields ['txn_id'] @@ -42,7 +40,8 @@ def backwards(self, orm): db.alter_column('paypal_pdt', 'txn_type', self.gf('models.CharField')("Transaction Type", max_length=128)) # Changing field 'PayPalPDT.parent_txn_id' - db.alter_column('paypal_pdt', 'parent_txn_id', self.gf('models.CharField')("Parent Transaction ID", max_length=19)) + db.alter_column('paypal_pdt', 'parent_txn_id', + self.gf('models.CharField')("Parent Transaction ID", max_length=19)) # Changing field 'PayPalPDT.ipaddress' db.alter_column('paypal_pdt', 'ipaddress', self.gf('models.IPAddressField')()) @@ -58,16 +57,26 @@ def backwards(self, orm): 'address_status': ('django.db.models.fields.CharField', [], {'max_length': '11', 'blank': 'True'}), 'address_street': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), 'address_zip': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}), - 'amount': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amount1': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amount2': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amount3': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amount_per_cycle': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'amt': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount1': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount2': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount3': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'amount_per_cycle': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'amt': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), 'auction_buyer_id': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), 'auction_closing_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'auction_multi_item': ('django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), - 'auth_amount': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'auction_multi_item': ( + 'django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), + 'auth_amount': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'auth_exp': ('django.db.models.fields.CharField', [], {'max_length': '28', 'blank': 'True'}), 'auth_id': ('django.db.models.fields.CharField', [], {'max_length': '19', 'blank': 'True'}), 'auth_status': ('django.db.models.fields.CharField', [], {'max_length': '9', 'blank': 'True'}), @@ -79,38 +88,66 @@ def backwards(self, orm): 'cm': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'contact_phone': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}), 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'currency_code': ('django.db.models.fields.CharField', [], {'default': "'USD'", 'max_length': '32', 'blank': 'True'}), + 'currency_code': ( + 'django.db.models.fields.CharField', [], {'default': "'USD'", 'max_length': '32', 'blank': 'True'}), 'custom': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'exchange_rate': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '16', 'blank': 'True'}), + 'exchange_rate': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '16', + 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), 'flag': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'flag_code': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), 'flag_info': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'for_auction': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'from_view': ('django.db.models.fields.CharField', [], {'max_length': '6', 'null': 'True', 'blank': 'True'}), - 'handling_amount': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'for_auction': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'from_view': ( + 'django.db.models.fields.CharField', [], {'max_length': '6', 'null': 'True', 'blank': 'True'}), + 'handling_amount': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'initial_payment_amount': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'initial_payment_amount': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'invoice': ('django.db.models.fields.CharField', [], {'max_length': '127', 'blank': 'True'}), 'ipaddress': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'blank': 'True'}), 'item_name': ('django.db.models.fields.CharField', [], {'max_length': '127', 'blank': 'True'}), 'item_number': ('django.db.models.fields.CharField', [], {'max_length': '127', 'blank': 'True'}), 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), - 'mc_amount1': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_amount2': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_amount3': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_currency': ('django.db.models.fields.CharField', [], {'default': "'USD'", 'max_length': '32', 'blank': 'True'}), - 'mc_fee': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_gross': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_handling': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'mc_shipping': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'mc_amount1': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'mc_amount2': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'mc_amount3': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'mc_currency': ( + 'django.db.models.fields.CharField', [], {'default': "'USD'", 'max_length': '32', 'blank': 'True'}), + 'mc_fee': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'mc_gross': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'mc_handling': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'mc_shipping': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'memo': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'next_payment_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'notify_version': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), - 'num_cart_items': ('django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), + 'notify_version': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), + 'num_cart_items': ( + 'django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), 'option_name1': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), 'option_name2': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), - 'outstanding_balance': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'outstanding_balance': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'parent_txn_id': ('django.db.models.fields.CharField', [], {'max_length': '19', 'blank': 'True'}), 'password': ('django.db.models.fields.CharField', [], {'max_length': '24', 'blank': 'True'}), 'payer_business_name': ('django.db.models.fields.CharField', [], {'max_length': '127', 'blank': 'True'}), @@ -119,7 +156,9 @@ def backwards(self, orm): 'payer_status': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'}), 'payment_cycle': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), 'payment_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'payment_gross': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'payment_gross': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'payment_status': ('django.db.models.fields.CharField', [], {'max_length': '17', 'blank': 'True'}), 'payment_type': ('django.db.models.fields.CharField', [], {'max_length': '7', 'blank': 'True'}), 'pending_reason': ('django.db.models.fields.CharField', [], {'max_length': '14', 'blank': 'True'}), @@ -138,30 +177,38 @@ def backwards(self, orm): 'receipt_id': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), 'receiver_email': ('django.db.models.fields.EmailField', [], {'max_length': '127', 'blank': 'True'}), 'receiver_id': ('django.db.models.fields.CharField', [], {'max_length': '127', 'blank': 'True'}), - 'recur_times': ('django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), + 'recur_times': ( + 'django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), 'recurring': ('django.db.models.fields.CharField', [], {'max_length': '1', 'blank': 'True'}), 'recurring_payment_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}), - 'remaining_settle': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'remaining_settle': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'residence_country': ('django.db.models.fields.CharField', [], {'max_length': '2', 'blank': 'True'}), 'response': ('django.db.models.fields.TextField', [], {'blank': 'True'}), 'retry_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'rp_invoice_id': ('django.db.models.fields.CharField', [], {'max_length': '127', 'blank': 'True'}), - 'settle_amount': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'settle_amount': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', + 'blank': 'True'}), 'settle_currency': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), - 'shipping': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'shipping': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), 'shipping_method': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'sig': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'st': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), 'subscr_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'subscr_effective': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'subscr_id': ('django.db.models.fields.CharField', [], {'max_length': '19', 'blank': 'True'}), - 'tax': ('django.db.models.fields.DecimalField', [], {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), + 'tax': ('django.db.models.fields.DecimalField', [], + {'default': '0', 'null': 'True', 'max_digits': '64', 'decimal_places': '2', 'blank': 'True'}), 'test_ipn': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'time_created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'transaction_entity': ('django.db.models.fields.CharField', [], {'max_length': '7', 'blank': 'True'}), 'transaction_subject': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'tx': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'txn_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '19', 'blank': 'True'}), + 'txn_id': ( + 'django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '19', 'blank': 'True'}), 'txn_type': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}), 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), 'username': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), diff --git a/paypal/standard/pdt/models.py b/paypal/standard/pdt/models.py index 8e6da92..1983a94 100644 --- a/paypal/standard/pdt/models.py +++ b/paypal/standard/pdt/models.py @@ -16,10 +16,12 @@ class PayPalSettingsError(Exception): """Raised when settings are incorrect.""" + try: IDENTITY_TOKEN = settings.PAYPAL_IDENTITY_TOKEN except: - raise PayPalSettingsError("You must set PAYPAL_IDENTITY_TOKEN in settings.py. Get this token by enabling PDT in your PayPal account.") + raise PayPalSettingsError( + "You must set PAYPAL_IDENTITY_TOKEN in settings.py. Get this token by enabling PDT in your PayPal account.") class PayPalPDT(PayPalStandardBase): @@ -56,6 +58,7 @@ def get_endpoint(self): def _verify_postback(self): # ### Now we don't really care what result was, just whether a flag was set or not. from paypal.standard.pdt.forms import PayPalPDTForm + result = False response_list = self.response.split('\n') response_dict = {} @@ -78,7 +81,8 @@ def _verify_postback(self): qd = QueryDict('', mutable=True) qd.update(response_dict) - qd.update(dict(ipaddress=self.ipaddress, st=self.st, flag_info=self.flag_info,flag=self.flag,flag_code=self.flag_code)) + qd.update(dict(ipaddress=self.ipaddress, st=self.st, flag_info=self.flag_info, flag=self.flag, + flag_code=self.flag_code)) pdt_form = PayPalPDTForm(qd, instance=self) pdt_form.save(commit=False) diff --git a/paypal/standard/pdt/templates/pdt/pdt.html b/paypal/standard/pdt/templates/pdt/pdt.html index f0f3dd4..7536ea0 100755 --- a/paypal/standard/pdt/templates/pdt/pdt.html +++ b/paypal/standard/pdt/templates/pdt/pdt.html @@ -6,20 +6,32 @@

Transaction complete

Thank you for your payment

Please print this page for your records

-
- - - - - - -
Payer:{{ pdt_obj.first_name }} {{ pdt_obj.last_name }}
Payer Email:{{ pdt_obj.payer_email }}
Amount:{{ pdt_obj.mc_currency }} {{ pdt_obj.mc_gross }}
Reference:{{ pdt_obj.txn_id }}
+
+ + + + + + + + + + + + + + + + + + +
Payer:{{ pdt_obj.first_name }} {{ pdt_obj.last_name }}
Payer Email:{{ pdt_obj.payer_email }}
Amount:{{ pdt_obj.mc_currency }} {{ pdt_obj.mc_gross }}
Reference:{{ pdt_obj.txn_id }}
- -{% else %} + +{% else %}

Transaction Failed

-

Sorry transaction failed, please try a different form of payment

-{% endifequal %} +

Sorry transaction failed, please try a different form of payment

+{% endifequal %} {% endblock %} diff --git a/paypal/standard/pdt/templates/pdt/test_pdt_response.html b/paypal/standard/pdt/templates/pdt/test_pdt_response.html index affa30f..a96acbd 100644 --- a/paypal/standard/pdt/templates/pdt/test_pdt_response.html +++ b/paypal/standard/pdt/templates/pdt/test_pdt_response.html @@ -32,4 +32,4 @@ transaction_subject={{custom}} payment_gross= shipping=0.00 - - \ No newline at end of file +- \ No newline at end of file diff --git a/paypal/standard/pdt/tests/templates/pdt/pdt.html b/paypal/standard/pdt/tests/templates/pdt/pdt.html index e492b0a..4886b7b 100755 --- a/paypal/standard/pdt/tests/templates/pdt/pdt.html +++ b/paypal/standard/pdt/tests/templates/pdt/pdt.html @@ -3,17 +3,29 @@

Transaction complete

Thank you for your payment

Please print this page for your records

-
- - - - - - -
Payer:{{ pdt_obj.first_name }} {{ pdt_obj.last_name }}
Payer Email:{{ pdt_obj.payer_email }}
Amount:{{ pdt_obj.mc_currency }} {{ pdt_obj.mc_gross }}
Reference:{{ pdt_obj.txn_id }}
+
+ + + + + + + + + + + + + + + + + + +
Payer:{{ pdt_obj.first_name }} {{ pdt_obj.last_name }}
Payer Email:{{ pdt_obj.payer_email }}
Amount:{{ pdt_obj.mc_currency }} {{ pdt_obj.mc_gross }}
Reference:{{ pdt_obj.txn_id }}
- -{% else %} + +{% else %}

Transaction Failed

-

Sorry transaction failed, please try a different form of payment

+

Sorry transaction failed, please try a different form of payment

{% endifequal %} \ No newline at end of file diff --git a/paypal/standard/pdt/tests/test_pdt.py b/paypal/standard/pdt/tests/test_pdt.py index e49e12b..2263656 100644 --- a/paypal/standard/pdt/tests/test_pdt.py +++ b/paypal/standard/pdt/tests/test_pdt.py @@ -6,21 +6,19 @@ from django.conf import settings from django.shortcuts import render_to_response from django.test import TestCase -from paypal.standard.pdt.forms import PayPalPDTForm from paypal.standard.pdt.models import PayPalPDT from paypal.standard.pdt.signals import pdt_successful, pdt_failed class DummyPayPalPDT(object): - def __init__(self, update_context_dict={}): - self.context_dict = {'st': 'SUCCESS', 'custom':'cb736658-3aad-4694-956f-d0aeade80194', - 'txn_id':'1ED550410S3402306', 'mc_gross': '225.00', + self.context_dict = {'st': 'SUCCESS', 'custom': 'cb736658-3aad-4694-956f-d0aeade80194', + 'txn_id': '1ED550410S3402306', 'mc_gross': '225.00', 'business': settings.PAYPAL_RECEIVER_EMAIL, 'error': 'Error code: 1234'} - + self.context_dict.update(update_context_dict) self.response = '' - + def update_with_get_params(self, get_params): if get_params.has_key('tx'): self.context_dict['txn_id'] = get_params.get('tx') @@ -28,22 +26,23 @@ def update_with_get_params(self, get_params): self.context_dict['mc_gross'] = get_params.get('amt') if get_params.has_key('cm'): self.context_dict['custom'] = get_params.get('cm') - + def _postback(self, test=True): """Perform a Fake PayPal PDT Postback request.""" # @@@ would be cool if this could live in the test templates dir... return render_to_response("pdt/test_pdt_response.html", self.context_dict).content + class PDTTest(TestCase): urls = "paypal.standard.pdt.tests.test_urls" - template_dirs = [os.path.join(os.path.dirname(__file__), 'templates'),] + template_dirs = [os.path.join(os.path.dirname(__file__), 'templates'), ] def setUp(self): # set up some dummy PDT get parameters - self.get_params = {"tx":"4WJ86550014687441", "st":"Completed", "amt":"225.00", "cc":"EUR", - "cm":"a3e192b8-8fea-4a86-b2e8-d5bf502e36be", "item_number":"", - "sig":"blahblahblah"} - + self.get_params = {"tx": "4WJ86550014687441", "st": "Completed", "amt": "225.00", "cc": "EUR", + "cm": "a3e192b8-8fea-4a86-b2e8-d5bf502e36be", "item_number": "", + "sig": "blahblahblah"} + # monkey patch the PayPalPDT._postback function self.dpppdt = DummyPayPalPDT() self.dpppdt.update_with_get_params(self.get_params) @@ -52,7 +51,7 @@ def setUp(self): def test_verify_postback(self): dpppdt = DummyPayPalPDT() paypal_response = dpppdt._postback() - assert('SUCCESS' in paypal_response) + assert ('SUCCESS' in paypal_response) self.assertEqual(len(PayPalPDT.objects.all()), 0) pdt_obj = PayPalPDT() pdt_obj.ipaddress = '127.0.0.1' @@ -60,42 +59,44 @@ def test_verify_postback(self): pdt_obj._verify_postback() self.assertEqual(len(PayPalPDT.objects.all()), 0) self.assertEqual(pdt_obj.txn_id, '1ED550410S3402306') - - def test_pdt(self): - self.assertEqual(len(PayPalPDT.objects.all()), 0) + + def test_pdt(self): + self.assertEqual(len(PayPalPDT.objects.all()), 0) self.dpppdt.update_with_get_params(self.get_params) - paypal_response = self.client.get("/pdt/", self.get_params) + paypal_response = self.client.get("/pdt/", self.get_params) self.assertContains(paypal_response, 'Transaction complete', status_code=200) self.assertEqual(len(PayPalPDT.objects.all()), 1) def test_pdt_signals(self): - self.successful_pdt_fired = False + self.successful_pdt_fired = False self.failed_pdt_fired = False - + def successful_pdt(sender, **kwargs): self.successful_pdt_fired = True + pdt_successful.connect(successful_pdt) - + def failed_pdt(sender, **kwargs): - self.failed_pdt_fired = True + self.failed_pdt_fired = True + pdt_failed.connect(failed_pdt) - - self.assertEqual(len(PayPalPDT.objects.all()), 0) + + self.assertEqual(len(PayPalPDT.objects.all()), 0) paypal_response = self.client.get("/pdt/", self.get_params) - self.assertContains(paypal_response, 'Transaction complete', status_code=200) + self.assertContains(paypal_response, 'Transaction complete', status_code=200) self.assertEqual(len(PayPalPDT.objects.all()), 1) self.assertTrue(self.successful_pdt_fired) - self.assertFalse(self.failed_pdt_fired) + self.assertFalse(self.failed_pdt_fired) pdt_obj = PayPalPDT.objects.all()[0] self.assertEqual(pdt_obj.flag, False) - + def test_double_pdt_get(self): - self.assertEqual(len(PayPalPDT.objects.all()), 0) + self.assertEqual(len(PayPalPDT.objects.all()), 0) paypal_response = self.client.get("/pdt/", self.get_params) self.assertContains(paypal_response, 'Transaction complete', status_code=200) self.assertEqual(len(PayPalPDT.objects.all()), 1) - pdt_obj = PayPalPDT.objects.all()[0] - self.assertEqual(pdt_obj.flag, False) + pdt_obj = PayPalPDT.objects.all()[0] + self.assertEqual(pdt_obj.flag, False) paypal_response = self.client.get("/pdt/", self.get_params) self.assertContains(paypal_response, 'Transaction complete', status_code=200) self.assertEqual(len(PayPalPDT.objects.all()), 1) # we don't create a new pdt @@ -104,16 +105,16 @@ def test_double_pdt_get(self): def test_no_txn_id_in_pdt(self): self.dpppdt.context_dict.pop('txn_id') - self.get_params={} + self.get_params = {} paypal_response = self.client.get("/pdt/", self.get_params) self.assertContains(paypal_response, 'Transaction Failed', status_code=200) self.assertEqual(len(PayPalPDT.objects.all()), 0) - + def test_custom_passthrough(self): - self.assertEqual(len(PayPalPDT.objects.all()), 0) + self.assertEqual(len(PayPalPDT.objects.all()), 0) self.dpppdt.update_with_get_params(self.get_params) paypal_response = self.client.get("/pdt/", self.get_params) self.assertContains(paypal_response, 'Transaction complete', status_code=200) self.assertEqual(len(PayPalPDT.objects.all()), 1) pdt_obj = PayPalPDT.objects.all()[0] - self.assertEqual(pdt_obj.custom, self.get_params['cm'] ) \ No newline at end of file + self.assertEqual(pdt_obj.custom, self.get_params['cm']) \ No newline at end of file diff --git a/paypal/standard/pdt/tests/test_urls.py b/paypal/standard/pdt/tests/test_urls.py index 70d06a4..a3aff9f 100644 --- a/paypal/standard/pdt/tests/test_urls.py +++ b/paypal/standard/pdt/tests/test_urls.py @@ -1,5 +1,5 @@ from django.conf.urls import patterns urlpatterns = patterns('paypal.standard.pdt.views', - (r'^pdt/$', 'pdt'), + (r'^pdt/$', 'pdt'), ) diff --git a/paypal/standard/pdt/urls.py b/paypal/standard/pdt/urls.py index f1f06b1..cca65de 100644 --- a/paypal/standard/pdt/urls.py +++ b/paypal/standard/pdt/urls.py @@ -1,5 +1,5 @@ from django.conf.urls import patterns, url urlpatterns = patterns('paypal.standard.pdt.views', - url(r'^$', 'pdt', name="paypal-pdt"), + url(r'^$', 'pdt', name="paypal-pdt"), ) diff --git a/paypal/standard/pdt/views.py b/paypal/standard/pdt/views.py index 817364c..2892b6f 100644 --- a/paypal/standard/pdt/views.py +++ b/paypal/standard/pdt/views.py @@ -15,9 +15,10 @@ def pdt(request, item_check_callable=None, template="pdt/pdt.html", context=None pdt_obj, failed = process_pdt(request, item_check_callable) context = context or {} - context.update({"failed":failed, "pdt_obj":pdt_obj}) + context.update({"failed": failed, "pdt_obj": pdt_obj}) return render_to_response(template, context, RequestContext(request)) + def process_pdt(request, item_check_callable=None): """ Payment data transfer implementation: http://tinyurl.com/c9jjmw diff --git a/paypal/standard/widgets.py b/paypal/standard/widgets.py index 51aea94..71ca90c 100644 --- a/paypal/standard/widgets.py +++ b/paypal/standard/widgets.py @@ -11,17 +11,20 @@ class ValueHiddenInput(forms.HiddenInput): Widget that renders only if it has a value. Used to remove unused fields from PayPal buttons. """ + def render(self, name, value, attrs=None): if value is None: return u'' else: return super(ValueHiddenInput, self).render(name, value, attrs) + class ReservedValueHiddenInput(ValueHiddenInput): """ Overrides the default name attribute of the form. Used for the PayPal `return` field. """ + def render(self, name, value, attrs=None): if value is None: value = ''