acquiring-sdk-ruby 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +2 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +140 -0
  5. data/Rakefile +34 -0
  6. data/acquiring-sdk-ruby.gemspec +30 -0
  7. data/lib/worldline/acquiring/sdk/api_resource.rb +53 -0
  8. data/lib/worldline/acquiring/sdk/authentication/authenticator.rb +21 -0
  9. data/lib/worldline/acquiring/sdk/authentication/authorization_type.rb +17 -0
  10. data/lib/worldline/acquiring/sdk/authentication/oauth2_authenticator.rb +142 -0
  11. data/lib/worldline/acquiring/sdk/authentication/oauth2_exception.rb +15 -0
  12. data/lib/worldline/acquiring/sdk/authentication.rb +1 -0
  13. data/lib/worldline/acquiring/sdk/call_context.rb +9 -0
  14. data/lib/worldline/acquiring/sdk/client.rb +69 -0
  15. data/lib/worldline/acquiring/sdk/communication/communication_exception.rb +21 -0
  16. data/lib/worldline/acquiring/sdk/communication/connection.rb +50 -0
  17. data/lib/worldline/acquiring/sdk/communication/default_connection.rb +429 -0
  18. data/lib/worldline/acquiring/sdk/communication/metadata_provider.rb +162 -0
  19. data/lib/worldline/acquiring/sdk/communication/multipart_form_data_object.rb +54 -0
  20. data/lib/worldline/acquiring/sdk/communication/multipart_form_data_request.rb +15 -0
  21. data/lib/worldline/acquiring/sdk/communication/not_found_exception.rb +21 -0
  22. data/lib/worldline/acquiring/sdk/communication/param_request.rb +16 -0
  23. data/lib/worldline/acquiring/sdk/communication/pooled_connection.rb +28 -0
  24. data/lib/worldline/acquiring/sdk/communication/request_header.rb +64 -0
  25. data/lib/worldline/acquiring/sdk/communication/request_param.rb +30 -0
  26. data/lib/worldline/acquiring/sdk/communication/response_exception.rb +58 -0
  27. data/lib/worldline/acquiring/sdk/communication/response_header.rb +80 -0
  28. data/lib/worldline/acquiring/sdk/communication.rb +1 -0
  29. data/lib/worldline/acquiring/sdk/communicator.rb +506 -0
  30. data/lib/worldline/acquiring/sdk/communicator_configuration.rb +197 -0
  31. data/lib/worldline/acquiring/sdk/domain/data_object.rb +34 -0
  32. data/lib/worldline/acquiring/sdk/domain/shopping_cart_extension.rb +62 -0
  33. data/lib/worldline/acquiring/sdk/domain/uploadable_file.rb +35 -0
  34. data/lib/worldline/acquiring/sdk/domain.rb +1 -0
  35. data/lib/worldline/acquiring/sdk/factory.rb +183 -0
  36. data/lib/worldline/acquiring/sdk/json/default_marshaller.rb +36 -0
  37. data/lib/worldline/acquiring/sdk/json/marshaller.rb +29 -0
  38. data/lib/worldline/acquiring/sdk/json/marshaller_syntax_exception.rb +11 -0
  39. data/lib/worldline/acquiring/sdk/json.rb +1 -0
  40. data/lib/worldline/acquiring/sdk/logging/communicator_logger.rb +26 -0
  41. data/lib/worldline/acquiring/sdk/logging/log_message_builder.rb +91 -0
  42. data/lib/worldline/acquiring/sdk/logging/logging_capable.rb +19 -0
  43. data/lib/worldline/acquiring/sdk/logging/obfuscation/body_obfuscator.rb +101 -0
  44. data/lib/worldline/acquiring/sdk/logging/obfuscation/header_obfuscator.rb +54 -0
  45. data/lib/worldline/acquiring/sdk/logging/obfuscation/obfuscation_capable.rb +23 -0
  46. data/lib/worldline/acquiring/sdk/logging/obfuscation/obfuscation_rule.rb +49 -0
  47. data/lib/worldline/acquiring/sdk/logging/obfuscation.rb +1 -0
  48. data/lib/worldline/acquiring/sdk/logging/request_log_message_builder.rb +52 -0
  49. data/lib/worldline/acquiring/sdk/logging/response_log_message_builder.rb +43 -0
  50. data/lib/worldline/acquiring/sdk/logging/ruby_communicator_logger.rb +63 -0
  51. data/lib/worldline/acquiring/sdk/logging/stdout_communicator_logger.rb +33 -0
  52. data/lib/worldline/acquiring/sdk/logging.rb +1 -0
  53. data/lib/worldline/acquiring/sdk/proxy_configuration.rb +76 -0
  54. data/lib/worldline/acquiring/sdk/v1/acquirer/acquirer_client.rb +35 -0
  55. data/lib/worldline/acquiring/sdk/v1/acquirer/merchant/accountverifications/account_verifications_client.rb +60 -0
  56. data/lib/worldline/acquiring/sdk/v1/acquirer/merchant/accountverifications.rb +4 -0
  57. data/lib/worldline/acquiring/sdk/v1/acquirer/merchant/dynamiccurrencyconversion/dynamic_currency_conversion_client.rb +60 -0
  58. data/lib/worldline/acquiring/sdk/v1/acquirer/merchant/dynamiccurrencyconversion.rb +4 -0
  59. data/lib/worldline/acquiring/sdk/v1/acquirer/merchant/merchant_client.rb +66 -0
  60. data/lib/worldline/acquiring/sdk/v1/acquirer/merchant/payments/get_payment_status_params.rb +34 -0
  61. data/lib/worldline/acquiring/sdk/v1/acquirer/merchant/payments/payments_client.rb +224 -0
  62. data/lib/worldline/acquiring/sdk/v1/acquirer/merchant/payments.rb +4 -0
  63. data/lib/worldline/acquiring/sdk/v1/acquirer/merchant/refunds/get_refund_params.rb +34 -0
  64. data/lib/worldline/acquiring/sdk/v1/acquirer/merchant/refunds/refunds_client.rb +157 -0
  65. data/lib/worldline/acquiring/sdk/v1/acquirer/merchant/refunds.rb +4 -0
  66. data/lib/worldline/acquiring/sdk/v1/acquirer/merchant/technicalreversals/technical_reversals_client.rb +64 -0
  67. data/lib/worldline/acquiring/sdk/v1/acquirer/merchant/technicalreversals.rb +4 -0
  68. data/lib/worldline/acquiring/sdk/v1/acquirer/merchant.rb +4 -0
  69. data/lib/worldline/acquiring/sdk/v1/acquirer.rb +4 -0
  70. data/lib/worldline/acquiring/sdk/v1/api_exception.rb +63 -0
  71. data/lib/worldline/acquiring/sdk/v1/authorization_exception.rb +23 -0
  72. data/lib/worldline/acquiring/sdk/v1/domain/address_verification_data.rb +41 -0
  73. data/lib/worldline/acquiring/sdk/v1/domain/amount_data.rb +48 -0
  74. data/lib/worldline/acquiring/sdk/v1/domain/api_account_verification_request.rb +70 -0
  75. data/lib/worldline/acquiring/sdk/v1/domain/api_account_verification_response.rb +87 -0
  76. data/lib/worldline/acquiring/sdk/v1/domain/api_action_response.rb +71 -0
  77. data/lib/worldline/acquiring/sdk/v1/domain/api_action_response_for_refund.rb +71 -0
  78. data/lib/worldline/acquiring/sdk/v1/domain/api_capture_request.rb +75 -0
  79. data/lib/worldline/acquiring/sdk/v1/domain/api_capture_request_for_refund.rb +43 -0
  80. data/lib/worldline/acquiring/sdk/v1/domain/api_increment_request.rb +61 -0
  81. data/lib/worldline/acquiring/sdk/v1/domain/api_increment_response.rb +43 -0
  82. data/lib/worldline/acquiring/sdk/v1/domain/api_payment_error_response.rb +62 -0
  83. data/lib/worldline/acquiring/sdk/v1/domain/api_payment_refund_request.rb +77 -0
  84. data/lib/worldline/acquiring/sdk/v1/domain/api_payment_request.rb +95 -0
  85. data/lib/worldline/acquiring/sdk/v1/domain/api_payment_resource.rb +103 -0
  86. data/lib/worldline/acquiring/sdk/v1/domain/api_payment_response.rb +126 -0
  87. data/lib/worldline/acquiring/sdk/v1/domain/api_payment_reversal_request.rb +61 -0
  88. data/lib/worldline/acquiring/sdk/v1/domain/api_payment_summary_for_response.rb +66 -0
  89. data/lib/worldline/acquiring/sdk/v1/domain/api_references_for_responses.rb +48 -0
  90. data/lib/worldline/acquiring/sdk/v1/domain/api_refund_request.rb +88 -0
  91. data/lib/worldline/acquiring/sdk/v1/domain/api_refund_resource.rb +110 -0
  92. data/lib/worldline/acquiring/sdk/v1/domain/api_refund_response.rb +133 -0
  93. data/lib/worldline/acquiring/sdk/v1/domain/api_refund_summary_for_response.rb +66 -0
  94. data/lib/worldline/acquiring/sdk/v1/domain/api_reversal_response.rb +36 -0
  95. data/lib/worldline/acquiring/sdk/v1/domain/api_technical_reversal_request.rb +50 -0
  96. data/lib/worldline/acquiring/sdk/v1/domain/api_technical_reversal_response.rb +62 -0
  97. data/lib/worldline/acquiring/sdk/v1/domain/card_data_for_dcc.rb +48 -0
  98. data/lib/worldline/acquiring/sdk/v1/domain/card_on_file_data.rb +52 -0
  99. data/lib/worldline/acquiring/sdk/v1/domain/card_payment_data.rb +114 -0
  100. data/lib/worldline/acquiring/sdk/v1/domain/card_payment_data_for_refund.rb +82 -0
  101. data/lib/worldline/acquiring/sdk/v1/domain/card_payment_data_for_resource.rb +43 -0
  102. data/lib/worldline/acquiring/sdk/v1/domain/card_payment_data_for_response.rb +52 -0
  103. data/lib/worldline/acquiring/sdk/v1/domain/card_payment_data_for_verification.rb +91 -0
  104. data/lib/worldline/acquiring/sdk/v1/domain/dcc_data.rb +55 -0
  105. data/lib/worldline/acquiring/sdk/v1/domain/dcc_proposal.rb +60 -0
  106. data/lib/worldline/acquiring/sdk/v1/domain/e_commerce_data.rb +52 -0
  107. data/lib/worldline/acquiring/sdk/v1/domain/e_commerce_data_for_account_verification.rb +45 -0
  108. data/lib/worldline/acquiring/sdk/v1/domain/e_commerce_data_for_response.rb +41 -0
  109. data/lib/worldline/acquiring/sdk/v1/domain/get_dcc_rate_request.rb +75 -0
  110. data/lib/worldline/acquiring/sdk/v1/domain/get_dcc_rate_response.rb +57 -0
  111. data/lib/worldline/acquiring/sdk/v1/domain/initial_card_on_file_data.rb +41 -0
  112. data/lib/worldline/acquiring/sdk/v1/domain/merchant_data.rb +76 -0
  113. data/lib/worldline/acquiring/sdk/v1/domain/network_token_data.rb +41 -0
  114. data/lib/worldline/acquiring/sdk/v1/domain/payment_references.rb +48 -0
  115. data/lib/worldline/acquiring/sdk/v1/domain/plain_card_data.rb +48 -0
  116. data/lib/worldline/acquiring/sdk/v1/domain/point_of_sale_data.rb +34 -0
  117. data/lib/worldline/acquiring/sdk/v1/domain/point_of_sale_data_for_dcc.rb +41 -0
  118. data/lib/worldline/acquiring/sdk/v1/domain/rate_data.rb +64 -0
  119. data/lib/worldline/acquiring/sdk/v1/domain/sub_operation.rb +94 -0
  120. data/lib/worldline/acquiring/sdk/v1/domain/sub_operation_for_refund.rb +87 -0
  121. data/lib/worldline/acquiring/sdk/v1/domain/subsequent_card_on_file_data.rb +48 -0
  122. data/lib/worldline/acquiring/sdk/v1/domain/three_d_secure.rb +62 -0
  123. data/lib/worldline/acquiring/sdk/v1/domain/transaction_data_for_dcc.rb +52 -0
  124. data/lib/worldline/acquiring/sdk/v1/domain.rb +4 -0
  125. data/lib/worldline/acquiring/sdk/v1/exception_factory.rb +48 -0
  126. data/lib/worldline/acquiring/sdk/v1/ping/ping_client.rb +52 -0
  127. data/lib/worldline/acquiring/sdk/v1/ping.rb +4 -0
  128. data/lib/worldline/acquiring/sdk/v1/platform_exception.rb +23 -0
  129. data/lib/worldline/acquiring/sdk/v1/reference_exception.rb +23 -0
  130. data/lib/worldline/acquiring/sdk/v1/v1_client.rb +43 -0
  131. data/lib/worldline/acquiring/sdk/v1/validation_exception.rb +23 -0
  132. data/lib/worldline/acquiring/sdk/v1.rb +4 -0
  133. data/lib/worldline/acquiring/sdk.rb +1 -0
  134. data/spec/comparable_extension.rb +29 -0
  135. data/spec/fixtures/resources/authentication/oauth2AccessToken.expired.json +4 -0
  136. data/spec/fixtures/resources/authentication/oauth2AccessToken.invalidClient.json +4 -0
  137. data/spec/fixtures/resources/authentication/oauth2AccessToken.json +4 -0
  138. data/spec/fixtures/resources/communication/getWithQueryParams.json +3 -0
  139. data/spec/fixtures/resources/communication/getWithoutQueryParams.json +3 -0
  140. data/spec/fixtures/resources/communication/notFound.html +1 -0
  141. data/spec/fixtures/resources/communication/postWithBadRequestResponse.json +11 -0
  142. data/spec/fixtures/resources/communication/postWithCreatedResponse.json +6 -0
  143. data/spec/fixtures/resources/communication/unknownServerError.json +10 -0
  144. data/spec/fixtures/resources/logging/bodyNoObfuscation.json +7 -0
  145. data/spec/fixtures/resources/logging/bodyWithBinObfuscated.json +3 -0
  146. data/spec/fixtures/resources/logging/bodyWithBinOriginal.json +3 -0
  147. data/spec/fixtures/resources/logging/bodyWithCardCustomObfuscated.json +13 -0
  148. data/spec/fixtures/resources/logging/bodyWithCardObfuscated.json +13 -0
  149. data/spec/fixtures/resources/logging/bodyWithCardOriginal.json +13 -0
  150. data/spec/fixtures/resources/logging/bodyWithObjectObfuscated.json +5 -0
  151. data/spec/fixtures/resources/logging/bodyWithObjectOriginal.json +5 -0
  152. data/spec/fixtures/resources/properties.oauth2.yml +8 -0
  153. data/spec/fixtures/resources/properties.proxy.yml +14 -0
  154. data/spec/integration/connection_pooling_spec.rb +74 -0
  155. data/spec/integration/multipart_form_data_spec.rb +216 -0
  156. data/spec/integration/process_payment_spec.rb +43 -0
  157. data/spec/integration/request_dcc_rate_spec.rb +24 -0
  158. data/spec/integration/sdk_proxy_spec.rb +70 -0
  159. data/spec/integration_setup.rb +111 -0
  160. data/spec/lib/authentication/oauth2_authenticator_spec.rb +68 -0
  161. data/spec/lib/client_spec.rb +47 -0
  162. data/spec/lib/communication/default_connection_logger_spec.rb +484 -0
  163. data/spec/lib/communication/default_connection_spec.rb +352 -0
  164. data/spec/lib/communication/metadata_provider_spec.rb +93 -0
  165. data/spec/lib/communicator_configuration_spec.rb +181 -0
  166. data/spec/lib/communicator_spec.rb +34 -0
  167. data/spec/lib/factory_spec.rb +38 -0
  168. data/spec/lib/json/default_marshaller_spec.rb +39 -0
  169. data/spec/lib/logging/obfuscation/body_obfuscator_spec.rb +86 -0
  170. data/spec/lib/logging/obfuscation/header_obfuscator_spec.rb +100 -0
  171. data/spec/lib/logging/ruby_communicator_logger_spec.rb +92 -0
  172. data/spec/lib/logging/stdout_communicator_logger_spec.rb +64 -0
  173. data/spec/spec_helper.rb +32 -0
  174. metadata +375 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fbe14771bc49443b36f8ef127ab56e7c24db6b0f303a829032efa785891e52fb
4
+ data.tar.gz: cf3df20c97cb1d9add95fe64ded24ce955248ef32d69049a2fa98812d3a7199a
5
+ SHA512:
6
+ metadata.gz: 3efbf4847c46be0f3ac265628581d1e880b2950b7b6793f3b6ae9100e4b830479be35f47674bda088447d55634e7dcbaf70a79d9524eb9f2736ff3297dbd8941
7
+ data.tar.gz: a94f4720710ebeb5e54db83f57c92e58096ccc72a3af197298a0558253096c0590b74e6f30569c8aa9e165cd2ec56e7d81678ed93725f2f4bc891734482fd2e8
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2024 Worldline Financial Services (Europe) SA
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # Worldline Acquiring Ruby SDK
2
+
3
+ ## Introduction
4
+
5
+ The Ruby SDK helps you to communicate with the Worldline Acquiring API. Its primary features are:
6
+
7
+ * convenient Ruby library for the API calls and responses
8
+ * marshalls Ruby request objects to HTTP requests
9
+ * unmarshalls HTTP responses to Ruby response objects or Ruby exceptions
10
+ * handling of all the details concerning authentication
11
+ * handling of required metadata
12
+
13
+ See the [Worldline Acquiring Documentation](https://docs.acquiring.worldline-solutions.com/Developer-Tools/sdk/ruby) for more information on how to use the SDK.
14
+
15
+ ## Structure of this repository
16
+
17
+ This repository consists out of four main components:
18
+
19
+ 1. The source code of the SDK itself: `/lib/worldline/acquiring/sdk/`
20
+ 2. The source code of the SDK unit tests: `/spec/lib/`
21
+ 3. The source code of the SDK integration tests: `/spec/integration/`
22
+
23
+ Note that the source code of the unit tests and integration tests can only be found on GitHub.
24
+
25
+ ## Requirements
26
+
27
+ Ruby 2.3 or higher is required.
28
+ As for JRuby, version 9.0.0.0 and higher are supported.
29
+ In addition, the following packages are required:
30
+
31
+ * [httpclient](https://github.com/nahi/httpclient) 2.8 or higher
32
+ * [concurrent-ruby](https://github.com/ruby-concurrency/concurrent-ruby) 1.0 or higher
33
+
34
+ ## Installation
35
+
36
+ ### Using RubyGems
37
+
38
+ To install the SDK using `gem`, execute the following command:
39
+
40
+ gem install acquiring-sdk-ruby
41
+
42
+ ### Using a pre-built gem
43
+
44
+ 1. Download the latest version of the Ruby SDK from GitHub. Choose the `acquiring-sdk-ruby-x.y.z.gem` file from the [releases](https://github.com/Worldline-Acquiring/acquiring-sdk-ruby/releases) page, where `x.y.z` is the version number.
45
+ 2. Navigate into the folder where the gem file is downloaded to, and execute the following command:
46
+
47
+ ```
48
+ gem install acquiring-sdk-ruby-x.y.z.gem
49
+ ```
50
+ 3. Feel free to delete the gem file at this point, it is no longer required.
51
+
52
+ ### From source
53
+
54
+ 1. Download the latest version of the Ruby SDK from GitHub. Choose the `acquiring-sdk-ruby-x.y.z.zip` file from the [releases](https://github.com/Worldline-Acquiring/acquiring-sdk-ruby/releases) page, where `x.y.z` is the version number.
55
+ 2. Unzip the file, navigate into the folder where the file is unzipped to, and execute the following commands:
56
+
57
+ ```
58
+ gem build acquiring-sdk-ruby.gemspec
59
+ gem install acquiring-sdk-ruby-x.y.z.gem
60
+ ```
61
+ 3. Feel free to delete the unzipped archive, the zip file and the gem file at this point, they are no longer required.
62
+
63
+ ## Uninstalling
64
+
65
+ After the Ruby SDK has been installed, it can be uninstalled using the
66
+ following command:
67
+
68
+ gem uninstall acquiring-sdk-ruby
69
+
70
+ The required packages can be uninstalled in the same way.
71
+
72
+ ## Usage
73
+
74
+ After the Ruby SDK has been installed, it can be required in Ruby program as follows:
75
+
76
+ require 'worldline/acquiring/sdk'
77
+
78
+ ## Running tests
79
+
80
+ There are two types of tests: unit tests and integration tests. The unit tests will work out-of-the-box; for the integration tests some configuration is required.
81
+ First, some environment variables need to be set:
82
+
83
+ * `acquiring_api_oauth2_clientId` for the OAuth2 client id to use.
84
+ * `acquiring_api_oauth2_clientsecret` for the OAuth2 client secret to use.
85
+ * `acquiring_api_merchantId` for your merchant ID.
86
+
87
+ In addition, to run the proxy integration tests, the proxy URI, username and password should be set in the `spec/fixtures/resources/properties.proxy.yml` file.
88
+
89
+ In order to run the unit and integration tests, some additional dependencies are required:
90
+
91
+ * [rake](https://ruby.github.io/rake/) 12.3.3 or higher
92
+ * [rspec](https://github.com/rspec/rspec) 3.5 or higher
93
+ * [webmock](https://github.com/bblimke/webmock) 2.1 or higher
94
+ * [sinatra](https://github.com/sinatra/sinatra) 2.1 or higher
95
+ * [webrick](https://github.com/ruby/webrick) 1.7 or higher
96
+
97
+ They can be installed using the following command:
98
+
99
+ gem install rake rspec webmock sinatra
100
+
101
+ *Note: if rake is already installed as part of the Ruby installation, this will cause a conflict error. This can safely be ignored.*
102
+
103
+ The following commands can now be executed from the root directory of the SDK folder (/) to execute the tests:
104
+
105
+ * Unit tests:
106
+
107
+ ```
108
+ rake unit
109
+ ```
110
+
111
+ * Integration tests:
112
+
113
+ ```
114
+ rake integration
115
+ ```
116
+
117
+ * Both unit and integration tests:
118
+
119
+ ```
120
+ rake spec
121
+ ```
122
+
123
+ ## Generating documentation
124
+
125
+ Documentation can be generated with YARD. YARD can be installed as a gem. The gems required to generate documentation are:
126
+
127
+ * [rake](https://ruby.github.io/rake/) 12.3.3 or higher
128
+ * [yard](https://github.com/lsegal/yard) 0.9.5 or higher
129
+
130
+ They can be installed using the following command:
131
+
132
+ gem install rake yard
133
+
134
+ *Note: if rake is already installed as part of the Ruby installation, this will cause a conflict error. This can safely be ignored.*
135
+
136
+ Once YARD and rake are installed, documentation can be generated with the following command (ran from the root folder):
137
+
138
+ rake yard
139
+
140
+ Documentation will be generated in the `/doc` folder. The file `/doc/index.html` is the main documentation file.
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |t| # supports automated testing using the command *rake* *spec*
5
+ t.rspec_opts = '--color --format documentation'
6
+ end
7
+
8
+ RSpec::Core::RakeTask.new(:unit) do |t| # supports automated testing using unit tests using the command *rake* *unit*
9
+ t.rspec_opts = '--color --format documentation'
10
+ t.exclude_pattern = 'spec/integration/**'
11
+ end
12
+
13
+ RSpec::Core::RakeTask.new(:integration) do |t| # supports automated testing of integration using the command *rake* *integration*
14
+ t.rspec_opts = '--color --format documentation'
15
+ t.pattern = 'spec/integration/**_spec.rb'
16
+ end
17
+
18
+ task :default => :spec
19
+ rescue LoadError
20
+ puts '[*] error -- development dependency is not installed'
21
+ end
22
+
23
+ begin
24
+ require 'yard'
25
+
26
+ YARD::Rake::YardocTask.new(:yard) do |t| # supports generating documentation using the command *rake* *yard*
27
+ # t.files = ['lib/**/*.rb', OTHER_PATHS] # optional
28
+ t.options = ['--no-private']
29
+ end
30
+
31
+ task :doc => :yard # alternative alias to generate documentation
32
+ rescue LoadError
33
+ puts '[*] error -- development dependency is not installed'
34
+ end
@@ -0,0 +1,30 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = 'acquiring-sdk-ruby'
3
+ spec.version = '0.1.0'
4
+ spec.authors = ['Worldline Acquiring']
5
+ spec.email = ['github.acquiring@worldline.com']
6
+ spec.summary = %q{SDK to communicate with the Worldline Acquiring platform using the Worldline Acquiring API}
7
+ spec.description = %q{SDK to communicate with the Worldline Acquiring platform using the Worldline Acquiring API}
8
+ spec.homepage = %q{https://github.com/Worldline-Acquiring/acquiring-sdk-ruby}
9
+ spec.license = 'MIT'
10
+
11
+ # exclude hidden files like .gitignore
12
+ spec.files = Dir['lib/**/*'] + Dir['spec/**/*'] +
13
+ ['acquiring-sdk-ruby.gemspec', 'Gemfile', 'LICENSE.txt', 'Rakefile', 'README.md']
14
+ spec.executables = spec.files.grep(%r{^bin\/}) { |f| File.basename(f) }
15
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)\/})
16
+ spec.require_paths = ['lib']
17
+
18
+ spec.required_ruby_version = '>= 2.0'
19
+
20
+ spec.add_dependency 'httpclient', '~> 2.8'
21
+ spec.add_dependency 'concurrent-ruby', '~>1.0'
22
+
23
+ spec.add_development_dependency 'yard', '~> 0.9'
24
+ spec.add_development_dependency 'rspec', '~> 3.5'
25
+ spec.add_development_dependency 'webmock', '~> 2.1'
26
+ spec.add_development_dependency 'sinatra', '~> 2.1'
27
+ spec.add_development_dependency 'webrick', '~> 1.7'
28
+ spec.add_development_dependency 'rake', '~> 12.3', '>= 12.3.3'
29
+ # spec.metadata['yard.run'] = 'yri' # compiles yard doc on install
30
+ end
@@ -0,0 +1,53 @@
1
+ module Worldline
2
+ module Acquiring
3
+ module SDK
4
+ # Base class of all Worldline Acquiring platform API resources.
5
+ # Provides shared functionality to facilitate communication with the Worldline Acquiring platform.
6
+ #
7
+ # @attr_reader [Worldline::Acquiring::SDK::Communicator] communicator Communicator instance that provides communication with the Worldline Acquiring platform.
8
+ class ApiResource
9
+
10
+ # Creates a new ApiResource.
11
+ #
12
+ # @param parent [Worldline::Acquiring::SDK::ApiResource] parent resource instance.
13
+ # @param communicator [Worldline::Acquiring::SDK::Communicator] Communicator instance.
14
+ # @param path_context [Hash] hash that contains substitutions for generic locations in the URL path.
15
+ # This hash will be used to instantiate a concrete URL used to access specific resources.
16
+ def initialize(parent: nil, communicator: nil, path_context: nil)
17
+ raise ArgumentError.new('parent and/or communicator is required') if parent.nil? and communicator.nil?
18
+ @parent = parent
19
+ @communicator = communicator.nil? ? parent.communicator : communicator
20
+ @path_context = path_context
21
+ end
22
+
23
+ attr_reader :communicator
24
+
25
+ protected
26
+
27
+ def instantiate_uri(uri, path_context = nil)
28
+ if path_context
29
+ uri = replace_all(uri, path_context)
30
+ instantiate_uri(uri)
31
+ else
32
+ uri = replace_all(uri, @path_context)
33
+ unless @parent.nil?
34
+ uri = @parent.instantiate_uri(uri)
35
+ end
36
+ uri
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def replace_all(uri, path_context)
43
+ if path_context
44
+ path_context.each do |key, value|
45
+ uri = uri.gsub('{' + key + '}', value)
46
+ end
47
+ end
48
+ uri
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,21 @@
1
+ module Worldline
2
+ module Acquiring
3
+ module SDK
4
+ module Authentication
5
+ # Abstract class that is responsible for authenticating requests sent to the Worldline Acquiring platform.
6
+ class Authenticator
7
+
8
+ # Returns a value that can be used for the "Authorization" header.
9
+ #
10
+ # @param http_method [String] 'GET', 'PUT', 'POST' or 'DELETE' indicating which HTTP method will be used with the request
11
+ # @param resource_uri [URI::HTTP] URI object that includes #path and #query of the URL that will be used, #query may be *nil*
12
+ # @param request_headers [Array<Worldline::Acquiring::SDK::Communication::RequestHeader>] all headers used by the request
13
+ # @return [String] the "Authorization" header value
14
+ def get_authorization(http_method, resource_uri, request_headers)
15
+ raise NotImplementedError
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ module Worldline
2
+ module Acquiring
3
+ module SDK
4
+ module Authentication
5
+ # Contains all authentication schemes supported by the Worldline Acquiring platform.
6
+ class AuthorizationType
7
+ OAUTH2 = "OAuth2".freeze
8
+
9
+ # @return [String] the authorization string that belongs to the parameter _authorization_, or _nil_ if not found.
10
+ def self.get_authorization(authorization)
11
+ authorization if authorization == 'OAuth2'
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,142 @@
1
+ require 'concurrent'
2
+ require 'worldline/acquiring/sdk/authentication/authenticator'
3
+ require 'worldline/acquiring/sdk/authentication/oauth2_exception'
4
+ require 'worldline/acquiring/sdk/communication/default_connection'
5
+ require 'worldline/acquiring/sdk/communication/request_header'
6
+
7
+ module Worldline
8
+ module Acquiring
9
+ module SDK
10
+ module Authentication
11
+ # Authenticates requests made to the Worldline Acquiring platform using OAuth2.
12
+ class OAuth2Authenticator < Authenticator
13
+
14
+ private
15
+
16
+ class TokenType
17
+
18
+ def initialize(path, scopes)
19
+ @path = path
20
+ @scopes = scopes.join(' ')
21
+ end
22
+
23
+ attr_reader :path
24
+ attr_reader :scopes
25
+ end
26
+
27
+ class AccessToken
28
+
29
+ def initialize(token, expiration)
30
+ @token = token
31
+ @expiration = expiration
32
+ end
33
+
34
+ attr_reader :token
35
+ attr_reader :expiration
36
+ end
37
+
38
+ # Only a limited amount of scopes may be sent in one request.
39
+ # While at the moment all scopes fit in one request, keep this code so we can easily add more token types if necessary.
40
+ # The empty path will ensure that all paths will match, as each full path ends with an empty string.
41
+ TOKEN_TYPES = [
42
+ TokenType.new('', [
43
+ 'processing_payment', 'processing_refund', 'processing_credittransfer', 'processing_accountverification',
44
+ 'processing_operation_reverse', 'processing_dcc_rate', 'services_ping'
45
+ ]),
46
+ ]
47
+
48
+ public
49
+
50
+ # Constructs a new OAuth2Authenticator instance using the provided CommunicatorConfiguration.
51
+ #
52
+ # @param communicator_configuration [Worldline::Acquiring::SDK::CommunicatorConfiguration] The configuration object
53
+ # containing the OAuth2 client id, client secret and token URI,
54
+ # connection timeout, and socket timeout. None of these can be _nil_ or empty,
55
+ # and the timeout values must be positive.
56
+ def initialize(communicator_configuration)
57
+ raise ArgumentError unless communicator_configuration.oauth2_client_id and not communicator_configuration.oauth2_client_id.strip.empty?
58
+ raise ArgumentError unless communicator_configuration.oauth2_client_secret and not communicator_configuration.oauth2_client_secret.strip.empty?
59
+ raise ArgumentError unless communicator_configuration.oauth2_token_uri and not communicator_configuration.oauth2_token_uri.strip.empty?
60
+ raise ArgumentError unless communicator_configuration.connect_timeout > 0
61
+ raise ArgumentError unless communicator_configuration.socket_timeout > 0
62
+
63
+ @access_tokens = Concurrent::Map.new
64
+ @client_id = communicator_configuration.oauth2_client_id
65
+ @client_secret = communicator_configuration.oauth2_client_secret
66
+ @token_uri = communicator_configuration.oauth2_token_uri
67
+ @connect_timeout = communicator_configuration.connect_timeout
68
+ @socket_timeout = communicator_configuration.socket_timeout
69
+ @proxy_configuration = communicator_configuration.proxy_configuration
70
+ end
71
+
72
+ # @param http_method [String, nil] 'GET', 'PUT', 'POST' or 'DELETE' indicating which HTTP method will be used with the request
73
+ # @param resource_uri [URI::HTTP, nil] URI object that includes #path and #query of the URL that will be used, #query may be *nil*
74
+ # @param request_headers [Array<Worldline::Acquiring::SDK::Communication::RequestHeader>, nil] all headers used by the request
75
+ def get_authorization(http_method, resource_uri, request_headers)
76
+ token_type = get_token_type(resource_uri&.path)
77
+ access_token = @access_tokens.compute(token_type.path) { |existing_token| get_valid_access_token(existing_token, token_type) }
78
+ "Bearer #{access_token.token}"
79
+ end
80
+
81
+ private
82
+
83
+ def get_token_type(full_path)
84
+ TOKEN_TYPES.each do |token_type|
85
+ if full_path&.end_with? token_type.path || full_path&.include?("#{token_type.path}/")
86
+ return token_type
87
+ end
88
+ end
89
+ raise ArgumentError.new("scope could not be found for path '#{full_path}'")
90
+ end
91
+
92
+ def get_valid_access_token(existing_token, token_type)
93
+ if is_token_invalid(existing_token)
94
+ return get_access_token(token_type)
95
+ end
96
+ existing_token
97
+ end
98
+
99
+ def is_token_invalid(access_token)
100
+ not access_token or access_token.expiration < Time.now
101
+ end
102
+
103
+ def get_access_token(token_type)
104
+ request_headers = [RequestHeader.new('Content-Type', 'application/x-www-form-urlencoded')]
105
+ request_body = "grant_type=client_credentials&client_id=#{@client_id}&client_secret=#{@client_secret}&scope=#{token_type.scopes}"
106
+
107
+ start_time = Time.now
108
+
109
+ new_connection do |connection|
110
+ response_status_code, access_token_response = nil
111
+ connection.post(@token_uri, request_headers, request_body) do |status_code, _, content|
112
+ response_status_code = status_code
113
+ response_body = content.read.force_encoding('UTF-8')
114
+ access_token_response = ::JSON.load(response_body)
115
+ end
116
+
117
+ if response_status_code != 200
118
+ error = access_token_response['error']
119
+ error_description = access_token_response['error_description']
120
+ raise OAuth2Exception.new("There was an error while retrieving the OAuth2 access token: #{error} - #{error_description}")
121
+ end
122
+
123
+ token = access_token_response['access_token']
124
+ expiration = start_time + access_token_response['expires_in']
125
+ AccessToken.new(token, expiration)
126
+ end
127
+ end
128
+
129
+ def new_connection
130
+ connection = Worldline::Acquiring::SDK::Communication::DefaultConnection.new({ connect_timeout: @connect_timeout,
131
+ socket_timeout: @socket_timeout,
132
+ max_connections: 1,
133
+ proxy_configuration: @proxy_configuration })
134
+ yield connection
135
+ ensure
136
+ connection.close
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,15 @@
1
+ module Worldline
2
+ module Acquiring
3
+ module SDK
4
+ module Authentication
5
+ # Raised when an exception regarding the authorization with the Worldline OAuth2 Authorization Server occurs.
6
+ class OAuth2Exception < RuntimeError
7
+
8
+ def initialize(message)
9
+ super(message)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1 @@
1
+ Dir[File.join(__dir__, 'authentication', '*.rb')].each { |f| require f }
@@ -0,0 +1,9 @@
1
+ module Worldline
2
+ module Acquiring
3
+ module SDK
4
+ # A CallContext is used to identify requests.
5
+ class CallContext
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,69 @@
1
+ #
2
+ # This file was automatically generated.
3
+ #
4
+ require 'worldline/acquiring/sdk/api_resource'
5
+ require 'worldline/acquiring/sdk/logging/logging_capable'
6
+ require 'worldline/acquiring/sdk/logging/obfuscation/obfuscation_capable'
7
+ require 'worldline/acquiring/sdk/v1/v1_client'
8
+
9
+ module Worldline
10
+ module Acquiring
11
+ module SDK
12
+ # Worldline Acquiring platform client.
13
+ #
14
+ # Thread safe.
15
+ class Client < ApiResource
16
+ include Logging::LoggingCapable
17
+ include Logging::Obfuscation::ObfuscationCapable
18
+
19
+ # @param communicator [Worldline::Acquiring::SDK::Communicator]
20
+ def initialize(communicator)
21
+ super(communicator: communicator)
22
+ end
23
+
24
+ # Utility method that delegates the call to this client's communicator.
25
+ def close_idle_connections(idle_time)
26
+ @communicator.close_idle_connections(idle_time)
27
+ end
28
+
29
+ # Utility method that delegates the call to this client's communicator.
30
+ def close_expired_connections
31
+ @communicator.close_expired_connections
32
+ end
33
+
34
+ # Sets the current body obfuscator to use.
35
+ # @param body_obfuscator [Worldline::Acquiring::SDK::Logging::Obfuscation::BodyObfuscator]
36
+ def set_body_obfuscator(body_obfuscator)
37
+ @communicator.set_body_obfuscator(body_obfuscator)
38
+ end
39
+
40
+ # Sets the current header obfuscator to use.
41
+ # @param header_obfuscator [Worldline::Acquiring::SDK::Logging::Obfuscation::HeaderObfuscator]
42
+ def set_header_obfuscator(header_obfuscator)
43
+ @communicator.set_header_obfuscator(header_obfuscator)
44
+ end
45
+
46
+ # Turns on logging using the given communicator logger.
47
+ # @param communicator_logger [Worldline::Acquiring::SDK::Logging::CommunicatorLogger]
48
+ def enable_logging(communicator_logger)
49
+ @communicator.enable_logging(communicator_logger)
50
+ end
51
+
52
+ # Turns off logging.
53
+ def disable_logging
54
+ @communicator.disable_logging
55
+ end
56
+
57
+ # Releases any system resources associated with this object.
58
+ def close
59
+ @communicator.close
60
+ end
61
+
62
+ # @return [Worldline::Acquiring::SDK::V1::V1Client]
63
+ def v1
64
+ Worldline::Acquiring::SDK::V1::V1Client.new(self, nil)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,21 @@
1
+ module Worldline
2
+ module Acquiring
3
+ module SDK
4
+ module Communication
5
+ # This exception is used when an error occurs during network communication with the Worldline Acquiring platform.
6
+ # A common cause is a timeout while connecting or when receiving or sending data.
7
+ #
8
+ # @attr [Exception] cause The error that is the cause of this error.
9
+ class CommunicationException < RuntimeError
10
+
11
+ def initialize(cause)
12
+ super()
13
+ @cause = cause
14
+ end
15
+
16
+ attr_accessor :cause
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,50 @@
1
+ require 'worldline/acquiring/sdk/logging/logging_capable'
2
+ require 'worldline/acquiring/sdk/logging/obfuscation/obfuscation_capable'
3
+
4
+ module Worldline
5
+ module Acquiring
6
+ module SDK
7
+ module Communication
8
+ # Class used to communicate using the HTTP (or HTTPS) protocol.
9
+ # Performs GET, DELETE, POST and PUT requests given a target uri and request headers.
10
+ # @see Worldline::Acquiring::SDK::Communication::DefaultConnection
11
+ class Connection
12
+ include Worldline::Acquiring::SDK::Logging::LoggingCapable
13
+ include Worldline::Acquiring::SDK::Logging::Obfuscation::ObfuscationCapable
14
+
15
+ # Performs a GET request to _uri_ using _request_headers_,
16
+ # and yields the response as the status code, headers and body.
17
+ #
18
+ # @yield (Integer, Array<Worldline::Acquiring::SDK::Communication::ResponseHeader>, IO) The status code, headers and body of the response.
19
+ def get(uri, request_headers)
20
+ raise NotImplementedError
21
+ end
22
+
23
+ # Performs a DELETE request to _uri_ using _request_headers_,
24
+ # and yields the response as the status code, headers and body.
25
+ #
26
+ # @yield (Integer, Array<Worldline::Acquiring::SDK::Communication::ResponseHeader>, IO) The status code, headers and body of the response.
27
+ def delete(uri, request_headers)
28
+ raise NotImplementedError
29
+ end
30
+
31
+ # Performs a POST request to _uri_ using _request_headers_ and _body_,
32
+ # and yields the response as the status code, headers and body.
33
+ #
34
+ # @yield (Integer, Array<Worldline::Acquiring::SDK::Communication::ResponseHeader>, IO) The status code, headers and body of the response.
35
+ def post(uri, request_headers, body)
36
+ raise NotImplementedError
37
+ end
38
+
39
+ # Performs a PUT request to _uri_ using _request_headers_ and _body_,
40
+ # and yields the response as the status code, headers and body.
41
+ #
42
+ # @yield (Integer, Array<Worldline::Acquiring::SDK::Communication::ResponseHeader>, IO) The status code, headers and body of the response.
43
+ def put(uri, request_headers, body)
44
+ raise NotImplementedError
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end