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.
- checksums.yaml +7 -0
- data/README.md +51 -0
- data/lib/perata/client.rb +91 -0
- data/lib/perata/error.rb +43 -0
- data/lib/perata/model.rb +45 -0
- data/lib/perata/models.rb +527 -0
- data/lib/perata/page.rb +34 -0
- data/lib/perata/params.rb +200 -0
- data/lib/perata/services.rb +295 -0
- data/lib/perata/version.rb +15 -0
- data/lib/perata/webhooks.rb +87 -0
- data/lib/perata.rb +37 -0
- metadata +52 -0
|
@@ -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: []
|