billingio 1.0.0 → 2.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.
- checksums.yaml +4 -4
- data/README.md +226 -1
- data/billingio.gemspec +4 -3
- data/lib/billingio/client.rb +55 -0
- data/lib/billingio/http_client.rb +10 -0
- data/lib/billingio/models/accounting_report.rb +46 -0
- data/lib/billingio/models/adjustment.rb +46 -0
- data/lib/billingio/models/customer.rb +46 -0
- data/lib/billingio/models/entitlement.rb +46 -0
- data/lib/billingio/models/entitlement_check.rb +39 -0
- data/lib/billingio/models/payment_link.rb +47 -0
- data/lib/billingio/models/payment_method.rb +51 -0
- data/lib/billingio/models/payout_intent.rb +51 -0
- data/lib/billingio/models/revenue_event.rb +49 -0
- data/lib/billingio/models/settlement.rb +51 -0
- data/lib/billingio/models/subscription.rb +50 -0
- data/lib/billingio/models/subscription_plan.rb +51 -0
- data/lib/billingio/models/subscription_renewal.rb +49 -0
- data/lib/billingio/resources/adjustments.rb +52 -0
- data/lib/billingio/resources/customers.rb +75 -0
- data/lib/billingio/resources/entitlements.rb +95 -0
- data/lib/billingio/resources/payment_links.rb +47 -0
- data/lib/billingio/resources/payment_methods.rb +91 -0
- data/lib/billingio/resources/payout_intents.rb +78 -0
- data/lib/billingio/resources/revenue_events.rb +47 -0
- data/lib/billingio/resources/settlements.rb +30 -0
- data/lib/billingio/resources/subscription_plans.rb +71 -0
- data/lib/billingio/resources/subscription_renewals.rb +42 -0
- data/lib/billingio/resources/subscriptions.rb +67 -0
- data/lib/billingio/version.rb +1 -1
- data/lib/billingio.rb +24 -0
- metadata +30 -6
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BillingIO
|
|
4
|
+
# Represents a payout intent (withdrawal request).
|
|
5
|
+
#
|
|
6
|
+
# @attr_reader payout_id [String] unique identifier (prefixed +po_+)
|
|
7
|
+
# @attr_reader amount_usd [Float] payout amount in USD
|
|
8
|
+
# @attr_reader chain [String] blockchain network
|
|
9
|
+
# @attr_reader token [String] stablecoin token
|
|
10
|
+
# @attr_reader destination [String] destination wallet address
|
|
11
|
+
# @attr_reader tx_hash [String, nil] on-chain transaction hash
|
|
12
|
+
# @attr_reader status [String] payout status
|
|
13
|
+
# @attr_reader metadata [Hash, nil] arbitrary key-value pairs
|
|
14
|
+
# @attr_reader executed_at [String, nil] ISO-8601 execution timestamp
|
|
15
|
+
# @attr_reader created_at [String] ISO-8601 creation timestamp
|
|
16
|
+
# @attr_reader updated_at [String] ISO-8601 last-update timestamp
|
|
17
|
+
class PayoutIntent
|
|
18
|
+
ATTRS = %i[
|
|
19
|
+
payout_id amount_usd chain token destination
|
|
20
|
+
tx_hash status metadata
|
|
21
|
+
executed_at created_at updated_at
|
|
22
|
+
].freeze
|
|
23
|
+
|
|
24
|
+
attr_reader(*ATTRS)
|
|
25
|
+
|
|
26
|
+
# @param attrs [Hash{String,Symbol => Object}]
|
|
27
|
+
def initialize(attrs = {})
|
|
28
|
+
ATTRS.each do |attr|
|
|
29
|
+
value = attrs[attr.to_s] || attrs[attr]
|
|
30
|
+
instance_variable_set(:"@#{attr}", value)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @param hash [Hash]
|
|
35
|
+
# @return [BillingIO::PayoutIntent]
|
|
36
|
+
def self.from_hash(hash)
|
|
37
|
+
new(hash)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @return [Hash{String => Object}]
|
|
41
|
+
def to_h
|
|
42
|
+
ATTRS.each_with_object({}) do |attr, h|
|
|
43
|
+
h[attr.to_s] = instance_variable_get(:"@#{attr}")
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def inspect
|
|
48
|
+
"#<BillingIO::PayoutIntent payout_id=#{@payout_id.inspect} amount_usd=#{@amount_usd.inspect} status=#{@status.inspect}>"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BillingIO
|
|
4
|
+
# Represents a revenue event for reporting.
|
|
5
|
+
#
|
|
6
|
+
# @attr_reader revenue_event_id [String] unique identifier (prefixed +rev_+)
|
|
7
|
+
# @attr_reader type [String] event type (e.g. "payment", "refund")
|
|
8
|
+
# @attr_reader amount_usd [Float] revenue amount in USD
|
|
9
|
+
# @attr_reader customer_id [String, nil] related customer
|
|
10
|
+
# @attr_reader checkout_id [String, nil] related checkout
|
|
11
|
+
# @attr_reader subscription_id [String, nil] related subscription
|
|
12
|
+
# @attr_reader metadata [Hash, nil] arbitrary key-value pairs
|
|
13
|
+
# @attr_reader occurred_at [String] ISO-8601 event timestamp
|
|
14
|
+
# @attr_reader created_at [String] ISO-8601 creation timestamp
|
|
15
|
+
class RevenueEvent
|
|
16
|
+
ATTRS = %i[
|
|
17
|
+
revenue_event_id type amount_usd
|
|
18
|
+
customer_id checkout_id subscription_id
|
|
19
|
+
metadata occurred_at created_at
|
|
20
|
+
].freeze
|
|
21
|
+
|
|
22
|
+
attr_reader(*ATTRS)
|
|
23
|
+
|
|
24
|
+
# @param attrs [Hash{String,Symbol => Object}]
|
|
25
|
+
def initialize(attrs = {})
|
|
26
|
+
ATTRS.each do |attr|
|
|
27
|
+
value = attrs[attr.to_s] || attrs[attr]
|
|
28
|
+
instance_variable_set(:"@#{attr}", value)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @param hash [Hash]
|
|
33
|
+
# @return [BillingIO::RevenueEvent]
|
|
34
|
+
def self.from_hash(hash)
|
|
35
|
+
new(hash)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @return [Hash{String => Object}]
|
|
39
|
+
def to_h
|
|
40
|
+
ATTRS.each_with_object({}) do |attr, h|
|
|
41
|
+
h[attr.to_s] = instance_variable_get(:"@#{attr}")
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def inspect
|
|
46
|
+
"#<BillingIO::RevenueEvent revenue_event_id=#{@revenue_event_id.inspect} type=#{@type.inspect} amount_usd=#{@amount_usd.inspect}>"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BillingIO
|
|
4
|
+
# Represents a payout settlement record.
|
|
5
|
+
#
|
|
6
|
+
# @attr_reader settlement_id [String] unique identifier (prefixed +stl_+)
|
|
7
|
+
# @attr_reader payout_id [String] parent payout intent
|
|
8
|
+
# @attr_reader amount_usd [Float] settled amount in USD
|
|
9
|
+
# @attr_reader fee_usd [Float] fee amount in USD
|
|
10
|
+
# @attr_reader net_usd [Float] net amount in USD
|
|
11
|
+
# @attr_reader chain [String] blockchain network
|
|
12
|
+
# @attr_reader token [String] stablecoin token
|
|
13
|
+
# @attr_reader tx_hash [String, nil] on-chain transaction hash
|
|
14
|
+
# @attr_reader status [String] settlement status
|
|
15
|
+
# @attr_reader settled_at [String, nil] ISO-8601 settlement timestamp
|
|
16
|
+
# @attr_reader created_at [String] ISO-8601 creation timestamp
|
|
17
|
+
class Settlement
|
|
18
|
+
ATTRS = %i[
|
|
19
|
+
settlement_id payout_id amount_usd fee_usd net_usd
|
|
20
|
+
chain token tx_hash status
|
|
21
|
+
settled_at created_at
|
|
22
|
+
].freeze
|
|
23
|
+
|
|
24
|
+
attr_reader(*ATTRS)
|
|
25
|
+
|
|
26
|
+
# @param attrs [Hash{String,Symbol => Object}]
|
|
27
|
+
def initialize(attrs = {})
|
|
28
|
+
ATTRS.each do |attr|
|
|
29
|
+
value = attrs[attr.to_s] || attrs[attr]
|
|
30
|
+
instance_variable_set(:"@#{attr}", value)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @param hash [Hash]
|
|
35
|
+
# @return [BillingIO::Settlement]
|
|
36
|
+
def self.from_hash(hash)
|
|
37
|
+
new(hash)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @return [Hash{String => Object}]
|
|
41
|
+
def to_h
|
|
42
|
+
ATTRS.each_with_object({}) do |attr, h|
|
|
43
|
+
h[attr.to_s] = instance_variable_get(:"@#{attr}")
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def inspect
|
|
48
|
+
"#<BillingIO::Settlement settlement_id=#{@settlement_id.inspect} amount_usd=#{@amount_usd.inspect} status=#{@status.inspect}>"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BillingIO
|
|
4
|
+
# Represents an active subscription.
|
|
5
|
+
#
|
|
6
|
+
# @attr_reader subscription_id [String] unique identifier (prefixed +sub_+)
|
|
7
|
+
# @attr_reader customer_id [String] owning customer
|
|
8
|
+
# @attr_reader plan_id [String] associated plan
|
|
9
|
+
# @attr_reader status [String] subscription status
|
|
10
|
+
# @attr_reader current_period_start [String, nil] ISO-8601 current period start
|
|
11
|
+
# @attr_reader current_period_end [String, nil] ISO-8601 current period end
|
|
12
|
+
# @attr_reader canceled_at [String, nil] ISO-8601 cancellation timestamp
|
|
13
|
+
# @attr_reader metadata [Hash, nil] arbitrary key-value pairs
|
|
14
|
+
# @attr_reader created_at [String] ISO-8601 creation timestamp
|
|
15
|
+
# @attr_reader updated_at [String] ISO-8601 last-update timestamp
|
|
16
|
+
class Subscription
|
|
17
|
+
ATTRS = %i[
|
|
18
|
+
subscription_id customer_id plan_id status
|
|
19
|
+
current_period_start current_period_end
|
|
20
|
+
canceled_at metadata created_at updated_at
|
|
21
|
+
].freeze
|
|
22
|
+
|
|
23
|
+
attr_reader(*ATTRS)
|
|
24
|
+
|
|
25
|
+
# @param attrs [Hash{String,Symbol => Object}]
|
|
26
|
+
def initialize(attrs = {})
|
|
27
|
+
ATTRS.each do |attr|
|
|
28
|
+
value = attrs[attr.to_s] || attrs[attr]
|
|
29
|
+
instance_variable_set(:"@#{attr}", value)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @param hash [Hash]
|
|
34
|
+
# @return [BillingIO::Subscription]
|
|
35
|
+
def self.from_hash(hash)
|
|
36
|
+
new(hash)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @return [Hash{String => Object}]
|
|
40
|
+
def to_h
|
|
41
|
+
ATTRS.each_with_object({}) do |attr, h|
|
|
42
|
+
h[attr.to_s] = instance_variable_get(:"@#{attr}")
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def inspect
|
|
47
|
+
"#<BillingIO::Subscription subscription_id=#{@subscription_id.inspect} plan_id=#{@plan_id.inspect} status=#{@status.inspect}>"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BillingIO
|
|
4
|
+
# Represents a subscription plan template.
|
|
5
|
+
#
|
|
6
|
+
# @attr_reader plan_id [String] unique identifier (prefixed +plan_+)
|
|
7
|
+
# @attr_reader name [String] human-readable plan name
|
|
8
|
+
# @attr_reader amount_usd [Float] recurring amount in USD
|
|
9
|
+
# @attr_reader interval [String] billing interval (e.g. "monthly", "yearly")
|
|
10
|
+
# @attr_reader interval_count [Integer] number of intervals between billings
|
|
11
|
+
# @attr_reader chain [String, nil] blockchain network
|
|
12
|
+
# @attr_reader token [String, nil] stablecoin token
|
|
13
|
+
# @attr_reader metadata [Hash, nil] arbitrary key-value pairs
|
|
14
|
+
# @attr_reader status [String] plan status
|
|
15
|
+
# @attr_reader created_at [String] ISO-8601 creation timestamp
|
|
16
|
+
# @attr_reader updated_at [String] ISO-8601 last-update timestamp
|
|
17
|
+
class SubscriptionPlan
|
|
18
|
+
ATTRS = %i[
|
|
19
|
+
plan_id name amount_usd interval interval_count
|
|
20
|
+
chain token metadata status
|
|
21
|
+
created_at updated_at
|
|
22
|
+
].freeze
|
|
23
|
+
|
|
24
|
+
attr_reader(*ATTRS)
|
|
25
|
+
|
|
26
|
+
# @param attrs [Hash{String,Symbol => Object}]
|
|
27
|
+
def initialize(attrs = {})
|
|
28
|
+
ATTRS.each do |attr|
|
|
29
|
+
value = attrs[attr.to_s] || attrs[attr]
|
|
30
|
+
instance_variable_set(:"@#{attr}", value)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @param hash [Hash]
|
|
35
|
+
# @return [BillingIO::SubscriptionPlan]
|
|
36
|
+
def self.from_hash(hash)
|
|
37
|
+
new(hash)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @return [Hash{String => Object}]
|
|
41
|
+
def to_h
|
|
42
|
+
ATTRS.each_with_object({}) do |attr, h|
|
|
43
|
+
h[attr.to_s] = instance_variable_get(:"@#{attr}")
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def inspect
|
|
48
|
+
"#<BillingIO::SubscriptionPlan plan_id=#{@plan_id.inspect} name=#{@name.inspect} amount_usd=#{@amount_usd.inspect}>"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BillingIO
|
|
4
|
+
# Represents a subscription renewal attempt.
|
|
5
|
+
#
|
|
6
|
+
# @attr_reader renewal_id [String] unique identifier (prefixed +ren_+)
|
|
7
|
+
# @attr_reader subscription_id [String] parent subscription
|
|
8
|
+
# @attr_reader status [String] renewal status
|
|
9
|
+
# @attr_reader amount_usd [Float] renewal amount in USD
|
|
10
|
+
# @attr_reader attempt_count [Integer] number of attempts made
|
|
11
|
+
# @attr_reader next_retry_at [String, nil] ISO-8601 next retry timestamp
|
|
12
|
+
# @attr_reader checkout_id [String, nil] checkout created for this renewal
|
|
13
|
+
# @attr_reader created_at [String] ISO-8601 creation timestamp
|
|
14
|
+
# @attr_reader updated_at [String] ISO-8601 last-update timestamp
|
|
15
|
+
class SubscriptionRenewal
|
|
16
|
+
ATTRS = %i[
|
|
17
|
+
renewal_id subscription_id status amount_usd
|
|
18
|
+
attempt_count next_retry_at checkout_id
|
|
19
|
+
created_at updated_at
|
|
20
|
+
].freeze
|
|
21
|
+
|
|
22
|
+
attr_reader(*ATTRS)
|
|
23
|
+
|
|
24
|
+
# @param attrs [Hash{String,Symbol => Object}]
|
|
25
|
+
def initialize(attrs = {})
|
|
26
|
+
ATTRS.each do |attr|
|
|
27
|
+
value = attrs[attr.to_s] || attrs[attr]
|
|
28
|
+
instance_variable_set(:"@#{attr}", value)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @param hash [Hash]
|
|
33
|
+
# @return [BillingIO::SubscriptionRenewal]
|
|
34
|
+
def self.from_hash(hash)
|
|
35
|
+
new(hash)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @return [Hash{String => Object}]
|
|
39
|
+
def to_h
|
|
40
|
+
ATTRS.each_with_object({}) do |attr, h|
|
|
41
|
+
h[attr.to_s] = instance_variable_get(:"@#{attr}")
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def inspect
|
|
46
|
+
"#<BillingIO::SubscriptionRenewal renewal_id=#{@renewal_id.inspect} subscription_id=#{@subscription_id.inspect} status=#{@status.inspect}>"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BillingIO
|
|
4
|
+
# Provides access to revenue adjustment endpoints.
|
|
5
|
+
#
|
|
6
|
+
# client.adjustments.list
|
|
7
|
+
# client.adjustments.create(type: "credit", amount_usd: 10.00, reason: "Goodwill credit")
|
|
8
|
+
class Adjustments
|
|
9
|
+
# @api private
|
|
10
|
+
def initialize(http_client)
|
|
11
|
+
@http = http_client
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# List adjustments with cursor-based pagination.
|
|
15
|
+
#
|
|
16
|
+
# @param cursor [String, nil] opaque cursor for the next page
|
|
17
|
+
# @param limit [Integer] items per page (1..100, default 25)
|
|
18
|
+
# @param customer_id [String, nil] filter by customer
|
|
19
|
+
# @return [BillingIO::PaginatedList<BillingIO::Adjustment>]
|
|
20
|
+
# @raise [BillingIO::Error]
|
|
21
|
+
def list(cursor: nil, limit: 25, customer_id: nil)
|
|
22
|
+
params = { limit: limit }
|
|
23
|
+
params[:cursor] = cursor if cursor
|
|
24
|
+
params[:customer_id] = customer_id if customer_id
|
|
25
|
+
|
|
26
|
+
data = @http.get("/revenue/adjustments", params)
|
|
27
|
+
PaginatedList.from_hash(data, Adjustment)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Create a new revenue adjustment.
|
|
31
|
+
#
|
|
32
|
+
# @param type [String] adjustment type ("credit", "debit", "correction")
|
|
33
|
+
# @param amount_usd [Float] adjustment amount in USD
|
|
34
|
+
# @param reason [String, nil] human-readable reason
|
|
35
|
+
# @param customer_id [String, nil] related customer
|
|
36
|
+
# @param metadata [Hash, nil] arbitrary key-value pairs
|
|
37
|
+
# @return [BillingIO::Adjustment]
|
|
38
|
+
# @raise [BillingIO::Error]
|
|
39
|
+
def create(type:, amount_usd:, reason: nil, customer_id: nil, metadata: nil)
|
|
40
|
+
body = {
|
|
41
|
+
"type" => type,
|
|
42
|
+
"amount_usd" => amount_usd
|
|
43
|
+
}
|
|
44
|
+
body["reason"] = reason if reason
|
|
45
|
+
body["customer_id"] = customer_id if customer_id
|
|
46
|
+
body["metadata"] = metadata if metadata
|
|
47
|
+
|
|
48
|
+
data = @http.post("/revenue/adjustments", body)
|
|
49
|
+
Adjustment.from_hash(data)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BillingIO
|
|
4
|
+
# Provides access to customer management endpoints.
|
|
5
|
+
#
|
|
6
|
+
# client.customers.create(email: "user@example.com")
|
|
7
|
+
# client.customers.list
|
|
8
|
+
# client.customers.get("cus_abc123")
|
|
9
|
+
# client.customers.update("cus_abc123", name: "Jane Doe")
|
|
10
|
+
class Customers
|
|
11
|
+
# @api private
|
|
12
|
+
def initialize(http_client)
|
|
13
|
+
@http = http_client
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Create a new customer.
|
|
17
|
+
#
|
|
18
|
+
# @param email [String, nil] customer email address
|
|
19
|
+
# @param name [String, nil] customer display name
|
|
20
|
+
# @param metadata [Hash, nil] arbitrary key-value pairs
|
|
21
|
+
# @return [BillingIO::Customer]
|
|
22
|
+
# @raise [BillingIO::Error]
|
|
23
|
+
def create(email: nil, name: nil, metadata: nil)
|
|
24
|
+
body = {}
|
|
25
|
+
body["email"] = email if email
|
|
26
|
+
body["name"] = name if name
|
|
27
|
+
body["metadata"] = metadata if metadata
|
|
28
|
+
|
|
29
|
+
data = @http.post("/customers", body)
|
|
30
|
+
Customer.from_hash(data)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# List customers with cursor-based pagination.
|
|
34
|
+
#
|
|
35
|
+
# @param cursor [String, nil] opaque cursor for the next page
|
|
36
|
+
# @param limit [Integer] items per page (1..100, default 25)
|
|
37
|
+
# @return [BillingIO::PaginatedList<BillingIO::Customer>]
|
|
38
|
+
# @raise [BillingIO::Error]
|
|
39
|
+
def list(cursor: nil, limit: 25)
|
|
40
|
+
params = { limit: limit }
|
|
41
|
+
params[:cursor] = cursor if cursor
|
|
42
|
+
|
|
43
|
+
data = @http.get("/customers", params)
|
|
44
|
+
PaginatedList.from_hash(data, Customer)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Retrieve a single customer by ID.
|
|
48
|
+
#
|
|
49
|
+
# @param customer_id [String] customer identifier (prefixed +cus_+)
|
|
50
|
+
# @return [BillingIO::Customer]
|
|
51
|
+
# @raise [BillingIO::Error]
|
|
52
|
+
def get(customer_id)
|
|
53
|
+
data = @http.get("/customers/#{customer_id}")
|
|
54
|
+
Customer.from_hash(data)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Update an existing customer.
|
|
58
|
+
#
|
|
59
|
+
# @param customer_id [String] customer identifier (prefixed +cus_+)
|
|
60
|
+
# @param email [String, nil] new email address
|
|
61
|
+
# @param name [String, nil] new display name
|
|
62
|
+
# @param metadata [Hash, nil] new metadata (replaces existing)
|
|
63
|
+
# @return [BillingIO::Customer]
|
|
64
|
+
# @raise [BillingIO::Error]
|
|
65
|
+
def update(customer_id, email: nil, name: nil, metadata: nil)
|
|
66
|
+
body = {}
|
|
67
|
+
body["email"] = email if email
|
|
68
|
+
body["name"] = name if name
|
|
69
|
+
body["metadata"] = metadata if metadata
|
|
70
|
+
|
|
71
|
+
data = @http.patch("/customers/#{customer_id}", body)
|
|
72
|
+
Customer.from_hash(data)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BillingIO
|
|
4
|
+
# Provides access to subscription entitlement endpoints.
|
|
5
|
+
#
|
|
6
|
+
# client.entitlements.list(subscription_id: "sub_abc123")
|
|
7
|
+
# client.entitlements.create(subscription_id: "sub_abc123", feature_key: "api_calls")
|
|
8
|
+
# client.entitlements.update("ent_abc123", value: 1000)
|
|
9
|
+
# client.entitlements.delete("ent_abc123")
|
|
10
|
+
# client.entitlements.check(customer_id: "cus_abc123", feature_key: "api_calls")
|
|
11
|
+
class Entitlements
|
|
12
|
+
# @api private
|
|
13
|
+
def initialize(http_client)
|
|
14
|
+
@http = http_client
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# List entitlements with cursor-based pagination.
|
|
18
|
+
#
|
|
19
|
+
# @param cursor [String, nil] opaque cursor for the next page
|
|
20
|
+
# @param limit [Integer] items per page (1..100, default 25)
|
|
21
|
+
# @param subscription_id [String, nil] filter by subscription
|
|
22
|
+
# @return [BillingIO::PaginatedList<BillingIO::Entitlement>]
|
|
23
|
+
# @raise [BillingIO::Error]
|
|
24
|
+
def list(cursor: nil, limit: 25, subscription_id: nil)
|
|
25
|
+
params = { limit: limit }
|
|
26
|
+
params[:cursor] = cursor if cursor
|
|
27
|
+
params[:subscription_id] = subscription_id if subscription_id
|
|
28
|
+
|
|
29
|
+
data = @http.get("/subscriptions/entitlements", params)
|
|
30
|
+
PaginatedList.from_hash(data, Entitlement)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Create a new entitlement.
|
|
34
|
+
#
|
|
35
|
+
# @param subscription_id [String] parent subscription
|
|
36
|
+
# @param feature_key [String] machine-readable feature identifier
|
|
37
|
+
# @param value [Object, nil] entitlement value
|
|
38
|
+
# @param metadata [Hash, nil] arbitrary key-value pairs
|
|
39
|
+
# @return [BillingIO::Entitlement]
|
|
40
|
+
# @raise [BillingIO::Error]
|
|
41
|
+
def create(subscription_id:, feature_key:, value: nil, metadata: nil)
|
|
42
|
+
body = {
|
|
43
|
+
"subscription_id" => subscription_id,
|
|
44
|
+
"feature_key" => feature_key
|
|
45
|
+
}
|
|
46
|
+
body["value"] = value unless value.nil?
|
|
47
|
+
body["metadata"] = metadata if metadata
|
|
48
|
+
|
|
49
|
+
data = @http.post("/subscriptions/entitlements", body)
|
|
50
|
+
Entitlement.from_hash(data)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Update an existing entitlement.
|
|
54
|
+
#
|
|
55
|
+
# @param entitlement_id [String] entitlement identifier (prefixed +ent_+)
|
|
56
|
+
# @param value [Object, nil] new entitlement value
|
|
57
|
+
# @param metadata [Hash, nil] new metadata (replaces existing)
|
|
58
|
+
# @return [BillingIO::Entitlement]
|
|
59
|
+
# @raise [BillingIO::Error]
|
|
60
|
+
def update(entitlement_id, value: nil, metadata: nil)
|
|
61
|
+
body = {}
|
|
62
|
+
body["value"] = value unless value.nil?
|
|
63
|
+
body["metadata"] = metadata if metadata
|
|
64
|
+
|
|
65
|
+
data = @http.patch("/subscriptions/entitlements/#{entitlement_id}", body)
|
|
66
|
+
Entitlement.from_hash(data)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Delete an entitlement.
|
|
70
|
+
#
|
|
71
|
+
# @param entitlement_id [String] entitlement identifier (prefixed +ent_+)
|
|
72
|
+
# @return [nil]
|
|
73
|
+
# @raise [BillingIO::Error]
|
|
74
|
+
def delete(entitlement_id)
|
|
75
|
+
@http.delete("/subscriptions/entitlements/#{entitlement_id}")
|
|
76
|
+
nil
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Check whether a customer has a specific entitlement.
|
|
80
|
+
#
|
|
81
|
+
# @param customer_id [String] customer identifier
|
|
82
|
+
# @param feature_key [String] feature key to check
|
|
83
|
+
# @return [BillingIO::EntitlementCheck]
|
|
84
|
+
# @raise [BillingIO::Error]
|
|
85
|
+
def check(customer_id:, feature_key:)
|
|
86
|
+
params = {
|
|
87
|
+
customer_id: customer_id,
|
|
88
|
+
feature_key: feature_key
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
data = @http.get("/subscriptions/entitlements/check", params)
|
|
92
|
+
EntitlementCheck.from_hash(data)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BillingIO
|
|
4
|
+
# Provides access to payment link endpoints.
|
|
5
|
+
#
|
|
6
|
+
# client.payment_links.create(amount_usd: 25.00, chain: "tron", token: "USDT")
|
|
7
|
+
# client.payment_links.list
|
|
8
|
+
class PaymentLinks
|
|
9
|
+
# @api private
|
|
10
|
+
def initialize(http_client)
|
|
11
|
+
@http = http_client
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Create a new payment link.
|
|
15
|
+
#
|
|
16
|
+
# @param amount_usd [Float, nil] fixed amount in USD (nil for open-amount)
|
|
17
|
+
# @param chain [String, nil] blockchain network
|
|
18
|
+
# @param token [String, nil] stablecoin token
|
|
19
|
+
# @param metadata [Hash, nil] arbitrary key-value pairs
|
|
20
|
+
# @return [BillingIO::PaymentLink]
|
|
21
|
+
# @raise [BillingIO::Error]
|
|
22
|
+
def create(amount_usd: nil, chain: nil, token: nil, metadata: nil)
|
|
23
|
+
body = {}
|
|
24
|
+
body["amount_usd"] = amount_usd if amount_usd
|
|
25
|
+
body["chain"] = chain if chain
|
|
26
|
+
body["token"] = token if token
|
|
27
|
+
body["metadata"] = metadata if metadata
|
|
28
|
+
|
|
29
|
+
data = @http.post("/payment-links", body)
|
|
30
|
+
PaymentLink.from_hash(data)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# List payment links with cursor-based pagination.
|
|
34
|
+
#
|
|
35
|
+
# @param cursor [String, nil] opaque cursor for the next page
|
|
36
|
+
# @param limit [Integer] items per page (1..100, default 25)
|
|
37
|
+
# @return [BillingIO::PaginatedList<BillingIO::PaymentLink>]
|
|
38
|
+
# @raise [BillingIO::Error]
|
|
39
|
+
def list(cursor: nil, limit: 25)
|
|
40
|
+
params = { limit: limit }
|
|
41
|
+
params[:cursor] = cursor if cursor
|
|
42
|
+
|
|
43
|
+
data = @http.get("/payment-links", params)
|
|
44
|
+
PaginatedList.from_hash(data, PaymentLink)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BillingIO
|
|
4
|
+
# Provides access to payment method management endpoints.
|
|
5
|
+
#
|
|
6
|
+
# client.payment_methods.create(customer_id: "cus_abc123", type: "wallet")
|
|
7
|
+
# client.payment_methods.list
|
|
8
|
+
# client.payment_methods.update("pm_abc123", metadata: { "label" => "main" })
|
|
9
|
+
# client.payment_methods.delete("pm_abc123")
|
|
10
|
+
# client.payment_methods.set_default("pm_abc123")
|
|
11
|
+
class PaymentMethods
|
|
12
|
+
# @api private
|
|
13
|
+
def initialize(http_client)
|
|
14
|
+
@http = http_client
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Register a new payment method.
|
|
18
|
+
#
|
|
19
|
+
# @param customer_id [String] owning customer
|
|
20
|
+
# @param type [String] method type (e.g. "wallet")
|
|
21
|
+
# @param chain [String, nil] blockchain network
|
|
22
|
+
# @param token [String, nil] stablecoin token
|
|
23
|
+
# @param address [String, nil] wallet address
|
|
24
|
+
# @param metadata [Hash, nil] arbitrary key-value pairs
|
|
25
|
+
# @return [BillingIO::PaymentMethod]
|
|
26
|
+
# @raise [BillingIO::Error]
|
|
27
|
+
def create(customer_id:, type:, chain: nil, token: nil, address: nil, metadata: nil)
|
|
28
|
+
body = {
|
|
29
|
+
"customer_id" => customer_id,
|
|
30
|
+
"type" => type
|
|
31
|
+
}
|
|
32
|
+
body["chain"] = chain if chain
|
|
33
|
+
body["token"] = token if token
|
|
34
|
+
body["address"] = address if address
|
|
35
|
+
body["metadata"] = metadata if metadata
|
|
36
|
+
|
|
37
|
+
data = @http.post("/payment-methods", body)
|
|
38
|
+
PaymentMethod.from_hash(data)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# List payment methods with cursor-based pagination.
|
|
42
|
+
#
|
|
43
|
+
# @param cursor [String, nil] opaque cursor for the next page
|
|
44
|
+
# @param limit [Integer] items per page (1..100, default 25)
|
|
45
|
+
# @param customer_id [String, nil] filter by customer
|
|
46
|
+
# @return [BillingIO::PaginatedList<BillingIO::PaymentMethod>]
|
|
47
|
+
# @raise [BillingIO::Error]
|
|
48
|
+
def list(cursor: nil, limit: 25, customer_id: nil)
|
|
49
|
+
params = { limit: limit }
|
|
50
|
+
params[:cursor] = cursor if cursor
|
|
51
|
+
params[:customer_id] = customer_id if customer_id
|
|
52
|
+
|
|
53
|
+
data = @http.get("/payment-methods", params)
|
|
54
|
+
PaginatedList.from_hash(data, PaymentMethod)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Update an existing payment method.
|
|
58
|
+
#
|
|
59
|
+
# @param payment_method_id [String] payment method identifier (prefixed +pm_+)
|
|
60
|
+
# @param metadata [Hash, nil] new metadata (replaces existing)
|
|
61
|
+
# @return [BillingIO::PaymentMethod]
|
|
62
|
+
# @raise [BillingIO::Error]
|
|
63
|
+
def update(payment_method_id, metadata: nil)
|
|
64
|
+
body = {}
|
|
65
|
+
body["metadata"] = metadata if metadata
|
|
66
|
+
|
|
67
|
+
data = @http.patch("/payment-methods/#{payment_method_id}", body)
|
|
68
|
+
PaymentMethod.from_hash(data)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Delete a payment method.
|
|
72
|
+
#
|
|
73
|
+
# @param payment_method_id [String] payment method identifier (prefixed +pm_+)
|
|
74
|
+
# @return [nil]
|
|
75
|
+
# @raise [BillingIO::Error]
|
|
76
|
+
def delete(payment_method_id)
|
|
77
|
+
@http.delete("/payment-methods/#{payment_method_id}")
|
|
78
|
+
nil
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Set a payment method as the customer's default.
|
|
82
|
+
#
|
|
83
|
+
# @param payment_method_id [String] payment method identifier (prefixed +pm_+)
|
|
84
|
+
# @return [BillingIO::PaymentMethod]
|
|
85
|
+
# @raise [BillingIO::Error]
|
|
86
|
+
def set_default(payment_method_id)
|
|
87
|
+
data = @http.post("/payment-methods/#{payment_method_id}/default")
|
|
88
|
+
PaymentMethod.from_hash(data)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|