def test_idempotence_second_request(self): """ Test that the client can successfully handle a response indicating a request has been sent prior """ response_body = read_resource("idempotence_success.json") idempotence_key = str(uuid.uuid4()) idempotence_timestamp = str(int(time.time() * 1000)) call_context = CallContext(idempotence_key) request = create_payment_request() test_path = "/v2/1/payments" # relative url through which the request should be sent additional_headers \ = (("Content-Type", "application/json"), ("Location", "http://localhost/v2/1/payments/1_1"), ("X-GCS-Idempotence-Request-Timestamp", idempotence_timestamp)) handler = self.create_handler(response_code=201, body=response_body, additional_headers=additional_headers) with create_server_listening(handler) as address: with create_client(address) as client: response = client.merchant("1").payments().create_payment(request, call_context) self.assertIsNotNone(response) self.assertIsNotNone(response.payment) self.assertIsNotNone(response.payment.id) self.assertEqual(test_path, self.request_path, 'Request has arrived at the wrong path') self.assertEqual(idempotence_key, self.idempotence_header, "Wrong idempotence key is sent in the request") self.assertEqual(idempotence_key, call_context.idempotence_key) self.assertEqual(int(idempotence_timestamp), int(call_context.idempotence_request_timestamp))
def test_idempotence_duplicate_request(self): """Test a request where a request arrived twice""" response_body = read_resource("idempotence_duplicate_failure.json") idempotence_key = str(uuid.uuid4()) idempotence_timestamp = str(int(time.time() * 1000)) call_context = CallContext(idempotence_key) request = create_payment_request() test_path = "/v2/1/payments" # relative url through which the request should be sent additional_headers = (("Content-Type", "application/json"), ("X-GCS-Idempotence-Request-Timestamp", idempotence_timestamp)) handler = self.create_handler(response_code=409, body=response_body, additional_headers=additional_headers) with create_server_listening(handler) as address: with create_client(address) as client: with self.assertRaises(IdempotenceException) as exc: client.merchant("1").payments().create_payment(request, call_context) self.assertEqual(409, exc.exception.status_code) self.assertEqual(response_body, exc.exception.response_body) self.assertEqual(idempotence_key, exc.exception.idempotence_key) self.assertEqual(idempotence_key, self.idempotence_header, "Wrong idempotence key is sent in the request") self.assertEqual(idempotence_key, call_context.idempotence_key) self.assertEqual(test_path, self.request_path, 'Request has arrived at the wrong path') self.assertEqual(int(idempotence_timestamp), int(call_context.idempotence_request_timestamp))
def test_idempotence(self): """Test that the client can successfully detect that an idempotent request is sent twice""" amount_of_money = AmountOfMoney() amount_of_money.currency_code = "EUR" amount_of_money.amount = 100 billing_address = Address() billing_address.country_code = "BE" customer = Customer() customer.locale = "en" customer.billing_address = billing_address order = Order() order.amount_of_money = amount_of_money order.customer = customer card = Card() card.card_number = "4567350000427977" card.cardholder_name = "Wile E. Coyote" card.cvv = "123" card.expiry_date = "1234" payment_method_input = CardPaymentMethodSpecificInput() payment_method_input.return_url = "http://example.com" payment_method_input.payment_product_id = 1 payment_method_input.card = card body = CreatePaymentRequest() body.order = order body.card_payment_method_specific_input = payment_method_input idempotence_key = str(uuid.uuid4()) context = CallContext(idempotence_key) with init_utils.create_client() as client: response = client.merchant(MERCHANT_ID).payments().create_payment( body, context) payment_id = response.payment.id self.assertEqual(idempotence_key, context.idempotence_key) self.assertIsNone(context.idempotence_request_timestamp) response_2 = client.merchant( MERCHANT_ID).payments().create_payment(body, context) payment_id_2 = response_2.payment.id self.assertEqual(payment_id, payment_id_2) self.assertEqual(idempotence_key, context.idempotence_key) self.assertIsNotNone(context.idempotence_request_timestamp)
def test_idempotence_first_failure(self): """Test a request where a request is rejected without prior requests""" response_body = read_resource("idempotence_rejected.json") idempotence_key = str(uuid.uuid4()) call_context = CallContext(idempotence_key) request = create_payment_request() test_path = "/v2/1/payments" # relative url through which the request should be sent handler = self.create_handler(response_code=402, body=response_body, additional_headers=(("Content-Type", "application/json"),)) with create_server_listening(handler) as address: with create_client(address) as client: with self.assertRaises(DeclinedPaymentException) as exc: client.merchant("1").payments().create_payment(request, call_context) self.assertEqual(402, exc.exception.status_code) self.assertEqual(response_body, exc.exception.response_body) self.assertEqual(test_path, self.request_path, 'Request has arrived at the wrong path') self.assertEqual(idempotence_key, self.idempotence_header, "Wrong idempotence key is sent in the request") self.assertEqual(idempotence_key, call_context.idempotence_key) self.assertIsNone(call_context.idempotence_request_timestamp)
def test_create_idempotence_error(self): """Tests that a 409 failure response with a duplicate request code and an idempotence key will throw an IdempotenceException """ client = Factory.create_client_from_communicator(self.communicator) response_body = read_resource("duplicate_request.json") request_body = create_request() context = CallContext("key") def receive_post(uri, request_headers, body): def generate_response(): for start in range(0, len(response_body), 1024): yield response_body[start: start + 1024].encode('utf-8') return 409, None, generate_response() self.mock_connection.post.side_effect = receive_post with self.assertRaises(IdempotenceException) as exception: client.merchant("merchantId").payments().create_payment(request_body, context) self.assertIn(response_body, str(exception.exception)) self.assertEqual(context.idempotence_key, exception.exception.idempotence_key)