direct-sdk-ruby 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,8 @@
|
|
1
|
+
prefix = 'ingenico/direct/sdk/'
|
2
|
+
suffix = '_exception'
|
3
|
+
exception_types = %w[api authorization communication declined_transaction
|
4
|
+
declined_payment declined_refund
|
5
|
+
direct idempotence marshaller_syntax not_found
|
6
|
+
reference response validation]
|
7
|
+
|
8
|
+
exception_types.each { |type| require prefix + type + suffix }
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Ingenico::Direct::SDK
|
4
|
+
|
5
|
+
# Convenience class that constructs instances of several other classes in the SDK.
|
6
|
+
# Provides methods to construct
|
7
|
+
# {Ingenico::Direct::SDK::CommunicatorConfiguration}, {Ingenico::Direct::SDK::Communicator} and {Ingenico::Direct::SDK::Client} instances.
|
8
|
+
class Factory
|
9
|
+
|
10
|
+
# Creates and returns a {Ingenico::Direct::SDK::CommunicatorConfiguration} based on the configuration in the file located at _configuration_file_name_.
|
11
|
+
#
|
12
|
+
# @param config_file_name [String] Path to the configuration file to use, should be in YAML format.
|
13
|
+
# @param api_key_id [String] Key id for the GlobalCollect service.
|
14
|
+
# @param secret_api_key [String] Secret key used for authentication to the GlobalCollect service.
|
15
|
+
# @return [Ingenico::Direct::SDK::CommunicatorConfiguration] The created communicator configuration
|
16
|
+
def self.create_configuration(config_file_name, api_key_id, secret_api_key)
|
17
|
+
properties = YAML::load_file(config_file_name)
|
18
|
+
CommunicatorConfiguration.new(properties: properties,
|
19
|
+
api_key_id: api_key_id,
|
20
|
+
secret_api_key: secret_api_key)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Creates and returns an {Ingenico::Direct::SDK::Communicator} that can be used for communication with the GlobalCollect service.
|
24
|
+
#
|
25
|
+
# @param configuration [Ingenico::Direct::SDK::CommunicatorConfiguration] contains configuration settings to be used by the client.
|
26
|
+
# @param meta_data_provider [Ingenico::Direct::SDK::MetaDataProvider,nil] stores the metadata for the communicating client.
|
27
|
+
# @param connection [Ingenico::Direct::SDK::Connection,nil] connection that can be used to communicate with the Ingenico Direct platform.
|
28
|
+
# @param authenticator [Ingenico::Direct::SDK::Authenticator,nil] authenticator that can authenticate messages sent to the Ingenico Direct platform.
|
29
|
+
# @param marshaller [Ingenico::Direct::SDK::Marshaller,nil] marshaller that marshalls and unmarshalls messages sent to the Ingenico Direct platform.
|
30
|
+
# @return [Ingenico::Direct::SDK::Communicator] The created communicator
|
31
|
+
def self.create_communicator_from_configuration(configuration, meta_data_provider: nil, connection: nil, authenticator: nil, marshaller: DefaultImpl::DefaultMarshaller.INSTANCE)
|
32
|
+
meta_data_provider ||= MetaDataProvider.new(configuration.integrator, shopping_cart_extension: configuration.shopping_cart_extension)
|
33
|
+
connection ||= DefaultImpl::DefaultConnection.new({ connect_timeout: configuration.connect_timeout,
|
34
|
+
socket_timeout: configuration.socket_timeout,
|
35
|
+
max_connections: configuration.max_connections,
|
36
|
+
proxy_configuration: configuration.proxy_configuration })
|
37
|
+
authenticator ||= DefaultImpl::DefaultAuthenticator.new(configuration.api_key_id,
|
38
|
+
configuration.secret_api_key,
|
39
|
+
configuration.authorization_type)
|
40
|
+
Communicator.new(configuration.api_endpoint, connection, authenticator, meta_data_provider, marshaller)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Creates and returns an {Ingenico::Direct::SDK::Communicator} that is used for communication with the GlobalCollect service.
|
44
|
+
#
|
45
|
+
# @param config_file_name [String] Path to the configuration file to use, should be in YAML format.
|
46
|
+
# @param api_key_id [String] Key id for the GlobalCollect service.
|
47
|
+
# @param secret_api_key [String] Secret key used for authentication to the GlobalCollect service.
|
48
|
+
# @param meta_data_provider [Ingenico::Direct::SDK::MetaDataProvider,nil] stores the metadata for the communicating client.
|
49
|
+
# @param connection [Ingenico::Direct::SDK::Connection,nil] connection that can be used to communicate with the Ingenico Direct platform.
|
50
|
+
# @param authenticator [Ingenico::Direct::SDK::Authenticator,nil] authenticator that can authenticate messages sent to the Ingenico Direct platform.
|
51
|
+
# @return [Ingenico::Direct::SDK::Communicator] The created communicator
|
52
|
+
def self.create_communicator_from_file(config_file_name, api_key_id, secret_api_key,
|
53
|
+
meta_data_provider: nil, connection: nil, authenticator: nil,
|
54
|
+
marshaller: DefaultImpl::DefaultMarshaller.INSTANCE)
|
55
|
+
configuration = create_configuration(config_file_name, api_key_id, secret_api_key)
|
56
|
+
create_communicator_from_configuration(configuration, meta_data_provider: meta_data_provider, connection: connection,
|
57
|
+
authenticator: authenticator, marshaller: marshaller)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Creates and returns an {Ingenico::Direct::SDK::Client} that provides the a high-level interface with the GlobalCollect service.
|
61
|
+
# If a code block is given, the created client is returned to the code block and closed afterwards.
|
62
|
+
#
|
63
|
+
# @example Providing a code block
|
64
|
+
# Factory.create_client_from_configuration(configuration) do |client|
|
65
|
+
# client.merchant(merchant_id).services.testconnection
|
66
|
+
# end
|
67
|
+
# # client is closed here
|
68
|
+
#
|
69
|
+
# @param configuration [Ingenico::Direct::SDK::CommunicatorConfiguration] contains configuration settings to be used by the client.
|
70
|
+
# @return [Ingenico::Direct::SDK::Client] The created client
|
71
|
+
def self.create_client_from_configuration(configuration)
|
72
|
+
communicator = create_communicator_from_configuration(configuration)
|
73
|
+
client = Client.new(communicator)
|
74
|
+
if block_given?
|
75
|
+
begin
|
76
|
+
yield client
|
77
|
+
ensure
|
78
|
+
client.close
|
79
|
+
end
|
80
|
+
else
|
81
|
+
return client
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Creates and returns an {Ingenico::Direct::SDK::Client} that provides the a high-level interface with the GlobalCollect service.
|
86
|
+
# If a code block is given, the created client is returned to the code block and closed afterwards.
|
87
|
+
#
|
88
|
+
# @example Providing a code block
|
89
|
+
# Factory.create_client_from_communicator(communicator) do |client|
|
90
|
+
# client.merchant(merchant_id).services.testconnection
|
91
|
+
# end
|
92
|
+
# # client is closed here
|
93
|
+
#
|
94
|
+
# @param communicator [Ingenico::Direct::SDK::Communicator] provides network communication service for the Client
|
95
|
+
# @return [Ingenico::Direct::SDK::Client] The created client
|
96
|
+
def self.create_client_from_communicator(communicator)
|
97
|
+
client = Client.new(communicator)
|
98
|
+
if block_given?
|
99
|
+
begin
|
100
|
+
yield client
|
101
|
+
ensure
|
102
|
+
client.close
|
103
|
+
end
|
104
|
+
else
|
105
|
+
return client
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Creates and returns an {Ingenico::Direct::SDK::Client} that provides the a high-level interface with the GlobalCollect service.
|
110
|
+
# If a code block is given, the created client is returned to the code block and closed afterwards.
|
111
|
+
#
|
112
|
+
# @example Providing a code block
|
113
|
+
# Factory.create_client_from_file(config_file_name, api_key_id, secret_api_key) do |client|
|
114
|
+
# client.merchant(merchant_id).services.testconnection
|
115
|
+
# end
|
116
|
+
# # client is closed here
|
117
|
+
#
|
118
|
+
# @param config_file_name [String] Path to the configuration file to use, should be in YAML format.
|
119
|
+
# @param api_key_id [String] Key id for the GlobalCollect service.
|
120
|
+
# @param secret_api_key [String] Secret key used for authentication to the GlobalCollect service.
|
121
|
+
# @return [Ingenico::Direct::SDK::Client] The created client
|
122
|
+
def self.create_client_from_file(config_file_name, api_key_id, secret_api_key)
|
123
|
+
communicator = create_communicator_from_file(config_file_name, api_key_id, secret_api_key)
|
124
|
+
client = Client.new(communicator)
|
125
|
+
if block_given?
|
126
|
+
begin
|
127
|
+
yield client
|
128
|
+
ensure
|
129
|
+
client.close
|
130
|
+
end
|
131
|
+
else
|
132
|
+
return client
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Ingenico::Direct::SDK
|
2
|
+
|
3
|
+
# This exception is thrown when a response from the Ingenico ePayments platform indicates
|
4
|
+
# a request with the same _idempotence_key_ was received earlier.
|
5
|
+
# The _idempotence_request_timestamp_ indicates the time when the first request with this _idempotence_key_ arrived.
|
6
|
+
#
|
7
|
+
# @attr_reader [String] idempotence_key The idempotence key used in the request.
|
8
|
+
# @attr_reader [Integer] idempotence_request_timestamp A timestamp indicating the arrival time of the request that conflicts with the request just sent.
|
9
|
+
class IdempotenceException < ApiException
|
10
|
+
|
11
|
+
# Create a new IdempotenceException
|
12
|
+
# @see ApiException#initialize
|
13
|
+
def initialize(status_code, response_body, error_id, errors, idempotence_key,
|
14
|
+
idempotence_request_timestamp,
|
15
|
+
message='the Ingenico ePayments platform returned a duplicate request error response')
|
16
|
+
super(status_code, response_body, error_id, errors, message)
|
17
|
+
@idempotence_key = idempotence_key
|
18
|
+
@idempotence_request_timestamp = idempotence_request_timestamp
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :idempotence_key
|
22
|
+
attr_reader :idempotence_request_timestamp
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
prefix = 'ingenico/direct/sdk/logging'
|
2
|
+
|
3
|
+
require "#{prefix}/logging_capable"
|
4
|
+
require "#{prefix}/log_message_builder"
|
5
|
+
require "#{prefix}/request_log_message_builder"
|
6
|
+
require "#{prefix}/response_log_message_builder"
|
7
|
+
require "#{prefix}/logging_util"
|
8
|
+
require "#{prefix}/communicator_logger"
|
9
|
+
require "#{prefix}/ruby_communicator_logger"
|
10
|
+
require "#{prefix}/stdout_communicator_logger"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Ingenico::Direct::SDK
|
2
|
+
module Logging
|
3
|
+
|
4
|
+
# Base logger class used in this SDK. This class is an interface and cannot be instantiated.
|
5
|
+
class CommunicatorLogger
|
6
|
+
# Interface, no instantiation
|
7
|
+
# @see Ingenico::Direct::SDK::Logging::StdoutCommunicatorLogger
|
8
|
+
# @see Ingenico::Direct::SDK::Logging::RubyCommunicatorLogger
|
9
|
+
def initialize
|
10
|
+
raise NotImplementedError, "#{self.class.name} is not implemented."
|
11
|
+
end
|
12
|
+
|
13
|
+
# Logs a message with or without exception
|
14
|
+
#
|
15
|
+
# @param message [String] the message to log
|
16
|
+
# @param thrown [Exception, false] the exception to log, or false to log no exception
|
17
|
+
def log(message, thrown = false)
|
18
|
+
raise NotImplementedError, "#{self.class.name}#log() is not implemented."
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Ingenico::Direct::SDK
|
2
|
+
module Logging
|
3
|
+
|
4
|
+
# Abstract class used to construct a message describing a request or response.
|
5
|
+
#
|
6
|
+
# @attr_reader [String] request_id An identifier assigned to the request and response
|
7
|
+
# @attr_reader [String] headers Request or response headers in string form
|
8
|
+
# @attr_reader [String] body Request or response body as a string
|
9
|
+
# @attr_reader [String] content_type Content type of the body, generally 'application/json' or 'text/html'
|
10
|
+
class LogMessageBuilder
|
11
|
+
|
12
|
+
attr_reader :request_id
|
13
|
+
attr_reader :headers
|
14
|
+
attr_reader :body
|
15
|
+
attr_reader :content_type
|
16
|
+
|
17
|
+
# Create a new LogMessageBuilder
|
18
|
+
def initialize(request_id)
|
19
|
+
raise ArgumentError if request_id.nil? || request_id.empty?
|
20
|
+
@request_id = request_id
|
21
|
+
@headers = ''
|
22
|
+
end
|
23
|
+
|
24
|
+
# Adds a single header to the #headers string
|
25
|
+
def add_headers(name, value)
|
26
|
+
@headers += ', ' unless @headers.empty?
|
27
|
+
@headers += "#{name}='#{LoggingUtil.obfuscate_header(name, value)}'"
|
28
|
+
end
|
29
|
+
|
30
|
+
# Sets the body of this message to the parameter body.
|
31
|
+
|
32
|
+
# @param body [String] the message body
|
33
|
+
# @param content_type [String] the content type of the body
|
34
|
+
def set_body(body, content_type)
|
35
|
+
@body = LoggingUtil.obfuscate_body(body)
|
36
|
+
@content_type = content_type
|
37
|
+
end
|
38
|
+
|
39
|
+
# Constructs and returns the log message as a string.
|
40
|
+
def get_message
|
41
|
+
raise NotImplementedError, "#{self.class.name}#get_message() is not implemented."
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_s
|
45
|
+
self.class == LogMessageBuilder ?
|
46
|
+
super.to_s :
|
47
|
+
get_message
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns an empty string if the parameter is nil, and returns the parameter itself otherwise
|
51
|
+
protected def empty_if_null(value)
|
52
|
+
value.nil? ? '' : value
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Ingenico
|
2
|
+
module Direct
|
3
|
+
module SDK
|
4
|
+
module Logging
|
5
|
+
|
6
|
+
# Abstract mixin module that allows loggers to be registered to an object.
|
7
|
+
module LoggingCapable
|
8
|
+
def enable_logging(communicator_logger)
|
9
|
+
raise NotImplementedError
|
10
|
+
end
|
11
|
+
|
12
|
+
def disable_logging
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,271 @@
|
|
1
|
+
module Ingenico::Direct::SDK
|
2
|
+
module Logging
|
3
|
+
|
4
|
+
# Class responsible for obfuscating sensitive data in a message body.
|
5
|
+
class ValueObfuscator
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
alias_method :private_new, :new
|
10
|
+
|
11
|
+
protected :private_new, :new
|
12
|
+
end
|
13
|
+
|
14
|
+
public
|
15
|
+
|
16
|
+
def self.INSTANCE
|
17
|
+
# use lazy instantiation
|
18
|
+
@@INSTANCE ||= ValueObfuscator.new
|
19
|
+
end
|
20
|
+
|
21
|
+
# Obfuscates the parameter value.
|
22
|
+
def obfuscate_value(value)
|
23
|
+
(value.nil? or value.empty?) ? value : "*#{value.length}"
|
24
|
+
end
|
25
|
+
end # end of ValueObfuscator
|
26
|
+
|
27
|
+
# Class responsible for obfuscating sensitive data.
|
28
|
+
class SensitiveValueObfuscator
|
29
|
+
|
30
|
+
class << self
|
31
|
+
|
32
|
+
alias_method :private_new, :new
|
33
|
+
|
34
|
+
protected :private_new, :new
|
35
|
+
end
|
36
|
+
public
|
37
|
+
|
38
|
+
def self.INSTANCE
|
39
|
+
# use lazy instantiation
|
40
|
+
@@INSTANCE ||= SensitiveValueObfuscator.new
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return an arbitrary number of '*', or null/empty if the value is null/empty.
|
44
|
+
def obfuscate_value(value)
|
45
|
+
value.nil? or value.empty? ? value : "***"
|
46
|
+
end
|
47
|
+
end # end of SensitiveValueObfuscator
|
48
|
+
|
49
|
+
class Obfuscator
|
50
|
+
def initialize(obfuscators, case_insensitive)
|
51
|
+
raise ArgumentError unless obfuscators.is_a? Hash
|
52
|
+
@obfuscators = copy(obfuscators, case_insensitive)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
# case insensitive hash
|
58
|
+
# @private
|
59
|
+
class HashClod < Hash
|
60
|
+
|
61
|
+
def initialize(other)
|
62
|
+
other.each { |k, v| self.[]=(k, v) }
|
63
|
+
end
|
64
|
+
|
65
|
+
def [](key)
|
66
|
+
super _insensitive(key)
|
67
|
+
end
|
68
|
+
|
69
|
+
def []=(key, value)
|
70
|
+
super _insensitive(key), value
|
71
|
+
end
|
72
|
+
|
73
|
+
protected
|
74
|
+
|
75
|
+
def _insensitive(key)
|
76
|
+
key.respond_to?(:upcase) ? key.upcase : key
|
77
|
+
end
|
78
|
+
end # end of HashClod
|
79
|
+
|
80
|
+
def copy(obfuscators, case_insensitive)
|
81
|
+
cp = case_insensitive ? HashClod.new(obfuscators) : obfuscators
|
82
|
+
Marshal.load(Marshal.dump(cp)) # deep copy
|
83
|
+
end
|
84
|
+
|
85
|
+
public
|
86
|
+
|
87
|
+
def obfuscate_value(key, value)
|
88
|
+
obfuscator = @obfuscators[key]
|
89
|
+
if obfuscator.nil?
|
90
|
+
value
|
91
|
+
else
|
92
|
+
obfuscator.obfuscate_value(value)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# A convenient wrapper to build obfuscators
|
97
|
+
class Builder
|
98
|
+
attr_accessor :obfuscators
|
99
|
+
|
100
|
+
def initialize
|
101
|
+
raise NotImplementedError, "#{self.class.name} is not implemented."
|
102
|
+
end
|
103
|
+
|
104
|
+
def with_field(key)
|
105
|
+
@obfuscators[key] = ValueObfuscator.INSTANCE
|
106
|
+
self
|
107
|
+
end
|
108
|
+
|
109
|
+
def with_sensitive_field(key)
|
110
|
+
@obfuscators[key] = SensitiveValueObfuscator.INSTANCE
|
111
|
+
self
|
112
|
+
end
|
113
|
+
|
114
|
+
def build
|
115
|
+
raise NotImplementedError, "#{self.class.name}#build() is not implemented."
|
116
|
+
end
|
117
|
+
end # Builder
|
118
|
+
end # Obfuscator
|
119
|
+
|
120
|
+
# Class that obfuscates headers of a message
|
121
|
+
class HeaderObfuscator < Obfuscator
|
122
|
+
def initialize(obfuscators)
|
123
|
+
# case insensitive
|
124
|
+
super(obfuscators, true)
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.builder
|
128
|
+
Builder.new
|
129
|
+
end
|
130
|
+
|
131
|
+
class Builder < Obfuscator::Builder
|
132
|
+
def initialize
|
133
|
+
@obfuscators = {}
|
134
|
+
end
|
135
|
+
|
136
|
+
def with_field(name)
|
137
|
+
raise ArgumentError unless name.is_a? String
|
138
|
+
super(name)
|
139
|
+
end
|
140
|
+
|
141
|
+
def with_sensitive_field(name)
|
142
|
+
raise ArgumentError unless name.is_a? String
|
143
|
+
super(name)
|
144
|
+
end
|
145
|
+
|
146
|
+
def build
|
147
|
+
HeaderObfuscator.new(obfuscators)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end # end of HeadObfuscator
|
151
|
+
|
152
|
+
# Class that obfuscates properties in the JSON body of a message
|
153
|
+
class PropertyObfuscator < Obfuscator
|
154
|
+
def initialize(obfuscators)
|
155
|
+
# case sensitive
|
156
|
+
super(obfuscators, false)
|
157
|
+
@property_pattern = build_property_pattern(obfuscators.keys)
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
def build_property_pattern(pn)
|
163
|
+
return /$^/ if pn.empty? # no possible match
|
164
|
+
# Regex to create:
|
165
|
+
# (["'])(X|Y|Z)\1\s*:\s*(?:(["'])(.*?)(?<!\\)\3|([^"'\s\[\{]\S*))
|
166
|
+
# Groups:
|
167
|
+
# 1: opening " or ' for the property name
|
168
|
+
# 2: property name
|
169
|
+
# 3: opening " or ' for the value
|
170
|
+
# 4: quoted value
|
171
|
+
# 5: non-quoted-value
|
172
|
+
# The negative lookbehind is to allow escaped quotes to be part of
|
173
|
+
# the value. What this does not allow currently is having values end
|
174
|
+
# with a \ (which would be escaped to \\).
|
175
|
+
regex = pn.inject("([\"'])(") { |r, p| "#{r}#{Regexp.quote(p)}|"}.chop <<
|
176
|
+
")\\1\\s*:\\s*(?:([\"'])(.*?)(?<!\\\\)\\3|([^\"'\\s\\[\\{]((?!,)\\S)*))"
|
177
|
+
/#{regex}/m # dotall mode
|
178
|
+
end
|
179
|
+
|
180
|
+
public
|
181
|
+
|
182
|
+
def obfuscate(body)
|
183
|
+
return nil if body.nil?
|
184
|
+
return "" if body.empty?
|
185
|
+
|
186
|
+
body.gsub(@property_pattern) do
|
187
|
+
m = Regexp.last_match
|
188
|
+
property_name = m[2]
|
189
|
+
value = m[4] || m[5]
|
190
|
+
# copy value 'cause it's part of m[0]
|
191
|
+
m[0].sub(value, obfuscate_value(property_name, value.dup))
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def self.builder
|
196
|
+
Builder.new
|
197
|
+
end
|
198
|
+
|
199
|
+
class Builder < Obfuscator::Builder
|
200
|
+
def initialize
|
201
|
+
@obfuscators = {}
|
202
|
+
end
|
203
|
+
|
204
|
+
def with_field(property)
|
205
|
+
raise ArgumentError unless property.is_a? String
|
206
|
+
super(property)
|
207
|
+
end
|
208
|
+
|
209
|
+
def with_sensitive_field(property)
|
210
|
+
raise ArgumentError unless property.is_a? String
|
211
|
+
super(property)
|
212
|
+
end
|
213
|
+
|
214
|
+
def build
|
215
|
+
PropertyObfuscator.new(obfuscators)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end # end of property obfuscator
|
219
|
+
|
220
|
+
module LoggingUtil
|
221
|
+
@@PROPERTY_OBFUSCATOR = PropertyObfuscator.builder
|
222
|
+
.with_field("cardNumber")
|
223
|
+
.with_field("expiryDate")
|
224
|
+
.with_field("cvv")
|
225
|
+
.with_field("iban")
|
226
|
+
.with_field("accountNumber")
|
227
|
+
.with_field("reformattedAccountNumber")
|
228
|
+
.with_field("additionalInfo")
|
229
|
+
.with_field("cardholderName")
|
230
|
+
.with_field("dateOfBirth")
|
231
|
+
.with_field("emailAddress")
|
232
|
+
.with_field("faxNumber")
|
233
|
+
.with_field("firstName")
|
234
|
+
.with_field("houseNumber")
|
235
|
+
.with_field("mobilePhoneNumber")
|
236
|
+
.with_field("passengerName")
|
237
|
+
.with_field("phoneNumber")
|
238
|
+
.with_field("street")
|
239
|
+
.with_field("surname")
|
240
|
+
.with_field("workPhoneNumber")
|
241
|
+
.with_field("zip")
|
242
|
+
.with_field("bin")
|
243
|
+
.with_field("value")
|
244
|
+
.with_sensitive_field("keyId")
|
245
|
+
.with_sensitive_field("secretKey")
|
246
|
+
.with_sensitive_field("publicKey")
|
247
|
+
.with_sensitive_field("userAuthenticationToken")
|
248
|
+
.with_sensitive_field("encryptedPayload")
|
249
|
+
.with_sensitive_field("decryptedPayload")
|
250
|
+
.with_sensitive_field("encryptedCustomerInput")
|
251
|
+
.build
|
252
|
+
|
253
|
+
@@HEADER_OBFUSCATOR = HeaderObfuscator.builder
|
254
|
+
.with_sensitive_field("Authorization")
|
255
|
+
.with_sensitive_field("WWW-Authenticate")
|
256
|
+
.with_sensitive_field("Proxy-Authenticate")
|
257
|
+
.with_sensitive_field("Proxy-Authorization")
|
258
|
+
.with_sensitive_field("X-GCS-Authentication-Token")
|
259
|
+
.with_sensitive_field("X-GCS-CallerPassword")
|
260
|
+
.build
|
261
|
+
|
262
|
+
def self.obfuscate_body(body)
|
263
|
+
@@PROPERTY_OBFUSCATOR.obfuscate(body)
|
264
|
+
end
|
265
|
+
|
266
|
+
def self.obfuscate_header(name, value)
|
267
|
+
@@HEADER_OBFUSCATOR.obfuscate_value(name, value)
|
268
|
+
end
|
269
|
+
end # end of LoggingUtil
|
270
|
+
end
|
271
|
+
end
|