direct-sdk-ruby 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +141 -0
- data/Rakefile +34 -0
- data/direct-sdk-ruby.gemspec +28 -0
- data/lib/ingenico/direct/sdk.rb +26 -0
- data/lib/ingenico/direct/sdk/api_exception.rb +42 -0
- data/lib/ingenico/direct/sdk/api_resource.rb +115 -0
- data/lib/ingenico/direct/sdk/authenticator.rb +16 -0
- data/lib/ingenico/direct/sdk/authorization_exception.rb +13 -0
- data/lib/ingenico/direct/sdk/call_context.rb +26 -0
- data/lib/ingenico/direct/sdk/client.rb +85 -0
- data/lib/ingenico/direct/sdk/communication_exception.rb +16 -0
- data/lib/ingenico/direct/sdk/communicator.rb +301 -0
- data/lib/ingenico/direct/sdk/communicator_configuration.rb +59 -0
- data/lib/ingenico/direct/sdk/connection.rb +41 -0
- data/lib/ingenico/direct/sdk/data_object.rb +32 -0
- data/lib/ingenico/direct/sdk/declined_payment_exception.rb +30 -0
- data/lib/ingenico/direct/sdk/declined_payout_exception.rb +32 -0
- data/lib/ingenico/direct/sdk/declined_refund_exception.rb +32 -0
- data/lib/ingenico/direct/sdk/declined_transaction_exception.rb +16 -0
- data/lib/ingenico/direct/sdk/defaultimpl.rb +6 -0
- data/lib/ingenico/direct/sdk/defaultimpl/authorization_type.rb +24 -0
- data/lib/ingenico/direct/sdk/defaultimpl/default_authenticator.rb +108 -0
- data/lib/ingenico/direct/sdk/defaultimpl/default_connection.rb +293 -0
- data/lib/ingenico/direct/sdk/defaultimpl/default_marshaller.rb +32 -0
- data/lib/ingenico/direct/sdk/direct_exception.rb +15 -0
- data/lib/ingenico/direct/sdk/domain/account_on_file.rb +50 -0
- data/lib/ingenico/direct/sdk/domain/account_on_file_attribute.rb +39 -0
- data/lib/ingenico/direct/sdk/domain/account_on_file_display_hints.rb +38 -0
- data/lib/ingenico/direct/sdk/domain/additional_order_input.rb +47 -0
- data/lib/ingenico/direct/sdk/domain/address.rb +51 -0
- data/lib/ingenico/direct/sdk/domain/address_personal.rb +59 -0
- data/lib/ingenico/direct/sdk/domain/airline_data.rb +129 -0
- data/lib/ingenico/direct/sdk/domain/airline_flight_leg.rb +99 -0
- data/lib/ingenico/direct/sdk/domain/airline_passenger.rb +39 -0
- data/lib/ingenico/direct/sdk/domain/amount_breakdown.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/amount_of_money.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/api_error.rb +47 -0
- data/lib/ingenico/direct/sdk/domain/browser_data.rb +39 -0
- data/lib/ingenico/direct/sdk/domain/cancel_payment_response.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/capture.rb +47 -0
- data/lib/ingenico/direct/sdk/domain/capture_output.rb +79 -0
- data/lib/ingenico/direct/sdk/domain/capture_payment_request.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/capture_response.rb +47 -0
- data/lib/ingenico/direct/sdk/domain/capture_status_output.rb +27 -0
- data/lib/ingenico/direct/sdk/domain/captures_response.rb +34 -0
- data/lib/ingenico/direct/sdk/domain/card.rb +39 -0
- data/lib/ingenico/direct/sdk/domain/card_essentials.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/card_fraud_results.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/card_payment_method_specific_input.rb +95 -0
- data/lib/ingenico/direct/sdk/domain/card_payment_method_specific_input_base.rb +79 -0
- data/lib/ingenico/direct/sdk/domain/card_payment_method_specific_output.rb +67 -0
- data/lib/ingenico/direct/sdk/domain/card_payout_method_specific_input.rb +39 -0
- data/lib/ingenico/direct/sdk/domain/card_recurrence_details.rb +27 -0
- data/lib/ingenico/direct/sdk/domain/card_without_cvv.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/company_information.rb +27 -0
- data/lib/ingenico/direct/sdk/domain/complete_payment_card_payment_method_specific_input.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/complete_payment_request.rb +39 -0
- data/lib/ingenico/direct/sdk/domain/complete_payment_response.rb +47 -0
- data/lib/ingenico/direct/sdk/domain/contact_details.rb +43 -0
- data/lib/ingenico/direct/sdk/domain/create_hosted_checkout_request.rb +63 -0
- data/lib/ingenico/direct/sdk/domain/create_hosted_checkout_response.rb +49 -0
- data/lib/ingenico/direct/sdk/domain/create_hosted_tokenization_request.rb +39 -0
- data/lib/ingenico/direct/sdk/domain/create_hosted_tokenization_response.rb +41 -0
- data/lib/ingenico/direct/sdk/domain/create_payment_request.rb +67 -0
- data/lib/ingenico/direct/sdk/domain/create_payment_response.rb +47 -0
- data/lib/ingenico/direct/sdk/domain/create_payout_request.rb +47 -0
- data/lib/ingenico/direct/sdk/domain/create_token_request.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/created_payment_output.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/created_token_response.rb +51 -0
- data/lib/ingenico/direct/sdk/domain/customer.rb +87 -0
- data/lib/ingenico/direct/sdk/domain/customer_account.rb +71 -0
- data/lib/ingenico/direct/sdk/domain/customer_account_authentication.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/customer_device.rb +51 -0
- data/lib/ingenico/direct/sdk/domain/customer_payment_activity.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/customer_token.rb +47 -0
- data/lib/ingenico/direct/sdk/domain/decrypted_payment_data.rb +43 -0
- data/lib/ingenico/direct/sdk/domain/directory_entry.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/empty_validator.rb +13 -0
- data/lib/ingenico/direct/sdk/domain/error_response.rb +38 -0
- data/lib/ingenico/direct/sdk/domain/external_cardholder_authentication_data.rb +59 -0
- data/lib/ingenico/direct/sdk/domain/external_token_linked.rb +27 -0
- data/lib/ingenico/direct/sdk/domain/fixed_list_validator.rb +33 -0
- data/lib/ingenico/direct/sdk/domain/fraud_fields.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/fraud_results.rb +27 -0
- data/lib/ingenico/direct/sdk/domain/g_pay_three_d_secure.rb +47 -0
- data/lib/ingenico/direct/sdk/domain/get_hosted_checkout_response.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/get_hosted_tokenization_response.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/get_payment_product_groups_response.rb +34 -0
- data/lib/ingenico/direct/sdk/domain/get_payment_products_response.rb +34 -0
- data/lib/ingenico/direct/sdk/domain/gift_card_purchase.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/hosted_checkout_specific_input.rb +55 -0
- data/lib/ingenico/direct/sdk/domain/hosted_checkout_specific_output.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/label_template_element.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/length_validator.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/line_item.rb +47 -0
- data/lib/ingenico/direct/sdk/domain/line_item_invoice_data.rb +27 -0
- data/lib/ingenico/direct/sdk/domain/loan_recipient.rb +43 -0
- data/lib/ingenico/direct/sdk/domain/merchant_action.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/mobile_payment_data.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/mobile_payment_method_specific_input.rb +63 -0
- data/lib/ingenico/direct/sdk/domain/mobile_payment_method_specific_output.rb +59 -0
- data/lib/ingenico/direct/sdk/domain/mobile_payment_product320_specific_input.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/order.rb +71 -0
- data/lib/ingenico/direct/sdk/domain/order_line_details.rb +55 -0
- data/lib/ingenico/direct/sdk/domain/order_references.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/order_status_output.rb +50 -0
- data/lib/ingenico/direct/sdk/domain/order_type_information.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/payment_account_on_file.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/payment_creation_output.rb +39 -0
- data/lib/ingenico/direct/sdk/domain/payment_error_response.rb +46 -0
- data/lib/ingenico/direct/sdk/domain/payment_output.rb +79 -0
- data/lib/ingenico/direct/sdk/domain/payment_product.rb +77 -0
- data/lib/ingenico/direct/sdk/domain/payment_product5100_specific_input.rb +27 -0
- data/lib/ingenico/direct/sdk/domain/payment_product5402_specific_output.rb +27 -0
- data/lib/ingenico/direct/sdk/domain/payment_product5500_specific_output.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/payment_product771_specific_output.rb +13 -0
- data/lib/ingenico/direct/sdk/domain/payment_product840_customer_account.rb +55 -0
- data/lib/ingenico/direct/sdk/domain/payment_product840_specific_output.rb +54 -0
- data/lib/ingenico/direct/sdk/domain/payment_product_display_hints.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/payment_product_field.rb +47 -0
- data/lib/ingenico/direct/sdk/domain/payment_product_field_data_restrictions.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/payment_product_field_display_element.rb +39 -0
- data/lib/ingenico/direct/sdk/domain/payment_product_field_display_hints.rb +71 -0
- data/lib/ingenico/direct/sdk/domain/payment_product_field_form_element.rb +38 -0
- data/lib/ingenico/direct/sdk/domain/payment_product_field_tooltip.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/payment_product_field_validators.rb +91 -0
- data/lib/ingenico/direct/sdk/domain/payment_product_filter.rb +43 -0
- data/lib/ingenico/direct/sdk/domain/payment_product_filters_hosted_checkout.rb +38 -0
- data/lib/ingenico/direct/sdk/domain/payment_product_group.rb +43 -0
- data/lib/ingenico/direct/sdk/domain/payment_product_networks_response.rb +33 -0
- data/lib/ingenico/direct/sdk/domain/payment_references.rb +27 -0
- data/lib/ingenico/direct/sdk/domain/payment_response.rb +55 -0
- data/lib/ingenico/direct/sdk/domain/payment_status_output.rb +58 -0
- data/lib/ingenico/direct/sdk/domain/payout_error_response.rb +46 -0
- data/lib/ingenico/direct/sdk/domain/payout_output.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/payout_response.rb +47 -0
- data/lib/ingenico/direct/sdk/domain/payout_result.rb +47 -0
- data/lib/ingenico/direct/sdk/domain/payout_status_output.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/personal_information.rb +39 -0
- data/lib/ingenico/direct/sdk/domain/personal_information_token.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/personal_name.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/personal_name_token.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/product_directory.rb +34 -0
- data/lib/ingenico/direct/sdk/domain/protection_eligibility.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/range_validator.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/redirect_data.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/redirect_payment_method_specific_input.rb +67 -0
- data/lib/ingenico/direct/sdk/domain/redirect_payment_method_specific_output.rb +67 -0
- data/lib/ingenico/direct/sdk/domain/redirect_payment_product809_specific_input.rb +27 -0
- data/lib/ingenico/direct/sdk/domain/redirect_payment_product840_specific_input.rb +27 -0
- data/lib/ingenico/direct/sdk/domain/redirection_data.rb +27 -0
- data/lib/ingenico/direct/sdk/domain/refund_card_method_specific_output.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/refund_e_wallet_method_specific_output.rb +39 -0
- data/lib/ingenico/direct/sdk/domain/refund_error_response.rb +46 -0
- data/lib/ingenico/direct/sdk/domain/refund_mobile_method_specific_output.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/refund_output.rb +79 -0
- data/lib/ingenico/direct/sdk/domain/refund_payment_product840_customer_account.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/refund_payment_product840_specific_output.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/refund_redirect_method_specific_output.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/refund_request.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/refund_response.rb +47 -0
- data/lib/ingenico/direct/sdk/domain/refunds_response.rb +34 -0
- data/lib/ingenico/direct/sdk/domain/regular_expression_validator.rb +27 -0
- data/lib/ingenico/direct/sdk/domain/sepa_direct_debit_payment_method_specific_output.rb +43 -0
- data/lib/ingenico/direct/sdk/domain/session_request.rb +33 -0
- data/lib/ingenico/direct/sdk/domain/session_response.rb +49 -0
- data/lib/ingenico/direct/sdk/domain/shipping.rb +51 -0
- data/lib/ingenico/direct/sdk/domain/shopping_cart.rb +65 -0
- data/lib/ingenico/direct/sdk/domain/shopping_cart_extension.rb +52 -0
- data/lib/ingenico/direct/sdk/domain/test_connection.rb +27 -0
- data/lib/ingenico/direct/sdk/domain/three_d_secure.rb +63 -0
- data/lib/ingenico/direct/sdk/domain/three_d_secure_base.rb +47 -0
- data/lib/ingenico/direct/sdk/domain/three_d_secure_data.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/three_d_secure_results.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/token_card.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/token_card_data.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/token_card_specific_input.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/token_data.rb +31 -0
- data/lib/ingenico/direct/sdk/domain/token_e_wallet.rb +35 -0
- data/lib/ingenico/direct/sdk/domain/token_response.rb +55 -0
- data/lib/ingenico/direct/sdk/domain/value_mapping_element.rb +38 -0
- data/lib/ingenico/direct/sdk/endpoint_configuration.rb +127 -0
- data/lib/ingenico/direct/sdk/exceptions.rb +8 -0
- data/lib/ingenico/direct/sdk/factory.rb +136 -0
- data/lib/ingenico/direct/sdk/idempotence_exception.rb +24 -0
- data/lib/ingenico/direct/sdk/logging.rb +10 -0
- data/lib/ingenico/direct/sdk/logging/communicator_logger.rb +22 -0
- data/lib/ingenico/direct/sdk/logging/log_message_builder.rb +56 -0
- data/lib/ingenico/direct/sdk/logging/logging_capable.rb +19 -0
- data/lib/ingenico/direct/sdk/logging/logging_util.rb +271 -0
- data/lib/ingenico/direct/sdk/logging/request_log_message_builder.rb +39 -0
- data/lib/ingenico/direct/sdk/logging/response_log_message_builder.rb +34 -0
- data/lib/ingenico/direct/sdk/logging/ruby_communicator_logger.rb +57 -0
- data/lib/ingenico/direct/sdk/logging/stdout_communicator_logger.rb +34 -0
- data/lib/ingenico/direct/sdk/marshaller.rb +24 -0
- data/lib/ingenico/direct/sdk/marshaller_syntax_exception.rb +6 -0
- data/lib/ingenico/direct/sdk/merchant/hostedcheckout/hosted_checkout_client.rb +87 -0
- data/lib/ingenico/direct/sdk/merchant/hostedtokenization/hosted_tokenization_client.rb +87 -0
- data/lib/ingenico/direct/sdk/merchant/merchant_client.rb +83 -0
- data/lib/ingenico/direct/sdk/merchant/payments/payments_client.rb +291 -0
- data/lib/ingenico/direct/sdk/merchant/payouts/payouts_client.rb +87 -0
- data/lib/ingenico/direct/sdk/merchant/productgroups/get_product_group_params.rb +58 -0
- data/lib/ingenico/direct/sdk/merchant/productgroups/get_product_groups_params.rb +58 -0
- data/lib/ingenico/direct/sdk/merchant/productgroups/product_groups_client.rb +88 -0
- data/lib/ingenico/direct/sdk/merchant/products/get_payment_product_networks_params.rb +39 -0
- data/lib/ingenico/direct/sdk/merchant/products/get_payment_product_params.rb +58 -0
- data/lib/ingenico/direct/sdk/merchant/products/get_payment_products_params.rb +58 -0
- data/lib/ingenico/direct/sdk/merchant/products/get_product_directory_params.rb +31 -0
- data/lib/ingenico/direct/sdk/merchant/products/products_client.rb +156 -0
- data/lib/ingenico/direct/sdk/merchant/services/services_client.rb +52 -0
- data/lib/ingenico/direct/sdk/merchant/sessions/sessions_client.rb +55 -0
- data/lib/ingenico/direct/sdk/merchant/tokens/tokens_client.rb +117 -0
- data/lib/ingenico/direct/sdk/meta_data_provider.rb +150 -0
- data/lib/ingenico/direct/sdk/modules.rb +71 -0
- data/lib/ingenico/direct/sdk/not_found_exception.rb +16 -0
- data/lib/ingenico/direct/sdk/param_request.rb +11 -0
- data/lib/ingenico/direct/sdk/pooled_connection.rb +21 -0
- data/lib/ingenico/direct/sdk/proxy_configuration.rb +74 -0
- data/lib/ingenico/direct/sdk/reference_exception.rb +14 -0
- data/lib/ingenico/direct/sdk/request_header.rb +50 -0
- data/lib/ingenico/direct/sdk/request_param.rb +23 -0
- data/lib/ingenico/direct/sdk/response_exception.rb +47 -0
- data/lib/ingenico/direct/sdk/response_header.rb +42 -0
- data/lib/ingenico/direct/sdk/validation_exception.rb +14 -0
- data/lib/ingenico/direct/sdk/webhooks.rb +11 -0
- data/lib/ingenico/direct/sdk/webhooks/api_version_mismatch_exception.rb +20 -0
- data/lib/ingenico/direct/sdk/webhooks/in_memory_secret_key_store.rb +56 -0
- data/lib/ingenico/direct/sdk/webhooks/secret_key_not_available_exception.rb +17 -0
- data/lib/ingenico/direct/sdk/webhooks/secret_key_store.rb +16 -0
- data/lib/ingenico/direct/sdk/webhooks/signature_validation_exception.rb +19 -0
- data/lib/ingenico/direct/sdk/webhooks/webhooks.rb +22 -0
- data/lib/ingenico/direct/sdk/webhooks/webhooks_event.rb +58 -0
- data/lib/ingenico/direct/sdk/webhooks/webhooks_helper.rb +99 -0
- data/lib/ingenico/direct/sdk/webhooks/webhooks_helper_builder.rb +25 -0
- metadata +385 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Ingenico::Direct::SDK
|
|
2
|
+
|
|
3
|
+
# Class used to communicate using the HTTP (or HTTPS) protocol.
|
|
4
|
+
# Performs GET, DELETE, POST and PUT requests given a target uri and request headers.
|
|
5
|
+
# @see Ingenico::Direct::SDK::DefaultImpl::DefaultConnection
|
|
6
|
+
class Connection
|
|
7
|
+
include Ingenico::Direct::SDK::Logging::LoggingCapable
|
|
8
|
+
|
|
9
|
+
# Performs a GET request to _uri_ using _request_headers_,
|
|
10
|
+
# and yields the response as the status code, headers and body.
|
|
11
|
+
#
|
|
12
|
+
# @yield (Integer, Array<Ingenico::Direct::SDK::ResponseHeader>, IO) The status code, headers and body of the response.
|
|
13
|
+
def get(uri, request_headers)
|
|
14
|
+
raise NotImplementedError
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Performs a DELETE request to _uri_ using _request_headers_,
|
|
18
|
+
# and yields the response as the status code, headers and body.
|
|
19
|
+
#
|
|
20
|
+
# @yield (Integer, Array<Ingenico::Direct::SDK::ResponseHeader>, IO) The status code, headers and body of the response.
|
|
21
|
+
def delete(uri, request_headers)
|
|
22
|
+
raise NotImplementedError
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Performs a POST request to _uri_ using _request_headers_ and _body_,
|
|
26
|
+
# and yields the response as the status code, headers and body.
|
|
27
|
+
#
|
|
28
|
+
# @yield (Integer, Array<Ingenico::Direct::SDK::ResponseHeader>, IO) The status code, headers and body of the response.
|
|
29
|
+
def post(uri, request_headers, body)
|
|
30
|
+
raise NotImplementedError
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Performs a PUT request to _uri_ using _request_headers_ and _body_,
|
|
34
|
+
# and yields the response as the status code, headers and body.
|
|
35
|
+
#
|
|
36
|
+
# @yield (Integer, Array<Ingenico::Direct::SDK::ResponseHeader>, IO) The status code, headers and body of the response.
|
|
37
|
+
def put(uri, request_headers, body)
|
|
38
|
+
raise NotImplementedError
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
module Ingenico::Direct::SDK
|
|
4
|
+
|
|
5
|
+
# Base class for all SDK data objects, supports marshalling and unmarshalling the data object to and from JSON.
|
|
6
|
+
class DataObject
|
|
7
|
+
|
|
8
|
+
# Returns a hash representation of the DataObject.
|
|
9
|
+
# The hash contains camelCase representations of the variables, and their values.
|
|
10
|
+
# Should be overridden to add all instance variables of the object.
|
|
11
|
+
#
|
|
12
|
+
# @return [Hash]
|
|
13
|
+
def to_h
|
|
14
|
+
{}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Create a new instance of this object (DataObject or descendant)
|
|
18
|
+
# from a hash containing attribute values in camelCase.
|
|
19
|
+
# Note that the hash contains Strings as keys instead of more commonly used tokens.
|
|
20
|
+
def self.new_from_hash(hash)
|
|
21
|
+
obj = self.new
|
|
22
|
+
obj.from_hash(hash)
|
|
23
|
+
obj
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Set attributes from values in parameter hash.
|
|
27
|
+
# Should be overridden by descendants in order to properly restore their attributes from the hash.
|
|
28
|
+
# Note that the hash contains Strings as keys instead of more commonly used tokens.
|
|
29
|
+
def from_hash(hash)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Ingenico::Direct::SDK
|
|
2
|
+
|
|
3
|
+
# Indicates that a payment is declined by the Ingenico ePayments platform or one of its downstream partners/acquirers.
|
|
4
|
+
class DeclinedPaymentException < DeclinedTransactionException
|
|
5
|
+
|
|
6
|
+
# Create a new DeclinedPaymentException.
|
|
7
|
+
# @see ApiException#initialize
|
|
8
|
+
def initialize(status_code, response_body, errors)
|
|
9
|
+
super(status_code, response_body, errors&.error_id, errors&.errors, build_message(errors))
|
|
10
|
+
@errors = errors
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# The declined payment result returned by the Ingenico ePayments platform.
|
|
14
|
+
# @return [Ingenico::Direct::SDK::Domain::CreatePaymentResult, nil]
|
|
15
|
+
def payment_result
|
|
16
|
+
@errors&.payment_result
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def build_message(errors)
|
|
22
|
+
payment = errors&.payment_result&.payment
|
|
23
|
+
if payment
|
|
24
|
+
"declined payment '#{payment.id}' with status '#{payment.status}'"
|
|
25
|
+
else
|
|
26
|
+
'the Ingenico ePayments platform returned a declined payment response'
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'ingenico/direct/sdk/declined_transaction_exception'
|
|
2
|
+
|
|
3
|
+
module Ingenico::Direct::SDK
|
|
4
|
+
|
|
5
|
+
# Indicates that a payout is declined by the Ingenico ePayments platform or one of its downstream partners/acquirers.
|
|
6
|
+
class DeclinedPayoutException < DeclinedTransactionException
|
|
7
|
+
|
|
8
|
+
# Create a new DeclinedPayoutException
|
|
9
|
+
# @see ApiException#initialize
|
|
10
|
+
def initialize(status_code, response_body, errors)
|
|
11
|
+
super(status_code, response_body, errors&.error_id, errors&.errors, build_message(errors))
|
|
12
|
+
@errors = errors
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# The declined payout result as returned by the Ingenico ePayments platform.
|
|
16
|
+
# @return [Ingenico::Direct::SDK::Domain::PayoutResult, nil]
|
|
17
|
+
def payout_result
|
|
18
|
+
@errors&.payout_result
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def build_message(errors)
|
|
24
|
+
payout = errors&.payout_result
|
|
25
|
+
if payout
|
|
26
|
+
"declined payout '#{payout.id}' with status '#{payout.status}'"
|
|
27
|
+
else
|
|
28
|
+
'the Ingenico ePayments platform returned a declined payout response'
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'ingenico/direct/sdk/declined_transaction_exception'
|
|
2
|
+
|
|
3
|
+
module Ingenico::Direct::SDK
|
|
4
|
+
|
|
5
|
+
# Indicates that a refund is declined by the Ingenico ePayments platform or one of its downstream partners/acquirers.
|
|
6
|
+
class DeclinedRefundException < DeclinedTransactionException
|
|
7
|
+
|
|
8
|
+
# Create a new DeclinedRefundException
|
|
9
|
+
# @see ApiException#initialize
|
|
10
|
+
def initialize(status_code, response_body, errors)
|
|
11
|
+
super(status_code, response_body, errors&.error_id, errors&.errors, build_message(errors))
|
|
12
|
+
@errors = errors
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# The declined refund result as returned by the Ingenico ePayments platform.
|
|
16
|
+
# @return [Ingenico::Direct::SDK::Domain::RefundResult, nil]
|
|
17
|
+
def refund_result
|
|
18
|
+
@errors&.refund_result
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def build_message(errors)
|
|
24
|
+
refund = errors&.refund_result
|
|
25
|
+
if refund
|
|
26
|
+
"declined refund '#{refund.id}' with status '#{refund.status}'"
|
|
27
|
+
else
|
|
28
|
+
'the Ingenico ePayments platform returned a declined refund response'
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Ingenico::Direct::SDK
|
|
2
|
+
|
|
3
|
+
# Indicates that a transaction is declined by the Ingenico ePayments platform or one of its downstream partners/acquirers.
|
|
4
|
+
class DeclinedTransactionException < ApiException
|
|
5
|
+
|
|
6
|
+
# Create a new DeclinedTransactionException.
|
|
7
|
+
# @see ApiException#initialize
|
|
8
|
+
def initialize(status_code, response_body, error_id, errors, message = nil)
|
|
9
|
+
if message
|
|
10
|
+
super(status_code, response_body, error_id, errors, message)
|
|
11
|
+
else
|
|
12
|
+
super(status_code, response_body, error_id, errors)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Ingenico::Direct::SDK
|
|
2
|
+
module DefaultImpl
|
|
3
|
+
|
|
4
|
+
# Contains all authentication schemes supported by the GlobabCollect platform.
|
|
5
|
+
class AuthorizationType
|
|
6
|
+
V1HMAC = 'v1HMAC'
|
|
7
|
+
|
|
8
|
+
# @return [String] the authorization string that belongs to the parameter _authorization_, or _nil_ if not found.
|
|
9
|
+
def self.get_authorization(authorization)
|
|
10
|
+
case authorization.downcase
|
|
11
|
+
when V1HMAC.downcase
|
|
12
|
+
return V1HMAC
|
|
13
|
+
else
|
|
14
|
+
raise ArgumentError "Unknown authorization type '#{authorization}'"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @return [String]
|
|
19
|
+
def self.get_signature_string
|
|
20
|
+
V1HMAC
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
require 'openssl' # for HMAC-SHA256
|
|
2
|
+
require 'base64'
|
|
3
|
+
|
|
4
|
+
module Ingenico::Direct::SDK
|
|
5
|
+
module DefaultImpl
|
|
6
|
+
|
|
7
|
+
# Authenticates requests made to the Ingenico ePayments platform using the HMAC algorithm.
|
|
8
|
+
class DefaultAuthenticator < Authenticator
|
|
9
|
+
|
|
10
|
+
# HMAC algorithm used to generate the signature
|
|
11
|
+
HMAC_ALGOR = 'SHA256'.freeze
|
|
12
|
+
CONTENT_TYPE = 'Content-Type'.freeze
|
|
13
|
+
DATE = 'Date'.freeze
|
|
14
|
+
XGCS = 'x-gcs'.freeze
|
|
15
|
+
|
|
16
|
+
# Construct a new DefaultAuthenticator instance that can sign requests
|
|
17
|
+
# with the provided _api_key_id_ and _secret_api_key_.
|
|
18
|
+
#
|
|
19
|
+
# @param api_key_id [String] identifier for the secret key used in authentication.
|
|
20
|
+
# @param secret_api_key [String] the secret key that is used to generate the authentication signature.
|
|
21
|
+
# @param authorization_type [String] the authorization protocol to use for authentication.
|
|
22
|
+
def initialize(api_key_id, secret_api_key, authorization_type = AuthorizationType::V1HMAC)
|
|
23
|
+
raise ArgumentError unless api_key_id && !api_key_id.strip.empty?
|
|
24
|
+
raise ArgumentError unless secret_api_key && !secret_api_key.strip.empty?
|
|
25
|
+
raise ArgumentError unless authorization_type && !authorization_type.strip.empty?
|
|
26
|
+
|
|
27
|
+
@api_key_id = api_key_id
|
|
28
|
+
@secret_api_key = secret_api_key
|
|
29
|
+
@authorization_type = authorization_type
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Creates a signature to authenticate a request.
|
|
33
|
+
#
|
|
34
|
+
# @param http_method [String] 'GET', 'PUT', 'POST' or 'DELETE' indicating which HTTP method will be used with the request
|
|
35
|
+
# @param resource_uri [URI::HTTP] URI object that includes #path and #query of the URL that will be used, #query may be *nil*
|
|
36
|
+
# @param http_headers [Array<Ingenico::Direct::SDK::RequestHeader>] list that contains all headers used by the request
|
|
37
|
+
# @return [String] the created signature
|
|
38
|
+
def create_simple_authentication_signature(http_method, resource_uri, http_headers)
|
|
39
|
+
raise ArgumentError unless http_method && !http_method.strip.empty?
|
|
40
|
+
raise ArgumentError unless resource_uri
|
|
41
|
+
|
|
42
|
+
data_to_sign = to_data_to_sign(http_method, resource_uri, http_headers)
|
|
43
|
+
"GCS #{@authorization_type}:#{@api_key_id}:#{create_auth_signature(data_to_sign)}"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
protected
|
|
47
|
+
|
|
48
|
+
# Canonizes the _http_method_, _resource_uri_ and _http_headers_ so a unique signature can be generated.
|
|
49
|
+
# Canonical form is as follows:
|
|
50
|
+
# * _http_method_ in upper case
|
|
51
|
+
# * Content-Type
|
|
52
|
+
# * Date header
|
|
53
|
+
# * X-GCS headers sorted alphabetically. Names are in lowercase and values are stripped of excess whitespace
|
|
54
|
+
# * path and query portion of the uri, separated by a question mark
|
|
55
|
+
def to_data_to_sign(http_method, resource_uri, http_headers)
|
|
56
|
+
content_type = ''
|
|
57
|
+
date = ''
|
|
58
|
+
canonical_resource = to_canonical_resource(resource_uri)
|
|
59
|
+
xgc_http_headers = []
|
|
60
|
+
|
|
61
|
+
http_headers&.each do |header|
|
|
62
|
+
name = header.name
|
|
63
|
+
value = header.value
|
|
64
|
+
case
|
|
65
|
+
when name.casecmp(CONTENT_TYPE).zero?
|
|
66
|
+
content_type = value
|
|
67
|
+
when name.casecmp(DATE).zero?
|
|
68
|
+
date = value
|
|
69
|
+
when to_canonical_header_name(name).start_with?("x-gcs")
|
|
70
|
+
xgc_http_headers << [to_canonical_header_name(name), to_canonical_header_value(value)]
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
xgc_http_headers.sort! { |(h1, v1), (h2, v2)| h1 <=> h2 } unless xgc_http_headers.empty?
|
|
75
|
+
|
|
76
|
+
data = "#{http_method.upcase}\n#{content_type}\n#{date}\n"
|
|
77
|
+
data << xgc_http_headers.inject('') { |s, (k, v)| "#{s}#{k}:#{v}\n" } unless xgc_http_headers.empty?
|
|
78
|
+
data << "#{canonical_resource}\n" if canonical_resource
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Applies the HMAC algorithm to the canonicalized data to obtain an HMAC digest.
|
|
82
|
+
# Afterwards the HMAC digest is encoded using base64 encoding.
|
|
83
|
+
def create_auth_signature(data_to_sign)
|
|
84
|
+
digest = OpenSSL::Digest.new(HMAC_ALGOR)
|
|
85
|
+
hmac = OpenSSL::HMAC.digest(digest, @secret_api_key, data_to_sign)
|
|
86
|
+
Base64.strict_encode64(hmac).strip
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
private
|
|
90
|
+
|
|
91
|
+
# Returns the encoded URI path without the HTTP method and including all decoded query parameters.
|
|
92
|
+
def to_canonical_resource(resource_uri)
|
|
93
|
+
return "#{resource_uri.path}?#{resource_uri.query}" if resource_uri.query
|
|
94
|
+
resource_uri.path
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def to_canonical_header_name(original_name)
|
|
98
|
+
original_name ? original_name.downcase : original_name
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Strips a header value of excess whitespace to produce a canonical value
|
|
102
|
+
def to_canonical_header_value(original_value)
|
|
103
|
+
return '' unless original_value
|
|
104
|
+
original_value.gsub(/\r?\n[\s&&[^\r\n]]*/, ' ').strip
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
require 'securerandom'
|
|
2
|
+
require 'uri'
|
|
3
|
+
require 'httpclient'
|
|
4
|
+
|
|
5
|
+
# @private :nodoc: this is not our class
|
|
6
|
+
module RefineHTTPClient
|
|
7
|
+
refine HTTPClient do
|
|
8
|
+
# (monkey) patch to gain access to the session pool size in HTTPClient
|
|
9
|
+
def session_count
|
|
10
|
+
sess_pool = @session_manager.instance_variable_get(:@sess_pool)
|
|
11
|
+
sess_pool.size
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
module Ingenico::Direct::SDK
|
|
17
|
+
module DefaultImpl
|
|
18
|
+
class DefaultConnection < PooledConnection
|
|
19
|
+
using RefineHTTPClient
|
|
20
|
+
|
|
21
|
+
CONTENT_TYPE = 'Content-Type'.freeze
|
|
22
|
+
JSON_CONTENT_TYPE = 'application/json'.freeze
|
|
23
|
+
|
|
24
|
+
# @param args [Hash] the parameters to initialize the connection with
|
|
25
|
+
# @option args [Integer] :connect_timeout connection timeout in seconds.
|
|
26
|
+
# Uses {CommunicatorConfiguration.default_connect_timeout} if not given.
|
|
27
|
+
# @option args [Integer] :socket_timeout socket timeout in seconds.
|
|
28
|
+
# Uses {CommunicatorConfiguration.default_socket_timeout} if not given.
|
|
29
|
+
# @option args [Integer] :max_connections number of connections kept alive in the thread pool.
|
|
30
|
+
# Uses {CommunicatorConfiguration.default_max_connections} if not given.
|
|
31
|
+
# @option args [Hash] :proxy_configuration object that stores the proxy to use.
|
|
32
|
+
# If not given the system default proxy is used;
|
|
33
|
+
# if there is no system default proxy set either, no proxy is used.
|
|
34
|
+
def initialize(args)
|
|
35
|
+
raise ArgumentError unless args.is_a? Hash
|
|
36
|
+
|
|
37
|
+
super()
|
|
38
|
+
|
|
39
|
+
# Set timeouts to nil if they are negative
|
|
40
|
+
@connect_timeout = args[:connect_timeout] || CommunicatorConfiguration.default_connect_timeout
|
|
41
|
+
@connect_timeout = nil unless @connect_timeout&.positive?
|
|
42
|
+
@socket_timeout = args[:socket_timeout] || CommunicatorConfiguration.default_socket_timeout
|
|
43
|
+
@socket_timeout = nil unless @socket_timeout&.positive?
|
|
44
|
+
@max_connections = args[:max_connections] || CommunicatorConfiguration.default_max_connections
|
|
45
|
+
@proxy_configuration = args[:proxy_configuration]
|
|
46
|
+
|
|
47
|
+
# HTTPClient provides the following features:
|
|
48
|
+
# 1) thread safe, an instance can be used by multiple threads without
|
|
49
|
+
# explicit synchronization
|
|
50
|
+
# 2) use persistent connection if HTTP 1.1 is supported. The connection
|
|
51
|
+
# will be left open until explicitly closed or keep_alive_timeout
|
|
52
|
+
# 3) a built-in connection pool with no limit for max connections
|
|
53
|
+
@http_client = create_http_client
|
|
54
|
+
@http_client.connect_timeout = @connect_timeout
|
|
55
|
+
@http_client.send_timeout = @socket_timeout
|
|
56
|
+
@http_client.receive_timeout = @socket_timeout
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
# Create a HTTPClient instance that uses @proxy_configuration or the system proxy if @proxy_configuration is not set
|
|
62
|
+
def create_http_client
|
|
63
|
+
if @proxy_configuration
|
|
64
|
+
httpclient = HTTPClient.new(@proxy_configuration.proxy_uri)
|
|
65
|
+
httpclient.set_proxy_auth(@proxy_configuration.username, @proxy_configuration.password)
|
|
66
|
+
httpclient.force_basic_auth = true if @proxy_configuration.username && @proxy_configuration.password
|
|
67
|
+
else # use system settings
|
|
68
|
+
proxy_string = ENV['https_proxy'] || ENV['http_proxy']
|
|
69
|
+
# proxy string format = 'http://username:password@hostname:port'
|
|
70
|
+
proxy_string =~ %r{https?//(?<username>[^:]):(?<password>[^@])@.*}
|
|
71
|
+
username = Regexp.last_match(1)
|
|
72
|
+
password = Regexp.last_match(2)
|
|
73
|
+
httpclient = HTTPClient.new(proxy_string)
|
|
74
|
+
httpclient.set_proxy_auth(username, password) if username && password
|
|
75
|
+
httpclient.force_basic_auth = true if username && password
|
|
76
|
+
end
|
|
77
|
+
httpclient
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
public
|
|
81
|
+
|
|
82
|
+
# Closes all connections idle for longer than _idle_time_ seconds.
|
|
83
|
+
# In addition, the keep_alive_timeout is set to _idle_time_
|
|
84
|
+
# so any future connections idle for longer than _idle_time_ seconds will also be closed.
|
|
85
|
+
def close_idle_connections(idle_time) # in sec
|
|
86
|
+
@http_client.keep_alive_timeout = idle_time # set timeout value
|
|
87
|
+
close_expired_connections
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# HTTPClient automatically closes expired connections so _close_expired_connections_ is a no-operation.
|
|
91
|
+
def close_expired_connections
|
|
92
|
+
# By default the keep alive timeout is 15 sec, which is the HTTP 1.1
|
|
93
|
+
# standard. To change the value, use keep_alive_timeout= method
|
|
94
|
+
# do nothing, handled by HTTPClient
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Frees all networking resources used.
|
|
98
|
+
def close
|
|
99
|
+
@http_client.reset_all
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Returns the number of open connections
|
|
103
|
+
def session_count
|
|
104
|
+
@http_client.session_count
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Performs a GET request to the Ingenico ePayments platform
|
|
108
|
+
# @see request
|
|
109
|
+
def get(uri, request_headers)
|
|
110
|
+
request('get', uri, request_headers) do |response_status_code, response_headers, response_body|
|
|
111
|
+
yield response_status_code, response_headers, response_body
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Performs a DELETE request to the Ingenico ePayments platform
|
|
116
|
+
# @see request
|
|
117
|
+
def delete(uri, request_headers)
|
|
118
|
+
request('delete', uri, request_headers) do |response_status_code, response_headers, response_body|
|
|
119
|
+
yield response_status_code, response_headers, response_body
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Performs a POST request to the Ingenico ePayments platform
|
|
124
|
+
# @see request
|
|
125
|
+
def post(uri, request_headers, body)
|
|
126
|
+
request('post', uri, request_headers, body) do |response_status_code, response_headers, response_body|
|
|
127
|
+
yield response_status_code, response_headers, response_body
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Performs a PUT request to the Ingenico ePayments platform
|
|
132
|
+
# @see request
|
|
133
|
+
def put(uri, request_headers, body)
|
|
134
|
+
request('put', uri, request_headers, body) do |response_status_code, response_headers, response_body|
|
|
135
|
+
yield response_status_code, response_headers, response_body
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Performs a HTTP request and yields the response as the status code, headers and body.
|
|
140
|
+
# Also ensures the request is logged when sent and its response is logged when received.
|
|
141
|
+
#
|
|
142
|
+
# @param method [String] 'GET', 'DELETE', 'POST' or 'PUT' depending on the HTTP method being used.
|
|
143
|
+
# @param uri [URI::HTTP] full URI of the location the request is targeted at, including query parameters.
|
|
144
|
+
# @param request_headers [Array<Ingenico::Direct::SDK::RequestHeader>] list of headers that should be used as HTTP headers in the request.
|
|
145
|
+
# @param body [String] request body.
|
|
146
|
+
# @yield (Integer, Array<Ingenico::Direct::SDK::ResponseHeader>, IO) The status code, headers and body of the response.
|
|
147
|
+
# @raise [Ingenico::Direct::SDK::CommunicationException] when communication with the Ingenico ePayments platform was not successful.
|
|
148
|
+
def request(method, uri, request_headers, body = nil)
|
|
149
|
+
request_headers = convert_from_headers(request_headers)
|
|
150
|
+
request_id = SecureRandom.uuid
|
|
151
|
+
content_type = request_headers[CONTENT_TYPE]
|
|
152
|
+
|
|
153
|
+
info = { headers: request_headers, content_type: content_type }
|
|
154
|
+
info[:body] = body if body
|
|
155
|
+
|
|
156
|
+
log_request(request_id, method.upcase, uri, info)
|
|
157
|
+
|
|
158
|
+
start_time = Time.now
|
|
159
|
+
begin
|
|
160
|
+
response_headers = nil
|
|
161
|
+
response_status_code = nil
|
|
162
|
+
response_content_type = nil
|
|
163
|
+
response_body = ''
|
|
164
|
+
raw_request(method, uri, request_headers, body) do |status_code, headers, r_content_type, r_body|
|
|
165
|
+
response_headers = headers
|
|
166
|
+
response_status_code = status_code
|
|
167
|
+
response_content_type = r_content_type
|
|
168
|
+
response_body = r_body.read.force_encoding('UTF-8')
|
|
169
|
+
r_body = StringIO.new(response_body)
|
|
170
|
+
|
|
171
|
+
yield status_code, headers, r_body
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
log_response(request_id, response_status_code, start_time,
|
|
175
|
+
headers: response_headers, body: response_body,
|
|
176
|
+
content_type: response_content_type)
|
|
177
|
+
rescue HTTPClient::TimeoutError => e
|
|
178
|
+
log_error(request_id, start_time, e)
|
|
179
|
+
raise Ingenico::Direct::SDK::CommunicationException, e
|
|
180
|
+
rescue HTTPClient::KeepAliveDisconnected, HTTPClient::RetryableResponse => e # retry these?
|
|
181
|
+
log_error(request_id, start_time, e)
|
|
182
|
+
raise Ingenico::Direct::SDK::CommunicationException, e
|
|
183
|
+
rescue StandardError => e
|
|
184
|
+
log_error(request_id, start_time, e)
|
|
185
|
+
raise Ingenico::Direct::SDK::CommunicationException, e
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# logging code
|
|
190
|
+
|
|
191
|
+
# Enables logging outgoing requests and incoming responses by registering the _communicator_logger_.
|
|
192
|
+
# Note that only one logger can be registered at a time and calling _enable_logging_
|
|
193
|
+
# a second time will override the old logger instance with the new one.
|
|
194
|
+
#
|
|
195
|
+
# @param communicator_logger [Ingenico::Direct::SDK::Logging::CommunicatorLogger] the communicator logger the requests and responses are logged to
|
|
196
|
+
def enable_logging(communicator_logger)
|
|
197
|
+
raise ArgumentError, 'communicatorLogger is required' unless communicator_logger
|
|
198
|
+
|
|
199
|
+
@communicator_logger = communicator_logger
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Disables logging by unregistering any previous logger that might be registered.
|
|
203
|
+
def disable_logging
|
|
204
|
+
@communicator_logger = nil
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
private
|
|
208
|
+
|
|
209
|
+
# Converts a {Ingenico::Direct::SDK::RequestHeader} list headers to a hash
|
|
210
|
+
def convert_from_headers(headers)
|
|
211
|
+
headers.each_with_object({}) { |h, hash| hash[h.name] = h.value }
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Converts a hash to a {Ingenico::Direct::SDK::ResponseHeader} list
|
|
215
|
+
def convert_to_response_headers(headers)
|
|
216
|
+
arr ||= []
|
|
217
|
+
headers.each { |k, v| arr << Ingenico::Direct::SDK::ResponseHeader.new(k, v) }
|
|
218
|
+
arr
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def log_request(request_id, method, uri, args = {})
|
|
222
|
+
return unless @communicator_logger
|
|
223
|
+
|
|
224
|
+
headers = args[:headers]
|
|
225
|
+
body = args[:body]
|
|
226
|
+
content_type = args[:content_type]
|
|
227
|
+
log_msg_builder = Ingenico::Direct::SDK::Logging::RequestLogMessageBuilder.new(request_id, method, uri)
|
|
228
|
+
headers.each { |k, v| log_msg_builder.add_headers(k, v) } if headers
|
|
229
|
+
|
|
230
|
+
log_msg_builder.set_body(body, content_type)
|
|
231
|
+
|
|
232
|
+
begin
|
|
233
|
+
@communicator_logger.log(log_msg_builder.get_message)
|
|
234
|
+
rescue StandardError => e
|
|
235
|
+
@communicator_logger.log("An error occurred trying to log request #{request_id}", e)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# Creates the log_response stream
|
|
240
|
+
def log_response(request_id, status_code, start_time, args = {})
|
|
241
|
+
return unless @communicator_logger
|
|
242
|
+
|
|
243
|
+
duration = (Time.now - start_time) * 1000 # in milliseconds
|
|
244
|
+
headers = args[:headers]
|
|
245
|
+
body = args[:body] if args[:body]
|
|
246
|
+
content_type = args[:content_type]
|
|
247
|
+
|
|
248
|
+
log_msg_builder = Ingenico::Direct::SDK::Logging::ResponseLogMessageBuilder.new(request_id, status_code, duration)
|
|
249
|
+
if headers
|
|
250
|
+
convert_from_headers(headers)
|
|
251
|
+
.each do |key, value|
|
|
252
|
+
log_msg_builder.add_headers(key, value)
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
log_msg_builder.set_body(body, content_type)
|
|
257
|
+
|
|
258
|
+
begin
|
|
259
|
+
@communicator_logger.log(log_msg_builder.get_message)
|
|
260
|
+
rescue StandardError => e
|
|
261
|
+
@communicator_logger.log("An error occurred trying to log response #{request_id}", e)
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def log_error(request_id, start_time, thrown)
|
|
266
|
+
return unless @communicator_logger
|
|
267
|
+
|
|
268
|
+
duration = (Time.now - start_time) * 1000 # in millisecs
|
|
269
|
+
@communicator_logger.log("Error occurred for outgoing request (requestId='#{request_id}', #{duration} ms)", thrown)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# Makes a request using the specified method
|
|
273
|
+
#
|
|
274
|
+
# Yields a status code, an array of {Ingenico::Direct::SDK::ResponseHeader},
|
|
275
|
+
# the content_type and body
|
|
276
|
+
def raw_request(method, uri, headers, body = nil)
|
|
277
|
+
connection = body ?
|
|
278
|
+
@http_client.send("#{method}_async", uri, body: body, header: headers) :
|
|
279
|
+
@http_client.send("#{method}_async", uri, header: headers)
|
|
280
|
+
|
|
281
|
+
response = connection.pop
|
|
282
|
+
pipe = response.content
|
|
283
|
+
response_headers = convert_to_response_headers(response.headers)
|
|
284
|
+
|
|
285
|
+
begin
|
|
286
|
+
yield response.status_code, response_headers, response.content_type, pipe
|
|
287
|
+
ensure
|
|
288
|
+
pipe.close
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
end
|