Adding amazon FPS return view, execute and preapproval support

pull/1/head
icellama21 2012-04-18 16:22:00 -04:00
parent 125582eebd
commit d370091db7
4 changed files with 203 additions and 31 deletions

View File

@ -10,7 +10,7 @@ from django.db.models.query_utils import Q
from django.shortcuts import render_to_response
from django.template import RequestContext
from boto.fps.connection import FPSConnection
from django.http import HttpResponse, HttpRequest, HttpResponseRedirect, HttpResponseBadRequest
from datetime import timedelta
from regluit.utils.localdatetime import now, zuluformat
import dateutil
@ -29,10 +29,108 @@ import commands
import smtplib
import urlparse
import decimal
import sys
import time
logger = logging.getLogger(__name__)
AMAZON_STATUS_SUCCESS_ABT = 'SA'
AMAZON_STATUS_SUCCESS_ACH = 'SB'
AMAZON_STATUS_SUCCESS_CREDIT = 'SC'
AMAZON_STATUS_ERROR = 'SE'
AMAZON_STATUS_ADBANDONED = 'A'
AMAZON_STATUS_EXCEPTION = 'CE'
AMAZON_STATUS_PAYMENT_MISMATCH = 'PE'
AMAZON_STATUS_INCOMPLETE = 'NP'
AMAZON_STATUS_NOT_REGISTERED = 'NM'
AMAZON_STATUS_CANCLLED = 'Cancelled'
AMAZON_STATUS_FAILURE = 'Failure'
AMAZON_STATUS_PENDING = 'Pending'
AMAZON_STATUS_RESERVED = 'Reserved'
AMAZON_STATUS_SUCCESS = 'Success'
AMAZON_IPN_STATUS_CANCELLED = 'CANCELLED'
AMAZON_IPN_STATUS_FAILURE = 'FAILURE'
AMAZON_IPN_STATUS_PENDING = 'PENDING'
AMAZON_IPN_STATUS_RESERVED = 'RESERVED'
AMAZON_IPN_STATUS_SUCCESS = 'SUCCESS'
def amazonPaymentReturn(request):
try:
# pick up all get and post parameters and display
output = "payment complete"
output += request.method + "\n" + str(request.REQUEST.items())
print output
signature = request.GET['signature']
reference = request.GET['callerReference']
token = request.GET['tokenID']
status = request.GET['status']
# BUGUBG - Should we verify the signature here?
#
# Find the transaction by reference, there should only be one
# We will catch the exception if it does not exist
#
transaction = Transaction.objects.get(secret=reference)
#
# BUGBUG, for now lets map amazon status code to paypal, just to keep things uninform
#
if transaction.type == PAYMENT_TYPE_INSTANT:
# Instant payments need to be executed now
if status == AMAZON_STATUS_SUCCESS_ABT or status == AMAZON_STATUS_SUCCESS_ACH or status == AMAZON_STATUS_SUCCESS_CREDIT:
# The above status code are unique to the return URL and are different than the pay API codes
# Store the token
transaction.pay_key = token
#
# BUGBUG, need to handle multiple recipients
# Send the pay request now to ourselves
#
e = Execute(transaction=transaction)
transaction.status = e.status
if e.success() and not e.error():
# Success case, save the ID
print "Amazon Execute returned succesfully"
else:
print "Amazon Execute returned an error, status %s" % e.status
# Failure case
# Save some context for this transaction
else:
transaction.status = AMAZON_STATUS_FAILURE
elif transaction.type == PAYMENT_TYPE_AUTHORIZATION:
#
# Future payments, we only need to store the token. The authorization was requested with the default expidation
# date set in our settings. When we are ready, we can call execute on this
#
if status == AMAZON_STATUS_SUCCESS_ABT or status == AMAZON_STATUS_SUCCESS_ACH or status == AMAZON_STATUS_SUCCESS_CREDIT:
# The above status code are unique to the return URL and are different than the pay API codes
transaction.status = AMAZON_STATUS_PENDING
transaction.approved = True
transaction.pay_key = token
else:
transaction.status = AMAZON_STATUS_FAILURE
transaction.save()
return HttpResponse("Success")
except:
traceback.print_exc()
return HttpResponseBadRequest("Error")
class AmazonRequest:
'''
Handles common information that is processed from the response envelope of the amazon request.
@ -43,12 +141,25 @@ class AmazonRequest:
response = None
raw_response = None
errorMessage = None
status = None
url = None
def ack( self ):
return None
def success(self):
print "CALLING SUCCESS"
if self.status:
#
# process the boto response if we have one. The status codes here are only boto response codes, not
# return_url codes
#
if self.status == AMAZON_STATUS_SUCCESS:
return True
else:
return False
if self.errorMessage:
return False
else:
@ -71,17 +182,23 @@ class AmazonRequest:
return self.errorMessage
def envelope(self):
return None
# The envelope is used to store info about this request
if self.response:
return str(self.response)
else:
return None
def correlation_id(self):
return None
def timestamp(self):
return None
class Pay( AmazonRequest ):
def __init__( self, transaction, return_url=None, cancel_url=None, options=None):
def __init__( self, transaction, return_url=None, cancel_url=None, options=None, amount=None):
try:
@ -94,22 +211,29 @@ class Pay( AmazonRequest ):
receiver_list = []
receivers = transaction.receiver_set.all()
if len(receivers) == 0:
raise Exception
# by setting primary_string of the first receiver to 'true', we are doing a Chained payment
total_amount = 0
for r in receivers:
total_amount += r.amount
if not amount:
# by setting primary_string of the first receiver to 'true', we are doing a Chained payment
amount = 0
for r in receivers:
amount += r.amount
logger.info(receiver_list)
logger.info(receiver_list)
# Data fields for amazon
data = {}
expiry = now() + timedelta( days=settings.PREAPPROVAL_PERIOD )
data = {
'amountType':'Maximum', # The transaction amount is the maximum amount
'callerReference': transaction.secret,
'currencyCode': 'USD',
'globalAmountLimit': str(amount),
'validityExpiry': str(int(time.mktime(expiry.timetuple()))), # use the preapproval date by default
}
print "Amazon PURCHASE url request data: %s" % data
self.url = self.connection.make_url(return_url, "Test Payment", "SingleUse", str(total_amount), **data)
self.url = self.connection.make_url(return_url, "Test Payment", "MultiUse", str(amount), **data)
print "Amazon PURCHASE url was: %s" % self.url
except:
@ -133,4 +257,46 @@ class Pay( AmazonRequest ):
def embedded_url(self):
return None
class Preapproval(Pay):
def __init__( self, transaction, amount, expiry=None, return_url=None, cancel_url=None):
# Call into our parent class
Pay.__init__(self, transaction, return_url=return_url, cancel_url=cancel_url, options=None, amount=amount)
class Execute(AmazonRequest):
def __init__(self, transaction=None):
try:
# Use the boto class top open a connection
self.connection = FPSConnection(settings.FPS_ACCESS_KEY, settings.FPS_SECRET_KEY)
# BUGBUG, handle multiple receivers! For now we just send the money to ourselves
self.raw_response = self.connection.pay(transaction.amount,
transaction.pay_key,
recipientTokenId=None,
callerReference=transaction.secret,
senderReference=None,
recipientReference=None,
senderDescription=None,
recipientDescription=None,
callerDescription=None,
metadata=None,
transactionDate=None,
reserve=False)
print "Amazon EXECUTE response was: %s" % self.raw_response
self.response = self.raw_response[0]
print "RESPONSE: %s" % self.response
self.status = self.response.TransactionStatus
print "STATUS: %s" % self.status
except:
traceback.print_exc()
self.errorMessage = "Error: Server Error"

View File

@ -6,13 +6,13 @@ from django.conf import settings
from regluit.payment.parameters import *
if settings.PAYMENT_PROCESSOR == 'paypal':
from regluit.payment.paypal import Pay
from regluit.payment.paypal import Pay, Execute, Preapproval
elif settings.PAYMENT_PROCESSOR == 'amazon':
from regluit.payment.amazon import Pay
from regluit.payment.amazon import Pay, Execute, Preapproval
from regluit.payment.paypal import Execute, IPN, IPN_TYPE_PAYMENT, IPN_TYPE_PREAPPROVAL, IPN_TYPE_ADJUSTMENT, IPN_PREAPPROVAL_STATUS_ACTIVE, IPN_PAY_STATUS_INCOMPLETE, IPN_PAY_STATUS_NONE
from regluit.payment.paypal import Preapproval, IPN_PAY_STATUS_COMPLETED, CancelPreapproval, PaymentDetails, PreapprovalDetails, IPN_SENDER_STATUS_COMPLETED, IPN_TXN_STATUS_COMPLETED
from regluit.payment.paypal import IPN, IPN_TYPE_PAYMENT, IPN_TYPE_PREAPPROVAL, IPN_TYPE_ADJUSTMENT, IPN_PREAPPROVAL_STATUS_ACTIVE, IPN_PAY_STATUS_INCOMPLETE, IPN_PAY_STATUS_NONE
from regluit.payment.paypal import IPN_PAY_STATUS_COMPLETED, CancelPreapproval, PaymentDetails, PreapprovalDetails, IPN_SENDER_STATUS_COMPLETED, IPN_TXN_STATUS_COMPLETED
from regluit.payment.paypal import RefundPayment
import uuid
import traceback

View File

@ -10,7 +10,12 @@ fps_recur_obj = get_integration("fps")
urlpatterns = patterns(
"regluit.payment.views",
url(r"^paypalipn", "paypalIPN", name="PayPalIPN"),
url(r"^amazonpaymentreturn", "amazonPaymentReturn", name="AmazonPaymentReturn"),
)
# Amazon payment URLs
urlpatterns += patterns(
"regluit.payment.amazon",
url(r"^amazonpaymentreturn", "amazonPaymentReturn", name="AmazonPaymentReturn"),
)
if not settings.IS_PREVIEW:

View File

@ -8,7 +8,7 @@ from django.shortcuts import render_to_response
from django.contrib.auth.models import User
from django.contrib.sites.models import RequestSite
from regluit.payment.parameters import *
from django.http import HttpResponse, HttpRequest, HttpResponseRedirect
from django.http import HttpResponse, HttpRequest, HttpResponseRedirect, HttpResponseBadRequest
from django.views.decorators.csrf import csrf_exempt
from django.test.utils import setup_test_environment
from django.template import RequestContext
@ -114,12 +114,18 @@ def testAuthorize(request):
receiver_list = [{'email': TEST_RECEIVERS[0], 'amount':20.00},
{'email': TEST_RECEIVERS[1], 'amount':10.00}]
# Set the return url for the processor
if settings.PAYMENT_PROCESSOR == 'amazon':
return_url = settings.BASE_URL + reverse('AmazonPaymentReturn')
else:
return_url = None
if campaign_id:
campaign = Campaign.objects.get(id=int(campaign_id))
t, url = p.authorize('USD', TARGET_TYPE_CAMPAIGN, amount, campaign=campaign, list=None, user=None)
t, url = p.authorize('USD', TARGET_TYPE_CAMPAIGN, amount, campaign=campaign, return_url=return_url, list=None, user=None)
else:
t, url = p.authorize('USD', TARGET_TYPE_NONE, amount, campaign=None, list=None, user=None)
t, url = p.authorize('USD', TARGET_TYPE_NONE, amount, campaign=None, return_url=return_url, list=None, user=None)
if url:
logger.info("testAuthorize: " + url)
@ -309,12 +315,7 @@ def paypalIPN(request):
logger.info(str(request.POST))
return HttpResponse("ipn")
def amazonPaymentReturn(request):
# pick up all get and post parameters and display
output = "payment complete"
output += request.method + "\n" + str(request.REQUEST.items())
return HttpResponse(output)
def paymentcomplete(request):
# pick up all get and post parameters and display