Adding amazon FPS return view, execute and preapproval support
parent
125582eebd
commit
d370091db7
|
@ -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"
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue