Search code examples
ruby-on-railsrubystripe-paymentssubscription

How to handle multiple subscriptions in signle checkout? How to handle stripe webhook event?


For context I'm implementing the same billing interval subscriptions in one checkout

As far as I've understood, I've added multiple line_items with their price_ids and quantity and all checkout is working fine. But I'm not able to handle the webhook events for this kinda multiple subscriptions checkout.

When we do single subscription checkout we get the subscription data in checkout.session.complete event object.

How can we get the all the subscriptions data from this object. So that for all subscriotions we can loop through this array and create a record in our DB.


def handle_checkout_session_completed(event)
  puts "checkout.session.completed\n"
  return unless User.exists?(event.data.object.client_reference_id)

  checkout_session = event.data.object
  puts "checkout_session: #{checkout_session}\n"

  session = Stripe::Checkout::Session.retrieve({
    id: checkout_session['id'],
    expand: ['line_items']
  })

  line_items = session.line_items.data
  puts line_items

  if checkout_session.payment_status == 'paid'
    fulfill_order(checkout_session, line_items)
  end
end

def fulfill_order(checkout_session, line_items)
  user = User.find(checkout_session.client_reference_id)
  user.update(stripe_id: checkout_session.customer)

  line_items.each do |line_item|
    product_id = line_item.price.product
    tool_id = determine_tool_id(product_id)

    Subscription.create(
      user: user,
      subscription_id: checkout_session.subscription,
      plan_id: tool_id,
      interval: line_item.price.recurring.interval,
      status: 'active',
      current_period_start: Time.at(checkout_session.subscription.current_period_start).to_datetime,
      current_period_end: Time.at(checkout_session.subscription.current_period_end).to_datetime
    )
  end
end


Solution

  • when 'invoice.payment.succeeded'
          puts "invoice.payment.succeeded\n"
          return unless event.data.object.subscription.present?
    
          stripe_subscriptions = Stripe::Subscription.retrieve(event.data.object.subscription)
          subscriptions_items = stripe_subscriptions.items.data
          # find all the subscriptions associate with the stripe subscription
    
          subscriptions_items.each do |subscription_item|
            subscription = Subscription.find_by(subscription_item_id: subscription_item.id)
            subscription.update(
              status: stripe_subscriptions.status,
              current_period_start: Time.at(stripe_subscriptions.current_period_start).to_datetime,
              current_period_end: Time.at(stripe_subscriptions.current_period_end).to_datetime,
              interval: subscription_item.price.recurring.interval
            )
          end
    

    Basically we have to listen for the invoice.payment.succeeded event which returns the object which has included the subscription id. And we can retrieve the subscriptions using following line stripe_subscriptions = Stripe::Subscription.retrieve(event.data.object.subscription)

    And we can for_each the each sub-subscription that user has subscribed to and save in our database.