perata-sdk 0.1.1

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.
@@ -0,0 +1,200 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Code generated by sdk/generator. DO NOT EDIT.
4
+
5
+ module Perata
6
+ # The body of checkouts:create.
7
+ class CheckoutsCreateParams < Params
8
+ MEMBERS = %i[cancel_url label price_id product_id quantity success_url].freeze
9
+
10
+ # @return [String, nil]
11
+ attr_reader :cancel_url
12
+
13
+ # @return [String, nil]
14
+ attr_reader :label
15
+
16
+ # @return [String]
17
+ attr_reader :price_id
18
+
19
+ # @return [String]
20
+ attr_reader :product_id
21
+
22
+ # @return [Integer, nil]
23
+ attr_reader :quantity
24
+
25
+ # @return [String, nil]
26
+ attr_reader :success_url
27
+
28
+ def initialize(cancel_url: nil, label: nil, price_id:, product_id:, quantity: nil, success_url: nil)
29
+ @cancel_url = cancel_url
30
+ @label = label
31
+ @price_id = price_id
32
+ @product_id = product_id
33
+ @quantity = quantity
34
+ @success_url = success_url
35
+ freeze
36
+ end
37
+
38
+ # The body as the API reads it.
39
+ def to_wire
40
+ wire = {}
41
+ wire["cancel_url"] = @cancel_url unless @cancel_url.nil?
42
+ wire["label"] = @label unless @label.nil?
43
+ wire["price_id"] = @price_id
44
+ wire["product_id"] = @product_id
45
+ wire["quantity"] = @quantity unless @quantity.nil?
46
+ wire["success_url"] = @success_url unless @success_url.nil?
47
+ wire
48
+ end
49
+ end
50
+
51
+ # The body of customers:create.
52
+ class CustomersCreateParams < Params
53
+ MEMBERS = %i[email external_id name].freeze
54
+
55
+ # @return [String]
56
+ attr_reader :email
57
+
58
+ # @return [String, nil]
59
+ attr_reader :external_id
60
+
61
+ # @return [String]
62
+ attr_reader :name
63
+
64
+ def initialize(email:, external_id: nil, name:)
65
+ @email = email
66
+ @external_id = external_id
67
+ @name = name
68
+ freeze
69
+ end
70
+
71
+ # The body as the API reads it.
72
+ def to_wire
73
+ wire = {}
74
+ wire["email"] = @email
75
+ wire["external_id"] = @external_id unless @external_id.nil?
76
+ wire["name"] = @name
77
+ wire
78
+ end
79
+ end
80
+
81
+ # The body of prices:create.
82
+ class PricesCreateParams < Params
83
+ MEMBERS = %i[amount_cents interval product_id type].freeze
84
+
85
+ # @return [Integer]
86
+ attr_reader :amount_cents
87
+
88
+ # @return [String ("month", "year"), nil]
89
+ attr_reader :interval
90
+
91
+ # @return [String]
92
+ attr_reader :product_id
93
+
94
+ # @return [String ("one_time", "recurring")]
95
+ attr_reader :type
96
+
97
+ def initialize(amount_cents:, interval: nil, product_id:, type:)
98
+ @amount_cents = amount_cents
99
+ @interval = interval
100
+ @product_id = product_id
101
+ @type = type
102
+ freeze
103
+ end
104
+
105
+ # The body as the API reads it.
106
+ def to_wire
107
+ wire = {}
108
+ wire["amount_cents"] = @amount_cents
109
+ wire["interval"] = @interval unless @interval.nil?
110
+ wire["product_id"] = @product_id
111
+ wire["type"] = @type
112
+ wire
113
+ end
114
+ end
115
+
116
+ # The body of products:create.
117
+ class ProductsCreateParams < Params
118
+ MEMBERS = %i[description name].freeze
119
+
120
+ # @return [String, nil]
121
+ attr_reader :description
122
+
123
+ # @return [String]
124
+ attr_reader :name
125
+
126
+ def initialize(description: nil, name:)
127
+ @description = description
128
+ @name = name
129
+ freeze
130
+ end
131
+
132
+ # The body as the API reads it.
133
+ def to_wire
134
+ wire = {}
135
+ wire["description"] = @description unless @description.nil?
136
+ wire["name"] = @name
137
+ wire
138
+ end
139
+ end
140
+
141
+ # The body of refunds:create.
142
+ class RefundsCreateParams < Params
143
+ MEMBERS = %i[amount_cents note payment_id reason].freeze
144
+
145
+ # @return [Integer]
146
+ attr_reader :amount_cents
147
+
148
+ # @return [String, nil]
149
+ attr_reader :note
150
+
151
+ # @return [String]
152
+ attr_reader :payment_id
153
+
154
+ # @return [String ("requested_by_customer", "duplicate", "fraudulent", "product_unavailable", "service_disruption", "other")]
155
+ attr_reader :reason
156
+
157
+ def initialize(amount_cents:, note: nil, payment_id:, reason:)
158
+ @amount_cents = amount_cents
159
+ @note = note
160
+ @payment_id = payment_id
161
+ @reason = reason
162
+ freeze
163
+ end
164
+
165
+ # The body as the API reads it.
166
+ def to_wire
167
+ wire = {}
168
+ wire["amount_cents"] = @amount_cents
169
+ wire["note"] = @note unless @note.nil?
170
+ wire["payment_id"] = @payment_id
171
+ wire["reason"] = @reason
172
+ wire
173
+ end
174
+ end
175
+
176
+ # The body of subscriptions:cancel.
177
+ class SubscriptionsCancelParams < Params
178
+ MEMBERS = %i[at_period_end reason].freeze
179
+
180
+ # @return [Boolean, nil]
181
+ attr_reader :at_period_end
182
+
183
+ # @return [String, nil]
184
+ attr_reader :reason
185
+
186
+ def initialize(at_period_end: nil, reason: nil)
187
+ @at_period_end = at_period_end
188
+ @reason = reason
189
+ freeze
190
+ end
191
+
192
+ # The body as the API reads it.
193
+ def to_wire
194
+ wire = {}
195
+ wire["at_period_end"] = @at_period_end unless @at_period_end.nil?
196
+ wire["reason"] = @reason unless @reason.nil?
197
+ wire
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,295 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Code generated by sdk/generator. DO NOT EDIT.
4
+
5
+ module Perata
6
+ # The API's checkouts.
7
+ class CheckoutsService
8
+ def initialize(client)
9
+ @client = client
10
+ end
11
+
12
+ # Create a checkout address for one product and price.
13
+ #
14
+ # @param params [CheckoutsCreateParams, Hash]
15
+ # @return [Checkout]
16
+ def create(params, idempotency_key: nil, api_key: nil)
17
+ data = @client.request("POST", "/api/v1/checkouts", body: CheckoutsCreateParams.coerce(params).to_wire, idempotency_key: idempotency_key, api_key: api_key)
18
+ Checkout.from_hash(data)
19
+ end
20
+ end
21
+
22
+ # The API's customers.
23
+ class CustomersService
24
+ def initialize(client)
25
+ @client = client
26
+ end
27
+
28
+ # Create a customer.
29
+ #
30
+ # @param params [CustomersCreateParams, Hash]
31
+ # @return [Customer]
32
+ def create(params, idempotency_key: nil, api_key: nil)
33
+ data = @client.request("POST", "/api/v1/customers", body: CustomersCreateParams.coerce(params).to_wire, idempotency_key: idempotency_key, api_key: api_key)
34
+ Customer.from_hash(data)
35
+ end
36
+
37
+ # Read a customer.
38
+ #
39
+ # @return [Customer]
40
+ def get(customer, api_key: nil)
41
+ data = @client.request("GET", "/api/v1/customers/#{Perata.segment(customer)}", api_key: api_key)
42
+ Customer.from_hash(data)
43
+ end
44
+
45
+ # List customers. One page; +list_iter+ walks every page.
46
+ #
47
+ # @return [Page<Customer>]
48
+ def list(page: nil, limit: nil, api_key: nil)
49
+ query = { "page" => page, "limit" => limit }
50
+ data = @client.request("GET", "/api/v1/customers", query: query, api_key: api_key)
51
+ Page.from_hash(data) { |item| Customer.from_hash(item) }
52
+ end
53
+
54
+ # Walks every page of customers:list from +page+, item by item.
55
+ #
56
+ # @return [Enumerator<Customer>]
57
+ def list_iter(page: nil, limit: nil, api_key: nil, &block)
58
+ items = Page.iterate(page) do |at|
59
+ list(page: at, limit: limit, api_key: api_key)
60
+ end
61
+ block ? items.each(&block) : items
62
+ end
63
+ end
64
+
65
+ # The API's orders.
66
+ class OrdersService
67
+ def initialize(client)
68
+ @client = client
69
+ end
70
+
71
+ # List orders: paid checkouts. One page; +list_iter+ walks every page.
72
+ #
73
+ # @return [Page<Order>]
74
+ def list(page: nil, limit: nil, api_key: nil)
75
+ query = { "page" => page, "limit" => limit }
76
+ data = @client.request("GET", "/api/v1/orders", query: query, api_key: api_key)
77
+ Page.from_hash(data) { |item| Order.from_hash(item) }
78
+ end
79
+
80
+ # Walks every page of orders:list from +page+, item by item.
81
+ #
82
+ # @return [Enumerator<Order>]
83
+ def list_iter(page: nil, limit: nil, api_key: nil, &block)
84
+ items = Page.iterate(page) do |at|
85
+ list(page: at, limit: limit, api_key: api_key)
86
+ end
87
+ block ? items.each(&block) : items
88
+ end
89
+ end
90
+
91
+ # The API's payment_methods.
92
+ class PaymentMethodsService
93
+ def initialize(client)
94
+ @client = client
95
+ end
96
+
97
+ # Stop charging a stored card; refused while an active subscription charges it.
98
+ #
99
+ # @return [PaymentMethodDetached]
100
+ def detach(payment_method, idempotency_key: nil, api_key: nil)
101
+ data = @client.request("POST", "/api/v1/payment_methods/#{Perata.segment(payment_method)}/detach", idempotency_key: idempotency_key, api_key: api_key)
102
+ PaymentMethodDetached.from_hash(data)
103
+ end
104
+
105
+ # List a customer's stored cards: brand, last four digits and expiry. One page; +list_iter+ walks every page.
106
+ #
107
+ # @return [Page<PaymentMethod>]
108
+ def list(customer, page: nil, limit: nil, api_key: nil)
109
+ query = { "page" => page, "limit" => limit }
110
+ data = @client.request("GET", "/api/v1/customers/#{Perata.segment(customer)}/payment_methods", query: query, api_key: api_key)
111
+ Page.from_hash(data) { |item| PaymentMethod.from_hash(item) }
112
+ end
113
+
114
+ # Walks every page of payment_methods:list from +page+, item by item.
115
+ #
116
+ # @return [Enumerator<PaymentMethod>]
117
+ def list_iter(customer, page: nil, limit: nil, api_key: nil, &block)
118
+ items = Page.iterate(page) do |at|
119
+ list(customer, page: at, limit: limit, api_key: api_key)
120
+ end
121
+ block ? items.each(&block) : items
122
+ end
123
+ end
124
+
125
+ # The API's payments.
126
+ class PaymentsService
127
+ def initialize(client)
128
+ @client = client
129
+ end
130
+
131
+ # Read a payment.
132
+ #
133
+ # @return [Payment]
134
+ def get(payment, api_key: nil)
135
+ data = @client.request("GET", "/api/v1/payments/#{Perata.segment(payment)}", api_key: api_key)
136
+ Payment.from_hash(data)
137
+ end
138
+
139
+ # List payments. One page; +list_iter+ walks every page.
140
+ #
141
+ # @return [Page<Payment>]
142
+ def list(page: nil, limit: nil, api_key: nil)
143
+ query = { "page" => page, "limit" => limit }
144
+ data = @client.request("GET", "/api/v1/payments", query: query, api_key: api_key)
145
+ Page.from_hash(data) { |item| Payment.from_hash(item) }
146
+ end
147
+
148
+ # Walks every page of payments:list from +page+, item by item.
149
+ #
150
+ # @return [Enumerator<Payment>]
151
+ def list_iter(page: nil, limit: nil, api_key: nil, &block)
152
+ items = Page.iterate(page) do |at|
153
+ list(page: at, limit: limit, api_key: api_key)
154
+ end
155
+ block ? items.each(&block) : items
156
+ end
157
+ end
158
+
159
+ # The API's prices.
160
+ class PricesService
161
+ def initialize(client)
162
+ @client = client
163
+ end
164
+
165
+ # Create a BRL price, one-time or recurring.
166
+ #
167
+ # @param params [PricesCreateParams, Hash]
168
+ # @return [Price]
169
+ def create(params, idempotency_key: nil, api_key: nil)
170
+ data = @client.request("POST", "/api/v1/prices", body: PricesCreateParams.coerce(params).to_wire, idempotency_key: idempotency_key, api_key: api_key)
171
+ Price.from_hash(data)
172
+ end
173
+
174
+ # List prices, optionally of one product (product_id). One page; +list_iter+ walks every page.
175
+ #
176
+ # @return [Page<Price>]
177
+ def list(page: nil, limit: nil, product_id: nil, api_key: nil)
178
+ query = { "page" => page, "limit" => limit, "product_id" => product_id }
179
+ data = @client.request("GET", "/api/v1/prices", query: query, api_key: api_key)
180
+ Page.from_hash(data) { |item| Price.from_hash(item) }
181
+ end
182
+
183
+ # Walks every page of prices:list from +page+, item by item.
184
+ #
185
+ # @return [Enumerator<Price>]
186
+ def list_iter(page: nil, limit: nil, product_id: nil, api_key: nil, &block)
187
+ items = Page.iterate(page) do |at|
188
+ list(page: at, limit: limit, product_id: product_id, api_key: api_key)
189
+ end
190
+ block ? items.each(&block) : items
191
+ end
192
+ end
193
+
194
+ # The API's products.
195
+ class ProductsService
196
+ def initialize(client)
197
+ @client = client
198
+ end
199
+
200
+ # Create a product.
201
+ #
202
+ # @param params [ProductsCreateParams, Hash]
203
+ # @return [Product]
204
+ def create(params, idempotency_key: nil, api_key: nil)
205
+ data = @client.request("POST", "/api/v1/products", body: ProductsCreateParams.coerce(params).to_wire, idempotency_key: idempotency_key, api_key: api_key)
206
+ Product.from_hash(data)
207
+ end
208
+
209
+ # Read a product.
210
+ #
211
+ # @return [Product]
212
+ def get(product, api_key: nil)
213
+ data = @client.request("GET", "/api/v1/products/#{Perata.segment(product)}", api_key: api_key)
214
+ Product.from_hash(data)
215
+ end
216
+
217
+ # List products. One page; +list_iter+ walks every page.
218
+ #
219
+ # @return [Page<Product>]
220
+ def list(page: nil, limit: nil, api_key: nil)
221
+ query = { "page" => page, "limit" => limit }
222
+ data = @client.request("GET", "/api/v1/products", query: query, api_key: api_key)
223
+ Page.from_hash(data) { |item| Product.from_hash(item) }
224
+ end
225
+
226
+ # Walks every page of products:list from +page+, item by item.
227
+ #
228
+ # @return [Enumerator<Product>]
229
+ def list_iter(page: nil, limit: nil, api_key: nil, &block)
230
+ items = Page.iterate(page) do |at|
231
+ list(page: at, limit: limit, api_key: api_key)
232
+ end
233
+ block ? items.each(&block) : items
234
+ end
235
+ end
236
+
237
+ # The API's refunds.
238
+ class RefundsService
239
+ def initialize(client)
240
+ @client = client
241
+ end
242
+
243
+ # Refund part or all of a payment.
244
+ #
245
+ # @param params [RefundsCreateParams, Hash]
246
+ # @return [Refund]
247
+ def create(params, idempotency_key: nil, api_key: nil)
248
+ data = @client.request("POST", "/api/v1/refunds", body: RefundsCreateParams.coerce(params).to_wire, idempotency_key: idempotency_key, api_key: api_key)
249
+ Refund.from_hash(data)
250
+ end
251
+ end
252
+
253
+ # The API's subscriptions.
254
+ class SubscriptionsService
255
+ def initialize(client)
256
+ @client = client
257
+ end
258
+
259
+ # Cancel a subscription, by default at the end of its period.
260
+ #
261
+ # @param params [SubscriptionsCancelParams, Hash]
262
+ # @return [Subscription]
263
+ def cancel(subscription, params, idempotency_key: nil, api_key: nil)
264
+ data = @client.request("POST", "/api/v1/subscriptions/#{Perata.segment(subscription)}/cancel", body: SubscriptionsCancelParams.coerce(params).to_wire, idempotency_key: idempotency_key, api_key: api_key)
265
+ Subscription.from_hash(data)
266
+ end
267
+
268
+ # Read a subscription.
269
+ #
270
+ # @return [Subscription]
271
+ def get(subscription, api_key: nil)
272
+ data = @client.request("GET", "/api/v1/subscriptions/#{Perata.segment(subscription)}", api_key: api_key)
273
+ Subscription.from_hash(data)
274
+ end
275
+
276
+ # List subscriptions, optionally of one customer (customer_id). One page; +list_iter+ walks every page.
277
+ #
278
+ # @return [Page<Subscription>]
279
+ def list(page: nil, limit: nil, customer_id: nil, api_key: nil)
280
+ query = { "page" => page, "limit" => limit, "customer_id" => customer_id }
281
+ data = @client.request("GET", "/api/v1/subscriptions", query: query, api_key: api_key)
282
+ Page.from_hash(data) { |item| Subscription.from_hash(item) }
283
+ end
284
+
285
+ # Walks every page of subscriptions:list from +page+, item by item.
286
+ #
287
+ # @return [Enumerator<Subscription>]
288
+ def list_iter(page: nil, limit: nil, customer_id: nil, api_key: nil, &block)
289
+ items = Page.iterate(page) do |at|
290
+ list(page: at, limit: limit, customer_id: customer_id, api_key: api_key)
291
+ end
292
+ block ? items.each(&block) : items
293
+ end
294
+ end
295
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Code generated by sdk/generator. DO NOT EDIT.
4
+
5
+ module Perata
6
+ # This SDK's version.
7
+ VERSION = "0.1.1"
8
+
9
+ # The contract this SDK was generated from.
10
+ API_VERSION = "0.1.0"
11
+
12
+ # Peráta's API. The environment, test or live, is the API key's: prk_test_…
13
+ # or prk_live_….
14
+ DEFAULT_BASE_URL = "https://perata.sh"
15
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "openssl"
5
+
6
+ # Verifying the webhooks Peráta sends, as Standard Webhooks signs them.
7
+ module Perata
8
+ # How far from now a webhook's timestamp may be, in seconds.
9
+ WEBHOOK_TOLERANCE_SECONDS = 300
10
+
11
+ # A request Peráta did not sign, or signed too long ago.
12
+ class WebhookVerificationError < StandardError
13
+ def initialize(message = "perata: webhook signature does not verify")
14
+ super
15
+ end
16
+ end
17
+
18
+ # What Peráta posts to an endpoint.
19
+ class WebhookEvent < Model
20
+ MEMBERS = %i[id type timestamp data].freeze
21
+
22
+ # @return [String]
23
+ attr_reader :id, :type, :timestamp
24
+ # @return [Hash{String => String}]
25
+ attr_reader :data
26
+
27
+ def initialize(id:, type:, timestamp:, data:)
28
+ @id = id
29
+ @type = type
30
+ @timestamp = timestamp
31
+ @data = data
32
+ freeze
33
+ end
34
+ end
35
+
36
+ # Checks a webhook Peráta sent and answers its event.
37
+ #
38
+ # The signature is an HMAC-SHA256 of +{webhook-id}.{webhook-timestamp}.{body}+
39
+ # under the key the endpoint's +whsec_+ secret encodes. Pass the body exactly
40
+ # as it arrived, before parsing it; +headers+ is a hash of the request's
41
+ # headers, in any case, or a Rack env.
42
+ #
43
+ # @return [WebhookEvent]
44
+ # @raise [WebhookVerificationError]
45
+ def self.verify_webhook(secret, headers, body, now: Time.now)
46
+ key = begin
47
+ secret.delete_prefix("whsec_").unpack1("m0")
48
+ rescue ArgumentError
49
+ ""
50
+ end
51
+ raise ArgumentError, "perata: the webhook secret is whsec_ and a base64 key" if key.empty?
52
+
53
+ raw = body.to_s.b
54
+ webhook_id = webhook_header(headers, "webhook-id")
55
+ stamp = webhook_header(headers, "webhook-timestamp")
56
+ raise WebhookVerificationError if webhook_id.empty? || !stamp.match?(/\A\d+\z/)
57
+ raise WebhookVerificationError if (now.to_i - stamp.to_i).abs > WEBHOOK_TOLERANCE_SECONDS
58
+
59
+ expected = OpenSSL::HMAC.digest("SHA256", key, "#{webhook_id}.#{stamp}.".b + raw)
60
+ webhook_header(headers, "webhook-signature").split.each do |signature|
61
+ version, encoded = signature.split(",", 2)
62
+ next unless version == "v1" && encoded
63
+
64
+ decoded = begin
65
+ encoded.unpack1("m0")
66
+ rescue ArgumentError
67
+ next
68
+ end
69
+ next unless decoded.bytesize == expected.bytesize && OpenSSL.fixed_length_secure_compare(decoded, expected)
70
+
71
+ event = JSON.parse(raw.force_encoding(Encoding::UTF_8))
72
+ return WebhookEvent.new(id: event.fetch("id"), type: event.fetch("type"), timestamp: event.fetch("timestamp"),
73
+ data: event["data"] || {})
74
+ end
75
+ raise WebhookVerificationError
76
+ end
77
+
78
+ # A header's value, looked up in any case; a Rack env's HTTP_WEBHOOK_ID
79
+ # names webhook-id.
80
+ def self.webhook_header(headers, name)
81
+ headers.each do |key, value|
82
+ return value.to_s if key.to_s.downcase.tr("_", "-").delete_prefix("http-") == name
83
+ end
84
+ ""
85
+ end
86
+ private_class_method :webhook_header
87
+ end
data/lib/perata.rb ADDED
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Code generated by sdk/generator. DO NOT EDIT.
4
+
5
+ # Peráta's SDK for Ruby, generated from Peráta's API contract.
6
+ #
7
+ # perata = Perata::Client.new(ENV.fetch("PERATA_API_KEY"))
8
+ # product = perata.products.create({ name: "Curso" }, idempotency_key: "produto-curso")
9
+ # perata.products.list_iter.each { |product| puts product.name }
10
+ module Perata
11
+ # A path parameter, escaped.
12
+ def self.segment(value)
13
+ value.to_s.b.gsub(/[^A-Za-z0-9\-._~]/) { |char| format("%%%02X", char.ord) }
14
+ end
15
+
16
+ # A value as JSON writes it: params and models as hashes, lists and maps of
17
+ # them walked.
18
+ def self.wire(value)
19
+ case value
20
+ when Params then value.to_wire
21
+ when Model then value.to_h.transform_keys(&:to_s).transform_values { |each| wire(each) }
22
+ when Array then value.map { |each| wire(each) }
23
+ when Hash then value.transform_values { |each| wire(each) }
24
+ else value
25
+ end
26
+ end
27
+ end
28
+
29
+ require_relative "perata/version"
30
+ require_relative "perata/error"
31
+ require_relative "perata/model"
32
+ require_relative "perata/models"
33
+ require_relative "perata/params"
34
+ require_relative "perata/page"
35
+ require_relative "perata/services"
36
+ require_relative "perata/client"
37
+ require_relative "perata/webhooks"
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: perata-sdk
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Peráta
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ executables: []
13
+ extensions: []
14
+ extra_rdoc_files: []
15
+ files:
16
+ - README.md
17
+ - lib/perata.rb
18
+ - lib/perata/client.rb
19
+ - lib/perata/error.rb
20
+ - lib/perata/model.rb
21
+ - lib/perata/models.rb
22
+ - lib/perata/page.rb
23
+ - lib/perata/params.rb
24
+ - lib/perata/services.rb
25
+ - lib/perata/version.rb
26
+ - lib/perata/webhooks.rb
27
+ homepage: https://perata.sh
28
+ licenses:
29
+ - MIT
30
+ metadata:
31
+ homepage_uri: https://perata.sh
32
+ source_code_uri: https://github.com/perata-sh/sdk
33
+ rubygems_mfa_required: 'true'
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '3.1'
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubygems_version: 4.0.16
49
+ specification_version: 4
50
+ summary: 'Peráta''s SDK for Ruby: products, customers, checkouts, payments, subscriptions
51
+ and webhooks.'
52
+ test_files: []