mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-23 07:09:39 +02:00
* Save work * Subscriptions and trials domain * Store family ID on customer * Remove indirection of stripe calls * Test simplifications * Update brakeman * Fix stripe tests in CI * Update billing page to show subscription details * Remove legacy columns * Complete billing settings page * Fix hardcoded plan name * Handle subscriptions for self hosting mode * Lint fixes
88 lines
2.5 KiB
Ruby
88 lines
2.5 KiB
Ruby
class Provider::Stripe
|
|
Error = Class.new(StandardError)
|
|
|
|
def initialize(secret_key:, webhook_secret:)
|
|
@client = Stripe::StripeClient.new(secret_key)
|
|
@webhook_secret = webhook_secret
|
|
end
|
|
|
|
def process_event(event_id)
|
|
event = retrieve_event(event_id)
|
|
|
|
case event.type
|
|
when /^customer\.subscription\./
|
|
SubscriptionEventProcessor.new(event).process
|
|
else
|
|
Rails.logger.warn "Unhandled event type: #{event.type}"
|
|
end
|
|
end
|
|
|
|
def process_webhook_later(webhook_body, sig_header)
|
|
thin_event = client.parse_thin_event(webhook_body, sig_header, webhook_secret)
|
|
StripeEventHandlerJob.perform_later(thin_event.id)
|
|
end
|
|
|
|
def create_checkout_session(plan:, family_id:, family_email:, success_url:, cancel_url:)
|
|
customer = client.v1.customers.create(
|
|
email: family_email,
|
|
metadata: {
|
|
family_id: family_id
|
|
}
|
|
)
|
|
|
|
session = client.v1.checkout.sessions.create(
|
|
customer: customer.id,
|
|
line_items: [ { price: price_id_for(plan), quantity: 1 } ],
|
|
mode: "subscription",
|
|
allow_promotion_codes: true,
|
|
success_url: success_url,
|
|
cancel_url: cancel_url
|
|
)
|
|
|
|
NewCheckoutSession.new(url: session.url, customer_id: customer.id)
|
|
end
|
|
|
|
def get_checkout_result(session_id)
|
|
session = client.v1.checkout.sessions.retrieve(session_id)
|
|
|
|
unless session.status == "complete" && session.payment_status == "paid"
|
|
raise Error, "Checkout session not complete"
|
|
end
|
|
|
|
CheckoutSessionResult.new(success?: true, subscription_id: session.subscription)
|
|
rescue StandardError => e
|
|
Sentry.capture_exception(e)
|
|
Rails.logger.error "Error fetching checkout result for session #{session_id}: #{e.message}"
|
|
CheckoutSessionResult.new(success?: false, subscription_id: nil)
|
|
end
|
|
|
|
def create_billing_portal_session_url(customer_id:, return_url:)
|
|
client.v1.billing_portal.sessions.create(
|
|
customer: customer_id,
|
|
return_url: return_url
|
|
).url
|
|
end
|
|
|
|
def update_customer_metadata(customer_id:, metadata:)
|
|
client.v1.customers.update(customer_id, metadata: metadata)
|
|
end
|
|
|
|
private
|
|
attr_reader :client, :webhook_secret
|
|
|
|
NewCheckoutSession = Data.define(:url, :customer_id)
|
|
CheckoutSessionResult = Data.define(:success?, :subscription_id)
|
|
|
|
def price_id_for(plan)
|
|
prices = {
|
|
monthly: ENV["STRIPE_MONTHLY_PRICE_ID"],
|
|
annual: ENV["STRIPE_ANNUAL_PRICE_ID"]
|
|
}
|
|
|
|
prices[plan.to_sym || :monthly]
|
|
end
|
|
|
|
def retrieve_event(event_id)
|
|
client.v1.events.retrieve(event_id)
|
|
end
|
|
end
|