| 1 | # frozen_string_literal: true |
| 2 | |
| 3 | # Web billing page for siGit Code (session-authenticated). Shows the plan + cloud |
| 4 | # usage and starts Stripe Checkout / Billing Portal sessions. Purchases happen on |
| 5 | # the web so the desktop app can link here and avoid the App Store cut. |
| 6 | class BillingController < ApplicationController |
| 7 | before_action :require_sign_in! |
| 8 | before_action :noindex! |
| 9 | |
| 10 | def show |
| 11 | @subscription = current_user.subscription |
| 12 | @plan = @subscription&.plan || "free" |
| 13 | @status = @subscription&.status |
| 14 | @entitled = current_user.entitled_to_cloud? |
| 15 | @used = current_user.cloud_requests_used |
| 16 | @allowance = current_user.cloud_allowance |
| 17 | @period_end = @subscription&.current_period_end |
| 18 | end |
| 19 | |
| 20 | def checkout |
| 21 | return redirect_to billing_path, alert: "Billing is not configured." unless StripeService.configured? |
| 22 | |
| 23 | plan = StripeService::PRICE_LOOKUP_KEYS.key?(params[:plan]) ? params[:plan] : "pro" |
| 24 | url = StripeService.checkout_url( |
| 25 | user: current_user, |
| 26 | plan: plan, |
| 27 | success_url: billing_url(billing: "success"), |
| 28 | cancel_url: billing_url(billing: "cancel") |
| 29 | ) |
| 30 | redirect_to url, allow_other_host: true |
| 31 | rescue Stripe::AuthenticationError, Stripe::PermissionError => e |
| 32 | # A revoked/expired key or wrong-account key — a server-side misconfig, not a |
| 33 | # user error. Don't tell the user to "try again"; flag it loudly for ops. |
| 34 | Rails.logger.error("Stripe is misconfigured (checkout): #{e.class}: #{e.message}") |
| 35 | redirect_to billing_path, alert: "Billing is temporarily unavailable. Please try again later." |
| 36 | rescue StandardError => e |
| 37 | Rails.logger.error("Stripe checkout failed: #{e.class}: #{e.message}") |
| 38 | redirect_to billing_path, alert: "Could not start checkout. Please try again." |
| 39 | end |
| 40 | |
| 41 | def portal |
| 42 | return redirect_to billing_path, alert: "Billing is not configured." unless StripeService.configured? |
| 43 | |
| 44 | url = StripeService.portal_url(user: current_user, return_url: billing_url) |
| 45 | return redirect_to billing_path, alert: "No subscription to manage yet." unless url |
| 46 | |
| 47 | redirect_to url, allow_other_host: true |
| 48 | rescue Stripe::AuthenticationError, Stripe::PermissionError => e |
| 49 | Rails.logger.error("Stripe is misconfigured (portal): #{e.class}: #{e.message}") |
| 50 | redirect_to billing_path, alert: "Billing is temporarily unavailable. Please try again later." |
| 51 | rescue StandardError => e |
| 52 | Rails.logger.error("Stripe portal failed: #{e.class}: #{e.message}") |
| 53 | redirect_to billing_path, alert: "Could not open the billing portal." |
| 54 | end |
| 55 | end |