Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
April 14, 2023 05:03 pm GMT

Stripe Connect onboarding with Ruby on Rails

Stripe Connect provides a suite of tools and APIs that allow you to create, manage, and scale your platform or marketplace and facilitate payments and payouts for your users. If youre new to Stripe Connect, take a look at the first few articles in this series. In this article youll learn how to integrate Stripe Connect Onboarding with Ruby on Rails, so that you can start facilitating money movement for your users.

We'll focus on an email newsletter platform use case, where readers support their favorite authors by paying a monthly fee to receive periodic emails. Youll learn how to create Stripe Accounts and collect business details using Stripe Connect hosted onboarding. Well also cover setting up the Rails environment and some best practices for smooth integration.

Let's get started!

Creating a new Rails application

Well kick things off by breaking ground on a new Rails application that uses Tailwind CSS for styles and Postgres for the database. -T means skip adding the default testing infrastructure and --main sets the git branch name.

rails new newsletter-platform -c tailwind -j esbuild -d postgresql -T --main

Well store each newsletter issue in the database so that authors can direct users to their back catalog if theyd like to read past issues. Before sending a newsletter issue to a reader, well check to make sure readers have an active payment subscription.

Lets start by setting up these database models.

Database setup

To set up the necessary database models for this newsletter platform, we'll create the main models: User, Newsletter, NewsletterIssue, and Subscription. The User model represents the author, the Newsletter model corresponds to each collection of issues, the NewsletterIssue model represents each monthly edition of the newsletter, and the Subscription model links the readers to the newsletters they have active payment subscriptions for. Let's begin by generating these models.

Generating the User model:

The User model is used for authentication. Both readers and authors are represented in the database as Users.

We store the stripe_customer_id for readers. Well use the Stripe API to create customer objects for all users so that we can keep track of all subscriptions and invoices that are related to a given reader.

We store the stripe_account_id for authors. This represents the ID of the authors Stripe Account and enables us to route payments from readers to the author. We also store charges_enabled and payouts_enabled flags to know when the account is fully onboarded and can successfully receive money.

rails generate model User name:string email:string stripe_customer_id:string stripe_account_id:string charges_enabled:boolean payouts_enabled:boolean

Generating the Newsletter model:

Newsletters have a foreign key relationship back to the ID of the author in the Users table.

rails generate model Newsletter user:references title:string

Generating the Newsletter Issue model:

Newsletter Issues are related to the newsletter they are about and to start, well simple with a title and block of text for content. The published_at datetime enables us to schedule issues to be published in the future.

rails generate model NewsletterIssue newsletter:references subject:string content:text published_at:datetime

Generating the Subscription model:

When a reader subscribes to a newsletter for the first time, well send them through a payment flow using Stripe Checkout to collect their payment details and start a Stripe Subscription that collects recurring payments. Well store that stripe_subscription_id in the database so that we can check the Stripe API to know whether payment is active.

rails generate model Subscription user:references newsletter:references stripe_subscription_id:string status:string

Run the database migrations:

rails db:migrate

Now, let's set up the relationships between these models:

In app/models/user.rb:

class User < ApplicationRecord  has_many :newsletters  has_many :subscriptionsend

In app/models/newsletter.rb:

class Newsletter < ApplicationRecord  belongs_to :user  has_many :newsletter_issuesend

In app/models/newsletter_issue.rb:

class NewsletterIssue < ApplicationRecord  belongs_to :newsletterend

In app/models/subscription.rb:

class Subscription < ApplicationRecord  belongs_to :user  belongs_to :newsletterend

With these models in place, we can now represent authors, newsletters and their issues, and reader subscriptions in our database. In the next steps, we'll implement the Stripe Connect Onboarding logic.

Set up Stripe

Use the stripe-ruby SDK to interact with the Stripe API.

bundle add stripe

Retrieve API keys from dashboard.stripe.com and set those into our Rails credentials.

EDITOR=vi rails credentials:edit

Insert the keys like so:

stripe:  secret_key: sk_test_51EceeUCZ6qs...  publishable_key: pk_test_vAZ3gh1Lc...

Add an initializer to config/initializers/stripe.rb in order to set the platform level API key. Note that each authors Stripe account will have its own API keys, but with Stripe Connect, we never need the connected accounts keys. Instead we authenticate requests for connected accounts with the combination of our platform level API key and the connected accounts ID. See here for more details.

Stripe.api_key = Rails.application.credentials.dig(:stripe, :secret_key)

Now were ready to start making API calls to Stripe from Ruby. Before we start using the Stripe API, lets get authentication up and running.

Set up authentication

For this use-case, users need a way to authenticate into the application. Since were using Ruby on Rails, well use devise authentication for authors.

Well install the devise gem, run the install scripts and generate the routes and migration for Authors to be database authenticatable.

bundle add deviserails generate devise:installrails g devise:viewsrails g devise Author

Again, we migrate the database.

rails db:migrate

Running bin/dev fires up the server so we can test our registration flow at localhost:3000/authors/sign_up.

Were presented this unstyled login view that well clean up later.

Now that users can register for the application, well want to onboard them to Stripe Connect so that we can start interacting with the Stripe API on their behalf.

Set up Connect onboarding

Connect supports 3 different account types: Standard, Express, and Custom. Since authors might not have experience handling refunds, and chargebacks in this use case, it makes sense to provide them an integration where they have access to the simpler Stripe dashboard with a Express-type connected account. Learn more about the tradeoffs between different account types here. Side note: were hoping to remove the concept of an account type so stay tuned for a less confusing approach to differentiating Connect functionality for your users.

For onboarding, well have a page where well either show the account details for the connected account, or a button for the user to create a new account and go through the onboarding process. These functions will be handled by a new StripeAccountsController.

rails g controller StripeAccounts show

Well add singular resource routes for /stripe_account by updating config/routes.rb.

Rails.application.routes.draw do  resource :stripe_account  devise_for :usersend

Next, well add the before action macro from devise that requires an authenticated author to access these routes.

class StripeAccountsController < ApplicationController  before_action :authenticate_author!end

The view for the show route is very simple for now.

<% if current_user.stripe_account_id.present? %>  <%= current_user.stripe_account.to_json %><% else %>  <p>No Stripe account found</p>  <%= button_to "Create a Stripe Account", stripe_account_path, method: :post, data: { turbo: false } %><% end %>

When a user clicks on Create a Stripe Account, well first make an API call to Stripe to create a new Express account, then well update the database with the accounts ID and finally redirect through the account onboarding flow with an Account Link.

The goal here is to minimize the amount of information the author needs to re-enter. For instance, we already have the authors email address, so we can prefill that at the account and individual level. Well also assume that all authors are individuals rather than businesses. We can prefill the business profiles mcc (merchant category code) as digital goods so that each author isnt required to dig through the list of service types to find digital goods.

  def create    account = Stripe::Account.create(      type: 'standard',      email: current_user.email,      business_type: 'individual',      business_profile: {        mcc: '5818',      },            individual: {        email: current_user.email,      },      metadata: {        author_id: current_user.id,      }    )    current_user.update(stripe_account_id: account.id)    account_link = Stripe::AccountLink.create(      account: account.id,      refresh_url: stripe_account_url,      return_url: stripe_account_url,      type: 'account_onboarding'    )    redirect_to account_link.url, status: :see_other, allow_other_host: true  end

When events related to Stripe accounts happen in Stripe, the application can be notified using webhooks. We need to listen for the account.updated webhook event type so that we know when an account has successfully completed onboarding.

Set up webhooks

We need a controller to handle the incoming POST requests from Stripe.

rails g controller Webhooks

Well add a simple route of /webhooks for handling POST requests.

resources :webhooks, only: [:create]

Since the requests come from Stripe, we cannot verify any CSRF token, so we skip that check at the top of the controller.

class WebhooksController < ApplicationController  skip_before_action :verify_authenticity_token

Then well add a create method for handling post requests from Stripe to deserialize the event body and switch based on the type of event notification.

  def create    payload = request.body.read    event = nil    begin      event = Stripe::Event.construct_from(        JSON.parse(payload, symbolize_names: true)      )    rescue JSON::ParserError => e      # Invalid payload      puts "  Webhook error while parsing basic request. #{e.message})"      render json: { message: 'failed' }, status: 400      return    end    case event.type    when 'account.updated'      account = event.data.object # contains a Stripe::Account      # TODO: Handle account updates    else      puts "Unhandled event type: #{event.type}"    end    render json: { message: 'success' }  end

Each time we receive the account.updated event we want to update our local Authors flags for whether charges and payouts are enabled.

    when 'account.updated'      account = event.data.object # contains a Stripe::Account      author = User.find_by(stripe_account_id: account.id)      author.update(        charges_enabled: account.charges_enabled,        payouts_enabled: account.payouts_enabled      )

To build and test webhooks locally, well use the Stripe CLI. The listen command enables us to forward both account and connect webhook events. Account a.k.a. direct events are those events that fire on our account, connect events are those that happen on connected accounts.

Start the listener with:

stripe listen --forward-to localhost:3000/webhooks --forward-connect-to localhost:3000/webhooks

As a shortcut with Rails, I add a new process to Procfile.dev so that this starts each time we run bin/dev. My Procfile.dev looks like this:

web: bin/rails server -p 3000js: yarn build --watchcss: yarn build:css --watchstripe: stripe listen --forward-to localhost:3000/webhooks --forward-connect-to localhost:3000/webhooks

Now we can go through the onboarding flow and enter test details. Use the magic test strings from this doc to ensure a verified test account. Note youll also need to verify your email in order to activate the account, so use a real email address that you have access to when creating the new connect account.

If all went to plan, you see the JSON for the Stripe Account in the browser, your Author has a Stripe Account ID, charges enabled is true, and payouts enabled is true in the database.


Original Link: https://dev.to/stripe/stripe-connect-onboarding-with-ruby-on-rails-32i4

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To