def test_get_fields_billing(self): scaffold = Scaffold() address = BillingAddress( first_name='First Name', last_name='Last Name', line1='First Line Address 1', line4='Bruxelles', postcode='1000', country_id='BE') order_data = { 'billing_address': address } fields = scaffold.get_fields_billing(None, order_data) assert Constants.BILLING_STREET in fields assert Constants.BILLING_NUMBER in fields assert Constants.BILLING_CITY in fields assert Constants.BILLING_POSTCODE in fields assert Constants.BILLING_STATE in fields assert Constants.BILLING_COUNTRY in fields assert fields[Constants.BILLING_STREET] == 'First Line Address' assert fields[Constants.BILLING_NUMBER] == '1', ( 'Since Oscar does not provide a street number we set a fake value') assert fields[Constants.BILLING_CITY] == address.city assert fields[Constants.BILLING_POSTCODE] == address.postcode assert fields[Constants.BILLING_STATE] == address.state assert fields[Constants.BILLING_COUNTRY] == address.country_id
def test_get_fields_billing(self): scaffold = Scaffold() address = BillingAddress( first_name='First Name', last_name='Last Name', line1='First Line Address', line4='Bruxelles', postcode='1000', country_id='BE') order_data = { 'billing_address': address } fields = scaffold.get_fields_billing(None, order_data) assert Constants.BILLING_STREET in fields assert Constants.BILLING_NUMBER in fields assert Constants.BILLING_CITY in fields assert Constants.BILLING_POSTCODE in fields assert Constants.BILLING_STATE in fields assert Constants.BILLING_COUNTRY in fields assert fields[Constants.BILLING_STREET] == address.line1 assert fields[Constants.BILLING_NUMBER] == '.', ( 'Since Oscar does not provide a street number we set a fake value') assert fields[Constants.BILLING_CITY] == address.city assert fields[Constants.BILLING_POSTCODE] == address.postcode assert fields[Constants.BILLING_STATE] == address.state assert fields[Constants.BILLING_COUNTRY] == address.country_id
def test_duplicate_notifications(self): """ This test tests that duplicate notifications are ignored. """ # We have a valid request. So let's confirm that we think we should process # and acknowledge it. assert (True, True) == Scaffold().assess_notification_relevance(self.request) # Let's process it then. __, __, __ = Scaffold().handle_payment_feedback(self.request) # As we have already processed that request, we now shouldn't process the request # any more. But we still acknowledge it. assert (False, True) == Scaffold().assess_notification_relevance(self.request)
def test_test_notification(self): """ Adyen can send test notifications even to the live system for debugging connection problems. We should acknowledge them, but not process. """ self.request.POST[Constants.PSP_REFERENCE] = Constants.TEST_REFERENCE_PREFIX + '_5' assert (False, True) == Scaffold().assess_notification_relevance(self.request)
def test_platform_mismatch_live_notification(self): """ If there is a mismatch between the request origin and target platforms, we should just let it be. """ self.request.POST['live'] = 'true' assert (False, False) == Scaffold().assess_notification_relevance(self.request)
def test_valid_request(self): """ If this is an `AUTHORISATION` request targeting the proper platform, we should both process and acknowledge it. This test is needed as a base assumption for the tests below. """ assert (True, True) == Scaffold().assess_notification_relevance(self.request)
def test_signing_is_enforced(self): """ Test that the supplied signature (in field merchantSig) is checked and notifications are ignored when the signature doesn't match. In an ideal world, our other tests would ignore the signature checking because it's annoying to have to alter the sig when altering the fake data. Maik gets valid signatures by adding a print(expected_hash) to PaymentRedirection.validate. """ fake_signature = copy(AUTHORISED_PAYMENT_PARAMS_GET) fake_signature['merchantSig'] = '14M4N3V1LH4X0RZ' signature_none = copy(AUTHORISED_PAYMENT_PARAMS_GET) signature_none['merchantSig'] = None signature_empty = copy(AUTHORISED_PAYMENT_PARAMS_GET) signature_empty['merchantSig'] = '' for tampered_data in [fake_signature, signature_empty, signature_none]: request = MockRequest(tampered_data) try: Scaffold().handle_payment_feedback(request) except (InvalidTransactionException, MissingFieldException): pass else: raise AssertionError( "Should've raised an exception, but didn't") # Make sure we haven't recorded any of those faulty transactions. # That way, nobody can fill up our database! assert not AdyenTransaction.objects.exists()
def test_non_authorisation(self): """ If this is not an `AUTHORISATION` request, we should acknowledge it but not try to process it. """ self.request.POST[Constants.EVENT_CODE] = 'REPORT_AVAILABLE' assert (False, True) == Scaffold().assess_notification_relevance(self.request)
def test_handle_authorised_payment(self): request = MockRequest(AUTHORISED_PAYMENT_PARAMS_GET) success, status, details = Scaffold().handle_payment_feedback(request) assert success assert status == Scaffold.PAYMENT_STATUS_ACCEPTED assert details['amount'] == 13894 assert details['ip_address'] == '127.0.0.1' assert details['method'] == 'adyen' assert details['psp_reference'] == '8814136447235922' assert details['status'] == 'AUTHORISED' # After calling `handle_payment_feedback` there is one authorised # transaction and no refused transaction in the database. assert AdyenTransaction.objects.filter( status='AUTHORISED').count() == 1 assert AdyenTransaction.objects.filter(status='REFUSED').count() == 0 # We delete the previously recorded AdyenTransaction. AdyenTransaction.objects.filter(status='AUTHORISED').delete() # We now test with POST instead of GET. request = MockRequest(AUTHORISED_PAYMENT_PARAMS_GET, method='POST') # This is going to fail because the mandatory fields are not the same # for GET and POST requests. with self.assertRaises(MissingFieldException): Scaffold().handle_payment_feedback(request) # So, let's try again with valid POST parameters. request = MockRequest(AUTHORISED_PAYMENT_PARAMS_POST, method='POST') success, status, details = Scaffold().handle_payment_feedback(request) assert success assert status == Scaffold.PAYMENT_STATUS_ACCEPTED assert details['amount'] == 21714 assert details['ip_address'] == '127.0.0.1' assert details['method'] == 'adyen' assert details['psp_reference'] == '7914120802434172' assert details['status'] == 'AUTHORISED' # After calling `handle_payment_feedback` there is one authorised # transaction and no refused transaction in the database. assert AdyenTransaction.objects.filter( status='AUTHORISED').count() == 1 assert AdyenTransaction.objects.filter(status='REFUSED').count() == 0
def test_form_fields_with_missing_mandatory_field(self): """ Test that the proper exception is raised when trying to build a fields list with a missing mandatory field. """ new_order_data = ORDER_DATA.copy() del new_order_data['amount'] with self.assertRaises(MissingFieldException): Scaffold().get_form_fields(request=None, order_data=new_order_data)
def test_form_fields_ok(self): """ Test that the payment form fields list is properly built. """ with freeze_time('2014-07-31 17:00:00'): # Any datetime will do. fields_list = Scaffold().get_form_fields(request=None, order_data=ORDER_DATA) # Order doesn't matter, so normally we'd use a set. But Python doesn't do # sets of dictionaries, so we compare individually. assert len(fields_list) == len(EXPECTED_FIELDS_LIST) for field in fields_list: assert field in EXPECTED_FIELDS_LIST
def test_get_fields_shopper(self): scaffold = Scaffold() shopper = { 'first_name': 'First Name', 'last_name': 'Last Name', } order_data = { 'adyen_shopper': shopper } fields = scaffold.get_fields_shopper(None, order_data) assert Constants.SHOPPER_FIRSTNAME in fields assert Constants.SHOPPER_INFIX in fields assert Constants.SHOPPER_LASTNAME in fields assert Constants.SHOPPER_GENDER in fields assert Constants.SHOPPER_BIRTH_DAY in fields assert Constants.SHOPPER_BIRTH_MONTH in fields assert Constants.SHOPPER_BIRTH_YEAR in fields assert Constants.SHOPPER_PHONE in fields assert fields[Constants.SHOPPER_FIRSTNAME] == 'First Name' assert fields[Constants.SHOPPER_INFIX] == '' assert fields[Constants.SHOPPER_LASTNAME] == 'Last Name' assert fields[Constants.SHOPPER_GENDER] == '' assert fields[Constants.SHOPPER_BIRTH_DAY] == '' assert fields[Constants.SHOPPER_BIRTH_MONTH] == '' assert fields[Constants.SHOPPER_BIRTH_YEAR] == '' assert fields[Constants.SHOPPER_PHONE] == '' shopper['birthdate'] = datetime.date(1815, 12, 10) order_data = { 'adyen_shopper': shopper } fields = scaffold.get_fields_shopper(None, order_data) assert fields[Constants.SHOPPER_BIRTH_DAY] == '10' assert fields[Constants.SHOPPER_BIRTH_MONTH] == '12' assert fields[Constants.SHOPPER_BIRTH_YEAR] == '1815'
def test_get_street_housenr(self): scaffold = Scaffold() address = ShippingAddress(first_name='First Name', last_name='Last Name', line1='First Line Address 1', line4='Bruxelles', postcode='1000', country_id='BE') street, housenr = scaffold.get_street_housenr(address) assert housenr == '1' address.line1 = 'First Line Address' address.line2 = '1' street, housenr = scaffold.get_street_housenr(address) assert housenr == '1' address.line1 = 'First Line' address.line2 = 'Address' address.line3 = '1' street, housenr = scaffold.get_street_housenr(address) assert housenr == '1'
def test_get_street_housenr(self): scaffold = Scaffold() address = ShippingAddress( first_name='First Name', last_name='Last Name', line1='First Line Address 1', line4='Bruxelles', postcode='1000', country_id='BE') street, housenr = scaffold.get_street_housenr(address) assert housenr == '1' address.line1 = 'First Line Address' address.line2 = '1' street, housenr = scaffold.get_street_housenr(address) assert housenr == '1' address.line1 = 'First Line' address.line2 = 'Address' address.line3 = '1' street, housenr = scaffold.get_street_housenr(address) assert housenr == '1'
def test_handle_pending_payment(self): # Modified actual data (see test_handle_error_payment) request = MockRequest({ 'authResult': 'PENDING', 'merchantReference': '09016057', 'merchantReturnData': '29232', 'merchantSig': 'QTUYO2Bk9CbVCfUztp+MuCFe8do=', 'paymentMethod': 'visa', 'shopperLocale': 'fr', 'skinCode': '4d72uQqA', }) success, status, __ = Scaffold().handle_payment_feedback(request) assert (not success) and (status == Scaffold.PAYMENT_STATUS_PENDING) assert AdyenTransaction.objects.filter(status='PENDING').count() == 1
def test_handle_cancelled_payment(self): request = MockRequest({ 'authResult': 'CANCELLED', 'merchantReference': 'WVubjVRFOTPBsLNy33zqliF-vmc:110:00000110', 'merchantReturnData': '13894', 'merchantSig': 'AMkos00Nn+bTgS3Ndm2bgnRBj1c=', 'shopperLocale': 'en_GB', 'skinCode': '4d72uQqA', }) success, status, __ = Scaffold().handle_payment_feedback(request) assert (not success) and (status == Scaffold.PAYMENT_STATUS_CANCELLED) # After the test there's one cancelled transaction and no authorised transaction in the DB. assert AdyenTransaction.objects.filter( status='AUTHORISED').count() == 0 assert AdyenTransaction.objects.filter(status='CANCELLED').count() == 1
def test_handle_error_payment(self): # This is actual data received from Adyen causing a bug. # The merchantSig hash was replaced to pass hashing with the test secret key. request = MockRequest({ 'authResult': 'ERROR', 'merchantReference': '09016057', 'merchantReturnData': '29232', 'merchantSig': 'Y2lpKZPCOpK7WAlCVSgUQcJ9+xQ=', 'paymentMethod': 'visa', 'shopperLocale': 'fr', 'skinCode': '4d72uQqA', }) success, status, __ = Scaffold().handle_payment_feedback(request) assert (not success) and (status == Scaffold.PAYMENT_STATUS_ERROR) assert AdyenTransaction.objects.filter(status='ERROR').count() == 1
def test_handle_refused_payment(self): request = MockRequest({ 'authResult': 'REFUSED', 'merchantReference': 'WVubjVRFOTPBsLNy33zqliF-vmc:110:00000110', 'merchantReturnData': '13894', 'merchantSig': '1fFM0LaC0uhsN3L/C9nddUeMiyw=', 'paymentMethod': 'visa', 'pspReference': '8814136452896857', 'shopperLocale': 'en_GB', 'skinCode': '4d72uQqA', }) success, status, __ = Scaffold().handle_payment_feedback(request) assert (not success) and (status == Scaffold.PAYMENT_STATUS_REFUSED) # After the test there's one refused transaction and no authorised transaction in the DB. assert AdyenTransaction.objects.filter( status='AUTHORISED').count() == 0 assert AdyenTransaction.objects.filter(status='REFUSED').count() == 1
def test_handle_authorized_payment_if_no_ip_address_was_found(self): """ A slight variation on the previous test. We just want to ensure that the backend does not crash if we haven't been able to find a reliable origin IP address. """ # We create a request so no IP address will be found... request = MockRequest(AUTHORISED_PAYMENT_PARAMS_GET, remote_address=None) # ... double-check that the IP address is, therefore, `None` ... assert Facade()._get_origin_ip_address(request) is None # ... and finally make sure everything works as expected. success, status, details = Scaffold().handle_payment_feedback(request) assert success assert status == Scaffold.PAYMENT_STATUS_ACCEPTED assert details['ip_address'] is None # After the test there's one authorised transaction and no refused transaction in the DB. assert AdyenTransaction.objects.filter( status='AUTHORISED').count() == 1 assert AdyenTransaction.objects.filter(status='REFUSED').count() == 0
def test_form_action(self): """ Test that the form action is properly fetched from the settings. """ assert 'foo' == Scaffold().get_form_action(request=None)
def test_platform_mismatch_live_server(self): self.request.POST['live'] = 'false' with self.settings(ADYEN_ACTION_URL='https://live.adyen.com/hpp/select.shtml'): assert (False, False) == Scaffold().assess_notification_relevance(self.request)