Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
Rebase and cleanup remainder of Authorize implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
zeantsoi committed Nov 5, 2015
1 parent 9b645f8 commit eddee73
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 70 deletions.
31 changes: 22 additions & 9 deletions r2/r2/controllers/promotecontroller.py
Expand Up @@ -47,6 +47,7 @@
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
Expand Down Expand Up @@ -1264,6 +1265,12 @@ def POST_terminate_campaign(self, form, jquery, link, campaign):
)
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

Expand Down Expand Up @@ -1305,11 +1312,19 @@ def POST_update_pay(self, form, jquery, link, campaign, customer_id, pay_id,
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,
Expand All @@ -1328,12 +1343,10 @@ def POST_update_pay(self, form, jquery, link, campaign, customer_id, pay_id,
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"),
Expand Down
36 changes: 16 additions & 20 deletions r2/r2/lib/authorize/api.py
Expand Up @@ -72,27 +72,31 @@

@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>",
msg)
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


Expand Down Expand Up @@ -316,7 +320,6 @@ def process_error(self, res):

# --- real request classes below


class CreateCustomerProfileRequest(AuthorizeNetRequest):
_keys = AuthorizeNetRequest._keys + ["profile", "validationMode"]

Expand Down Expand Up @@ -359,8 +362,6 @@ def process_response(self, res):

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)


Expand Down Expand Up @@ -399,9 +400,11 @@ def process_response(self, res):

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"]
Expand Down Expand Up @@ -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

Expand All @@ -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,
Expand Down Expand Up @@ -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:
Expand Down
70 changes: 29 additions & 41 deletions r2/r2/lib/authorize/interaction.py
Expand Up @@ -29,21 +29,7 @@
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__ = []
Expand All @@ -54,13 +40,13 @@

@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")
Expand All @@ -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:
Expand All @@ -84,25 +70,26 @@ 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


@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)


@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
Expand Down Expand Up @@ -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,
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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)
Expand Down

0 comments on commit eddee73

Please sign in to comment.