paystack_sdk 0.0.1 → 0.0.3

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: c6c4ffb56d54aca1c129d5f8d9c825e31f0c4f0df719a95c324eb8b220156f2f
4
- data.tar.gz: 8a5a351599e8795c3c61deb5d8d2737c5fb5e445e20bf7c72b357bf0fb84f0ca
3
+ metadata.gz: cfe0137a6cc918043bc34e2be6dcb579713ef3dfec0641763234e66d51e08717
4
+ data.tar.gz: a331be86e1c23da3621d4b6a1d6d6c5ecfa31de7685c3776872b3ff6f3adc99d
5
5
  SHA512:
6
- metadata.gz: c9c76e4b0ef258ac320e4088d15ba07d7703d3436ad57246b22ab079873b9a0f590553dd0b712d8e2c2a4a3220c41090000d1fa115b83650a5e00780d519f033
7
- data.tar.gz: cf9454f62965fbc0555303a83f658ebf6cf7f249605a263a429dfa6d5da9810db5bb4b5ed76ea844f0228bb391ce21b0143b7a7846f343515705d07b5479e248
6
+ metadata.gz: de4c777e2d89ce4cf1e30a13a352d4dab8bee5696716af0eb771964ce3aad3a10b0a6381c67b64c42dea342954c5e6d69d05b75fa43e72c288f55eeb45192a7d
7
+ data.tar.gz: cc889820541066ea486dfe9b4aa86d1009c692efd7c1fa52929a0791ae1f954ecabd0c66bb75b733bae0af44398e6687004867a78dc64bf7f33b33ec81eaebbc
data/README.md CHANGED
@@ -36,19 +36,37 @@ paystack = PaystackSdk::Client.new(api_key: "sk_test_xxx")
36
36
  params = {email: "customer@email.com", amount: "2300", currency: "USD"}
37
37
  response = paystack.transactions.initialize_transaction(params)
38
38
 
39
+ if response.success?
40
+ puts response.authorization_url
41
+ else
42
+ puts resposne.error_message
43
+ end
44
+
39
45
  # Example: Verify a payment
40
46
  response = paystack.transactions.verify(reference: "transaction_reference")
41
- if paystack.transactions.success?
47
+ if response.success?
42
48
  puts "Payment verified successfully!"
43
49
  else
44
50
  puts "Payment verification failed: #{response.error_message}"
45
51
  end
52
+ ```
53
+
54
+ ### The Orginal Response
46
55
 
47
- # Note: The `response` object is a hash containing the API response. Use the `#success?`
48
- # method on the relevant resource instance (e.g., `transactions`, `plans`, `subscriptions`)
49
- # to determine if the request was successful.
56
+ There will be times you may need access to the original API response. For such cases, you
57
+ can use the `#original_response` method on the response object.
58
+
59
+ The return value is a hash with all the values from the HTTP request. This could be useful
60
+ when you need to debug or gain access to the response its raw state.
61
+
62
+ For example
63
+ ```ruby
64
+ response = transaction.list
65
+
66
+ puts response.original_response # => This will return the exact response received from Paystack
50
67
  ```
51
68
 
69
+
52
70
  Refer to the [documentation](https://github.com/nanafox/paystack_sdk) for more detailed usage examples and supported endpoints.
53
71
 
54
72
  ## Development
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../response"
4
+
1
5
  module PaystackSdk
2
6
  module Resources
3
7
  # The `Base` class serves as a parent class for all resource classes in the SDK.
@@ -10,29 +14,15 @@ module PaystackSdk
10
14
  @connection = connection
11
15
  end
12
16
 
13
- # Checks if the last API response was successful.
14
- #
15
- # @return [Boolean] `true` if the last API response was successful, otherwise `false`.
16
- def success?
17
- @api_response&.success? || false
18
- end
19
-
20
17
  private
21
18
 
22
19
  # Handles the API response, raising an error if the response is unsuccessful.
23
20
  #
24
21
  # @param response [Faraday::Response] The response object returned by the Faraday connection.
25
- # @return [Hash] The parsed response body if the request was successful.
22
+ # @return [PaystackSdk::Response] The parsed response body wrapped in a `PaystackSdk::Response` object if the request was successful.
26
23
  # @raise [PaystackSdk::Error] If the response indicates an error.
27
24
  def handle_response(response)
28
- @api_response ||= response
29
-
30
- if response.success?
31
- response.body
32
- else
33
- error_message = response.body.is_a?(Hash) ? response.body["message"] : "Paystack API Error"
34
- raise PaystackSdk::Error, error_message
35
- end
25
+ PaystackSdk::Response.new(response)
36
26
  end
37
27
  end
38
28
  end
@@ -4,8 +4,38 @@ require_relative "base"
4
4
 
5
5
  module PaystackSdk
6
6
  module Resources
7
- # The `Transactions` class provides methods for interacting with the Paystack Transactions API.
7
+ # The `Transactions` class provides methods for interacting with the Paystack
8
+ # Transactions API.
8
9
  # It allows you to initialize transactions, verify payments, list transactions, and fetch transaction details.
10
+ # The Transactions class provides methods to interact with the Paystack API for managing transactions.
11
+ # It includes functionalities for initializing, verifying, listing, fetching, and retrieving transaction totals.
12
+ #
13
+ # Example usage:
14
+ # ```ruby
15
+ # transactions = PaystackSdk::Resources::Transactions.new(connection)
16
+ #
17
+ # # Initialize a transaction
18
+ # payload = { email: "customer@email.com", amount: 10000, currency: "GHS" }
19
+ # response = transactions.initialize_transaction(payload)
20
+ # if response.success?
21
+ # puts "Transaction initialized successfully."
22
+ # puts "Authorization URL: #{response.data.authorization_url}"
23
+ # else
24
+ # puts "Error initializing transaction: #{response.error_message}"
25
+ # end
26
+ #
27
+ # # Verify a transaction
28
+ # response = transactions.verify(reference: "transaction_reference")
29
+ #
30
+ # # List transactions
31
+ # response = transactions.list(per_page: 50, page: 1)
32
+ #
33
+ # # Fetch a single transaction
34
+ # response = transactions.fetch(transaction_id: 12345)
35
+ #
36
+ # # Get transaction totals
37
+ # response = transactions.totals
38
+ # ```
9
39
  class Transactions < PaystackSdk::Resources::Base
10
40
  # Initializes a new transaction.
11
41
  #
@@ -16,8 +46,8 @@ module PaystackSdk
16
46
  # @example
17
47
  # payload = { email: "customer@email.com", amount: 10000, currency: "GHS" }
18
48
  # response = transactions.initialize_transaction(payload)
19
- def initialize_transaction(payload)
20
- raise PaystackSdk::Error, "Invalid payload" unless payload.is_a?(Hash)
49
+ def initiate(payload)
50
+ raise PaystackSdk::Error, "Payload must be a hash" unless payload.is_a?(Hash)
21
51
  response = @connection.post("/transaction/initialize", payload)
22
52
  handle_response(response)
23
53
  end
@@ -37,26 +67,29 @@ module PaystackSdk
37
67
 
38
68
  # Lists all transactions.
39
69
  #
40
- # @return [Hash] The response from the Paystack API containing a list of transactions.
70
+ # @param per_page [Integer] Number of records per page (default: 50)
71
+ # @param page [Integer] Page number to retrieve (default: 1)
72
+ # @return [PaystackSdk::Response] The response from the Paystack API containing a
73
+ # list of transactions.
41
74
  # @raise [PaystackSdk::Error] If the API request fails.
42
75
  #
43
76
  # @example
44
- # response = transactions.list
45
- def list
46
- response = @connection.get("/transaction")
77
+ # response = transactions.list(per_page: 20, page: 2)
78
+ def list(per_page: 50, page: 1)
79
+ response = @connection.get("/transaction", {perPage: per_page, page: page})
47
80
  handle_response(response)
48
81
  end
49
82
 
50
83
  # Fetches details of a single transaction by its ID.
51
84
  #
52
- # @param id [Integer] The ID of the transaction to fetch.
85
+ # @param transaction_id [Integer] The ID of the transaction to fetch.
53
86
  # @return [Hash] The response from the Paystack API containing transaction details.
54
87
  # @raise [PaystackSdk::Error] If the API request fails.
55
88
  #
56
89
  # @example
57
90
  # response = transactions.fetch("transaction_id")
58
- def fetch(id)
59
- response = @connection.get("/transaction/#{id}")
91
+ def fetch(transaction_id)
92
+ response = @connection.get("/transaction/#{transaction_id}")
60
93
  handle_response(response)
61
94
  end
62
95
 
@@ -0,0 +1,238 @@
1
+ module PaystackSdk
2
+ # The Response class provides a wrapper around Paystack API responses.
3
+ # It offers convenient access to response data through dot notation and
4
+ # supports both direct attribute access and hash/array-like operations.
5
+ #
6
+ # Features:
7
+ # - Dynamic attribute access via dot notation (response.data.attribute)
8
+ # - Hash-like access (response[:key])
9
+ # - Array-like access for list responses (response[0])
10
+ # - Iteration support (response.each)
11
+ # - Automatic handling of nested data structures
12
+ #
13
+ # @example Basic usage
14
+ # ```ruby
15
+ # response = PaystackSdk::Response.new(api_response)
16
+ #
17
+ # # Check if request was successful
18
+ # if response.success?
19
+ # # Access data using dot notation
20
+ # puts response.data.authorization_url
21
+ # puts response.data.reference
22
+ #
23
+ # # Or directly from response
24
+ # puts response.authorization_url
25
+ # else
26
+ # puts "Error: #{response.error_message}"
27
+ # end
28
+ #
29
+ # @example Working with list responses
30
+ # response = transactions.list
31
+ #
32
+ # # Iterate through items
33
+ # response.data.each do |transaction|
34
+ # puts transaction.amount
35
+ # puts transaction.reference
36
+ # end
37
+ #
38
+ # # Access by index
39
+ # first_transaction = response.data[0] # => same as `response.first`
40
+ # puts first_transaction.customer.email
41
+ # ```
42
+ class Response
43
+ # @return [String, nil] Error message if the request failed
44
+ attr_reader :error_message
45
+
46
+ # @return [String, nil] API message from the response
47
+ attr_reader :api_message
48
+
49
+ # @return [Hash, Array, Object] The underlying data
50
+ attr_reader :raw_data
51
+
52
+ # Initializes a new Response object
53
+ #
54
+ # @param response [Faraday::Response, Hash, Array] The raw API response or data
55
+ def initialize(response)
56
+ if response.is_a?(Faraday::Response)
57
+ # Handle direct Faraday response
58
+ @success = response.success?
59
+ @body = response.body
60
+ @api_message = extract_api_message(@body)
61
+ @raw_data = extract_data_from_body(@body)
62
+
63
+ unless @success
64
+ @error_message = @api_message || "Paystack API Error"
65
+ end
66
+ elsif response.is_a?(Response)
67
+ # If we're wrapping a Response object, just copy its data
68
+ @success = response.success
69
+ @error_message = response.error_message
70
+ @api_message = response.api_message
71
+ @raw_data = response.raw_data
72
+ else
73
+ # For direct data (Hash, Array, etc.)
74
+ @success = true
75
+ @raw_data = response
76
+ end
77
+ end
78
+
79
+ # Returns a Response object for the data
80
+ # This enables chained access like response.data.key
81
+ #
82
+ # @return [Response] self, to enable chaining
83
+ def data
84
+ self
85
+ end
86
+
87
+ # Check if the response was successful
88
+ #
89
+ # @return [Boolean] true if the API request was successful
90
+ def success?
91
+ @success
92
+ end
93
+
94
+ # Returns the original response body
95
+ # This is useful for debugging or accessing raw data
96
+ #
97
+ # @return [Hash, Array] The original response body
98
+ def original_response
99
+ @body
100
+ end
101
+
102
+ # Access hash values via methods (dot notation)
103
+ # Allows accessing data attributes directly: response.attribute_name
104
+ #
105
+ # @param method_name [Symbol] The attribute name to access
106
+ # @param args [Array] Method arguments (unused)
107
+ # @param block [Proc] Method block (unused)
108
+ # @return [Object, Response] The attribute value, wrapped in Response if it's a complex type
109
+ def method_missing(method_name, *args, &block)
110
+ if @raw_data.is_a?(Hash) && (@raw_data.key?(method_name) || @raw_data.key?(method_name.to_s))
111
+ value = @raw_data[method_name] || @raw_data[method_name.to_s]
112
+ wrap_value(value)
113
+ elsif @raw_data.is_a?(Array) && @raw_data.respond_to?(method_name)
114
+ result = @raw_data.send(method_name, *args, &block)
115
+ wrap_value(result)
116
+ else
117
+ super
118
+ end
119
+ end
120
+
121
+ # Check if the object responds to a method
122
+ #
123
+ # @param method_name [Symbol] The method name
124
+ # @param include_private [Boolean] Whether to include private methods
125
+ # @return [Boolean] Whether the method is supported
126
+ def respond_to_missing?(method_name, include_private = false)
127
+ (@raw_data.is_a?(Hash) && (@raw_data.key?(method_name) || @raw_data.key?(method_name.to_s))) ||
128
+ (@raw_data.is_a?(Array) && @raw_data.respond_to?(method_name)) ||
129
+ super
130
+ end
131
+
132
+ # Access data via hash/array notation
133
+ #
134
+ # @param key [Object] The key or index to access
135
+ # @return [Object, Response] The value for the given key or index
136
+ def [](key)
137
+ return nil unless @raw_data
138
+
139
+ if @raw_data.is_a?(Hash)
140
+ value = @raw_data[key.is_a?(String) ? key.to_sym : key]
141
+ wrap_value(value)
142
+ elsif @raw_data.is_a?(Array) && key.is_a?(Integer)
143
+ wrap_value(@raw_data[key])
144
+ end
145
+ end
146
+
147
+ # Check if key exists in hash
148
+ #
149
+ # @param key [Symbol, String] The key to check
150
+ # @return [Boolean] Whether the key exists
151
+ def key?(key)
152
+ @raw_data.is_a?(Hash) && @raw_data.key?(key.is_a?(String) ? key.to_sym : key)
153
+ end
154
+
155
+ # Iterate through hash entries or array items
156
+ #
157
+ # @yield [key, value] For hashes, passes each key-value pair
158
+ # @yield [value] For arrays, passes each item
159
+ # @return [Response, Enumerator] Self for chaining or Enumerator if no block given
160
+ def each(&block)
161
+ return enum_for(:each) unless block_given?
162
+
163
+ if @raw_data.is_a?(Hash)
164
+ @raw_data.each { |k, v| yield k, wrap_value(v) }
165
+ elsif @raw_data.is_a?(Array)
166
+ @raw_data.each { |item| yield wrap_value(item) }
167
+ end
168
+ self
169
+ end
170
+
171
+ # Standard array methods, delegated to the raw data
172
+ # @!method size
173
+ # @return [Integer] The number of items
174
+ # @!method length
175
+ # @return [Integer] The number of items
176
+ # @!method count
177
+ # @return [Integer] The number of items
178
+ # @!method empty?
179
+ # @return [Boolean] Whether the collection is empty
180
+ [:size, :length, :count, :empty?].each do |method_name|
181
+ define_method(method_name) do
182
+ @raw_data.send(method_name) if @raw_data.respond_to?(method_name)
183
+ end
184
+ end
185
+
186
+ # Special array methods that return wrapped values
187
+ # @!method first
188
+ # @return [Object, Response] The first item, wrapped if necessary
189
+ # @!method last
190
+ # @return [Object, Response] The last item, wrapped if necessary
191
+ [:first, :last].each do |method_name|
192
+ define_method(method_name) do
193
+ return nil unless @raw_data.is_a?(Array)
194
+ wrap_value(@raw_data.send(method_name))
195
+ end
196
+ end
197
+
198
+ private
199
+
200
+ # Extract API message from response body
201
+ #
202
+ # @param body [Hash] The response body
203
+ # @return [String, nil] The API message
204
+ def extract_api_message(body)
205
+ body["message"] || body[:message] if body.is_a?(Hash)
206
+ end
207
+
208
+ # Extract data from response body
209
+ #
210
+ # @param body [Hash, Array] The response body
211
+ # @return [Hash, Array, Object] The data portion of the response
212
+ def extract_data_from_body(body)
213
+ if body.is_a?(Hash)
214
+ body["data"] || body[:data] || body
215
+ else
216
+ body
217
+ end
218
+ end
219
+
220
+ # Wrap value in Response if needed
221
+ #
222
+ # @param value [Object] The value to wrap
223
+ # @return [Object, Response] The wrapped value
224
+ def wrap_value(value)
225
+ case value
226
+ when Response
227
+ # Already wrapped
228
+ value
229
+ when Hash, Array
230
+ # Create a new Response with the value
231
+ Response.new(value)
232
+ else
233
+ # Return primitives as-is
234
+ value
235
+ end
236
+ end
237
+ end
238
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PaystackSdk
4
- VERSION = "0.0.1"
4
+ VERSION = "0.0.3"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paystack_sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maxwell Nana Forson (theLazyProgrammer)
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-05-10 00:00:00.000000000 Z
11
+ date: 2025-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 13.2.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: debug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 1.9.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 1.9.0
83
97
  description: |
84
98
  The `paystack_sdk` gem provides a simple and intuitive interface for
85
99
  interacting with Paystack's payment gateway API. It allows developers to
@@ -104,6 +118,7 @@ files:
104
118
  - lib/paystack_sdk/client.rb
105
119
  - lib/paystack_sdk/resources/base.rb
106
120
  - lib/paystack_sdk/resources/transactions.rb
121
+ - lib/paystack_sdk/response.rb
107
122
  - lib/paystack_sdk/version.rb
108
123
  - mise.toml
109
124
  - sig/paystack_sdk.rbs