Home > Net >  500 error for stripe webhook event checkout.session.completed
500 error for stripe webhook event checkout.session.completed

Time:06-27

I am currently working on stripe webhooks for my rails application and am encountering a problem. All events except for checkout.session.completed are working. My main goal is to change the payment status booking.paid to true when the event checkout.session.completed happens. The stripe webhooks logs give me a 500 internal server error for the event checkout.session.completed. I think the problem is in my Webhook controller but I just can't figure out what's wrong. Any help would be amazing!

This is my Webhooks_controller:

 class WebhooksController < ApplicationController
  skip_before_action :authenticate_user!
  skip_before_action :verify_authenticity_token

  def create
    payload = request.body.read
    sig_header = request.env['HTTP_STRIPE_SIGNATURE']
    event = nil

    begin
      event = Stripe::Webhook.construct_event(
        payload, sig_header, Rails.application.credentials[:stripe][:webhook]
      )
    rescue JSON::ParserError => e
      status 400
      return
    rescue Stripe::SignatureVerificationError => e
      # Invalid signature
      puts "Signature error"
      p e
      return
    end

    # Handle the event
    case event.type
    when 'checkout.session.completed'
      # session = event.data.object
      # @booking.session.client_reference_id.paid = true
      booking = Booking.find_by(checkout_session_id: event.data.object.id)
      booking.update(paid: true)
    end

    render json: { message: 'success' }
  end
end

CodePudding user response:

I think the issue might lie in the Booking.find_by method. Try adding a line to inspect the value of booking prior to updating its status.

CodePudding user response:

I just happen to be writing the exact same feature as you so I'm glad this popped up in my queue.

From taking a quick look at the code nothing stands out much. If we know that the only event that doesn't work is checkout.session.completed, and that's the only one we're even processing, that narrows the problem down a bit... so here's what I did:

  1. I copied your implementation into a controller in my Rails API project, then used the Stripe CLI to listen for, and forward Stripe events to the new endpoint:
stripe listen --forward-to http://localhost:3000/webhook_events
  1. I commented out the actual handling of the event so it was only processing the event.

  2. I then used the Stripe CLI in a new terminal to trigger a checkout.session.completed event:

$ stripe trigger checkout.session.completed
  1. Once I did this, my API responded with a 201 and Stripe was happy.

So after all of that, as the previous answer suggests, I think the issue lies with your updating the Booking model, so I have a few suggestions to make working with webhooks in general easier:

  1. Ideally, your controller should respond with a 2xx to Stripe as soon as you've verified the authenticity of the event with the Stripe gem.
  2. Once you've completed that, I would immediately move the processing of the event to a background job using ActiveJob.
  3. In the background job, you know that your event is valid and that the session completed successfully, so now you can start to update your Booking model. The arguments to the job could be as simple as just the Stripe checkout session ID.
  4. Finally, splitting the responsibilities like this will make writing tests much easier (and will catch what the actual problem is!).

I hope this helps, good luck!

  • Related