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