perata-sdk 0.1.1 → 0.3.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: 64384c4af37e5af51b1adea727b0475da68c843b5c25aedb6392bd3b3cd4bc8a
4
- data.tar.gz: b87c39face8ac30151097de8cc07b5be89787420501ea236afc5f4d875f77348
3
+ metadata.gz: 4ce69fcabc384e43ef9a829c444ced516fb44a64d82daf72fd4d8b7b9ad6dab9
4
+ data.tar.gz: 43e9821c4ad1cd264bfe59fb8b3fdafabf6d44d31755d067e1e626d21fba753a
5
5
  SHA512:
6
- metadata.gz: 2cc402f3ac1361b6eaa815bc97615c7d0754486b677fe930623e83a5c7b73f454dd348b6b9f3a942ff235d42e84512580f6ad29fd9af31757cace6f1094fb62c
7
- data.tar.gz: 497bec18e6a4a0b4d1f2fd1a7aeccb289877a2cd638d8a8297008d07fd86b0d87b276a3e193532a8160a4f774418dd4da51fd4ce497c58ea554673ef04af6385
6
+ metadata.gz: 74f8e47737ccb716ff1c9d18354c97eb7260f016ade4b5c4ee4d5b3caa4ba4b676f943c1cf60d089f33eb76f63b5f724983edacc1179021e4cc2b2031adea0c2
7
+ data.tar.gz: f3e2c307da8270f8db0c41d28b1d4b78bd283e65a83c63d6e6d789c466c65be78976f7c1ce080be492f01e9fd189c1cfefee3c08f3daae08d3caf2507f773f92
data/README.md CHANGED
@@ -22,19 +22,27 @@ end
22
22
 
23
23
  | Serviço | Métodos |
24
24
  |---|---|
25
- | `perata.checkouts` | `create` |
26
- | `perata.customers` | `create`, `get`, `list`, `list_iter` |
27
- | `perata.orders` | `list`, `list_iter` |
25
+ | `perata.benefits` | `create`, `delete`, `get`, `list`, `list_iter`, `list_grants`, `list_grants_iter`, `update` |
26
+ | `perata.checkout_links` | `create`, `delete`, `get`, `list`, `list_iter`, `update` |
27
+ | `perata.checkouts` | `create`, `get`, `update` |
28
+ | `perata.customer_sessions` | `create` |
29
+ | `perata.customers` | `create`, `delete`, `get`, `get_external`, `get_state`, `list`, `list_iter`, `update`, `update_external` |
30
+ | `perata.discounts` | `create`, `delete`, `get`, `list`, `list_iter`, `update` |
31
+ | `perata.disputes` | `get`, `list`, `list_iter` |
32
+ | `perata.events` | `list`, `list_iter` |
33
+ | `perata.meters` | `get`, `list`, `list_iter` |
34
+ | `perata.orders` | `get`, `get_invoice`, `get_receipt`, `list`, `list_iter` |
28
35
  | `perata.payment_methods` | `detach`, `list`, `list_iter` |
29
36
  | `perata.payments` | `get`, `list`, `list_iter` |
30
37
  | `perata.prices` | `create`, `list`, `list_iter` |
31
- | `perata.products` | `create`, `get`, `list`, `list_iter` |
32
- | `perata.refunds` | `create` |
33
- | `perata.subscriptions` | `cancel`, `get`, `list`, `list_iter` |
38
+ | `perata.products` | `archive`, `create`, `get`, `list`, `list_iter`, `update` |
39
+ | `perata.refunds` | `create`, `list`, `list_iter` |
40
+ | `perata.subscriptions` | `cancel`, `get`, `list`, `list_iter`, `update` |
41
+ | `perata.webhooks` | `create_endpoint`, `delete_endpoint`, `get_endpoint`, `list_deliveries`, `list_deliveries_iter`, `list_endpoints`, `list_endpoints_iter`, `update_endpoint` |
34
42
 
35
43
  Os modelos são objetos imutáveis com leitores em snake_case (`payment.amount_cents`). O corpo de uma escrita é a classe de parâmetros do método (`Perata::ProductsCreateParams.new(name: "Curso")`) ou um `Hash` com os mesmos nomes; um campo opcional não informado fica fora do JSON. Os métodos `_iter` devolvem um `Enumerator` que percorre todas as páginas a partir de `page:` (ou recebem um bloco).
36
44
 
37
- As escritas aceitam `idempotency_key:`, e todas aceitam `api_key:` para usar a chave de outra organização numa chamada. `Perata::Client.new` aceita `base_url:`, `timeout:` (30 segundos) e `transport:`.
45
+ As escritas aceitam `idempotency_key:`, e todas aceitam `api_key:` para usar a chave de outra organização numa chamada. `Perata::Client.new` aceita `base_url:`, `timeout:` (30 segundos) e `transport:`. Um POST sem chave de idempotência é enviado com uma `Idempotency-Key` própria (UUID v4 aleatório, uma por chamada); passe a sua para poder repetir a mesma operação com segurança.
38
46
 
39
47
  ## Erros
40
48
 
@@ -44,8 +52,15 @@ Uma recusa da API levanta `Perata::Error`, com `status`, `code` (`invalid_reques
44
52
 
45
53
  ```ruby
46
54
  event = Perata.verify_webhook(ENV.fetch("PERATA_WEBHOOK_SECRET"), request.headers, request.raw_post)
55
+ case event
56
+ when Perata::OrderWebhookEvent then puts event.type, event.data.id, event.data.installments
57
+ when Perata::DisputeWebhookEvent then puts event.data.provider_dispute_id
58
+ when Perata::UnknownWebhookEvent then nil # um tipo que esta versão ainda não conhece: event.data é o JSON
59
+ end
47
60
  ```
48
61
 
49
62
  A assinatura é a do Standard Webhooks (`webhook-id`, `webhook-timestamp`, `webhook-signature`), com tolerância de 5 minutos. Passe o corpo cru, antes de interpretar; os cabeçalhos podem vir num `Hash` ou no env do Rack. Uma assinatura que não confere levanta `Perata::WebhookVerificationError`.
50
63
 
51
- Versão do SDK: 0.1.1 · contrato da API: 0.1.0
64
+ O evento é tipado: um tipo para cada dado que o webhook carrega (`OrderWebhookEvent` traz um `Order`, `DisputeWebhookEvent` a disputa, `IdentifiersWebhookEvent` os identificadores…), e o `type` diz o que aconteceu; um tipo que esta versão do SDK ainda não conhece chega como `UnknownWebhookEvent`, com os dados como vieram. Durante a rotação do segredo o cabeçalho traz mais de uma assinatura, e basta uma conferir. `Perata.verify_webhook_signature` só confere a assinatura.
65
+
66
+ Versão do SDK: 0.3.0 · contrato da API: 0.1.0
data/lib/perata/client.rb CHANGED
@@ -2,8 +2,10 @@
2
2
 
3
3
  # Code generated by sdk/generator. DO NOT EDIT.
4
4
 
5
+ require "ipaddr"
5
6
  require "json"
6
7
  require "net/http"
8
+ require "securerandom"
7
9
  require "uri"
8
10
 
9
11
  module Perata
@@ -30,10 +32,24 @@ module Perata
30
32
  # product = perata.products.create({ name: "Curso" })
31
33
  # perata.products.list_iter { |product| puts product.name }
32
34
  class Client
35
+ # @return [BenefitsService]
36
+ attr_reader :benefits
37
+ # @return [CheckoutLinksService]
38
+ attr_reader :checkout_links
33
39
  # @return [CheckoutsService]
34
40
  attr_reader :checkouts
41
+ # @return [CustomerSessionsService]
42
+ attr_reader :customer_sessions
35
43
  # @return [CustomersService]
36
44
  attr_reader :customers
45
+ # @return [DiscountsService]
46
+ attr_reader :discounts
47
+ # @return [DisputesService]
48
+ attr_reader :disputes
49
+ # @return [EventsService]
50
+ attr_reader :events
51
+ # @return [MetersService]
52
+ attr_reader :meters
37
53
  # @return [OrdersService]
38
54
  attr_reader :orders
39
55
  # @return [PaymentMethodsService]
@@ -48,14 +64,26 @@ module Perata
48
64
  attr_reader :refunds
49
65
  # @return [SubscriptionsService]
50
66
  attr_reader :subscriptions
67
+ # @return [WebhooksService]
68
+ attr_reader :webhooks
51
69
 
70
+ # The base URL must be https; http is accepted only for localhost,
71
+ # 127.0.0.0/8 and ::1, and any other raises ArgumentError.
52
72
  def initialize(api_key, base_url: DEFAULT_BASE_URL, timeout: 30, transport: NetHTTPTransport.new)
53
73
  @api_key = api_key
54
74
  @base_url = base_url.chomp("/")
75
+ check_base_url!(@base_url)
55
76
  @timeout = timeout
56
77
  @transport = transport
78
+ @benefits = BenefitsService.new(self)
79
+ @checkout_links = CheckoutLinksService.new(self)
57
80
  @checkouts = CheckoutsService.new(self)
81
+ @customer_sessions = CustomerSessionsService.new(self)
58
82
  @customers = CustomersService.new(self)
83
+ @discounts = DiscountsService.new(self)
84
+ @disputes = DisputesService.new(self)
85
+ @events = EventsService.new(self)
86
+ @meters = MetersService.new(self)
59
87
  @orders = OrdersService.new(self)
60
88
  @payment_methods = PaymentMethodsService.new(self)
61
89
  @payments = PaymentsService.new(self)
@@ -63,6 +91,7 @@ module Perata
63
91
  @products = ProductsService.new(self)
64
92
  @refunds = RefundsService.new(self)
65
93
  @subscriptions = SubscriptionsService.new(self)
94
+ @webhooks = WebhooksService.new(self)
66
95
  end
67
96
 
68
97
  # Calls the API and answers what it wrapped in +data+; a refusal raises
@@ -81,11 +110,35 @@ module Perata
81
110
  data = JSON.generate(body)
82
111
  headers["Content-Type"] = "application/json"
83
112
  end
113
+ # A POST is sent with a key of its own, one a call, unless the caller gave one.
114
+ idempotency_key = SecureRandom.uuid if (idempotency_key.nil? || idempotency_key.empty?) && method == "POST"
84
115
  headers["Idempotency-Key"] = idempotency_key if idempotency_key && !idempotency_key.empty?
85
116
  status, response_headers, raw = @transport.call(method, url, headers, data, @timeout)
86
117
  raise Error.from_response(status, response_headers, raw) if status >= 300
87
118
 
119
+ return nil if status == 204
120
+
88
121
  JSON.parse(raw).fetch("data")
89
122
  end
123
+
124
+ private
125
+
126
+ def check_base_url!(base_url)
127
+ uri = begin
128
+ URI.parse(base_url)
129
+ rescue URI::InvalidURIError
130
+ nil
131
+ end
132
+ scheme = uri&.scheme.to_s.downcase
133
+ host = uri&.hostname.to_s.downcase
134
+ loopback = host == "localhost" || begin
135
+ IPAddr.new(host).loopback?
136
+ rescue IPAddr::Error
137
+ false
138
+ end
139
+ return if scheme == "https" || (scheme == "http" && loopback)
140
+
141
+ raise ArgumentError, "perata: the base URL must be https (http is accepted only for localhost, 127.0.0.0/8 and ::1), so the API key is never sent in clear text"
142
+ end
90
143
  end
91
144
  end