mirror of
https://github.com/reddit-archive/reddit.git
synced 2026-01-28 16:28:01 -05:00
Modify authorize/* code to use new @export syntax
* Modify authorize/*.py to add @export and __all__ * Do a style sweep on authorize/* to clear up a few style issues * add unit test for authorize/* that tests non-DB classes and imports *
This commit is contained in:
committed by
Keith Mitchell
parent
288b9be012
commit
9b83d48eba
@@ -20,4 +20,5 @@
|
||||
# Inc. All Rights Reserved.
|
||||
###############################################################################
|
||||
|
||||
from api import *
|
||||
from interaction import *
|
||||
|
||||
@@ -27,28 +27,33 @@ This file consists mostly of wrapper classes for dealing with their
|
||||
API, while the actual useful functions live in interaction.py
|
||||
"""
|
||||
|
||||
from pylons import g
|
||||
import re
|
||||
import socket
|
||||
from httplib import HTTPSConnection
|
||||
from urlparse import urlparse
|
||||
import socket, re
|
||||
|
||||
from BeautifulSoup import BeautifulStoneSoup
|
||||
from r2.lib.utils import iters, Storage
|
||||
|
||||
from r2.models import NotFound
|
||||
from r2.models.bidding import CustomerID, PayID, ShippingAddress
|
||||
|
||||
from pylons import g
|
||||
from xml.sax.saxutils import escape
|
||||
|
||||
from r2.lib.export import export
|
||||
from r2.lib.utils import iters, Storage
|
||||
from r2.models.bidding import CustomerID, PayID, ShippingAddress
|
||||
|
||||
__all__ = ["PROFILE_LIMIT"]
|
||||
|
||||
|
||||
# list of the most common errors.
|
||||
Errors = Storage(TESTMODE = "E00009",
|
||||
TRANSACTION_FAIL = "E00027",
|
||||
DUPLICATE_RECORD = "E00039",
|
||||
RECORD_NOT_FOUND = "E00040",
|
||||
TOO_MANY_PAY_PROFILES = "E00042",
|
||||
TOO_MANY_SHIP_ADDRESSES = "E00043")
|
||||
Errors = Storage(TESTMODE="E00009",
|
||||
TRANSACTION_FAIL="E00027",
|
||||
DUPLICATE_RECORD="E00039",
|
||||
RECORD_NOT_FOUND="E00040",
|
||||
TOO_MANY_PAY_PROFILES="E00042",
|
||||
TOO_MANY_SHIP_ADDRESSES="E00043")
|
||||
|
||||
PROFILE_LIMIT = 10 # max payment profiles per user allowed by authorize.net
|
||||
|
||||
@export
|
||||
class AuthorizeNetException(Exception):
|
||||
def __init__(self, msg):
|
||||
# don't let CC info show up in logs
|
||||
@@ -65,6 +70,7 @@ class AuthorizeNetException(Exception):
|
||||
# xml tags whose content shouldn't be escaped
|
||||
_no_escape_list = ["extraOptions"]
|
||||
|
||||
|
||||
class SimpleXMLObject(object):
|
||||
"""
|
||||
All API transactions are done with authorize.net using XML, so
|
||||
@@ -81,9 +87,10 @@ class SimpleXMLObject(object):
|
||||
@staticmethod
|
||||
def simple_tag(name, content, **attrs):
|
||||
attrs = " ".join('%s="%s"' % (k, v) for k, v in attrs.iteritems())
|
||||
if attrs: attrs = " " + attrs
|
||||
if attrs:
|
||||
attrs = " " + attrs
|
||||
return ("<%(name)s%(attrs)s>%(content)s</%(name)s>" %
|
||||
dict(name = name, content = content, attrs = attrs))
|
||||
dict(name=name, content=content, attrs=attrs))
|
||||
|
||||
def toXML(self):
|
||||
content = []
|
||||
@@ -128,9 +135,12 @@ class SimpleXMLObject(object):
|
||||
def _wrapper(self, content):
|
||||
return content
|
||||
|
||||
|
||||
class Auth(SimpleXMLObject):
|
||||
_keys = ["name", "transactionKey"]
|
||||
|
||||
|
||||
@export
|
||||
class Address(SimpleXMLObject):
|
||||
_keys = ["firstName", "lastName", "company", "address",
|
||||
"city", "state", "zip", "country", "phoneNumber",
|
||||
@@ -144,11 +154,11 @@ class Address(SimpleXMLObject):
|
||||
SimpleXMLObject.__init__(self, **kw)
|
||||
|
||||
|
||||
@export
|
||||
class CreditCard(SimpleXMLObject):
|
||||
_keys = ["cardNumber", "expirationDate", "cardCode"]
|
||||
|
||||
|
||||
|
||||
class Profile(SimpleXMLObject):
|
||||
"""
|
||||
Converts a user into a Profile object.
|
||||
@@ -157,23 +167,22 @@ class Profile(SimpleXMLObject):
|
||||
"email", "customerProfileId", "paymentProfiles", "shipToList",
|
||||
"validationMode"]
|
||||
def __init__(self, user, paymentProfiles, address,
|
||||
validationMode = None):
|
||||
SimpleXMLObject.__init__(self, merchantCustomerId = user._fullname,
|
||||
description = user.name, email = "",
|
||||
paymentProfiles = paymentProfiles,
|
||||
shipToList = address,
|
||||
validationMode = validationMode,
|
||||
validationMode=None):
|
||||
SimpleXMLObject.__init__(self, merchantCustomerId=user._fullname,
|
||||
description=user.name, email="",
|
||||
paymentProfiles=paymentProfiles,
|
||||
shipToList=address,
|
||||
validationMode=validationMode,
|
||||
customerProfileId=CustomerID.get_id(user))
|
||||
|
||||
|
||||
class PaymentProfile(SimpleXMLObject):
|
||||
_keys = ["billTo", "payment", "customerPaymentProfileId", "validationMode"]
|
||||
def __init__(self, billTo, card, paymentId = None,
|
||||
validationMode = None):
|
||||
SimpleXMLObject.__init__(self, billTo = billTo,
|
||||
customerPaymentProfileId = paymentId,
|
||||
payment = SimpleXMLObject(creditCard = card),
|
||||
validationMode = validationMode)
|
||||
def __init__(self, billTo, card, paymentId=None,
|
||||
validationMode=None):
|
||||
SimpleXMLObject.__init__(self, billTo=billTo,
|
||||
customerPaymentProfileId=paymentId,
|
||||
payment=SimpleXMLObject(creditCard=card),
|
||||
validationMode=validationMode)
|
||||
|
||||
@classmethod
|
||||
def fromXML(cls, res):
|
||||
@@ -181,38 +190,56 @@ class PaymentProfile(SimpleXMLObject):
|
||||
return cls(Address.fromXML(res.billto),
|
||||
CreditCard.fromXML(res.payment), payid)
|
||||
|
||||
|
||||
@export
|
||||
class Order(SimpleXMLObject):
|
||||
_keys = ["invoiceNumber", "description", "purchaseOrderNumber"]
|
||||
|
||||
|
||||
class Transaction(SimpleXMLObject):
|
||||
_keys = ["amount", "customerProfileId", "customerPaymentProfileId",
|
||||
"transId", "order"]
|
||||
|
||||
def __init__(self, amount, profile_id, pay_id, trans_id = None,
|
||||
order = None):
|
||||
SimpleXMLObject.__init__(self, amount = amount,
|
||||
customerProfileId = profile_id,
|
||||
customerPaymentProfileId = pay_id,
|
||||
transId = trans_id,
|
||||
order = order)
|
||||
def __init__(self, amount, profile_id, pay_id, trans_id=None,
|
||||
order=None):
|
||||
SimpleXMLObject.__init__(self, amount=amount,
|
||||
customerProfileId=profile_id,
|
||||
customerPaymentProfileId=pay_id,
|
||||
transId=trans_id,
|
||||
order=order)
|
||||
|
||||
def _wrapper(self, content):
|
||||
return self.simple_tag(self._name(), content)
|
||||
|
||||
|
||||
# authorize and charge
|
||||
@export
|
||||
class ProfileTransAuthCapture(Transaction): pass
|
||||
|
||||
# only authorize (no charge is made)
|
||||
class ProfileTransAuthOnly(Transaction): pass
|
||||
# charge only (requires previous auth_only)
|
||||
class ProfileTransPriorAuthCapture(Transaction): pass
|
||||
# stronger than above: charge even on decline (not sure why you would want to)
|
||||
class ProfileTransCaptureOnly(Transaction): pass
|
||||
# refund a transaction
|
||||
class ProfileTransRefund(Transaction): pass
|
||||
# void a transaction
|
||||
class ProfileTransVoid(Transaction): pass
|
||||
|
||||
# only authorize (no charge is made)
|
||||
@export
|
||||
class ProfileTransAuthOnly(Transaction): pass
|
||||
|
||||
|
||||
# charge only (requires previous auth_only)
|
||||
@export
|
||||
class ProfileTransPriorAuthCapture(Transaction): pass
|
||||
|
||||
|
||||
# stronger than above: charge even on decline (not sure why you would want to)
|
||||
@export
|
||||
class ProfileTransCaptureOnly(Transaction): pass
|
||||
|
||||
|
||||
# refund a transaction
|
||||
@export
|
||||
class ProfileTransRefund(Transaction): pass
|
||||
|
||||
|
||||
# void a transaction
|
||||
@export
|
||||
class ProfileTransVoid(Transaction): pass
|
||||
|
||||
|
||||
#-----
|
||||
@@ -221,8 +248,8 @@ class AuthorizeNetRequest(SimpleXMLObject):
|
||||
|
||||
@property
|
||||
def merchantAuthentication(self):
|
||||
return Auth(name = g.authorizenetname,
|
||||
transactionKey = g.authorizenetkey)
|
||||
return Auth(name=g.authorizenetname,
|
||||
transactionKey=g.authorizenetkey)
|
||||
|
||||
def _wrapper(self, content):
|
||||
return ('<?xml version="1.0" encoding="utf-8"?>' +
|
||||
@@ -253,7 +280,7 @@ class AuthorizeNetRequest(SimpleXMLObject):
|
||||
|
||||
_autoclose_re = re.compile("<([^/]+)/>")
|
||||
def _autoclose_handler(self, m):
|
||||
return "<%(m)s></%(m)s>" % dict(m = m.groups()[0])
|
||||
return "<%(m)s></%(m)s>" % dict(m=m.groups()[0])
|
||||
|
||||
def handle_response(self, res):
|
||||
res = self._autoclose_re.sub(self._autoclose_handler, res)
|
||||
@@ -277,11 +304,11 @@ class CustomerRequest(AuthorizeNetRequest):
|
||||
else:
|
||||
cust_id = CustomerID.get_id(user)
|
||||
self._user = user
|
||||
AuthorizeNetRequest.__init__(self, customerProfileId = cust_id, **kw)
|
||||
|
||||
AuthorizeNetRequest.__init__(self, customerProfileId=cust_id, **kw)
|
||||
|
||||
# --- real request classes below
|
||||
|
||||
|
||||
class CreateCustomerProfileRequest(AuthorizeNetRequest):
|
||||
"""
|
||||
Create a new user object on authorize.net and return the new object ID.
|
||||
@@ -291,12 +318,12 @@ class CreateCustomerProfileRequest(AuthorizeNetRequest):
|
||||
"""
|
||||
_keys = AuthorizeNetRequest._keys + ["profile", "validationMode"]
|
||||
|
||||
def __init__(self, user, validationMode = None):
|
||||
def __init__(self, user, validationMode=None):
|
||||
# cache the user object passed in
|
||||
self._user = user
|
||||
AuthorizeNetRequest.__init__(self,
|
||||
profile = Profile(user, None, None),
|
||||
validationMode = validationMode)
|
||||
profile=Profile(user, None, None),
|
||||
validationMode=validationMode)
|
||||
|
||||
def process_response(self, res):
|
||||
customer_id = int(res.customerprofileid.contents[0])
|
||||
@@ -330,6 +357,7 @@ class CreateCustomerProfileRequest(AuthorizeNetRequest):
|
||||
return cust_id
|
||||
return AuthorizeNetRequest.process_error(self, res)
|
||||
|
||||
|
||||
class CreateCustomerPaymentProfileRequest(CustomerRequest):
|
||||
"""
|
||||
Adds a payment profile to an existing user object. The profile
|
||||
@@ -337,11 +365,11 @@ class CreateCustomerPaymentProfileRequest(CustomerRequest):
|
||||
"""
|
||||
_keys = (CustomerRequest._keys + ["paymentProfile", "validationMode"])
|
||||
|
||||
def __init__(self, user, address, creditcard, validationMode = None):
|
||||
def __init__(self, user, address, creditcard, validationMode=None):
|
||||
CustomerRequest.__init__(self, user,
|
||||
paymentProfile = PaymentProfile(address,
|
||||
creditcard),
|
||||
validationMode = validationMode)
|
||||
paymentProfile=PaymentProfile(address,
|
||||
creditcard),
|
||||
validationMode=validationMode)
|
||||
|
||||
def process_response(self, res):
|
||||
pay_id = int(res.customerpaymentprofileid.contents[0])
|
||||
@@ -355,7 +383,8 @@ class CreateCustomerPaymentProfileRequest(CustomerRequest):
|
||||
if len(profiles) == 1:
|
||||
return profiles[0].customerPaymentProfileId
|
||||
return
|
||||
return CustomerRequest.process_error(self,res)
|
||||
return CustomerRequest.process_error(self, res)
|
||||
|
||||
|
||||
class CreateCustomerShippingAddressRequest(CustomerRequest):
|
||||
"""
|
||||
@@ -396,7 +425,7 @@ class GetCustomerPaymentProfileRequest(CustomerRequest):
|
||||
def process_error(self, res):
|
||||
if self.is_error_code(res, Errors.RECORD_NOT_FOUND):
|
||||
PayID.delete(self._user, self.customerPaymentProfileId)
|
||||
return CustomerRequest.process_error(self,res)
|
||||
return CustomerRequest.process_error(self, res)
|
||||
|
||||
|
||||
class GetCustomerShippingAddressRequest(CustomerRequest):
|
||||
@@ -418,7 +447,8 @@ class GetCustomerShippingAddressRequest(CustomerRequest):
|
||||
def process_error(self, res):
|
||||
if self.is_error_code(res, Errors.RECORD_NOT_FOUND):
|
||||
ShippingAddress.delete(self._user, self.customerAddressId)
|
||||
return CustomerRequest.process_error(self,res)
|
||||
return CustomerRequest.process_error(self, res)
|
||||
|
||||
|
||||
class GetCustomerProfileIdsRequest(AuthorizeNetRequest):
|
||||
"""
|
||||
@@ -428,6 +458,7 @@ class GetCustomerProfileIdsRequest(AuthorizeNetRequest):
|
||||
def process_response(self, res):
|
||||
return [int(x.contents[0]) for x in res.ids.findAll('numericstring')]
|
||||
|
||||
|
||||
class GetCustomerProfileRequest(CustomerRequest):
|
||||
"""
|
||||
Given a user, find their customer information.
|
||||
@@ -458,7 +489,7 @@ class GetCustomerProfileRequest(CustomerRequest):
|
||||
for profile in res.findAll("paymentprofiles"):
|
||||
a = Address.fromXML(profile)
|
||||
cc = CreditCard.fromXML(profile.payment)
|
||||
payprof = PaymentProfile(a, cc,int(a.customerPaymentProfileId))
|
||||
payprof = PaymentProfile(a, cc, int(a.customerPaymentProfileId))
|
||||
PayID.add(acct, a.customerPaymentProfileId)
|
||||
profiles.append(payprof)
|
||||
|
||||
@@ -476,20 +507,22 @@ class DeleteCustomerProfileRequest(CustomerRequest):
|
||||
def process_error(self, res):
|
||||
if self.is_error_code(res, Errors.RECORD_NOT_FOUND):
|
||||
CustomerID.delete(self._user)
|
||||
return CustomerRequest.process_error(self,res)
|
||||
return CustomerRequest.process_error(self, res)
|
||||
|
||||
|
||||
class DeleteCustomerPaymentProfileRequest(GetCustomerPaymentProfileRequest):
|
||||
"""
|
||||
Delete a customer shipping address
|
||||
"""
|
||||
def process_response(self, res):
|
||||
PayID.delete(self._user,self.customerPaymentProfileId)
|
||||
PayID.delete(self._user, self.customerPaymentProfileId)
|
||||
return True
|
||||
|
||||
def process_error(self, res):
|
||||
if self.is_error_code(res, Errors.RECORD_NOT_FOUND):
|
||||
PayID.delete(self._user,self.customerPaymentProfileId)
|
||||
return GetCustomerPaymentProfileRequest.process_error(self,res)
|
||||
PayID.delete(self._user, self.customerPaymentProfileId)
|
||||
return GetCustomerPaymentProfileRequest.process_error(self, res)
|
||||
|
||||
|
||||
class DeleteCustomerShippingAddressRequest(GetCustomerShippingAddressRequest):
|
||||
"""
|
||||
@@ -502,9 +535,7 @@ class DeleteCustomerShippingAddressRequest(GetCustomerShippingAddressRequest):
|
||||
def process_error(self, res):
|
||||
if self.is_error_code(res, Errors.RECORD_NOT_FOUND):
|
||||
ShippingAddress.delete(self._user, self.customerAddressId)
|
||||
GetCustomerShippingAddressRequest.process_error(self,res)
|
||||
|
||||
|
||||
GetCustomerShippingAddressRequest.process_error(self, res)
|
||||
|
||||
|
||||
# TODO
|
||||
@@ -520,12 +551,12 @@ class UpdateCustomerPaymentProfileRequest(CreateCustomerPaymentProfileRequest):
|
||||
For updating the user's payment profile
|
||||
"""
|
||||
def __init__(self, user, paymentid, address, creditcard,
|
||||
validationMode = None):
|
||||
validationMode=None):
|
||||
CustomerRequest.__init__(self, user,
|
||||
paymentProfile=PaymentProfile(address,
|
||||
creditcard,
|
||||
paymentid),
|
||||
validationMode = validationMode)
|
||||
validationMode=validationMode)
|
||||
|
||||
def process_response(self, res):
|
||||
return self.paymentProfile.customerPaymentProfileId
|
||||
@@ -539,14 +570,12 @@ class UpdateCustomerShippingAddressRequest(
|
||||
def __init__(self, user, address_id, address):
|
||||
address.customerAddressId = address_id
|
||||
CreateCustomerShippingAddressRequest.__init__(self, user,
|
||||
address = address)
|
||||
address=address)
|
||||
|
||||
def process_response(self, res):
|
||||
return True
|
||||
|
||||
|
||||
|
||||
|
||||
class CreateCustomerProfileTransactionRequest(AuthorizeNetRequest):
|
||||
_keys = AuthorizeNetRequest._keys + ["transaction", "extraOptions"]
|
||||
|
||||
@@ -579,10 +608,10 @@ class CreateCustomerProfileTransactionRequest(AuthorizeNetRequest):
|
||||
"cav_response")
|
||||
|
||||
# list of casts for the response fields given above
|
||||
response_types = dict(response_code = int,
|
||||
response_subcode = int,
|
||||
response_reason_code = int,
|
||||
trans_id = int)
|
||||
response_types = dict(response_code=int,
|
||||
response_subcode=int,
|
||||
response_reason_code=int,
|
||||
trans_id=int)
|
||||
|
||||
def __init__(self, **kw):
|
||||
from pylons import g
|
||||
@@ -604,7 +633,7 @@ class CreateCustomerProfileTransactionRequest(AuthorizeNetRequest):
|
||||
return (False, self.package_response(res))
|
||||
elif self.is_error_code(res, Errors.TESTMODE):
|
||||
return (None, None)
|
||||
return AuthorizeNetRequest.process_error(self,res)
|
||||
return AuthorizeNetRequest.process_error(self, res)
|
||||
|
||||
|
||||
def package_response(self, res):
|
||||
@@ -617,6 +646,7 @@ class CreateCustomerProfileTransactionRequest(AuthorizeNetRequest):
|
||||
pass
|
||||
return s
|
||||
|
||||
|
||||
class GetSettledBatchListRequest(AuthorizeNetRequest):
|
||||
_keys = AuthorizeNetRequest._keys + ["includeStatistics",
|
||||
"firstSettlementDate",
|
||||
|
||||
@@ -20,9 +20,29 @@
|
||||
# Inc. All Rights Reserved.
|
||||
###############################################################################
|
||||
|
||||
from api import *
|
||||
from pylons import g
|
||||
from r2.models.bidding import Bid
|
||||
|
||||
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 (
|
||||
Address,
|
||||
AuthorizeNetException,
|
||||
CreateCustomerPaymentProfileRequest,
|
||||
CreateCustomerProfileRequest,
|
||||
CreateCustomerProfileTransactionRequest,
|
||||
CreditCard,
|
||||
GetCustomerProfileRequest,
|
||||
Order,
|
||||
ProfileTransAuthOnly,
|
||||
ProfileTransPriorAuthCapture,
|
||||
ProfileTransVoid,
|
||||
UpdateCustomerPaymentProfileRequest,
|
||||
)
|
||||
|
||||
__all__ = []
|
||||
|
||||
# useful test data:
|
||||
test_card = dict(AMEX = ("370000000000002" , 1234),
|
||||
@@ -32,15 +52,21 @@ test_card = dict(AMEX = ("370000000000002" , 1234),
|
||||
# visa card which generates error codes based on the amount
|
||||
ERRORCARD = ("4222222222222" , 123))
|
||||
|
||||
test_card = Storage((k, CreditCard(cardNumber = x, expirationDate="2011-11",
|
||||
cardCode = y)) for k, (x, y) in
|
||||
test_card = Storage((k, CreditCard(cardNumber=x,
|
||||
expirationDate="2011-11",
|
||||
cardCode=y)) for k, (x, y) in
|
||||
test_card.iteritems())
|
||||
|
||||
test_address = Address(firstName = "John", lastName = "Doe",
|
||||
address = "123 Fake St.",
|
||||
city = "Anytown", state = "MN", zip = "12346")
|
||||
test_address = Address(firstName="John",
|
||||
lastName="Doe",
|
||||
address="123 Fake St.",
|
||||
city="Anytown",
|
||||
state="MN",
|
||||
zip="12346")
|
||||
|
||||
def get_account_info(user, recursed = False):
|
||||
|
||||
@export
|
||||
def get_account_info(user, recursed=False):
|
||||
# if we don't have an ID for the user, try to make one
|
||||
if not CustomerID.get_id(user):
|
||||
cust_id = CreateCustomerProfileRequest(user).make_request()
|
||||
@@ -61,7 +87,9 @@ def get_account_info(user, recursed = False):
|
||||
raise AuthorizeNetException, "error creating user"
|
||||
return data
|
||||
|
||||
def edit_profile(user, address, creditcard, pay_id = None):
|
||||
|
||||
@export
|
||||
def edit_profile(user, address, creditcard, pay_id=None):
|
||||
if pay_id:
|
||||
return UpdateCustomerPaymentProfileRequest(
|
||||
user, pay_id, address, creditcard).make_request()
|
||||
@@ -70,10 +98,8 @@ def edit_profile(user, address, creditcard, pay_id = None):
|
||||
user, address, creditcard).make_request()
|
||||
|
||||
|
||||
|
||||
|
||||
def _make_transaction(trans_cls, amount, user, pay_id,
|
||||
order = None, trans_id = None, test = None):
|
||||
order=None, trans_id=None, test=None):
|
||||
"""
|
||||
private function for handling transactions (since the data is
|
||||
effectively the same regardless of trans_cls)
|
||||
@@ -84,32 +110,33 @@ def _make_transaction(trans_cls, amount, user, pay_id,
|
||||
# lookup customer ID
|
||||
cust_id = CustomerID.get_id(user)
|
||||
# create a new transaction
|
||||
trans = trans_cls(amount, cust_id, pay_id, trans_id = trans_id,
|
||||
order = order)
|
||||
trans = trans_cls(amount, cust_id, pay_id, trans_id=trans_id,
|
||||
order=order)
|
||||
extra = {}
|
||||
# the optional test field makes the transaction a test, and will
|
||||
# make the response be the error code corresponding to int(test).
|
||||
if isinstance(test, int):
|
||||
extra = dict(x_test_request = "TRUE",
|
||||
x_card_num = test_card.ERRORCARD.cardNumber,
|
||||
x_amount = test)
|
||||
extra = dict(x_test_request="TRUE",
|
||||
x_card_num=test_card.ERRORCARD.cardNumber,
|
||||
x_amount=test)
|
||||
|
||||
# using the transaction, generate a transaction request and make it
|
||||
req = CreateCustomerProfileTransactionRequest(transaction = trans,
|
||||
extraOptions = extra)
|
||||
req = CreateCustomerProfileTransactionRequest(transaction=trans,
|
||||
extraOptions=extra)
|
||||
return req.make_request()
|
||||
|
||||
|
||||
def auth_transaction(amount, user, payid, thing, campaign, test = None):
|
||||
@export
|
||||
def auth_transaction(amount, user, payid, thing, campaign, test=None):
|
||||
# use negative pay_ids to identify freebies, coupons, or anything
|
||||
# that doesn't require a CC.
|
||||
if payid < 0:
|
||||
trans_id = -thing._id
|
||||
# update previous freebie transactions if we can
|
||||
try:
|
||||
bid = Bid.one(thing_id = thing._id,
|
||||
transaction = trans_id,
|
||||
campaign = campaign)
|
||||
bid = Bid.one(thing_id=thing._id,
|
||||
transaction=trans_id,
|
||||
campaign=campaign)
|
||||
bid.bid = amount
|
||||
bid.auth()
|
||||
except NotFound:
|
||||
@@ -117,10 +144,10 @@ def auth_transaction(amount, user, payid, thing, campaign, test = None):
|
||||
return bid.transaction, ""
|
||||
|
||||
elif int(payid) in PayID.get_ids(user):
|
||||
order = Order(invoiceNumber = "T%dC%d" % (thing._id, campaign))
|
||||
order = Order(invoiceNumber="T%dC%d" % (thing._id, campaign))
|
||||
success, res = _make_transaction(ProfileTransAuthOnly,
|
||||
amount, user, payid,
|
||||
order = order, test = test)
|
||||
order=order, test=test)
|
||||
if success:
|
||||
if test:
|
||||
return auth_transaction(amount, user, -1, thing, campaign,
|
||||
@@ -130,7 +157,7 @@ def auth_transaction(amount, user, payid, thing, campaign, test = None):
|
||||
return res.trans_id, ""
|
||||
elif res is None:
|
||||
# we are in test mode!
|
||||
return auth_transaction(amount, user, -1, thing, test = test)
|
||||
return auth_transaction(amount, user, -1, thing, test=test)
|
||||
# duplicate transaction, which is bad, but not horrible. Log
|
||||
# the transaction id, creating a new bid if necessary.
|
||||
elif res.trans_id and (res.response_code, res.response_reason_code) == (3,11):
|
||||
@@ -143,24 +170,27 @@ def auth_transaction(amount, user, payid, thing, campaign, test = None):
|
||||
return res.trans_id, res.response_reason_text
|
||||
|
||||
|
||||
|
||||
def void_transaction(user, trans_id, campaign, test = None):
|
||||
bid = Bid.one(transaction = trans_id, campaign = campaign)
|
||||
@export
|
||||
def void_transaction(user, trans_id, campaign, test=None):
|
||||
bid = Bid.one(transaction=trans_id, campaign=campaign)
|
||||
bid.void()
|
||||
if trans_id > 0:
|
||||
res = _make_transaction(ProfileTransVoid,
|
||||
None, user, None, trans_id = trans_id,
|
||||
test = test)
|
||||
None, user, None, trans_id=trans_id,
|
||||
test=test)
|
||||
return res
|
||||
|
||||
|
||||
@export
|
||||
def is_charged_transaction(trans_id, campaign):
|
||||
if not trans_id: return False # trans_id == 0 means no bid
|
||||
bid = Bid.one(transaction = trans_id, campaign = campaign)
|
||||
bid = Bid.one(transaction=trans_id, campaign=campaign)
|
||||
return bid.is_charged()
|
||||
|
||||
def charge_transaction(user, trans_id, campaign, test = None):
|
||||
bid = Bid.one(transaction = trans_id, campaign = campaign)
|
||||
|
||||
@export
|
||||
def charge_transaction(user, trans_id, campaign, test=None):
|
||||
bid = Bid.one(transaction=trans_id, campaign=campaign)
|
||||
if not bid.is_charged():
|
||||
bid.charged()
|
||||
if trans_id < 0:
|
||||
@@ -169,8 +199,8 @@ def charge_transaction(user, trans_id, campaign, test = None):
|
||||
elif bid.account_id == user._id:
|
||||
res = _make_transaction(ProfileTransPriorAuthCapture,
|
||||
bid.bid, user,
|
||||
bid.pay_id, trans_id = trans_id,
|
||||
test = test)
|
||||
bid.pay_id, trans_id=trans_id,
|
||||
test=test)
|
||||
return bool(res)
|
||||
|
||||
# already charged
|
||||
|
||||
168
r2/r2/tests/unit/lib/authorize/test_api.py
Executable file
168
r2/r2/tests/unit/lib/authorize/test_api.py
Executable file
@@ -0,0 +1,168 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import unittest
|
||||
|
||||
class AuthorizeNetExceptionTest(unittest.TestCase):
|
||||
|
||||
def test_exception_message(self):
|
||||
from r2.lib.authorize.api import AuthorizeNetException
|
||||
card_number = "<cardNumber>1111222233334444</cardNumber>"
|
||||
expected = "<cardNumber>...4444</cardNumber>"
|
||||
full_msg = "Wrong Card %s was given"
|
||||
|
||||
exp = AuthorizeNetException(full_msg % (card_number))
|
||||
|
||||
self.assertNotEqual(str(exp), (full_msg % card_number))
|
||||
self.assertEqual(str(exp), (full_msg % expected))
|
||||
|
||||
class SimpleXMLObjectTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
from r2.lib.authorize.api import SimpleXMLObject
|
||||
self.basic_object = SimpleXMLObject(name="Test",
|
||||
test="123",
|
||||
)
|
||||
|
||||
def test_to_xml(self):
|
||||
self.assertEqual(self.basic_object.toXML(),
|
||||
"<test>123</test><name>Test</name>",
|
||||
"Unexpected XML produced")
|
||||
|
||||
def test_simple_tag(self):
|
||||
from r2.lib.authorize.api import SimpleXMLObject
|
||||
xml_output = SimpleXMLObject.simple_tag("cat", "Jini", breed="calico",
|
||||
demenor="evil",
|
||||
)
|
||||
self.assertEqual(xml_output,
|
||||
'<cat breed="calico" demenor="evil">Jini</cat>')
|
||||
|
||||
def test_from_xml(self):
|
||||
from r2.lib.authorize.api import SimpleXMLObject
|
||||
from BeautifulSoup import BeautifulStoneSoup
|
||||
class TestXML(SimpleXMLObject):
|
||||
_keys = ["color", "breed"]
|
||||
|
||||
parsed = BeautifulStoneSoup("<dog>" +
|
||||
"<color>black</color>" +
|
||||
"<breed>mixed</breed>" +
|
||||
"<something>else</something>" +
|
||||
"</dog>")
|
||||
constructed = TestXML.fromXML(parsed)
|
||||
expected = SimpleXMLObject(color="black",
|
||||
breed="mixed",
|
||||
)
|
||||
self.assertEqual(constructed.toXML(), expected.toXML(),
|
||||
"Constructed does not match expected")
|
||||
|
||||
def test_address(self):
|
||||
from r2.lib.authorize import Address
|
||||
address = Address(firstName="Bob",
|
||||
lastName="Smith",
|
||||
company="Reddit Inc.",
|
||||
address="123 Main St.",
|
||||
city="San Francisco",
|
||||
state="California",
|
||||
zip="12345",
|
||||
country="USA",
|
||||
phoneNumber="415-555-1234",
|
||||
faxNumber="415-555-4321",
|
||||
customerPaymentProfileId="1234567890",
|
||||
customerAddressId="2233",
|
||||
)
|
||||
expected = ("<firstName>Bob</firstName>" +
|
||||
"<lastName>Smith</lastName>" +
|
||||
"<company>Reddit Inc.</company>" +
|
||||
"<address>123 Main St.</address>" +
|
||||
"<city>San Francisco</city>" +
|
||||
"<state>California</state>" +
|
||||
"<zip>12345</zip>" +
|
||||
"<country>USA</country>" +
|
||||
"<phoneNumber>415-555-1234</phoneNumber>" +
|
||||
"<faxNumber>415-555-4321</faxNumber>" +
|
||||
"<customerPaymentProfileId>1234567890</customerPaymentProfileId>" +
|
||||
"<customerAddressId>2233</customerAddressId>")
|
||||
|
||||
self.assertEqual(address.toXML(), expected)
|
||||
|
||||
def test_credit_card(self):
|
||||
from r2.lib.authorize import CreditCard
|
||||
card = CreditCard(cardNumber="1111222233334444",
|
||||
expirationDate="11/22/33",
|
||||
cardCode="123"
|
||||
)
|
||||
expected = ("<cardNumber>1111222233334444</cardNumber>" +
|
||||
"<expirationDate>11/22/33</expirationDate>" +
|
||||
"<cardCode>123</cardCode>")
|
||||
self.assertEqual(card.toXML(), expected)
|
||||
|
||||
def test_payment_profile(self):
|
||||
from r2.lib.authorize.api import PaymentProfile
|
||||
profile = PaymentProfile(billTo="Joe",
|
||||
paymentId="222",
|
||||
card="1111222233334444",
|
||||
validationMode="42",
|
||||
)
|
||||
expected = ("<billTo>Joe</billTo>" +
|
||||
"<payment>" +
|
||||
"<creditCard>1111222233334444</creditCard>" +
|
||||
"</payment>" +
|
||||
"<customerPaymentProfileId>222</customerPaymentProfileId>" +
|
||||
"<validationMode>42</validationMode>")
|
||||
self.assertEqual(profile.toXML(), expected)
|
||||
|
||||
def test_transation(self):
|
||||
from r2.lib.authorize.api import Transaction
|
||||
transaction = Transaction(amount="42.42",
|
||||
profile_id="112233",
|
||||
pay_id="1111",
|
||||
trans_id="2222",
|
||||
order="42",
|
||||
)
|
||||
|
||||
expected = ("<transaction>" +
|
||||
"<amount>42.42</amount>" +
|
||||
"<customerProfileId>112233</customerProfileId>" +
|
||||
"<customerPaymentProfileId>1111</customerPaymentProfileId>" +
|
||||
"<transId>2222</transId>" +
|
||||
"<order>42</order>" +
|
||||
"</transaction>")
|
||||
self.assertEqual(transaction.toXML(), expected)
|
||||
|
||||
class ImportTest(unittest.TestCase):
|
||||
|
||||
def test_importable(self):
|
||||
#validator
|
||||
from r2.lib.authorize import Address, CreditCard
|
||||
#promotecontroller
|
||||
from r2.lib.authorize import (
|
||||
get_account_info,
|
||||
edit_profile,
|
||||
PROFILE_LIMIT,
|
||||
)
|
||||
#promote.py
|
||||
from r2.lib.authorize import (
|
||||
auth_transaction,
|
||||
charge_transaction,
|
||||
is_charged_transaction,
|
||||
void_transaction,
|
||||
)
|
||||
|
||||
|
||||
def get_suite():
|
||||
suite = unittest.TestSuite()
|
||||
suite.addTest(AuthorizeNetExceptionTest('test_exception_message'))
|
||||
suite.addTest(SimpleXMLObjectTest('test_to_xml'))
|
||||
suite.addTest(SimpleXMLObjectTest('test_simple_tag'))
|
||||
suite.addTest(SimpleXMLObjectTest('test_from_xml'))
|
||||
suite.addTest(SimpleXMLObjectTest('test_address'))
|
||||
suite.addTest(SimpleXMLObjectTest('test_credit_card'))
|
||||
suite.addTest(SimpleXMLObjectTest('test_payment_profile'))
|
||||
suite.addTest(SimpleXMLObjectTest('test_transation'))
|
||||
suite.addTest(ImportTest('test_importable'))
|
||||
return suite
|
||||
|
||||
def run_tests():
|
||||
unittest.TextTestRunner(verbosity=2).run(get_suite())
|
||||
|
||||
if __name__ == '__main__':
|
||||
run_tests()
|
||||
Reference in New Issue
Block a user