Rebase and cleanup remainder of Authorize implementation

This commit is contained in:
zeantsoi
2015-08-18 16:46:24 -07:00
parent 9b645f8a68
commit eddee73fc4
3 changed files with 67 additions and 70 deletions

View File

@@ -47,6 +47,7 @@ from r2.lib.authorize import (
add_or_update_payment_method,
PROFILE_LIMIT,
)
from r2.lib.authorize.api import AuthorizeNetException
from r2.lib.base import abort
from r2.lib.db import queries
from r2.lib.errors import errors
@@ -1264,6 +1265,12 @@ class PromoteApiController(ApiController):
)
def POST_update_pay(self, form, jquery, link, campaign, customer_id, pay_id,
edit, address, creditcard):
def _handle_failed_payment(reason=None):
promote.failed_payment_method(c.user, link)
msg = reason or _("failed to authenticate card. sorry.")
form.set_text(".status", msg)
if not g.authorizenetapi:
return
@@ -1305,11 +1312,19 @@ class PromoteApiController(ApiController):
form.has_errors(card_fields, errors.BAD_CARD)):
return
pay_id = add_or_update_payment_method(
c.user, address, creditcard, pay_id)
try:
pay_id = add_or_update_payment_method(
c.user, address, creditcard, pay_id)
if pay_id:
promote.new_payment_method(user=c.user, ip=request.ip, address=address, link=link)
if pay_id:
promote.new_payment_method(user=c.user,
ip=request.ip,
address=address,
link=link)
except AuthorizeNetException:
_handle_failed_payment()
return
if pay_id:
success, reason = promote.auth_campaign(link, campaign, c.user,
@@ -1328,12 +1343,10 @@ class PromoteApiController(ApiController):
jquery.payment_redirect(promote.promo_edit_url(link), new_payment, campaign.bid)
return
else:
promote.failed_payment_method(c.user, link)
msg = reason or _("failed to authenticate card. sorry.")
form.set_text(".status", msg)
_handle_failed_payment(reason)
else:
promote.failed_payment_method(c.user, link)
form.set_text(".status", _("failed to authenticate card. sorry."))
_handle_failed_payment()
@validate(
VSponsor("link_name"),

View File

@@ -72,7 +72,7 @@ PROFILE_LIMIT = 10 # max payment profiles per user allowed by authorize.net
@export
class AuthorizeNetException(Exception):
def __init__(self, msg):
def __init__(self, msg, code=None):
# don't let CC info show up in logs
msg = re.sub("<cardNumber>\d+(\d{4})</cardNumber>",
"<cardNumber>...\g<1></cardNumber>",
@@ -80,19 +80,23 @@ class AuthorizeNetException(Exception):
msg = re.sub("<cardCode>\d+</cardCode>",
"<cardCode>omitted</cardCode>",
msg)
self.code = code
super(AuthorizeNetException, self).__init__(msg)
class DuplicateTransactionError(Exception):
def __init__(self, transaction_id):
self.transaction_id = transaction_id
class TransactionError(Exception):
def __init__(self, message):
self.message = message
class DuplicateTransactionError(TransactionError):
def __init__(self, transaction_id):
self.transaction_id = transaction_id
message = ('DuplicateTransactionError with transaction_id %d' %
transaction_id)
super(DuplicateTransactionError, self).__init__(message)
class AuthorizationHoldNotFound(Exception): pass
@@ -316,7 +320,6 @@ class AuthorizeNetRequest(SimpleXMLObject):
# --- real request classes below
class CreateCustomerProfileRequest(AuthorizeNetRequest):
_keys = AuthorizeNetRequest._keys + ["profile", "validationMode"]
@@ -359,8 +362,6 @@ class CreateCustomerPaymentProfileRequest(AuthorizeNetRequest):
def process_error(self, res):
message_text = res.find("text").contents[0]
if self.is_error_code(res, Errors.DUPLICATE_RECORD):
raise AuthorizeNetException(message_text)
raise AuthorizeNetException(message_text)
@@ -399,9 +400,11 @@ class GetCustomerProfileRequest(AuthorizeNetRequest):
def process_error(self, res):
message_text = res.find("text").contents[0]
raise AuthorizeNetException(message_text)
code = res.find('code').contents[0]
raise AuthorizeNetException(message_text, code=code)
# TODO: implement
class DeleteCustomerPaymentProfileRequest(AuthorizeNetRequest):
_keys = AuthorizeNetRequest._keys + ["customerProfileId",
"customerPaymentProfileId"]
@@ -559,10 +562,7 @@ def create_payment_profile(customer_id, address, credit_card, validate=False):
validationMode="liveMode" if validate else None,
)
try:
payment_profile_id = request.make_request()
except AuthorizeNetException:
return None
payment_profile_id = request.make_request()
return payment_profile_id
@@ -581,14 +581,12 @@ def update_payment_profile(customer_id, payment_profile_id, address,
validationMode="liveMode" if validate else None,
)
try:
payment_profile_id = request.make_request()
except AuthorizeNetException:
return None
payment_profile_id = request.make_request()
return payment_profile_id
# TODO: implement
def delete_payment_profile(customer_id, payment_profile_id):
request = DeleteCustomerPaymentProfileRequest(
customerProfileId=customer_id,
@@ -625,8 +623,6 @@ def create_authorization_hold(customer_id, payment_profile_id, amount, invoice,
if (res.trans_id and
res.response_code == TRANSACTION_ERROR and
res.response_reason_code == TRANSACTION_DUPLICATE):
g.log.error("Authorize.net duplicate trans %d on campaign %d" %
(res.trans_id, campaign_id))
raise DuplicateTransactionError(res.trans_id)
if success:

View File

@@ -29,21 +29,7 @@ from r2.lib.db.thing import NotFound
from r2.lib.utils import Storage
from r2.lib.export import export
from r2.models.bidding import Bid, CustomerID, PayID
from r2.lib.authorize.api import (
AuthorizationHoldNotFound,
capture_authorization_hold,
create_authorization_hold,
create_customer_profile,
create_payment_profile,
delete_payment_profile,
DuplicateTransactionError,
get_customer_profile,
refund_transaction as _refund_transaction,
TRANSACTION_NOT_FOUND,
TransactionError,
update_payment_profile,
void_authorization_hold,
)
from r2.lib.authorize import api
__all__ = []
@@ -54,13 +40,13 @@ FREEBIE_PAYMENT_METHOD_ID = -1
@export
def get_or_create_customer_profile(user):
profile_id = CustomerID.get_id(user)
if not CustomerID.get_id(user._id):
profile_id = create_customer_profile(
profile_id = CustomerID.get_id(user._id)
if not profile_id:
profile_id = api.create_customer_profile(
merchant_customer_id=user._fullname, description=user.name)
CustomerID.set(user, profile_id)
profile = get_customer_profile(profile_id)
profile = api.get_customer_profile(profile_id)
if not profile or profile.merchantCustomerId != user._fullname:
raise ValueError("error getting customer profile")
@@ -73,7 +59,7 @@ def get_or_create_customer_profile(user):
def add_payment_method(user, address, credit_card, validate=False):
profile_id = CustomerID.get_id(user._id)
payment_method_id = create_payment_profile(
payment_method_id = api.create_payment_profile(
profile_id, address, credit_card, validate)
if payment_method_id:
@@ -84,7 +70,7 @@ def add_payment_method(user, address, credit_card, validate=False):
def update_payment_method(user, payment_method_id, address, credit_card,
validate=False):
profile_id = CustomerID.get_id(user._id)
payment_method_id = update_payment_profile(
payment_method_id = api.update_payment_profile(
profile_id, payment_method_id, address, credit_card, validate)
return payment_method_id
@@ -92,7 +78,7 @@ def update_payment_method(user, payment_method_id, address, credit_card,
@export
def delete_payment_method(user, payment_method_id):
profile_id = CustomerID.get_id(user._id)
success = delete_payment_profile(profile_id, payment_method_id)
success = api.delete_payment_profile(profile_id, payment_method_id)
if success:
PayID.delete(user, payment_method_id)
@@ -100,9 +86,10 @@ def delete_payment_method(user, payment_method_id):
@export
def add_or_update_payment_method(user, address, credit_card, pay_id=None):
if pay_id:
return update_payment_method(user, pay_id, address, credit_card)
return update_payment_method(user, pay_id, address, credit_card,
validate=True)
else:
return add_payment_method(user, address, credit_card)
return add_payment_method(user, address, credit_card, validate=True)
@export
@@ -139,24 +126,25 @@ def auth_freebie_transaction(amount, user, link, campaign_id):
@export
def auth_transaction(amount, user, payment_method_id, link, campaign_id):
if payment_method_id not in PayID.get_ids(user):
if payment_method_id not in PayID.get_ids(user._id):
return None, "invalid payment method"
profile_id = CustomerID.get_id(user)
profile_id = CustomerID.get_id(user._id)
invoice = "T%dC%d" % (link._id, campaign_id)
try:
transaction_id = create_authorization_hold(
transaction_id = api.create_authorization_hold(
profile_id, payment_method_id, amount, invoice, request.ip)
except DuplicateTransactionError as e:
except api.DuplicateTransactionError as e:
transaction_id = e.transaction_id
try:
bid = Bid.one(transaction_id, campaign=campaign_id)
except NotFound:
bid = Bid._new(transaction_id, user, payment_method_id, link._id,
amount, campaign_id)
g.log.error("%s on campaign %d" % (e.message, campaign_id))
return transaction_id, None
except TransactionError as e:
except api.TransactionError as e:
return None, e.message
bid = Bid._new(transaction_id, user, payment_method_id, link._id, amount,
@@ -174,20 +162,20 @@ def charge_transaction(user, transaction_id, campaign_id):
bid.charged()
return True, None
profile_id = CustomerID.get_id(user)
profile_id = CustomerID.get_id(user._id)
try:
capture_authorization_hold(
api.capture_authorization_hold(
customer_id=profile_id,
payment_profile_id=bid.pay_id,
amount=bid.bid,
transaction_id=transaction_id,
)
except AuthorizationHoldNotFound:
except api.AuthorizationHoldNotFound:
# authorization hold has expired
bid.void()
return False, TRANSACTION_NOT_FOUND
except TransactionError as e:
return False, api.TRANSACTION_NOT_FOUND
except api.TransactionError as e:
return False, e.message
bid.charged()
@@ -198,14 +186,14 @@ def charge_transaction(user, transaction_id, campaign_id):
def void_transaction(user, transaction_id, campaign_id):
bid = Bid.one(transaction=transaction_id, campaign=campaign_id)
if transaction_id < 0:
if transaction_id <= 0:
bid.void()
return True, None
profile_id = CustomerID.get_id(user)
profile_id = CustomerID.get_id(user._id)
try:
void_authorization_hold(profile_id, bid.pay_id, transaction_id)
except TransactionError as e:
api.void_authorization_hold(profile_id, bid.pay_id, transaction_id)
except api.TransactionError as e:
return False, e.message
bid.void()
@@ -219,15 +207,15 @@ def refund_transaction(user, transaction_id, campaign_id, amount):
bid.refund(amount)
return True, None
profile_id = CustomerID.get_id(user)
profile_id = CustomerID.get_id(user._id)
try:
_refund_transaction(
api.refund_transaction(
customer_id=profile_id,
payment_profile_id=bid.pay_id,
amount=amount,
transaction_id=transaction_id,
)
except TransactionError as e:
except api.TransactionError as e:
return False, e.message
bid.refund(amount)