McTaba Labs logo
Software EngineeringThe WhiteboardProjectsEventsMasterclassesWebinarsLearn
Book Call

500+ developers already in the community

Get answers, find accountability partners, and stay ahead

Join Discord →
McTaba Labs logo

Educating 1 million students in tech by 2030.

Programs

  • HighSchool Graduates Launchpad
  • AI & Business Automation
  • Corporate Training
  • McTaba Story & Mission
  • Full-Stack Curriculum
  • Course Pricing & Plans
  • Frequently Asked Questions

Resources

  • Join Discord Community
  • Tech Events in Nairobi
  • Masterclasses
  • Free Resources
  • Learn
  • Campus
  • Africa Tech Talent Report
  • Partner With Us
  • Start a Project
  • Our Work

Contact Us

  • 124 Manyani East Road, Lavington, Nairobi
  • +254727795603
  • Book a Discovery Call

Office Hours:

Mon-Fri: 9am - 2pm EAT

Sat: 10am - 12pm EAT

© 2027 McTaba Labs - A product of Edtech Industries. All rights reserved.

Privacy PolicyTerms of ServiceRefund Policy
  1. Learn
  2. Paystack for African Developers
  3. Build Paystack Subscriptions in Ruby on Rails
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 20, 2026

Build Paystack Subscriptions in Ruby on Rails

To build Paystack subscriptions in Rails, create a plan via the API, initialize a transaction with the plan code, handle subscription webhooks in ActiveJob, track status in an ActiveRecord model, and use before_action filters to gate premium content.

In this article

  1. 1. Subscription Model
  2. 2. Subscribe Action
  3. 3. Webhook Handlers
  4. 4. Access Control
  5. 5. Cancellation
  6. 6. Ship Payments Faster

Subscription Model

rails generate model Subscription user:references subscription_code:string:uniq plan_code:string email_token:string status:string next_payment_date:datetime
rails db:migrate

Subscribe Action

def subscribe
  service = PaystackService.new
  result = service.initialize_with_plan(
    email: current_user.email,
    plan_code: params[:plan_code],
    callback_url: subscription_callback_url
  )

  if result['status']
    redirect_to result['data']['authorization_url'], allow_other_host: true
  else
    flash[:error] = result['message']
    redirect_to pricing_path
  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.

Webhook Handlers

def handle_subscription_create(data)
  user = User.find_by(email: data['customer']['email'])
  return unless user

  Subscription.find_or_initialize_by(user: user).update!(
    subscription_code: data['subscription_code'],
    plan_code: data['plan']['plan_code'],
    email_token: data['email_token'] || '',
    status: 'active',
    next_payment_date: data['next_payment_date']
  )
end

def handle_invoice_failed(data)
  sub_code = data.dig('subscription', 'subscription_code')
  Subscription.where(subscription_code: sub_code).update_all(status: 'past_due') if sub_code
end

Access Control

# app/controllers/concerns/subscription_required.rb
module SubscriptionRequired
  extend ActiveSupport::Concern

  included do
    before_action :require_active_subscription
  end

  private

  def require_active_subscription
    unless current_user&.subscription&.status == 'active'
      redirect_to pricing_path, alert: 'An active subscription is required.'
    end
  end
end

# In premium controllers:
class PremiumController < ApplicationController
  include SubscriptionRequired
end

Cancellation

def cancel
  sub = current_user.subscription
  return redirect_to dashboard_path, alert: 'No subscription' unless sub

  service = PaystackService.new
  result = service.disable_subscription(sub.subscription_code, sub.email_token)

  if result['status']
    sub.update!(status: 'cancelled')
    redirect_to dashboard_path, notice: 'Subscription cancelled'
  else
    redirect_to dashboard_path, alert: 'Cancellation failed'
  end
end

Ship Payments Faster

This guide is part of the Paystack integration guides by language and framework series.

Sign up for the McTaba newsletter

Key Takeaways

  • ✓Paystack handles recurring billing. Create plans once and subscribe customers.
  • ✓Use ActiveRecord for subscription tracking with status, subscription_code, and email_token.
  • ✓Webhook events drive state changes. Handle subscription.create and invoice.payment_failed.
  • ✓Use before_action to gate premium controllers behind subscription checks.
  • ✓Store email_token for cancellation via the API.
  • ✓ActiveJob handles async webhook processing with Sidekiq or another backend.

Frequently Asked Questions

Can I use Stripe-like subscription gems with Paystack?
No. Gems like Pay and Cashier are designed for Stripe. Build Paystack subscriptions directly using the API and ActiveRecord as shown in this guide.
How do I handle plan upgrades?
Cancel the current subscription and create a new one on the new plan. Handle prorating in your Rails application.
What if a renewal payment fails?
Paystack retries automatically. You receive invoice.payment_failed webhooks. Update the status and notify the customer.

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

Keep reading

Paystack Integration Guides by Language and Framework

A complete directory of Paystack integration guides organized by programming language and framework. Each guide covers accepting payments, verifying transactions, handling webhooks, and building subscriptions in your specific stack.

Read more

Accept Payments with Paystack in Svelte and SvelteKit

Accept Paystack payments in SvelteKit using server endpoints for backend logic and Svelte components for the frontend. This guide covers initializing transactions, inline popup checkout, redirect checkout, and verification in a single full-stack SvelteKit project.

Read more

Verify Paystack Payments in Flask

Verify Paystack payments server-side in your Flask application. This guide covers calling the Paystack verify endpoint, validating amounts and currencies, building reusable verification helpers, and preventing double-granting.

Read more

Build Paystack Subscriptions in ASP.NET Core

Implement Paystack recurring billing in ASP.NET Core. This guide covers creating plans, subscribing customers through transaction initialization, handling renewal webhooks with C#, and cancelling subscriptions.

Read more

Paystack Charge API for Custom Checkout Experiences

The Paystack Charge API lets you collect payment details on your own form and submit them server-to-server. This guide walks through each charge channel, the submit flow, and the engineering decisions that come with owning your checkout UI.

Read more

Reading Paystack Gateway Response Codes

When a Paystack transaction fails, the gateway_response field contains the bank's reason. "Declined" is not helpful to a developer or a customer. This guide decodes every common response, explains the actual cause, and gives you the exact customer-facing message to show for each one.

Read more

Explore related topics

M-Pesa & African Stack

M-Pesa Daraja API tutorials, USSD development, and WhatsApp Business API guides. The African Stack that global bootcamps do not teach.

Learn to Code in Kenya

Everything a Kenyan needs to know before writing their first line of code. Career paths, real costs, hardware requirements, and honest answers about what it takes.

Learning to Code

Roadmaps, language guides, and practical advice for learning to code and launching a programming career.

Breaking Into Tech

Practical, no-nonsense guides for anyone looking to start or change their career in tech. From choosing your first language to acing interviews.

The African Stack: Skills for This Market

The skills that make Kenyan developers hard to replace: M-Pesa, USSD, WhatsApp, fintech, and building for the African market.

Bonaventure Ogeto

Bonaventure Ogeto

Founder, McTaba Labs

Bonaventure is the founder of McTaba Labs, a coding bootcamp in Nairobi, Kenya. He has spent years building products for the African market and mentoring the next generation of developers across the continent.