Upgrade Stripe con addebito immediato; downgrade programmato a fine periodo. UX billing più sobria con box info; icone piani. API inviti e OAuth YouTube per staff trasmissione; deep link join; scelta partita programmata o nuova. Co-authored-by: Cursor <cursoragent@cursor.com>
68 lines
1.9 KiB
Ruby
68 lines
1.9 KiB
Ruby
module Billing
|
|
module Stripe
|
|
class WebhookHandler
|
|
def self.call(event)
|
|
new(event).call
|
|
end
|
|
|
|
def initialize(event)
|
|
@event = event
|
|
end
|
|
|
|
def call
|
|
case @event.type
|
|
when "checkout.session.completed"
|
|
CheckoutSync.from_session(@event.data.object)
|
|
when "customer.subscription.updated", "customer.subscription.created"
|
|
stripe_sub = @event.data.object
|
|
CheckoutSync.from_subscription(stripe_sub)
|
|
club = Club.joins(:subscription)
|
|
.find_by(subscriptions: { stripe_subscription_id: stripe_sub.id })
|
|
ApplyPendingPlan.call(club: club) if club
|
|
when "customer.subscription.deleted"
|
|
downgrade_to_free(@event.data.object)
|
|
when "invoice.payment_failed"
|
|
mark_past_due(@event.data.object)
|
|
when "invoice.paid"
|
|
record_payment(@event.data.object)
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def downgrade_to_free(stripe_sub)
|
|
club = Club.joins(:subscription)
|
|
.find_by(subscriptions: { stripe_subscription_id: stripe_sub.id })
|
|
return unless club
|
|
|
|
Billing::AssignPlan.call(
|
|
club: club,
|
|
plan_slug: "free",
|
|
status: "active",
|
|
stripe_attrs: {
|
|
stripe_subscription_id: nil,
|
|
current_period_start: nil,
|
|
current_period_end: nil,
|
|
cancel_at_period_end: false
|
|
}
|
|
)
|
|
end
|
|
|
|
def record_payment(invoice)
|
|
Billing::Stripe::RecordPayment.call(stripe_invoice: invoice)
|
|
end
|
|
|
|
def mark_past_due(invoice)
|
|
return if invoice.subscription.blank?
|
|
|
|
club = Club.joins(:subscription)
|
|
.find_by(subscriptions: { stripe_subscription_id: invoice.subscription })
|
|
return unless club&.subscription
|
|
|
|
club.subscription.update!(status: "past_due")
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|