Skip to content

Commit

Permalink
Replace Stripe Plan API with the Prices API
Browse files Browse the repository at this point in the history
Using Prices provides more flexibility and will allow us to change the
which prices are used on both current and future subscriptions.
  • Loading branch information
gbp committed Oct 18, 2024
1 parent 479c599 commit 8487998
Show file tree
Hide file tree
Showing 18 changed files with 359 additions and 301 deletions.
6 changes: 3 additions & 3 deletions app/controllers/alaveteli_pro/plans_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ class AlaveteliPro::PlansController < AlaveteliPro::BaseController
before_action :authenticate, :check_has_current_subscription, only: [:show]

def index
@plans = AlaveteliPro::Plan.list
@prices = AlaveteliPro::Price.list
@pro_site_name = pro_site_name
end

def show
@plan = AlaveteliPro::Plan.retrieve(params[:id])
@plan || raise(ActiveRecord::RecordNotFound)
@price = AlaveteliPro::Price.retrieve(params[:id])
@price || raise(ActiveRecord::RecordNotFound)
end

private
Expand Down
18 changes: 9 additions & 9 deletions app/controllers/alaveteli_pro/subscriptions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class AlaveteliPro::SubscriptionsController < AlaveteliPro::BaseController

before_action :check_allowed_to_subscribe_to_pro, only: [:create]
before_action :prevent_duplicate_submission, only: [:create]
before_action :load_plan, :load_coupon, only: [:create]
before_action :load_price, :load_coupon, only: [:create]

def index
@customer = current_user.pro_account.try(:stripe_customer)
Expand All @@ -28,8 +28,8 @@ def create
@pro_account.update_stripe_customer

attributes = {
plan: @plan.id,
tax_percent: @plan.tax_percent,
items: [{ price: @price.id }],
tax_percent: @price.tax_percent,
payment_behavior: 'allow_incomplete'
}
attributes[:coupon] = @coupon.id if @coupon
Expand Down Expand Up @@ -62,7 +62,7 @@ def create
end

if flash[:error]
json_redirect_to plan_path(@plan)
json_redirect_to plan_path(@price)
else
redirect_to authorise_subscription_path(@subscription.id)
end
Expand All @@ -89,7 +89,7 @@ def authorise
flash[:error] = _('There was a problem authorising your payment. You ' \
'have not been charged. Please try again.')

json_redirect_to plan_path(@subscription.plan)
json_redirect_to plan_path(@subscription.price)

elsif @subscription.active?
current_user.add_role(:pro)
Expand Down Expand Up @@ -168,16 +168,16 @@ def check_allowed_to_subscribe_to_pro
end

def check_has_current_subscription
# TODO: This doesn't take the plan in to account
# TODO: This doesn't take the price in to account
return if @user.pro_account.try(:subscription?)

flash[:notice] = _("You don't currently have a Pro subscription")
redirect_to pro_plans_path
end

def load_plan
@plan = AlaveteliPro::Plan.retrieve(params[:plan_id])
@plan || redirect_to(pro_plans_path)
def load_price
@price = AlaveteliPro::Price.retrieve(params[:price_id])
@price || redirect_to(pro_plans_path)
end

def load_coupon
Expand Down
45 changes: 0 additions & 45 deletions app/helpers/alaveteli_pro/plan_helper.rb

This file was deleted.

45 changes: 45 additions & 0 deletions app/helpers/alaveteli_pro/price_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
##
# Helper methods for formatting and displaying billing and price information
# in the Alaveteli Pro interface
#
module AlaveteliPro::PriceHelper
def billing_frequency(price)
if interval(price) == 'day' && interval_count(price) == 1
_('Billed: Daily')
elsif interval(price) == 'week' && interval_count(price) == 1
_('Billed: Weekly')
elsif interval(price) == 'month' && interval_count(price) == 1
_('Billed: Monthly')
elsif interval(price) == 'year' && interval_count(price) == 1
_('Billed: Annually')
else
_('Billed: every {{interval}}', interval: interval(price))
end
end

def billing_interval(price)
if interval_count(price) == 1
_('per user, per {{interval}}', interval: pluralize_interval(price))
else
_('per user, every {{interval}}', interval: pluralize_interval(price))
end
end

private

def pluralize_interval(price)
count = interval_count(price)
interval = interval(price)
return interval if count == 1

pluralize(count, interval)
end

def interval(price)
price.recurring['interval']
end

def interval_count(price)
price.recurring['interval_count']
end
end
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
##
# A wrapper for a Stripe::Plan
# A wrapper for a Stripe::Price
#
class AlaveteliPro::Plan < SimpleDelegator
class AlaveteliPro::Price < SimpleDelegator
extend AlaveteliPro::StripeNamespace
include AlaveteliPro::StripeNamespace
include Taxable

tax :amount
tax :unit_amount

def self.list
@list ||= [retrieve('pro')]
@list ||= AlaveteliConfiguration.stripe_price_ids.inject([]) do |arr, id|
price = retrieve(id)
arr << price if price
arr
end
end

def self.retrieve(id)
new(Stripe::Plan.retrieve(add_stripe_namespace(id)))
new(Stripe::Price.retrieve(add_stripe_namespace(id)))
rescue Stripe::InvalidRequestError
nil
end
Expand Down
6 changes: 3 additions & 3 deletions app/models/alaveteli_pro/subscription.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ def delete
Stripe::Subscription.cancel(id)
end

# plan
def plan
@plan ||= AlaveteliPro::Plan.new(__getobj__.plan)
# price
def price
@price ||= AlaveteliPro::Price.new(items.first.price)
end

private
Expand Down
8 changes: 4 additions & 4 deletions app/views/alaveteli_pro/plans/_pricing_tiers.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="pricing__tiers">
<% @plans.each do |plan| %>
<% @prices.each do |price| %>
<div class="pricing__tier pricing__tier--primary">
<div class="pricing__tier__heading">
<h2><%= _('Professional') %></h2>
Expand All @@ -10,10 +10,10 @@

<p class="price-label">
<span class="price-label__amount">
<%= format_currency(plan.amount_with_tax, no_cents_if_whole: true) %>
<%= format_currency(price.unit_amount_with_tax, no_cents_if_whole: true) %>
</span>

<%= billing_interval(plan) %>
<%= billing_interval(price) %>
</p>
</div>

Expand All @@ -27,7 +27,7 @@
<li><%= _('Friendly support') %></li>
</ul>

<%= link_to _('Sign up'), plan_path(plan), class: 'button button-pop' %>
<%= link_to _('Sign up'), plan_path(price), class: 'button button-pop' %>
</div>
</div>
<% end %>
Expand Down
8 changes: 4 additions & 4 deletions app/views/alaveteli_pro/plans/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@
<h3><%= _('Selected plan') %></h3>
<div class="plan-overview">
<div class="plan-overview__desc">
<%= @plan.product.name %>
<%= @price.product.name %>
</div>
<div class="plan-overview__amount">
<%= format_currency(@plan.amount_with_tax) %>
<%= billing_frequency(@plan) %>
<%= format_currency(@price.unit_amount_with_tax) %>
<%= billing_frequency(@price) %>
</div>
</div>
</div>
Expand Down Expand Up @@ -65,7 +65,7 @@
</div>

<div class="settings__section">
<%= hidden_field_tag 'plan_id', @plan.id %>
<%= hidden_field_tag 'price_id', @price.id %>
<%= submit_tag _('Subscribe'), id: 'js-stripe-submit', disabled: true, data: { disable_with: 'Processing...' } %>
<%= link_to _('Cancel'), pro_plans_path, class: 'settings__cancel-button' %>
<p id="card-errors"></p>
Expand Down
6 changes: 3 additions & 3 deletions app/views/alaveteli_pro/subscriptions/_subscription.html.erb
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@

<div class="plan-overview">
<div class="plan-overview__desc">
<%= subscription.plan.product.name %>
<%= subscription.price.product.name %>
</div>

<div class="plan-overview__amount">
<%= format_currency(subscription.plan.amount_with_tax) %>
<%= billing_frequency(subscription.plan) %>
<%= format_currency(subscription.price.unit_amount_with_tax) %>
<%= billing_frequency(subscription.price) %>
<% if subscription.discounted? %>
<br>
<%= _('<strong>{{discounted_amount}}</strong> with discount ' \
Expand Down
15 changes: 15 additions & 0 deletions config/general.yml-example
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,21 @@ STRIPE_SECRET_KEY: ''
# ---
STRIPE_NAMESPACE: ''

# List of Stripe Subscription Prices IDs which if a user signs up to will grant
# them access to Alaveteli Pro. Rendered on the Pro pricing pages in the ordered
# defined here.
#
# STRIPE_PRICE_IDS - Array Stripe Price IDs
#
# Examples:
#
# STRIPE_PRICE_IDS:
# - pro
# - pro-annual-billing
#
# ---
STRIPE_PRICE_IDS: []

# Stripe.com webhook secret. Only required for Alaveteli Pro.
#
# STRIPE_WEBHOOK_SECRET: - String (default: '')
Expand Down
1 change: 1 addition & 0 deletions lib/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ module AlaveteliConfiguration
SMTP_MAILER_PORT: 25,
SMTP_MAILER_USER_NAME: '',
STRIPE_NAMESPACE: '',
STRIPE_PRICE_IDS: [],
STRIPE_PUBLISHABLE_KEY: '',
STRIPE_SECRET_KEY: '',
STRIPE_TAX_RATE: '0.20',
Expand Down
Loading

0 comments on commit 8487998

Please sign in to comment.