I have a rails application that uses Stripe for credit card processing. Currently several exceptions are being handled anywhere a transaction takes place. The code below is being used currently in 11 places. In all places it is essentially the same with the exception of the message being passed to stripe_error. Is it possible to create a reusable piece of code that can be used in all these places?

  charge = Stripe::Charge.retrieve(@purchase.stripe_charge_id)
  resp = charge.capture(amount: fee.cancellation_fee,
                        receipt_email: @customer.email)
    accepted_charge: true,
    stripe_transaction_id: resp['balance_transaction']
  logger.info("Charged customer for cancellation #{@customer.id} #{@purchase.total_fee}")
  event('cancellation_charge', 'purchase_id', @purchase.id,
        fee: @purchase.total_fee, customer_id: @purchase.customer_id,
        provider_id: @purchase.provider_id)
rescue Stripe::CardError => e
  @err = stripe_error(e, 'cancellation', fee.cancellation_fee)
    accepted_charge: false,
    charge_errors: message,
    stripe_transaction_id: '',
    status: "Cancellation fee charge did not go through #{@err['message']}"
  render :err_show, status: :payment_required, json: @err
rescue Stripe::InvalidRequestError => e
  @err = stripe_error(e, 'cancellation_invalid_request', fee.cancellation_fee)
  render :err_show, status: :payment_required, json: @err
rescue Stripe::AuthenticationError => e
  @err = stripe_error(e, 'cancellation_authentication', fee.cancellation_fee)
  render :err_show, status: :payment_required, json: @err
rescue Stripe::APIConnectionError => e
  @err = stripe_error(e, 'cancellation_api_connect', fee.cancellation_fee)
  render :err_show, status: :payment_required, json: @err
rescue Stripe::StripeError => e
  @err = stripe_error(e, 'cancellation_generic error', fee.cancellation_fee)
  render :err_show, status: :payment_required, json: @err
rescue => e
  @err = stripe_error(e, 'cancellation_something_else', fee.cancellation_fee)
  render :err_show, status: :payment_required, json: @err


  def stripe_error(e, charge_type, fee = 0)
    logger.error("e #{e}")
    err = {
      charge_type: charge_type,
      errcode: ERR_STRIPE_ERR,
      message: "#{e}"
    event(charge_type, 'error', "#{e}")
    logger.error("Charging error on #{charge_type} purchase for #{fee} ")
    logger.error("type #{e} ")
  • 2
    \$\begingroup\$ Do these exceptions inherit from a Stripe exception base? You could catch that base, and check for the is_a? of the exception later to change the string you use when you forward it \$\endgroup\$ – casraf May 14 '15 at 5:22
  • 1
    \$\begingroup\$ Stripe API for Ruby \$\endgroup\$ – 200_success May 14 '15 at 10:55
  • \$\begingroup\$ I'm sure this can be simplified, but the solution would probably involve the stripe_error method does, which isn't included in the code posted. \$\endgroup\$ – Flambino May 14 '15 at 17:05
  • \$\begingroup\$ @Flambino I've update the post with stripe_error code . Thanks \$\endgroup\$ – Antarr Byrd May 14 '15 at 17:11

Your first step would be to separate out actually rendering the error message from rescueing the exceptions:

def render_errors(errors, template: :err_show,  status: :payment_required)
  render template, status: status, json: errors

Then can you group the majority of the exceptions:

rescue Stripe::InvalidRequestError, 
       Stripe::StripeError => e

render_errors( stripe_error(e) )

A good idea would be then to separate generating the errors and logging them.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.