abacatepay-ruby 0.1.0 → 1.0.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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +125 -0
  3. data/CHANGELOG.md +121 -1
  4. data/README.md +408 -87
  5. data/Rakefile +1 -1
  6. data/abacatepay-ruby.gemspec +16 -10
  7. data/lib/abacate_pay/clients/billing_client.rb +80 -0
  8. data/lib/abacate_pay/clients/checkout_client.rb +70 -0
  9. data/lib/{abacatepay → abacate_pay}/clients/client.rb +20 -7
  10. data/lib/abacate_pay/clients/coupon_client.rb +57 -0
  11. data/lib/abacate_pay/clients/customer_client.rb +58 -0
  12. data/lib/abacate_pay/clients/payment_link_client.rb +71 -0
  13. data/lib/abacate_pay/clients/payout_client.rb +41 -0
  14. data/lib/abacate_pay/clients/pix_client.rb +47 -0
  15. data/lib/abacate_pay/clients/product_client.rb +54 -0
  16. data/lib/abacate_pay/clients/store_client.rb +40 -0
  17. data/lib/abacate_pay/clients/subscription_client.rb +55 -0
  18. data/lib/abacate_pay/clients/transparent_client.rb +73 -0
  19. data/lib/abacate_pay/clients/webhook_client.rb +82 -0
  20. data/lib/abacate_pay/clients.rb +24 -0
  21. data/lib/abacate_pay/configuration.rb +67 -0
  22. data/lib/{abacatepay/enums/billing → abacate_pay/enums/billings}/frequencies.rb +9 -3
  23. data/lib/{abacatepay/enums/billing → abacate_pay/enums/billings}/methods.rb +5 -3
  24. data/lib/{abacatepay/enums/billing → abacate_pay/enums/billings}/statuses.rb +3 -2
  25. data/lib/abacate_pay/enums/checkouts/statuses.rb +29 -0
  26. data/lib/abacate_pay/enums/coupons/discount_kinds.rb +26 -0
  27. data/lib/abacate_pay/enums/coupons/statuses.rb +27 -0
  28. data/lib/abacate_pay/enums/payouts/statuses.rb +29 -0
  29. data/lib/abacate_pay/enums/pix/key_types.rb +30 -0
  30. data/lib/abacate_pay/enums/products/cycles.rb +28 -0
  31. data/lib/abacate_pay/enums/transfers/statuses.rb +30 -0
  32. data/lib/abacate_pay/enums/webhooks/event_types.rb +43 -0
  33. data/lib/abacate_pay/enums.rb +20 -0
  34. data/lib/{abacatepay/resources/billing → abacate_pay/resources/billings}/metadata.rb +2 -8
  35. data/lib/{abacatepay/resources/billing → abacate_pay/resources/billings}/product.rb +2 -8
  36. data/lib/{abacatepay/resources/billing.rb → abacate_pay/resources/billings.rb} +16 -16
  37. data/lib/abacate_pay/resources/checkouts.rb +76 -0
  38. data/lib/abacate_pay/resources/coupons.rb +41 -0
  39. data/lib/{abacatepay/resources/customer → abacate_pay/resources/customers}/metadata.rb +2 -8
  40. data/lib/{abacatepay/resources/customer.rb → abacate_pay/resources/customers.rb} +5 -5
  41. data/lib/abacate_pay/resources/payouts.rb +40 -0
  42. data/lib/abacate_pay/resources/pix_transfers.rb +41 -0
  43. data/lib/abacate_pay/resources/products.rb +40 -0
  44. data/lib/{abacatepay → abacate_pay}/resources/resource.rb +33 -21
  45. data/lib/abacate_pay/resources/store/balance.rb +20 -0
  46. data/lib/abacate_pay/resources/store.rb +36 -0
  47. data/lib/abacate_pay/resources/subscriptions.rb +72 -0
  48. data/lib/abacate_pay/resources/transparents.rb +46 -0
  49. data/lib/abacate_pay/resources/webhook_endpoints.rb +49 -0
  50. data/lib/abacate_pay/resources.rb +27 -0
  51. data/lib/{abacatepay → abacate_pay}/version.rb +2 -2
  52. data/lib/abacate_pay/webhooks/event.rb +20 -0
  53. data/lib/abacate_pay/webhooks.rb +100 -0
  54. data/lib/abacate_pay.rb +111 -4
  55. metadata +69 -56
  56. data/lib/abacatepay/clients/billing_client.rb +0 -60
  57. data/lib/abacatepay/clients/customer_client.rb +0 -39
  58. data/lib/abacatepay/clients.rb +0 -12
  59. data/lib/abacatepay/configuration.rb +0 -56
  60. data/lib/abacatepay/enums.rb +0 -12
  61. data/lib/abacatepay/resources.rb +0 -15
  62. data/sig/abacatepay/rails.rbs +0 -6
data/README.md CHANGED
@@ -1,121 +1,239 @@
1
- # AbacatePay SDK for Ruby on Rails
1
+ <div align="center">
2
2
 
3
- ## 💻 Installation
3
+ # AbacatePay Ruby SDK
4
4
 
5
- Add this line to your application's Gemfile:
5
+ SDK oficial da **AbacatePay** para integrar pagamentos via **PIX** de forma simples, segura e idiomática em Ruby.
6
6
 
7
- ```ruby
8
- gem 'abacatepay-ruby'
9
- ```
7
+ O [`abacatepay-ruby`](https://rubygems.org/gems/abacatepay-ruby) é um **wrapper versionado de alto nível** sobre a API da AbacatePay, focado em **DX**, **verificação segura de webhooks** e **erros tipados**.
10
8
 
11
- And then execute:
9
+ <img src="https://res.cloudinary.com/dkok1obj5/image/upload/v1767631413/avo_clhmaf.png" width="100%" alt="AbacatePay Open Source"/>
12
10
 
13
- ```bash
14
- bundle install
15
- ```
11
+ Funciona em qualquer aplicação Ruby — Rails, Sinatra, Hanami ou Ruby puro.
16
12
 
17
- Or install it yourself as:
13
+ Referência completa da API [aqui](https://abacatepay.readme.io/reference).
14
+
15
+ ## Requisitos
16
+
17
+ Ruby **3.2 ou superior**. Testado em 3.2, 3.3, 3.4 e 4.0.
18
+
19
+ ## Instalação
20
+
21
+ </div>
18
22
 
19
23
  ```bash
20
- gem install abacatepay-ruby
24
+ bundle add abacatepay-ruby
21
25
  ```
22
26
 
23
- ## 🔧 Configuration
27
+ <div align="center">
28
+
29
+ Ou adicione ao seu `Gemfile`:
24
30
 
25
- Configure your API token and environment in an initializer:
31
+ </div>
26
32
 
27
33
  ```ruby
28
- # config/initializers/abacatepay.rb
29
- AbacatePay.configure do |config|
30
- config.api_token = ENV['ABACATEPAY_TOKEN']
31
- config.environment = :sandbox # or :production
32
- end
34
+ gem 'abacatepay-ruby'
33
35
  ```
34
36
 
35
- ## 🌟 Resources
37
+ <div align="center">
36
38
 
37
- ### Billing
39
+ ## Uso básico
38
40
 
39
- **Initialize the Billing Client**
41
+ </div>
40
42
 
41
43
  ```ruby
42
- billing_client = AbacatePay::Clients::BillingClient.new
44
+ AbacatePay.configure do |config|
45
+ config.api_token = ENV['ABACATEPAY_TOKEN']
46
+ config.timeout = 30 # opcional, em segundos
47
+ end
43
48
  ```
44
49
 
45
- **List Billings**
50
+ <div align="center">
46
51
 
47
- Retrieve a list of all billings:
52
+ Nunca utilize sua API key diretamente no código.
53
+ **Sempre use variáveis de ambiente**.
48
54
 
49
- ```ruby
50
- billing_client.list
51
- ```
55
+ Em Rails, coloque isso em `config/initializers/abacatepay.rb`.
56
+
57
+ Trocar o token em runtime tem efeito imediato — os clients são reconstruídos a cada `configure`.
52
58
 
53
- **Create a Billing**
59
+ ### Criando uma cobrança
54
60
 
55
- To create a billing, use the following code:
61
+ </div>
56
62
 
57
63
  ```ruby
58
- billing_client.create(
59
- AbacatePay::Resources::Billing.new(
60
- frequency: AbacatePay::Enums::Billing::Frequencies::ONE_TIME,
61
- methods: [AbacatePay::Enums::Billing::Methods::PIX],
64
+ checkout = AbacatePay.checkouts.create(
65
+ AbacatePay::Resources::Checkouts.new(
66
+ frequency: 'ONE_TIME',
67
+ methods: ['PIX'],
62
68
  products: [
63
- AbacatePay::Resources::Billing::Product.new(
64
- external_id: 'abc_123',
69
+ AbacatePay::Resources::Billings::Product.new(
70
+ external_id: 'prod_123',
65
71
  name: 'Product A',
66
- description: 'Description of product A',
67
72
  quantity: 1,
68
- price: 100 # Price in cents
73
+ price: 100
69
74
  )
70
75
  ],
71
- metadata: AbacatePay::Resources::Billing::Metadata.new(
72
- return_url: 'https://www.abacatepay.com',
73
- completion_url: 'https://www.abacatepay.com'
74
- ),
75
- customer: AbacatePay::Resources::Customer.new(
76
- metadata: AbacatePay::Resources::Customer::Metadata.new(
77
- name: 'Abacate Lover',
78
- cellphone: '01912341234',
79
- email: 'lover@abacate.com',
80
- tax_id: '13827826837'
81
- )
82
- )
76
+ customer: AbacatePay::Resources::Customers.new(id: 'cust_123')
83
77
  )
84
78
  )
85
79
  ```
86
80
 
87
- Alternatively, you can use a previously created customer by specifying their ID:
81
+ <div align="center">
82
+
83
+ ### Procure por alguns clientes
84
+
85
+ </div>
88
86
 
89
87
  ```ruby
90
- AbacatePay::Resources::Customer.new(
91
- id: 'cust_DEbpqcN...'
92
- )
88
+ customers = AbacatePay.customers.list(limit: 25)
89
+ ```
90
+
91
+ <div align="center">
92
+
93
+ Todos os métodos `list` aceitam parâmetros de paginação e filtro opcionais:
94
+
95
+ </div>
96
+
97
+ ```ruby
98
+ AbacatePay.customers.list(limit: 10, after: 'cursor_abc')
99
+ AbacatePay.checkouts.list(status: 'PAID', email: 'user@example.com')
100
+ ```
101
+
102
+ <div align="center">
103
+
104
+ ## Versionamento
105
+
106
+ O SDK fala **exclusivamente a v2** — `https://api.abacatepay.com/v2`. A v1 foi desligada pela AbacatePay e responde `{"error":"Not found"}` em toda rota, então não há o que negociar.
107
+
108
+ O ambiente (dev mode x produção) é definido **pela chave de API**, não por configuração: chaves de Dev mode geram transações simuladas. Por isso `config.environment` não faz nada — ela continua aceita para não quebrar initializers existentes, mas emite aviso de depreciação.
109
+
110
+ O `BillingClient` também está descontinuado, substituído pelo `CheckoutClient`. Ele emite um aviso ao ser instanciado, e seus endpoints `/billings/*` não existem na v2:
111
+
112
+ </div>
113
+
114
+ ```
115
+ [DEPRECATION] BillingClient is deprecated. Use CheckoutClient instead.
93
116
  ```
94
117
 
95
- ### Customer
118
+ <div align="center">
96
119
 
97
- **Initialize the Customer Client**
120
+ ## Tratamento de erros
121
+
122
+ Diferente do SDK de Node, **este SDK levanta exceções** — ele não retorna `{ data, error, success }`. Toda falha vira uma exceção tipada que herda de `AbacatePay::Error`, então você pode capturar tudo de uma vez ou tratar caso a caso.
123
+
124
+ </div>
98
125
 
99
126
  ```ruby
100
- customer_client = AbacatePay::Clients::CustomerClient.new
127
+ begin
128
+ checkout = AbacatePay.checkouts.create(data)
129
+ rescue AbacatePay::ConfigurationError => e
130
+ # token ausente ou vazio
131
+ rescue AbacatePay::ApiError => e
132
+ # a API recusou a chamada, ou houve falha de rede/timeout
133
+ Rails.logger.error(e.message)
134
+ end
101
135
  ```
102
136
 
103
- **List Customers**
137
+ <div align="center">
138
+
139
+ | Exceção | Quando acontece |
140
+ |---|---|
141
+ | `AbacatePay::ConfigurationError` | Token ausente ou vazio |
142
+ | `AbacatePay::ApiError` | Erro da API, falha de rede ou timeout |
143
+ | `AbacatePay::Webhooks::SignatureError` | Assinatura de webhook ausente, vazia ou inválida |
144
+ | `AbacatePay::Webhooks::PayloadError` | Corpo do webhook malformado ou que não é um objeto JSON |
145
+
146
+ Erros de rede e timeout são normalizados para `ApiError`, com a mensagem da API preservada quando ela envia uma.
147
+
148
+ ## Webhooks
104
149
 
105
- Retrieve a list of all customers:
150
+ Endpoints de webhook são públicos e não autenticados. Use `construct_event`, que **verifica a assinatura antes de fazer o parse** — é o único ponto de entrada que não permite agir sobre um payload não verificado.
151
+
152
+ </div>
106
153
 
107
154
  ```ruby
108
- customer_client.list
155
+ payload = request.body.read
156
+ signature = request.headers['X-Webhook-Signature']
157
+ secret = ENV['ABACATEPAY_WEBHOOK_SECRET']
158
+
159
+ begin
160
+ event = AbacatePay::Webhooks.construct_event(
161
+ payload: payload, signature: signature, secret: secret
162
+ )
163
+ rescue AbacatePay::Webhooks::SignatureError
164
+ return head :unauthorized
165
+ rescue AbacatePay::Webhooks::PayloadError
166
+ return head :bad_request
167
+ end
168
+
169
+ case event.type
170
+ when 'checkout.completed' then handle_payment(event.data)
171
+ when 'checkout.refunded' then handle_refund(event.data)
172
+ when 'subscription.renewed' then handle_renewal(event.data)
173
+ end
109
174
  ```
110
175
 
111
- **Create a Customer**
176
+ <div align="center">
177
+
178
+ Header ausente, secret vazio, assinatura forjada e corpo malformado são todos tratados como casos esperados — levantam erro tipado em vez de derrubar o endpoint. A comparação de assinatura é feita em tempo constante.
179
+
180
+ Os métodos de baixo nível continuam disponíveis:
112
181
 
113
- To create a customer, use the following code:
182
+ </div>
114
183
 
115
184
  ```ruby
116
- customer_client.create(
117
- AbacatePay::Resources::Customer.new(
118
- metadata: AbacatePay::Resources::Customer::Metadata.new(
185
+ # Levanta SignatureError se a assinatura estiver ausente ou inválida
186
+ AbacatePay::Webhooks.verify!(payload: payload, signature: signature, secret: secret)
187
+
188
+ # Contraparte booleana — nunca levanta exceção
189
+ AbacatePay::Webhooks.valid?(payload: payload, signature: signature, secret: secret)
190
+
191
+ # Faz parse de um corpo já verificado
192
+ AbacatePay::Webhooks.parse(payload)
193
+ ```
194
+
195
+ <div align="center">
196
+
197
+ ### Eventos disponíveis
198
+
199
+ | Categoria | Eventos |
200
+ |---|---|
201
+ | Checkout | `checkout.completed`, `checkout.refunded`, `checkout.disputed` |
202
+ | Transparent | `transparent.completed`, `transparent.refunded`, `transparent.disputed` |
203
+ | Subscription | `subscription.completed`, `subscription.renewed`, `subscription.cancelled` |
204
+ | Transfer | `transfer.completed`, `transfer.failed` |
205
+ | Payout | `payout.completed`, `payout.failed` |
206
+
207
+ ## Recursos
208
+
209
+ Todos os recursos são acessíveis pela fachada `AbacatePay.<recurso>`.
210
+
211
+ | Recurso | Métodos |
212
+ |---|---|
213
+ | `customers` | `list` `get` `create` `delete` |
214
+ | `products` | `list` `get` `create` `delete` |
215
+ | `coupons` | `list` `get` `create` `delete` `toggle` |
216
+ | `checkouts` | `list` `get` `create` `refund` |
217
+ | `subscriptions` | `list` `create` `cancel` |
218
+ | `transparents` | `list` `create` `check` `simulate_payment` `refund` |
219
+ | `pix` | `list` `get` `send_pix` |
220
+ | `payouts` | `list` `get` `create` |
221
+ | `store` | `get` `merchant_info` `mrr` `revenue` |
222
+ | `payment_links` | `list` `get` `create` `refund` |
223
+ | `webhook_endpoints` | `list` `get` `create` `delete` |
224
+
225
+ ### Clientes
226
+
227
+ </div>
228
+
229
+ ```ruby
230
+ AbacatePay.customers.list
231
+ AbacatePay.customers.get('cust_123')
232
+ AbacatePay.customers.delete('cust_123')
233
+
234
+ AbacatePay.customers.create(
235
+ AbacatePay::Resources::Customers.new(
236
+ metadata: AbacatePay::Resources::Customers::Metadata.new(
119
237
  name: 'Abacate Lover',
120
238
  cellphone: '01912341234',
121
239
  email: 'lover@abacate.com',
@@ -125,42 +243,245 @@ customer_client.create(
125
243
  )
126
244
  ```
127
245
 
128
- ## 📚 Documentation
246
+ <div align="center">
247
+
248
+ ### Produtos
249
+
250
+ </div>
251
+
252
+ ```ruby
253
+ AbacatePay.products.create(
254
+ AbacatePay::Resources::Products.new(
255
+ external_id: 'my-product-1',
256
+ name: 'Monthly Plan',
257
+ price: 2990, # R$ 29,90 em centavos
258
+ currency: 'BRL',
259
+ description: 'Acesso a todos os recursos',
260
+ cycle: 'MONTHLY' # ou nil para pagamento único
261
+ )
262
+ )
263
+ ```
129
264
 
130
- For detailed information about the API and SDK, refer to the official documentation:
131
- https://abacatepay.readme.io/reference
265
+ <div align="center">
132
266
 
133
- ## 🤝 Contribution
267
+ ### Cupons
134
268
 
135
- Contributions are welcome! If you wish to contribute:
269
+ </div>
136
270
 
137
- 1. Fork the repository
138
- 2. Create a new branch for your feature or fix:
271
+ ```ruby
272
+ AbacatePay.coupons.create(
273
+ AbacatePay::Resources::Coupons.new(
274
+ code: 'SAVE20',
275
+ discount: 20,
276
+ discount_kind: 'PERCENTAGE', # ou 'FIXED'
277
+ max_redeems: 100
278
+ )
279
+ )
139
280
 
140
- ```bash
141
- git checkout -b feature/your-feature-name
281
+ AbacatePay.coupons.toggle('coup_123')
142
282
  ```
143
283
 
144
- 3. Make your changes and commit them:
284
+ <div align="center">
145
285
 
146
- ```bash
147
- git commit -m "Add your detailed commit message here"
286
+ ### Assinaturas
287
+
288
+ Exigem exatamente um produto com `cycle` definido.
289
+
290
+ </div>
291
+
292
+ ```ruby
293
+ AbacatePay.subscriptions.create(
294
+ AbacatePay::Resources::Subscriptions.new(
295
+ methods: ['PIX'],
296
+ customer: AbacatePay::Resources::Customers.new(id: 'cust_123'),
297
+ products: [
298
+ AbacatePay::Resources::Billings::Product.new(
299
+ external_id: 'plan-monthly',
300
+ name: 'Monthly Plan',
301
+ price: 2990,
302
+ quantity: 1
303
+ )
304
+ ]
305
+ )
306
+ )
307
+ ```
308
+
309
+ <div align="center">
310
+
311
+ ### PIX transparente (QR Code)
312
+
313
+ </div>
314
+
315
+ ```ruby
316
+ AbacatePay.transparents.create(
317
+ AbacatePay::Resources::Transparents.new(
318
+ amount: 1000,
319
+ description: 'Pedido #123',
320
+ expires_in: 3600
321
+ )
322
+ )
323
+
324
+ AbacatePay.transparents.check('tr_123')
325
+ AbacatePay.transparents.simulate_payment('tr_123') # apenas em dev mode
326
+ ```
327
+
328
+ <div align="center">
329
+
330
+ ### Transferências PIX
331
+
332
+ </div>
333
+
334
+ ```ruby
335
+ AbacatePay.pix.send_pix(
336
+ AbacatePay::Resources::PixTransfers.new(
337
+ amount: 500,
338
+ external_id: 'transfer-001',
339
+ description: 'Pagamento ao fornecedor',
340
+ key: '12345678900',
341
+ key_type: 'CPF' # CPF, CNPJ, PHONE, EMAIL, RANDOM, BR_CODE
342
+ )
343
+ )
344
+ ```
345
+
346
+ <div align="center">
347
+
348
+ ### Saques
349
+
350
+ Valor mínimo de R$ 3,50.
351
+
352
+ </div>
353
+
354
+ ```ruby
355
+ AbacatePay.payouts.create(
356
+ AbacatePay::Resources::Payouts.new(
357
+ amount: 5000,
358
+ external_id: 'withdrawal-001',
359
+ description: 'Saque mensal'
360
+ )
361
+ )
362
+ ```
363
+
364
+ <div align="center">
365
+
366
+ ### Links de pagamento
367
+
368
+ Um link reutilizável, pago por vários clientes de forma independente — vendas em massa, rifas, formulários de inscrição. Para uma cobrança por cliente, use `checkouts`.
369
+
370
+ </div>
371
+
372
+ ```ruby
373
+ link = AbacatePay.payment_links.create(
374
+ AbacatePay::Resources::Checkouts.new(
375
+ methods: ['PIX', 'CARD'],
376
+ external_id: 'campanha-black-friday',
377
+ products: [
378
+ AbacatePay::Resources::Billings::Product.new(external_id: 'prod_123', quantity: 1)
379
+ ]
380
+ )
381
+ )
382
+
383
+ puts link.url # compartilhe esta URL
148
384
  ```
149
385
 
150
- 4. Push to your branch:
386
+ <div align="center">
387
+
388
+ ### Estornos
389
+
390
+ O estorno é sempre integral — a AbacatePay não faz estorno parcial.
391
+
392
+ </div>
393
+
394
+ ```ruby
395
+ AbacatePay.checkouts.refund('bill_abc123xyz')
396
+ AbacatePay.transparents.refund('pix_char_abc123xyz')
397
+ AbacatePay.payment_links.refund('char_abc123xyz')
398
+ ```
399
+
400
+ <div align="center">
401
+
402
+ ### Cancelar assinatura
403
+
404
+ Cancela imediatamente; parcelas futuras pendentes são canceladas junto.
405
+
406
+ </div>
407
+
408
+ ```ruby
409
+ AbacatePay.subscriptions.cancel('subs_abc123xyz')
410
+ ```
411
+
412
+ <div align="center">
413
+
414
+ ### Registro de webhooks
415
+
416
+ Isto gerencia **para onde** a AbacatePay entrega os eventos. Para verificar uma entrega recebida, use `Webhooks.construct_event`.
417
+
418
+ </div>
419
+
420
+ ```ruby
421
+ AbacatePay.webhook_endpoints.create(
422
+ name: 'Pagamentos',
423
+ endpoint: 'https://meusite.com/webhooks/abacatepay', # precisa ser HTTPS
424
+ secret: ENV['ABACATEPAY_WEBHOOK_SECRET'],
425
+ events: ['checkout.completed', 'subscription.renewed']
426
+ )
427
+
428
+ AbacatePay.webhook_endpoints.list
429
+ AbacatePay.webhook_endpoints.delete('wh_123')
430
+ ```
431
+
432
+ <div align="center">
433
+
434
+ ### Loja
435
+
436
+ </div>
437
+
438
+ ```ruby
439
+ store = AbacatePay.store.get
440
+ store.balance.available # => 10000
441
+ store.balance.pending # => 500
442
+ store.balance.blocked # => 0
443
+
444
+ AbacatePay.store.revenue(start_date: '2026-01-01', end_date: '2026-03-30')
445
+ ```
446
+
447
+ <div align="center">
448
+
449
+ ## Enums
450
+
451
+ Os valores são validados na construção do recurso — um valor inválido levanta `ArgumentError` antes de qualquer chamada de rede.
452
+
453
+ | Enum | Valores |
454
+ |---|---|
455
+ | `Billings::Methods` | `PIX`, `CARD` |
456
+ | `Billings::Frequencies` | `ONE_TIME`, `WEEKLY`, `MONTHLY`, `SEMIANNUALLY`, `ANNUALLY`, `MULTIPLE_PAYMENTS` |
457
+ | `Billings::Statuses` | `PENDING`, `EXPIRED`, `CANCELLED`, `PAID`, `REFUNDED` |
458
+ | `Products::Cycles` | `WEEKLY`, `MONTHLY`, `SEMIANNUALLY`, `ANNUALLY` |
459
+ | `Coupons::Statuses` | `ACTIVE`, `INACTIVE`, `EXPIRED` |
460
+ | `Coupons::DiscountKinds` | `PERCENTAGE`, `FIXED` |
461
+ | `Pix::KeyTypes` | `CPF`, `CNPJ`, `PHONE`, `EMAIL`, `RANDOM`, `BR_CODE` |
462
+ | `Transfers::Statuses` | `PENDING`, `COMPLETE`, `CANCELLED`, `EXPIRED`, `REFUNDED`, `FAILED` |
463
+ | `Payouts::Statuses` | `PENDING`, `COMPLETE`, `CANCELLED`, `EXPIRED`, `REFUNDED` |
464
+
465
+ ## Contribuindo
466
+
467
+ </div>
151
468
 
152
469
  ```bash
153
- git push origin feature/your-feature-name
470
+ git clone https://github.com/AbacatePay/abacatepay-ruby-sdk.git
471
+ cd abacatepay-ruby-sdk
472
+ bundle install
473
+ bundle exec rake # specs + rubocop
154
474
  ```
155
475
 
156
- 5. Open a pull request with a clear description of your changes
476
+ <div align="center">
477
+
478
+ Antes de abrir um PR, garanta que `bundle exec rake` passa e que a cobertura não caiu — o CI roda os specs em Ruby 3.2, 3.3, 3.4 e 4.0, mais RuboCop, auditoria de dependências e build do gem.
479
+
480
+ ## Licença
157
481
 
158
- Please ensure your code:
482
+ MIT
159
483
 
160
- - Includes proper documentation
161
- - Follows Ruby style guidelines
162
- - Includes appropriate tests
163
- - Passes all existing tests (bundle exec rspec)
164
- - Passes code style checks (bundle exec rubocop)
484
+ Feito com 🥑 pela equipe AbacatePay</br>
485
+ Open source, de verdade.
165
486
 
166
- ### Happy coding! 🚀
487
+ </div>
data/Rakefile CHANGED
@@ -7,4 +7,4 @@ require "rubocop/rake_task"
7
7
  RSpec::Core::RakeTask.new(:spec)
8
8
  RuboCop::RakeTask.new
9
9
 
10
- task default: %i[spec rubocop]
10
+ task default: %i[spec rubocop]
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "lib/abacatepay/version"
3
+ require_relative "lib/abacate_pay/version"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "abacatepay-ruby"
@@ -8,17 +8,21 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ["Matheus Cardoso"]
9
9
  spec.email = ["mathuscardoso@gmail.com"]
10
10
 
11
- spec.summary = "AbacatePay Ruby on Rails SDK for you to start receiving payments in seconds"
12
- spec.description = "The easiest way to integrate your Ruby on Rails SDK base code to AbacatePay Gateway with support to coroutines."
11
+ spec.summary = "AbacatePay Ruby SDK for you to start receiving payments in seconds"
12
+ spec.description = "The easiest way to integrate your Ruby application with AbacatePay Gateway " \
13
+ "for payments, subscriptions, PIX transfers, and more."
13
14
  spec.homepage = "https://www.abacatepay.com/"
14
15
  spec.license = "MIT"
15
- spec.required_ruby_version = ">= 2.6.0"
16
+ # faraday 2.x requires Ruby >= 3.0 and the pinned Bundler requires >= 3.2.
17
+ # 3.2 is the oldest version exercised by CI; 2.6 was never actually installable.
18
+ spec.required_ruby_version = ">= 3.2.0"
16
19
 
17
- # spec.metadata["allowed_push_host"] = "https://github.com/AbacatePay/abacatepay-ruby-sdk"
20
+ # spec.metadata["allowed_push_host"] = "https://rubygems.pkg.github.com/AbacatePay"
18
21
 
19
22
  spec.metadata["homepage_uri"] = spec.homepage
20
23
  spec.metadata["source_code_uri"] = "https://github.com/AbacatePay/abacatepay-ruby-sdk"
21
24
  spec.metadata["changelog_uri"] = "https://github.com/AbacatePay/abacatepay-ruby-sdk/blob/main/CHANGELOG.md"
25
+ spec.metadata["rubygems_mfa_required"] = "true"
22
26
 
23
27
  # Specify which files should be added to the gem when it is released.
24
28
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -33,14 +37,16 @@ Gem::Specification.new do |spec|
33
37
  spec.require_paths = ["lib"]
34
38
 
35
39
  # Runtime dependencies
36
- spec.add_dependency "rails", "~> 7.0", ">= 7.0.0"
37
- spec.add_dependency "faraday", "~> 2.9"
40
+ # >= 2.14.3 excludes CVE-2026-54297 (stack-exhaustion DoS in
41
+ # NestedParamsEncoder). The lockfile only protects this repo — consumers are
42
+ # protected by the constraint here.
43
+ spec.add_dependency "faraday", "~> 2.14", ">= 2.14.3"
38
44
 
39
45
  # Development dependencies
40
- spec.add_development_dependency "rspec-rails", "~> 6.0"
46
+ spec.add_development_dependency "bundler-audit", "~> 0.9"
47
+ spec.add_development_dependency "rspec", "~> 3.12"
41
48
  spec.add_development_dependency "rubocop", "~> 1.57"
42
- spec.add_development_dependency "rubocop-rails", "~> 2.22"
43
- spec.add_development_dependency "rubocop-rspec", "~> 2.25"
49
+ spec.add_development_dependency "rubocop-rspec", "~> 3.0"
44
50
  spec.add_development_dependency "simplecov", "~> 0.22"
45
51
 
46
52
  # For more information and examples about making a new gem, check out our