mangopay4-ruby-sdk 3.45.0 → 3.48.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: 674878e4aba915f0f767a1a58f76f9330bb0000628d0ea0d5fca7ca124eaa3bc
4
+ data.tar.gz: 5a4dcd8a5b50557536daf8f57b82fb8ebefa8c73cb963a4e5087ab6dfaf6b4e9
5
5
  SHA512:
6
- metadata.gz: 401e7578d63593838a3ddd30ccf4f51a7dc954d03a425eddbc3328e872692adf9fc2b16c3ab96310b31de856bdd6e000e63adee0fa5b0aaae8197f3ddd9258ee
7
- data.tar.gz: 3f33993df417398540c62ed379f07b00a6a7fafd3115803b18f1fda163138ea7b431577bbcd933de503e45647a523983600cb29de7c7046b6897127254f4e884
6
+ metadata.gz: d69b73f8eba11516e2cd4c93992732a0eddcc02ab3ba6aa9779b9c692b3a827f17078dba7ce6654d3e2dccf59ab218717dc58111c368ebf790eb17bef05b5df2
7
+ data.tar.gz: f1c53aa135c0f4343522bb7d5df8c65ae7d31654a42075cc39322ecbb394c4538777458b54e369bf9dec1549c3b5e9502246d3186b2d716dc2f29016a77ac46e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,63 @@
1
+ ## [3.48.0] - 2026-03-25
2
+ ### Removed
3
+ - Payconiq PayIn (`MangoPay::PayIn::PayconiqWeb::Create`) removed following provider discontinuation on 4 Dec 2025 (#334)
4
+
5
+ ## [3.47.0] - 2026-03-19
6
+ ### Added - mTLS certificates support
7
+ - mTLS certificates are now configurable in the SDK via file paths or encoded strings
8
+
9
+ ## [3.46.0] - 2026-02-12
10
+ ### FX
11
+
12
+ #### Breaking change – Custom fees
13
+ #329
14
+ To support percentage-based FX fees ([API release note](/release-notes/api/2026-02-11)):
15
+ - Updated tests to check for conversion custom fees
16
+
17
+ #### Added – User margin
18
+ #329
19
+ To support the FX user margin ([API release note](/release-notes/api/2026-02-11)):
20
+ - Updated tests to check for conversion user margins
21
+
22
+ ### Echo
23
+
24
+ #### Breaking change - Settlement upload endpoints
25
+ #325
26
+ To support the new behavior of the [POST Create a Settlement](/api-reference/settlements/create-settlement) endpoint to obtain an `UploadUrl`:
27
+ - Updated `settlement_sample.csv` and tests
28
+ - **Breaking change** – Replaced `upload` method in `Settlement` with `generate_upload_url`:
29
+ - **Breaking change** – Replaced `update` method in `Settlement` with `generate_new_upload_url`:
30
+
31
+ #### Added - GET validations for a Settlement endpoint
32
+ #325
33
+ To support the [GET View validations for a Settlement](/api-reference/settlements/view-settlement-validations) endpoint:
34
+ - Added `get_validations` method to `Settlement`
35
+
36
+ #### Added - PUT Cancel a Settlement endpoint
37
+ #325
38
+ To support the [PUT Cancel a Settlement](/api-reference/settlements/cancel-settlement) endpoint:
39
+ - Added `cancel` method to `Settlement`
40
+
41
+ #### Added – POST Create a Refund of an Intent
42
+ #324
43
+ To support [POST Create a Refund of an Intent](/api-reference/intents/create-intent-refund):
44
+ - Added `create` method to `Refund`
45
+
46
+ #### Added – POST Reverse the Refund of an Intent
47
+ #324
48
+ To support [POST Reverse the Refund of an Intent](/api-reference/intents/create-intent-refund):
49
+ - Added `reverse` method to `Refund`
50
+
51
+ #### Added – POST Create a Dispute of an Intent
52
+ #324
53
+ To support [POST Create a Dispute of an Intent](/api-reference/intents/create-intent-refund):
54
+ - Added `create` method to `Dispute`
55
+
56
+ #### Added - PUT Update an Intent Dispute
57
+ #324
58
+ To support [PUT Update an Intent Dispute](/api-reference/intents/create-intent-dispute):
59
+ - Added `update_outcome` method to `Dispute`
60
+
1
61
  ## [3.45.0] - 2026-01-27
2
62
  ### Added
3
63
  - 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
@@ -147,22 +147,6 @@ module MangoPay
147
147
 
148
148
  end
149
149
 
150
- module Payconiq
151
-
152
- class Web < Resource
153
- include HTTPCalls::Create
154
-
155
- def self.url(*)
156
- "#{MangoPay.api_path}/payins/payment-methods/payconiq"
157
- end
158
-
159
- def self.create_legacy(params, idempotency_key = nil)
160
- MangoPay.request(:post, "#{MangoPay.api_path}/payins/payconiq/web", params, {}, idempotency_key)
161
- end
162
- end
163
-
164
- end
165
-
166
150
  module ApplePay
167
151
  class Direct < Resource
168
152
  include HTTPCalls::Create
@@ -409,6 +393,30 @@ module MangoPay
409
393
  end
410
394
  end
411
395
  end
396
+
397
+ class Refund < Resource
398
+ class << self
399
+ def create(intent_id, params, idempotency_key = nil)
400
+ MangoPay.request(:post, "#{MangoPay.api_path_v3}/payins/intents/#{intent_id}/refunds", params, {}, idempotency_key)
401
+ end
402
+
403
+ def reverse(intent_id, refund_id, params, idempotency_key = nil)
404
+ MangoPay.request(:post, "#{MangoPay.api_path_v3}/payins/intents/#{intent_id}/refunds/#{refund_id}/reverse", params, {}, idempotency_key)
405
+ end
406
+ end
407
+ end
408
+
409
+ class Dispute < Resource
410
+ class << self
411
+ def create(intent_id, capture_id, params, idempotency_key = nil)
412
+ MangoPay.request(:post, "#{MangoPay.api_path_v3}/payins/intents/#{intent_id}/captures/#{capture_id}/disputes", params, {}, idempotency_key)
413
+ end
414
+
415
+ def update_outcome(intent_id, capture_id, dispute_id, params, idempotency_key = nil)
416
+ MangoPay.request(:put, "#{MangoPay.api_path_v3}/payins/intents/#{intent_id}/captures/#{capture_id}/disputes/#{dispute_id}/decision", params, {}, idempotency_key)
417
+ end
418
+ end
419
+ end
412
420
  end
413
421
 
414
422
  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.48.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
@@ -358,34 +358,6 @@ shared_context 'payins' do
358
358
  )
359
359
  end
360
360
 
361
- ###############################################
362
- # payconiq/web
363
- ###############################################
364
-
365
- let(:new_payin_payconiq_web) do
366
- MangoPay::PayIn::Payconiq::Web.create(
367
- AuthorId: new_natural_user['Id'],
368
- CreditedWalletId: new_wallet['Id'],
369
- DebitedFunds: { Currency: 'EUR', Amount: 100 },
370
- Fees: { Currency: 'EUR', Amount: 0 },
371
- ReturnURL: MangoPay.configuration.root_url,
372
- Country: "BE",
373
- Tag: 'Custom Meta'
374
- )
375
- end
376
-
377
- let(:new_payin_payconiq_web_legacy) do
378
- MangoPay::PayIn::Payconiq::Web.create_legacy(
379
- AuthorId: new_natural_user['Id'],
380
- CreditedWalletId: new_wallet['Id'],
381
- DebitedFunds: { Currency: 'EUR', Amount: 100 },
382
- Fees: { Currency: 'EUR', Amount: 0 },
383
- ReturnURL: MangoPay.configuration.root_url,
384
- Country: "BE",
385
- Tag: 'Custom Meta'
386
- )
387
- end
388
-
389
361
  ###############################################
390
362
  # applepay/direct
391
363
  ###############################################
@@ -1225,7 +1197,8 @@ shared_context 'instant_conversion' do
1225
1197
  },
1226
1198
  Fees: {
1227
1199
  Currency: 'EUR',
1228
- Amount: 9
1200
+ Amount: 10,
1201
+ Type: 'PERCENTAGE'
1229
1202
  },
1230
1203
  Tag: 'Instant conversion test'
1231
1204
  )
@@ -1259,6 +1232,24 @@ shared_context 'instant_conversion' do
1259
1232
  )
1260
1233
  end
1261
1234
 
1235
+ def create_conversion_quote_with_fees
1236
+ MangoPay::Conversion.create_quote(
1237
+ CreditedFunds: { Currency: 'GBP' },
1238
+ DebitedFunds: { Currency: 'EUR', Amount: 50 },
1239
+ Duration: 300,
1240
+ Tag: 'Created using the Mangopay Ruby SDK',
1241
+ Fees: {
1242
+ Currency: 'EUR',
1243
+ Amount: 1,
1244
+ Type: 'FIXED'
1245
+ },
1246
+ UserMargin: {
1247
+ Type: "PERCENTAGE",
1248
+ Value: 0.01
1249
+ }
1250
+ )
1251
+ end
1252
+
1262
1253
  def get_conversion(id)
1263
1254
  MangoPay::Conversion.get(id, params = {})
1264
1255
  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.48.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-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_json
@@ -159,7 +159,6 @@ files:
159
159
  - spec/mangopay/payin_mbway_web_spec.rb
160
160
  - spec/mangopay/payin_multibanco_web_spec.rb
161
161
  - spec/mangopay/payin_paybybank_web_spec.rb
162
- - spec/mangopay/payin_payconiq_web_spec.rb
163
162
  - spec/mangopay/payin_paypal_web_spec.rb
164
163
  - spec/mangopay/payin_preauthorized_direct_spec.rb
165
164
  - spec/mangopay/payin_satispay_web_spec.rb
@@ -176,6 +175,7 @@ files:
176
175
  - spec/mangopay/report_v2_spec.rb
177
176
  - spec/mangopay/report_wallets_spec.rb
178
177
  - spec/mangopay/settlement_sample.csv
178
+ - spec/mangopay/settlement_sample_bad.csv
179
179
  - spec/mangopay/settlement_spec.rb
180
180
  - spec/mangopay/shared_resources.rb
181
181
  - spec/mangopay/transaction_spec.rb
@@ -250,7 +250,6 @@ test_files:
250
250
  - spec/mangopay/payin_mbway_web_spec.rb
251
251
  - spec/mangopay/payin_multibanco_web_spec.rb
252
252
  - spec/mangopay/payin_paybybank_web_spec.rb
253
- - spec/mangopay/payin_payconiq_web_spec.rb
254
253
  - spec/mangopay/payin_paypal_web_spec.rb
255
254
  - spec/mangopay/payin_preauthorized_direct_spec.rb
256
255
  - spec/mangopay/payin_satispay_web_spec.rb
@@ -267,6 +266,7 @@ test_files:
267
266
  - spec/mangopay/report_v2_spec.rb
268
267
  - spec/mangopay/report_wallets_spec.rb
269
268
  - spec/mangopay/settlement_sample.csv
269
+ - spec/mangopay/settlement_sample_bad.csv
270
270
  - spec/mangopay/settlement_spec.rb
271
271
  - spec/mangopay/shared_resources.rb
272
272
  - spec/mangopay/transaction_spec.rb
@@ -1,32 +0,0 @@
1
- describe MangoPay::PayIn::Payconiq::Web, type: :feature do
2
- include_context 'payins'
3
-
4
- def check_type_and_status(payin)
5
- expect(payin['Type']).to eq('PAYIN')
6
- expect(payin['Nature']).to eq('REGULAR')
7
- expect(payin['PaymentType']).to eq('PAYCONIQ')
8
- expect(payin['ExecutionType']).to eq('WEB')
9
-
10
- # not SUCCEEDED yet: waiting for processing
11
- expect(payin['Status']).to eq('CREATED')
12
- expect(payin['ResultCode']).to be_nil
13
- expect(payin['ResultMessage']).to be_nil
14
- expect(payin['ExecutionDate']).to be_nil
15
- end
16
-
17
- describe 'CREATE' do
18
- it 'creates a payconiq web payin' do
19
- created = new_payin_payconiq_web
20
- expect(created['Id']).not_to be_nil
21
- check_type_and_status(created)
22
- end
23
-
24
- # endpoint removed
25
- xit 'creates a payconiq web payin using the old endpoint' do
26
- created = new_payin_payconiq_web_legacy
27
- expect(created['Id']).not_to be_nil
28
- check_type_and_status(created)
29
- end
30
- end
31
-
32
- end