Mercurial > public > sg101
diff gpp/donations/views.py @ 36:296b610ee507
Added IPN logic to the donations module. Added a thank-you view. Need to add logging to the IPN function.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Thu, 11 Jun 2009 00:54:44 +0000 |
parents | f77a1cdd7a46 |
children | 5dbfb7fec629 |
line wrap: on
line diff
--- a/gpp/donations/views.py Sun Jun 07 00:22:50 2009 +0000 +++ b/gpp/donations/views.py Thu Jun 11 00:54:44 2009 +0000 @@ -1,26 +1,43 @@ """ Views for the donations application. """ +import urllib2 +import decimal +import datetime + from django.shortcuts import render_to_response from django.template import RequestContext -from django.http import Http404 # TODO: remove from django.conf import settings from django.contrib.sites.models import Site +from django.http import HttpResponse +from django.http import HttpResponseServerError +from django.contrib.auth.models import User from donations.models import Donation +PP_DATE_FMT = '%H:%M:%S %b %d, %Y PST' -def index(request): - gross, net, donations = Donation.objects.monthly_stats() - current_site = Site.objects.get_current() - - if settings.DEBUG: +def paypal_params(): + """ + This function returns a tuple where the 1st element is the Paypal + URL and the 2nd element is the Paypal business email. This information + depends on the setting DONATIONS_DEBUG. + """ + if settings.DONATIONS_DEBUG: form_action = 'https://www.sandbox.paypal.com/cgi-bin/webscr' business = settings.DONATIONS_BUSINESS_DEBUG else: form_action = 'https://www.paypal.com/cgi-bin/webscr' business = settings.DONATIONS_BUSINESS + return form_action, business + + +def index(request): + gross, net, donations = Donation.objects.monthly_stats() + current_site = Site.objects.get_current() + form_action, business = paypal_params() + return render_to_response('donations/index.html', { 'goal': settings.DONATIONS_GOAL, 'gross': gross, @@ -39,8 +56,121 @@ def ipn(request): - raise Http404 #TODO + """ + This function is the IPN listener and handles the IPN POST from Paypal. + TODO: Add logging. + """ + parameters = None + try: + if request['payment_status'] == 'Completed': + if request.POST: + parameters = request.POST.copy() + else: + parameters = request.GET.copy() -def thanks(request): - raise Http404 #TODO + if parameters: + parameters['cmd']='_notify-validate' + req = urllib2.Request(paypal_params()[0], parameters.urlencode()) + req.add_header("Content-type", "application/x-www-form-urlencoded") + response = urllib2.urlopen(req) + status = response.read() + if status != "VERIFIED": + parameters = None + + if parameters: + # is this a donation to the site? + try: + item_number = int(parameters['item_number']) + except ValueError: + pass + else: + if item_number == settings.DONATIONS_ITEM_NUM or \ + item_number == settings.DONATIONS_ITEM_ANON_NUM: + process_donation(item_number, parameters) + + return HttpResponse("Ok") + + except Exception, e: + # print "An exeption was caught: " + str(e) + pass + + return HttpResponseServerError("Error") + + +def process_donation(item_number, params): + """ + Constructs a donation object from the parameters and stores + in the database. + """ + # Has this transaction been processed before? + if 'txn_id' not in params: + return + txn_id = params['txn_id'] + try: + donation = Donation.objects.get(txn_id__exact=txn_id) + except Donation.DoesNotExist: + pass + else: + return # no exception, this is a duplicate + + # Is the email address ours? + business = params.get('business') + if business != paypal_params()[1]: + return + + # is this a payment received? + txn_type = params.get('txn_type') + if txn_type != 'web_accept': + 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 + # the donation was made. + user = None + if 'custom' in params: + try: + user = User.objects.get(username__exact=params['custom']) + except User.DoesNotExist: + pass + + is_anonymous = item_number == settings.DONATIONS_ITEM_ANON_NUM + test_ipn = params.get('test_ipn') == '1' + + first_name = params.get('first_name', '') + last_name = params.get('last_name', '') + payer_email = params.get('payer_email', '') + payer_id = params.get('payer_id', '') + memo = params.get('memo', '') + payer_status = params.get('payer_status', '') + + try: + mc_gross = decimal.Decimal(params['mc_gross']) + mc_fee = decimal.Decimal(params['mc_fee']) + except KeyError, decimal.InvalidOperation: + return + + try: + payment_date = datetime.datetime.strptime(params['payment_date'], + PP_DATE_FMT) + except KeyError, ValueError: + return + + donation = Donation( + user=user, + is_anonymous=is_anonymous, + test_ipn=test_ipn, + txn_id=txn_id, + first_name=first_name, + last_name=last_name, + payer_email=payer_email, + payer_id=payer_id, + memo=memo, + payer_status=payer_status, + mc_gross=mc_gross, + mc_fee=mc_fee, + payment_date=payment_date) + + donation.save() +