acquiring-sdk-ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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