3
\$\begingroup\$

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?

begin
  charge = Stripe::Charge.retrieve(@purchase.stripe_charge_id)
  resp = charge.capture(amount: fee.cancellation_fee,
                        receipt_email: @customer.email)
  @purchase.update_attributes(
    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)
  purchase_set_md5(@purchase.id)
rescue Stripe::CardError => e
  @err = stripe_error(e, 'cancellation', fee.cancellation_fee)
  @purchase.update_attributes(
    accepted_charge: false,
    charge_errors: message,
    stripe_transaction_id: '',
    status: "Cancellation fee charge did not go through #{@err['message']}"
  )
  purchase_set_md5(@purchase.id)
  render :err_show, status: :payment_required, json: @err
  return
rescue Stripe::InvalidRequestError => e
  @err = stripe_error(e, 'cancellation_invalid_request', fee.cancellation_fee)
  render :err_show, status: :payment_required, json: @err
  return
rescue Stripe::AuthenticationError => e
  @err = stripe_error(e, 'cancellation_authentication', fee.cancellation_fee)
  render :err_show, status: :payment_required, json: @err
  return
rescue Stripe::APIConnectionError => e
  @err = stripe_error(e, 'cancellation_api_connect', fee.cancellation_fee)
  render :err_show, status: :payment_required, json: @err
  return
rescue Stripe::StripeError => e
  @err = stripe_error(e, 'cancellation_generic error', fee.cancellation_fee)
  render :err_show, status: :payment_required, json: @err
  return
rescue => e
  @err = stripe_error(e, 'cancellation_something_else', fee.cancellation_fee)
  render :err_show, status: :payment_required, json: @err
  return
end

stripe_error

  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} ")
    err
  end
\$\endgroup\$
  • 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
1
\$\begingroup\$

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
end

Then can you group the majority of the exceptions:

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

render_errors( stripe_error(e) )

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

\$\endgroup\$

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.