fix stripe v2 calls

This commit is contained in:
Tanmay Sharma
2025-10-09 09:52:56 +02:00
parent 59f60936a7
commit 125ae5523a
4 changed files with 162 additions and 69 deletions
@@ -58,14 +58,18 @@ class Enterprise::Billing::V2::PricingPlanComponentBuilder < Enterprise::Billing
private
def create_licensed_item(display_name:, lookup_key:, unit_label:)
Stripe::V2::Billing::LicensedItem.create(
StripeV2Client.request(
:post,
'/v2/billing/licensed_items',
{ display_name: display_name, lookup_key: lookup_key, unit_label: unit_label },
{ api_key: ENV.fetch('STRIPE_SECRET_KEY', nil), stripe_version: '2025-08-27.preview' }
)
end
def create_license_fee(display_name:, unit_amount:, licensed_item_id:)
Stripe::V2::Billing::LicenseFee.create(
StripeV2Client.request(
:post,
'/v2/billing/license_fees',
{
display_name: display_name,
currency: 'usd',
@@ -80,7 +84,9 @@ class Enterprise::Billing::V2::PricingPlanComponentBuilder < Enterprise::Billing
end
def create_service_action(lookup_key:, credit_amount:, cpu_id:)
Stripe::V2::Billing::ServiceAction.create(
StripeV2Client.request(
:post,
'/v2/billing/service_actions',
{
lookup_key: lookup_key,
service_interval: 'month',
@@ -101,7 +107,9 @@ class Enterprise::Billing::V2::PricingPlanComponentBuilder < Enterprise::Billing
end
def create_rate_card(display_name:)
Stripe::V2::Billing::RateCard.create(
StripeV2Client.request(
:post,
'/v2/billing/rate_cards',
{
display_name: display_name,
currency: 'usd',
@@ -114,15 +122,18 @@ class Enterprise::Billing::V2::PricingPlanComponentBuilder < Enterprise::Billing
end
def create_metered_item(display_name:, lookup_key:, meter_id:)
Stripe::V2::Billing::MeteredItem.create(
StripeV2Client.request(
:post,
'/v2/billing/metered_items',
{ display_name: display_name, lookup_key: lookup_key, meter: meter_id },
{ api_key: ENV.fetch('STRIPE_SECRET_KEY', nil), stripe_version: '2025-08-27.preview' }
)
end
def add_rate(card_id:, item_id:, cpu_id:, value:)
Stripe::V2::Billing::RateCard::Rate.create(
card_id,
StripeV2Client.request(
:post,
"/v2/billing/rate_cards/#{card_id}/rates",
{
metered_item: item_id,
custom_pricing_unit_amount: { id: cpu_id, value: value.to_s }
@@ -141,8 +152,9 @@ class Enterprise::Billing::V2::PricingPlanComponentBuilder < Enterprise::Billing
{ type: 'rate_card', rate_card: data }
end
Stripe::V2::Billing::PricingPlan::Component.create(
plan_id,
StripeV2Client.request(
:post,
"/v2/billing/pricing_plans/#{plan_id}/components",
params,
{ api_key: ENV.fetch('STRIPE_SECRET_KEY', nil), stripe_version: '2025-08-27.preview' }
)
@@ -1,26 +1,34 @@
class Enterprise::Billing::V2::PricingPlanService < Enterprise::Billing::V2::BaseService
def create_custom_pricing_unit(display_name:, lookup_key:)
Stripe::V2::Billing::CustomPricingUnit.create(
StripeV2Client.request(
:post,
'/v2/billing/custom_pricing_units',
{ display_name: display_name, lookup_key: lookup_key },
{ api_key: ENV.fetch('STRIPE_SECRET_KEY', nil), stripe_version: '2025-08-27.preview' }
)
end
def create_meter(display_name:, event_name:)
Stripe::Billing::Meter.create(
{
display_name: display_name,
event_name: event_name,
default_aggregation: { formula: 'sum' },
customer_mapping: { type: 'by_id', event_payload_key: 'stripe_customer_id' },
value_settings: { event_payload_key: 'value' }
},
params = {
'display_name' => display_name,
'event_name' => event_name,
'default_aggregation[formula]' => 'sum',
'customer_mapping[type]' => 'by_id',
'customer_mapping[event_payload_key]' => 'stripe_customer_id',
'value_settings[event_payload_key]' => 'value'
}
StripeV2Client.request(
:post,
'/v1/billing/meters',
params,
{ api_key: ENV.fetch('STRIPE_SECRET_KEY', nil), stripe_version: '2025-08-27.preview' }
)
end
def create_pricing_plan(display_name:, currency: 'usd', tax_behavior: 'exclusive')
Stripe::V2::Billing::PricingPlan.create(
StripeV2Client.request(
:post,
'/v2/billing/pricing_plans',
{ display_name: display_name, currency: currency, tax_behavior: tax_behavior },
{ api_key: ENV.fetch('STRIPE_SECRET_KEY', nil), stripe_version: '2025-08-27.preview' }
)
+76
View File
@@ -0,0 +1,76 @@
module StripeV2Client
class << self
def request(method, path, params = {}, options = {})
api_key = options[:api_key] || ENV.fetch('STRIPE_SECRET_KEY', nil)
stripe_version = options[:stripe_version] || '2025-08-27.preview'
uri = URI("https://api.stripe.com#{path}")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = build_request(method, uri, params, path)
request['Authorization'] = "Bearer #{api_key}"
request['Stripe-Version'] = stripe_version
response = http.request(request)
parse_response(response)
end
private
def build_request(method, uri, params, path)
case method
when :get
Net::HTTP::Get.new(uri)
when :post
req = Net::HTTP::Post.new(uri)
if v2_endpoint?(path)
req.body = params.to_json unless params.empty?
req['Content-Type'] = 'application/json'
else
req.set_form_data(params) unless params.empty?
req['Content-Type'] = 'application/x-www-form-urlencoded'
end
req
when :delete
Net::HTTP::Delete.new(uri)
end
end
def v2_endpoint?(path)
path.start_with?('/v2/')
end
def parse_response(response)
body = JSON.parse(response.body)
# Convert to OpenStruct for dot notation access (mimicking Stripe SDK objects)
case body
when Hash
recursive_to_struct(body)
when Array
body.map { |item| recursive_to_struct(item) }
else
body
end
rescue JSON::ParserError
response.body
end
def recursive_to_struct(hash)
return hash unless hash.is_a?(Hash)
OpenStruct.new(hash.transform_values do |value|
case value
when Hash
recursive_to_struct(value)
when Array
value.map { |item| item.is_a?(Hash) ? recursive_to_struct(item) : item }
else
value
end
end)
end
end
end
@@ -10,95 +10,92 @@ RSpec.describe Enterprise::Billing::V2::PricingPlanService do
describe '#create_custom_pricing_unit' do
it 'creates a custom pricing unit' do
cpu_double = instance_double(Stripe::V2::Billing::CustomPricingUnit, id: 'cpu_123')
allow(Stripe::V2::Billing::CustomPricingUnit).to receive(:create).and_return(cpu_double)
cpu_response = OpenStruct.new(id: 'cpu_123')
allow(StripeV2Client).to receive(:request).and_return(cpu_response)
result = service.create_custom_pricing_unit(display_name: 'Credits', lookup_key: 'credits_001')
expect(result.id).to eq('cpu_123')
expect(StripeV2Client).to have_received(:request).with(
:post,
'/v2/billing/custom_pricing_units',
{ display_name: 'Credits', lookup_key: 'credits_001' },
{ api_key: 'sk_test_123', stripe_version: '2025-08-27.preview' }
)
end
end
describe '#create_meter' do
it 'creates a billing meter' do
meter_double = instance_double(Stripe::Billing::Meter, id: 'meter_123')
allow(Stripe::Billing::Meter).to receive(:create).and_return(meter_double)
meter_response = OpenStruct.new(id: 'meter_123')
allow(StripeV2Client).to receive(:request).and_return(meter_response)
result = service.create_meter(display_name: 'Prompts', event_name: 'prompts_001')
expect(result.id).to eq('meter_123')
expect(StripeV2Client).to have_received(:request).with(
:post,
'/v1/billing/meters',
kind_of(Hash),
{ api_key: 'sk_test_123', stripe_version: '2025-08-27.preview' }
)
end
end
describe '#create_pricing_plan' do
it 'creates a pricing plan' do
plan_double = instance_double(Stripe::V2::Billing::PricingPlan, id: 'plan_123')
allow(Stripe::V2::Billing::PricingPlan).to receive(:create).and_return(plan_double)
plan_response = OpenStruct.new(id: 'plan_123')
allow(StripeV2Client).to receive(:request).and_return(plan_response)
result = service.create_pricing_plan(display_name: 'Business Plan')
expect(result.id).to eq('plan_123')
end
end
describe '#create_service_action' do
it 'creates a service action for monthly credit grants' do
action_double = instance_double(Stripe::V2::Billing::ServiceAction, id: 'sa_123')
allow(Stripe::V2::Billing::ServiceAction).to receive(:create).and_return(action_double)
result = service.create_service_action(
lookup_key: 'monthly_credits_001',
cpu_id: 'cpu_123',
credit_amount: 2000
expect(StripeV2Client).to have_received(:request).with(
:post,
'/v2/billing/pricing_plans',
{ display_name: 'Business Plan', currency: 'usd', tax_behavior: 'exclusive' },
{ api_key: 'sk_test_123', stripe_version: '2025-08-27.preview' }
)
expect(result.id).to eq('sa_123')
end
end
describe '#create_complete_pricing_plan' do
let(:config) do
{
cpu_display_name: 'Captain Credits',
cpu_lookup_key: 'captain_credits_001',
meter_display_name: 'Captain Prompts',
meter_event_name: 'captain_prompts_001',
plan_display_name: 'Business Plan - 2000 Credits',
cpu_display_name: 'Credits',
cpu_lookup_key: 'cpu_001',
meter_display_name: 'Prompts',
meter_event_name: 'prompts_001',
plan_display_name: 'Business Plan',
include_license_fee: true,
licensed_item_display_name: 'Business Seat',
licensed_item_lookup_key: 'business_seat_001',
licensed_item_display_name: 'Seat',
licensed_item_lookup_key: 'seat_001',
licensed_item_unit_label: 'per agent',
license_fee_display_name: 'Business Monthly Fee',
license_fee_display_name: 'Fee',
license_fee_amount: '3900',
service_action_lookup_key: 'monthly_credits_001',
service_action_lookup_key: 'credits_001',
monthly_credit_amount: 2000,
rate_card_display_name: 'Usage Rates',
metered_item_display_name: 'Captain Prompt',
metered_item_lookup_key: 'captain_prompt_001',
rate_card_display_name: 'Rates',
metered_item_display_name: 'Prompt',
metered_item_lookup_key: 'prompt_001',
rate_value: 1
}
end
it 'creates a complete pricing plan with all components' do
cpu = instance_double(Stripe::V2::Billing::CustomPricingUnit, id: 'cpu_123')
meter = instance_double(Stripe::Billing::Meter, id: 'meter_123')
plan = instance_double(Stripe::V2::Billing::PricingPlan, id: 'plan_123')
licensed_item = instance_double(Stripe::V2::Billing::LicensedItem, id: 'li_123')
license_fee = instance_double(Stripe::V2::Billing::LicenseFee, id: 'lf_123', latest_version: 'v1')
service_action = instance_double(Stripe::V2::Billing::ServiceAction, id: 'sa_123')
rate_card = instance_double(Stripe::V2::Billing::RateCard, id: 'rc_123', latest_version: 'v1')
metered_item = instance_double(Stripe::V2::Billing::MeteredItem, id: 'mi_123')
cpu = OpenStruct.new(id: 'cpu_123')
meter = OpenStruct.new(id: 'meter_123')
plan = OpenStruct.new(id: 'plan_123')
service_action = OpenStruct.new(id: 'sa_123')
rate_card = OpenStruct.new(id: 'rc_123', latest_version: 'v1')
allow(service).to receive(:create_custom_pricing_unit).and_return(cpu)
allow(service).to receive(:create_meter).and_return(meter)
allow(service).to receive(:create_pricing_plan).and_return(plan)
allow(service).to receive(:create_licensed_item).and_return(licensed_item)
allow(service).to receive(:create_license_fee).and_return(license_fee)
allow(service).to receive(:create_service_action).and_return(service_action)
allow(service).to receive(:create_rate_card).and_return(rate_card)
allow(service).to receive(:create_metered_item).and_return(metered_item)
allow(service).to receive(:add_rate_to_rate_card).and_return(true)
allow(service).to receive(:add_component_to_plan).and_return(true)
allow(StripeV2Client).to receive(:request).and_return(cpu, meter, plan, service_action, rate_card)
allow_any_instance_of(Enterprise::Billing::V2::PricingPlanComponentBuilder)
.to receive(:add_license_fee_component).and_return(true)
allow_any_instance_of(Enterprise::Billing::V2::PricingPlanComponentBuilder)
.to receive(:add_service_action_component).and_return(service_action)
allow_any_instance_of(Enterprise::Billing::V2::PricingPlanComponentBuilder)
.to receive(:add_rate_card_component).and_return(rate_card)
result = service.create_complete_pricing_plan(config)