onlinepayments-sdk-python3 7.4.1__py3-none-any.whl
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.
- onlinepayments/__init__.py +0 -0
- onlinepayments/sdk/__init__.py +4 -0
- onlinepayments/sdk/api_exception.py +60 -0
- onlinepayments/sdk/api_resource.py +57 -0
- onlinepayments/sdk/authentication/__init__.py +0 -0
- onlinepayments/sdk/authentication/authenticator.py +24 -0
- onlinepayments/sdk/authentication/authorization_type.py +10 -0
- onlinepayments/sdk/authentication/v1hmac_authenticator.py +122 -0
- onlinepayments/sdk/authorization_exception.py +19 -0
- onlinepayments/sdk/call_context.py +72 -0
- onlinepayments/sdk/client.py +107 -0
- onlinepayments/sdk/communication/__init__.py +0 -0
- onlinepayments/sdk/communication/communication_exception.py +8 -0
- onlinepayments/sdk/communication/connection.py +84 -0
- onlinepayments/sdk/communication/default_connection.py +313 -0
- onlinepayments/sdk/communication/i_metadata_provider.py +19 -0
- onlinepayments/sdk/communication/metadata_provider.py +132 -0
- onlinepayments/sdk/communication/multipart_form_data_object.py +51 -0
- onlinepayments/sdk/communication/multipart_form_data_request.py +16 -0
- onlinepayments/sdk/communication/not_found_exception.py +10 -0
- onlinepayments/sdk/communication/param_request.py +17 -0
- onlinepayments/sdk/communication/pooled_connection.py +29 -0
- onlinepayments/sdk/communication/request_header.py +60 -0
- onlinepayments/sdk/communication/request_param.py +30 -0
- onlinepayments/sdk/communication/response_exception.py +58 -0
- onlinepayments/sdk/communication/response_header.py +50 -0
- onlinepayments/sdk/communicator.py +465 -0
- onlinepayments/sdk/communicator_configuration.py +264 -0
- onlinepayments/sdk/declined_payment_exception.py +46 -0
- onlinepayments/sdk/declined_payout_exception.py +46 -0
- onlinepayments/sdk/declined_refund_exception.py +46 -0
- onlinepayments/sdk/declined_transaction_exception.py +22 -0
- onlinepayments/sdk/domain/__init__.py +4 -0
- onlinepayments/sdk/domain/acceptance.py +56 -0
- onlinepayments/sdk/domain/account_on_file.py +102 -0
- onlinepayments/sdk/domain/account_on_file_attribute.py +97 -0
- onlinepayments/sdk/domain/account_on_file_display_hints.py +64 -0
- onlinepayments/sdk/domain/acquirer_information.py +59 -0
- onlinepayments/sdk/domain/acquirer_selection_information.py +73 -0
- onlinepayments/sdk/domain/additional_order_input.py +107 -0
- onlinepayments/sdk/domain/address.py +145 -0
- onlinepayments/sdk/domain/address_personal.py +185 -0
- onlinepayments/sdk/domain/airline_data.py +519 -0
- onlinepayments/sdk/domain/airline_flight_leg.py +386 -0
- onlinepayments/sdk/domain/airline_passenger.py +129 -0
- onlinepayments/sdk/domain/amount_breakdown.py +63 -0
- onlinepayments/sdk/domain/amount_of_money.py +59 -0
- onlinepayments/sdk/domain/api_error.py +177 -0
- onlinepayments/sdk/domain/apple_pay_line_item.py +145 -0
- onlinepayments/sdk/domain/apple_pay_recurring_payment_request.py +116 -0
- onlinepayments/sdk/domain/bank_account_iban.py +37 -0
- onlinepayments/sdk/domain/batch_metadata.py +73 -0
- onlinepayments/sdk/domain/browser_data.py +130 -0
- onlinepayments/sdk/domain/calculate_surcharge_request.py +63 -0
- onlinepayments/sdk/domain/calculate_surcharge_response.py +44 -0
- onlinepayments/sdk/domain/cancel_payment_batch_request.py +57 -0
- onlinepayments/sdk/domain/cancel_payment_request.py +130 -0
- onlinepayments/sdk/domain/cancel_payment_response.py +41 -0
- onlinepayments/sdk/domain/capture.py +97 -0
- onlinepayments/sdk/domain/capture_output.py +272 -0
- onlinepayments/sdk/domain/capture_payment_batch_request.py +57 -0
- onlinepayments/sdk/domain/capture_payment_request.py +148 -0
- onlinepayments/sdk/domain/capture_response.py +99 -0
- onlinepayments/sdk/domain/capture_status_output.py +37 -0
- onlinepayments/sdk/domain/captures_response.py +46 -0
- onlinepayments/sdk/domain/card.py +91 -0
- onlinepayments/sdk/domain/card_bin_details.py +384 -0
- onlinepayments/sdk/domain/card_data_without_cvv.py +73 -0
- onlinepayments/sdk/domain/card_essentials.py +438 -0
- onlinepayments/sdk/domain/card_fraud_results.py +112 -0
- onlinepayments/sdk/domain/card_info.py +55 -0
- onlinepayments/sdk/domain/card_payment_method_specific_input.py +608 -0
- onlinepayments/sdk/domain/card_payment_method_specific_input_base.py +441 -0
- onlinepayments/sdk/domain/card_payment_method_specific_input_for_hosted_checkout.py +105 -0
- onlinepayments/sdk/domain/card_payment_method_specific_output.py +467 -0
- onlinepayments/sdk/domain/card_payout_method_specific_input.py +99 -0
- onlinepayments/sdk/domain/card_recurrence_details.py +40 -0
- onlinepayments/sdk/domain/card_source.py +95 -0
- onlinepayments/sdk/domain/card_without_cvv.py +73 -0
- onlinepayments/sdk/domain/click_to_pay.py +37 -0
- onlinepayments/sdk/domain/company_information.py +37 -0
- onlinepayments/sdk/domain/complete_payment_card_payment_method_specific_input.py +39 -0
- onlinepayments/sdk/domain/complete_payment_request.py +61 -0
- onlinepayments/sdk/domain/complete_payment_response.py +85 -0
- onlinepayments/sdk/domain/contact_details.py +109 -0
- onlinepayments/sdk/domain/create_certificate_response.py +55 -0
- onlinepayments/sdk/domain/create_hosted_checkout_request.py +195 -0
- onlinepayments/sdk/domain/create_hosted_checkout_response.py +132 -0
- onlinepayments/sdk/domain/create_hosted_fields_session_request.py +37 -0
- onlinepayments/sdk/domain/create_hosted_fields_session_response.py +102 -0
- onlinepayments/sdk/domain/create_hosted_tokenization_request.py +133 -0
- onlinepayments/sdk/domain/create_hosted_tokenization_response.py +127 -0
- onlinepayments/sdk/domain/create_mandate_request.py +187 -0
- onlinepayments/sdk/domain/create_mandate_response.py +63 -0
- onlinepayments/sdk/domain/create_mandate_with_return_url.py +187 -0
- onlinepayments/sdk/domain/create_payment_link_request.py +344 -0
- onlinepayments/sdk/domain/create_payment_request.py +249 -0
- onlinepayments/sdk/domain/create_payment_response.py +85 -0
- onlinepayments/sdk/domain/create_payout_request.py +176 -0
- onlinepayments/sdk/domain/create_token_request.py +77 -0
- onlinepayments/sdk/domain/created_payment_output.py +57 -0
- onlinepayments/sdk/domain/created_token_response.py +142 -0
- onlinepayments/sdk/domain/credit_card_specific_input_hosted_tokenization.py +66 -0
- onlinepayments/sdk/domain/credit_card_validation_rules.py +55 -0
- onlinepayments/sdk/domain/credit_card_validation_rules_hosted_tokenization.py +55 -0
- onlinepayments/sdk/domain/crm_token.py +55 -0
- onlinepayments/sdk/domain/csr_request.py +37 -0
- onlinepayments/sdk/domain/currency_conversion.py +59 -0
- onlinepayments/sdk/domain/currency_conversion_input.py +55 -0
- onlinepayments/sdk/domain/currency_conversion_request.py +59 -0
- onlinepayments/sdk/domain/currency_conversion_response.py +81 -0
- onlinepayments/sdk/domain/currency_conversion_result.py +61 -0
- onlinepayments/sdk/domain/currency_conversion_specific_input.py +40 -0
- onlinepayments/sdk/domain/customer.py +234 -0
- onlinepayments/sdk/domain/customer_account.py +204 -0
- onlinepayments/sdk/domain/customer_account_authentication.py +81 -0
- onlinepayments/sdk/domain/customer_bank_account.py +73 -0
- onlinepayments/sdk/domain/customer_device.py +155 -0
- onlinepayments/sdk/domain/customer_device_output.py +37 -0
- onlinepayments/sdk/domain/customer_output.py +41 -0
- onlinepayments/sdk/domain/customer_payment_activity.py +73 -0
- onlinepayments/sdk/domain/customer_token.py +83 -0
- onlinepayments/sdk/domain/data_object.py +47 -0
- onlinepayments/sdk/domain/dcc_card_source.py +93 -0
- onlinepayments/sdk/domain/dcc_proposal.py +118 -0
- onlinepayments/sdk/domain/decrypted_payment_data.py +120 -0
- onlinepayments/sdk/domain/detokenization_response.py +46 -0
- onlinepayments/sdk/domain/detokenized_token_response.py +145 -0
- onlinepayments/sdk/domain/directory_entry.py +73 -0
- onlinepayments/sdk/domain/discount.py +41 -0
- onlinepayments/sdk/domain/empty_validator.py +16 -0
- onlinepayments/sdk/domain/error_response.py +64 -0
- onlinepayments/sdk/domain/external_cardholder_authentication_data.py +216 -0
- onlinepayments/sdk/domain/external_token_linked.py +75 -0
- onlinepayments/sdk/domain/feedbacks.py +64 -0
- onlinepayments/sdk/domain/fixed_list_validator.py +42 -0
- onlinepayments/sdk/domain/fraud_fields.py +84 -0
- onlinepayments/sdk/domain/fraud_results.py +43 -0
- onlinepayments/sdk/domain/g_pay_three_d_secure.py +159 -0
- onlinepayments/sdk/domain/get_batch_status_response.py +91 -0
- onlinepayments/sdk/domain/get_hosted_checkout_response.py +63 -0
- onlinepayments/sdk/domain/get_hosted_tokenization_response.py +61 -0
- onlinepayments/sdk/domain/get_iin_details_request.py +57 -0
- onlinepayments/sdk/domain/get_iin_details_response.py +450 -0
- onlinepayments/sdk/domain/get_mandate_response.py +41 -0
- onlinepayments/sdk/domain/get_payment_product_groups_response.py +44 -0
- onlinepayments/sdk/domain/get_payment_products_response.py +44 -0
- onlinepayments/sdk/domain/get_privacy_policy_response.py +37 -0
- onlinepayments/sdk/domain/gift_card_purchase.py +59 -0
- onlinepayments/sdk/domain/hosted_checkout_specific_input.py +250 -0
- onlinepayments/sdk/domain/hosted_checkout_specific_output.py +55 -0
- onlinepayments/sdk/domain/iin_detail.py +423 -0
- onlinepayments/sdk/domain/import_cof_series_request.py +113 -0
- onlinepayments/sdk/domain/import_cof_series_response.py +37 -0
- onlinepayments/sdk/domain/label_template_element.py +55 -0
- onlinepayments/sdk/domain/length_validator.py +51 -0
- onlinepayments/sdk/domain/line_item.py +107 -0
- onlinepayments/sdk/domain/line_item_detail.py +99 -0
- onlinepayments/sdk/domain/line_item_invoice_data.py +37 -0
- onlinepayments/sdk/domain/loan_recipient.py +109 -0
- onlinepayments/sdk/domain/lodging_data.py +37 -0
- onlinepayments/sdk/domain/mandate_address.py +109 -0
- onlinepayments/sdk/domain/mandate_address_response.py +109 -0
- onlinepayments/sdk/domain/mandate_contact_details.py +37 -0
- onlinepayments/sdk/domain/mandate_customer.py +125 -0
- onlinepayments/sdk/domain/mandate_customer_response.py +125 -0
- onlinepayments/sdk/domain/mandate_merchant_action.py +61 -0
- onlinepayments/sdk/domain/mandate_personal_information.py +59 -0
- onlinepayments/sdk/domain/mandate_personal_information_response.py +59 -0
- onlinepayments/sdk/domain/mandate_personal_name.py +55 -0
- onlinepayments/sdk/domain/mandate_personal_name_response.py +55 -0
- onlinepayments/sdk/domain/mandate_redirect_data.py +55 -0
- onlinepayments/sdk/domain/mandate_response.py +150 -0
- onlinepayments/sdk/domain/market_place.py +55 -0
- onlinepayments/sdk/domain/merchant_action.py +132 -0
- onlinepayments/sdk/domain/mobile_payment_data.py +55 -0
- onlinepayments/sdk/domain/mobile_payment_method_hosted_checkout_specific_input.py +105 -0
- onlinepayments/sdk/domain/mobile_payment_method_specific_input.py +202 -0
- onlinepayments/sdk/domain/mobile_payment_method_specific_output.py +139 -0
- onlinepayments/sdk/domain/mobile_payment_product302_specific_input.py +103 -0
- onlinepayments/sdk/domain/mobile_payment_product320_specific_input.py +103 -0
- onlinepayments/sdk/domain/mobile_three_d_secure_challenge_parameters.py +91 -0
- onlinepayments/sdk/domain/multiple_payment_information.py +57 -0
- onlinepayments/sdk/domain/network_token_data.py +127 -0
- onlinepayments/sdk/domain/network_token_essentials.py +134 -0
- onlinepayments/sdk/domain/network_token_linked.py +80 -0
- onlinepayments/sdk/domain/omnichannel_payment_specific_input.py +37 -0
- onlinepayments/sdk/domain/omnichannel_payout_specific_input.py +55 -0
- onlinepayments/sdk/domain/omnichannel_refund_specific_input.py +37 -0
- onlinepayments/sdk/domain/omnichannel_subsequent_specific_input.py +37 -0
- onlinepayments/sdk/domain/operation_output.py +161 -0
- onlinepayments/sdk/domain/operation_payment_references.py +55 -0
- onlinepayments/sdk/domain/order.py +213 -0
- onlinepayments/sdk/domain/order_line_details.py +189 -0
- onlinepayments/sdk/domain/order_references.py +120 -0
- onlinepayments/sdk/domain/order_status_output.py +119 -0
- onlinepayments/sdk/domain/order_type_information.py +64 -0
- onlinepayments/sdk/domain/other_details.py +55 -0
- onlinepayments/sdk/domain/payment_account_on_file.py +57 -0
- onlinepayments/sdk/domain/payment_context.py +77 -0
- onlinepayments/sdk/domain/payment_creation_output.py +94 -0
- onlinepayments/sdk/domain/payment_details_response.py +148 -0
- onlinepayments/sdk/domain/payment_error_response.py +84 -0
- onlinepayments/sdk/domain/payment_link_event.py +73 -0
- onlinepayments/sdk/domain/payment_link_order_input.py +84 -0
- onlinepayments/sdk/domain/payment_link_order_output.py +81 -0
- onlinepayments/sdk/domain/payment_link_response.py +216 -0
- onlinepayments/sdk/domain/payment_link_specific_input.py +74 -0
- onlinepayments/sdk/domain/payment_links_response.py +44 -0
- onlinepayments/sdk/domain/payment_output.py +335 -0
- onlinepayments/sdk/domain/payment_product.py +296 -0
- onlinepayments/sdk/domain/payment_product130_specific_input.py +41 -0
- onlinepayments/sdk/domain/payment_product130_specific_three_d_secure.py +91 -0
- onlinepayments/sdk/domain/payment_product3012.py +55 -0
- onlinepayments/sdk/domain/payment_product3012_specific_input.py +100 -0
- onlinepayments/sdk/domain/payment_product3013_specific_input.py +73 -0
- onlinepayments/sdk/domain/payment_product302_specific_data.py +44 -0
- onlinepayments/sdk/domain/payment_product3203_specific_output.py +62 -0
- onlinepayments/sdk/domain/payment_product3204_specific_output.py +37 -0
- onlinepayments/sdk/domain/payment_product3208_specific_input.py +37 -0
- onlinepayments/sdk/domain/payment_product3208_specific_output.py +37 -0
- onlinepayments/sdk/domain/payment_product3209_specific_input.py +37 -0
- onlinepayments/sdk/domain/payment_product3209_specific_output.py +37 -0
- onlinepayments/sdk/domain/payment_product320_specific_data.py +62 -0
- onlinepayments/sdk/domain/payment_product350.py +55 -0
- onlinepayments/sdk/domain/payment_product5001.py +58 -0
- onlinepayments/sdk/domain/payment_product5001_specific_output.py +112 -0
- onlinepayments/sdk/domain/payment_product5100_specific_input.py +37 -0
- onlinepayments/sdk/domain/payment_product5402_specific_output.py +37 -0
- onlinepayments/sdk/domain/payment_product5404.py +55 -0
- onlinepayments/sdk/domain/payment_product5407.py +55 -0
- onlinepayments/sdk/domain/payment_product5500_specific_output.py +91 -0
- onlinepayments/sdk/domain/payment_product771_specific_output.py +37 -0
- onlinepayments/sdk/domain/payment_product840.py +37 -0
- onlinepayments/sdk/domain/payment_product840_customer_account.py +170 -0
- onlinepayments/sdk/domain/payment_product840_specific_output.py +167 -0
- onlinepayments/sdk/domain/payment_product_display_hints.py +73 -0
- onlinepayments/sdk/domain/payment_product_field.py +95 -0
- onlinepayments/sdk/domain/payment_product_field_data_restrictions.py +60 -0
- onlinepayments/sdk/domain/payment_product_field_display_element.py +97 -0
- onlinepayments/sdk/domain/payment_product_field_display_hints.py +218 -0
- onlinepayments/sdk/domain/payment_product_field_form_element.py +72 -0
- onlinepayments/sdk/domain/payment_product_field_tooltip.py +57 -0
- onlinepayments/sdk/domain/payment_product_field_validators.py +195 -0
- onlinepayments/sdk/domain/payment_product_filter.py +67 -0
- onlinepayments/sdk/domain/payment_product_filter_hosted_tokenization.py +42 -0
- onlinepayments/sdk/domain/payment_product_filters_hosted_checkout.py +62 -0
- onlinepayments/sdk/domain/payment_product_filters_hosted_tokenization.py +62 -0
- onlinepayments/sdk/domain/payment_product_group.py +103 -0
- onlinepayments/sdk/domain/payment_product_networks_response.py +42 -0
- onlinepayments/sdk/domain/payment_references.py +73 -0
- onlinepayments/sdk/domain/payment_response.py +143 -0
- onlinepayments/sdk/domain/payment_status_output.py +152 -0
- onlinepayments/sdk/domain/payout_error_response.py +80 -0
- onlinepayments/sdk/domain/payout_output.py +63 -0
- onlinepayments/sdk/domain/payout_response.py +93 -0
- onlinepayments/sdk/domain/payout_result.py +93 -0
- onlinepayments/sdk/domain/payout_status_output.py +76 -0
- onlinepayments/sdk/domain/pending_authentication.py +37 -0
- onlinepayments/sdk/domain/personal_information.py +77 -0
- onlinepayments/sdk/domain/personal_information_token.py +39 -0
- onlinepayments/sdk/domain/personal_name.py +73 -0
- onlinepayments/sdk/domain/personal_name_token.py +51 -0
- onlinepayments/sdk/domain/product302_recurring.py +37 -0
- onlinepayments/sdk/domain/product320_recurring.py +37 -0
- onlinepayments/sdk/domain/product_directory.py +46 -0
- onlinepayments/sdk/domain/protection_eligibility.py +59 -0
- onlinepayments/sdk/domain/range_validator.py +51 -0
- onlinepayments/sdk/domain/rate_details.py +109 -0
- onlinepayments/sdk/domain/reattempt_instructions.py +82 -0
- onlinepayments/sdk/domain/reattempt_instructions_conditions.py +55 -0
- onlinepayments/sdk/domain/redirect_data.py +55 -0
- onlinepayments/sdk/domain/redirect_payment_method_specific_input.py +575 -0
- onlinepayments/sdk/domain/redirect_payment_method_specific_output.py +267 -0
- onlinepayments/sdk/domain/redirect_payment_product11_specific_input.py +38 -0
- onlinepayments/sdk/domain/redirect_payment_product3103_specific_input.py +40 -0
- onlinepayments/sdk/domain/redirect_payment_product3112_specific_input.py +40 -0
- onlinepayments/sdk/domain/redirect_payment_product3116_specific_input.py +40 -0
- onlinepayments/sdk/domain/redirect_payment_product3203_specific_input.py +40 -0
- onlinepayments/sdk/domain/redirect_payment_product3204_specific_input.py +55 -0
- onlinepayments/sdk/domain/redirect_payment_product3302_specific_input.py +73 -0
- onlinepayments/sdk/domain/redirect_payment_product3306_specific_input.py +37 -0
- onlinepayments/sdk/domain/redirect_payment_product3307_specific_input.py +16 -0
- onlinepayments/sdk/domain/redirect_payment_product5001_specific_input.py +62 -0
- onlinepayments/sdk/domain/redirect_payment_product5300_specific_input.py +163 -0
- onlinepayments/sdk/domain/redirect_payment_product5402_specific_input.py +40 -0
- onlinepayments/sdk/domain/redirect_payment_product5403_specific_input.py +40 -0
- onlinepayments/sdk/domain/redirect_payment_product5406_specific_input.py +41 -0
- onlinepayments/sdk/domain/redirect_payment_product5408_specific_input.py +60 -0
- onlinepayments/sdk/domain/redirect_payment_product5410_specific_input.py +38 -0
- onlinepayments/sdk/domain/redirect_payment_product5412_specific_input.py +55 -0
- onlinepayments/sdk/domain/redirect_payment_product5601_specific_input.py +40 -0
- onlinepayments/sdk/domain/redirect_payment_product809_specific_input.py +40 -0
- onlinepayments/sdk/domain/redirect_payment_product840_specific_input.py +100 -0
- onlinepayments/sdk/domain/redirection_data.py +37 -0
- onlinepayments/sdk/domain/refund_card_method_specific_output.py +71 -0
- onlinepayments/sdk/domain/refund_e_wallet_method_specific_output.py +71 -0
- onlinepayments/sdk/domain/refund_error_response.py +82 -0
- onlinepayments/sdk/domain/refund_mobile_method_specific_output.py +69 -0
- onlinepayments/sdk/domain/refund_output.py +217 -0
- onlinepayments/sdk/domain/refund_payment_batch_request.py +57 -0
- onlinepayments/sdk/domain/refund_payment_product840_customer_account.py +69 -0
- onlinepayments/sdk/domain/refund_payment_product840_specific_output.py +39 -0
- onlinepayments/sdk/domain/refund_redirect_method_specific_output.py +51 -0
- onlinepayments/sdk/domain/refund_redirect_payment_method_specific_input.py +41 -0
- onlinepayments/sdk/domain/refund_redirect_payment_product900_specific_input.py +37 -0
- onlinepayments/sdk/domain/refund_request.py +210 -0
- onlinepayments/sdk/domain/refund_response.py +97 -0
- onlinepayments/sdk/domain/refunds_response.py +46 -0
- onlinepayments/sdk/domain/regular_expression_validator.py +35 -0
- onlinepayments/sdk/domain/revoke_mandate_request.py +48 -0
- onlinepayments/sdk/domain/send_test_request.py +37 -0
- onlinepayments/sdk/domain/sepa_direct_debit_payment_method_specific_input.py +59 -0
- onlinepayments/sdk/domain/sepa_direct_debit_payment_method_specific_input_base.py +59 -0
- onlinepayments/sdk/domain/sepa_direct_debit_payment_method_specific_output.py +81 -0
- onlinepayments/sdk/domain/sepa_direct_debit_payment_product771_specific_input.py +59 -0
- onlinepayments/sdk/domain/sepa_direct_debit_payment_product771_specific_input_base.py +59 -0
- onlinepayments/sdk/domain/session_data.py +116 -0
- onlinepayments/sdk/domain/session_details.py +55 -0
- onlinepayments/sdk/domain/session_request.py +44 -0
- onlinepayments/sdk/domain/session_response.py +114 -0
- onlinepayments/sdk/domain/shipping.py +214 -0
- onlinepayments/sdk/domain/shipping_detail.py +63 -0
- onlinepayments/sdk/domain/shipping_method.py +91 -0
- onlinepayments/sdk/domain/shopping_cart.py +155 -0
- onlinepayments/sdk/domain/shopping_cart_extension.py +77 -0
- onlinepayments/sdk/domain/shopping_cart_output.py +46 -0
- onlinepayments/sdk/domain/show_form_data.py +173 -0
- onlinepayments/sdk/domain/show_instructions_data.py +37 -0
- onlinepayments/sdk/domain/split_payment_product_filter.py +42 -0
- onlinepayments/sdk/domain/split_payment_product_filters_hosted_checkout.py +62 -0
- onlinepayments/sdk/domain/submit_batch_request_body.py +230 -0
- onlinepayments/sdk/domain/submit_batch_response.py +55 -0
- onlinepayments/sdk/domain/subsequent_card_payment_method_specific_input.py +175 -0
- onlinepayments/sdk/domain/subsequent_payment_batch_request.py +57 -0
- onlinepayments/sdk/domain/subsequent_payment_product5001_specific_input.py +41 -0
- onlinepayments/sdk/domain/subsequent_payment_request.py +107 -0
- onlinepayments/sdk/domain/subsequent_payment_response.py +41 -0
- onlinepayments/sdk/domain/surcharge.py +141 -0
- onlinepayments/sdk/domain/surcharge_calculation_card.py +55 -0
- onlinepayments/sdk/domain/surcharge_for_payment_link.py +40 -0
- onlinepayments/sdk/domain/surcharge_rate.py +91 -0
- onlinepayments/sdk/domain/surcharge_specific_input.py +62 -0
- onlinepayments/sdk/domain/surcharge_specific_output.py +84 -0
- onlinepayments/sdk/domain/test_connection.py +35 -0
- onlinepayments/sdk/domain/three_d_secure.py +281 -0
- onlinepayments/sdk/domain/three_d_secure_base.py +219 -0
- onlinepayments/sdk/domain/three_d_secure_data.py +78 -0
- onlinepayments/sdk/domain/three_d_secure_results.py +266 -0
- onlinepayments/sdk/domain/token_card.py +57 -0
- onlinepayments/sdk/domain/token_card_data.py +83 -0
- onlinepayments/sdk/domain/token_card_specific_input.py +41 -0
- onlinepayments/sdk/domain/token_data.py +63 -0
- onlinepayments/sdk/domain/token_e_wallet.py +59 -0
- onlinepayments/sdk/domain/token_response.py +181 -0
- onlinepayments/sdk/domain/transaction.py +41 -0
- onlinepayments/sdk/domain/uploadable_file.py +51 -0
- onlinepayments/sdk/domain/validate_credentials_request.py +55 -0
- onlinepayments/sdk/domain/validate_credentials_response.py +37 -0
- onlinepayments/sdk/domain/value_mapping_element.py +62 -0
- onlinepayments/sdk/domain/web_hooks_event.py +214 -0
- onlinepayments/sdk/exception_factory.py +75 -0
- onlinepayments/sdk/factory.py +127 -0
- onlinepayments/sdk/i_client.py +78 -0
- onlinepayments/sdk/i_communicator.py +180 -0
- onlinepayments/sdk/idempotence_exception.py +36 -0
- onlinepayments/sdk/json/__init__.py +0 -0
- onlinepayments/sdk/json/default_marshaller.py +60 -0
- onlinepayments/sdk/json/marshaller.py +32 -0
- onlinepayments/sdk/json/marshaller_syntax_exception.py +13 -0
- onlinepayments/sdk/log/__init__.py +0 -0
- onlinepayments/sdk/log/body_obfuscator.py +113 -0
- onlinepayments/sdk/log/communicator_logger.py +35 -0
- onlinepayments/sdk/log/header_obfuscator.py +49 -0
- onlinepayments/sdk/log/log_message.py +94 -0
- onlinepayments/sdk/log/logging_capable.py +26 -0
- onlinepayments/sdk/log/obfuscation_capable.py +24 -0
- onlinepayments/sdk/log/obfuscation_rule.py +50 -0
- onlinepayments/sdk/log/python_communicator_logger.py +54 -0
- onlinepayments/sdk/log/request_log_message.py +28 -0
- onlinepayments/sdk/log/response_log_message.py +37 -0
- onlinepayments/sdk/log/sys_out_communicator_logger.py +36 -0
- onlinepayments/sdk/merchant/__init__.py +4 -0
- onlinepayments/sdk/merchant/captures/__init__.py +4 -0
- onlinepayments/sdk/merchant/captures/captures_client.py +63 -0
- onlinepayments/sdk/merchant/captures/i_captures_client.py +34 -0
- onlinepayments/sdk/merchant/cofseries/__init__.py +4 -0
- onlinepayments/sdk/merchant/cofseries/cof_series_client.py +62 -0
- onlinepayments/sdk/merchant/cofseries/i_cof_series_client.py +35 -0
- onlinepayments/sdk/merchant/complete/__init__.py +4 -0
- onlinepayments/sdk/merchant/complete/complete_client.py +67 -0
- onlinepayments/sdk/merchant/complete/i_complete_client.py +37 -0
- onlinepayments/sdk/merchant/hostedcheckout/__init__.py +4 -0
- onlinepayments/sdk/merchant/hostedcheckout/hosted_checkout_client.py +99 -0
- onlinepayments/sdk/merchant/hostedcheckout/i_hosted_checkout_client.py +55 -0
- onlinepayments/sdk/merchant/hostedfields/__init__.py +4 -0
- onlinepayments/sdk/merchant/hostedfields/hosted_fields_client.py +62 -0
- onlinepayments/sdk/merchant/hostedfields/i_hosted_fields_client.py +35 -0
- onlinepayments/sdk/merchant/hostedtokenization/__init__.py +4 -0
- onlinepayments/sdk/merchant/hostedtokenization/hosted_tokenization_client.py +99 -0
- onlinepayments/sdk/merchant/hostedtokenization/i_hosted_tokenization_client.py +55 -0
- onlinepayments/sdk/merchant/i_merchant_client.py +202 -0
- onlinepayments/sdk/merchant/mandates/__init__.py +4 -0
- onlinepayments/sdk/merchant/mandates/i_mandates_client.py +114 -0
- onlinepayments/sdk/merchant/mandates/mandates_client.py +212 -0
- onlinepayments/sdk/merchant/merchant_client.py +232 -0
- onlinepayments/sdk/merchant/merchantbatch/__init__.py +4 -0
- onlinepayments/sdk/merchant/merchantbatch/i_merchant_batch_client.py +74 -0
- onlinepayments/sdk/merchant/merchantbatch/merchant_batch_client.py +138 -0
- onlinepayments/sdk/merchant/paymentlinks/__init__.py +4 -0
- onlinepayments/sdk/merchant/paymentlinks/get_payment_links_in_bulk_params.py +36 -0
- onlinepayments/sdk/merchant/paymentlinks/i_payment_links_client.py +73 -0
- onlinepayments/sdk/merchant/paymentlinks/payment_links_client.py +135 -0
- onlinepayments/sdk/merchant/payments/__init__.py +4 -0
- onlinepayments/sdk/merchant/payments/i_payments_client.py +143 -0
- onlinepayments/sdk/merchant/payments/payments_client.py +260 -0
- onlinepayments/sdk/merchant/payouts/__init__.py +4 -0
- onlinepayments/sdk/merchant/payouts/i_payouts_client.py +55 -0
- onlinepayments/sdk/merchant/payouts/payouts_client.py +100 -0
- onlinepayments/sdk/merchant/privacypolicy/__init__.py +4 -0
- onlinepayments/sdk/merchant/privacypolicy/get_privacy_policy_params.py +54 -0
- onlinepayments/sdk/merchant/privacypolicy/i_privacy_policy_client.py +36 -0
- onlinepayments/sdk/merchant/privacypolicy/privacy_policy_client.py +61 -0
- onlinepayments/sdk/merchant/productgroups/__init__.py +4 -0
- onlinepayments/sdk/merchant/productgroups/get_product_group_params.py +140 -0
- onlinepayments/sdk/merchant/productgroups/get_product_groups_params.py +140 -0
- onlinepayments/sdk/merchant/productgroups/i_product_groups_client.py +58 -0
- onlinepayments/sdk/merchant/productgroups/product_groups_client.py +100 -0
- onlinepayments/sdk/merchant/products/__init__.py +4 -0
- onlinepayments/sdk/merchant/products/get_payment_product_networks_params.py +89 -0
- onlinepayments/sdk/merchant/products/get_payment_product_params.py +138 -0
- onlinepayments/sdk/merchant/products/get_payment_products_params.py +138 -0
- onlinepayments/sdk/merchant/products/get_product_directory_params.py +54 -0
- onlinepayments/sdk/merchant/products/i_products_client.py +102 -0
- onlinepayments/sdk/merchant/products/products_client.py +178 -0
- onlinepayments/sdk/merchant/refunds/__init__.py +4 -0
- onlinepayments/sdk/merchant/refunds/i_refunds_client.py +34 -0
- onlinepayments/sdk/merchant/refunds/refunds_client.py +63 -0
- onlinepayments/sdk/merchant/services/__init__.py +4 -0
- onlinepayments/sdk/merchant/services/i_services_client.py +96 -0
- onlinepayments/sdk/merchant/services/services_client.py +167 -0
- onlinepayments/sdk/merchant/sessions/__init__.py +4 -0
- onlinepayments/sdk/merchant/sessions/i_sessions_client.py +35 -0
- onlinepayments/sdk/merchant/sessions/sessions_client.py +62 -0
- onlinepayments/sdk/merchant/subsequent/__init__.py +4 -0
- onlinepayments/sdk/merchant/subsequent/i_subsequent_client.py +37 -0
- onlinepayments/sdk/merchant/subsequent/subsequent_client.py +67 -0
- onlinepayments/sdk/merchant/tokenization/__init__.py +4 -0
- onlinepayments/sdk/merchant/tokenization/get_card_data_by_payments_params.py +48 -0
- onlinepayments/sdk/merchant/tokenization/get_card_data_by_tokens_params.py +48 -0
- onlinepayments/sdk/merchant/tokenization/i_tokenization_client.py +77 -0
- onlinepayments/sdk/merchant/tokenization/tokenization_client.py +131 -0
- onlinepayments/sdk/merchant/tokens/__init__.py +4 -0
- onlinepayments/sdk/merchant/tokens/i_tokens_client.py +74 -0
- onlinepayments/sdk/merchant/tokens/tokens_client.py +135 -0
- onlinepayments/sdk/merchant/webhooks/__init__.py +4 -0
- onlinepayments/sdk/merchant/webhooks/i_webhooks_client.py +55 -0
- onlinepayments/sdk/merchant/webhooks/webhooks_client.py +97 -0
- onlinepayments/sdk/platform_exception.py +19 -0
- onlinepayments/sdk/proxy_configuration.py +102 -0
- onlinepayments/sdk/reference_exception.py +19 -0
- onlinepayments/sdk/validation_exception.py +19 -0
- onlinepayments/sdk/webhooks/__init__.py +0 -0
- onlinepayments/sdk/webhooks/api_version_mismatch_exception.py +24 -0
- onlinepayments/sdk/webhooks/in_memory_secret_key_store.py +48 -0
- onlinepayments/sdk/webhooks/secret_key_not_available_exception.py +18 -0
- onlinepayments/sdk/webhooks/secret_key_store.py +15 -0
- onlinepayments/sdk/webhooks/signature_validation_exception.py +17 -0
- onlinepayments/sdk/webhooks/signature_validator.py +56 -0
- onlinepayments/sdk/webhooks/webhooks_helper.py +52 -0
- onlinepayments_sdk_python3-7.4.1.dist-info/METADATA +154 -0
- onlinepayments_sdk_python3-7.4.1.dist-info/RECORD +475 -0
- onlinepayments_sdk_python3-7.4.1.dist-info/WHEEL +5 -0
- onlinepayments_sdk_python3-7.4.1.dist-info/licenses/LICENSE.txt +52 -0
- onlinepayments_sdk_python3-7.4.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
import gzip
|
|
5
|
+
import uuid
|
|
6
|
+
from datetime import datetime, timedelta
|
|
7
|
+
from typing import Mapping, Optional, Sequence, Any, Generator
|
|
8
|
+
from urllib.parse import urlparse
|
|
9
|
+
|
|
10
|
+
import requests
|
|
11
|
+
from requests.adapters import HTTPAdapter
|
|
12
|
+
from requests.models import PreparedRequest
|
|
13
|
+
from requests.exceptions import RequestException, Timeout
|
|
14
|
+
from requests.structures import CaseInsensitiveDict
|
|
15
|
+
from requests_toolbelt import MultipartEncoder
|
|
16
|
+
|
|
17
|
+
from .communication_exception import CommunicationException
|
|
18
|
+
from .connection import RequestBody, Response, URI
|
|
19
|
+
from .multipart_form_data_object import MultipartFormDataObject
|
|
20
|
+
from .pooled_connection import PooledConnection
|
|
21
|
+
from .request_header import RequestHeader
|
|
22
|
+
from .response_header import get_header_value
|
|
23
|
+
|
|
24
|
+
from onlinepayments.sdk.communicator_configuration import CommunicatorConfiguration
|
|
25
|
+
from onlinepayments.sdk.proxy_configuration import ProxyConfiguration
|
|
26
|
+
from onlinepayments.sdk.log.body_obfuscator import BodyObfuscator
|
|
27
|
+
from onlinepayments.sdk.log.communicator_logger import CommunicatorLogger
|
|
28
|
+
from onlinepayments.sdk.log.header_obfuscator import HeaderObfuscator
|
|
29
|
+
from onlinepayments.sdk.log.request_log_message import RequestLogMessage
|
|
30
|
+
from onlinepayments.sdk.log.response_log_message import ResponseLogMessage
|
|
31
|
+
|
|
32
|
+
CHARSET = "UTF-8"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class DefaultConnection(PooledConnection):
|
|
36
|
+
"""
|
|
37
|
+
Provides an HTTP request interface, thread-safe
|
|
38
|
+
|
|
39
|
+
:param connect_timeout: timeout in seconds before a pending connection is dropped
|
|
40
|
+
:param socket_timeout: timeout in seconds before dropping an established connection.
|
|
41
|
+
This is the time the server is allowed for a response
|
|
42
|
+
:param max_connections: the maximum number of connections in the connection pool
|
|
43
|
+
:param proxy_configuration: ProxyConfiguration object that contains data about proxy settings if present.
|
|
44
|
+
It should be writeable as string and have a scheme attribute.
|
|
45
|
+
|
|
46
|
+
Use the methods get, delete, post and put to perform the corresponding HTTP request.
|
|
47
|
+
Alternatively you can use request with the request method as the first parameter.
|
|
48
|
+
|
|
49
|
+
URI, headers and body should be given on a per-request basis.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def __init__(self, connect_timeout: int, socket_timeout: int,
|
|
53
|
+
max_connections: int = CommunicatorConfiguration.DEFAULT_MAX_CONNECTIONS,
|
|
54
|
+
proxy_configuration: Optional[ProxyConfiguration] = None):
|
|
55
|
+
self.logger = None
|
|
56
|
+
self.__requests_session = requests.session()
|
|
57
|
+
self.__requests_session.mount("http://", HTTPAdapter(pool_maxsize=max_connections,
|
|
58
|
+
pool_connections=1))
|
|
59
|
+
self.__requests_session.mount("https://", HTTPAdapter(pool_maxsize=max_connections,
|
|
60
|
+
pool_connections=1))
|
|
61
|
+
# request timeouts are in seconds
|
|
62
|
+
self.__connect_timeout = connect_timeout if connect_timeout >= 0 else None
|
|
63
|
+
self.__socket_timeout = socket_timeout if socket_timeout >= 0 else None
|
|
64
|
+
if proxy_configuration:
|
|
65
|
+
proxy = {
|
|
66
|
+
"http": str(proxy_configuration),
|
|
67
|
+
"https": str(proxy_configuration)
|
|
68
|
+
}
|
|
69
|
+
self.__requests_session.proxies = proxy
|
|
70
|
+
|
|
71
|
+
self.__body_obfuscator = BodyObfuscator.default_body_obfuscator()
|
|
72
|
+
self.__header_obfuscator = HeaderObfuscator.default_header_obfuscator()
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def connect_timeout(self) -> Optional[int]:
|
|
76
|
+
"""Connection timeout in seconds"""
|
|
77
|
+
return self.__connect_timeout
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def socket_timeout(self) -> Optional[int]:
|
|
81
|
+
"""Socket timeout in seconds"""
|
|
82
|
+
return self.__socket_timeout
|
|
83
|
+
|
|
84
|
+
def get(self, url: URI, request_headers: Sequence[RequestHeader]) -> Response:
|
|
85
|
+
"""Perform a request to the server given by url
|
|
86
|
+
|
|
87
|
+
:param url: the url to the server, given as a parsed url
|
|
88
|
+
:param request_headers: a sequence containing RequestHeader objects representing the request headers
|
|
89
|
+
"""
|
|
90
|
+
return self._request('get', url, request_headers)
|
|
91
|
+
|
|
92
|
+
def delete(self, url: URI, request_headers: Sequence[RequestHeader]) -> Response:
|
|
93
|
+
"""Perform a request to the server given by url
|
|
94
|
+
|
|
95
|
+
:param url: the url to the server, given as a parsed url
|
|
96
|
+
:param request_headers: a sequence containing RequestHeader objects representing the request headers
|
|
97
|
+
"""
|
|
98
|
+
return self._request('delete', url, request_headers)
|
|
99
|
+
|
|
100
|
+
def post(self, url: URI, request_headers: Sequence[RequestHeader], body: RequestBody) -> Response:
|
|
101
|
+
"""Perform a request to the server given by url
|
|
102
|
+
|
|
103
|
+
:param url: the url to the server, given as a parsed url
|
|
104
|
+
:param request_headers: a sequence containing RequestHeader objects representing the request headers
|
|
105
|
+
:param body: the request body
|
|
106
|
+
"""
|
|
107
|
+
if isinstance(body, MultipartFormDataObject):
|
|
108
|
+
body = self.__to_multipart_encoder(body).to_string()
|
|
109
|
+
|
|
110
|
+
headers_dict = {h.name: h.value for h in (request_headers or [])}
|
|
111
|
+
content_encoding = headers_dict.get('Content-Encoding') or headers_dict.get('content-encoding')
|
|
112
|
+
|
|
113
|
+
if body is not None and content_encoding and 'gzip' in content_encoding.lower():
|
|
114
|
+
body = gzip.compress(body.encode("utf-8"))
|
|
115
|
+
|
|
116
|
+
return self._request('post', url, request_headers, body)
|
|
117
|
+
|
|
118
|
+
def put(self, url: URI, request_headers: Sequence[RequestHeader], body: RequestBody) -> Response:
|
|
119
|
+
"""Perform a request to the server given by url
|
|
120
|
+
|
|
121
|
+
:param url: the url to the server, given as a parsed url
|
|
122
|
+
:param request_headers: a sequence containing RequestHeader objects representing the request headers
|
|
123
|
+
:param body: the request body
|
|
124
|
+
"""
|
|
125
|
+
if isinstance(body, MultipartFormDataObject):
|
|
126
|
+
body = self.__to_multipart_encoder(body).to_string()
|
|
127
|
+
return self._request('put', url, request_headers, body)
|
|
128
|
+
|
|
129
|
+
@staticmethod
|
|
130
|
+
def __to_multipart_encoder(multipart: MultipartFormDataObject) -> MultipartEncoder:
|
|
131
|
+
fields = {}
|
|
132
|
+
for name, value in multipart.values.items():
|
|
133
|
+
fields[name] = value
|
|
134
|
+
for name, uploadable_file in multipart.files.items():
|
|
135
|
+
fields[name] = (uploadable_file.file_name, uploadable_file.content, uploadable_file.content_type)
|
|
136
|
+
encoder = MultipartEncoder(fields=fields,
|
|
137
|
+
boundary=multipart.boundary)
|
|
138
|
+
if encoder.content_type != multipart.content_type:
|
|
139
|
+
raise ValueError("MultipartEncoder did not create the expected content type")
|
|
140
|
+
return encoder
|
|
141
|
+
|
|
142
|
+
class _ToResult(object):
|
|
143
|
+
def __call__(self, func):
|
|
144
|
+
def _wrapper(*args, **kwargs):
|
|
145
|
+
result = func(*args, **kwargs)
|
|
146
|
+
header = next(result)
|
|
147
|
+
return header + (result,)
|
|
148
|
+
return _wrapper
|
|
149
|
+
|
|
150
|
+
@_ToResult()
|
|
151
|
+
def _request(self, method: str, url: URI, headers: Sequence[RequestHeader], body: RequestBody = None) -> Generator[
|
|
152
|
+
tuple[int, CaseInsensitiveDict[str]] | Any, Any, None]:
|
|
153
|
+
"""
|
|
154
|
+
Perform a request to the server given by url
|
|
155
|
+
|
|
156
|
+
:param url: the url to the server, given as a parsed url
|
|
157
|
+
:param headers: a sequence containing RequestHeader objects representing the request headers
|
|
158
|
+
:param body: the request body
|
|
159
|
+
"""
|
|
160
|
+
headers = {} if not headers else headers
|
|
161
|
+
if not isinstance(url, str):
|
|
162
|
+
url = url.geturl()
|
|
163
|
+
|
|
164
|
+
# convert the sequence of RequestParam objects to a dictionary of key:value pairs if necessary
|
|
165
|
+
if headers and not isinstance(headers, dict):
|
|
166
|
+
headers = {param.name: param.value for param in headers}
|
|
167
|
+
|
|
168
|
+
# send request with all parameters not declared in session and with callback for logging response
|
|
169
|
+
request = requests.Request(method, url,
|
|
170
|
+
headers=headers,
|
|
171
|
+
data=body,
|
|
172
|
+
hooks={'response': self._cb_log_response})
|
|
173
|
+
prepped_request = self.__requests_session.prepare_request(request)
|
|
174
|
+
# add timestamp to request for later reference
|
|
175
|
+
prepped_request.timestamp = datetime.now()
|
|
176
|
+
_id = str(uuid.uuid4())
|
|
177
|
+
# store random id in request so it can be matched with its response in logging
|
|
178
|
+
prepped_request.id = _id
|
|
179
|
+
self._log_request(prepped_request)
|
|
180
|
+
try:
|
|
181
|
+
timeout_ = (self.__connect_timeout, self.__socket_timeout)
|
|
182
|
+
requests_response = self.__requests_session.send(prepped_request,
|
|
183
|
+
timeout=timeout_,
|
|
184
|
+
stream=True)
|
|
185
|
+
try:
|
|
186
|
+
iterable = requests_response.iter_content(chunk_size=1024)
|
|
187
|
+
yield requests_response.status_code, requests_response.headers
|
|
188
|
+
for chunk in iterable:
|
|
189
|
+
yield chunk
|
|
190
|
+
finally:
|
|
191
|
+
requests_response.close()
|
|
192
|
+
|
|
193
|
+
except Timeout as timeout:
|
|
194
|
+
self._log_error(prepped_request.id, timeout, prepped_request.timestamp)
|
|
195
|
+
raise CommunicationException(timeout)
|
|
196
|
+
except RequestException as exception:
|
|
197
|
+
self._log_error(prepped_request.id, exception, prepped_request.timestamp)
|
|
198
|
+
raise CommunicationException(exception)
|
|
199
|
+
except Exception as exception:
|
|
200
|
+
self._log_error(prepped_request.id, exception, prepped_request.timestamp)
|
|
201
|
+
raise
|
|
202
|
+
|
|
203
|
+
def _log_request(self, request: PreparedRequest) -> None:
|
|
204
|
+
"""
|
|
205
|
+
Log parameter request if logging is enabled at the moment of logging.
|
|
206
|
+
Also adds a timestamp to the request for response logging
|
|
207
|
+
"""
|
|
208
|
+
logger = self.logger
|
|
209
|
+
if logger is None:
|
|
210
|
+
return
|
|
211
|
+
method = request.method
|
|
212
|
+
url = urlparse(request.url)
|
|
213
|
+
if url.query:
|
|
214
|
+
local_path = url.path + "?" + url.query
|
|
215
|
+
else:
|
|
216
|
+
local_path = url.path
|
|
217
|
+
try:
|
|
218
|
+
message = RequestLogMessage(request_id=request.id,
|
|
219
|
+
method=method,
|
|
220
|
+
uri=local_path,
|
|
221
|
+
body_obfuscator=self.__body_obfuscator,
|
|
222
|
+
header_obfuscator=self.__header_obfuscator)
|
|
223
|
+
for name in request.headers:
|
|
224
|
+
message.add_header(name, request.headers[name])
|
|
225
|
+
body = request.body
|
|
226
|
+
if body:
|
|
227
|
+
content = request.headers['Content-Type']
|
|
228
|
+
if content != "application/json":
|
|
229
|
+
message.set_body(body, content, CHARSET)
|
|
230
|
+
else:
|
|
231
|
+
message.set_body(body, content)
|
|
232
|
+
logger.log_request(message)
|
|
233
|
+
except Exception as exception:
|
|
234
|
+
logger.log("An error occurred trying to log request '{}'".format(request.id), exception)
|
|
235
|
+
|
|
236
|
+
def _cb_log_response(self, response: requests.models.Response, **kwargs) -> None:
|
|
237
|
+
"""Log parameter response if logging is enabled at the moment of logging"""
|
|
238
|
+
logger = self.logger
|
|
239
|
+
if logger is None:
|
|
240
|
+
return
|
|
241
|
+
request = response.request
|
|
242
|
+
_id = request.id
|
|
243
|
+
duration = math.ceil((datetime.now() - request.timestamp).total_seconds() * 1000)
|
|
244
|
+
status_code = response.status_code
|
|
245
|
+
try:
|
|
246
|
+
message = ResponseLogMessage(request_id=_id,
|
|
247
|
+
status_code=status_code,
|
|
248
|
+
duration=duration,
|
|
249
|
+
body_obfuscator=self.__body_obfuscator,
|
|
250
|
+
header_obfuscator=self.__header_obfuscator)
|
|
251
|
+
for name in response.headers:
|
|
252
|
+
message.add_header(name, response.headers[name])
|
|
253
|
+
if self.__is_binary(response.headers):
|
|
254
|
+
body = "<binary content>"
|
|
255
|
+
else:
|
|
256
|
+
# The response is always encoded UTF8
|
|
257
|
+
# When this is not specified anywhere, the response body will be encoded in the wrong way
|
|
258
|
+
response.encoding = 'utf8'
|
|
259
|
+
body = response.text
|
|
260
|
+
if body:
|
|
261
|
+
content = response.headers['Content-Type']
|
|
262
|
+
message.set_body(body, content)
|
|
263
|
+
logger.log_response(message)
|
|
264
|
+
except Exception as exception:
|
|
265
|
+
logger.log("An error occurred trying to log response '{}'".format(_id), exception)
|
|
266
|
+
|
|
267
|
+
def _log_error(self, request_id: str, error: Exception, start_time: datetime) -> None:
|
|
268
|
+
"""Log communication errors when logging is enabled"""
|
|
269
|
+
logger = self.logger
|
|
270
|
+
if logger:
|
|
271
|
+
duration = math.ceil((datetime.now() - start_time).total_seconds() * 1000)
|
|
272
|
+
logger.log("Error occurred for outgoing request (requestId='{}', {} s)".format(request_id, duration), error)
|
|
273
|
+
|
|
274
|
+
@staticmethod
|
|
275
|
+
def __is_binary(headers: Mapping[str, str]) -> bool:
|
|
276
|
+
content_type = get_header_value(headers, "Content-Type")
|
|
277
|
+
if content_type is None:
|
|
278
|
+
return False
|
|
279
|
+
content_type = content_type.lower()
|
|
280
|
+
return not (content_type.startswith("text/") or "json" in content_type or "xml" in content_type)
|
|
281
|
+
|
|
282
|
+
def set_body_obfuscator(self, body_obfuscator: BodyObfuscator) -> None:
|
|
283
|
+
self.__body_obfuscator = body_obfuscator
|
|
284
|
+
|
|
285
|
+
def set_header_obfuscator(self, header_obfuscator: HeaderObfuscator) -> None:
|
|
286
|
+
self.__header_obfuscator = header_obfuscator
|
|
287
|
+
|
|
288
|
+
def enable_logging(self, communicator_logger: CommunicatorLogger) -> None:
|
|
289
|
+
self.logger = communicator_logger
|
|
290
|
+
|
|
291
|
+
def disable_logging(self) -> None:
|
|
292
|
+
self.logger = None
|
|
293
|
+
|
|
294
|
+
def close_idle_connections(self, idle_time: timedelta) -> None:
|
|
295
|
+
"""
|
|
296
|
+
:param idle_time: a datetime.timedelta object indicating the idle time
|
|
297
|
+
"""
|
|
298
|
+
pass
|
|
299
|
+
|
|
300
|
+
def close_expired_connections(self) -> None:
|
|
301
|
+
pass
|
|
302
|
+
|
|
303
|
+
def __enter__(self):
|
|
304
|
+
return self
|
|
305
|
+
|
|
306
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
307
|
+
self.close()
|
|
308
|
+
|
|
309
|
+
def close(self) -> None:
|
|
310
|
+
"""
|
|
311
|
+
Explicitly closes the connection
|
|
312
|
+
"""
|
|
313
|
+
self.__requests_session.close()
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Sequence
|
|
3
|
+
|
|
4
|
+
from onlinepayments.sdk.communication.request_header import RequestHeader
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class IMetadataProvider(ABC):
|
|
8
|
+
"""
|
|
9
|
+
Provides meta info about the server.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
@property
|
|
13
|
+
@abstractmethod
|
|
14
|
+
def metadata_headers(self) -> Sequence[RequestHeader]:
|
|
15
|
+
"""
|
|
16
|
+
:return: The server related headers containing the metadata to be
|
|
17
|
+
associated with the request (if any). This will always contain at least
|
|
18
|
+
an automatically generated header X-GCS-ServerMetaInfo.
|
|
19
|
+
"""
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import platform
|
|
2
|
+
import re
|
|
3
|
+
from base64 import b64encode
|
|
4
|
+
from typing import Optional, Sequence
|
|
5
|
+
|
|
6
|
+
from .i_metadata_provider import IMetadataProvider
|
|
7
|
+
from .request_header import RequestHeader
|
|
8
|
+
|
|
9
|
+
from onlinepayments.sdk.domain.data_object import DataObject
|
|
10
|
+
from onlinepayments.sdk.domain.shopping_cart_extension import ShoppingCartExtension
|
|
11
|
+
from onlinepayments.sdk.json.default_marshaller import DefaultMarshaller
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class IterProperty(object):
|
|
15
|
+
def __init__(self, func):
|
|
16
|
+
self.func = func
|
|
17
|
+
|
|
18
|
+
def __get__(self, instance, owner):
|
|
19
|
+
return self.func(owner)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class MetadataProvider(IMetadataProvider):
|
|
23
|
+
"""
|
|
24
|
+
Provides meta info about the server.
|
|
25
|
+
"""
|
|
26
|
+
__sdk_version = "7.4.1"
|
|
27
|
+
__server_meta_info_header = "X-GCS-ServerMetaInfo"
|
|
28
|
+
__prohibited_headers = tuple(sorted([__server_meta_info_header, "X-GCS-Idempotence-Key", "Date", "Content-Type", "Authorization"],
|
|
29
|
+
key=str.lower))
|
|
30
|
+
__metadata_headers: Sequence[RequestHeader] = None
|
|
31
|
+
|
|
32
|
+
class ServerMetaInfo(DataObject):
|
|
33
|
+
platform_identifier = None
|
|
34
|
+
sdk_identifier = None
|
|
35
|
+
sdk_creator = None
|
|
36
|
+
integrator = None
|
|
37
|
+
shopping_cart_extension = None
|
|
38
|
+
|
|
39
|
+
def to_dictionary(self) -> dict:
|
|
40
|
+
dictionary = super(MetadataProvider.ServerMetaInfo, self).to_dictionary()
|
|
41
|
+
if self.platform_identifier is not None:
|
|
42
|
+
dictionary['platformIdentifier'] = self.platform_identifier
|
|
43
|
+
if self.sdk_identifier is not None:
|
|
44
|
+
dictionary['sdkIdentifier'] = self.sdk_identifier
|
|
45
|
+
if self.sdk_creator is not None:
|
|
46
|
+
dictionary['sdkCreator'] = self.sdk_creator
|
|
47
|
+
if self.integrator is not None:
|
|
48
|
+
dictionary['integrator'] = self.integrator
|
|
49
|
+
if self.shopping_cart_extension is not None:
|
|
50
|
+
dictionary['shoppingCartExtension'] = self.shopping_cart_extension.to_dictionary()
|
|
51
|
+
return dictionary
|
|
52
|
+
|
|
53
|
+
def from_dictionary(self, dictionary: dict) -> 'MetadataProvider.ServerMetaInfo':
|
|
54
|
+
super(MetadataProvider.ServerMetaInfo, self).from_dictionary(dictionary)
|
|
55
|
+
if 'platformIdentifier' in dictionary:
|
|
56
|
+
self.platform_identifier = dictionary['platformIdentifier']
|
|
57
|
+
if 'sdkIdentifier' in dictionary:
|
|
58
|
+
self.sdk_identifier = dictionary['sdkIdentifier']
|
|
59
|
+
if 'sdkCreator' in dictionary:
|
|
60
|
+
self.sdk_creator = dictionary['sdkCreator']
|
|
61
|
+
if 'integrator' in dictionary:
|
|
62
|
+
self.integrator = dictionary['integrator']
|
|
63
|
+
if 'shoppingCartExtension' in dictionary:
|
|
64
|
+
if not isinstance(dictionary['shoppingCartExtension'], dict):
|
|
65
|
+
raise TypeError('value \'{}\' is not a dictionary'.format(dictionary['shoppingCartExtension']))
|
|
66
|
+
self.shopping_cart_extension = ShoppingCartExtension.create_from_dictionary(dictionary['shoppingCartExtension'])
|
|
67
|
+
return self
|
|
68
|
+
|
|
69
|
+
def __init__(self, integrator: Optional[str], shopping_cart_extension: Optional[ShoppingCartExtension] = None,
|
|
70
|
+
additional_request_headers: Optional[Sequence[RequestHeader]] = ()):
|
|
71
|
+
if integrator is None or not integrator.strip():
|
|
72
|
+
raise ValueError("integrator is required")
|
|
73
|
+
|
|
74
|
+
MetadataProvider.__validate_additional_request_headers(additional_request_headers)
|
|
75
|
+
|
|
76
|
+
def subber(name_or_value):
|
|
77
|
+
return re.sub(r'\r?\n(?:(?![\r\n])\s)*', " ", name_or_value).strip()
|
|
78
|
+
additional_request_headers = [RequestHeader(subber(header.name), subber(header.value)) for header in additional_request_headers]
|
|
79
|
+
|
|
80
|
+
server_meta_info = self.ServerMetaInfo()
|
|
81
|
+
server_meta_info.platform_identifier = self._platform_identifier
|
|
82
|
+
server_meta_info.sdk_identifier = self._sdk_identifier
|
|
83
|
+
server_meta_info.sdk_creator = "OnlinePayments"
|
|
84
|
+
server_meta_info.integrator = integrator
|
|
85
|
+
server_meta_info.shopping_cart_extension = shopping_cart_extension
|
|
86
|
+
|
|
87
|
+
server_meta_info_string = DefaultMarshaller.instance().marshal(server_meta_info)
|
|
88
|
+
server_meta_info_header = RequestHeader(self.__server_meta_info_header, b64encode(server_meta_info_string.encode('utf-8')).decode('utf-8'))
|
|
89
|
+
if not additional_request_headers:
|
|
90
|
+
self.__metadata_headers = tuple([server_meta_info_header])
|
|
91
|
+
else:
|
|
92
|
+
request_headers = [server_meta_info_header]
|
|
93
|
+
request_headers.extend(additional_request_headers)
|
|
94
|
+
self.__metadata_headers = tuple(request_headers)
|
|
95
|
+
|
|
96
|
+
@staticmethod
|
|
97
|
+
def __validate_additional_request_headers(additional_request_headers: Optional[Sequence[RequestHeader]]) -> None:
|
|
98
|
+
if additional_request_headers is not None:
|
|
99
|
+
for additional_request_header in additional_request_headers:
|
|
100
|
+
MetadataProvider.__validate_additional_request_header(additional_request_header)
|
|
101
|
+
|
|
102
|
+
@staticmethod
|
|
103
|
+
def __validate_additional_request_header(additional_request_header: RequestHeader) -> None:
|
|
104
|
+
try:
|
|
105
|
+
if additional_request_header.name in MetadataProvider.__prohibited_headers:
|
|
106
|
+
raise ValueError("request header not allowed: " + str(additional_request_header))
|
|
107
|
+
except AttributeError:
|
|
108
|
+
raise AttributeError("Each request header should have an attribute 'name' and an attribute 'value'")
|
|
109
|
+
|
|
110
|
+
@IterProperty
|
|
111
|
+
def prohibited_headers(self) -> Sequence[str]:
|
|
112
|
+
return self.__prohibited_headers
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def metadata_headers(self) -> Sequence[RequestHeader]:
|
|
116
|
+
"""
|
|
117
|
+
:return: The server related headers containing the metadata to be
|
|
118
|
+
associated with the request (if any). This will always contain at least
|
|
119
|
+
an automatically generated header X-GCS-ServerMetaInfo.
|
|
120
|
+
"""
|
|
121
|
+
return self.__metadata_headers
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def _platform_identifier(self) -> str:
|
|
125
|
+
return platform.system() + " " + platform.release() + "/" + \
|
|
126
|
+
platform.version() + " Python/" + platform.python_version() + \
|
|
127
|
+
" (" + platform.python_implementation() + "; " + \
|
|
128
|
+
str(platform.python_compiler()) + ")"
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def _sdk_identifier(self) -> str:
|
|
132
|
+
return "PythonServerSDK/v" + self.__sdk_version
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
|
|
3
|
+
from typing import Mapping
|
|
4
|
+
|
|
5
|
+
from onlinepayments.sdk.domain.uploadable_file import UploadableFile
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class MultipartFormDataObject(object):
|
|
9
|
+
"""
|
|
10
|
+
A representation of a multipart/form-data object.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
def __init__(self):
|
|
14
|
+
self.__boundary = str(uuid.uuid4())
|
|
15
|
+
self.__content_type = "multipart/form-data; boundary=" + self.__boundary
|
|
16
|
+
self.__values = {}
|
|
17
|
+
self.__files = {}
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def boundary(self) -> str:
|
|
21
|
+
return self.__boundary
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def content_type(self) -> str:
|
|
25
|
+
return self.__content_type
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def values(self) -> Mapping[str, str]:
|
|
29
|
+
return self.__values
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def files(self) -> Mapping[str, UploadableFile]:
|
|
33
|
+
return self.__files
|
|
34
|
+
|
|
35
|
+
def add_value(self, parameter_name: str, value: str) -> None:
|
|
36
|
+
if parameter_name is None or not parameter_name.strip():
|
|
37
|
+
raise ValueError("parameter_name is required")
|
|
38
|
+
if value is None:
|
|
39
|
+
raise ValueError("value is required")
|
|
40
|
+
if parameter_name in self.__values or parameter_name in self.__files:
|
|
41
|
+
raise ValueError("duplicate parameterName: " + parameter_name)
|
|
42
|
+
self.__values[parameter_name] = value
|
|
43
|
+
|
|
44
|
+
def add_file(self, parameter_name: str, uploadable_file: UploadableFile) -> None:
|
|
45
|
+
if parameter_name is None or not parameter_name.strip():
|
|
46
|
+
raise ValueError("parameter_name is required")
|
|
47
|
+
if uploadable_file is None:
|
|
48
|
+
raise ValueError("uploadable_file is required")
|
|
49
|
+
if parameter_name in self.__values or parameter_name in self.__files:
|
|
50
|
+
raise ValueError("duplicate parameterName: " + parameter_name)
|
|
51
|
+
self.__files[parameter_name] = uploadable_file
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
from .multipart_form_data_object import MultipartFormDataObject
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class MultipartFormDataRequest(ABC):
|
|
7
|
+
"""
|
|
8
|
+
A representation of a multipart/form-data request.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
@abstractmethod
|
|
12
|
+
def to_multipart_form_data_object(self) -> MultipartFormDataObject:
|
|
13
|
+
"""
|
|
14
|
+
:return: :class:`onlinepayments.sdk.communication.MultipartFormDataObject`
|
|
15
|
+
"""
|
|
16
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class NotFoundException(RuntimeError):
|
|
2
|
+
"""
|
|
3
|
+
Indicates an exception that occurs when the requested resource is not found.
|
|
4
|
+
In normal usage of the SDK, this exception should not occur, however it is possible.
|
|
5
|
+
For example when path parameters are set with invalid values.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
def __init__(self, exception: Exception, message: str):
|
|
9
|
+
super(NotFoundException, self).__init__(message, exception)
|
|
10
|
+
self.cause = exception
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
from .request_param import RequestParam
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ParamRequest(ABC):
|
|
8
|
+
"""
|
|
9
|
+
Represents a set of request parameters.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
@abstractmethod
|
|
13
|
+
def to_request_parameters(self) -> List[RequestParam]:
|
|
14
|
+
"""
|
|
15
|
+
:return: list[:class:`onlinepayments.sdk.communication.RequestParam`] representing the HTTP request parameters
|
|
16
|
+
"""
|
|
17
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from datetime import timedelta
|
|
3
|
+
|
|
4
|
+
from .connection import Connection
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class PooledConnection(Connection, ABC):
|
|
8
|
+
"""
|
|
9
|
+
Represents a pooled connection to the Online Payments platform server.
|
|
10
|
+
Instead of setting up a new HTTP connection for each request, this
|
|
11
|
+
connection uses a pool of HTTP connections.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
@abstractmethod
|
|
15
|
+
def close_idle_connections(self, idle_time: timedelta) -> None:
|
|
16
|
+
"""
|
|
17
|
+
Closes all HTTP connections that have been idle for the specified time.
|
|
18
|
+
This should also include all expired HTTP connections.
|
|
19
|
+
|
|
20
|
+
:param idle_time: a datetime.timedelta object indicating the idle time
|
|
21
|
+
"""
|
|
22
|
+
raise NotImplementedError
|
|
23
|
+
|
|
24
|
+
@abstractmethod
|
|
25
|
+
def close_expired_connections(self) -> None:
|
|
26
|
+
"""
|
|
27
|
+
Closes all expired HTTP connections.
|
|
28
|
+
"""
|
|
29
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from typing import Mapping, Optional, Sequence, Union
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class RequestHeader(object):
|
|
5
|
+
"""
|
|
6
|
+
A single request header. Immutable.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
def __init__(self, name: str, value: Optional[str]):
|
|
10
|
+
if name is None or not name.strip():
|
|
11
|
+
raise ValueError("name is required")
|
|
12
|
+
self.__name = name
|
|
13
|
+
self.__value = value
|
|
14
|
+
|
|
15
|
+
@property
|
|
16
|
+
def name(self) -> str:
|
|
17
|
+
"""
|
|
18
|
+
:return: The header name.
|
|
19
|
+
"""
|
|
20
|
+
return self.__name
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def value(self) -> Optional[str]:
|
|
24
|
+
"""
|
|
25
|
+
:return: The un-encoded value.
|
|
26
|
+
"""
|
|
27
|
+
return self.__value.decode('utf-8') if isinstance(self.__value, bytes) else self.__value
|
|
28
|
+
|
|
29
|
+
def __str__(self):
|
|
30
|
+
return self.__name + ":" + str(self.__value)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def get_header_value(headers: Union[Sequence[RequestHeader], Mapping[str, str], None], header_name: str) -> Optional[str]:
|
|
34
|
+
"""
|
|
35
|
+
:return: The value of the header with the given name, or None if there was no such header.
|
|
36
|
+
"""
|
|
37
|
+
if isinstance(headers, dict):
|
|
38
|
+
for name, value in headers.items():
|
|
39
|
+
if name.lower() == header_name.lower():
|
|
40
|
+
return value
|
|
41
|
+
elif headers is not None:
|
|
42
|
+
for header in headers:
|
|
43
|
+
if header.name.lower() == header_name.lower():
|
|
44
|
+
return header.value
|
|
45
|
+
return None
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def get_header(headers: Union[Sequence[RequestHeader], Mapping[str, str], None], header_name: str) -> Optional[RequestHeader]:
|
|
49
|
+
"""
|
|
50
|
+
:return: The header with the given name, or None if there was no such header.
|
|
51
|
+
"""
|
|
52
|
+
if isinstance(headers, dict):
|
|
53
|
+
for name, value in headers.items():
|
|
54
|
+
if name.lower() == header_name.lower():
|
|
55
|
+
return RequestHeader(name, value)
|
|
56
|
+
elif headers is not None:
|
|
57
|
+
for header in headers:
|
|
58
|
+
if header.name.lower() == header_name.lower():
|
|
59
|
+
return header
|
|
60
|
+
return None
|