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.shortcuts import render_to_response
from django.template import RequestContext from django.template import RequestContext
from boto.fps.connection import FPSConnection from boto.fps.connection import FPSConnection
from django.http import HttpResponse, HttpRequest, HttpResponseRedirect, HttpResponseBadRequest
from datetime import timedelta from datetime import timedelta
from regluit.utils.localdatetime import now, zuluformat from regluit.utils.localdatetime import now, zuluformat
import dateutil import dateutil
@ -29,10 +29,108 @@ import commands
import smtplib import smtplib
import urlparse import urlparse
import decimal import decimal
import sys import time
logger = logging.getLogger(__name__) 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: class AmazonRequest:
''' '''
Handles common information that is processed from the response envelope of the amazon request. Handles common information that is processed from the response envelope of the amazon request.
@ -43,12 +141,25 @@ class AmazonRequest:
response = None response = None
raw_response = None raw_response = None
errorMessage = None errorMessage = None
status = None
url = None url = None
def ack( self ): def ack( self ):
return None return None
def success(self): 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: if self.errorMessage:
return False return False
else: else:
@ -71,6 +182,11 @@ class AmazonRequest:
return self.errorMessage return self.errorMessage
def envelope(self): def envelope(self):
# The envelope is used to store info about this request
if self.response:
return str(self.response)
else:
return None return None
def correlation_id(self): def correlation_id(self):
@ -81,7 +197,8 @@ class AmazonRequest:
class Pay( AmazonRequest ): 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: try:
@ -94,22 +211,29 @@ class Pay( AmazonRequest ):
receiver_list = [] receiver_list = []
receivers = transaction.receiver_set.all() receivers = transaction.receiver_set.all()
if len(receivers) == 0: if not amount:
raise Exception
# by setting primary_string of the first receiver to 'true', we are doing a Chained payment # by setting primary_string of the first receiver to 'true', we are doing a Chained payment
total_amount = 0 amount = 0
for r in receivers: for r in receivers:
total_amount += r.amount amount += r.amount
logger.info(receiver_list) logger.info(receiver_list)
# Data fields for amazon # 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 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 print "Amazon PURCHASE url was: %s" % self.url
except: except:
@ -134,3 +258,45 @@ class Pay( AmazonRequest ):
def embedded_url(self): def embedded_url(self):
return None 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 * from regluit.payment.parameters import *
if settings.PAYMENT_PROCESSOR == 'paypal': if settings.PAYMENT_PROCESSOR == 'paypal':
from regluit.payment.paypal import Pay from regluit.payment.paypal import Pay, Execute, Preapproval
elif settings.PAYMENT_PROCESSOR == 'amazon': 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 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_PAY_STATUS_COMPLETED, CancelPreapproval, PaymentDetails, PreapprovalDetails, IPN_SENDER_STATUS_COMPLETED, IPN_TXN_STATUS_COMPLETED
from regluit.payment.paypal import RefundPayment from regluit.payment.paypal import RefundPayment
import uuid import uuid
import traceback import traceback

View File

@ -10,6 +10,11 @@ fps_recur_obj = get_integration("fps")
urlpatterns = patterns( urlpatterns = patterns(
"regluit.payment.views", "regluit.payment.views",
url(r"^paypalipn", "paypalIPN", name="PayPalIPN"), url(r"^paypalipn", "paypalIPN", name="PayPalIPN"),
)
# Amazon payment URLs
urlpatterns += patterns(
"regluit.payment.amazon",
url(r"^amazonpaymentreturn", "amazonPaymentReturn", name="AmazonPaymentReturn"), url(r"^amazonpaymentreturn", "amazonPaymentReturn", name="AmazonPaymentReturn"),
) )

View File

@ -8,7 +8,7 @@ from django.shortcuts import render_to_response
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.sites.models import RequestSite from django.contrib.sites.models import RequestSite
from regluit.payment.parameters import * 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.views.decorators.csrf import csrf_exempt
from django.test.utils import setup_test_environment from django.test.utils import setup_test_environment
from django.template import RequestContext from django.template import RequestContext
@ -114,12 +114,18 @@ def testAuthorize(request):
receiver_list = [{'email': TEST_RECEIVERS[0], 'amount':20.00}, receiver_list = [{'email': TEST_RECEIVERS[0], 'amount':20.00},
{'email': TEST_RECEIVERS[1], 'amount':10.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: if campaign_id:
campaign = Campaign.objects.get(id=int(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: 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: if url:
logger.info("testAuthorize: " + url) logger.info("testAuthorize: " + url)
@ -310,11 +316,6 @@ def paypalIPN(request):
logger.info(str(request.POST)) logger.info(str(request.POST))
return HttpResponse("ipn") 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): def paymentcomplete(request):
# pick up all get and post parameters and display # pick up all get and post parameters and display