solidgate-ruby-sdk 0.1.17 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b83cbd4040caae35563e9c6ee94f0c1b7527f8bc20860a5590db41cfd4f863c1
4
- data.tar.gz: 2d9d52fe8fcb04ecf1e61a3349383958af3a615a01970318acbf34be9d141e44
3
+ metadata.gz: 2c09427f81d0f0efc89e60222716d8d66490eec414145f244df791d9c6f486dd
4
+ data.tar.gz: 87b350ffcec8b48c8506278fd3c0cb24892c99a04348990ffa36f2d242aabfa6
5
5
  SHA512:
6
- metadata.gz: 8fbf089574bf7a8e1dd1215708bea4326d5efaca50189d1bf9962924c60f655c3a6be5b60e8fe5a0f54978a4b70c4e7afb67be1ef0526a815f97f671d331f5bc
7
- data.tar.gz: f34708de83f200743353cd76276c0208cebb0750c620abe63506027ad229f57702da85e319afd798808aeb46b564a13decd50ecffed438c399c2bb8ab424a28e
6
+ metadata.gz: 58cbef4744fbf27bf91b43921d25284b46af5c0be8b50b05c5a938172b418f7d762d708c0f19a59b3686b62d6002a290a3e01ac532d9f8d933e46ad729f89266
7
+ data.tar.gz: 4244c8c9944e9c1175868ed53726781a36d26d21cd00acf75efe67cc4cbd3fce1a3cbdaf425c38c04d471d06e116b814309c0c640b5d03a5ad04772549290c3e
data/AGENTS.md CHANGED
@@ -5,6 +5,9 @@
5
5
  Solidgate Ruby SDK is an unofficial Ruby library for integrating with the Solidgate payment gateway API.
6
6
  It provides a clean, object-oriented interface for payment processing, subscription management, and webhook handling.
7
7
 
8
+ ## Integration Documentation
9
+ - Payment integration guide for humans and LLM agents: `docs/payment-integration-guide.md`
10
+
8
11
  ## Project Structure
9
12
 
10
13
  ### Core Components
@@ -32,9 +35,9 @@ It provides a clean, object-oriented interface for payment processing, subscript
32
35
  - Handles authentication via HMAC-SHA512 signatures
33
36
  - Provides methods for all Solidgate API endpoints:
34
37
  - Payment operations: `create_payment`, `get_payment`, `capture_payment`, `void_payment`, `refund_payment`, `settle_payment`
35
- - Subscription operations: `create_subscription`, `subscription_status`, `switch_subscription_product`, `update_subscription_pause`, `create_subscription_pause`, `delete_subscription_pause`, `cancel_subscription`, `restore_subscription`
38
+ - Subscription operations: `create_subscription`, `subscription_status`, `switch_subscription_product`, `update_subscription_pause`, `create_subscription_pause`, `delete_subscription_pause`, `cancel_subscription`, `restore_subscription`, `update_subscription_payment_method`
36
39
  - Product operations: `create_product`, `update_product`, `create_price`, `products`, `product_prices`, `update_product_price`
37
- - Utility methods: `generate_intent`, `generate_signature`, `refund`, `order_status`
40
+ - Utility methods: `generate_intent`, `generate_signature`, `refund`, `alt_refund`, `order_status`, `apm_order_status`, `make_card_recurring`, `make_apm_recurring`
38
41
  - Private methods for HTTP operations: `get`, `post`, `patch`, `delete`, `request`
39
42
  - Encryption: `encrypt_payload` for payment intent generation (AES-256-CBC)
40
43
 
@@ -62,7 +65,7 @@ It provides a clean, object-oriented interface for payment processing, subscript
62
65
  - `Solidgate::ValidationError` - Parameter validation (includes errors hash)
63
66
 
64
67
  #### `lib/solidgate/version.rb`
65
- - Version constant: `Solidgate::VERSION = "0.1.17"`
68
+ - Version constant: `Solidgate::VERSION = "0.2.0"`
66
69
 
67
70
  ### Test Structure
68
71
 
data/CHANGELOG.md CHANGED
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.1] - 2026-06-11
11
+ ### Added
12
+ - `decrypt_intent` public method to decrypt payment intents generated by `generate_intent`.
13
+ - Internal `decrypt_payload` helper using AES-256-CBC with IV-prefix parsing.
14
+
15
+ ### Changed
16
+ - Added client spec coverage for encrypt/decrypt round-trip and invalid payload handling.
17
+
18
+ ## [0.2.0] - 2026-05-05
19
+ ### Added
20
+ - `apm_order_status` endpoint for checking alternative payment method order status.
21
+ - Spec coverage for previously untested client methods added in this worktree.
22
+
23
+ ### Fixed
24
+ - Recurring payment spec coverage bug affecting the recurring endpoint test suite.
25
+
26
+ ### Changed
27
+ - Documentation updates and version bump for the `0.2.0` release.
28
+
10
29
  ## [0.1.17] - 2026-03-03
11
30
  ### Added
12
31
  - `update_product` endpoint (`Solidgate::Client#update_product`) to modify product attributes.
@@ -18,6 +37,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
18
37
  ### Added
19
38
  - `alt_refund` endpoint to create refunds using an alternative payment method (`Solidgate::Client#alt_refund`).
20
39
 
40
+ ## [0.1.15] - 2026-02-20
41
+ ### Added
42
+ - `make_apm_recurring` endpoint to create recurring alternative payment method charges (`Solidgate::Client#make_apm_recurring`).
43
+
44
+ ## [0.1.14] - 2026-02-17
45
+ ### Added
46
+ - `make_card_recurring` endpoint to create recurring card charges (`Solidgate::Client#make_card_recurring`).
47
+
21
48
  ## [0.1.13] - 2026-02-13
22
49
  ### Added
23
50
  - `order_status` endpoint to check order/payment status on `pay.solidgate.com` (`Solidgate::Client#order_status`).
@@ -75,9 +102,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
75
102
  - Thread-safe configuration
76
103
  - Comprehensive documentation and examples
77
104
 
78
- [Unreleased]: https://github.com/carrfane/solidgate-ruby-sdk/compare/v0.1.17...HEAD
105
+ [Unreleased]: https://github.com/carrfane/solidgate-ruby-sdk/compare/v0.2.1...HEAD
106
+ [0.2.1]: https://github.com/carrfane/solidgate-ruby-sdk/compare/v0.2.0...v0.2.1
107
+ [0.2.0]: https://github.com/carrfane/solidgate-ruby-sdk/compare/v0.1.17...v0.2.0
79
108
  [0.1.17]: https://github.com/carrfane/solidgate-ruby-sdk/releases/tag/v0.1.17
80
109
  [0.1.16]: https://github.com/carrfane/solidgate-ruby-sdk/releases/tag/v0.1.16
110
+ [0.1.15]: https://github.com/carrfane/solidgate-ruby-sdk/compare/v0.1.14...v0.1.15
111
+ [0.1.14]: https://github.com/carrfane/solidgate-ruby-sdk/compare/v0.1.13...v0.1.14
81
112
  [0.1.13]: https://github.com/carrfane/solidgate-ruby-sdk/releases/tag/v0.1.13
82
113
  [0.1.12]: https://github.com/carrfane/solidgate-ruby-sdk/releases/tag/v0.1.12
83
114
  [0.1.11]: https://github.com/carrfane/solidgate-ruby-sdk/releases/tag/v0.1.11
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- solidgate-ruby-sdk (0.1.17)
4
+ solidgate-ruby-sdk (0.2.1)
5
5
  faraday
6
6
  faraday-multipart
7
7
 
data/README.md CHANGED
@@ -4,6 +4,10 @@
4
4
 
5
5
  A Ruby (unofficial) SDK for integrating with the Solidgate payment gateway API.
6
6
 
7
+ ## Additional Documentation
8
+
9
+ - Integration guide for payments (humans and LLM agents): `docs/payment-integration-guide.md`
10
+
7
11
  ## Installation
8
12
 
9
13
  Add this line to your application's Gemfile:
@@ -112,8 +116,32 @@ client.refund_payment('payment_id_123', amount: 500, reason: 'Customer requested
112
116
  # Refund by order ID (pay.solidgate.com)
113
117
  client.refund(order_id: 'order_123', amount: 1000)
114
118
 
119
+ # Refund an alternative payment method order (gate.solidgate.com)
120
+ client.alt_refund(order_id: 'apm_order_123', amount: 750)
121
+
115
122
  # Check order status (pay.solidgate.com)
116
123
  client.order_status(order_id: 'order_123')
124
+
125
+ # Check alternative payment method order status (gate.solidgate.com)
126
+ client.apm_order_status(order_id: 'apm_order_123')
127
+
128
+ # Charge a saved card payment method for a recurring payment
129
+ client.make_card_recurring(
130
+ order_id: 'renewal_order_123',
131
+ amount: 1999,
132
+ currency: 'USD',
133
+ customer_email: 'customer@example.com',
134
+ token: 'card_tok_abc123'
135
+ )
136
+
137
+ # Charge a saved APM payment method for a recurring payment
138
+ client.make_apm_recurring(
139
+ order_id: 'apm_renewal_123',
140
+ amount: 1499,
141
+ currency: 'EUR',
142
+ customer_email: 'customer@example.com',
143
+ token: 'apm_tok_xyz789'
144
+ )
117
145
  ```
118
146
 
119
147
  ### Subscription Management
@@ -0,0 +1,266 @@
1
+ # Solidgate Ruby SDK Integration Guide (Payments)
2
+
3
+ > Target version: `solidgate-ruby-sdk` `0.2.0`
4
+ > Audience: engineers and LLM agents integrating Solidgate payments in Ruby apps.
5
+
6
+ ## 1) What this SDK provides
7
+
8
+ Core entrypoints:
9
+
10
+ - `Solidgate.configure` for global credentials/config
11
+ - `Solidgate::Client` as the low-level API client (recommended for full control)
12
+ - `Solidgate::Payment` as a higher-level payment wrapper
13
+ - `Solidgate::Webhook` for webhook signature validation
14
+
15
+ Main domains used by the SDK:
16
+
17
+ - `https://subscriptions.solidgate.com` (default API base)
18
+ - `https://pay.solidgate.com` (refund/order-status/recurring card flows)
19
+ - `https://gate.solidgate.com` (alternative refund/APM recurring flows)
20
+
21
+ ---
22
+
23
+ ## 2) Install and initialize
24
+
25
+ ### Gem installation
26
+
27
+ ```ruby
28
+ # Gemfile
29
+ gem "solidgate-ruby-sdk"
30
+ ```
31
+
32
+ Then:
33
+
34
+ ```bash
35
+ bundle install
36
+ ```
37
+
38
+ ### Require and configure
39
+
40
+ ```ruby
41
+ require "solidgate-ruby-sdk"
42
+
43
+ Solidgate.configure do |config|
44
+ config.public_key = ENV.fetch("SOLIDGATE_PUBLIC_KEY")
45
+ config.private_key = ENV.fetch("SOLIDGATE_PRIVATE_KEY")
46
+ config.webhook_public_key = ENV["SOLIDGATE_WEBHOOK_PUBLIC_KEY"]
47
+ config.webhook_private_key = ENV["SOLIDGATE_WEBHOOK_PRIVATE_KEY"]
48
+
49
+ # Optional
50
+ config.sandbox = true
51
+ config.timeout = 30
52
+ config.open_timeout = 10
53
+ # config.api_url = "https://custom.example.com" # optional override
54
+ end
55
+ ```
56
+
57
+ Environment variables commonly used:
58
+
59
+ - `SOLIDGATE_PUBLIC_KEY`
60
+ - `SOLIDGATE_PRIVATE_KEY`
61
+ - `SOLIDGATE_WEBHOOK_PUBLIC_KEY`
62
+ - `SOLIDGATE_WEBHOOK_PRIVATE_KEY`
63
+
64
+ ---
65
+
66
+ ## 3) Quick start payment flow
67
+
68
+ Use `Solidgate::Client` directly for integration scripts and backend services.
69
+
70
+ ```ruby
71
+ client = Solidgate::Client.new
72
+
73
+ # 1) Create charge
74
+ created = client.create_payment(
75
+ order_id: "order_123",
76
+ amount: 1000, # minor units (e.g., cents)
77
+ currency: "USD",
78
+ customer_email: "customer@example.com"
79
+ )
80
+
81
+ payment_id = created["id"] || created["payment_id"]
82
+
83
+ # 2) Get payment details/status
84
+ payment = client.get_payment(payment_id)
85
+
86
+ # 3a) Capture (for auth flow)
87
+ captured = client.capture_payment(payment_id)
88
+ # or partial capture
89
+ # captured = client.capture_payment(payment_id, amount: 500)
90
+
91
+ # 3b) Void (if authorized and not captured)
92
+ # voided = client.void_payment(payment_id)
93
+
94
+ # 3c) Refund by payment_id
95
+ refunded = client.refund_payment(payment_id, amount: 300, reason: "partial_refund")
96
+ ```
97
+
98
+ ---
99
+
100
+ ## 4) API methods relevant for payments
101
+
102
+ ### Charges (`subscriptions.solidgate.com`)
103
+
104
+ - `create_payment(params)` -> `POST /v1/charge`
105
+ - `get_payment(payment_id)` -> `GET /v1/charge/:payment_id`
106
+ - `capture_payment(payment_id, params = {})` -> `POST /v1/charge/:payment_id/capture`
107
+ - `void_payment(payment_id)` -> `POST /v1/charge/:payment_id/void`
108
+ - `refund_payment(payment_id, params = {})` -> `POST /v1/charge/:payment_id/refund`
109
+
110
+ ### Refund and status helper routes
111
+
112
+ - `refund(params)` -> `POST https://pay.solidgate.com/api/v1/refund`
113
+ - typically `order_id`, optional `amount`
114
+ - `order_status(params)` -> `POST https://pay.solidgate.com/api/v1/status`
115
+ - `apm_order_status(params)` -> `POST https://gate.solidgate.com/api/v1/status`
116
+
117
+ ### Alternative payment routes
118
+
119
+ - `alt_refund(params)` -> `POST https://gate.solidgate.com/api/v1/refund`
120
+ - `make_card_recurring(params)` -> `POST https://pay.solidgate.com/api/v1/recurring`
121
+ - `make_apm_recurring(params)` -> `POST https://gate.solidgate.com/api/v1/recurring`
122
+
123
+ ---
124
+
125
+ ## 5) Frontend payment intent flow (server-side generation)
126
+
127
+ For hosted/payment-form flows, generate encrypted intent and signature server-side.
128
+
129
+ ```ruby
130
+ client = Solidgate::Client.new
131
+
132
+ intent_json = {
133
+ order_id: "order_123",
134
+ product_id: "product_456",
135
+ customer_account_id: "cust_789",
136
+ order_description: "Premium plan",
137
+ type: "auth", # or "sale"
138
+ settle_interval: 0,
139
+ retry_attempt: 3,
140
+ language: "en"
141
+ }.to_json
142
+
143
+ payment_intent = client.generate_intent(intent_json)
144
+
145
+ payment_data = {
146
+ merchant: Solidgate.configuration.public_key,
147
+ signature: client.generate_signature(payment_intent),
148
+ paymentIntent: payment_intent
149
+ }
150
+ ```
151
+
152
+ Return `payment_data` to the frontend that initializes Solidgate JS.
153
+
154
+ ---
155
+
156
+ ## 6) Webhook verification
157
+
158
+ Always validate signature before parsing/trusting webhook payload.
159
+
160
+ ```ruby
161
+ payload = request.body.read
162
+ signature = request.headers["Signature"]
163
+
164
+ webhook = Solidgate::Webhook.new
165
+
166
+ unless webhook.validate_signature(payload, signature)
167
+ head :unauthorized
168
+ return
169
+ end
170
+
171
+ event = JSON.parse(payload)
172
+ # process event
173
+ ```
174
+
175
+ ---
176
+
177
+ ## 7) Error handling
178
+
179
+ SDK error classes:
180
+
181
+ - `Solidgate::Error`
182
+ - `Solidgate::ConfigurationError`
183
+ - `Solidgate::ValidationError`
184
+ - `Solidgate::AuthenticationError`
185
+ - `Solidgate::InvalidRequestError`
186
+ - `Solidgate::APIError`
187
+ - `Solidgate::ConnectionError`
188
+ - `Solidgate::TimeoutError`
189
+ - `Solidgate::RateLimitError`
190
+
191
+ Recommended handling pattern:
192
+
193
+ ```ruby
194
+ begin
195
+ client.create_payment(order_id: "o1", amount: 1000, currency: "USD")
196
+ rescue Solidgate::ValidationError => e
197
+ # local validation (wrapper-level)
198
+ rescue Solidgate::ConnectionError, Solidgate::TimeoutError => e
199
+ # network/retry logic
200
+ rescue Solidgate::APIError => e
201
+ # inspect e.code, e.http_status, e.details
202
+ rescue Solidgate::Error => e
203
+ # fallback
204
+ end
205
+ ```
206
+
207
+ ---
208
+
209
+ ## 8) Auth/signing model used by this SDK
210
+
211
+ Each request includes:
212
+
213
+ - `Merchant: <public_key>`
214
+ - `Signature: <generated_signature>`
215
+ - `Content-Type: application/json`
216
+
217
+ Signature generation in this SDK:
218
+
219
+ 1. Serialize body to JSON string (empty string for no body)
220
+ 2. Build message: `public_key + json_string + public_key`
221
+ 3. HMAC-SHA512 with `private_key`
222
+ 4. Base64-encode the hex digest string
223
+
224
+ Use SDK-generated signatures instead of re-implementing to avoid mismatch.
225
+
226
+ ---
227
+
228
+ ## 9) LLM-agent integration playbook
229
+
230
+ If an LLM agent is integrating this SDK into another project, follow this sequence:
231
+
232
+ 1. Add `gem "solidgate-ruby-sdk"` and install dependencies.
233
+ 2. Create initializer with `Solidgate.configure`.
234
+ 3. Add a service object wrapping `Solidgate::Client` for:
235
+ - create/get/capture/void/refund
236
+ 4. Add idempotency/order-id strategy in app layer.
237
+ 5. Implement webhook endpoint with signature validation first.
238
+ 6. Add retries for `ConnectionError`/`TimeoutError` and safe backoff.
239
+ 7. Add structured logs with:
240
+ - `order_id`, `payment_id`, `status`, error code/status
241
+ 8. Add integration tests with WebMock/VCR style stubs.
242
+ 9. Add runbooks for capture/refund/manual reconciliation.
243
+
244
+ ---
245
+
246
+ ## 10) Known quirks in current SDK (v0.2.0)
247
+
248
+ - `settle_payment` currently does **not** call an API endpoint; it returns `config.api_url`.
249
+ - `README.md` examples may not fully match actual method signatures in code.
250
+ - `Solidgate::Payment#refund` refunds by `order_id` through `client.refund`, not by `payment_id`.
251
+ - Sandbox and production constants currently point to the same URL in config.
252
+ - Broad rescue in request pipeline may wrap some API exceptions into `Solidgate::Error` depending on failure path.
253
+
254
+ For robust integrations, prefer `Solidgate::Client` and explicitly test your payment flows.
255
+
256
+ ---
257
+
258
+ ## 11) Minimal production checklist
259
+
260
+ - [ ] Credentials loaded from secure env/secret manager
261
+ - [ ] Webhook signature validation enabled
262
+ - [ ] Retries/backoff for transient failures
263
+ - [ ] Monitoring for failed captures/refunds
264
+ - [ ] Reconciliation job using `order_status`
265
+ - [ ] Alerting on repeated auth/429/5xx errors
266
+ - [ ] Test mode and live mode credentials isolated
@@ -289,6 +289,19 @@ module Solidgate
289
289
  encrypt_payload(params)
290
290
  end
291
291
 
292
+ # Decrypts an encrypted payment intent generated by {#generate_intent}.
293
+ #
294
+ # @param encrypted_payload [String] URL-safe Base64 encrypted payload
295
+ # @return [String] decrypted JSON payload
296
+ # @raise [ArgumentError] if payload cannot be decoded/decrypted
297
+ #
298
+ # @example Decrypt payment intent
299
+ # payload = client.decrypt_intent(encrypted_intent)
300
+ #
301
+ def decrypt_intent(encrypted_payload)
302
+ decrypt_payload(encrypted_payload)
303
+ end
304
+
292
305
  # Updates an existing price for a product.
293
306
  # Use this to modify the amount, currency, or billing interval of a price.
294
307
  #
@@ -417,6 +430,20 @@ module Solidgate
417
430
  post('/api/v1/status', body: params, base_url: "https://pay.solidgate.com")
418
431
  end
419
432
 
433
+ # Retrieves order status from the Solidgate gate domain for APM transactions.
434
+ #
435
+ # @param params [Hash] status request parameters:
436
+ # - :order_id [String] unique order identifier
437
+ # - :payment_id [String] optional payment identifier
438
+ # @return [Hash] order status response
439
+ # @raise [InvalidRequestError] if params are invalid
440
+ #
441
+ # @example Get APM order status
442
+ # client.apm_order_status(order_id: 'order_123')
443
+ def apm_order_status(params)
444
+ post('/api/v1/status', body: params, base_url: "https://gate.solidgate.com")
445
+ end
446
+
420
447
  def make_card_recurring(params)
421
448
  post('/api/v1/recurring', body: params, base_url: "https://pay.solidgate.com")
422
449
  end
@@ -649,5 +676,30 @@ module Solidgate
649
676
  base64_encoded = Base64.urlsafe_encode64(iv + encrypted)
650
677
  base64_encoded.gsub('+', '-').gsub('/', '_')
651
678
  end
679
+
680
+ # Decrypts a URL-safe Base64 payload encrypted with AES-256-CBC.
681
+ # Expects the IV to be prepended to the encrypted content.
682
+ #
683
+ # @param encrypted_payload [String] URL-safe Base64 encrypted payload
684
+ # @return [String] decrypted payload
685
+ # @raise [ArgumentError] if payload format/content is invalid
686
+ #
687
+ def decrypt_payload(encrypted_payload)
688
+ raw_payload = Base64.urlsafe_decode64(encrypted_payload)
689
+ raise ArgumentError, "Invalid encrypted payload" if raw_payload.bytesize <= IV_LENGTH
690
+
691
+ iv = raw_payload[0, IV_LENGTH]
692
+ encrypted_data = raw_payload[IV_LENGTH..]
693
+ key = config.private_key[0, KEY_LENGTH]
694
+
695
+ cipher = OpenSSL::Cipher.new('aes-256-cbc')
696
+ cipher.decrypt
697
+ cipher.key = key
698
+ cipher.iv = iv
699
+
700
+ cipher.update(encrypted_data) + cipher.final
701
+ rescue ArgumentError, OpenSSL::Cipher::CipherError
702
+ raise ArgumentError, "Invalid encrypted payload"
703
+ end
652
704
  end
653
705
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Solidgate
4
- VERSION = "0.1.17"
4
+ VERSION = "0.2.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solidgate-ruby-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.17
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hector Carrillo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-03-03 00:00:00.000000000 Z
11
+ date: 2026-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -124,6 +124,7 @@ files:
124
124
  - LICENSE.txt
125
125
  - README.md
126
126
  - Rakefile
127
+ - docs/payment-integration-guide.md
127
128
  - examples/basic_usage.rb
128
129
  - lib/solidgate-ruby-sdk.rb
129
130
  - lib/solidgate/client.rb