To get credit module working again, had to move some methods into an object that inherits from a base class
So now all payment processor specific methods are on a Processor object,pull/1/head
parent
7a1cf969ca
commit
73910ae8a0
|
@ -8,18 +8,6 @@ import datetime
|
|||
import time
|
||||
|
||||
|
||||
def requires_explicit_preapprovals():
|
||||
"""a function that returns for the given payment processor"""
|
||||
return False
|
||||
|
||||
def make_account(user, token):
|
||||
"""template function for return a payment.Account corresponding to the payment system"""
|
||||
return None
|
||||
|
||||
def ProcessIPN(request):
|
||||
return HttpResponseForbidden()
|
||||
|
||||
|
||||
class BasePaymentRequest:
|
||||
'''
|
||||
Handles common information incident to payment processing
|
||||
|
@ -71,120 +59,131 @@ class BasePaymentRequest:
|
|||
def timestamp(self):
|
||||
return str(datetime.datetime.now())
|
||||
|
||||
class Processor:
|
||||
"""a function that returns for the given payment processor"""
|
||||
requires_explicit_preapprovals=False
|
||||
|
||||
class Pay( BasePaymentRequest ):
|
||||
|
||||
'''
|
||||
The pay function generates a redirect URL to approve the transaction
|
||||
'''
|
||||
def make_account(self, user, token):
|
||||
"""template function for return a payment.Account corresponding to the payment system"""
|
||||
return None
|
||||
|
||||
def __init__( self, transaction, return_url=None, amount=None, paymentReason=""):
|
||||
self.transaction=transaction
|
||||
|
||||
def api(self):
|
||||
return "null api"
|
||||
|
||||
def exec_status( self ):
|
||||
return None
|
||||
|
||||
def amount( self ):
|
||||
return None
|
||||
|
||||
def key( self ):
|
||||
return None
|
||||
|
||||
def next_url( self ):
|
||||
return self.url
|
||||
|
||||
class Preapproval(Pay):
|
||||
|
||||
def __init__( self, transaction, amount, expiry=None, return_url=None, paymentReason=""):
|
||||
|
||||
# set the expiration date for the preapproval if not passed in. This is what the paypal library does
|
||||
now_val = now()
|
||||
if expiry is None:
|
||||
expiry = now_val + timedelta( days=settings.PREAPPROVAL_PERIOD )
|
||||
transaction.date_authorized = now_val
|
||||
transaction.date_expired = expiry
|
||||
transaction.save()
|
||||
|
||||
# Call into our parent class
|
||||
Pay.__init__(self, transaction, return_url=return_url, amount=amount, paymentReason=paymentReason)
|
||||
|
||||
|
||||
class Execute(BasePaymentRequest):
|
||||
|
||||
'''
|
||||
The Execute function sends an existing token(generated via the URL from the pay operation), and collects
|
||||
the money.
|
||||
'''
|
||||
|
||||
def __init__(self, transaction=None):
|
||||
self.transaction = transaction
|
||||
|
||||
def api(self):
|
||||
return "Base Pay"
|
||||
|
||||
def key(self):
|
||||
# IN paypal land, our key is updated from a preapproval to a pay key here, just return the existing key
|
||||
return self.transaction.pay_key
|
||||
|
||||
|
||||
|
||||
class Finish(BasePaymentRequest):
|
||||
'''
|
||||
The Finish function handles the secondary receiver in a chained payment.
|
||||
'''
|
||||
def __init__(self, transaction):
|
||||
def ProcessIPN(self, request):
|
||||
return HttpResponseForbidden()
|
||||
|
||||
print "Finish"
|
||||
|
||||
|
||||
class PaymentDetails(BasePaymentRequest):
|
||||
'''
|
||||
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):
|
||||
self.transaction = transaction
|
||||
|
||||
class Pay( BasePaymentRequest ):
|
||||
|
||||
'''
|
||||
The pay function generates a redirect URL to approve the transaction
|
||||
'''
|
||||
|
||||
def __init__( self, transaction, return_url=None, amount=None, paymentReason=""):
|
||||
self.transaction=transaction
|
||||
|
||||
|
||||
|
||||
class CancelPreapproval(BasePaymentRequest):
|
||||
'''
|
||||
Cancels an exisiting token.
|
||||
'''
|
||||
def api(self):
|
||||
return "null api"
|
||||
|
||||
def exec_status( self ):
|
||||
return None
|
||||
|
||||
def amount( self ):
|
||||
return None
|
||||
|
||||
def key( self ):
|
||||
return None
|
||||
|
||||
def __init__(self, transaction):
|
||||
self.transaction = transaction
|
||||
|
||||
|
||||
class RefundPayment(BasePaymentRequest):
|
||||
def next_url( self ):
|
||||
return self.url
|
||||
|
||||
class Preapproval(Pay):
|
||||
|
||||
def __init__( self, transaction, amount, expiry=None, return_url=None, paymentReason=""):
|
||||
|
||||
# set the expiration date for the preapproval if not passed in. This is what the paypal library does
|
||||
now_val = now()
|
||||
if expiry is None:
|
||||
expiry = now_val + timedelta( days=settings.PREAPPROVAL_PERIOD )
|
||||
transaction.date_authorized = now_val
|
||||
transaction.date_expired = expiry
|
||||
transaction.save()
|
||||
|
||||
# Call into our parent class
|
||||
Pay.__init__(self, transaction, return_url=return_url, amount=amount, paymentReason=paymentReason)
|
||||
|
||||
|
||||
class Execute(BasePaymentRequest):
|
||||
|
||||
'''
|
||||
The Execute function sends an existing token(generated via the URL from the pay operation), and collects
|
||||
the money.
|
||||
'''
|
||||
|
||||
def __init__(self, transaction=None):
|
||||
self.transaction = transaction
|
||||
|
||||
def api(self):
|
||||
return "Base Pay"
|
||||
|
||||
def key(self):
|
||||
# IN paypal land, our key is updated from a preapproval to a pay key here, just return the existing key
|
||||
return self.transaction.pay_key
|
||||
|
||||
|
||||
|
||||
def __init__(self, transaction):
|
||||
self.transaction = transaction
|
||||
class Finish(BasePaymentRequest):
|
||||
'''
|
||||
The Finish function handles the secondary receiver in a chained payment.
|
||||
'''
|
||||
def __init__(self, transaction):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class PreapprovalDetails(BasePaymentRequest):
|
||||
'''
|
||||
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 - not used in this API, but we can get some more info via other APIs - TODO
|
||||
amount - not used in this API, but we can get some more info via other APIs - TODO
|
||||
|
||||
'''
|
||||
def __init__(self, transaction=None):
|
||||
self.transaction = transaction
|
||||
|
||||
print "Finish"
|
||||
|
||||
|
||||
class PaymentDetails(BasePaymentRequest):
|
||||
'''
|
||||
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):
|
||||
self.transaction = transaction
|
||||
|
||||
|
||||
|
||||
class CancelPreapproval(BasePaymentRequest):
|
||||
'''
|
||||
Cancels an exisiting token.
|
||||
'''
|
||||
|
||||
def __init__(self, transaction):
|
||||
self.transaction = transaction
|
||||
|
||||
|
||||
class RefundPayment(BasePaymentRequest):
|
||||
|
||||
def __init__(self, transaction):
|
||||
self.transaction = transaction
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class PreapprovalDetails(BasePaymentRequest):
|
||||
'''
|
||||
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 - not used in this API, but we can get some more info via other APIs - TODO
|
||||
amount - not used in this API, but we can get some more info via other APIs - TODO
|
||||
|
||||
'''
|
||||
def __init__(self, transaction=None):
|
||||
self.transaction = transaction
|
||||
|
|
@ -4,6 +4,7 @@ from django.contrib.auth.models import User
|
|||
from django.conf import settings
|
||||
|
||||
from regluit.payment.parameters import *
|
||||
from regluit.payment import baseprocessor
|
||||
from regluit.payment.baseprocessor import BasePaymentRequest
|
||||
|
||||
|
||||
|
@ -28,28 +29,29 @@ def credit_transaction(t,user,amount):
|
|||
user.credit.add_to_pledged(pledge_amount)
|
||||
t.set_credit_approved(pledge_amount)
|
||||
|
||||
class CancelPreapproval(BasePaymentRequest):
|
||||
'''
|
||||
Cancels an exisiting token.
|
||||
'''
|
||||
class Processor(baseprocessor.Processor):
|
||||
class CancelPreapproval(BasePaymentRequest):
|
||||
'''
|
||||
Cancels an exisiting token.
|
||||
'''
|
||||
|
||||
def __init__(self, transaction):
|
||||
self.transaction = transaction
|
||||
if transaction.user.credit.add_to_pledged(-transaction.amount):
|
||||
#success
|
||||
transaction.status=TRANSACTION_STATUS_CANCELED
|
||||
transaction.save()
|
||||
else:
|
||||
self.errorMessage="couldn't cancel the transaction"
|
||||
self.status = 'Credit Cancel Failure'
|
||||
|
||||
def __init__(self, transaction):
|
||||
self.transaction = transaction
|
||||
if transaction.user.credit.add_to_pledged(-transaction.amount):
|
||||
#success
|
||||
transaction.status=TRANSACTION_STATUS_CANCELED
|
||||
transaction.save()
|
||||
else:
|
||||
self.errorMessage="couldn't cancel the transaction"
|
||||
self.status = 'Credit Cancel Failure'
|
||||
|
||||
class PreapprovalDetails(BasePaymentRequest):
|
||||
status = None
|
||||
approved = None
|
||||
currency = None
|
||||
amount = None
|
||||
def __init__(self, transaction):
|
||||
self.status = transaction.status
|
||||
self.approved = transaction.approved
|
||||
self.currency = transaction.currency
|
||||
self.amount = transaction.amount
|
||||
class PreapprovalDetails(BasePaymentRequest):
|
||||
status = None
|
||||
approved = None
|
||||
currency = None
|
||||
amount = None
|
||||
def __init__(self, transaction):
|
||||
self.status = transaction.status
|
||||
self.approved = transaction.approved
|
||||
self.currency = transaction.currency
|
||||
self.amount = transaction.amount
|
||||
|
|
|
@ -6,8 +6,6 @@ from regluit.payment.parameters import *
|
|||
from regluit.payment.signals import transaction_charged, pledge_modified, pledge_created
|
||||
from regluit.payment import credit
|
||||
|
||||
from regluit.payment.baseprocessor import Pay, Finish, Preapproval, ProcessIPN, CancelPreapproval, PaymentDetails, PreapprovalDetails, RefundPayment
|
||||
|
||||
import uuid
|
||||
import traceback
|
||||
from regluit.utils.localdatetime import now
|
||||
|
@ -39,14 +37,13 @@ class PaymentManager( object ):
|
|||
|
||||
# Forward to our payment processor
|
||||
mod = __import__("regluit.payment." + module, fromlist=[str(module)])
|
||||
method = getattr(mod, "ProcessIPN")
|
||||
method = getattr(mod.Processor, "ProcessIPN")
|
||||
return method(request)
|
||||
|
||||
def update_preapproval(self, transaction):
|
||||
"""Update a transaction to hold the data from a PreapprovalDetails on that transaction"""
|
||||
t = transaction
|
||||
method = getattr(transaction.get_payment_class(), "PreapprovalDetails")
|
||||
p = method(t)
|
||||
p = transaction.get_payment_class().PreapprovalDetails(t)
|
||||
|
||||
preapproval_status = {'id':t.id, 'key':t.preapproval_key}
|
||||
|
||||
|
@ -98,8 +95,7 @@ class PaymentManager( object ):
|
|||
t = transaction
|
||||
payment_status = {'id':t.id}
|
||||
|
||||
method = getattr(transaction.get_payment_class(), "PaymentDetails")
|
||||
p = method(t)
|
||||
p = transaction.get_payment_class().PaymentDetails(t)
|
||||
|
||||
if p.error() or not p.success():
|
||||
logger.info("Error retrieving payment details for transaction %d" % t.id)
|
||||
|
@ -413,8 +409,7 @@ class PaymentManager( object ):
|
|||
transaction.date_executed = now()
|
||||
transaction.save()
|
||||
|
||||
method = getattr(transaction.get_payment_class(), "Finish")
|
||||
p = method(transaction)
|
||||
p = transaction.get_payment_class().Finish(transaction)
|
||||
|
||||
# Create a response for this
|
||||
envelope = p.envelope()
|
||||
|
@ -468,8 +463,7 @@ class PaymentManager( object ):
|
|||
transaction.date_payment = now()
|
||||
transaction.save()
|
||||
|
||||
method = getattr(transaction.get_payment_class(), "Execute")
|
||||
p = method(transaction)
|
||||
p = transaction.get_payment_class().Execute(transaction)
|
||||
|
||||
# Create a response for this
|
||||
envelope = p.envelope()
|
||||
|
@ -509,12 +503,11 @@ class PaymentManager( object ):
|
|||
'''
|
||||
|
||||
# does this transaction explicity require preapprovals?
|
||||
requires_explicit_preapprovals = getattr(transaction.get_payment_class(), "requires_explicit_preapprovals")
|
||||
requires_explicit_preapprovals = transaction.get_payment_class().requires_explicit_preapprovals
|
||||
|
||||
if requires_explicit_preapprovals():
|
||||
if requires_explicit_preapprovals:
|
||||
|
||||
method = getattr(transaction.get_payment_class(), "CancelPreapproval")
|
||||
p = method(transaction)
|
||||
p = transaction.get_payment_class().CancelPreapproval(transaction)
|
||||
|
||||
# Create a response for this
|
||||
envelope = p.envelope()
|
||||
|
@ -575,8 +568,7 @@ class PaymentManager( object ):
|
|||
urllib.urlencode({'tid':transaction.id}))
|
||||
return_url = urlparse.urljoin(settings.BASE_URL, return_path)
|
||||
|
||||
method = getattr(transaction.get_payment_class(), "Preapproval")
|
||||
p = method(transaction, transaction.amount, expiry, return_url=return_url, paymentReason=paymentReason)
|
||||
p = transaction.get_payment_class().Preapproval(transaction, transaction.amount, expiry, return_url=return_url, paymentReason=paymentReason)
|
||||
|
||||
# Create a response for this
|
||||
envelope = p.envelope()
|
||||
|
@ -744,7 +736,7 @@ class PaymentManager( object ):
|
|||
|
||||
# does this transaction explicity require preapprovals?
|
||||
|
||||
requires_explicit_preapprovals = getattr(transaction.get_payment_class(), "requires_explicit_preapprovals")
|
||||
requires_explicit_preapprovals = transaction.get_payment_class().requires_explicit_preapprovals
|
||||
|
||||
if transaction.type != PAYMENT_TYPE_AUTHORIZATION:
|
||||
logger.info("Error, attempt to modify an invalid transaction type")
|
||||
|
@ -785,7 +777,7 @@ class PaymentManager( object ):
|
|||
credit.CancelPreapproval(transaction)
|
||||
return t, reverse('fund_pledge', args=[t.id])
|
||||
|
||||
elif requires_explicit_preapprovals() and (amount > transaction.max_amount or expiry != transaction.date_expired):
|
||||
elif requires_explicit_preapprovals and (amount > transaction.max_amount or expiry != transaction.date_expired):
|
||||
|
||||
# set the expiry date based on the campaign deadline
|
||||
expiry = transaction.campaign.deadline + timedelta( days=settings.PREAPPROVAL_PERIOD_AFTER_CAMPAIGN )
|
||||
|
@ -828,7 +820,7 @@ class PaymentManager( object ):
|
|||
# corresponding notification to the user? that would go here.
|
||||
return False, None
|
||||
|
||||
elif (requires_explicit_preapprovals() and amount <= transaction.max_amount) or (not requires_explicit_preapprovals()):
|
||||
elif (requires_explicit_preapprovals and amount <= transaction.max_amount) or (not requires_explicit_preapprovals):
|
||||
# Update transaction but leave the preapproval alone
|
||||
transaction.amount = amount
|
||||
transaction.set_pledge_extra(pledge_extra)
|
||||
|
@ -861,8 +853,7 @@ class PaymentManager( object ):
|
|||
logger.info("Refund Transaction failed, invalid transaction status")
|
||||
return False
|
||||
|
||||
method = getattr(transaction.get_payment_class(), "RefundPayment")
|
||||
p = method(transaction)
|
||||
p = transaction.get_payment_class().RefundPayment(transaction)
|
||||
|
||||
# Create a response for this
|
||||
envelope = p.envelope()
|
||||
|
@ -920,8 +911,7 @@ class PaymentManager( object ):
|
|||
t.date_payment=now()
|
||||
t.execution=EXECUTE_TYPE_CHAINED_INSTANT
|
||||
t.type=PAYMENT_TYPE_INSTANT
|
||||
method = getattr(t.get_payment_class(), "Pay")
|
||||
p = method(t,return_url=return_url, nevermind_url=nevermind_url)
|
||||
p = t.get_payment_class().Pay(t,return_url=return_url, nevermind_url=nevermind_url)
|
||||
|
||||
# Create a response for this
|
||||
envelope = p.envelope()
|
||||
|
@ -954,8 +944,7 @@ class PaymentManager( object ):
|
|||
|
||||
"""delegate to a specific payment module the task of creating a payment account"""
|
||||
mod = __import__("regluit.payment." + host, fromlist=[host])
|
||||
method = getattr(mod, "make_account")
|
||||
return method(user, token)
|
||||
return mod.Processor().make_account(user, token)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -109,13 +109,13 @@ class Transaction(models.Model):
|
|||
|
||||
def get_payment_class(self):
|
||||
'''
|
||||
Returns the specific payment module that implements this transaction
|
||||
Returns the specific payment processor that implements this transaction
|
||||
'''
|
||||
if self.host == PAYMENT_HOST_NONE:
|
||||
return None
|
||||
else:
|
||||
mod = __import__("regluit.payment." + self.host, fromlist=[str(self.host)])
|
||||
return mod
|
||||
return mod.Processor()
|
||||
|
||||
def set_credit_approved(self, amount):
|
||||
self.amount=amount
|
||||
|
|
|
@ -265,155 +265,153 @@ class StripePaymentRequest(baseprocessor.BasePaymentRequest):
|
|||
"""so far there is no need to have a separate class here"""
|
||||
pass
|
||||
|
||||
def requires_explicit_preapprovals():
|
||||
"""a function that returns for the given payment processor"""
|
||||
return False
|
||||
|
||||
def make_account(user, token):
|
||||
"""returns a payment.models.Account based on stripe token and user"""
|
||||
class Processor(baseprocessor.Processor):
|
||||
|
||||
sc = StripeClient()
|
||||
|
||||
# create customer and charge id and then charge the customer
|
||||
customer = sc.create_customer(card=token, description=user.username,
|
||||
email=user.email)
|
||||
|
||||
account = Account(host = PAYMENT_HOST_STRIPE,
|
||||
account_id = customer.id,
|
||||
card_last4 = customer.active_card.last4,
|
||||
card_type = customer.active_card.type,
|
||||
card_exp_month = customer.active_card.exp_month,
|
||||
card_exp_year = customer.active_card.exp_year,
|
||||
card_fingerprint = customer.active_card.fingerprint,
|
||||
card_country = customer.active_card.country,
|
||||
user = user
|
||||
)
|
||||
|
||||
account.save()
|
||||
|
||||
return account
|
||||
|
||||
class Pay(StripePaymentRequest, baseprocessor.Pay):
|
||||
pass
|
||||
|
||||
class Preapproval(StripePaymentRequest, baseprocessor.Preapproval):
|
||||
|
||||
def __init__( self, transaction, amount, expiry=None, return_url=None, paymentReason=""):
|
||||
|
||||
# set the expiration date for the preapproval if not passed in. This is what the paypal library does
|
||||
|
||||
self.transaction = transaction
|
||||
|
||||
now_val = now()
|
||||
if expiry is None:
|
||||
expiry = now_val + timedelta( days=settings.PREAPPROVAL_PERIOD )
|
||||
transaction.date_authorized = now_val
|
||||
transaction.date_expired = expiry
|
||||
|
||||
sc = StripeClient()
|
||||
|
||||
# let's figure out what part of transaction can be used to store info
|
||||
# try placing charge id in transaction.pay_key
|
||||
# need to set amount
|
||||
# how does transaction.max_amount get set? -- coming from /pledge/xxx/ -> manager.process_transaction
|
||||
# max_amount is set -- but I don't think we need it for stripe
|
||||
|
||||
# ASSUMPTION: a user has any given moment one and only one active payment Account
|
||||
|
||||
if transaction.user.account_set.filter(date_deactivated__isnull=True).count() > 1:
|
||||
logger.warning("user {0} has more than one active payment account".format(transaction.user))
|
||||
elif transaction.user.account_set.filter(date_deactivated__isnull=True).count() == 0:
|
||||
logger.warning("user {0} has no active payment account".format(transaction.user))
|
||||
raise StripeError("user {0} has no active payment account".format(transaction.user))
|
||||
|
||||
account = transaction.user.account_set.filter(date_deactivated__isnull=True)[0]
|
||||
logger.info("user: {0} customer.id is {1}".format(transaction.user, account.account_id))
|
||||
|
||||
# settings to apply to transaction for TRANSACTION_STATUS_ACTIVE
|
||||
# should approved be set to False and wait for a webhook?
|
||||
transaction.approved = True
|
||||
transaction.type = PAYMENT_TYPE_AUTHORIZATION
|
||||
transaction.host = PAYMENT_HOST_STRIPE
|
||||
transaction.status = TRANSACTION_STATUS_ACTIVE
|
||||
|
||||
transaction.preapproval_key = account.account_id
|
||||
|
||||
transaction.currency = 'USD'
|
||||
transaction.amount = amount
|
||||
|
||||
transaction.save()
|
||||
|
||||
def key(self):
|
||||
return self.transaction.preapproval_key
|
||||
|
||||
def next_url(self):
|
||||
"""return None because no redirection to stripe is required"""
|
||||
return None
|
||||
|
||||
|
||||
class Execute(StripePaymentRequest):
|
||||
|
||||
'''
|
||||
The Execute function sends an existing token(generated via the URL from the pay operation), and collects
|
||||
the money.
|
||||
'''
|
||||
|
||||
def __init__(self, transaction=None):
|
||||
self.transaction = transaction
|
||||
|
||||
# execute transaction
|
||||
assert transaction.host == PAYMENT_HOST_STRIPE
|
||||
def make_account(self, user, token):
|
||||
"""returns a payment.models.Account based on stripe token and user"""
|
||||
|
||||
sc = StripeClient()
|
||||
|
||||
# look at transaction.preapproval_key
|
||||
# is it a customer or a token?
|
||||
|
||||
# BUGBUG: replace description with somethin more useful
|
||||
if transaction.preapproval_key.startswith('cus_'):
|
||||
charge = sc.create_charge(transaction.amount, customer=transaction.preapproval_key, description="${0} for test / retain cc".format(transaction.amount))
|
||||
elif transaction.preapproval_key.startswith('tok_'):
|
||||
charge = sc.create_charge(transaction.amount, card=transaction.preapproval_key, description="${0} for test / cc not retained".format(transaction.amount))
|
||||
|
||||
transaction.status = TRANSACTION_STATUS_COMPLETE
|
||||
transaction.pay_key = charge.id
|
||||
transaction.date_payment = now()
|
||||
transaction.save()
|
||||
# create customer and charge id and then charge the customer
|
||||
customer = sc.create_customer(card=token, description=user.username,
|
||||
email=user.email)
|
||||
|
||||
self.charge = charge
|
||||
|
||||
def api(self):
|
||||
return "Base Pay"
|
||||
account = Account(host = PAYMENT_HOST_STRIPE,
|
||||
account_id = customer.id,
|
||||
card_last4 = customer.active_card.last4,
|
||||
card_type = customer.active_card.type,
|
||||
card_exp_month = customer.active_card.exp_month,
|
||||
card_exp_year = customer.active_card.exp_year,
|
||||
card_fingerprint = customer.active_card.fingerprint,
|
||||
card_country = customer.active_card.country,
|
||||
user = user
|
||||
)
|
||||
|
||||
def key(self):
|
||||
# IN paypal land, our key is updated from a preapproval to a pay key here, just return the existing key
|
||||
return self.transaction.pay_key
|
||||
account.save()
|
||||
|
||||
return account
|
||||
|
||||
class Pay(StripePaymentRequest, baseprocessor.Processor.Pay):
|
||||
pass
|
||||
|
||||
class Preapproval(StripePaymentRequest, baseprocessor.Processor.Preapproval):
|
||||
|
||||
def __init__( self, transaction, amount, expiry=None, return_url=None, paymentReason=""):
|
||||
|
||||
# set the expiration date for the preapproval if not passed in. This is what the paypal library does
|
||||
|
||||
self.transaction = transaction
|
||||
|
||||
now_val = now()
|
||||
if expiry is None:
|
||||
expiry = now_val + timedelta( days=settings.PREAPPROVAL_PERIOD )
|
||||
transaction.date_authorized = now_val
|
||||
transaction.date_expired = expiry
|
||||
|
||||
sc = StripeClient()
|
||||
|
||||
# let's figure out what part of transaction can be used to store info
|
||||
# try placing charge id in transaction.pay_key
|
||||
# need to set amount
|
||||
# how does transaction.max_amount get set? -- coming from /pledge/xxx/ -> manager.process_transaction
|
||||
# max_amount is set -- but I don't think we need it for stripe
|
||||
|
||||
class PreapprovalDetails(StripePaymentRequest):
|
||||
'''
|
||||
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 - not used in this API, but we can get some more info via other APIs - TODO
|
||||
amount - not used in this API, but we can get some more info via other APIs - TODO
|
||||
|
||||
'''
|
||||
def __init__(self, transaction):
|
||||
|
||||
self.transaction = transaction
|
||||
self.status = self.transaction.status
|
||||
if self.status == TRANSACTION_STATUS_CANCELED:
|
||||
self.approved = False
|
||||
else:
|
||||
self.approved = True
|
||||
|
||||
# Set the other fields that are expected. We don't have values for these now, so just copy the transaction
|
||||
self.currency = transaction.currency
|
||||
self.amount = transaction.amount
|
||||
# ASSUMPTION: a user has any given moment one and only one active payment Account
|
||||
|
||||
if transaction.user.account_set.filter(date_deactivated__isnull=True).count() > 1:
|
||||
logger.warning("user {0} has more than one active payment account".format(transaction.user))
|
||||
elif transaction.user.account_set.filter(date_deactivated__isnull=True).count() == 0:
|
||||
logger.warning("user {0} has no active payment account".format(transaction.user))
|
||||
raise StripeError("user {0} has no active payment account".format(transaction.user))
|
||||
|
||||
account = transaction.user.account_set.filter(date_deactivated__isnull=True)[0]
|
||||
logger.info("user: {0} customer.id is {1}".format(transaction.user, account.account_id))
|
||||
|
||||
# settings to apply to transaction for TRANSACTION_STATUS_ACTIVE
|
||||
# should approved be set to False and wait for a webhook?
|
||||
transaction.approved = True
|
||||
transaction.type = PAYMENT_TYPE_AUTHORIZATION
|
||||
transaction.host = PAYMENT_HOST_STRIPE
|
||||
transaction.status = TRANSACTION_STATUS_ACTIVE
|
||||
|
||||
transaction.preapproval_key = account.account_id
|
||||
|
||||
transaction.currency = 'USD'
|
||||
transaction.amount = amount
|
||||
|
||||
transaction.save()
|
||||
|
||||
def key(self):
|
||||
return self.transaction.preapproval_key
|
||||
|
||||
def next_url(self):
|
||||
"""return None because no redirection to stripe is required"""
|
||||
return None
|
||||
|
||||
|
||||
class Execute(StripePaymentRequest):
|
||||
|
||||
'''
|
||||
The Execute function sends an existing token(generated via the URL from the pay operation), and collects
|
||||
the money.
|
||||
'''
|
||||
|
||||
def __init__(self, transaction=None):
|
||||
self.transaction = transaction
|
||||
|
||||
# execute transaction
|
||||
assert transaction.host == PAYMENT_HOST_STRIPE
|
||||
|
||||
sc = StripeClient()
|
||||
|
||||
# look at transaction.preapproval_key
|
||||
# is it a customer or a token?
|
||||
|
||||
# BUGBUG: replace description with somethin more useful
|
||||
if transaction.preapproval_key.startswith('cus_'):
|
||||
charge = sc.create_charge(transaction.amount, customer=transaction.preapproval_key, description="${0} for test / retain cc".format(transaction.amount))
|
||||
elif transaction.preapproval_key.startswith('tok_'):
|
||||
charge = sc.create_charge(transaction.amount, card=transaction.preapproval_key, description="${0} for test / cc not retained".format(transaction.amount))
|
||||
|
||||
transaction.status = TRANSACTION_STATUS_COMPLETE
|
||||
transaction.pay_key = charge.id
|
||||
transaction.date_payment = now()
|
||||
transaction.save()
|
||||
|
||||
self.charge = charge
|
||||
|
||||
def api(self):
|
||||
return "Base Pay"
|
||||
|
||||
def key(self):
|
||||
# IN paypal land, our key is updated from a preapproval to a pay key here, just return the existing key
|
||||
return self.transaction.pay_key
|
||||
|
||||
|
||||
class PreapprovalDetails(StripePaymentRequest):
|
||||
'''
|
||||
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 - not used in this API, but we can get some more info via other APIs - TODO
|
||||
amount - not used in this API, but we can get some more info via other APIs - TODO
|
||||
|
||||
'''
|
||||
def __init__(self, transaction):
|
||||
|
||||
self.transaction = transaction
|
||||
self.status = self.transaction.status
|
||||
if self.status == TRANSACTION_STATUS_CANCELED:
|
||||
self.approved = False
|
||||
else:
|
||||
self.approved = True
|
||||
|
||||
# Set the other fields that are expected. We don't have values for these now, so just copy the transaction
|
||||
self.currency = transaction.currency
|
||||
self.amount = transaction.amount
|
||||
|
||||
def suite():
|
||||
|
||||
|
|
Loading…
Reference in New Issue