mangopay4-ruby-sdk 3.45.0 → 3.47.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 34a20d61f0af4ebbb27b23462855b1e3245dea990232708c2cadf541388a1d3e
4
- data.tar.gz: 0c60b1686a83da66bbc35eff7d79c2dc76669b433d30ade26005fbff5804d6d2
3
+ metadata.gz: 8cc10e268ef7f7029a76cd99da66abdcfbe9a76c7cd1b938992e102758e4396e
4
+ data.tar.gz: 947581ca00b8c352e07be28d4bf5f21f28211a15f6c69afc6595aa669f201249
5
5
  SHA512:
6
- metadata.gz: 401e7578d63593838a3ddd30ccf4f51a7dc954d03a425eddbc3328e872692adf9fc2b16c3ab96310b31de856bdd6e000e63adee0fa5b0aaae8197f3ddd9258ee
7
- data.tar.gz: 3f33993df417398540c62ed379f07b00a6a7fafd3115803b18f1fda163138ea7b431577bbcd933de503e45647a523983600cb29de7c7046b6897127254f4e884
6
+ metadata.gz: 7deab526bea4f06430b8b0ce51ee9d7208a7c6e103abb0cced837e4463bf634f5a686215e8ca3a547d57a685b0a7b61912efcb9fb46455c592a96555d6b5a2de
7
+ data.tar.gz: 1dd444f37f32c14ea3f74d9fa12e40a1d1957eee20be9bb121c8707e7df13d6d92a7bd3e07e37756abec1addb3f53e9b0320fa84d451e69dcb02abff99533db8
data/CHANGELOG.md CHANGED
@@ -1,3 +1,59 @@
1
+ ## [3.47.0] - 2026-03-19
2
+ ### Added - mTLS certificates support
3
+ - mTLS certificates are now configurable in the SDK via file paths or encoded strings
4
+
5
+ ## [3.46.0] - 2026-02-12
6
+ ### FX
7
+
8
+ #### Breaking change – Custom fees
9
+ #329
10
+ To support percentage-based FX fees ([API release note](/release-notes/api/2026-02-11)):
11
+ - Updated tests to check for conversion custom fees
12
+
13
+ #### Added – User margin
14
+ #329
15
+ To support the FX user margin ([API release note](/release-notes/api/2026-02-11)):
16
+ - Updated tests to check for conversion user margins
17
+
18
+ ### Echo
19
+
20
+ #### Breaking change - Settlement upload endpoints
21
+ #325
22
+ To support the new behavior of the [POST Create a Settlement](/api-reference/settlements/create-settlement) endpoint to obtain an `UploadUrl`:
23
+ - Updated `settlement_sample.csv` and tests
24
+ - **Breaking change** – Replaced `upload` method in `Settlement` with `generate_upload_url`:
25
+ - **Breaking change** – Replaced `update` method in `Settlement` with `generate_new_upload_url`:
26
+
27
+ #### Added - GET validations for a Settlement endpoint
28
+ #325
29
+ To support the [GET View validations for a Settlement](/api-reference/settlements/view-settlement-validations) endpoint:
30
+ - Added `get_validations` method to `Settlement`
31
+
32
+ #### Added - PUT Cancel a Settlement endpoint
33
+ #325
34
+ To support the [PUT Cancel a Settlement](/api-reference/settlements/cancel-settlement) endpoint:
35
+ - Added `cancel` method to `Settlement`
36
+
37
+ #### Added – POST Create a Refund of an Intent
38
+ #324
39
+ To support [POST Create a Refund of an Intent](/api-reference/intents/create-intent-refund):
40
+ - Added `create` method to `Refund`
41
+
42
+ #### Added – POST Reverse the Refund of an Intent
43
+ #324
44
+ To support [POST Reverse the Refund of an Intent](/api-reference/intents/create-intent-refund):
45
+ - Added `reverse` method to `Refund`
46
+
47
+ #### Added – POST Create a Dispute of an Intent
48
+ #324
49
+ To support [POST Create a Dispute of an Intent](/api-reference/intents/create-intent-refund):
50
+ - Added `create` method to `Dispute`
51
+
52
+ #### Added - PUT Update an Intent Dispute
53
+ #324
54
+ To support [PUT Update an Intent Dispute](/api-reference/intents/create-intent-dispute):
55
+ - Added `update_outcome` method to `Dispute`
56
+
1
57
  ## [3.45.0] - 2026-01-27
2
58
  ### Added
3
59
  - Support for new [GET View the SCA status of a User](https://docs.mangopay.com/api-reference/users/view-user-sca-status) endpoint ([API release note](https://docs.mangopay.com/release-notes/api/2026-01-15)) (#326)
data/README.md CHANGED
@@ -19,6 +19,61 @@ or by adding it to your Gemfile ```gem 'mangopay4-ruby-sdk'```
19
19
 
20
20
  * Call ```MangoPay.configure``` in your script as shown in the snippet below.
21
21
 
22
+ ## mTLS configuration
23
+ ### Set the base URL for mTLS
24
+
25
+ Using mTLS authentication requires your integration to call a base URL with a different hostname from the standard API:
26
+
27
+ * Sandbox: `https://api-mtls.sandbox.mangopay.com`
28
+ * Production: `https://api-mtls.mangopay.com`
29
+
30
+ If using mTLS, your integration should use the `api-mtls` URLs for all API calls, including OAuth token generation.
31
+
32
+ **Caution:** Ensure you set the mTLS base URL, as shown in the configuration examples below. If you don’t, the mTLS certificate will not be transferred to Mangopay. When mTLS is enforced, your integration will result in an error.
33
+
34
+ ### Configure the SDK’s mTLS properties
35
+
36
+ The Ruby SDK’s mTLS properties accept one of:
37
+
38
+ * **Base64-encoded string** – To load the certificate content from environment variables
39
+ * **File path** – To point to the locally stored file, for example during testing
40
+
41
+ | Property | Type | Description |
42
+ | --------------------- | ----------------- |------------------------------------------------------------------------------------------|
43
+ | `mtls_cert` | string | Base64-encoded string of the certificate content or path to the certificate `.pem` file. |
44
+ | `mtls_private_key` | string | Base64-encoded string of the private key content or path to the private `.key` file. |
45
+ | `mtls_key_passphrase` | string (optional) | String passphrase if the private key is encrypted. |
46
+
47
+ #### Base64-encoded strings
48
+
49
+ ```ruby theme={null}
50
+ MangoPay.configure do |c|
51
+ c.client_id = 'your-mangopay-client-id'
52
+ c.client_apiKey = 'your-mangopay-api-key'
53
+ c.root_url = 'https://api-mtls.sandbox.mangopay.com' # mTLS base URL
54
+ c.preproduction = true
55
+
56
+ c.mtls_cert = ENV['CERTIFICATE_PEM_B64'] # Base64-encoded string
57
+ c.mtls_key = ENV['PRIVATE_KEY_B64'] # Base64-encoded string
58
+ c.mtls_key_passphrase = ENV['YOUR_CERT_PASSPHRASE'] # optional, if encrypted
59
+ end
60
+ ```
61
+
62
+ #### File paths
63
+
64
+ ```ruby theme={null}
65
+ MangoPay.configure do |c|
66
+ c.client_id = 'your-mangopay-client-id'
67
+ c.client_apiKey = 'your-mangopay-api-key'
68
+ c.root_url = 'https://api-mtls.sandbox.mangopay.com' # mTLS base URL
69
+ c.preproduction = true
70
+
71
+ c.mtls_cert = '/path/to/certificate.pem' # file path
72
+ c.mtls_key = '/path/to/private.key' # file path
73
+ c.mtls_key_passphrase = 'your-cert-passphrase' # optional, if encrypted
74
+ end
75
+ ```
76
+
22
77
  ### Usage
23
78
 
24
79
  ```ruby
@@ -409,6 +409,30 @@ module MangoPay
409
409
  end
410
410
  end
411
411
  end
412
+
413
+ class Refund < Resource
414
+ class << self
415
+ def create(intent_id, params, idempotency_key = nil)
416
+ MangoPay.request(:post, "#{MangoPay.api_path_v3}/payins/intents/#{intent_id}/refunds", params, {}, idempotency_key)
417
+ end
418
+
419
+ def reverse(intent_id, refund_id, params, idempotency_key = nil)
420
+ MangoPay.request(:post, "#{MangoPay.api_path_v3}/payins/intents/#{intent_id}/refunds/#{refund_id}/reverse", params, {}, idempotency_key)
421
+ end
422
+ end
423
+ end
424
+
425
+ class Dispute < Resource
426
+ class << self
427
+ def create(intent_id, capture_id, params, idempotency_key = nil)
428
+ MangoPay.request(:post, "#{MangoPay.api_path_v3}/payins/intents/#{intent_id}/captures/#{capture_id}/disputes", params, {}, idempotency_key)
429
+ end
430
+
431
+ def update_outcome(intent_id, capture_id, dispute_id, params, idempotency_key = nil)
432
+ MangoPay.request(:put, "#{MangoPay.api_path_v3}/payins/intents/#{intent_id}/captures/#{capture_id}/disputes/#{dispute_id}/decision", params, {}, idempotency_key)
433
+ end
434
+ end
435
+ end
412
436
  end
413
437
 
414
438
  end
@@ -2,9 +2,9 @@ module MangoPay
2
2
 
3
3
  class Settlement < Resource
4
4
  class << self
5
- def upload(file, idempotency_key = nil)
5
+ def generate_upload_url(settlement, idempotency_key = nil)
6
6
  url = "#{MangoPay.api_path_v3}/payins/intents/settlements"
7
- MangoPay.request_multipart(:post, url, file, 'settlement_file.csv', idempotency_key)
7
+ MangoPay.request(:post, url, settlement, {}, idempotency_key)
8
8
  end
9
9
 
10
10
  def get(settlement_id)
@@ -12,9 +12,19 @@ module MangoPay
12
12
  MangoPay.request(:get, url)
13
13
  end
14
14
 
15
- def update(settlement_id, file, idempotency_key = nil)
15
+ def generate_new_upload_url(settlement_id, settlement)
16
16
  url = "#{MangoPay.api_path_v3}/payins/intents/settlements/#{settlement_id}"
17
- MangoPay.request_multipart(:put, url, file, 'settlement_file.csv', idempotency_key)
17
+ MangoPay.request(:put, url, settlement, {})
18
+ end
19
+
20
+ def get_validations(settlement_id, filters = {})
21
+ url = "#{MangoPay.api_path_v3}/payins/intents/settlements/#{settlement_id}/validations"
22
+ MangoPay.request(:get, url, {}, filters)
23
+ end
24
+
25
+ def cancel(settlement_id, idempotency_key = nil)
26
+ url = "#{MangoPay.api_path_v3}/payins/intents/settlements/#{settlement_id}/cancel"
27
+ MangoPay.request(:post, url, {}, {}, idempotency_key)
18
28
  end
19
29
  end
20
30
  end
@@ -1,3 +1,3 @@
1
1
  module MangoPay
2
- VERSION = '3.45.0'
2
+ VERSION = '3.47.0'
3
3
  end
data/lib/mangopay.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require 'net/http'
2
+ require 'openssl'
3
+ require 'base64'
2
4
  require 'cgi/util'
3
5
  require 'digest/md5'
4
6
  require 'multi_json'
@@ -67,7 +69,8 @@ module MangoPay
67
69
  :temp_dir, :log_file, :log_trace_headers, :http_timeout,
68
70
  :http_max_retries, :http_open_timeout,
69
71
  :logger, :use_ssl, :uk_header_flag,
70
- :after_request_proc
72
+ :after_request_proc,
73
+ :mtls_cert, :mtls_key, :mtls_key_passphrase
71
74
 
72
75
  def apply_configuration
73
76
  MangoPay.configure do |config|
@@ -83,6 +86,9 @@ module MangoPay
83
86
  config.logger = @logger
84
87
  config.uk_header_flag = @uk_header_flag
85
88
  config.after_request_proc = @after_request_proc
89
+ config.mtls_cert = @mtls_cert
90
+ config.mtls_key = @mtls_key
91
+ config.mtls_key_passphrase = @mtls_key_passphrase
86
92
  end
87
93
  end
88
94
 
@@ -226,9 +232,7 @@ module MangoPay
226
232
  headers['x-tenant-id'] = 'uk'
227
233
  end
228
234
 
229
- res = Net::HTTP.start(uri.host, uri.port, :use_ssl => configuration.use_ssl?, :read_timeout => configuration.http_timeout,
230
- :max_retries => configuration.http_max_retries,
231
- :open_timeout => configuration.http_open_timeout, ssl_version: :TLSv1_2) do |http|
235
+ res = Net::HTTP.start(uri.host, uri.port, **ssl_options) do |http|
232
236
  req = Net::HTTP::const_get(method.capitalize).new(uri.request_uri, headers)
233
237
  req.body = JSON.dump(params)
234
238
  before_request_proc.call(req) if before_request_proc
@@ -296,12 +300,7 @@ module MangoPay
296
300
  # Join string parts and ensure binary content is preserved
297
301
  body = multipart_body.map { |part| part.is_a?(String) ? part.force_encoding("ASCII-8BIT") : part }.join("\r\n")
298
302
 
299
- res = Net::HTTP.start(uri.host, uri.port,
300
- use_ssl: configuration.use_ssl?,
301
- read_timeout: configuration.http_timeout,
302
- open_timeout: configuration.http_open_timeout,
303
- max_retries: configuration.http_max_retries,
304
- ssl_version: :TLSv1_2) do |http|
303
+ res = Net::HTTP.start(uri.host, uri.port, **ssl_options) do |http|
305
304
  req_class = Net::HTTP.const_get(method.capitalize)
306
305
  req = req_class.new(uri.request_uri, headers)
307
306
  req.body = body
@@ -380,6 +379,38 @@ module MangoPay
380
379
  end
381
380
  end
382
381
 
382
+ def ssl_options
383
+ opts = {
384
+ use_ssl: configuration.use_ssl?,
385
+ read_timeout: configuration.http_timeout,
386
+ open_timeout: configuration.http_open_timeout,
387
+ max_retries: configuration.http_max_retries,
388
+ }
389
+
390
+ if defined?(OpenSSL::SSL::TLS1_2_VERSION)
391
+ opts[:min_version] = OpenSSL::SSL::TLS1_2_VERSION
392
+ else
393
+ opts[:ssl_version] = :TLSv1_2
394
+ end
395
+
396
+ if configuration.mtls_cert && configuration.mtls_key
397
+ cert_pem = file_or_pem(configuration.mtls_cert)
398
+ key_pem = file_or_pem(configuration.mtls_key)
399
+ opts[:cert] = OpenSSL::X509::Certificate.new(cert_pem)
400
+ opts[:key] = OpenSSL::PKey.read(key_pem, configuration.mtls_key_passphrase)
401
+ end
402
+
403
+ opts
404
+ end
405
+
406
+ def file_or_pem(value)
407
+ if File.exist?(value)
408
+ File.read(value)
409
+ else
410
+ Base64.decode64(value)
411
+ end
412
+ end
413
+
383
414
  def do_request(http, req, uri)
384
415
  if logs_required?
385
416
  do_request_with_log(http, req, uri)
@@ -17,7 +17,10 @@ describe MangoPay::Conversion, type: :feature do
17
17
  expect(conversion['DebitedFunds']['Amount']).not_to be_nil
18
18
  expect(conversion['CreditedFunds']['Amount']).not_to be_nil
19
19
  expect(conversion['Fees']['Amount']).not_to be_nil
20
+ expect(conversion['RequestedFees']['Value']).not_to be_nil
20
21
  expect(conversion['Status']).equal? 'SUCCEEDED'
22
+ expect(conversion['MarginsResponse']['Mangopay']).not_to be_nil
23
+ expect(conversion['MarginsResponse']['User']).to be_nil
21
24
  end
22
25
  end
23
26
 
@@ -77,10 +80,14 @@ describe MangoPay::Conversion, type: :feature do
77
80
 
78
81
  describe 'CREATE CONVERSION QUOTE' do
79
82
  it 'create a conversion quote' do
80
- conversion_quote = create_conversion_quote
83
+ conversion_quote = create_conversion_quote_with_fees
81
84
  expect(conversion_quote['DebitedFunds']).not_to be_nil
82
85
  expect(conversion_quote['CreditedFunds']).not_to be_nil
83
86
  expect(conversion_quote['Duration']).equal? 90
87
+ expect(conversion_quote['Fees']['Amount']).not_to be_nil
88
+ expect(conversion_quote['RequestedFees']['Value']).not_to be_nil
89
+ expect(conversion_quote['MarginsResponse']['Mangopay']).not_to be_nil
90
+ expect(conversion_quote['MarginsResponse']['User']).not_to be_nil
84
91
  end
85
92
  end
86
93
 
@@ -10,18 +10,7 @@ describe MangoPay::PayIn::PayInIntent, type: :feature do
10
10
  end
11
11
 
12
12
  it 'creates a payin intent full capture' do
13
- intent = new_payin_intent_authorization
14
- to_create = {
15
- "ExternalData": {
16
- "ExternalProcessingDate": "01-10-2029",
17
- "ExternalProviderReference": SecureRandom.uuid,
18
- "ExternalMerchantReference": "Order-xyz-35e8490e-2ec9-4c82-978e-c712a3f5ba16",
19
- "ExternalProviderName": "Stripe",
20
- "ExternalProviderPaymentMethod": "PAYPAL"
21
- }
22
- }
23
-
24
- created = MangoPay::PayIn::PayInIntent::Capture.create(intent['Id'], to_create)
13
+ created = create_new_intent_full_capture
25
14
  expect(created['Id']).not_to be_nil
26
15
  expect(created['Status']).to eq('CAPTURED')
27
16
  end
@@ -122,6 +111,137 @@ describe MangoPay::PayIn::PayInIntent, type: :feature do
122
111
  end
123
112
  end
124
113
 
114
+ describe 'Intent Refund' do
115
+ it 'creates a full refund' do
116
+ created_refund = create_new_intent_full_refund
117
+ expect(created_refund['Id']).not_to be_nil
118
+ expect(created_refund['Status']).to eq('REFUNDED')
119
+ end
120
+
121
+ it 'creates a partial refund' do
122
+ full_capture = create_new_intent_full_capture
123
+ to_create = {
124
+ "Amount": 1000,
125
+ "LineItems": [
126
+ {
127
+ "Id": full_capture['LineItems'][0]['Id'],
128
+ "Amount": 1000
129
+ }
130
+ ],
131
+ "ExternalData": {
132
+ "ExternalProcessingDate": 1727913600,
133
+ "ExternalProviderReference": SecureRandom.uuid,
134
+ "ExternalMerchantReference": SecureRandom.uuid,
135
+ "ExternalProviderName": "Stripe",
136
+ "ExternalProviderPaymentMethod": "PAYPAL"
137
+ }
138
+ }
139
+ created_refund = MangoPay::PayIn::PayInIntent::Refund.create(full_capture['Id'], to_create)
140
+ expect(created_refund['Id']).not_to be_nil
141
+ expect(created_refund['Status']).to eq('REFUNDED')
142
+ end
143
+
144
+ it 'fully reverses a refund' do
145
+ created_refund = create_new_intent_full_refund
146
+ to_create = {
147
+ "ExternalData": {
148
+ "ExternalProcessingDate": 1727913600,
149
+ "ExternalProviderReference": SecureRandom.uuid,
150
+ "ExternalMerchantReference": SecureRandom.uuid,
151
+ "ExternalProviderName": "Stripe",
152
+ "ExternalProviderPaymentMethod": "PAYPAL"
153
+ }
154
+ }
155
+ reversed_refund = MangoPay::PayIn::PayInIntent::Refund.reverse(created_refund['Id'], created_refund['Refund']['Id'], to_create)
156
+ expect(reversed_refund['Id']).not_to be_nil
157
+ expect(reversed_refund['Status']).to eq('REFUND_REVERSED')
158
+ end
159
+
160
+ it 'partially reverses a refund' do
161
+ created_refund = create_new_intent_full_refund
162
+ to_create = {
163
+ "Amount": 1000,
164
+ "LineItems": [
165
+ {
166
+ "Id": created_refund['LineItems'][0]['Id'],
167
+ "Amount": 1000
168
+ }
169
+ ],
170
+ "ExternalData": {
171
+ "ExternalProcessingDate": 1727913600,
172
+ "ExternalProviderReference": SecureRandom.uuid,
173
+ "ExternalMerchantReference": SecureRandom.uuid,
174
+ "ExternalProviderName": "Stripe",
175
+ "ExternalProviderPaymentMethod": "PAYPAL"
176
+ }
177
+ }
178
+ reversed_refund = MangoPay::PayIn::PayInIntent::Refund.reverse(created_refund['Id'], created_refund['Refund']['Id'], to_create)
179
+ expect(reversed_refund['Id']).not_to be_nil
180
+ expect(reversed_refund['Status']).to eq('REFUND_REVERSED')
181
+ end
182
+
183
+ it 'creates a full dispute' do
184
+ capture = create_new_intent_full_capture
185
+ to_create = {
186
+ "ExternalData": {
187
+ "ExternalProcessingDate": 1727913600,
188
+ "ExternalProviderReference": SecureRandom.uuid,
189
+ "ExternalMerchantReference": SecureRandom.uuid,
190
+ "ExternalProviderName": "Stripe",
191
+ "ExternalProviderPaymentMethod": "PAYPAL"
192
+ }
193
+ }
194
+ created_dispute = MangoPay::PayIn::PayInIntent::Dispute.create(capture['Id'], capture['Capture']['Id'], to_create)
195
+ expect(created_dispute['Id']).not_to be_nil
196
+ expect(created_dispute['Status']).to eq('DISPUTED')
197
+ end
198
+
199
+ it 'creates a partial dispute' do
200
+ capture = create_new_intent_full_capture
201
+ to_create = {
202
+ "Amount": 1000,
203
+ "LineItems": [
204
+ {
205
+ "Id": capture['LineItems'][0]['Id'],
206
+ "Amount": 1000
207
+ }
208
+ ],
209
+ "ExternalData": {
210
+ "ExternalProcessingDate": 1727913600,
211
+ "ExternalProviderReference": SecureRandom.uuid,
212
+ "ExternalMerchantReference": SecureRandom.uuid,
213
+ "ExternalProviderName": "Stripe",
214
+ "ExternalProviderPaymentMethod": "PAYPAL"
215
+ }
216
+ }
217
+ created_dispute = MangoPay::PayIn::PayInIntent::Dispute.create(capture['Id'], capture['Capture']['Id'], to_create)
218
+ expect(created_dispute['Id']).not_to be_nil
219
+ expect(created_dispute['Status']).to eq('DISPUTED')
220
+ end
221
+
222
+ it 'updates dispute outcome' do
223
+ capture = create_new_intent_full_capture
224
+ to_create = {
225
+ "ExternalData": {
226
+ "ExternalProcessingDate": 1727913600,
227
+ "ExternalProviderReference": SecureRandom.uuid,
228
+ "ExternalMerchantReference": SecureRandom.uuid,
229
+ "ExternalProviderName": "Stripe",
230
+ "ExternalProviderPaymentMethod": "PAYPAL"
231
+ }
232
+ }
233
+ created_dispute = MangoPay::PayIn::PayInIntent::Dispute.create(capture['Id'], capture['Capture']['Id'], to_create)
234
+
235
+ dto = {
236
+ "Decision": "DEFENDED"
237
+ }
238
+ updated = MangoPay::PayIn::PayInIntent::Dispute.update_outcome(capture['Id'], capture['Capture']['Id'], created_dispute['Dispute']['Id'], dto)
239
+
240
+ expect(updated['Id']).not_to be_nil
241
+ expect(updated['Decision']).to eq('DEFENDED')
242
+ end
243
+ end
244
+
125
245
  def create_new_splits(intent)
126
246
  full_capture = {
127
247
  "ExternalData": {
@@ -143,4 +263,33 @@ describe MangoPay::PayIn::PayInIntent, type: :feature do
143
263
  }
144
264
  return MangoPay::PayIn::PayInIntent::Split.create(intent['Id'], split)
145
265
  end
266
+
267
+ def create_new_intent_full_capture
268
+ intent = new_payin_intent_authorization
269
+ to_create = {
270
+ "ExternalData": {
271
+ "ExternalProcessingDate": "01-10-2029",
272
+ "ExternalProviderReference": SecureRandom.uuid,
273
+ "ExternalMerchantReference": "Order-xyz-35e8490e-2ec9-4c82-978e-c712a3f5ba16",
274
+ "ExternalProviderName": "Stripe",
275
+ "ExternalProviderPaymentMethod": "PAYPAL"
276
+ }
277
+ }
278
+
279
+ return MangoPay::PayIn::PayInIntent::Capture.create(intent['Id'], to_create)
280
+ end
281
+
282
+ def create_new_intent_full_refund
283
+ full_capture = create_new_intent_full_capture
284
+ to_create = {
285
+ "ExternalData": {
286
+ "ExternalProcessingDate": 1727913600,
287
+ "ExternalProviderReference": SecureRandom.uuid,
288
+ "ExternalMerchantReference": SecureRandom.uuid,
289
+ "ExternalProviderName": "Stripe",
290
+ "ExternalProviderPaymentMethod": "PAYPAL"
291
+ }
292
+ }
293
+ return MangoPay::PayIn::PayInIntent::Refund.create(full_capture['Id'], to_create)
294
+ end
146
295
  end
@@ -1,8 +1,8 @@
1
- IntentId,ExternalProviderReference,ExternalPaymentMethod,ExternalTransactionType,ExternalTransactionStatus,ExternalProcessingDate,Amount,Currency,ExternalInitialReference,ExternalProviderFees
2
- int_0197b19d-ee51-7b60-84cb-207491cf383a,6TU984332A894613W,PAYPAL,PAYMENT,SETTLED,19-06-2025,1000,EUR,,0
3
- ,,,,,,,,,
4
- SettlementDate,19-06-2025,,,,,,,,
5
- ExternalProviderName,Paypal,,,,,,,,
6
- TotalSettlementFeesAmount,0,,,,,,,,
7
- TotalSettlementAmount,1000,,,,,,,,
8
- SettlementCurrency,EUR,,,,,,,,
1
+ ExternalProviderReference,ExternalPaymentMethod,ExternalTransactionType,ExternalTransactionStatus,ExternalProcessingDate,Amount,Currency,ExternalInitialReference,ExternalProviderFees
2
+ 6TU984332A894613W,PAYPAL,PAYMENT,SETTLED,19-06-2025,1000,EUR,,0
3
+ ,,,,,,,,
4
+ SettlementDate,19-06-2025,,,,,,,
5
+ ExternalProviderName,Paypal,,,,,,,
6
+ TotalSettlementFeesAmount,0,,,,,,,
7
+ TotalNetSettlementAmount,1000,,,,,,,
8
+ SettlementCurrency,EUR,,,,,,,
@@ -0,0 +1,8 @@
1
+ ExternalProviderReference,ExternalPaymentMethod,ExternalTransactionType,ExternalTransactionStatus,ExternalProcessingDate,Amount,Currency,ExternalInitialReference,ExternalProviderFees
2
+ 6TU984332A894613W,PAYPAL,PAYMENT,SETTLED,19-06-2025,1000,EUR,,0
3
+ ,,,,,,,,
4
+ SettlementDate,19-06-2025,,,,,,,
5
+ ExternalProviderName,Paypal,,,,,,,
6
+ TotalSettlementFeesAmount,0,,,,,,,
7
+ TotalNetSettlementAmount,999999,,,,,,,
8
+ SettlementCurrency,EUR,,,,,,
@@ -6,33 +6,60 @@ describe MangoPay::Settlement do
6
6
 
7
7
  def create_settlement_if_needed
8
8
  @settlement ||= begin
9
- file_path = File.expand_path('settlement_sample.csv', __dir__)
10
- file = File.binread(file_path)
11
- MangoPay::Settlement.upload(file)
9
+ MangoPay::Settlement.generate_upload_url({FileName: 'settlement_sample.csv'})
12
10
  end
13
11
  end
14
12
 
13
+ def upload_file(upload_url, file_name)
14
+ file_path = File.expand_path(file_name, __dir__)
15
+ file_content = File.binread(file_path)
16
+
17
+ uri = URI(upload_url)
18
+ http = Net::HTTP.new(uri.host, uri.port)
19
+ http.use_ssl = (uri.scheme == 'https')
20
+
21
+ request = Net::HTTP::Put.new(uri)
22
+ request.body = file_content
23
+ request['Content-Type'] = 'text/csv'
24
+
25
+ http.request(request)
26
+ end
27
+
15
28
  describe 'UPLOAD' do
29
+ it 'generates the upload URL' do
30
+ expect(@settlement['SettlementId']).not_to be_nil
31
+ expect(@settlement['UploadUrl']).not_to be_nil
32
+ end
33
+
34
+ it 'generates a new upload URL' do
35
+ new_url = MangoPay::Settlement.generate_new_upload_url(@settlement['SettlementId'], {FileName: 'settlement_sample.csv'})
36
+ expect(new_url['SettlementId']).not_to be_nil
37
+ expect(new_url['UploadUrl']).not_to be_nil
38
+ end
39
+
16
40
  it 'uploads the file' do
17
- expect(@settlement['Status']).to eq('UPLOADED')
41
+ response = upload_file(@settlement['UploadUrl'], 'settlement_sample.csv')
42
+ expect(response.code.to_i).to eq(200)
43
+ end
44
+
45
+ it 'fetches validations' do
46
+ upload_file(@settlement['UploadUrl'], 'settlement_sample_bad.csv')
47
+ validations = MangoPay::Settlement.get_validations(@settlement['SettlementId'], {page: 1, per_page: 10})
48
+ expect(validations).not_to be_nil
18
49
  end
19
50
  end
20
51
 
21
52
  describe 'GET' do
22
53
  it 'fetches the file' do
23
54
  fetched = MangoPay::Settlement.get(@settlement['SettlementId'])
24
- expect(fetched['Status']).to eq('UPLOADED')
55
+ expect(fetched['Status']).to eq('PENDING_UPLOAD')
25
56
  end
26
57
  end
27
58
 
28
- describe 'UPDATE' do
29
- it 'updates the file' do
30
- file_path = File.expand_path('settlement_sample.csv', __dir__)
31
- file = File.binread(file_path)
32
- before_update = MangoPay::Settlement.upload(file)
33
- expect(before_update['Status']).to eq('UPLOADED')
34
- updated = MangoPay::Settlement.update(before_update['SettlementId'], file)
35
- expect(updated['Status']).to eq('UPLOADED')
59
+ describe 'CANCEL' do
60
+ it 'cancels the settlement' do
61
+ fetched = MangoPay::Settlement.cancel(@settlement['SettlementId'])
62
+ expect(fetched['Status']).to eq('CANCELLED')
36
63
  end
37
64
  end
38
65
  end
@@ -1225,7 +1225,8 @@ shared_context 'instant_conversion' do
1225
1225
  },
1226
1226
  Fees: {
1227
1227
  Currency: 'EUR',
1228
- Amount: 9
1228
+ Amount: 0.01,
1229
+ Type: 'PERCENTAGE'
1229
1230
  },
1230
1231
  Tag: 'Instant conversion test'
1231
1232
  )
@@ -1259,6 +1260,24 @@ shared_context 'instant_conversion' do
1259
1260
  )
1260
1261
  end
1261
1262
 
1263
+ def create_conversion_quote_with_fees
1264
+ MangoPay::Conversion.create_quote(
1265
+ CreditedFunds: { Currency: 'GBP' },
1266
+ DebitedFunds: { Currency: 'EUR', Amount: 50 },
1267
+ Duration: 300,
1268
+ Tag: 'Created using the Mangopay Ruby SDK',
1269
+ Fees: {
1270
+ Currency: 'EUR',
1271
+ Amount: 1,
1272
+ Type: 'FIXED'
1273
+ },
1274
+ UserMargin: {
1275
+ Type: "PERCENTAGE",
1276
+ Value: 0.01
1277
+ }
1278
+ )
1279
+ end
1280
+
1262
1281
  def get_conversion(id)
1263
1282
  MangoPay::Conversion.get(id, params = {})
1264
1283
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mangopay4-ruby-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.45.0
4
+ version: 3.47.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geoffroy Lorieux
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2026-01-30 00:00:00.000000000 Z
12
+ date: 2026-03-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_json
@@ -176,6 +176,7 @@ files:
176
176
  - spec/mangopay/report_v2_spec.rb
177
177
  - spec/mangopay/report_wallets_spec.rb
178
178
  - spec/mangopay/settlement_sample.csv
179
+ - spec/mangopay/settlement_sample_bad.csv
179
180
  - spec/mangopay/settlement_spec.rb
180
181
  - spec/mangopay/shared_resources.rb
181
182
  - spec/mangopay/transaction_spec.rb
@@ -267,6 +268,7 @@ test_files:
267
268
  - spec/mangopay/report_v2_spec.rb
268
269
  - spec/mangopay/report_wallets_spec.rb
269
270
  - spec/mangopay/settlement_sample.csv
271
+ - spec/mangopay/settlement_sample_bad.csv
270
272
  - spec/mangopay/settlement_spec.rb
271
273
  - spec/mangopay/shared_resources.rb
272
274
  - spec/mangopay/transaction_spec.rb