addons-server/apps/amo/views.py

176 строки
6.3 KiB
Python
Исходник Обычный вид История

2010-05-11 03:27:13 +04:00
import logging
2010-05-07 10:47:26 +04:00
import random
import socket
import urllib2
from django import http
from django.conf import settings
2010-05-02 10:46:17 +04:00
from django.core.cache import cache, parse_backend_uri
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_exempt
2010-02-05 04:51:14 +03:00
import jingo
import phpserialize as php
from stats.models import Contribution, ContributionError, SubscriptionEvent
2010-03-24 21:50:50 +03:00
from . import log
2010-02-05 04:51:14 +03:00
2010-05-11 03:27:13 +04:00
paypal_log = logging.getLogger('z.paypal')
@never_cache
def monitor(request):
# For each check, a boolean pass/fail status to show in the template
status_summary = {}
status = 200
# Check all memcached servers
scheme, servers, _ = parse_backend_uri(settings.CACHE_BACKEND)
memcache_results = []
status_summary['memcache'] = True
if 'memcached' in scheme:
hosts = servers.split(';')
for host in hosts:
ip, port = host.split(':')
try:
s = socket.socket()
s.connect((ip, int(port)))
except Exception, e:
result = False
status_summary['memcache'] = False
status = 500
2010-03-24 22:51:03 +03:00
log.critical('Failed to connect to memcached (%s): %s' %
(host, e))
else:
result = True
finally:
s.close()
memcache_results.append((ip, port, result))
if len(memcache_results) < 2:
2010-02-05 11:14:43 +03:00
status = 500
status_summary['memcache'] = False
2010-03-24 22:51:03 +03:00
log.warning('You should have 2+ memcache servers. You have %s.' %
len(memcache_results))
if not memcache_results:
status = 500
status_summary['memcache'] = False
log.info('Memcache is not configured.')
return jingo.render(request, 'services/monitor.html',
{'memcache_results': memcache_results,
'status_summary': status_summary},
status=status)
2010-02-05 04:51:14 +03:00
@csrf_exempt
def paypal(request):
"""
Handle PayPal IPN post-back for contribution transactions.
IPN will retry periodically until it gets success (status=200). Any
db errors or replication lag will result in an exception and http
status of 500, which is good so PayPal will try again later.
2010-05-02 10:46:17 +04:00
PayPal IPN variables available at:
https://cms.paypal.com/us/cgi-bin/?cmd=_render-content
&content_ID=developer/e_howto_html_IPNandPDTVariables
"""
try:
return _paypal(request)
except Exception, e:
2010-05-11 03:27:13 +04:00
paypal_log.error('%s\n%s' % (e, request))
return http.HttpResponseServerError('Unknown error.')
2010-05-07 10:47:26 +04:00
def _paypal(request):
2010-05-11 03:27:13 +04:00
2010-05-07 10:47:26 +04:00
def _log_error_with_data(msg, request):
"""Log a message along with some of the POST info from PayPal."""
id = random.randint(0, 99999999)
2010-05-07 10:47:26 +04:00
msg = "[%s] %s (dumping data)" % (id, msg)
2010-05-11 03:27:13 +04:00
paypal_log.error(msg)
2010-05-07 10:47:26 +04:00
logme = {'txn_id': request.POST.get('txn_id'),
2010-05-11 02:33:01 +04:00
'txn_type': request.POST.get('txn_type'),
2010-05-07 10:47:26 +04:00
'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'),
}
2010-05-11 03:27:13 +04:00
paypal_log.error("[%s] PayPal Data: %s" % (id, logme))
2010-05-07 10:47:26 +04:00
2010-04-30 22:14:26 +04:00
if request.method != 'POST':
return http.HttpResponseNotAllowed(['POST'])
# Check that the request is valid and coming from PayPal.
data = '%s&%s' % ('cmd=_notify-validate', request.raw_post_data)
2010-05-07 10:47:26 +04:00
paypal_response = urllib2.urlopen(settings.PAYPAL_CGI_URL,
data, 20).readline()
2010-05-07 10:47:26 +04:00
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 request.POST.get('txn_type', '').startswith('subscr_'):
SubscriptionEvent.objects.create(post_data=php.serialize(request.POST))
2010-05-02 10:46:17 +04:00
return http.HttpResponse('Success!')
# We only care about completed transactions.
if request.POST.get('payment_status') != 'Completed':
return http.HttpResponse('Payment not completed')
# Make sure transaction has not yet been processed.
2010-05-02 10:46:17 +04:00
if (Contribution.objects
.filter(transaction_id=request.POST['txn_id']).count()) > 0:
return http.HttpResponse('Transaction already processed')
# Fetch and update the contribution - item_number is the uuid we created.
try:
2010-05-02 10:46:17 +04:00
c = Contribution.objects.no_cache().get(
uuid=request.POST['item_number'])
except Contribution.DoesNotExist:
2010-05-02 10:46:17 +04:00
key = "%s%s:%s" % (settings.CACHE_PREFIX, 'contrib',
request.POST['item_number'])
count = cache.get(key, 0) + 1
2010-05-11 03:27:13 +04:00
paypal_log.warning('Contribution (uuid=%s) not found for IPN request '
'#%s.' % (request.POST['item_number'], count))
2010-05-02 10:46:17 +04:00
if count > 10:
2010-05-07 10:47:26 +04:00
msg = ("Paypal sent a transaction that we don't know "
"about and we're giving up on it.")
_log_error_with_data(msg, request)
2010-05-02 10:46:17 +04:00
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 = request.POST['txn_id']
c.amount = request.POST['mc_gross']
c.uuid = None
c.post_data = php.serialize(request.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.
2010-05-11 03:27:13 +04:00
paypal_log.error('Thankyou note email failed with error: %s' % e)
return http.HttpResponse('Success!')
2010-02-05 04:51:14 +03:00
def handler404(request):
return jingo.render(request, 'amo/404.lhtml', status=404)
def handler500(request):
2010-02-17 02:55:22 +03:00
return jingo.render(request, 'amo/500.lhtml', status=500)