Mercurial > public > sg101
diff gpp/donations/views.py @ 316:767cedc7d12a
Fixing #144; integrate with new Django logging support. Also added unit tests for Donations app.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Sun, 30 Jan 2011 20:02:32 +0000 |
parents | a3b47d0f4df1 |
children |
line wrap: on
line diff
--- a/gpp/donations/views.py Sat Jan 29 20:39:55 2011 +0000 +++ b/gpp/donations/views.py Sun Jan 30 20:02:32 2011 +0000 @@ -4,6 +4,7 @@ import urllib2 import decimal import datetime +import logging from django.shortcuts import render_to_response from django.template import RequestContext @@ -35,6 +36,26 @@ return form_action, business +def verify_request(params): + """ + Send the parameters back to Paypal and return the response string. + """ + # If we are doing localhost-type unit tests, just return whatever + # the test wants us to... + if hasattr(settings, 'DONATIONS_DEBUG_VERIFY_RESPONSE'): + return settings.DONATIONS_DEBUG_VERIFY_RESPONSE + + req = urllib2.Request(paypal_params()[0], params) + req.add_header("Content-type", "application/x-www-form-urlencoded") + try: + response = urllib2.urlopen(req) + except URLError, e: + logging.exception('IPN: exception verifying IPN: %s', e) + return None + + return response.read() + + def index(request): gross, net, donations = Donation.objects.monthly_stats() current_site = Site.objects.get_current() @@ -63,28 +84,23 @@ This function is the IPN listener and handles the IPN POST from Paypal. The algorithm here roughly follows the outline described in chapter 2 of Paypal's IPNGuide.pdf "Implementing an IPN Listener". + """ - import logging - # Log some info about this IPN event ip = request.META.get('REMOTE_ADDR', '?') parameters = request.POST.copy() - logging.info('IPN from %s; post data: %s' % (ip, parameters.urlencode())) + logging.info('IPN from %s; post data: %s', ip, parameters.urlencode()) # Now we follow the instructions in chapter 2 of the Paypal IPNGuide.pdf. # Create a request that contains exactly the same IPN variables and values in # the same order, preceded with cmd=_notify-validate parameters['cmd']='_notify-validate' - # Post the request back to Paypal (either to the sandbox or the real deal). - req = urllib2.Request(paypal_params()[0], parameters.urlencode()) - req.add_header("Content-type", "application/x-www-form-urlencoded") - response = urllib2.urlopen(req) - - # Wait for the response from Paypal, which should be either VERIFIED or INVALID. - status = response.read() + # Post the request back to Paypal (either to the sandbox or the real deal), + # and read the response: + status = verify_request(parameters.urlencode()) if status != 'VERIFIED': - logging.warning('IPN: Payapl did not verify; status was %s' % status) + logging.warning('IPN: Payapl did not verify; status was %s', status) return HttpResponse() # Response was VERIFIED; act on this if it is a Completed donation, @@ -93,13 +109,13 @@ payment_status = parameters.get('payment_status') if payment_status != 'Completed': - logging.info('IPN: payment_status is %s; we are done.' % payment_status) + logging.info('IPN: payment_status is %s; we are done.', payment_status) return HttpResponse() # Is this a donation to the site? item_number = parameters.get('item_number') - if item_number == settings.DONATIONS_ITEM_NUM or \ - item_number == settings.DONATIONS_ITEM_ANON_NUM: + if (item_number == settings.DONATIONS_ITEM_NUM or + item_number == settings.DONATIONS_ITEM_ANON_NUM): process_donation(item_number, parameters) else: logging.info('IPN: not a donation; done.') @@ -110,11 +126,10 @@ def process_donation(item_number, params): """ A few validity and duplicate checks are made on the donation params. - If everything is ok, construct a donation object from the parameters and + If everything is ok, construct a donation object from the parameters and store it in the database. + """ - import logging - # Has this transaction been processed before? txn_id = params.get('txn_id') if txn_id is None: @@ -132,15 +147,15 @@ # Is the email address ours? business = params.get('business') if business != paypal_params()[1]: - logging.warning('IPN: invalid business: %s' % business) + logging.warning('IPN: invalid business: %s', business) return # is this a payment received? txn_type = params.get('txn_type') if txn_type != 'web_accept': - logging.warning('IPN: invalid txn_type: %s' % txn_type) + logging.warning('IPN: invalid txn_type: %s', txn_type) return - + # Looks like a donation, save it to the database. # Determine which user this came from, if any. # The username is stored in the custom field if the user was logged in when @@ -179,7 +194,7 @@ try: payment_date = datetime.datetime.strptime(payment_date, PP_DATE_FMT) except ValueError: - logging.error('IPN: invalid payment_date "%s"' % params['payment_date']) + logging.error('IPN: invalid payment_date "%s"', params['payment_date']) return try: