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
@@ -0,0 +1,216 @@
1
+ require 'json'
2
+ require 'spec_helper'
3
+ require 'integration_setup'
4
+ require 'webmock/rspec'
5
+ require 'worldline/acquiring/sdk/factory'
6
+ require 'worldline/acquiring/sdk/communication/multipart_form_data_object'
7
+ require 'worldline/acquiring/sdk/communication/multipart_form_data_request'
8
+ require 'worldline/acquiring/sdk/domain/data_object'
9
+ require 'worldline/acquiring/sdk/domain/uploadable_file'
10
+
11
+ describe 'multipart/form-data support' do
12
+ HTTPBIN_URL = ENV['httpbin_url'] || 'http://httpbin.org'
13
+
14
+ before(:context) { WebMock.allow_net_connect! }
15
+ after(:context) { WebMock.disable_net_connect! }
16
+
17
+ it 'Can send a Multipart Form Data Object POST upload with a response' do
18
+ configuration = Integration.init_communicator_configuration
19
+ configuration.api_endpoint = HTTPBIN_URL
20
+
21
+ multipart = Worldline::Acquiring::SDK::Communication::MultipartFormDataObject.new
22
+ multipart.add_file 'file', Worldline::Acquiring::SDK::Domain::UploadableFile.new(
23
+ 'file.txt', 'file-content', 'text/plain'
24
+ )
25
+
26
+ multipart.add_value 'value', 'Hello World'
27
+
28
+ communicator = Worldline::Acquiring::SDK::Factory.create_communicator_from_configuration configuration
29
+
30
+ response = communicator.post('/anything/operations', nil, nil, multipart,
31
+ HttpBinResponse, nil)
32
+
33
+ expect(response.form['value']).to eq 'Hello World'
34
+ expect(response.files['file']).to eq 'file-content'
35
+ end
36
+
37
+ it 'Can send a Multipart Form Data Request POST upload with a response' do
38
+ configuration = Integration.init_communicator_configuration
39
+ configuration.api_endpoint = HTTPBIN_URL
40
+
41
+ multipart = Worldline::Acquiring::SDK::Communication::MultipartFormDataObject.new
42
+ multipart.add_file 'file', Worldline::Acquiring::SDK::Domain::UploadableFile.new(
43
+ 'file.txt', 'file-content', 'text-plain'
44
+ )
45
+
46
+ multipart.add_value 'value', 'Hello World'
47
+
48
+ communicator = Worldline::Acquiring::SDK::Factory.create_communicator_from_configuration configuration
49
+
50
+ response = communicator.post '/anything/operations', nil, nil,
51
+ MultipartFormDataObjectWrapper.new(multipart), HttpBinResponse, nil
52
+
53
+ expect(response.form['value']).to eq 'Hello World'
54
+ expect(response.files['file']).to eq 'file-content'
55
+ end
56
+
57
+ it 'Can send a Multipart Form Data Object POST upload with a binary response' do
58
+ configuration = Integration.init_communicator_configuration
59
+ configuration.api_endpoint = HTTPBIN_URL
60
+
61
+ multipart = Worldline::Acquiring::SDK::Communication::MultipartFormDataObject.new
62
+ multipart.add_file 'file', Worldline::Acquiring::SDK::Domain::UploadableFile.new(
63
+ 'file.txt', 'file-content', 'text/plain'
64
+ )
65
+ multipart.add_value 'value', 'Hello World'
66
+
67
+ communicator = Worldline::Acquiring::SDK::Factory.create_communicator_from_configuration configuration
68
+
69
+ data = ''
70
+ communicator.post_with_binary_response '/anything/operations', nil, nil,
71
+ multipart, nil do |_, c|
72
+ data = c.read.force_encoding('UTF-8')
73
+ end
74
+ response = JSON.parse data
75
+
76
+ expect(response['form']['value']).to eq 'Hello World'
77
+ expect(response['files']['file']).to eq 'file-content'
78
+ end
79
+
80
+ it 'Can send a Multipart Form Data Request POST upload with a binary response' do
81
+ configuration = Integration.init_communicator_configuration
82
+ configuration.api_endpoint = HTTPBIN_URL
83
+
84
+ multipart = Worldline::Acquiring::SDK::Communication::MultipartFormDataObject.new
85
+ multipart.add_file 'file', Worldline::Acquiring::SDK::Domain::UploadableFile.new(
86
+ 'file.txt', 'file-content', 'text/plain'
87
+ )
88
+ multipart.add_value 'value', 'Hello World'
89
+
90
+ communicator = Worldline::Acquiring::SDK::Factory.create_communicator_from_configuration configuration
91
+
92
+ data = ''
93
+ communicator.post_with_binary_response '/anything/operations', nil, nil,
94
+ MultipartFormDataObjectWrapper.new(multipart), nil do |_, c|
95
+ data = c.read.force_encoding('UTF-8')
96
+ end
97
+ response = JSON.parse data
98
+
99
+ expect(response['form']['value']).to eq 'Hello World'
100
+ expect(response['files']['file']).to eq 'file-content'
101
+ end
102
+
103
+ it 'Can send a Multipart Form Data Object PUT upload with a response' do
104
+ configuration = Integration.init_communicator_configuration
105
+ configuration.api_endpoint = HTTPBIN_URL
106
+
107
+ multipart = Worldline::Acquiring::SDK::Communication::MultipartFormDataObject.new
108
+ multipart.add_file 'file', Worldline::Acquiring::SDK::Domain::UploadableFile.new(
109
+ 'file.txt', 'file-content', 'text/plain'
110
+ )
111
+
112
+ multipart.add_value 'value', 'Hello World'
113
+
114
+ communicator = Worldline::Acquiring::SDK::Factory.create_communicator_from_configuration configuration
115
+
116
+ response = communicator.put('/anything/operations', nil, nil, multipart,
117
+ HttpBinResponse, nil)
118
+
119
+ expect(response.form['value']).to eq 'Hello World'
120
+ expect(response.files['file']).to eq 'file-content'
121
+ end
122
+
123
+ it 'Can send a Multipart Form Data Request PUT upload with a response' do
124
+ configuration = Integration.init_communicator_configuration
125
+ configuration.api_endpoint = HTTPBIN_URL
126
+
127
+ multipart = Worldline::Acquiring::SDK::Communication::MultipartFormDataObject.new
128
+ multipart.add_file 'file', Worldline::Acquiring::SDK::Domain::UploadableFile.new(
129
+ 'file.txt', 'file-content', 'text-plain'
130
+ )
131
+
132
+ multipart.add_value 'value', 'Hello World'
133
+
134
+ communicator = Worldline::Acquiring::SDK::Factory.create_communicator_from_configuration configuration
135
+
136
+ response = communicator.put '/anything/operations', nil, nil,
137
+ MultipartFormDataObjectWrapper.new(multipart), HttpBinResponse, nil
138
+
139
+ expect(response.form['value']).to eq 'Hello World'
140
+ expect(response.files['file']).to eq 'file-content'
141
+ end
142
+
143
+ it 'Can send a Multipart Form Data Object PUT upload with a binary response' do
144
+ configuration = Integration.init_communicator_configuration
145
+ configuration.api_endpoint = HTTPBIN_URL
146
+
147
+ multipart = Worldline::Acquiring::SDK::Communication::MultipartFormDataObject.new
148
+ multipart.add_file 'file', Worldline::Acquiring::SDK::Domain::UploadableFile.new(
149
+ 'file.txt', 'file-content', 'text/plain'
150
+ )
151
+ multipart.add_value 'value', 'Hello World'
152
+
153
+ communicator = Worldline::Acquiring::SDK::Factory.create_communicator_from_configuration configuration
154
+
155
+ data = ''
156
+ communicator.put_with_binary_response '/anything/operations', nil, nil,
157
+ multipart, nil do |_, c|
158
+ data = c.read.force_encoding('UTF-8')
159
+ end
160
+ response = JSON.parse data
161
+
162
+ expect(response['form']['value']).to eq 'Hello World'
163
+ expect(response['files']['file']).to eq 'file-content'
164
+ end
165
+
166
+ it 'Can send a Multipart Form Data Request PUT upload with a binary response' do
167
+ configuration = Integration.init_communicator_configuration
168
+ configuration.api_endpoint = HTTPBIN_URL
169
+
170
+ multipart = Worldline::Acquiring::SDK::Communication::MultipartFormDataObject.new
171
+ multipart.add_file 'file', Worldline::Acquiring::SDK::Domain::UploadableFile.new(
172
+ 'file.txt', 'file-content', 'text/plain'
173
+ )
174
+ multipart.add_value 'value', 'Hello World'
175
+
176
+ communicator = Worldline::Acquiring::SDK::Factory.create_communicator_from_configuration configuration
177
+
178
+ data = ''
179
+ communicator.put_with_binary_response '/anything/operations', nil, nil,
180
+ MultipartFormDataObjectWrapper.new(multipart), nil do |_, c|
181
+ data = c.read.force_encoding('UTF-8')
182
+ end
183
+ response = JSON.parse data
184
+
185
+ expect(response['form']['value']).to eq 'Hello World'
186
+ expect(response['files']['file']).to eq 'file-content'
187
+ end
188
+ end
189
+
190
+ class HttpBinResponse < Worldline::Acquiring::SDK::Domain::DataObject
191
+ @form = nil
192
+ @files = nil
193
+
194
+ attr_reader :form
195
+ attr_reader :files
196
+
197
+ def from_hash(hash)
198
+ super
199
+ @form = hash['form'] if hash.key? 'form'
200
+ @files = hash['files'] if hash.key? 'files'
201
+ end
202
+ end
203
+
204
+ class MultipartFormDataObjectWrapper < Worldline::Acquiring::SDK::Communication::MultipartFormDataRequest
205
+ @multipart = nil
206
+
207
+ attr_reader :multipart
208
+
209
+ def initialize(multipart)
210
+ @multipart = multipart
211
+ end
212
+
213
+ def to_multipart_form_data_object
214
+ @multipart
215
+ end
216
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+ require 'yaml'
3
+ require 'integration_setup'
4
+ require 'webmock/rspec'
5
+ require 'worldline/acquiring/sdk/v1/acquirer/merchant/payments/get_payment_status_params'
6
+
7
+ describe 'process payment' do
8
+
9
+ before(:context){WebMock.allow_net_connect!}
10
+ after(:context){WebMock.disable_net_connect!}
11
+
12
+ it 'can be accessed' do
13
+ Integration.init_client(false) do |client|
14
+ payments_client = client.v1.acquirer(Integration::ACQUIRER_ID).merchant(Integration::MERCHANT_ID).payments
15
+
16
+ request = Integration.get_api_payment_request
17
+ response = payments_client.process_payment(request)
18
+
19
+ expect(response.operation_id).to eq(request.operation_id)
20
+ expect(response.response_code).to eq('0')
21
+ expect(response.response_code_category).to eq('APPROVED')
22
+ expect(response.response_code_description).to_not be_nil
23
+ expect(response.status).to eq('AUTHORIZED')
24
+ expect(response.initial_authorization_code).to_not be_nil
25
+ expect(response.payment_id).to_not be_nil
26
+ expect(response.total_authorized_amount).to_not be_nil
27
+ expect(response.total_authorized_amount.amount).to eq(200)
28
+ expect(response.total_authorized_amount.currency_code).to eq('GBP')
29
+ expect(response.total_authorized_amount.number_of_decimals).to eq(2)
30
+
31
+ payment_id = response.payment_id
32
+
33
+ query = Worldline::Acquiring::SDK::V1::Acquirer::Merchant::Payments::GetPaymentStatusParams.new
34
+ query.return_operations = true
35
+
36
+ status = payments_client.get_payment_status(payment_id, query)
37
+
38
+ expect(status.initial_authorization_code).to_not be_nil
39
+ expect(status.payment_id).to eq(payment_id)
40
+ expect(status.status).to eq('AUTHORIZED')
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'yaml'
3
+ require 'integration_setup'
4
+ require 'webmock/rspec'
5
+
6
+ describe 'request DCC rate' do
7
+
8
+ before(:context){WebMock.allow_net_connect!}
9
+ after(:context){WebMock.disable_net_connect!}
10
+
11
+ it 'can be accessed' do
12
+ Integration.init_client(false) do |client|
13
+ request = Integration.get_dcc_rate_request
14
+ response = client.v1.acquirer(Integration::ACQUIRER_ID).merchant(Integration::MERCHANT_ID).dynamic_currency_conversion.request_dcc_rate(request)
15
+
16
+ expect(response.proposal).to_not be_nil
17
+ expect(response.proposal.original_amount).to_not be_nil
18
+ expect(response.proposal.original_amount.amount).to eq(request.transaction.amount.amount)
19
+ expect(response.proposal.original_amount.currency_code).to eq(request.transaction.amount.currency_code)
20
+ expect(response.proposal.original_amount.number_of_decimals).to eq(request.transaction.amount.number_of_decimals)
21
+ expect(response.proposal.resulting_amount.currency_code).to eq(request.target_currency)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+ require 'integration_setup'
3
+ require 'worldline/acquiring/sdk/factory'
4
+ require 'worldline/acquiring/sdk/communicator_configuration'
5
+ require 'worldline/acquiring/sdk/proxy_configuration'
6
+ require 'worldline/acquiring/sdk/communication/communication_exception'
7
+
8
+ require 'webrick'
9
+ require 'webrick/httpproxy'
10
+
11
+ describe 'proxies' do
12
+
13
+ context 'using proxy server' do
14
+ proxy_server = nil
15
+
16
+ password_filename = 'password_file'
17
+
18
+ before :context do
19
+ WebMock.allow_net_connect!
20
+
21
+ # set up a proxy
22
+ proxy_server = Thread.new do
23
+ config = { Realm: 'testing' }
24
+ htpasswd = WEBrick::HTTPAuth::Htpasswd.new(password_filename) # create new Apache password file
25
+ proxy_configuration = Integration.init_communicator_configuration(properties_url: Integration::PROPERTIES_URI_PROXY).proxy_configuration
26
+ htpasswd.set_passwd config[:Realm], proxy_configuration.username, proxy_configuration.password
27
+ config[:UserDB] = htpasswd
28
+ basic_auth = WEBrick::HTTPAuth::ProxyBasicAuth.new(config)
29
+
30
+ auth_handler = Proc.new do |req, res|
31
+ basic_auth.authenticate(req, res)
32
+ end
33
+
34
+ proxy = WEBrick::HTTPProxyServer.new(Port: 9999, ProxyVia: false,
35
+ ProxyAuthProc: auth_handler)
36
+ Signal.trap('INT') do
37
+ proxy.shutdown
38
+ end
39
+
40
+ proxy.start
41
+ end
42
+
43
+ sleep 1 # wait for the proxy server
44
+ end
45
+
46
+ after :context do
47
+ Thread.kill(proxy_server)
48
+ File.delete(password_filename)
49
+ WebMock.disable_net_connect!
50
+ end
51
+
52
+ # NOTE: if this test is running for a long time with no response
53
+ # check https://api.preprod.acquiring.worldline-solutions.com because this is where merchant
54
+ # connects to.
55
+ it 'can be connected to' do
56
+ request = Integration.get_dcc_rate_request
57
+
58
+ Integration.init_client(true) do |client|
59
+ response = client.v1.acquirer(Integration::ACQUIRER_ID).merchant(Integration::MERCHANT_ID).dynamic_currency_conversion.request_dcc_rate(request)
60
+
61
+ expect(response.proposal).to_not be_nil
62
+ expect(response.proposal.original_amount).to_not be_nil
63
+ expect(response.proposal.original_amount.amount).to eq(request.transaction.amount.amount)
64
+ expect(response.proposal.original_amount.currency_code).to eq(request.transaction.amount.currency_code)
65
+ expect(response.proposal.original_amount.number_of_decimals).to eq(request.transaction.amount.number_of_decimals)
66
+ expect(response.proposal.resulting_amount.currency_code).to eq(request.target_currency)
67
+ end
68
+ end
69
+ end # end of using proxy server
70
+ end
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+ require 'date'
3
+ require 'securerandom'
4
+ require 'yaml'
5
+ require 'worldline/acquiring/sdk/v1/acquirer'
6
+ require 'worldline/acquiring/sdk/v1/domain'
7
+
8
+ module Integration
9
+ ACQUIRER_ID = ENV['acquiring_api_acquirerId']
10
+ MERCHANT_ID = ENV['acquiring_api_merchantId']
11
+ OAUTH2_CLIENT_ID = ENV['acquiring_api_oauth2_clientId']
12
+ OAUTH2_CLIENT_SECRET = ENV['acquiring_api_oauth2_clientSecret']
13
+ OAUTH2_TOKEN_URI = ENV['acquiring_api_oauth2_tokenUri']
14
+ raise 'could not access environment variable acquiring_api_acquirerId required for testing' unless ACQUIRER_ID
15
+ raise 'could not access environment variable acquiring_api_merchantId required for testing' unless MERCHANT_ID
16
+ raise 'could not access environment variable acquiring_api_oauth2_clientId required for testing' unless OAUTH2_CLIENT_ID
17
+ raise 'could not access environment variable acquiring_api_oauth2_clientSecret required for testing' unless OAUTH2_CLIENT_SECRET
18
+ raise 'could not access environment variable acquiring_api_oauth2_tokenUri required for testing' unless OAUTH2_TOKEN_URI
19
+ PROPERTIES_URI_OAUTH2 = File.absolute_path(File.join(__FILE__, '../fixtures/resources/properties.oauth2.yml'))
20
+ PROPERTIES_URI_PROXY = File.absolute_path(File.join(__FILE__, '../fixtures/resources/properties.proxy.yml'))
21
+
22
+ def self.create_uri(scheme, host, port)
23
+ if port == -1
24
+ "#{scheme}://#{host}"
25
+ else
26
+ "#{scheme}://#{host}:#{port.to_s}"
27
+ end
28
+ end
29
+
30
+ def self.init_communicator_configuration(properties_url: PROPERTIES_URI_OAUTH2, max_connections: nil)
31
+ yaml = YAML.load_file(properties_url)
32
+ configuration = Worldline::Acquiring::SDK::CommunicatorConfiguration.new(properties: yaml,
33
+ api_endpoint: 'https://api.preprod.acquiring.worldline-solutions.com',
34
+ authorization_type: 'OAuth2',
35
+ oauth2_client_id: OAUTH2_CLIENT_ID,
36
+ oauth2_client_secret: OAUTH2_CLIENT_SECRET,
37
+ oauth2_token_uri: OAUTH2_TOKEN_URI,
38
+ max_connections: max_connections)
39
+ host = ENV['acquiring_api_endpoint_host']
40
+ if host
41
+ scheme = ENV.fetch('acquiring_api_endpoint_scheme', 'https')
42
+ port = ENV.fetch('acquiring_api_endpoint_port', -1)
43
+ configuration.api_endpoint = create_uri(scheme, host, port)
44
+ end
45
+ configuration
46
+ end
47
+
48
+ def self.init_client(with_proxy, max_connections = nil)
49
+ if with_proxy
50
+ url = PROPERTIES_URI_PROXY
51
+ else
52
+ url = PROPERTIES_URI_OAUTH2
53
+ end
54
+ configuration = init_communicator_configuration(properties_url: url, max_connections: max_connections)
55
+ yield client = Worldline::Acquiring::SDK::Factory.create_client_from_configuration(configuration)
56
+ client.close
57
+ end
58
+
59
+ def self.get_api_payment_request
60
+ request = Worldline::Acquiring::SDK::V1::Domain::ApiPaymentRequest.new
61
+
62
+ request.amount = Worldline::Acquiring::SDK::V1::Domain::AmountData.new
63
+ request.amount.amount = 200
64
+ request.amount.currency_code = 'GBP'
65
+ request.amount.number_of_decimals = 2
66
+ request.authorization_type = 'PRE_AUTHORIZATION'
67
+ request.transaction_timestamp = DateTime.now
68
+ request.card_payment_data = Worldline::Acquiring::SDK::V1::Domain::CardPaymentData.new
69
+ request.card_payment_data.card_entry_mode = 'ECOMMERCE'
70
+ request.card_payment_data.allow_partial_approval = false
71
+ request.card_payment_data.brand = 'VISA'
72
+ request.card_payment_data.capture_immediately = false
73
+ request.card_payment_data.cardholder_verification_method = 'CARD_SECURITY_CODE'
74
+ request.card_payment_data.card_data = Worldline::Acquiring::SDK::V1::Domain::PlainCardData.new
75
+ request.card_payment_data.card_data.expiry_date = '122031'
76
+ request.card_payment_data.card_data.card_number = '4176669999000104'
77
+ request.card_payment_data.card_data.card_security_code = '012'
78
+ request.references = Worldline::Acquiring::SDK::V1::Domain::PaymentReferences.new
79
+ request.references.merchant_reference = 'your-order-' + SecureRandom.uuid
80
+ request.operation_id = SecureRandom.uuid
81
+ request
82
+ end
83
+
84
+ def self.get_dcc_rate_request(amount = 200)
85
+ amount_data = Worldline::Acquiring::SDK::V1::Domain::AmountData.new
86
+ amount_data.amount = amount
87
+ amount_data.currency_code = 'GBP'
88
+ amount_data.number_of_decimals = 2
89
+
90
+ transaction_data_for_dcc = Worldline::Acquiring::SDK::V1::Domain::TransactionDataForDcc.new
91
+ transaction_data_for_dcc.amount = amount_data
92
+ transaction_data_for_dcc.transaction_type = 'PAYMENT'
93
+ transaction_data_for_dcc.transaction_timestamp = DateTime.now
94
+
95
+ point_of_sale_data_for_dcc = Worldline::Acquiring::SDK::V1::Domain::PointOfSaleDataForDcc.new
96
+ point_of_sale_data_for_dcc.terminal_id = '12345678'
97
+
98
+ card_data_for_dcc = Worldline::Acquiring::SDK::V1::Domain::CardDataForDcc.new
99
+ card_data_for_dcc.bin = '41766699'
100
+ card_data_for_dcc.brand = 'VISA'
101
+
102
+ request = Worldline::Acquiring::SDK::V1::Domain::GetDCCRateRequest.new
103
+ request.operation_id = SecureRandom.uuid
104
+ request.target_currency = 'EUR'
105
+ request.card_payment_data = card_data_for_dcc
106
+ request.point_of_sale_data = point_of_sale_data_for_dcc
107
+ request.transaction = transaction_data_for_dcc
108
+
109
+ request
110
+ end
111
+ end
@@ -0,0 +1,68 @@
1
+ require 'uri'
2
+ require 'spec_helper'
3
+ require 'securerandom'
4
+
5
+ describe 'OAuth2Authenticator' do
6
+ resource_prefix = 'spec/fixtures/resources/authentication/'
7
+
8
+ OAuth2Exception = Worldline::Acquiring::SDK::Authentication::OAuth2Exception
9
+
10
+ before do
11
+ $configuration = Worldline::Acquiring::SDK::Factory.create_configuration(PROPERTIES_URI_OAUTH2,
12
+ SecureRandom.uuid,
13
+ SecureRandom.uuid)
14
+ end
15
+
16
+ it 'should retrieve the access token successfully' do
17
+ response_body = IO.read(resource_prefix + 'oauth2AccessToken.json')
18
+
19
+ stub_request(:post, $configuration.oauth2_token_uri)
20
+ .to_return(status: 200, body: response_body, headers: {'Content-Type' => 'application/json'})
21
+
22
+ authenticator = Worldline::Acquiring::SDK::Authentication::OAuth2Authenticator.new($configuration)
23
+ request_uri = URI::HTTP.build(path: '/operations')
24
+
25
+ runner_threads = Array.new(10){ Thread.new{
26
+ authenticator.get_authorization(nil, request_uri, nil)
27
+ }}
28
+ runner_threads.each { |t| expect(t.value).to eq('Bearer accessToken') }
29
+
30
+ assert_requested :post, $configuration.oauth2_token_uri, times: 1
31
+ end
32
+
33
+ it 'should fail with an invalid-client response' do
34
+ response_body = IO.read(resource_prefix + 'oauth2AccessToken.invalidClient.json')
35
+
36
+ stub_request(:post, $configuration.oauth2_token_uri)
37
+ .to_return(status: 401, body: response_body, headers: {'Content-Type' => 'application/json'})
38
+
39
+ authenticator = Worldline::Acquiring::SDK::Authentication::OAuth2Authenticator.new($configuration)
40
+ request_uri = URI::HTTP.build(path: '/operations')
41
+
42
+ runner_threads = Array.new(10){ Thread.new{
43
+ authenticator.get_authorization(nil, request_uri, nil)
44
+ }}
45
+ runner_threads.each { |t| expect{t.value}.to raise_error(OAuth2Exception) { |error|
46
+ expect(error.message).to eq('There was an error while retrieving the OAuth2 access token: unauthorized_client - INVALID_CREDENTIALS: Invalid client credentials');
47
+ }}
48
+
49
+ assert_requested :post, $configuration.oauth2_token_uri, times: runner_threads.length
50
+ end
51
+
52
+ it 'should retrieve the access token every time it is expired' do
53
+ response_body = IO.read(resource_prefix + 'oauth2AccessToken.expired.json')
54
+
55
+ stub_request(:post, $configuration.oauth2_token_uri)
56
+ .to_return(status: 200, body: response_body, headers: {'Content-Type' => 'application/json'})
57
+
58
+ authenticator = Worldline::Acquiring::SDK::Authentication::OAuth2Authenticator.new($configuration)
59
+ request_uri = URI::HTTP.build(path: '/operations')
60
+
61
+ runner_threads = Array.new(10){ Thread.new{
62
+ authenticator.get_authorization(nil, request_uri, nil)
63
+ }}
64
+ runner_threads.each { |t| expect(t.value).to eq('Bearer expiredAccessToken') }
65
+
66
+ assert_requested :post, $configuration.oauth2_token_uri, times: runner_threads.length
67
+ end
68
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Client' do
4
+ Factory ||= Worldline::Acquiring::SDK::Factory
5
+ Connection ||= Worldline::Acquiring::SDK::Communication::Connection
6
+ PooledConnection ||= Worldline::Acquiring::SDK::Communication::PooledConnection
7
+
8
+ it 'should not close idle connections of an unpooled connection' do
9
+ conn = Connection.allocate # Create fake (uninitialized) connection
10
+ communicator = Factory.create_communicator_from_file(PROPERTIES_URI_OAUTH2, OAUTH2_CLIENT_ID, OAUTH2_CLIENT_SECRET, connection: conn)
11
+ client = Factory.create_client_from_communicator(communicator)
12
+
13
+ expect(communicator.instance_variable_get(:@connection)).to_not receive(:close_idle_connections)
14
+
15
+ client.close_idle_connections(0.500)
16
+ end
17
+
18
+ it 'should close idle connections of a pooled connection' do
19
+ conn = PooledConnection.allocate # Create fake (uninitialized) connection
20
+ communicator = Factory.create_communicator_from_file(PROPERTIES_URI_OAUTH2, OAUTH2_CLIENT_ID, OAUTH2_CLIENT_SECRET, connection: conn)
21
+ client = Factory.create_client_from_communicator(communicator)
22
+
23
+ expect(communicator.instance_variable_get(:@connection)).to receive(:close_idle_connections).with(0.500)
24
+
25
+ client.close_idle_connections(0.500)
26
+ end
27
+
28
+ it 'should not close expired connections of an unpooled connection' do
29
+ conn = Connection.allocate # Create fake (uninitialized) connection
30
+ communicator = Factory.create_communicator_from_file(PROPERTIES_URI_OAUTH2, OAUTH2_CLIENT_ID, OAUTH2_CLIENT_SECRET, connection: conn)
31
+ client = Factory.create_client_from_communicator(communicator)
32
+
33
+ expect(communicator.instance_variable_get(:@connection)).to_not receive(:close_expired_connections)
34
+
35
+ client.close_expired_connections
36
+ end
37
+
38
+ it 'should close expired connections of a pooled connection' do
39
+ conn = PooledConnection.allocate # Create fake (uninitialized) connection
40
+ communicator = Factory.create_communicator_from_file(PROPERTIES_URI_OAUTH2, OAUTH2_CLIENT_ID, OAUTH2_CLIENT_SECRET, connection: conn)
41
+ client = Factory.create_client_from_communicator(communicator)
42
+
43
+ expect(communicator.instance_variable_get(:@connection)).to receive(:close_expired_connections)
44
+
45
+ client.close_expired_connections
46
+ end
47
+ end