solidgate-ruby-sdk 0.1.8 → 0.1.10
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 +4 -4
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +1 -1
- data/README.md +167 -10
- data/lib/solidgate/client.rb +333 -50
- data/lib/solidgate/payment.rb +6 -5
- data/lib/solidgate/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7f1670a04649a2c491affa62db248bd7bb08ecb82d3db6df1d132131ee486bf6
|
|
4
|
+
data.tar.gz: 1d611dae1d1e9d8ddb8aa8b74161ccb064b57cddfa0f57c2bc2777916f5d7eb6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '08e8fb84413b4e7ad186c4b70c9099764c5d0b7d3b598e12772e07712ebc98890d979b73b7c52a00ed1cb7bb1d833eac20ff85d95e1a1d8f6ddb698a9117fea7'
|
|
7
|
+
data.tar.gz: 6a4cc2aff3ce40534e1eb77b3a3b5d4e95232edc599e348054890a269eeb09659cf7f6f675b61c408cd10fa213dcf570999a46dc9532ab3c09df113df88e11f3
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.1.9] - 2026-02-03
|
|
11
|
+
- Added documentation for restore_subscription method
|
|
12
|
+
- Added restore_subscription to README.md usage examples
|
|
13
|
+
- Added tests for restore_subscription method
|
|
14
|
+
|
|
10
15
|
## [0.1.4] - 2026-01-14
|
|
11
16
|
- Client Specs enhancements
|
|
12
17
|
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
[](https://badge.fury.io/rb/solidgate-ruby-sdk)
|
|
2
|
+
|
|
1
3
|
# Solidgate Ruby SDK
|
|
2
4
|
|
|
3
5
|
A Ruby (unofficial) SDK for integrating with the Solidgate payment gateway API.
|
|
@@ -34,20 +36,35 @@ end
|
|
|
34
36
|
|
|
35
37
|
## Usage
|
|
36
38
|
|
|
37
|
-
### Creating a
|
|
39
|
+
### Creating a Client
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
# Using global configuration
|
|
43
|
+
client = Solidgate::Client.new
|
|
44
|
+
|
|
45
|
+
# Using custom configuration
|
|
46
|
+
client = Solidgate::Client.new(
|
|
47
|
+
public_key: 'your_public_key',
|
|
48
|
+
private_key: 'your_private_key'
|
|
49
|
+
)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Payment Intent (Frontend Integration)
|
|
53
|
+
|
|
54
|
+
Generate an encrypted payment intent for use with Solidgate's JavaScript SDK:
|
|
38
55
|
|
|
39
56
|
```ruby
|
|
40
57
|
SolidgateClient = Solidgate::Client.new
|
|
41
58
|
|
|
42
59
|
payment_intent = {
|
|
43
|
-
order_id: 'order_id_123',
|
|
44
|
-
product_id: 'product_id_456',
|
|
45
|
-
customer_account_id: 'customer_789',
|
|
60
|
+
order_id: 'order_id_123', # Unique order identifier provided by the merchant
|
|
61
|
+
product_id: 'product_id_456', # Product identifier generated in Solidgate Dashboard
|
|
62
|
+
customer_account_id: 'customer_789', # Unique customer identifier provided by the merchant
|
|
46
63
|
order_description: 'Premium package',
|
|
47
|
-
type: 'auth',
|
|
48
|
-
settle_interval: 0,
|
|
64
|
+
type: 'auth', # 'auth' for authorization only, 'sale' for immediate charge
|
|
65
|
+
settle_interval: 0, # Delay in hours for automatic settlement, 0 means immediate
|
|
49
66
|
retry_attempt: 3,
|
|
50
|
-
language: I18n.locale
|
|
67
|
+
language: I18n.locale # Language to render the payment form
|
|
51
68
|
}.to_json
|
|
52
69
|
|
|
53
70
|
encrypted_payment_intent = client.generate_intent(payment_intent)
|
|
@@ -61,13 +78,153 @@ payment_data = {
|
|
|
61
78
|
}
|
|
62
79
|
```
|
|
63
80
|
|
|
64
|
-
###
|
|
81
|
+
### Payment Operations
|
|
65
82
|
|
|
66
83
|
```ruby
|
|
67
|
-
|
|
68
|
-
|
|
84
|
+
client = Solidgate::Client.new
|
|
85
|
+
|
|
86
|
+
# Create a new payment
|
|
87
|
+
response = client.create_payment(
|
|
88
|
+
amount: 1000, # Amount in minor units (e.g., cents)
|
|
89
|
+
currency: 'USD',
|
|
90
|
+
order_id: 'order_123',
|
|
91
|
+
customer_email: 'customer@example.com'
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Get payment details
|
|
95
|
+
payment = client.get_payment('payment_id_123')
|
|
96
|
+
|
|
97
|
+
# Capture an authorized payment
|
|
98
|
+
client.capture_payment('payment_id_123')
|
|
99
|
+
|
|
100
|
+
# Capture with partial amount
|
|
101
|
+
client.capture_payment('payment_id_123', amount: 500)
|
|
102
|
+
|
|
103
|
+
# Void an authorized payment (before settlement)
|
|
104
|
+
client.void_payment('payment_id_123')
|
|
105
|
+
|
|
106
|
+
# Refund a captured payment
|
|
107
|
+
client.refund_payment('payment_id_123')
|
|
108
|
+
|
|
109
|
+
# Partial refund
|
|
110
|
+
client.refund_payment('payment_id_123', amount: 500, reason: 'Customer request')
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Subscription Management
|
|
114
|
+
|
|
115
|
+
```ruby
|
|
116
|
+
client = Solidgate::Client.new
|
|
117
|
+
|
|
118
|
+
# Create a subscription
|
|
119
|
+
subscription = client.create_subscription(
|
|
120
|
+
product_id: 'prod_123',
|
|
121
|
+
customer_account_id: 'customer_456',
|
|
122
|
+
order_id: 'order_789'
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# Get subscription status
|
|
126
|
+
status = client.subscription_status('subscription_id_123')
|
|
127
|
+
|
|
128
|
+
# Switch to a different product/plan
|
|
129
|
+
client.switch_subscription_product(
|
|
130
|
+
subscription_id: 'sub_123',
|
|
131
|
+
new_product_id: 'prod_premium_456'
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Cancel a subscription
|
|
135
|
+
client.cancel_subscription(
|
|
136
|
+
subscription_id: 'sub_123',
|
|
137
|
+
cancel_at_period_end: true,
|
|
138
|
+
reason: 'Customer requested cancellation'
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# Restore a cancelled subscription
|
|
142
|
+
client.restore_subscription(
|
|
143
|
+
subscription_id: 'sub_123'
|
|
144
|
+
)
|
|
69
145
|
```
|
|
70
146
|
|
|
147
|
+
### Subscription Pause Scheduling
|
|
148
|
+
|
|
149
|
+
```ruby
|
|
150
|
+
client = Solidgate::Client.new
|
|
151
|
+
|
|
152
|
+
# Create a pause schedule
|
|
153
|
+
client.create_subscription_pause('subscription_id_123',
|
|
154
|
+
pause_at: '2026-02-01T00:00:00Z',
|
|
155
|
+
resume_at: '2026-03-01T00:00:00Z'
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# Update an existing pause schedule
|
|
159
|
+
client.update_subscription_pause('subscription_id_123',
|
|
160
|
+
resume_at: '2026-04-01T00:00:00Z'
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# Delete/cancel a pending pause schedule
|
|
164
|
+
client.delete_subscription_pause('subscription_id_123')
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Product & Price Management
|
|
168
|
+
|
|
169
|
+
```ruby
|
|
170
|
+
client = Solidgate::Client.new
|
|
171
|
+
|
|
172
|
+
# Create a product
|
|
173
|
+
product = client.create_product(
|
|
174
|
+
name: 'Premium Plan',
|
|
175
|
+
description: 'Access to all premium features',
|
|
176
|
+
type: 'subscription'
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# Create a price for a product
|
|
180
|
+
price = client.create_price('product_id_123',
|
|
181
|
+
amount: 1999, # $19.99 in cents
|
|
182
|
+
currency: 'USD',
|
|
183
|
+
interval: 'month' # Billing interval for subscriptions
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
# List all products
|
|
187
|
+
all_products = client.products
|
|
188
|
+
|
|
189
|
+
# Get prices for a specific product
|
|
190
|
+
prices = client.product_prices('product_id_123')
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Signature Generation
|
|
194
|
+
|
|
195
|
+
Generate signatures for API authentication or custom integrations:
|
|
196
|
+
|
|
197
|
+
```ruby
|
|
198
|
+
client = Solidgate::Client.new
|
|
199
|
+
|
|
200
|
+
# Generate signature with configured keys
|
|
201
|
+
signature = client.generate_signature(json_payload)
|
|
202
|
+
|
|
203
|
+
# Generate signature with custom keys
|
|
204
|
+
signature = client.generate_signature(
|
|
205
|
+
json_payload,
|
|
206
|
+
public_key: 'custom_public_key',
|
|
207
|
+
private_key: 'custom_private_key'
|
|
208
|
+
)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Handling Webhooks
|
|
212
|
+
|
|
213
|
+
```ruby
|
|
214
|
+
# In your webhook controller
|
|
215
|
+
payload = request.body.read
|
|
216
|
+
signature = request.headers['Signature']
|
|
217
|
+
|
|
218
|
+
webhook = Solidgate::Webhook.new
|
|
219
|
+
if webhook.validate_signature(payload, signature)
|
|
220
|
+
# Process the webhook event
|
|
221
|
+
event = JSON.parse(payload)
|
|
222
|
+
# Handle event...
|
|
223
|
+
else
|
|
224
|
+
# Invalid signature, reject the webhook
|
|
225
|
+
head :unauthorized
|
|
226
|
+
end
|
|
227
|
+
```
|
|
71
228
|
|
|
72
229
|
## Available Error Classes
|
|
73
230
|
|
data/lib/solidgate/client.rb
CHANGED
|
@@ -9,130 +9,297 @@ require "openssl"
|
|
|
9
9
|
require 'pry'
|
|
10
10
|
|
|
11
11
|
module Solidgate
|
|
12
|
-
# HTTP client for interacting with the Solidgate API
|
|
12
|
+
# HTTP client for interacting with the Solidgate API.
|
|
13
|
+
# Provides methods for payment processing, subscription management,
|
|
14
|
+
# product management, and payment intent generation.
|
|
15
|
+
#
|
|
16
|
+
# @example Basic usage
|
|
17
|
+
# client = Solidgate::Client.new
|
|
18
|
+
# client.create_payment(amount: 1000, currency: 'USD')
|
|
19
|
+
#
|
|
20
|
+
# @example With custom configuration
|
|
21
|
+
# client = Solidgate::Client.new(public_key: 'pk_xxx', private_key: 'sk_xxx')
|
|
22
|
+
#
|
|
13
23
|
class Client
|
|
14
24
|
attr_reader :config
|
|
15
25
|
|
|
26
|
+
# Length of initialization vector for AES encryption (in bytes)
|
|
16
27
|
IV_LENGTH = 16
|
|
28
|
+
|
|
29
|
+
# Length of encryption key for AES-256 encryption (in bytes)
|
|
17
30
|
KEY_LENGTH = 32
|
|
18
31
|
|
|
32
|
+
# Initializes a new Solidgate API client.
|
|
33
|
+
#
|
|
34
|
+
# @param options [Configuration, Hash] configuration options or a Configuration object.
|
|
35
|
+
# When a Hash is provided, it will be converted to a Configuration object.
|
|
36
|
+
# Defaults to global Solidgate.configuration.
|
|
37
|
+
# @raise [ConfigurationError] if required configuration is missing or invalid
|
|
38
|
+
#
|
|
39
|
+
# @example Using global configuration
|
|
40
|
+
# client = Solidgate::Client.new
|
|
41
|
+
#
|
|
42
|
+
# @example Using custom options
|
|
43
|
+
# client = Solidgate::Client.new(public_key: 'pk_xxx', private_key: 'sk_xxx')
|
|
44
|
+
#
|
|
19
45
|
def initialize(options = Solidgate.configuration)
|
|
20
46
|
@config = build_config(options)
|
|
21
47
|
@config.validate!
|
|
22
48
|
end
|
|
23
49
|
|
|
24
|
-
#
|
|
50
|
+
# Creates a new payment charge.
|
|
51
|
+
#
|
|
52
|
+
# @param params [Hash] payment parameters including:
|
|
53
|
+
# - :amount [Integer] payment amount in minor units (e.g., cents)
|
|
54
|
+
# - :currency [String] three-letter ISO currency code (e.g., 'USD')
|
|
55
|
+
# - :order_id [String] unique order identifier
|
|
56
|
+
# - :customer_email [String] customer's email address
|
|
57
|
+
# - :card_number [String] credit card number (if applicable)
|
|
58
|
+
# @return [Hash] payment response containing payment ID, status, and transaction details
|
|
59
|
+
# @raise [InvalidRequestError] if payment parameters are invalid
|
|
60
|
+
# @raise [AuthenticationError] if API credentials are invalid
|
|
25
61
|
#
|
|
26
|
-
# @param params [Hash] payment parameters
|
|
27
|
-
# @return [Hash] payment response
|
|
28
62
|
def create_payment(params)
|
|
29
|
-
post("/v1/charge", params)
|
|
63
|
+
post("/v1/charge", body: params)
|
|
30
64
|
end
|
|
31
65
|
|
|
32
|
-
#
|
|
66
|
+
# Retrieves payment details and current status.
|
|
67
|
+
#
|
|
68
|
+
# @param payment_id [String] the unique payment identifier returned from create_payment
|
|
69
|
+
# @return [Hash] payment details including:
|
|
70
|
+
# - :id [String] payment identifier
|
|
71
|
+
# - :status [String] current payment status
|
|
72
|
+
# - :amount [Integer] payment amount
|
|
73
|
+
# - :currency [String] payment currency
|
|
74
|
+
# - :created_at [String] timestamp of payment creation
|
|
75
|
+
# @raise [InvalidRequestError] if payment_id is not found
|
|
33
76
|
#
|
|
34
|
-
# @param payment_id [String] payment ID
|
|
35
|
-
# @return [Hash] payment details
|
|
36
77
|
def get_payment(payment_id)
|
|
37
78
|
get("/v1/charge/#{payment_id}")
|
|
38
79
|
end
|
|
39
80
|
|
|
40
|
-
#
|
|
81
|
+
# Captures a previously authorized payment.
|
|
82
|
+
# Use this to finalize a payment that was created with type 'auth'.
|
|
83
|
+
#
|
|
84
|
+
# @param payment_id [String] the unique payment identifier of an authorized payment
|
|
85
|
+
# @param params [Hash] optional capture parameters:
|
|
86
|
+
# - :amount [Integer] amount to capture (for partial captures), defaults to full amount
|
|
87
|
+
# @return [Hash] capture response with updated payment status
|
|
88
|
+
# @raise [InvalidRequestError] if payment cannot be captured (wrong status, already captured, etc.)
|
|
41
89
|
#
|
|
42
|
-
# @param payment_id [String] payment ID
|
|
43
|
-
# @param params [Hash] capture parameters (optional)
|
|
44
|
-
# @return [Hash] capture response
|
|
45
90
|
def capture_payment(payment_id, params = {})
|
|
46
|
-
post("/v1/charge/#{payment_id}/capture", params)
|
|
91
|
+
post("/v1/charge/#{payment_id}/capture", body: params)
|
|
47
92
|
end
|
|
48
93
|
|
|
49
|
-
#
|
|
94
|
+
# Voids a payment that has not yet been settled.
|
|
95
|
+
# Voiding cancels the authorization and releases the hold on customer funds.
|
|
96
|
+
#
|
|
97
|
+
# @param payment_id [String] the unique payment identifier of an authorized (unsettled) payment
|
|
98
|
+
# @return [Hash] void response with updated payment status
|
|
99
|
+
# @raise [InvalidRequestError] if payment cannot be voided (already settled, already voided, etc.)
|
|
50
100
|
#
|
|
51
|
-
# @param payment_id [String] payment ID
|
|
52
|
-
# @return [Hash] void response
|
|
53
101
|
def void_payment(payment_id)
|
|
54
102
|
post("/v1/charge/#{payment_id}/void")
|
|
55
103
|
end
|
|
56
104
|
|
|
57
|
-
#
|
|
105
|
+
# Refunds a captured/settled payment.
|
|
106
|
+
# Supports both full and partial refunds.
|
|
107
|
+
#
|
|
108
|
+
# @param payment_id [String] the unique payment identifier of a captured payment
|
|
109
|
+
# @param params [Hash] optional refund parameters:
|
|
110
|
+
# - :amount [Integer] refund amount in minor units (for partial refunds)
|
|
111
|
+
# - :reason [String] reason for the refund
|
|
112
|
+
# @return [Hash] refund response including refund ID and status
|
|
113
|
+
# @raise [InvalidRequestError] if payment cannot be refunded
|
|
58
114
|
#
|
|
59
|
-
# @param payment_id [String] payment ID
|
|
60
|
-
# @param params [Hash] refund parameters
|
|
61
|
-
# @return [Hash] refund response
|
|
62
115
|
def refund_payment(payment_id, params = {})
|
|
63
|
-
post("/v1/charge/#{payment_id}/refund", params)
|
|
116
|
+
post("/v1/charge/#{payment_id}/refund", body: params)
|
|
64
117
|
end
|
|
65
118
|
|
|
66
|
-
#
|
|
119
|
+
# Settles a payment for final processing.
|
|
120
|
+
# Note: This method appears to have a bug and returns config.api_url instead of making an API call.
|
|
67
121
|
#
|
|
68
122
|
# @param params [Hash] settlement parameters
|
|
69
|
-
# @return [
|
|
123
|
+
# @return [String] currently returns the API URL (likely unintended behavior)
|
|
124
|
+
# @todo Fix this method to properly call the settlement endpoint
|
|
125
|
+
#
|
|
70
126
|
def settle_payment(params = {})
|
|
71
127
|
conifg.api_url
|
|
72
128
|
end
|
|
73
129
|
|
|
74
|
-
#
|
|
130
|
+
# Creates a new recurring subscription.
|
|
131
|
+
#
|
|
132
|
+
# @param params [Hash] subscription parameters including:
|
|
133
|
+
# - :product_id [String] Solidgate product identifier
|
|
134
|
+
# - :customer_account_id [String] unique customer identifier
|
|
135
|
+
# - :order_id [String] unique order identifier
|
|
136
|
+
# - :payment_method [Hash] payment method details
|
|
137
|
+
# @return [Hash] subscription response including subscription ID and status
|
|
138
|
+
# @raise [InvalidRequestError] if subscription parameters are invalid
|
|
75
139
|
#
|
|
76
|
-
# @param params [Hash] subscription parameters
|
|
77
|
-
# @return [Hash] subscription response
|
|
78
140
|
def create_subscription(params)
|
|
79
|
-
post("/v1/subscription", params)
|
|
141
|
+
post("/v1/subscription", body: params)
|
|
80
142
|
end
|
|
81
143
|
|
|
82
|
-
#
|
|
144
|
+
# Retrieves the current status and details of a subscription.
|
|
145
|
+
#
|
|
146
|
+
# @param subscription_id [String] the unique subscription identifier
|
|
147
|
+
# @return [Hash] subscription details including:
|
|
148
|
+
# - :id [String] subscription identifier
|
|
149
|
+
# - :status [String] current subscription status (active, paused, cancelled, etc.)
|
|
150
|
+
# - :current_period_start [String] start of current billing period
|
|
151
|
+
# - :current_period_end [String] end of current billing period
|
|
152
|
+
# @raise [InvalidRequestError] if subscription_id is not found
|
|
83
153
|
#
|
|
84
|
-
# @param subscription_id [String] subscription ID
|
|
85
|
-
# @return [Hash] subscription details
|
|
86
154
|
def subscription_status(subscription_id)
|
|
87
|
-
post("/api/v1/subscription/status", { subscription_id: subscription_id })
|
|
155
|
+
post("/api/v1/subscription/status", body: { subscription_id: subscription_id })
|
|
88
156
|
end
|
|
89
157
|
|
|
90
|
-
#
|
|
158
|
+
# Switches a subscription to a different product/plan.
|
|
159
|
+
# Use this for upgrades, downgrades, or plan changes.
|
|
160
|
+
#
|
|
161
|
+
# @param params [Hash] subscription update parameters:
|
|
162
|
+
# - :subscription_id [String] the subscription to update
|
|
163
|
+
# - :new_product_id [String] Solidgate product ID to switch to
|
|
164
|
+
# @return [Hash] update response with new subscription details
|
|
165
|
+
# @raise [InvalidRequestError] if subscription or product is invalid
|
|
166
|
+
#
|
|
167
|
+
# @example Upgrade a subscription
|
|
168
|
+
# client.switch_subscription_product(
|
|
169
|
+
# subscription_id: 'sub_12345',
|
|
170
|
+
# new_product_id: 'prod_premium_67890'
|
|
171
|
+
# )
|
|
91
172
|
#
|
|
92
|
-
# @param params [Hash] subscription update parameters
|
|
93
|
-
# @return [Hash] update response
|
|
94
|
-
# params = { subscription_id: "sub_12345", new_product_id: "prod_67890" }
|
|
95
|
-
# new product_id is the Solidgate ID of the product to switch to
|
|
96
173
|
def switch_subscription_product(params)
|
|
97
|
-
post("/api/v1/subscription/switch-subscription-product", params)
|
|
174
|
+
post("/api/v1/subscription/switch-subscription-product", body: params)
|
|
98
175
|
end
|
|
99
176
|
|
|
177
|
+
# Updates an existing pause schedule for a subscription.
|
|
178
|
+
#
|
|
179
|
+
# @param subscription_id [String] the unique subscription identifier
|
|
180
|
+
# @param params [Hash] pause schedule update parameters:
|
|
181
|
+
# - :pause_at [String] new date/time to pause the subscription
|
|
182
|
+
# - :resume_at [String] new date/time to resume the subscription
|
|
183
|
+
# @return [Hash] updated pause schedule details
|
|
184
|
+
# @raise [InvalidRequestError] if subscription has no pause schedule or params are invalid
|
|
185
|
+
#
|
|
100
186
|
def update_subscription_pause(subscription_id, params)
|
|
101
|
-
patch("/api/v1/subscriptions/#{subscription_id}/pause-schedule", params)
|
|
187
|
+
patch("/api/v1/subscriptions/#{subscription_id}/pause-schedule", body: params)
|
|
102
188
|
end
|
|
103
189
|
|
|
190
|
+
# Creates a pause schedule for a subscription.
|
|
191
|
+
# The subscription will be paused and resumed at the specified times.
|
|
192
|
+
#
|
|
193
|
+
# @param subscription_id [String] the unique subscription identifier
|
|
194
|
+
# @param params [Hash] pause schedule parameters:
|
|
195
|
+
# - :pause_at [String] date/time to pause the subscription
|
|
196
|
+
# - :resume_at [String] date/time to resume the subscription
|
|
197
|
+
# @return [Hash] created pause schedule details
|
|
198
|
+
# @raise [InvalidRequestError] if subscription is invalid or already has a pause schedule
|
|
199
|
+
#
|
|
104
200
|
def create_subscription_pause(subscription_id, params)
|
|
105
|
-
post("/api/v1/subscriptions/#{subscription_id}/pause-schedule", params)
|
|
201
|
+
post("/api/v1/subscriptions/#{subscription_id}/pause-schedule", body: params)
|
|
106
202
|
end
|
|
107
203
|
|
|
204
|
+
# Deletes/cancels a pending pause schedule for a subscription.
|
|
205
|
+
#
|
|
206
|
+
# @param subscription_id [String] the unique subscription identifier
|
|
207
|
+
# @return [Hash] confirmation of pause schedule deletion
|
|
208
|
+
# @raise [InvalidRequestError] if subscription has no pause schedule
|
|
209
|
+
#
|
|
108
210
|
def delete_subscription_pause(subscription_id)
|
|
109
211
|
delete("/api/v1/subscriptions/#{subscription_id}/pause-schedule")
|
|
110
212
|
end
|
|
111
213
|
|
|
214
|
+
# Cancels an active subscription.
|
|
215
|
+
#
|
|
216
|
+
# @param params [Hash] cancellation parameters:
|
|
217
|
+
# - :subscription_id [String] the subscription to cancel
|
|
218
|
+
# - :cancel_at_period_end [Boolean] if true, cancel at end of current period
|
|
219
|
+
# - :reason [String] optional cancellation reason
|
|
220
|
+
# @return [Hash] cancelled subscription details
|
|
221
|
+
# @raise [InvalidRequestError] if subscription is invalid or already cancelled
|
|
222
|
+
#
|
|
112
223
|
def cancel_subscription(params)
|
|
113
|
-
post("/api/v1/subscription/cancel", params)
|
|
224
|
+
post("/api/v1/subscription/cancel", body: params)
|
|
114
225
|
end
|
|
115
226
|
|
|
227
|
+
# Creates a new product in the Solidgate catalog.
|
|
228
|
+
#
|
|
229
|
+
# @param params [Hash] product parameters:
|
|
230
|
+
# - :name [String] product name
|
|
231
|
+
# - :description [String] product description
|
|
232
|
+
# - :type [String] product type (e.g., 'subscription', 'one_time')
|
|
233
|
+
# @return [Hash] created product details including product_id
|
|
234
|
+
# @raise [InvalidRequestError] if product parameters are invalid
|
|
235
|
+
#
|
|
116
236
|
def create_product(params)
|
|
117
|
-
post("/api/v1/products", params)
|
|
237
|
+
post("/api/v1/products", body: params)
|
|
118
238
|
end
|
|
119
239
|
|
|
240
|
+
# Creates a new price for an existing product.
|
|
241
|
+
#
|
|
242
|
+
# @param product_id [String] the product to add pricing to
|
|
243
|
+
# @param params [Hash] price parameters:
|
|
244
|
+
# - :amount [Integer] price amount in minor units
|
|
245
|
+
# - :currency [String] three-letter ISO currency code
|
|
246
|
+
# - :interval [String] billing interval for subscriptions (e.g., 'month', 'year')
|
|
247
|
+
# @return [Hash] created price details including price_id
|
|
248
|
+
# @raise [InvalidRequestError] if product_id is invalid or price params are invalid
|
|
249
|
+
#
|
|
120
250
|
def create_price(product_id, params)
|
|
121
|
-
post("/api/v1/products/#{product_id}/prices", params)
|
|
251
|
+
post("/api/v1/products/#{product_id}/prices", body: params)
|
|
122
252
|
end
|
|
123
253
|
|
|
254
|
+
# Retrieves all products from the Solidgate catalog.
|
|
255
|
+
#
|
|
256
|
+
# @return [Hash] list of all products with their details
|
|
257
|
+
#
|
|
124
258
|
def products
|
|
125
259
|
get("/api/v1/products")
|
|
126
260
|
end
|
|
127
261
|
|
|
262
|
+
# Retrieves all prices for a specific product.
|
|
263
|
+
#
|
|
264
|
+
# @param product_id [String] the product to retrieve prices for
|
|
265
|
+
# @return [Hash] list of prices associated with the product
|
|
266
|
+
# @raise [InvalidRequestError] if product_id is not found
|
|
267
|
+
#
|
|
128
268
|
def product_prices(product_id)
|
|
129
269
|
get("/api/v1/products/#{product_id}/prices")
|
|
130
270
|
end
|
|
131
271
|
|
|
272
|
+
# Generates an encrypted payment intent for client-side payment form rendering.
|
|
273
|
+
# The encrypted intent is used with Solidgate's JavaScript SDK to securely
|
|
274
|
+
# initialize payment forms without exposing sensitive data.
|
|
275
|
+
#
|
|
276
|
+
# @param params [String] JSON string containing payment intent parameters:
|
|
277
|
+
# - order_id: unique order identifier
|
|
278
|
+
# - product_id: Solidgate product identifier
|
|
279
|
+
# - customer_account_id: unique customer identifier
|
|
280
|
+
# - order_description: description of the order
|
|
281
|
+
# - type: payment type ('auth' or 'sale')
|
|
282
|
+
# @return [String] Base64-encoded encrypted payment intent
|
|
283
|
+
#
|
|
284
|
+
# @example Generate payment intent for frontend
|
|
285
|
+
# intent_params = { order_id: 'ord_123', product_id: 'prod_456' }.to_json
|
|
286
|
+
# encrypted_intent = client.generate_intent(intent_params)
|
|
287
|
+
#
|
|
132
288
|
def generate_intent(params)
|
|
133
289
|
encrypt_payload(params)
|
|
134
290
|
end
|
|
135
291
|
|
|
292
|
+
# Generates an HMAC-SHA512 signature for API request authentication.
|
|
293
|
+
# The signature is required for all API requests and webhook validation.
|
|
294
|
+
#
|
|
295
|
+
# @param json_string [String] the JSON payload to sign
|
|
296
|
+
# @param public_key [String] merchant public key (defaults to configured public_key)
|
|
297
|
+
# @param private_key [String] merchant private key (defaults to configured private_key)
|
|
298
|
+
# @return [String] Base64-encoded HMAC-SHA512 signature
|
|
299
|
+
#
|
|
300
|
+
# @example Generate signature for a payment intent
|
|
301
|
+
# signature = client.generate_signature(encrypted_intent)
|
|
302
|
+
#
|
|
136
303
|
def generate_signature(json_string, public_key: config.public_key, private_key: config.private_key)
|
|
137
304
|
digest = OpenSSL::Digest.new('sha512')
|
|
138
305
|
instance = OpenSSL::HMAC.new(private_key, digest)
|
|
@@ -140,8 +307,46 @@ module Solidgate
|
|
|
140
307
|
Base64.strict_encode64(instance.hexdigest)
|
|
141
308
|
end
|
|
142
309
|
|
|
310
|
+
# Restores a previously cancelled subscription.
|
|
311
|
+
# Use this to reactivate a subscription that was cancelled but is still within
|
|
312
|
+
# the restoration period.
|
|
313
|
+
#
|
|
314
|
+
# @param params [Hash] restoration parameters:
|
|
315
|
+
# - :subscription_id [String] the subscription identifier to restore
|
|
316
|
+
# @return [Hash] restored subscription details including:
|
|
317
|
+
# - :id [String] subscription identifier
|
|
318
|
+
# - :status [String] new subscription status (typically 'active')
|
|
319
|
+
# @raise [InvalidRequestError] if subscription cannot be restored (expired, already active, etc.)
|
|
320
|
+
#
|
|
321
|
+
# @example Restore a cancelled subscription
|
|
322
|
+
# client.restore_subscription(subscription_id: 'sub_12345')
|
|
323
|
+
#
|
|
324
|
+
def restore_subscription(params)
|
|
325
|
+
post("/api/v1/subscription/restore", body: params)
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
# Creates a refund for a transaction.
|
|
329
|
+
#
|
|
330
|
+
# @param params [Hash] refund parameters:
|
|
331
|
+
# - :order_id [String] the order identifier to refund
|
|
332
|
+
# - :amount [Integer] refund amount in minor units (for partial refunds)
|
|
333
|
+
# @return [Hash] refund response including refund status and details
|
|
334
|
+
# @raise [InvalidRequestError] if refund parameters are invalid
|
|
335
|
+
#
|
|
336
|
+
# @example Create a refund
|
|
337
|
+
# client.refund(order_id: 'ord_12345', amount: 1000)
|
|
338
|
+
#
|
|
339
|
+
def refund(params)
|
|
340
|
+
post("/api/v1/refund", body: params, base_url: "https://pay.solidgate.com")
|
|
341
|
+
end
|
|
342
|
+
|
|
143
343
|
private
|
|
144
344
|
|
|
345
|
+
# Builds a Configuration object from the provided options.
|
|
346
|
+
#
|
|
347
|
+
# @param options [Configuration, Hash] configuration options
|
|
348
|
+
# @return [Configuration] the configuration object
|
|
349
|
+
#
|
|
145
350
|
def build_config(options)
|
|
146
351
|
if options.is_a?(Configuration)
|
|
147
352
|
options
|
|
@@ -152,9 +357,22 @@ module Solidgate
|
|
|
152
357
|
end
|
|
153
358
|
end
|
|
154
359
|
|
|
360
|
+
# Creates and caches a Faraday HTTP connection.
|
|
361
|
+
#
|
|
362
|
+
# @return [Faraday::Connection] configured HTTP connection
|
|
363
|
+
#
|
|
155
364
|
def connection
|
|
156
|
-
@connection ||=
|
|
157
|
-
|
|
365
|
+
@connection ||= connection_for(config.api_url)
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
# Creates a Faraday HTTP connection for the specified base URL.
|
|
369
|
+
#
|
|
370
|
+
# @param base_url [String] the base URL for the connection
|
|
371
|
+
# @return [Faraday::Connection] configured HTTP connection
|
|
372
|
+
#
|
|
373
|
+
def connection_for(base_url)
|
|
374
|
+
Faraday.new(
|
|
375
|
+
url: base_url,
|
|
158
376
|
headers: default_headers
|
|
159
377
|
) do |conn|
|
|
160
378
|
conn.request :multipart
|
|
@@ -167,6 +385,10 @@ module Solidgate
|
|
|
167
385
|
end
|
|
168
386
|
end
|
|
169
387
|
|
|
388
|
+
# Returns default HTTP headers for API requests.
|
|
389
|
+
#
|
|
390
|
+
# @return [Hash] default headers including Accept, Content-Type, and User-Agent
|
|
391
|
+
#
|
|
170
392
|
def default_headers
|
|
171
393
|
{
|
|
172
394
|
"Accept" => "application/json",
|
|
@@ -175,27 +397,63 @@ module Solidgate
|
|
|
175
397
|
}
|
|
176
398
|
end
|
|
177
399
|
|
|
400
|
+
# Performs a GET request to the specified path.
|
|
401
|
+
#
|
|
402
|
+
# @param path [String] API endpoint path
|
|
403
|
+
# @return [Hash] parsed response body
|
|
404
|
+
#
|
|
178
405
|
def get(path)
|
|
179
406
|
request(:get, path)
|
|
180
407
|
end
|
|
181
408
|
|
|
182
|
-
|
|
183
|
-
|
|
409
|
+
# Performs a POST request to the specified path.
|
|
410
|
+
#
|
|
411
|
+
# @param path [String] API endpoint path
|
|
412
|
+
# @param body [Hash] request body parameters
|
|
413
|
+
# @param base_url [String, nil] optional base URL to override the default API URL
|
|
414
|
+
# @return [Hash] parsed response body
|
|
415
|
+
#
|
|
416
|
+
def post(path, body: {}, base_url: nil)
|
|
417
|
+
request(:post, path, body: body, base_url: base_url)
|
|
184
418
|
end
|
|
185
419
|
|
|
186
|
-
|
|
187
|
-
|
|
420
|
+
# Performs a PATCH request to the specified path.
|
|
421
|
+
#
|
|
422
|
+
# @param path [String] API endpoint path
|
|
423
|
+
# @param body [Hash] request body parameters
|
|
424
|
+
# @return [Hash] parsed response body
|
|
425
|
+
#
|
|
426
|
+
def patch(path, body: {})
|
|
427
|
+
request(:patch, path, body: body)
|
|
188
428
|
end
|
|
189
429
|
|
|
430
|
+
# Performs a DELETE request to the specified path.
|
|
431
|
+
#
|
|
432
|
+
# @param path [String] API endpoint path
|
|
433
|
+
# @return [Hash] parsed response body
|
|
434
|
+
#
|
|
190
435
|
def delete(path)
|
|
191
436
|
request(:delete, path)
|
|
192
437
|
end
|
|
193
438
|
|
|
194
|
-
|
|
439
|
+
# Performs an HTTP request with authentication and signature.
|
|
440
|
+
#
|
|
441
|
+
# @param method [Symbol] HTTP method (:get, :post, :patch, :delete)
|
|
442
|
+
# @param path [String] API endpoint path
|
|
443
|
+
# @param body [Hash, nil] optional request body
|
|
444
|
+
# @param base_url [String, nil] optional base URL to override the default API URL
|
|
445
|
+
# @return [Hash] parsed response body
|
|
446
|
+
# @raise [TimeoutError] if request times out
|
|
447
|
+
# @raise [ConnectionError] if connection fails
|
|
448
|
+
# @raise [Error] for other unexpected errors
|
|
449
|
+
#
|
|
450
|
+
def request(method, path, body: nil, base_url: nil)
|
|
195
451
|
body_json = body ? JSON.generate(body) : ''
|
|
196
452
|
signature = generate_signature(body_json)
|
|
197
453
|
|
|
198
|
-
|
|
454
|
+
conn = base_url ? connection_for(base_url) : connection
|
|
455
|
+
|
|
456
|
+
response = conn.send(method) do |req|
|
|
199
457
|
req.url path
|
|
200
458
|
req.headers["Merchant"] = config.public_key
|
|
201
459
|
req.headers["Signature"] = signature
|
|
@@ -211,6 +469,15 @@ module Solidgate
|
|
|
211
469
|
raise Error, "Unexpected error: #{e.message}"
|
|
212
470
|
end
|
|
213
471
|
|
|
472
|
+
# Handles HTTP response and raises appropriate errors for non-success statuses.
|
|
473
|
+
#
|
|
474
|
+
# @param response [Faraday::Response] the HTTP response object
|
|
475
|
+
# @return [Hash] parsed response body for successful requests
|
|
476
|
+
# @raise [InvalidRequestError] for 400 status
|
|
477
|
+
# @raise [AuthenticationError] for 401 status
|
|
478
|
+
# @raise [RateLimitError] for 429 status
|
|
479
|
+
# @raise [APIError] for 5xx statuses and unknown errors
|
|
480
|
+
#
|
|
214
481
|
def handle_response(response)
|
|
215
482
|
case response.status
|
|
216
483
|
when 200..299
|
|
@@ -253,6 +520,11 @@ module Solidgate
|
|
|
253
520
|
end
|
|
254
521
|
end
|
|
255
522
|
|
|
523
|
+
# Extracts error message from API error response.
|
|
524
|
+
#
|
|
525
|
+
# @param response [Faraday::Response] the HTTP response object
|
|
526
|
+
# @return [String] error message or "Unknown error" if not found
|
|
527
|
+
#
|
|
256
528
|
def extract_error_message(response)
|
|
257
529
|
return "Unknown error" unless response.body.is_a?(Hash)
|
|
258
530
|
|
|
@@ -261,6 +533,11 @@ module Solidgate
|
|
|
261
533
|
"Unknown error"
|
|
262
534
|
end
|
|
263
535
|
|
|
536
|
+
# Extracts error code from API error response.
|
|
537
|
+
#
|
|
538
|
+
# @param response [Faraday::Response] the HTTP response object
|
|
539
|
+
# @return [String, nil] error code or nil if not found
|
|
540
|
+
#
|
|
264
541
|
def extract_error_code(response)
|
|
265
542
|
return nil unless response.body.is_a?(Hash)
|
|
266
543
|
|
|
@@ -269,6 +546,12 @@ module Solidgate
|
|
|
269
546
|
nil
|
|
270
547
|
end
|
|
271
548
|
|
|
549
|
+
# Encrypts payload using AES-256-CBC encryption for secure transmission.
|
|
550
|
+
# Uses the first 32 characters of the private key as the encryption key.
|
|
551
|
+
#
|
|
552
|
+
# @param attributes [String] JSON string to encrypt
|
|
553
|
+
# @return [String] URL-safe Base64-encoded encrypted payload (IV prepended)
|
|
554
|
+
#
|
|
272
555
|
def encrypt_payload(attributes)
|
|
273
556
|
key = config.private_key[0, KEY_LENGTH]
|
|
274
557
|
iv = OpenSSL::Random.random_bytes(IV_LENGTH)
|
data/lib/solidgate/payment.rb
CHANGED
|
@@ -64,14 +64,15 @@ module Solidgate
|
|
|
64
64
|
# @param amount [Integer] amount to refund in cents (optional, defaults to full amount)
|
|
65
65
|
# @param reason [String] refund reason (optional)
|
|
66
66
|
# @return [Hash] refund response
|
|
67
|
-
def refund(
|
|
68
|
-
raise ArgumentError, "
|
|
67
|
+
def refund(order_id, amount: nil, reason: nil)
|
|
68
|
+
raise ArgumentError, "order_id is required" if order_id.nil? || order_id.empty?
|
|
69
69
|
|
|
70
70
|
params = {}
|
|
71
|
-
params[:amount]
|
|
72
|
-
params[:reason]
|
|
71
|
+
params[:amount] = amount if amount
|
|
72
|
+
params[:reason] = reason if reason
|
|
73
|
+
params[:order_id] = order_id
|
|
73
74
|
|
|
74
|
-
client.
|
|
75
|
+
client.refund(params)
|
|
75
76
|
end
|
|
76
77
|
|
|
77
78
|
private
|
data/lib/solidgate/version.rb
CHANGED
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.
|
|
4
|
+
version: 0.1.10
|
|
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-
|
|
11
|
+
date: 2026-02-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|