mercadopago-sdk 3.3.0 → 3.4.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/.github/workflows/ci.yml +35 -33
- data/.github/workflows/release.yml +4 -7
- data/.gitignore +1 -0
- data/.rubocop_todo.yml +6 -0
- data/CHANGELOG.md +16 -0
- data/Gemfile.lock +1 -1
- data/examples/order/create_automatic_payment.rb +162 -0
- data/lib/mercadopago/resources/disbursement_refund.rb +1 -1
- data/lib/mercadopago/resources/order/request.rb +388 -0
- data/lib/mercadopago/resources/order.rb +12 -4
- data/lib/mercadopago.rb +1 -0
- data/mercadopago.gemspec +1 -1
- data/tests/base_client_test.rb +48 -0
- data/tests/test_advanced_payment.rb +67 -0
- data/tests/test_card.rb +36 -77
- data/tests/test_card_token.rb +18 -29
- data/tests/test_chargeback.rb +14 -11
- data/tests/test_customer.rb +40 -45
- data/tests/test_disbursement_refund.rb +30 -0
- data/tests/test_identification_type.rb +8 -9
- data/tests/test_invoice.rb +15 -11
- data/tests/test_merchant_order.rb +23 -111
- data/tests/test_oauth.rb +28 -17
- data/tests/test_order.rb +57 -447
- data/tests/test_order_request.rb +272 -0
- data/tests/test_order_transaction.rb +18 -126
- data/tests/test_payment.rb +42 -265
- data/tests/test_payment_methods.rb +9 -7
- data/tests/test_point.rb +28 -13
- data/tests/test_preapproval.rb +28 -66
- data/tests/test_preapproval_plan.rb +24 -83
- data/tests/test_preference.rb +22 -64
- data/tests/test_refund.rb +22 -40
- data/tests/test_subscription.rb +24 -55
- data/tests/test_user.rb +8 -10
- data/tests/tests.rb +11 -1
- metadata +11 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fb7488c81eb88390ec65887c4f7626f51fabd3a268fec20e37a21c4bcb857551
|
|
4
|
+
data.tar.gz: 80ffcd3be59f116220171f3b4b053c0b48a5e222a09c22e4e9063ef6d8514826
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6fa0b01c59f95ee75586f5685212a899fd717963230cafafd237b2b8d981f7ecb75327446419323f88933e50fcc85850efbddafcb0bdd6b630de1d043b77fd6a
|
|
7
|
+
data.tar.gz: 101c97f483a49e8317b8ab9748e2433f42a0334969185fa26f21ee61ef0d139883cb22aa80618565dcea6702195868ea886893132b650b4dd2287b5c8c8d59c0
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -1,43 +1,45 @@
|
|
|
1
|
-
name:
|
|
1
|
+
name: CI
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
|
-
branches: [
|
|
5
|
+
branches: ["master"]
|
|
6
6
|
pull_request:
|
|
7
|
-
branches: [
|
|
7
|
+
branches: ["master"]
|
|
8
8
|
|
|
9
9
|
jobs:
|
|
10
10
|
test:
|
|
11
|
+
name: Test on Ruby ${{ matrix.ruby-version }}
|
|
11
12
|
runs-on: ubuntu-latest
|
|
12
|
-
container: ruby
|
|
13
|
+
container: ruby:${{ matrix.ruby-version }}
|
|
14
|
+
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
ruby-version: ["3.3", "3.4"]
|
|
13
19
|
|
|
14
20
|
steps:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
# - name: Run tests
|
|
41
|
-
# run: bundle exec rake
|
|
42
|
-
# env:
|
|
43
|
-
# ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN_V2 }}
|
|
21
|
+
- name: Checkout code
|
|
22
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
|
|
23
|
+
|
|
24
|
+
- name: Configure git safe directory
|
|
25
|
+
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: bundle install
|
|
29
|
+
|
|
30
|
+
- name: Lint with Rubocop
|
|
31
|
+
run: bundle exec rubocop lib
|
|
32
|
+
|
|
33
|
+
- name: Run unit tests
|
|
34
|
+
run: bundle exec rake test
|
|
35
|
+
|
|
36
|
+
- name: Dependency audit
|
|
37
|
+
run: |
|
|
38
|
+
gem install bundler-audit --no-document
|
|
39
|
+
bundle-audit check --update
|
|
40
|
+
|
|
41
|
+
- name: Dependency review
|
|
42
|
+
if: github.event_name == 'pull_request'
|
|
43
|
+
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v4
|
|
44
|
+
with:
|
|
45
|
+
fail-on-severity: high
|
|
@@ -2,7 +2,7 @@ name: Release SDK - Publish Gem
|
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
release:
|
|
5
|
-
types: [
|
|
5
|
+
types: [published]
|
|
6
6
|
|
|
7
7
|
jobs:
|
|
8
8
|
release:
|
|
@@ -16,12 +16,12 @@ jobs:
|
|
|
16
16
|
- name: Checkout code
|
|
17
17
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
18
18
|
|
|
19
|
-
- name: Install dependencies
|
|
20
|
-
run: bundle install
|
|
21
|
-
|
|
22
19
|
- name: Configure git safe directory
|
|
23
20
|
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
|
24
21
|
|
|
22
|
+
- name: Install dependencies
|
|
23
|
+
run: bundle install
|
|
24
|
+
|
|
25
25
|
- name: Build gem
|
|
26
26
|
run: gem build *.gemspec
|
|
27
27
|
|
|
@@ -29,6 +29,3 @@ jobs:
|
|
|
29
29
|
env:
|
|
30
30
|
GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
|
|
31
31
|
run: gem push *.gem
|
|
32
|
-
|
|
33
|
-
- name: Wait for release to propagate
|
|
34
|
-
run: gem install rubygems-await
|
data/.gitignore
CHANGED
data/.rubocop_todo.yml
CHANGED
|
@@ -48,8 +48,14 @@ Metrics/MethodLength:
|
|
|
48
48
|
|
|
49
49
|
# Offense count: 3
|
|
50
50
|
# Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
|
|
51
|
+
Metrics/ModuleLength:
|
|
52
|
+
Exclude:
|
|
53
|
+
- 'lib/mercadopago/resources/order/request.rb'
|
|
54
|
+
|
|
51
55
|
Metrics/ParameterLists:
|
|
52
56
|
Max: 7
|
|
57
|
+
Exclude:
|
|
58
|
+
- 'lib/mercadopago/resources/order/request.rb'
|
|
53
59
|
|
|
54
60
|
# Offense count: 1
|
|
55
61
|
Naming/AccessorMethodName:
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
|
6
6
|
and [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.4.0] - 2026-08-11
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Automatic Payments example**: two-step recurring flow ([#156](https://github.com/mercadopago/sdk-ruby/pull/156))
|
|
12
|
+
- **Pagination**: support `data` key for Orders v2 API and string paging totals ([#156](https://github.com/mercadopago/sdk-ruby/pull/156))
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
- **Stored credential**: rename `prev_transaction_ref` to `previous_transaction_reference` ([#156](https://github.com/mercadopago/sdk-ruby/pull/156))
|
|
16
|
+
- **`Iterator#call`**: use keyword args for Ruby 4.0 strict kwarg separation ([#156](https://github.com/mercadopago/sdk-ruby/pull/156))
|
|
17
|
+
|
|
18
|
+
### CI
|
|
19
|
+
- Standardize CI/CD workflows ([#166](https://github.com/mercadopago/sdk-ruby/pull/166))
|
|
20
|
+
- Migrate tests to mock-based unit tests ([#166](https://github.com/mercadopago/sdk-ruby/pull/166))
|
|
21
|
+
- Fix SDK bugs discovered during mock test migration ([#166](https://github.com/mercadopago/sdk-ruby/pull/166))
|
|
22
|
+
- Fix Ruby CI: drop 3.2 matrix (gemspec requires >=3.3), add `safe.directory` ([#166](https://github.com/mercadopago/sdk-ruby/pull/166))
|
|
23
|
+
|
|
8
24
|
## [3.3.0] - 2026-08-04
|
|
9
25
|
|
|
10
26
|
### Added
|
data/Gemfile.lock
CHANGED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
require_relative '../../lib/mercadopago'
|
|
2
|
+
|
|
3
|
+
# Mercado Pago Create Order — Automatic Payments (recurring charges).
|
|
4
|
+
#
|
|
5
|
+
# Demonstrates the two-step Automatic Payments flow:
|
|
6
|
+
# 1. First payment — CVV-validated charge that registers the card credential.
|
|
7
|
+
# 2. Recurring charge — subsequent MIT charge without CVV, referencing step 1.
|
|
8
|
+
#
|
|
9
|
+
# Prerequisites:
|
|
10
|
+
# - A customer created via POST /v1/customers → customer_id
|
|
11
|
+
# - A payment profile created via POST /v1/customers/{id}/payment-profiles → payment_profile_id
|
|
12
|
+
|
|
13
|
+
sdk = Mercadopago::SDK.new('<ACCESS_TOKEN>')
|
|
14
|
+
|
|
15
|
+
# ── Step 1: First payment ─────────────────────────────────────────────────────
|
|
16
|
+
# Registers the card credential with first_payment: true.
|
|
17
|
+
# No prev_transaction_ref is needed on the first charge.
|
|
18
|
+
def create_first_payment(sdk, customer_id:, payment_profile_id:, payer_email:, card_token:)
|
|
19
|
+
request = {
|
|
20
|
+
type: 'online',
|
|
21
|
+
processing_mode: 'automatic',
|
|
22
|
+
total_amount: '100.00',
|
|
23
|
+
external_reference: 'subscription-001-payment-1',
|
|
24
|
+
payer: {
|
|
25
|
+
email: payer_email,
|
|
26
|
+
customer_id: customer_id
|
|
27
|
+
},
|
|
28
|
+
transactions: {
|
|
29
|
+
payments: [
|
|
30
|
+
{
|
|
31
|
+
amount: '100.00',
|
|
32
|
+
payment_method: {
|
|
33
|
+
id: 'master',
|
|
34
|
+
type: 'credit_card',
|
|
35
|
+
token: card_token,
|
|
36
|
+
installments: 1
|
|
37
|
+
},
|
|
38
|
+
automatic_payments: {
|
|
39
|
+
payment_profile_id: payment_profile_id
|
|
40
|
+
},
|
|
41
|
+
stored_credential: {
|
|
42
|
+
payment_initiator: 'customer',
|
|
43
|
+
reason: 'recurring',
|
|
44
|
+
first_payment: true
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
custom_headers = { 'X-Idempotency-Key': '<IDEMPOTENCY_KEY_FIRST>' }
|
|
52
|
+
request_options = Mercadopago::RequestOptions.new(custom_headers: custom_headers)
|
|
53
|
+
|
|
54
|
+
sdk.order.create(request, request_options: request_options)
|
|
55
|
+
rescue StandardError => e
|
|
56
|
+
puts e.message
|
|
57
|
+
nil
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# ── Step 2: Recurring charge ──────────────────────────────────────────────────
|
|
61
|
+
# Subsequent MIT charge — no card token needed, uses the payment profile.
|
|
62
|
+
# prev_transaction_ref links this charge to the original authorization.
|
|
63
|
+
def create_recurring_charge(sdk,
|
|
64
|
+
customer_id:,
|
|
65
|
+
payment_profile_id:,
|
|
66
|
+
payer_email:,
|
|
67
|
+
previous_transaction_reference:,
|
|
68
|
+
sequence_number:)
|
|
69
|
+
request = {
|
|
70
|
+
type: 'online',
|
|
71
|
+
processing_mode: 'automatic_async',
|
|
72
|
+
total_amount: '100.00',
|
|
73
|
+
external_reference: "subscription-001-payment-#{sequence_number}",
|
|
74
|
+
payer: {
|
|
75
|
+
email: payer_email,
|
|
76
|
+
customer_id: customer_id
|
|
77
|
+
},
|
|
78
|
+
transactions: {
|
|
79
|
+
payments: [
|
|
80
|
+
{
|
|
81
|
+
amount: '100.00',
|
|
82
|
+
automatic_payments: {
|
|
83
|
+
payment_profile_id: payment_profile_id,
|
|
84
|
+
retries: 3,
|
|
85
|
+
schedule_date: '2026-09-01T00:00:00.000-04:00',
|
|
86
|
+
due_date: '2026-09-05T00:00:00.000-04:00'
|
|
87
|
+
},
|
|
88
|
+
stored_credential: {
|
|
89
|
+
payment_initiator: 'merchant',
|
|
90
|
+
reason: 'recurring',
|
|
91
|
+
first_payment: false,
|
|
92
|
+
previous_transaction_reference: previous_transaction_reference
|
|
93
|
+
},
|
|
94
|
+
subscription_data: {
|
|
95
|
+
invoice_id: "INV-00#{sequence_number}",
|
|
96
|
+
billing_date: '2026-08-01',
|
|
97
|
+
subscription_sequence: {
|
|
98
|
+
number: sequence_number,
|
|
99
|
+
total: 12
|
|
100
|
+
},
|
|
101
|
+
invoice_period: {
|
|
102
|
+
type: 'monthly',
|
|
103
|
+
period: 1
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
custom_headers = { 'X-Idempotency-Key': "<IDEMPOTENCY_KEY_RECURRING_#{sequence_number}>" }
|
|
112
|
+
request_options = Mercadopago::RequestOptions.new(custom_headers: custom_headers)
|
|
113
|
+
|
|
114
|
+
sdk.order.create(request, request_options: request_options)
|
|
115
|
+
rescue StandardError => e
|
|
116
|
+
puts e.message
|
|
117
|
+
nil
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# ── Run the flow ──────────────────────────────────────────────────────────────
|
|
121
|
+
customer_id = '<CUSTOMER_ID>'
|
|
122
|
+
payment_profile_id = '<PAYMENT_PROFILE_ID>'
|
|
123
|
+
payer_email = '<PAYER_EMAIL>'
|
|
124
|
+
card_token = '<CARD_TOKEN>'
|
|
125
|
+
|
|
126
|
+
# First payment
|
|
127
|
+
first_result = create_first_payment(
|
|
128
|
+
sdk,
|
|
129
|
+
customer_id: customer_id,
|
|
130
|
+
payment_profile_id: payment_profile_id,
|
|
131
|
+
payer_email: payer_email,
|
|
132
|
+
card_token: card_token
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
if first_result
|
|
136
|
+
first_order = first_result[:response]
|
|
137
|
+
puts "First payment order ID: #{first_order['id']}"
|
|
138
|
+
puts "Status: #{first_order['status']}"
|
|
139
|
+
|
|
140
|
+
# Save the payment ID for the next recurring charge
|
|
141
|
+
first_payment_id = first_order.dig('transactions', 'payments', 0, 'id')
|
|
142
|
+
puts "First payment ID (save for next charge): #{first_payment_id}"
|
|
143
|
+
|
|
144
|
+
# Recurring charge
|
|
145
|
+
if first_payment_id
|
|
146
|
+
recurring_result = create_recurring_charge(
|
|
147
|
+
sdk,
|
|
148
|
+
customer_id: customer_id,
|
|
149
|
+
payment_profile_id: payment_profile_id,
|
|
150
|
+
payer_email: payer_email,
|
|
151
|
+
previous_transaction_reference: first_payment_id,
|
|
152
|
+
sequence_number: 2
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
if recurring_result
|
|
156
|
+
recurring_order = recurring_result[:response]
|
|
157
|
+
puts "\nRecurring charge order ID: #{recurring_order['id']}"
|
|
158
|
+
puts "Status: #{recurring_order['status']}"
|
|
159
|
+
puts "Status detail: #{recurring_order['status_detail']}"
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
@@ -23,7 +23,7 @@ module Mercadopago
|
|
|
23
23
|
# @param request_options [RequestOptions, nil] per-call configuration override
|
|
24
24
|
# @return [Hash{Symbol => Object}] +:status+ and +:response+ with refund details
|
|
25
25
|
def create_all(advanced_payment_id, request_options: nil)
|
|
26
|
-
_post(uri: "/v1/advanced_payments/#{_path_param(advanced_payment_id)}/refunds", request_options: request_options)
|
|
26
|
+
_post(uri: "/v1/advanced_payments/#{_path_param(advanced_payment_id)}/refunds", data: nil, request_options: request_options)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
# Refunds a single disbursement (full or partial).
|