Skip to content

Commit

Permalink
Merge pull request #99 from ryanckulp/embedded_stripe_checkout
Browse files Browse the repository at this point in the history
Embedded Stripe Checkout
  • Loading branch information
ryanckulp authored Oct 26, 2023
2 parents 25b36a2 + 784b896 commit b1ba43b
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 71 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ features:
## Installation
1. clone the repo
2. `bin/speedrail new_app_name`
3. plug ENV vars into `config/application.yml`

## Development
```sh
Expand Down
1 change: 0 additions & 1 deletion app/controllers/account_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ def account_update_params
end

def set_flashes
flash.now[:alert] = 'Subscription declined' if params[:aborted] == 'true'
flash.now[:notice] = 'Subscription updated successfully' if params[:updated] == 'true'
end
end
43 changes: 26 additions & 17 deletions app/controllers/billing_portal_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,53 @@ class BillingPortalController < ApplicationController
before_action :authenticate_user!
skip_before_action :verify_authenticity_token, only: [:create] # ajax

def create
url = current_user.finished_onboarding? ? modify_subscription : begin_subscription

respond_to do |format|
format.html { redirect_to url, allow_other_host: true }
format.json { render json: { url: url } }
def new
session = Stripe::Checkout::Session.retrieve(params[:session_id])

# can add more checks, just inspect the 'session' and 'session.customer_details' object
if session.status == 'complete'
current_user.delay.set_stripe_subscription
redirect_to dashboard_index_path, notice: 'Your account is now active!'
else
redirect_to subscribe_index_path, alert: "Please subscribe to continue."
end
end

def destroy
current_user.unsubscribe!
def create
if current_user.finished_onboarding?
redirect_to modify_subscription, allow_other_host: true
else
render json: create_subscription
end
end

private

# invoked from /subscribe during onboarding
def begin_subscription
def create_subscription
session = Stripe::Checkout::Session.create({
ui_mode: 'embedded',
customer: current_user.stripe_customer_id,
payment_method_types: ['card'],
mode: 'subscription',
allow_promotion_codes: true,
payment_method_types: ['card'],
line_items: [{
quantity: 1,
price: ENV['STRIPE_PRODUCT_PRICE_ID']
# Provide the Price ID (e.g. price_1234) of the product you want to sell
price: ENV['STRIPE_PRODUCT_PRICE_ID'],
quantity: 1
}],
success_url: "#{ENV['BASE_URL']}#{dashboard_index_path}?subscribed=true",
cancel_url: "#{ENV['BASE_URL']}#{account_index_path}?aborted=true"
mode: 'subscription', # use 'payment' for products with 1-time pricing
return_url: "#{ENV['BASE_URL']}#{new_billing_portal_path}?session_id={CHECKOUT_SESSION_ID}",
automatic_tax: { enabled: false }
})

session.url
{ clientSecret: session.client_secret }
end

# invoked from /account when user is already subscribed
def modify_subscription
session = Stripe::BillingPortal::Session.create({
customer: current_user.stripe_customer_id,
return_url: "#{ENV['BASE_URL']}/#{account_index_path}?updated=true"
return_url: "#{ENV['BASE_URL']}#{account_index_path}?updated=true"
})

session.url
Expand Down
10 changes: 0 additions & 10 deletions app/controllers/dashboard_controller.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
class DashboardController < ApplicationController
before_action :authenticate_user!
before_action :set_flashes

def index; end

private

def set_flashes
if params[:subscribed] == 'true'
current_user.delay.set_stripe_subscription
flash.now[:notice] = 'Your account is now active!'
end
end
end
17 changes: 12 additions & 5 deletions app/models/concerns/billable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,22 @@ def setup_stripe_customer

update(stripe_customer_id: customer.id)
end
# handle_asynchronously :setup_stripe_customer

# done after user adds payment method, for easy CVR metrics inside Stripe UI
# done after user adds payment method, for easy CVR metrics inside database
def set_stripe_subscription
cust = Stripe::Customer.retrieve({
subscription_id = stripe_subscriptions&.first&.id
paying_customer = subscription_id ? true : false
update(stripe_subscription_id: subscription_id, paying_customer: paying_customer)
end

def stripe_subscriptions
stripe_customer.subscriptions
end

def stripe_customer
Stripe::Customer.retrieve({
id: stripe_customer_id,
expand: ['subscriptions']
})
subscription_id = cust.subscriptions.first.id
update(stripe_subscription_id: subscription_id, paying_customer: true)
end
end
2 changes: 1 addition & 1 deletion app/views/account/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
Billing Status: <%= red_green_message(current_user.paying_customer?, 'Active', 'Inactive') %><br>
</div>
<div class="flex-shrink">
<%= link_to 'Manage >>', billing_portal_path, data: { turbo: false }, class: "font-medium text-primary-500" %>
<%= button_to 'Manage >>', billing_portal_index_path, method: :post, data: { turbo: false }, class: "font-medium text-primary-500" %>
</div>
</div>

Expand Down
54 changes: 22 additions & 32 deletions app/views/subscribe/index.html.erb
Original file line number Diff line number Diff line change
@@ -1,39 +1,29 @@
<%= render partial: "shared/heading", locals: { title: 'Start Trial', description: "Start your 14 day free trial of #{ENV['COMPANY_NAME']}." } %>

<div class="text-center">
<!-- provide an image to compel user to add payment details -->
<!-- <%= image_path "", style: "display: inline-block; max-height: 375px;", class: "mt-6 object-center" %> -->
</div>

<p class="mt-12 text-center">Click here to choose a plan and activate your account.</p>
<div class="mt-2 justify-center text-center">
<div class="text-center inline-flex rounded-md shadow">
<button onclick="beginSubscription()" type="submit" class="items-center justify-center px-5 py-3 border border-transparent text-base font-medium rounded-md text-white bg-primary-600 hover:bg-primary-700">
Start Free
</button>
</div>
<div class="mt-2 text-center">
<!-- bind this element to a live chat tool or mailto address -->
<a id="open-live-chat" href="#" onclick="return false;" class="font-medium text-primary-300 hover:text-primary-500">Still have questions?</a>
</div>
<div id="checkout">
<!-- Checkout will insert the payment form here -->
</div>

<script src="https://js.stripe.com/v3/"></script>
<script type="text/javascript">
var beginSubscription = function() {
console.log('building subscription...');
// This is your test publishable API key.
const stripe = Stripe('<%= ENV['STRIPE_PUBLISHABLE_KEY'] %>');

initialize();

// Create a Checkout Session as soon as the page loads
async function initialize() {
const response = await fetch("/billing_portal", {
method: "POST",
});

const { clientSecret } = await response.json();

const checkout = await stripe.initEmbeddedCheckout({
clientSecret,
});

$.ajax({
url: '<%= billing_portal_index_path %>',
method: 'POST',
dataType: 'json',
data: {},
success: function(data) {
console.log('success! portal url: ', data.url)
window.location.href = data.url;
},
error: function(data) {
window.alert('Sorry, something went wrong. Please try again.');
}
})
}
// Mount Checkout
checkout.mount('#checkout');
}
</script>
6 changes: 4 additions & 2 deletions config/application-sample.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ COMPANY_NAME: Speedrail
POSTMARK_API_TOKEN: xxxx-yyy-zzzz
development:
BASE_URL: http://localhost:3000
STRIPE_PRODUCT_PRICE_ID: price_1asdfasdf
STRIPE_PRODUCT_PRICE_ID:
STRIPE_PUBLISHABLE_KEY:
STRIPE_SECRET_KEY:
production:
BASE_URL: https://speedrail.com
STRIPE_PRODUCT_PRICE_ID: price_1asdfasdf
STRIPE_PRODUCT_PRICE_ID:
STRIPE_PUBLISHABLE_KEY:
STRIPE_SECRET_KEY:
4 changes: 1 addition & 3 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
resources :subscribe, only: [:index]
resources :dashboard, only: [:index]
resources :account, only: [:index, :update]
resources :billing_portal, only: [:create]
match '/billing_portal' => 'billing_portal#create', via: [:get]
match '/cancel' => 'billing_portal#destroy', via: [:get]
resources :billing_portal, only: [:new, :create]

# static pages
pages = %w[
Expand Down

0 comments on commit b1ba43b

Please sign in to comment.