notebook/app/controllers/subscriptions_controller.rb
2017-03-24 22:01:02 +00:00

265 lines
10 KiB
Ruby

class SubscriptionsController < ApplicationController
protect_from_forgery except: :stripe_webhook
def new
return redirect_to new_user_session_path, notice: t(:no_do_permission) unless user_signed_in?
Mixpanel::Tracker.new(Rails.application.config.mixpanel_token).track(current_user.id, 'viewed billing page', {
'current billing plan': current_user.selected_billing_plan_id,
'content count': current_user.content_count
})
# We only support a single billing plan right now, so just grab the first one. If they don't have an active plan,
# we also treat them as if they have a Starter plan.
@active_billing_plan = current_user.active_billing_plans.first || BillingPlan.find_by(stripe_plan_id: 'starter')
@stripe_customer = Stripe::Customer.retrieve(current_user.stripe_customer_id)
@stripe_invoices = @stripe_customer.invoices # makes a second call to Stripe
end
def show
end
def change
new_plan_id = params[:stripe_plan_id]
possible_plan_ids = BillingPlan.where(available: true).map(&:stripe_plan_id)
raise "Invalid billing plan ID: #{new_plan_id}" unless possible_plan_ids.include? new_plan_id
# If the user is changing to Starter, go ahead and cancel any active subscriptions and do it
if new_plan_id == 'starter'
current_user.active_subscriptions.each do |subscription|
subscription.update(end_date: Time.now)
end
if current_user.selected_billing_plan_id.nil?
old_billing_plan = BillingPlan.new(name: 'No billing plan')
else
old_billing_plan = BillingPlan.find(current_user.selected_billing_plan_id)
end
new_billing_plan = BillingPlan.find_by(stripe_plan_id: new_plan_id, available: true)
current_user.selected_billing_plan_id = new_billing_plan.id
# Remove any bonus bandwidth our old plan granted
current_user.upload_bandwidth_kb -= old_billing_plan.bonus_bandwidth_kb
current_user.save
Subscription.create(
user: current_user,
billing_plan: new_billing_plan,
start_date: Time.now,
end_date: Time.now.end_of_day + 5.years
)
report_subscription_change_to_slack current_user, old_billing_plan, new_billing_plan
flash[:notice] = "You have been successfully downgraded to Starter." #todo proration/credit
return redirect_to subscription_path
end
# Fetch current subscription
stripe_customer = Stripe::Customer.retrieve current_user.stripe_customer_id
stripe_subscription = stripe_customer.subscriptions.data[0]
# If the user already has a payment method on file, change their plan and add a new subscription
if stripe_customer.sources.total_count > 0
# Cancel any active subscriptions, since we're changing plans
current_user.active_subscriptions.each do |subscription|
subscription.update(end_date: Time.now)
end
# Change subscription plan if they already have a payment method on file
stripe_subscription.plan = new_plan_id
begin
stripe_subscription.save
rescue Stripe::CardError => e
flash[:alert] = "We couldn't upgrade you to Premium because #{e.message.downcase} Please double check that your information is correct."
return redirect_to :back
end
if current_user.selected_billing_plan_id.nil?
old_billing_plan = BillingPlan.new(name: 'No billing plan')
else
old_billing_plan = BillingPlan.find(current_user.selected_billing_plan_id)
end
new_billing_plan = BillingPlan.find_by(stripe_plan_id: new_plan_id, available: true)
current_user.selected_billing_plan_id = new_billing_plan.id
# Add any bonus bandwidth our new plan grants
current_user.upload_bandwidth_kb += new_billing_plan.bonus_bandwidth_kb
current_user.save
Subscription.create(
user: current_user,
billing_plan: new_billing_plan,
start_date: Time.now,
end_date: Time.now.end_of_day + 5.years
)
report_subscription_change_to_slack current_user, old_billing_plan, new_billing_plan
flash[:notice] = "You have been successfully upgraded to #{new_billing_plan.name}!"
redirect_to subscription_path
else
# If they don't have a payment method on file, redirect them to collect one
redirect_to payment_info_path(plan: new_plan_id)
end
end
# This isn't actually needed since we change the paid plan to the free plan, but will be needed when we
# add a way to deactivate/delete accounts, so the logic is here for when it's needed.
# def cancel
# # Fetch the user's current subscription
# stripe_customer = Stripe::Customer.retrieve current_user.stripe_customer_id
# stripe_subscription = stripe_customer.subscriptions.data[0]
# # Cancel it at the end of its effective period on Stripe's end, so they don't get rebilled
# stripe_subscription.delete(at_period_end: true)
# end
def information
@selected_plan = BillingPlan.find_by(stripe_plan_id: params['plan'], available: true)
@stripe_customer = Stripe::Customer.retrieve(current_user.stripe_customer_id)
Mixpanel::Tracker.new(Rails.application.config.mixpanel_token).track(current_user.id, 'viewed payment method page', {
'current billing plan': current_user.selected_billing_plan_id,
'content count': current_user.content_count
})
end
def information_change
# No idea why current_user is nil for this endpoint (maybe CSRF isn't passing through correctly?) but
# calling authenticate_user! here reauths the user and sets current_user
authenticate_user!
valid_token = params[:stripeToken]
raise "Invalid token" if valid_token.nil?
stripe_customer = Stripe::Customer.retrieve current_user.stripe_customer_id
stripe_subscription = stripe_customer.subscriptions.data[0]
begin
# Delete all existing payment methods to have our new one "replace" them
stripe_customer.sources.each do |payment_method|
payment_method.delete
end
# Add the new card info
stripe_customer.sources.create(source: valid_token)
rescue Stripe::CardError => e
flash[:alert] = "We couldn't save your payment information because #{e.message.downcase} Please double check that your information is correct."
return redirect_to :back
end
notice = []
# After saving the user's payment method, move them over to the associated billing plan
new_billing_plan = BillingPlan.find_by(stripe_plan_id: params[:plan], available: true)
if new_billing_plan
if current_user.selected_billing_plan_id.nil?
old_billing_plan = BillingPlan.new(name: 'No billing plan')
else
old_billing_plan = BillingPlan.find(current_user.selected_billing_plan_id)
end
current_user.selected_billing_plan_id = new_billing_plan.id
# Remove any bonus bandwidth our old plan granted
current_user.upload_bandwidth_kb -= old_billing_plan.bonus_bandwidth_kb
# Add any bonus bandwidth our new plan grants
current_user.upload_bandwidth_kb += new_billing_plan.bonus_bandwidth_kb
current_user.save
stripe_subscription.plan = new_billing_plan.stripe_plan_id
begin
stripe_subscription.save
rescue Stripe::CardError => e
flash[:alert] = "We couldn't upgrade you to Premium because #{e.message.downcase} Please double check that your information is correct."
return redirect_to :back
end
# End all currently-active subscriptions
current_user.active_subscriptions.each do |subscription|
subscription.update(end_date: Time.now)
end
# And create a subscription for them for the current plan
Subscription.create(
user: current_user,
billing_plan: new_billing_plan,
start_date: Time.now,
end_date: Time.now.end_of_day + 31.days
)
report_subscription_change_to_slack current_user, old_billing_plan, new_billing_plan
notice << "you have been successfully upgraded to #{new_billing_plan.name}"
end
notice << "Your payment method has been successfully saved"
flash[:notice] = "#{notice.reverse.to_sentence}."
redirect_to subscription_path
end
def delete_payment_method
stripe_customer = Stripe::Customer.retrieve current_user.stripe_customer_id
stripe_subscription = stripe_customer.subscriptions.data[0]
stripe_customer.sources.each do |payment_method|
payment_method.delete
end
notice = ['Your payment method has been successfully deleted.']
if stripe_subscription.plan.id != 'starter'
# Cancel the user's at the end of its effective period on Stripe's end, so they don't get rebilled
stripe_subscription.delete(at_period_end: true)
active_billing_plan = BillingPlan.find_by(stripe_plan_id: stripe_subscription.plan.id)
if active_billing_plan
notice << "Your #{active_billing_plan.name} subscription will end on #{Time.at(stripe_subscription.current_period_end).strftime('%B %d')}."
end
end
flash[:notice] = notice.join ' '
redirect_to :back
end
def stripe_webhook
Mixpanel::Tracker.new(Rails.application.config.mixpanel_token).track(current_user.id, 'stripe webhook')
#todo handle webhooks
end
def report_subscription_change_to_slack user, from, to
return unless Rails.env == 'production'
slack_hook = ENV['SLACK_HOOK']
return unless slack_hook
notifier = Slack::Notifier.new slack_hook,
channel: '#subscriptions',
username: 'tristan'
if from.nil? || to.nil?
delta = ":tada: LOL :tada:"
elsif from.monthly_cents < to.monthly_cents
delta = ":tada: *UPGRADE* :tada:"
else
delta = ":wave: Downgrade"
end
active_subscriptions = Subscription.where('start_date < ?', Time.now).where('end_date > ?', Time.now)
total_subs_monthly = active_subscriptions.map(&:billing_plan).sum(&:monthly_cents).to_f / 100
notifier.ping [
"#{delta} for #{user.email.split('@').first}@ (##{user.id})",
"From: *#{from.name}* ($#{from.monthly_cents / 100}/month)",
"To: *#{to.name}* ($#{to.monthly_cents / 100}/month)",
"#{active_subscriptions.count} subscriptions total $#{'%.2f' % total_subs_monthly}/mo"
].join("\n")
end
end