From 5107dd87f4ca9deae13022a8a67055aeef0dd761 Mon Sep 17 00:00:00 2001 From: Vincent Catalano Date: Sat, 7 Feb 2015 19:05:05 +0000 Subject: [PATCH] Issue 30: Add functionality for updating credit card with masked number --- authorize/apis/credit_card_api.py | 9 ++++- authorize/schemas.py | 6 ++++ tests/test_credit_card_api.py | 60 +++++++++++++++++++++++++++++++ tests/test_live_credit_card.py | 31 +++++++++++++++- tests/test_schemas.py | 7 ++++ 5 files changed, 111 insertions(+), 2 deletions(-) diff --git a/authorize/apis/credit_card_api.py b/authorize/apis/credit_card_api.py index 3679904..09b281b 100644 --- a/authorize/apis/credit_card_api.py +++ b/authorize/apis/credit_card_api.py @@ -1,5 +1,6 @@ from authorize.apis.payment_profile_api import PaymentProfileAPI from authorize.schemas import CreateCreditCardSchema +from authorize.schemas import UpdateCreditCardSchema from authorize.schemas import ValidateCreditCardSchema from authorize.xml_data import * @@ -11,7 +12,7 @@ def create(self, customer_id, 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) + card = self._deserialize(UpdateCreditCardSchema(), params) return self.api._make_call(self._update_request(customer_id, payment_id, card)) def validate(self, customer_id, payment_id, params={}): @@ -24,6 +25,12 @@ 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={}): + + # Issue 30: If only the last 4 digits of a credit card are provided, + # add the additional XXXX character mask that is required. + if len(card['card_number']) == 4: + card['card_number'] = 'XXXX' + card['card_number'] + return self._make_xml('updateCustomerPaymentProfileRequest', customer_id, payment_id, params=card) def _validate_request(self, customer_id, payment_id, card={}): diff --git a/authorize/schemas.py b/authorize/schemas.py index 64ef0f0..6508d50 100644 --- a/authorize/schemas.py +++ b/authorize/schemas.py @@ -163,6 +163,12 @@ class CreateCreditCardSchema(CreditCardSchema, CustomerTypeSchema): billing = AddressSchema(missing=colander.drop) +class UpdateCreditCardSchema(CreateCreditCardSchema): + card_number = colander.SchemaNode(colander.String(), + validator=colander.Length(min=4), + required=True) + + class ValidateCreditCardSchema(colander.MappingSchema): address_id = colander.SchemaNode(colander.String(), validator=colander.Length(max=60), diff --git a/tests/test_credit_card_api.py b/tests/test_credit_card_api.py index 9ed4e6e..2cfd9f8 100644 --- a/tests/test_credit_card_api.py +++ b/tests/test_credit_card_api.py @@ -23,6 +23,27 @@ }, } +# Update the credit card information except the card number +UPDATE_CREDIT_CARD_INFO = { + 'customer_type': 'individual', + 'card_number': '1111', + 'card_code': '456', + 'expiration_month': '04', + 'expiration_year': '2014', + 'billing': { + 'first_name': 'Rob', + 'last_name': 'Oteron', + 'company': 'Robotron Studios', + 'address': '101 Computer Street', + 'city': 'Tucson', + 'state': 'AZ', + 'zip': '85704', + 'country': 'US', + 'phone_number': '520-123-4567', + 'fax_number': '520-456-7890', + }, +} + VALIDATE_CREDIT_CARD = { 'address_id': '7982053235', 'card_code': '456', @@ -108,6 +129,40 @@ ''' +UPDATE_CREDIT_CARD_INFO_REQUEST = ''' + + + + 8s8tVnG5t + 5GK7mncw8mG2946z + + 1234567890 + + individual + + Rob + Oteron + Robotron Studios +
101 Computer Street
+ Tucson + AZ + 85704 + US + 520-123-4567 + 520-456-7890 +
+ + + XXXX1111 + 2014-04 + 456 + + + 0987654321 +
+
+''' + DELETE_CREDIT_CARD_REQUEST = ''' @@ -155,6 +210,11 @@ def test_update_credit_card_request(self): request_string = prettify(request_xml) self.assertEqual(request_string, UPDATE_CREDIT_CARD_REQUEST.strip()) + def test_update_credit_card_info_request(self): + request_xml = Configuration.api.credit_card._update_request('1234567890', '0987654321', UPDATE_CREDIT_CARD_INFO) + request_string = prettify(request_xml) + self.assertEqual(request_string, UPDATE_CREDIT_CARD_INFO_REQUEST.strip()) + def test_delete_credit_card_request(self): request_xml = Configuration.api.credit_card._delete_request('1234567890', '0987654321') request_string = prettify(request_xml) diff --git a/tests/test_live_credit_card.py b/tests/test_live_credit_card.py index 70515db..b6e44e2 100644 --- a/tests/test_live_credit_card.py +++ b/tests/test_live_credit_card.py @@ -32,6 +32,30 @@ }, } +UPDATE_CREDIT_CARD = { + 'card_number': '5555555555554444', + 'expiration_date': '04/{0}'.format(date.today().year + 1), + 'card_code': '567', +} + +UPDATE_CREDIT_CARD_WITH_MASK = { + 'card_number': 'XXXX4444', + 'expiration_date': '04/{0}'.format(date.today().year + 1), + 'card_code': '567', +} + +UPDATE_CREDIT_CARD_WITHOUT_MASK = { + 'card_number': '4444', + 'expiration_date': '04/{0}'.format(date.today().year + 1), + 'card_code': '567', +} + +UPDATE_CREDIT_CARD_INVALID_MASK = { + 'card_number': '1111', + 'expiration_date': '04/{0}'.format(date.today().year + 1), + 'card_code': '567', +} + PAYMENT_RESULT = { 'credit_card': { 'card_number': 'XXXX1111', @@ -61,7 +85,12 @@ def test_live_basic_credit_card(self): self.assertEquals(PAYMENT_RESULT, result.payment_profile.payment) # Update credit card - CreditCard.update(customer_id, payment_id, CREDIT_CARD) + CreditCard.update(customer_id, payment_id, UPDATE_CREDIT_CARD) + CreditCard.update(customer_id, payment_id, UPDATE_CREDIT_CARD_WITH_MASK) + CreditCard.update(customer_id, payment_id, UPDATE_CREDIT_CARD_WITHOUT_MASK) + + # Invalid masked number + self.assertRaises(AuthorizeResponseError, CreditCard.update, customer_id, payment_id, UPDATE_CREDIT_CARD_INVALID_MASK) # Delete tests CreditCard.delete(customer_id, payment_id) diff --git a/tests/test_schemas.py b/tests/test_schemas.py index b262cc9..e3306b6 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -50,6 +50,13 @@ 'expiration_date': '04/{0}'.format(date.today().year + 1), } +UPDATE_CREDIT_CARD_EXP_MONTH_AND_YEAR = { + 'card_number': '4111111111111111', + 'card_code': '456', + 'expiration_month': '04', + 'expiration_year': str(date.today().year + 1) +} + INVALID_CREDIT_CARD_NUMBER = { 'card_number': 'Bad card number', 'card_code': '456',