Skip to content

Commit

Permalink
Initial code commit
Browse files Browse the repository at this point in the history
  • Loading branch information
vcatalano committed Jun 12, 2013
1 parent 5860475 commit c0ee75c
Show file tree
Hide file tree
Showing 60 changed files with 5,891 additions and 32 deletions.
39 changes: 7 additions & 32 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,35 +1,10 @@
*.py[cod]

# C extensions
*.so
*.py[co]
.DS_Store
docs/_build/
build/
dist/
Authorize.egg-info/
PyAuthorize.egg-info/

# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
lib
lib64

# Installer logs
pip-log.txt

# Unit test / coverage reports
.coverage
.tox
nosetests.xml

# Translations
*.mo

# Mr Developer
.mr.developer.cfg
.project
.pydevproject
13 changes: 13 additions & 0 deletions authorize/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from authorize.configuration import Configuration
from authorize.address import Address
from authorize.bank_account import BankAccount
from authorize.batch import Batch
from authorize.credit_card import CreditCard
from authorize.customer import Customer
from authorize.environment import Environment
from authorize.exceptions import AuthorizeError
from authorize.exceptions import AuthorizeConnectionError
from authorize.exceptions import AuthorizeResponseError
from authorize.exceptions import AuthorizeInvalidError
from authorize.recurring import Recurring
from authorize.transaction import Transaction
20 changes: 20 additions & 0 deletions authorize/address.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from authorize import Configuration


class Address(object):

@staticmethod
def create(customer_id, params={}):
return Configuration.api.address.create(customer_id, params)

@staticmethod
def details(customer_id, address_id):
return Configuration.api.address.details(customer_id, address_id)

@staticmethod
def update(customer_id, address_id, params={}):
return Configuration.api.address.update(customer_id, address_id, params)

@staticmethod
def delete(customer_id, address_id):
return Configuration.api.address.delete(customer_id, address_id)
Empty file added authorize/apis/__init__.py
Empty file.
57 changes: 57 additions & 0 deletions authorize/apis/address_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import xml.etree.cElementTree as E

from authorize.apis.base_api import BaseAPI
from authorize.schemas import AddressSchema
from authorize.xml_data import *


class AddressAPI(BaseAPI):

def create(self, customer_id, params={}):
address = self._deserialize(AddressSchema(), params)
return self.api._make_call(self._create_request(customer_id, address))

def details(self, customer_id, address_id):
return self.api._make_call(self._details_request(customer_id, address_id))

def update(self, customer_id, address_id, params={}):
address = self._deserialize(AddressSchema(), params)
return self.api._make_call(self._update_request(customer_id, address_id, address))

def delete(self, customer_id, address_id):
self.api._make_call(self._delete_request(customer_id, address_id))

# The following methods generate the XML for the corresponding API calls.
# This makes unit testing each of the calls easier.
def _create_request(self, customer_id, address={}):
return self._make_xml('createCustomerShippingAddressRequest', customer_id, None, params=address)

def _details_request(self, customer_id, address_id):
request = self.api._base_request('getCustomerShippingAddressRequest')
E.SubElement(request, 'customerProfileId').text = customer_id
E.SubElement(request, 'customerAddressId').text = address_id
return request

def _update_request(self, customer_id, address_id, address={}):
return self._make_xml('updateCustomerShippingAddressRequest', customer_id, address_id, params=address)

def _delete_request(self, customer_id, address_id):
request = self.api._base_request('deleteCustomerShippingAddressRequest')
E.SubElement(request, 'customerProfileId').text = customer_id
E.SubElement(request, 'customerAddressId').text = address_id
return request

def _make_xml(self, method, customer_id=None, address_id=None, params={}):
request = self.api._base_request(method)

if customer_id:
E.SubElement(request, 'customerProfileId').text = customer_id

address_data = create_address('address', params)

if address_id:
E.SubElement(address_data, 'customerAddressId').text = address_id

request.append(address_data)

return request
68 changes: 68 additions & 0 deletions authorize/apis/authorize_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import urllib2
import xml.etree.cElementTree as E

from urllib2 import HTTPError

from authorize.apis.address_api import AddressAPI
from authorize.apis.credit_card_api import CreditCardAPI
from authorize.apis.customer_api import CustomerAPI
from authorize.apis.bank_account_api import BankAccountAPI
from authorize.apis.batch_api import BatchAPI
from authorize.apis.recurring_api import RecurringAPI
from authorize.apis.transaction_api import TransactionAPI
from authorize.exceptions import AuthorizeConnectionError
from authorize.exceptions import AuthorizeResponseError
from authorize.response_parser import parse_response
from authorize.xml_data import *

E.register_namespace('', 'AnetApi/xml/v1/schema/AnetApiSchema.xsd')


class AuthorizeAPI(object):

def __init__(self, config):
"""Allow for multiple instances of the Authorize API."""
self.config = config
self.customer = CustomerAPI(self)
self.credit_card = CreditCardAPI(self)
self.bank_account = BankAccountAPI(self)
self.address = AddressAPI(self)
self.recurring = RecurringAPI(self)
self.batch = BatchAPI(self)
self.transaction = TransactionAPI(self)

@property
def client_auth(self):
"""Generate an XML element with client auth data populated."""
if not hasattr(self, '_client_auth'):
self._client_auth = E.Element('merchantAuthentication')
E.SubElement(self._client_auth, 'name').text = self.config.login_id
E.SubElement(self._client_auth, 'transactionKey').text = self.config.transaction_key
return self._client_auth

def _base_request(self, method):
"""Factory method for generating the base XML requests."""
request = E.Element(method)
request.set('xmlns', 'AnetApi/xml/v1/schema/AnetApiSchema.xsd')
request.append(self.client_auth)
return request

def _make_call(self, call):
"""Make a call to the Authorize.net server with the XML."""
try:
request = urllib2.Request(self.config.environment, E.tostring(call))
request.add_header('Content-Type', 'text/xml')
response = urllib2.urlopen(request).read()
response = E.fromstring(response)
result = parse_response(response)
except HTTPError, e:
return AuthorizeConnectionError('Error processing XML request.')

# Throw an exception for invalid calls. This makes error handling
# easier.
if result.messages.result_code != 'Ok':
error = result.messages.message
e = AuthorizeResponseError('%s: %s' % (error.code, error.text))
e.full_response = result
raise e
return result
22 changes: 22 additions & 0 deletions authorize/apis/bank_account_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from authorize.apis.payment_profile_api import PaymentProfileAPI
from authorize.schemas import CreateBankAccountSchema
from authorize.xml_data import *


class BankAccountAPI(PaymentProfileAPI):

def create(self, customer_id, params={}):
card = self._deserialize(CreateBankAccountSchema(), params)
return self.api._make_call(self._create_request(customer_id, card))

def update(self, customer_id, payment_id, params={}):
card = self._deserialize(CreateBankAccountSchema(), params)
return self.api._make_call(self._update_request(customer_id, payment_id, card))

# The following methods generate the XML for the corresponding API calls.
# This makes unit testing each of the calls easier.
def _create_request(self, customer_id, card={}):
return self._make_xml('createCustomerPaymentProfileRequest', customer_id, None, params=card)

def _update_request(self, customer_id, payment_id, card={}):
return self._make_xml('updateCustomerPaymentProfileRequest', customer_id, payment_id, params=card)
17 changes: 17 additions & 0 deletions authorize/apis/base_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import colander

from authorize.exceptions import AuthorizeInvalidError


class BaseAPI(object):

def __init__(self, api):
self.api = api
self.config = api.config

def _deserialize(self, schema, params={}):
try:
deserialized = schema.deserialize(params)
except colander.Invalid as e:
raise AuthorizeInvalidError(e)
return deserialized
31 changes: 31 additions & 0 deletions authorize/apis/batch_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import xml.etree.cElementTree as E

from authorize.apis.base_api import BaseAPI
from authorize.schemas import ListBatchSchema
from authorize.xml_data import *


class BatchAPI(BaseAPI):

def details(self, batch_id):
return self.api._make_call(self._details_request(batch_id))

def list(self, params={}):
batch = self._deserialize(ListBatchSchema(), params)
return self.api._make_call(self._list_request(batch))

# The following methods generate the XML for the corresponding API calls.
# This makes unit testing each of the calls easier.
def _details_request(self, batch_id):
request = self.api._base_request('getBatchStatisticsRequest')
E.SubElement(request, 'batchId').text = batch_id
return request

def _list_request(self, params={}):
request = self.api._base_request('getSettledBatchListRequest')
E.SubElement(request, 'includeStatistics').text = 'true'
if 'start' in params:
E.SubElement(request, 'firstSettlementDate').text = params['start']
if 'end' in params:
E.SubElement(request, 'lastSettlementDate').text = params['end']
return request
42 changes: 42 additions & 0 deletions authorize/apis/credit_card_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from authorize.apis.payment_profile_api import PaymentProfileAPI
from authorize.schemas import CreateCreditCardSchema
from authorize.schemas import ValidateCreditCardSchema
from authorize.xml_data import *


class CreditCardAPI(PaymentProfileAPI):

def create(self, customer_id, params={}):
card = self._deserialize(CreateCreditCardSchema(), params)
return self.api._make_call(self._create_request(customer_id, card))

def update(self, customer_id, payment_id, params={}):
card = self._deserialize(CreateCreditCardSchema(), params)
return self.api._make_call(self._update_request(customer_id, payment_id, card))

def validate(self, customer_id, payment_id, params={}):
card = self._deserialize(ValidateCreditCardSchema(), params)
return self.api._make_call(self._validate_request(customer_id, payment_id, card))

# The following methods generate the XML for the corresponding API calls.
# This makes unit testing each of the calls easier.
def _create_request(self, customer_id, card={}):
return self._make_xml('createCustomerPaymentProfileRequest', customer_id, None, params=card)

def _update_request(self, customer_id, payment_id, card={}):
return self._make_xml('updateCustomerPaymentProfileRequest', customer_id, payment_id, params=card)

def _validate_request(self, customer_id, payment_id, card={}):
request = self.api._base_request('validateCustomerPaymentProfileRequest')
E.SubElement(request, 'customerProfileId').text = customer_id
E.SubElement(request, 'customerPaymentProfileId').text = payment_id

if 'address_id' in card:
E.SubElement(request, 'customerShippingAddressId').text = card['address_id']

if 'card_code' in card:
E.SubElement(request, 'cardCode').text = str(card['card_code'])

E.SubElement(request, 'validationMode').text = card['validation_mode']

return request
78 changes: 78 additions & 0 deletions authorize/apis/customer_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import xml.etree.cElementTree as E

from authorize.apis.base_api import BaseAPI
from authorize.schemas import CustomerBaseSchema
from authorize.schemas import CreateCustomerSchema
from authorize.xml_data import *


class CustomerAPI(BaseAPI):

def create(self, params={}):
customer = self._deserialize(CreateCustomerSchema().bind(), params)
return self.api._make_call(self._create_request(customer))

def details(self, customer_id):
return self.api._make_call(self._details_request(customer_id))

def update(self, customer_id, params={}):
customer = self._deserialize(CustomerBaseSchema().bind(), params)
return self.api._make_call(self._update_request(customer_id, customer))

def delete(self, customer_id):
return self.api._make_call(self._delete_request(customer_id))

def list(self):
return self.api._make_call(self.api._base_request('getCustomerProfileIdsRequest'))

# The following methods generate the XML for the corresponding API calls.
# This makes unit testing each of the calls easier.
def _create_request(self, customer={}):
request = self.api._base_request('createCustomerProfileRequest')
profile = create_profile(customer)

payment_profiles = E.Element('paymentProfiles')

# We are only concerned about payment profile information if a
# payment method is included
if 'credit_card' in customer or 'bank_account' in customer:
# Customer type
if 'customer_type' in customer:
E.SubElement(payment_profiles, 'customerType').text = customer['customer_type']

# Customer billing information
if 'billing' in customer:
payment_profiles.append(create_address('billTo', customer['billing']))

# Payment method
payment = E.SubElement(payment_profiles, 'payment')
if 'credit_card' in customer:
payment.append(create_card(customer['credit_card']))
else:
payment.append(create_account(customer['bank_account']))
profile.append(payment_profiles)

# Customer shipping information
if 'shipping' in customer:
profile.append(create_address('shipToList', customer['shipping']))

request.append(profile)

return request

def _details_request(self, customer_id):
request = self.api._base_request('getCustomerProfileRequest')
E.SubElement(request, 'customerProfileId').text = customer_id
return request

def _update_request(self, customer_id, customer):
request = self.api._base_request('updateCustomerProfileRequest')
profile = create_profile(customer)
E.SubElement(profile, 'customerProfileId').text = customer_id
request.append(profile)
return request

def _delete_request(self, customer_id):
request = self.api._base_request('deleteCustomerProfileRequest')
E.SubElement(request, 'customerProfileId').text = customer_id
return request
Loading

0 comments on commit c0ee75c

Please sign in to comment.