def _paypal(request): if request.method != 'POST': return http.HttpResponseNotAllowed(['POST']) # raw_post_data has to be accessed before request.POST. wtf django? raw, post = request.raw_post_data, request.POST.copy() # Check that the request is valid and coming from PayPal. # The order of the params has to match the original request. data = u'cmd=_notify-validate&' + raw paypal_response = urllib2.urlopen(settings.PAYPAL_CGI_URL, data, 20).readline() # List of (old, new) codes so we can transpose the data for # embedded payments. for old, new in [('payment_status', 'status'), ('item_number', 'tracking_id'), ('txn_id', 'tracking_id'), ('payer_email', 'sender_email')]: if old not in post and new in post: post[old] = post[new] if paypal_response != 'VERIFIED': msg = ("Expecting 'VERIFIED' from PayPal, got '%s'. " "Failing." % paypal_response) _log_error_with_data(msg, post) return http.HttpResponseForbidden('Invalid confirmation') if post.get('txn_type', '').startswith('subscr_'): SubscriptionEvent.objects.create(post_data=php.serialize(post)) return http.HttpResponse('Success!') payment_status = post.get('payment_status', '').lower() if payment_status not in ('refunded', 'completed'): # Skip processing for anything other than events that change # payment status. return http.HttpResponse('Payment not completed') # Fetch and update the contribution - item_number is the uuid we created. try: c = Contribution.objects.get(uuid=post['item_number']) except Contribution.DoesNotExist: key = "%s%s:%s" % (settings.CACHE_PREFIX, 'contrib', post['item_number']) count = cache.get(key, 0) + 1 paypal_log.warning('Contribution (uuid=%s) not found for IPN request ' '#%s.' % (post['item_number'], count)) if count > 10: msg = ("PayPal sent a transaction that we don't know " "about and we're giving up on it.") _log_error_with_data(msg, post) cache.delete(key) return http.HttpResponse('Transaction not found; skipping.') cache.set(key, count, 1209600) # This is 2 weeks. return http.HttpResponseServerError('Contribution not found') if payment_status == 'refunded': return paypal_refunded(request, post, c) elif payment_status == 'completed': return paypal_completed(request, post, c)
def _log_error_with_data(msg, post): """Log a message along with some of the POST info from PayPal.""" id = random.randint(0, 99999999) msg = "[%s] %s (dumping data)" % (id, msg) paypal_log.error(msg) logme = {'txn_id': post.get('txn_id'), 'txn_type': post.get('txn_type'), 'payer_email': post.get('payer_email'), 'receiver_email': post.get('receiver_email'), 'payment_status': post.get('payment_status'), 'payment_type': post.get('payment_type'), 'mc_gross': post.get('mc_gross'), 'item_number': post.get('item_number'), } paypal_log.error("[%s] PayPal Data: %s" % (id, logme))
def _paypal(request): def _log_error_with_data(msg, request): """Log a message along with some of the POST info from PayPal.""" id = random.randint(0, 99999999) msg = "[%s] %s (dumping data)" % (id, msg) paypal_log.error(msg) logme = {'txn_id': request.POST.get('txn_id'), 'txn_type': request.POST.get('txn_type'), 'payer_email': request.POST.get('payer_email'), 'receiver_email': request.POST.get('receiver_email'), 'payment_status': request.POST.get('payment_status'), 'payment_type': request.POST.get('payment_type'), 'mc_gross': request.POST.get('mc_gross'), 'item_number': request.POST.get('item_number'), } paypal_log.error("[%s] PayPal Data: %s" % (id, logme)) if request.method != 'POST': return http.HttpResponseNotAllowed(['POST']) # raw_post_data has to be accessed before request.POST. wtf django? raw, post = request.raw_post_data, request.POST.copy() # Check that the request is valid and coming from PayPal. # The order of the params has to match the original request. data = u'cmd=_notify-validate&' + raw paypal_response = urllib2.urlopen(settings.PAYPAL_CGI_URL, data, 20).readline() if paypal_response != 'VERIFIED': msg = ("Expecting 'VERIFIED' from PayPal, got '%s'. " "Failing." % paypal_response) _log_error_with_data(msg, request) return http.HttpResponseForbidden('Invalid confirmation') if post.get('txn_type', '').startswith('subscr_'): SubscriptionEvent.objects.create(post_data=php.serialize(post)) return http.HttpResponse('Success!') # List of (old, new) codes so we can transpose the data for # embedded payments. for old, new in [('payment_status', 'status'), ('item_number', 'tracking_id'), ('txn_id', 'tracking_id'), ('payer_email', 'sender_email')]: if old not in post and new in post: post[old] = post[new] # We only care about completed transactions. if post.get('payment_status', '').lower() != 'completed': return http.HttpResponse('Payment not completed') # Make sure transaction has not yet been processed. if (Contribution.objects .filter(transaction_id=post['txn_id']).count()) > 0: return http.HttpResponse('Transaction already processed') # Fetch and update the contribution - item_number is the uuid we created. try: c = Contribution.objects.get(uuid=post['item_number']) except Contribution.DoesNotExist: key = "%s%s:%s" % (settings.CACHE_PREFIX, 'contrib', post['item_number']) count = cache.get(key, 0) + 1 paypal_log.warning('Contribution (uuid=%s) not found for IPN request ' '#%s.' % (post['item_number'], count)) if count > 10: msg = ("Paypal sent a transaction that we don't know " "about and we're giving up on it.") _log_error_with_data(msg, request) cache.delete(key) return http.HttpResponse('Transaction not found; skipping.') cache.set(key, count, 1209600) # This is 2 weeks. return http.HttpResponseServerError('Contribution not found') c.transaction_id = post['txn_id'] # Embedded payments does not send an mc_gross. if 'mc_gross' in post: c.amount = post['mc_gross'] c.uuid = None c.post_data = php.serialize(post) c.save() # Send thankyou email. try: c.mail_thankyou(request) except ContributionError as e: # A failed thankyou email is not a show stopper, but is good to know. paypal_log.error('Thankyou note email failed with error: %s' % e) return http.HttpResponse('Success!')
def _paypal(request): def _log_error_with_data(msg, post): """Log a message along with some of the POST info from PayPal.""" id = random.randint(0, 99999999) msg = "[%s] %s (dumping data)" % (id, msg) paypal_log.error(msg) logme = {'txn_id': post.get('txn_id'), 'txn_type': post.get('txn_type'), 'payer_email': post.get('payer_email'), 'receiver_email': post.get('receiver_email'), 'payment_status': post.get('payment_status'), 'payment_type': post.get('payment_type'), 'mc_gross': post.get('mc_gross'), 'item_number': post.get('item_number'), } paypal_log.error("[%s] PayPal Data: %s" % (id, logme)) if request.method != 'POST': return http.HttpResponseNotAllowed(['POST']) # raw_post_data has to be accessed before request.POST. wtf django? raw, post = request.raw_post_data, request.POST.copy() # Check that the request is valid and coming from PayPal. # The order of the params has to match the original request. data = u'cmd=_notify-validate&' + raw paypal_response = urllib2.urlopen(settings.PAYPAL_CGI_URL, data, 20).readline() # List of (old, new) codes so we can transpose the data for # embedded payments. for old, new in [('payment_status', 'status'), ('item_number', 'tracking_id'), ('txn_id', 'tracking_id'), ('payer_email', 'sender_email')]: if old not in post and new in post: post[old] = post[new] if paypal_response != 'VERIFIED': msg = ("Expecting 'VERIFIED' from PayPal, got '%s'. " "Failing." % paypal_response) _log_error_with_data(msg, post) return http.HttpResponseForbidden('Invalid confirmation') if post.get('txn_type', '').startswith('subscr_'): SubscriptionEvent.objects.create(post_data=php.serialize(post)) return http.HttpResponse('Success!') # We only care about completed transactions. if post.get('payment_status', '').lower() != 'completed': return http.HttpResponse('Payment not completed') # Make sure transaction has not yet been processed. if (Contribution.objects .filter(transaction_id=post['txn_id']).count()) > 0: return http.HttpResponse('Transaction already processed') # Fetch and update the contribution - item_number is the uuid we created. try: c = Contribution.objects.get(uuid=post['item_number']) except Contribution.DoesNotExist: key = "%s%s:%s" % (settings.CACHE_PREFIX, 'contrib', post['item_number']) count = cache.get(key, 0) + 1 paypal_log.warning('Contribution (uuid=%s) not found for IPN request ' '#%s.' % (post['item_number'], count)) if count > 10: msg = ("PayPal sent a transaction that we don't know " "about and we're giving up on it.") _log_error_with_data(msg, post) cache.delete(key) return http.HttpResponse('Transaction not found; skipping.') cache.set(key, count, 1209600) # This is 2 weeks. return http.HttpResponseServerError('Contribution not found') c.transaction_id = post['txn_id'] # Embedded payments does not send an mc_gross. if 'mc_gross' in post: c.amount = post['mc_gross'] c.uuid = None c.post_data = php.serialize(post) c.save() # Send thankyou email. try: c.mail_thankyou(request) except ContributionError as e: # A failed thankyou email is not a show stopper, but is good to know. paypal_log.error('Thankyou note email failed with error: %s' % e) return http.HttpResponse('Success!')