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.
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