Merge branch 'fps' of github.com:Gluejar/regluit into ry

pull/1/head
Raymond Yee 2012-05-07 16:50:00 -07:00
commit b06a1e218a
5 changed files with 151 additions and 19 deletions

View File

@ -49,7 +49,7 @@ from regluit.frontend.forms import EbookForm, CustomPremiumForm, EditManagersFor
from regluit.payment.manager import PaymentManager
from regluit.payment.models import Transaction
from regluit.payment.parameters import TARGET_TYPE_CAMPAIGN, TARGET_TYPE_DONATION, PAYMENT_TYPE_AUTHORIZATION
from regluit.payment.parameters import TRANSACTION_STATUS_ACTIVE, TRANSACTION_STATUS_COMPLETE_PRIMARY, TRANSACTION_STATUS_CANCELED, TRANSACTION_STATUS_ERROR, TRANSACTION_STATUS_FAILED, TRANSACTION_STATUS_INCOMPLETE
from regluit.payment.parameters import TRANSACTION_STATUS_ACTIVE, TRANSACTION_STATUS_COMPLETE, TRANSACTION_STATUS_CANCELED, TRANSACTION_STATUS_ERROR, TRANSACTION_STATUS_FAILED, TRANSACTION_STATUS_INCOMPLETE
from regluit.payment.paypal import Preapproval
from regluit.core import goodreads
from tastypie.models import ApiKey
@ -938,7 +938,7 @@ def campaign_admin(request):
# show all Campaigns with Transactions that are COMPLETED
campaigns_with_completed_transactions = models.Campaign.objects.filter(transaction__status=TRANSACTION_STATUS_COMPLETE_PRIMARY)
campaigns_with_completed_transactions = models.Campaign.objects.filter(transaction__status=TRANSACTION_STATUS_COMPLETE)
# show Campaigns with Transactions that are CANCELED

View File

@ -127,7 +127,7 @@ def ProcessIPN(request):
if status == AMAZON_IPN_STATUS_SUCCESS:
transaction.status = TRANSACTION_STATUS_COMPLETE_PRIMARY
transaction.status = TRANSACTION_STATUS_COMPLETE
elif status == AMAZON_IPN_STATUS_PENDING:
@ -154,7 +154,7 @@ def ProcessIPN(request):
elif operation == AMAZON_OPERATION_TYPE_CANCEL:
if status == AMAZON_IPN_STATUS_SUCCESS:
transaction.status = TRANSACTION_STATUS_COMPLETE_PRIMARY
transaction.status = TRANSACTION_STATUS_COMPLETE
else:
transaction.status = TRANSACTION_STATUS_ERROR
@ -542,7 +542,15 @@ class Finish(AmazonRequest):
self.errorMessage = "Error: Server Error"
class PaymentDetails(AmazonRequest):
'''
Get details about executed PAY operation
This api must set the following class variables to work with the code in manager.py
status - one of the global transaction status codes
transactions -- Not supported for amazon, used by paypal
'''
def __init__(self, transaction=None):
try:
@ -588,7 +596,7 @@ class PaymentDetails(AmazonRequest):
# that information
#
if transaction.status != TRANSACTION_STATUS_REFUNDED:
self.status = TRANSACTION_STATUS_COMPLETE_PRIMARY
self.status = TRANSACTION_STATUS_COMPLETE
else:
self.status = TRANSACTION_STATUS_REFUNDED

View File

@ -4,6 +4,7 @@ from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.conf import settings
from regluit.payment.parameters import *
from regluit.payment.paypal import IPN_SENDER_STATUS_COMPLETED
if settings.PAYMENT_PROCESSOR == 'paypal':
from regluit.payment.paypal import Pay, Finish, Preapproval, ProcessIPN, CancelPreapproval, PaymentDetails, PreapprovalDetails, RefundPayment
@ -11,7 +12,6 @@ if settings.PAYMENT_PROCESSOR == 'paypal':
elif settings.PAYMENT_PROCESSOR == 'amazon':
from regluit.payment.amazon import Pay, Execute, Finish, Preapproval, ProcessIPN, CancelPreapproval, PaymentDetails, PreapprovalDetails, RefundPayment
import uuid
import traceback
from regluit.utils.localdatetime import now
@ -62,6 +62,7 @@ class PaymentManager( object ):
if t.status != p.status:
preapproval_status["status"] = {'ours':t.status, 'theirs':p.status}
t.status = p.status
t.local_status = p.local_status
t.save()
# check the currency code
@ -213,7 +214,7 @@ class PaymentManager( object ):
if pledged:
pledged_list = transaction_list.filter(type=PAYMENT_TYPE_INSTANT,
status=TRANSACTION_STATUS_COMPLETE_PRIMARY)
status=TRANSACTION_STATUS_COMPLETE)
else:
pledged_list = []
@ -233,7 +234,7 @@ class PaymentManager( object ):
if completed:
completed_list = transaction_list.filter(type=PAYMENT_TYPE_AUTHORIZATION,
status=TRANSACTION_STATUS_COMPLETE_PRIMARY)
status=TRANSACTION_STATUS_COMPLETE)
else:
completed_list = []
@ -245,7 +246,10 @@ class PaymentManager( object ):
for t in pledged_list:
for r in t.receiver_set.all():
if r.status == TRANSACTION_STATUS_COMPLETED:
#
# Currently receivers are only used for paypal, so keep the paypal status code here
#
if r.status == IPN_SENDER_STATUS_COMPLETED:
# or IPN_SENDER_STATUS_COMPLETED
# individual senders may not have been paid due to errors, and disputes/chargebacks only appear here
pledged_amount += r.amount
@ -337,7 +341,9 @@ class PaymentManager( object ):
transactions = Transaction.objects.filter(campaign=campaign, status=TRANSACTION_STATUS_ACTIVE)
for t in transactions:
#
# Currently receivers are only used for paypal, so it is OK to leave the paypal info here
#
receiver_list = [{'email':settings.PAYPAL_GLUEJAR_EMAIL, 'amount':t.amount},
{'email':campaign.paypal_receiver, 'amount':D(t.amount) * (D('1.00') - D(str(settings.GLUEJAR_COMMISSION)))}]
@ -356,6 +362,7 @@ class PaymentManager( object ):
attempts to execute all remaining payment to non-primary receivers
This is currently only supported for paypal
return value: returns a list of transactions with the status of each receiver/transaction updated
@ -696,7 +703,7 @@ class PaymentManager( object ):
# First check if a payment has been made. It is possible that some of the receivers may be incomplete
# We need to verify that the refund API will cancel these
if transaction.status != TRANSACTION_STATUS_COMPLETE_PRIMARY:
if transaction.status != TRANSACTION_STATUS_COMPLETE:
logger.info("Refund Transaction failed, invalid transaction status")
return False

View File

@ -12,17 +12,35 @@ TARGET_TYPE_CAMPAIGN = 1
TARGET_TYPE_LIST = 2
TARGET_TYPE_DONATION = 3
# The default status for a transaction that is newly created
TRANSACTION_STATUS_NONE = 'None'
# Indicates a transaction has been sent to the co-branded API
TRANSACTION_STATUS_CREATED = 'Created'
# A general complete code to indicate payment is comlete to all receivers
TRANSACTION_STATUS_COMPLETE = 'Complete'
# A general pending code that means in process
TRANSACTION_STATUS_PENDING = 'Pending'
TRANSACTION_STATUS_COMPLETE_PRIMARY = 'Complete Primary'
TRANSACTION_STATUS_COMPLETE_SECONDARY = 'Complete Secondary'
# Indicates a preapproval is active
TRANSACTION_STATUS_ACTIVE = 'Active'
# Only used in paypal at the moment, indicates payment was made to only 1 of multiple receivers
TRANSACTION_STATUS_INCOMPLETE = 'Incomplete'
# A general error code, see provider specific info for more detils
TRANSACTION_STATUS_ERROR = 'Error'
# A preapproval was canceled
TRANSACTION_STATUS_CANCELED = 'Canceled'
# Money that was transfered was refunded, either through a reversal or manual refund
TRANSACTION_STATUS_REFUNDED = 'Refunded'
# The transaction was refused/denied
TRANSACTION_STATUS_FAILED = 'Failed'
# these two following parameters are probably extraneous since I think we will compute dynamically where to return each time.

View File

@ -105,6 +105,74 @@ IPN_REASON_CODE_CHARGEBACK_SETTLEMENT = 'Chargeback Settlement'
IPN_REASON_CODE_ADMIN_REVERSAL = 'Admin reversal'
IPN_REASON_CODE_REFUND = 'Refund'
def PaypalStatusToGlobalStatus(status):
'''
This represents the default mapping of paypal status codes to global status codes
There are cases where this mapping will not apply and the individual API calls must do
additional processing
'''
if status == IPN_PAY_STATUS_CREATED:
return TRANSACTION_STATUS_CREATED
elif status == IPN_PAY_STATUS_COMPLETED:
return TRANSACTION_STATUS_COMPLETE
elif status == IPN_PAY_STATUS_INCOMPLETE:
return TRANSACTION_STATUS_INCOMPLETE
elif status == IPN_PAY_STATUS_ERROR:
return TRANSACTION_STATUS_ERROR
elif status == IPN_PAY_STATUS_REVERSALERROR:
return TRANSACTION_STATUS_ERROR
elif status == IPN_PAY_STATUS_PROCESSING:
return TRANSACTION_STATUS_PENDING
elif status == IPN_PAY_STATUS_PENDING:
return TRANSACTION_STATUS_PENDING
elif status == IPN_PREAPPROVAL_STATUS_ACTIVE:
return TRANSACTION_STATUS_ACTIVE
elif status == IPN_PREAPPROVAL_STATUS_CANCELED:
return TRANSACTION_STATUS_CANCELED
elif status == IPN_PREAPPROVAL_STATUS_DEACTIVED:
return TRANSACTION_STATUS_CANCELED
elif status == IPN_SENDER_STATUS_COMPLETED:
return TRANSACTION_STATUS_COMPLETE
elif status == IPN_SENDER_STATUS_PENDING:
return TRANSACTION_STATUS_CPENDING
elif status == IPN_SENDER_STATUS_CREATED:
return TRANSACTION_STATUS_CREATED
elif status == IPN_SENDER_STATUS_PARTIALLY_REFUNDED:
return TRANSACTION_STATUS_REFUNDED
elif status == IPN_SENDER_STATUS_DENIED:
return TRANSACTION_STATUS_FAILED
elif status == IPN_SENDER_STATUS_PROCESSING:
return TRANSACTION_STATUS_PENDING
elif status == IPN_SENDER_STATUS_REVERSED:
return TRANSACTION_STATUS_REFUNDED
elif status == IPN_SENDER_STATUS_REFUNDED:
return TRANSACTION_STATUS_REFUNDED
elif status == IPN_SENDER_STATUS_FAILED:
return TRANSACTION_STATUS_FAILED
else:
return TRANSACTION_STATUS_ERRROR
def ProcessIPN(request):
'''
processIPN
@ -129,8 +197,9 @@ def ProcessIPN(request):
uniqueID = ipn.uniqueID()
t = Transaction.objects.get(secret=uniqueID)
# The status is always one of the IPN_PAY_STATUS codes defined in paypal.py
# The local_status is always one of the IPN_PAY_STATUS codes defined in paypal.py
t.local_status = ipn.status
t.status = PaypalStatusToGlobalStatus(ipn.status)
for item in ipn.transactions:
@ -163,6 +232,7 @@ def ProcessIPN(request):
# The status is always one of the IPN_PAY_STATUS codes defined in paypal.py
t.local_status = ipn.status
t.status = PaypalStatusToGlobalStatus(ipn.status)
# Reason code indicates more details of the adjustment type
t.reason = ipn.reason_code
@ -193,6 +263,7 @@ def ProcessIPN(request):
# The status is always one of the IPN_PREAPPROVAL_STATUS codes defined in paypal.py
t.local_status = ipn.status
t.status = PaypalStatusToGlobalStatus(ipn.status)
# capture whether the transaction has been approved
t.approved = ipn.approved
@ -400,7 +471,7 @@ class Pay( PaypalEnvelopeRequest ):
'returnUrl': return_url,
'cancelUrl': cancel_url,
'requestEnvelope': { 'errorLanguage': 'en_US' },
'ipnNotificationUrl': settings.BASE_URL + reverse('PayPalIPN'),
'ipnNotificationUrl': settings.BASE_URL + reverse('HandleIPN'),
'feesPayer': feesPayer,
'trackingId': transaction.secret
}
@ -519,6 +590,19 @@ class Finish(PaypalEnvelopeRequest):
class PaymentDetails(PaypalEnvelopeRequest):
'''
Get details about executed PAY operation
This api must set the following class variables to work with the code in manager.py
status - one of the global transaction status codes
transactions -- A list of all receiver transactions associated with this payment
status - the status of the receiver transaction
txn_id - the id of the receiver transaction
'''
def __init__(self, transaction=None):
try:
@ -558,7 +642,7 @@ class PaymentDetails(PaypalEnvelopeRequest):
logger.info(self.response)
self.local_status = self.response.get("status", None)
self.status = self.response.get("status", None)
self.status = PaypalStatusToGlobalStatus(self.local_status)
self.trackingId = self.response.get("trackingId", None)
self.feesPayer = self.response.get("feesPayer", None)
@ -730,7 +814,7 @@ class Preapproval( PaypalEnvelopeRequest ):
'returnUrl': return_url,
'cancelUrl': cancel_url,
'requestEnvelope': { 'errorLanguage': 'en_US' },
'ipnNotificationUrl': settings.BASE_URL + reverse('PayPalIPN')
'ipnNotificationUrl': settings.BASE_URL + reverse('HandleIPN')
}
# Is ipnNotificationUrl being computed properly
@ -767,6 +851,19 @@ class Preapproval( PaypalEnvelopeRequest ):
class PreapprovalDetails(PaypalEnvelopeRequest):
'''
Get details about an authorized token
This api must set 4 different class variables to work with the code in manager.py
status - one of the global transaction status codes
approved - boolean value
currency -
amount -
'''
def __init__(self, transaction):
try:
@ -803,7 +900,9 @@ class PreapprovalDetails(PaypalEnvelopeRequest):
self.response = json.loads( self.raw_response )
logger.info(self.response)
self.status = self.response.get("status", None)
self.local_status = self.response.get("status", None)
self.status = PaypalStatusToGlobalStatus(self.local_status)
self.amount = self.response.get("maxTotalAmountOfAllPayments", None)
self.currency = self.response.get("currencyCode", None)