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:
Kevin Kress
2012-12-23 22:28:23 -08:00
committed by Keith Mitchell
parent 288b9be012
commit 9b83d48eba
4 changed files with 344 additions and 115 deletions

View File

@@ -20,4 +20,5 @@
# Inc. All Rights Reserved.
###############################################################################
from api import *
from interaction import *

View File

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

View File

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

View 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()