inttegro 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 (46) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +9 -0
  3. data/CHANGELOG.md +17 -0
  4. data/Dockerfile +23 -0
  5. data/LICENSE +21 -0
  6. data/README.md +104 -0
  7. data/Rakefile +50 -0
  8. data/lib/inttegro/client.rb +159 -0
  9. data/lib/inttegro/enums.rb +6 -0
  10. data/lib/inttegro/errors.rb +128 -0
  11. data/lib/inttegro/file_download.rb +29 -0
  12. data/lib/inttegro/generated/enums.rb +693 -0
  13. data/lib/inttegro/generated/models.rb +3840 -0
  14. data/lib/inttegro/generated/operations.rb +369 -0
  15. data/lib/inttegro/http_client.rb +639 -0
  16. data/lib/inttegro/models.rb +132 -0
  17. data/lib/inttegro/resources/apps.rb +24 -0
  18. data/lib/inttegro/resources/balance_transactions.rb +28 -0
  19. data/lib/inttegro/resources/balances.rb +16 -0
  20. data/lib/inttegro/resources/broadcasts.rb +28 -0
  21. data/lib/inttegro/resources/chimes.rb +32 -0
  22. data/lib/inttegro/resources/customers.rb +28 -0
  23. data/lib/inttegro/resources/file_links.rb +50 -0
  24. data/lib/inttegro/resources/file_references.rb +20 -0
  25. data/lib/inttegro/resources/files.rb +39 -0
  26. data/lib/inttegro/resources/financial_accounts.rb +104 -0
  27. data/lib/inttegro/resources/keys.rb +60 -0
  28. data/lib/inttegro/resources/message_templates.rb +78 -0
  29. data/lib/inttegro/resources/orders.rb +422 -0
  30. data/lib/inttegro/resources/otp.rb +30 -0
  31. data/lib/inttegro/resources/payment_methods.rb +250 -0
  32. data/lib/inttegro/resources/payouts.rb +200 -0
  33. data/lib/inttegro/resources/prices.rb +40 -0
  34. data/lib/inttegro/resources/products.rb +48 -0
  35. data/lib/inttegro/resources/purchase_intents.rb +44 -0
  36. data/lib/inttegro/resources/refunds.rb +36 -0
  37. data/lib/inttegro/resources/schedules.rb +28 -0
  38. data/lib/inttegro/resources/spec.rb +16 -0
  39. data/lib/inttegro/resources/upload_requests.rb +66 -0
  40. data/lib/inttegro/response_object.rb +86 -0
  41. data/lib/inttegro/transport_response.rb +65 -0
  42. data/lib/inttegro/types.rb +32 -0
  43. data/lib/inttegro/version.rb +6 -0
  44. data/lib/inttegro.rb +14 -0
  45. data/rbi/inttegro/generated.rbi +529 -0
  46. metadata +107 -0
@@ -0,0 +1,422 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ module Inttegro
5
+ module Resources
6
+ # Orders resource for creating orders, processing payments, and managing order lifecycle.
7
+ #
8
+ # Orders are the central transaction object in Inttegro. They represent a purchase with
9
+ # line items, customer information, and payment details. Use this resource to create
10
+ # orders, charge customers, handle confirmations, and process refunds.
11
+ #
12
+ # @see https://studio.inttegro.com/orders for detailed guides
13
+ class Orders
14
+ def initialize(http)
15
+ @http = T.let(http, Inttegro::HTTPClient)
16
+ end
17
+
18
+ # Create a new order with line items, customer, and payment details.
19
+ #
20
+ # Creates an order representing a purchase. You can create an order for a new or
21
+ # existing customer, include multiple line items, and optionally execute payment
22
+ # immediately. Orders must have at least one line item and billing details.
23
+ #
24
+ # @param payload [Hash] Order creation parameters
25
+ # @option payload [Hash] :customer_data New customer information (required if customer_id not provided)
26
+ # @option payload [String] :customer_id Existing customer ID (required if customer_data not provided)
27
+ # @option payload [Array<Hash>] :line_items List of products/services being purchased (required)
28
+ # @option payload [Hash] :billing_details Billing contact information (required)
29
+ # @option payload [String] :payment_method_id ID of saved payment method to use
30
+ # @option payload [Hash] :payment_method_data Inline payment method details
31
+ # @option payload [Boolean] :execute_payment Whether to immediately charge (default: false)
32
+ # @option payload [Hash] :checkout_settings Checkout flow configuration with redirect_url and cancel_url
33
+ # @option payload [Hash] :payout_settings Order-specific payout destination configuration
34
+ # @option payload [Hash] :custom_data Key-value custom data (max 25KB, keys and values must be strings)
35
+ # @option payload [Hash] :request_meta Request controls such as idempotency_key
36
+ # @option payload [String] :number Optional order number for reference
37
+ # @option payload [String] :statement_descriptor Text on customer's bank statement (max 22 characters)
38
+ # @option payload [String] :statement_descriptor_prefix Static prefix, 2-10 characters, used to build prefix*order_id; mutually exclusive with statement_descriptor
39
+ # @option payload [Boolean] :finalize Whether to explicitly finalize order (default: false)
40
+ #
41
+ # @return [Inttegro::Models::OrderResponse] Response containing the created order
42
+ #
43
+ # @example Create order with new customer and execute payment
44
+ # result = client.orders.create(
45
+ # request_meta: {
46
+ # idempotency_key: 'order_2025_001'
47
+ # },
48
+ # execute_payment: true,
49
+ # customer_data: {
50
+ # name: 'Akua Asantewaa',
51
+ # email_address: 'akua@example.com',
52
+ # phone_number: '+233541234567'
53
+ # },
54
+ # payment_method_data: {
55
+ # type: 'mobile_money',
56
+ # mobile_money: {
57
+ # network: 'mtn',
58
+ # account_number: '0541234567'
59
+ # }
60
+ # },
61
+ # line_items: [{
62
+ # type: 'product',
63
+ # product: {
64
+ # type: 'digital',
65
+ # name: 'Premium Subscription',
66
+ # quantity: 1,
67
+ # price: { currency: 'ghs', value: 5000 }
68
+ # }
69
+ # }],
70
+ # billing_details: {
71
+ # name: 'Akua Asantewaa',
72
+ # phone_number: '+233541234567'
73
+ # },
74
+ # checkout_settings: {
75
+ # redirect_url: 'https://example.com/order/complete',
76
+ # cancel_url: 'https://example.com/order/cancelled'
77
+ # }
78
+ # )
79
+ #
80
+ # puts "Created order: #{result.order.id}"
81
+ #
82
+ # @example Create order with existing customer
83
+ # result = client.orders.create(
84
+ # customer_id: 'cu_abc123',
85
+ # line_items: [{
86
+ # type: 'product',
87
+ # product: {
88
+ # type: 'physical',
89
+ # name: 'T-Shirt',
90
+ # quantity: 2,
91
+ # price: { currency: 'ghs', value: 8000 }
92
+ # }
93
+ # }],
94
+ # billing_details: {
95
+ # name: 'Kwame Osei',
96
+ # phone_number: '+233501234567'
97
+ # }
98
+ # )
99
+ #
100
+ # @see https://studio.inttegro.com/accept-a-payment for payment flow guide
101
+ # @see https://studio.inttegro.com/order-lifecycle for order states
102
+ def create(payload)
103
+ @http.post_model("/orders/create", Inttegro::Models::OrderResponse, payload)
104
+ end
105
+
106
+ def new(payload)
107
+ @http.post_model("/orders/new", Inttegro::Models::OrderResponse, payload)
108
+ end
109
+
110
+ # Retrieve an existing order by its ID.
111
+ #
112
+ # Returns full order details including customer, line items, payment state, and invoice information.
113
+ # Use this to check order status, retrieve payment details, or display order confirmation to customers.
114
+ #
115
+ # @param order_id [String] Unique identifier of the order to retrieve (required)
116
+ # @param options [Hash] Additional options (currently unused)
117
+ #
118
+ # @return [Inttegro::Models::OrderResponse] Response containing the complete order object
119
+ #
120
+ # @example Lookup an order
121
+ # result = client.orders.lookup(
122
+ # order_id: 'GKj7A8lM5wEGRUvbqpI4bkDFsQvpqVyh5fqePNnb'
123
+ # )
124
+ #
125
+ # puts "Order status: #{result.order.status.serialize}"
126
+ #
127
+ # @see https://studio.inttegro.com/orders for API reference
128
+ def lookup(order_id:, **options)
129
+ body = { order_id: order_id }.merge(options)
130
+ @http.post_model("/orders/lookup", Inttegro::Models::OrderResponse, body)
131
+ end
132
+
133
+ def update(payload)
134
+ @http.post_model("/orders/update", Inttegro::Models::OrderResponse, payload)
135
+ end
136
+
137
+ # Initiate payment for an existing order.
138
+ #
139
+ # Supports three payment flows:
140
+ # 1. Saved payment method: Provide only order_id to charge a previously saved payment method
141
+ # 2. New payment method: Include payment_method_data with inline payment details
142
+ # 3. Offline payment: Set paid_out_of_band to true for cash, bank transfer, or check payments
143
+ #
144
+ # When payment requires customer confirmation (e.g., OTP), the response includes a next_action field.
145
+ #
146
+ # @param payload [Hash] Payment parameters
147
+ # @option payload [String] :order_id Unique identifier of the order to pay (required)
148
+ # @option payload [Hash] :payment_method_data Inline payment method details (mobile money, card, etc.)
149
+ # @option payload [String] :payment_method_id ID of a saved payment method to use
150
+ # @option payload [Boolean] :paid_out_of_band Set to true if payment received outside Inttegro (default: false)
151
+ #
152
+ # @return [Inttegro::Models::OrderResponse] Response containing order and payment state
153
+ #
154
+ # @example Pay with inline mobile money
155
+ # result = client.orders.pay(
156
+ # order_id: 'GKj7A8lM5wEGRUvbqpI4bkDFsQvpqVyh5fqePNnb',
157
+ # payment_method_data: {
158
+ # type: 'mobile_money',
159
+ # mobile_money: {
160
+ # network: 'mtn',
161
+ # account_number: '0544998605'
162
+ # }
163
+ # }
164
+ # )
165
+ #
166
+ # order = result.order
167
+ # if order.payment&.next_action&.type == Inttegro::Enums::PaymentNextActionType::CONFIRM_PAYMENT
168
+ # # Customer needs to provide OTP sent to their phone
169
+ # puts 'Please enter the OTP sent to your phone'
170
+ # end
171
+ #
172
+ # @example Pay with saved payment method
173
+ # result = client.orders.pay(
174
+ # order_id: 'GKj7A8lM5wEGRUvbqpI4bkDFsQvpqVyh5fqePNnb',
175
+ # payment_method_id: 'pm_xyz123abc456'
176
+ # )
177
+ #
178
+ # @example Mark as paid offline
179
+ # result = client.orders.pay(
180
+ # order_id: 'GKj7A8lM5wEGRUvbqpI4bkDFsQvpqVyh5fqePNnb',
181
+ # paid_out_of_band: true
182
+ # )
183
+ #
184
+ # @see https://studio.inttegro.com/accept-a-payment for payment flow guide
185
+ # @see https://studio.inttegro.com/charge-repeat-customers for saved payment methods
186
+ def pay(payload)
187
+ @http.post_model("/orders/pay", Inttegro::Models::OrderResponse, payload)
188
+ end
189
+
190
+ # Confirm a pending payment using a verification token (e.g., OTP sent to customer's phone).
191
+ #
192
+ # Call this method when a payment requires customer confirmation and you've collected the verification
193
+ # token from the customer. The token is typically a 6-digit OTP sent via SMS or email.
194
+ #
195
+ # @param payload [Hash] Confirmation parameters
196
+ # @option payload [String] :order_id Unique identifier of the order being paid (required)
197
+ # @option payload [String] :token Verification token provided by customer (required, typically 6 digits)
198
+ #
199
+ # @return [Inttegro::Models::OrderResponse] Updated order with payment status
200
+ #
201
+ # @example Confirm payment with OTP
202
+ # result = client.orders.confirm_payment(
203
+ # order_id: 'GKj7A8lM5wEGRUvbqpI4bkDFsQvpqVyh5fqePNnb',
204
+ # token: '123456'
205
+ # )
206
+ #
207
+ # order = result.order
208
+ # if order.payment&.status == Inttegro::Enums::OrderPaymentStatus::PAID
209
+ # puts 'Payment confirmed successfully!'
210
+ # end
211
+ #
212
+ # @see https://studio.inttegro.com/accept-a-payment for complete payment flow
213
+ def confirm_payment(payload)
214
+ @http.post_model("/orders/confirm_payment", Inttegro::Models::OrderResponse, payload)
215
+ end
216
+
217
+ # Request a new confirmation token to be sent to the customer (e.g., resend OTP).
218
+ #
219
+ # Use this when the customer didn't receive the original OTP or the token expired. A fresh verification
220
+ # token will be sent via SMS or email to the customer's registered contact information.
221
+ #
222
+ # @param order_id [String] Unique identifier of the order requiring confirmation (required)
223
+ # @param request_meta [Hash, nil] Request controls such as idempotency_key (optional)
224
+ #
225
+ # @return [Inttegro::Models::OrderResponse] Updated order
226
+ #
227
+ # @example Resend OTP to customer
228
+ # result = client.orders.request_confirmation(
229
+ # order_id: 'GKj7A8lM5wEGRUvbqpI4bkDFsQvpqVyh5fqePNnb'
230
+ # )
231
+ #
232
+ # puts 'New OTP sent to customer'
233
+ #
234
+ # @see https://studio.inttegro.com/accept-a-payment for payment confirmation flow
235
+ def request_confirmation(order_id:, request_meta: nil)
236
+ @http.post_model(
237
+ "/orders/request_confirmation",
238
+ Inttegro::Models::OrderResponse,
239
+ {
240
+ order_id: order_id,
241
+ request_meta: request_meta || stable_order_request_meta("request_confirmation", order_id)
242
+ }
243
+ )
244
+ end
245
+
246
+ # Finalize an order to make it immutable and ready for payment or fulfillment.
247
+ #
248
+ # Finalizing (sealing) an order locks its line items and totals, making it ready for payment execution
249
+ # or order completion. Most orders are finalized automatically, but you can explicitly finalize if needed.
250
+ #
251
+ # @param order_id [String] Unique identifier of the order to finalize (required)
252
+ # @param request_meta [Hash, nil] Request controls such as idempotency_key (optional)
253
+ #
254
+ # @return [Inttegro::Models::FinalizeOrderResponse] Finalized order object
255
+ #
256
+ # @example Finalize an order
257
+ # result = client.orders.finalize(
258
+ # order_id: 'GKj7A8lM5wEGRUvbqpI4bkDFsQvpqVyh5fqePNnb'
259
+ # )
260
+ #
261
+ # puts "Order finalized at: #{result.order&.sealed_at}"
262
+ #
263
+ # @see https://studio.inttegro.com/order-lifecycle for order states
264
+ def finalize(order_id:, request_meta: nil)
265
+ @http.post_model(
266
+ "/orders/finalize",
267
+ Inttegro::Models::FinalizeOrderResponse,
268
+ {
269
+ order_id: order_id,
270
+ request_meta: request_meta || stable_order_request_meta("finalize", order_id)
271
+ }
272
+ )
273
+ end
274
+
275
+ # Send the hosted invoice link for an existing order.
276
+ #
277
+ # @param order_id [String] Unique identifier of the order whose invoice should be sent (required)
278
+ #
279
+ # @return [Inttegro::Models::OrderDocumentDeliveryResponse] Order and delivery details
280
+ def send_invoice(order_id:)
281
+ @http.post_model(
282
+ "/orders/send_invoice",
283
+ Inttegro::Models::OrderDocumentDeliveryResponse,
284
+ { order_id: order_id }
285
+ )
286
+ end
287
+
288
+ # Send the hosted receipt link for a paid order.
289
+ #
290
+ # @param order_id [String] Unique identifier of the paid order whose receipt should be sent (required)
291
+ #
292
+ # @return [Inttegro::Models::OrderDocumentDeliveryResponse] Order and delivery details
293
+ def send_receipt(order_id:)
294
+ @http.post_model(
295
+ "/orders/send_receipt",
296
+ Inttegro::Models::OrderDocumentDeliveryResponse,
297
+ { order_id: order_id }
298
+ )
299
+ end
300
+
301
+ # Mark an order as completed, indicating fulfillment is done.
302
+ #
303
+ # Call this after you've shipped physical goods or delivered digital products to the customer.
304
+ # Completing an order transitions it to its final state and can optionally mark payment as received
305
+ # offline (out-of-band) if paid_out_of_band is set to true.
306
+ #
307
+ # @param payload [Hash] Completion parameters
308
+ # @option payload [String] :order_id Unique identifier of the order to complete (required)
309
+ # @option payload [Boolean] :paid_out_of_band Set to true if payment received outside Inttegro (default: false)
310
+ #
311
+ # @return [Inttegro::Models::CompleteOrderResponse] Completed order object
312
+ #
313
+ # @example Complete order after fulfillment
314
+ # result = client.orders.complete(
315
+ # order_id: 'GKj7A8lM5wEGRUvbqpI4bkDFsQvpqVyh5fqePNnb'
316
+ # )
317
+ #
318
+ # puts "Order completed at: #{result.order&.completed_at}"
319
+ #
320
+ # @example Complete order with offline payment
321
+ # result = client.orders.complete(
322
+ # order_id: 'GKj7A8lM5wEGRUvbqpI4bkDFsQvpqVyh5fqePNnb',
323
+ # paid_out_of_band: true
324
+ # )
325
+ #
326
+ # @see https://studio.inttegro.com/order-lifecycle for order states
327
+ def complete(payload)
328
+ @http.post_model("/orders/complete", Inttegro::Models::CompleteOrderResponse, payload)
329
+ end
330
+
331
+ # Cancel an order, stopping payment execution and preventing further processing.
332
+ #
333
+ # Canceling an order is irreversible and should be done when the customer requests cancellation or
334
+ # the order cannot be fulfilled. If payment was already captured, you'll need to refund it separately.
335
+ #
336
+ # @param order_id [String] Unique identifier of the order to cancel (required)
337
+ # @param request_meta [Hash, nil] Request controls such as idempotency_key (optional)
338
+ #
339
+ # @return [Inttegro::Models::OrderResponse] Cancelled order object
340
+ #
341
+ # @example Cancel an order
342
+ # result = client.orders.cancel(
343
+ # order_id: 'GKj7A8lM5wEGRUvbqpI4bkDFsQvpqVyh5fqePNnb'
344
+ # )
345
+ #
346
+ # puts "Order #{result.order.id} has been cancelled"
347
+ #
348
+ # @see https://studio.inttegro.com/order-lifecycle for order states
349
+ def cancel(order_id:, request_meta: nil)
350
+ @http.post_model(
351
+ "/orders/cancel",
352
+ Inttegro::Models::OrderResponse,
353
+ {
354
+ order_id: order_id,
355
+ request_meta: request_meta || stable_order_request_meta("cancel", order_id)
356
+ }
357
+ )
358
+ end
359
+
360
+ # Refund a paid order, returning funds to the customer.
361
+ #
362
+ # Refunds the payment associated with an order, sending funds back to the customer's original payment
363
+ # method. The order must have been successfully paid before it can be refunded.
364
+ #
365
+ # @param order_id [String] Unique identifier of the order to refund (required)
366
+ #
367
+ # @return [Inttegro::Models::RefundResponse] Created refund
368
+ #
369
+ # @example Refund an order
370
+ # result = client.orders.refund(
371
+ # order_id: 'GKj7A8lM5wEGRUvbqpI4bkDFsQvpqVyh5fqePNnb'
372
+ # )
373
+ #
374
+ # puts "Refund created: #{result.refund&.id}"
375
+ #
376
+ # @see https://studio.inttegro.com/retry-a-payment for payment retry guide
377
+ def refund(payload)
378
+ @http.post_model("/orders/refund", Inttegro::Models::RefundResponse, payload)
379
+ end
380
+
381
+ # Retrieve a paginated list of orders.
382
+ #
383
+ # Returns orders in reverse chronological order (most recent first). Use the has_more field
384
+ # and page parameter to navigate through results. Supports filtering by status and time range.
385
+ #
386
+ # @param payload [Hash] Pagination and filter parameters (optional)
387
+ # @option payload [Integer] :page Page number to retrieve (minimum 1, default: 1)
388
+ # @option payload [Integer] :per_page Number of results per page (minimum 1, maximum 100, default: 10)
389
+ # @option payload [String] :status Filter by order status (e.g., 'paid', 'requires_payment', 'completed')
390
+ # @option payload [String] :created_after Filter orders created after this timestamp (ISO 8601)
391
+ # @option payload [String] :created_before Filter orders created before this timestamp (ISO 8601)
392
+ #
393
+ # @return [Inttegro::Models::PageOrdersResponse] Paginated list of orders
394
+ #
395
+ # @example Get first page of orders
396
+ # result = client.orders.page(
397
+ # per_page: 25,
398
+ # page: 1
399
+ # )
400
+ #
401
+ # puts "Retrieved #{result.page&.orders&.length || 0} orders"
402
+ #
403
+ # @example Filter by status
404
+ # paid_orders = client.orders.page(
405
+ # status: 'paid',
406
+ # per_page: 50
407
+ # )
408
+ #
409
+ # @see https://studio.inttegro.com/pagination for pagination guide
410
+ # @see https://studio.inttegro.com/orders for API reference
411
+ def page(payload = {})
412
+ @http.post_model("/orders/page", Inttegro::Models::PageOrdersResponse, payload || {})
413
+ end
414
+
415
+ private
416
+
417
+ def stable_order_request_meta(action, order_id)
418
+ { idempotency_key: "orders_#{action}_#{order_id}" }
419
+ end
420
+ end
421
+ end
422
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ module Inttegro
5
+ module Resources
6
+ class Otp
7
+ def initialize(http)
8
+ @http = T.let(http, Inttegro::HTTPClient)
9
+ end
10
+
11
+ def initiate(payload)
12
+ @http.post_model("/otp/initiate", Inttegro::Models::InitiateOTPResponse, payload)
13
+ end
14
+
15
+ alias_method :initialize_session, :initiate
16
+
17
+ def verify(payload)
18
+ @http.post_model("/otp/verify", Inttegro::Models::VerifyOTPResponse, payload)
19
+ end
20
+
21
+ def lookup(payload)
22
+ @http.post_model("/otp/lookup", Inttegro::Models::LookupOTPResponse, payload)
23
+ end
24
+
25
+ def cancel(payload)
26
+ @http.post_model("/otp/cancel", Inttegro::Models::CancelOtpResponse, payload)
27
+ end
28
+ end
29
+ end
30
+ end