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 +4 -4
- data/CHANGELOG.md +56 -0
- data/README.md +55 -0
- data/lib/mangopay/pay_in.rb +24 -0
- data/lib/mangopay/settlement.rb +14 -4
- data/lib/mangopay/version.rb +1 -1
- data/lib/mangopay.rb +41 -10
- data/spec/mangopay/conversion_spec.rb +8 -1
- data/spec/mangopay/payin_intent_spec.rb +161 -12
- data/spec/mangopay/settlement_sample.csv +8 -8
- data/spec/mangopay/settlement_sample_bad.csv +8 -0
- data/spec/mangopay/settlement_spec.rb +40 -13
- data/spec/mangopay/shared_resources.rb +20 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8cc10e268ef7f7029a76cd99da66abdcfbe9a76c7cd1b938992e102758e4396e
|
|
4
|
+
data.tar.gz: 947581ca00b8c352e07be28d4bf5f21f28211a15f6c69afc6595aa669f201249
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
data/lib/mangopay/pay_in.rb
CHANGED
|
@@ -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
|
data/lib/mangopay/settlement.rb
CHANGED
|
@@ -2,9 +2,9 @@ module MangoPay
|
|
|
2
2
|
|
|
3
3
|
class Settlement < Resource
|
|
4
4
|
class << self
|
|
5
|
-
def
|
|
5
|
+
def generate_upload_url(settlement, idempotency_key = nil)
|
|
6
6
|
url = "#{MangoPay.api_path_v3}/payins/intents/settlements"
|
|
7
|
-
MangoPay.
|
|
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
|
|
15
|
+
def generate_new_upload_url(settlement_id, settlement)
|
|
16
16
|
url = "#{MangoPay.api_path_v3}/payins/intents/settlements/#{settlement_id}"
|
|
17
|
-
MangoPay.
|
|
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
|
data/lib/mangopay/version.rb
CHANGED
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,
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
SettlementDate,19-06-2025
|
|
5
|
-
ExternalProviderName,Paypal
|
|
6
|
-
TotalSettlementFeesAmount,0
|
|
7
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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('
|
|
55
|
+
expect(fetched['Status']).to eq('PENDING_UPLOAD')
|
|
25
56
|
end
|
|
26
57
|
end
|
|
27
58
|
|
|
28
|
-
describe '
|
|
29
|
-
it '
|
|
30
|
-
|
|
31
|
-
|
|
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:
|
|
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.
|
|
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-
|
|
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
|