McTaba Labs logo
Bonaventure OgetoBy Bonaventure Ogeto|

Verify Paystack Payments in Ruby on Rails

To verify a Paystack payment in Rails, call the Paystack verify endpoint with your PaystackService, check status, amount, and currency against your Order model, and use Order.where(reference: ref, paid: false).update_all(paid: true) for idempotent fulfillment.

Verification Service Method

# app/services/paystack_service.rb (extended)
def verify_and_fulfill(reference)
  order = Order.find_by(reference: reference)
  return { error: 'Order not found' } unless order
  return { success: true, already_fulfilled: true } if order.paid?

  result = verify_transaction(reference)
  return { error: 'Verification failed' } unless result['status']
  return { error: 'Payment not successful' } unless result['data']['status'] == 'success'
  return { error: 'Amount mismatch' } if result['data']['amount'] != order.amount_kobo
  return { error: 'Currency mismatch' } if result['data']['currency'] != order.currency

  updated = Order.where(reference: reference, paid: false)
                 .update_all(paid: true, paid_at: Time.current)

  { success: true, already_fulfilled: updated == 0 }
end

Controller Usage

def callback
  reference = params[:reference] || params[:trxref]
  return redirect_to root_path, alert: 'Missing reference' unless reference

  service = PaystackService.new
  result = service.verify_and_fulfill(reference)

  if result[:success]
    render :success
  else
    flash[:error] = result[:error]
    render :failed
  end
end

Get weekly developer tips

Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.

No spam. Unsubscribe anytime.

Common Mistakes

  • Using update instead of update_all. update triggers callbacks and is not atomic for concurrent requests.
  • Not checking currency. Always verify the currency matches your model.
  • Mixing test and live keys. Both must be in the same mode.

Ship Payments Faster

Key Takeaways

  • Verification is a GET request to the Paystack API. Use your PaystackService for consistency.
  • Always check status, amount, and currency against your ActiveRecord model.
  • Use where(paid: false).update_all for atomic idempotent fulfillment.
  • Create a verify_and_fulfill method in your service for reuse across callbacks and webhooks.
  • Never trust URL parameters as proof of payment.
  • If verification fails due to network issues, retry. Transaction state does not change.

Frequently Asked Questions

Should I use update_all or update for fulfillment?
Use update_all with a where clause. It generates a single SQL UPDATE with a WHERE condition, making it atomic. Regular update loads the record first, leaving a window for race conditions.
Can I verify a transaction multiple times?
Yes. The Paystack verify endpoint is idempotent and returns the same result every time.
Should I verify in webhooks too?
Yes. Call verify_and_fulfill from both your callback action and webhook handler. The idempotent logic ensures only one fulfills the order.

Learn Paystack Integration

KES 2,999

The definitive guide to building payment systems with Paystack — from your first transaction to production-grade payment infrastructure across Africa. 9 modules, 47 lessons. Free preview available.

Start Paystack Course

Not ready? Create Free Account