Handling Identity Verification Notifications for Custom accounts

    Create a webhook built on the Sinatra framework to notify Custom accounts when identity verification information is needed.

    Stripe makes use of webhooks to notify you about events that happen in your account and in Stripe accounts that are connected to yours. You can leverage webhooks to do all sorts of cool things, like notifying your customer when a recurring payment fails, adding invoice items to an invoice before it’s paid, or sending custom receipts.

    You can create a webhook script that is written in Ruby and the Sinatra framework. This script listens for the account.updated event that occurs when one of your connected accounts is updated. When Stripe indicates that additional information is required, the webhook script sends an email to the connected account owner a link to request they update their information. This event is useful for many reasons, though the script within this recipe focuses on when identity verification is needed.

    You can find the full source used in this recipe on GitHub.

    Prerequisites

    This recipe makes use of Mailgun to notify your connected users of the identity verification information needed. You’ll need to create a free Mailgun account to use this example, though you could alternatively send email directly from your server or use another mailing service if you prefer. You also need:

    • A Stripe account with Connect enabled, in a country that supports Custom accounts
    • A Ruby >= 1.9.3 environment

    Setting up the framework

    To start, open a terminal window and create a directory for our webhook, then move into that directory:

    mkdir webhook-handler && cd webhook-handler

    Next, create the files that you’ll use for your webhook handler:

    touch webhook.rb config.ru Gemfile

    The webhook.rb file does all the work, listening for POST requests from Stripe and taking actions depending on the event type. Open the file in your text editor and create an outline for your webhook script:

    require 'sinatra'
    require 'stripe'
    require 'mailgun'
    
    # Responds to webhooks sent by Stripe
    post '/webhook' do
    
    end

    Next, edit the config.ru file and add the following lines:

    require './webhook-handler'
    run Sinatra::Application

    Then add the Ruby gems you’ll be using to the Gemfile:

    source 'https://rubygems.org'
    gem 'sinatra'
    gem 'stripe'
    gem 'mailgun-ruby'

    Finally, run bundler to install the gems for your application.

    bundle install

    Creating the webhook handler

    The framework for the webhook has been created, but it’s not very useful yet. Get your webhook handler prepared by modifying your webhook.rb file as shown below:

    require 'sinatra'
    require 'stripe'
    require 'mailgun'
    
    set :secret_key, ENV['STRIPE_KEY']
    Stripe.api_key = settings.secret_key
    
    set :mailgun_key, ENV['MAILGUN_KEY']
    mg_client = Mailgun::Client.new settings.mailgun_key
    
    # Responds to webhooks sent by Stripe
    post "/webhook" do
      # Retrieve the request's body and parse it as JSON
      event_json = JSON.parse(request.body.read)
    
      # Retrieve the event from Stripe
      event = Stripe::Event.retrieve({ id: event_json['id'] },
      { stripe_account: event_json['user_id'] })
    
      # Only respond to `account.updated` events
      if event.type.eql?('account.updated')
        # Determine if identity verification is needed
    
      else
        # Nothing to see here, return a 200
        status 200
      end
    end

    To clarify what’s happening here, you’re first reading the environmental variables for your Stripe secret key and Mailgun key. You should keep these in environmental variables where they’re out of your code base.

    The webhook request is then parsed as JSON to find the ID of that event. Using this ID, you make an API call to retrieve the event again from Stripe; though this isn’t a requirement, it’s very much recommended to verify the authenticity of the event. Note that you also pass in the Stripe-account header to authenticate as the connected account (where the account.updated event occurred).

    Finally, the last block inspects the event type. If it’s an account.updated event type, then the script takes action. Otherwise, it just returns an HTTP 200 status to Stripe to indicate that everything is hunky dory.

    For the purpose of this webhook script, there are only a few things to be concerned with:

    1. Finding out when we need more information about a connected account.
    2. Determining what that information is and notifying the connected user about it.

    To do this, the part of the event payload that’s important is the verification hash and the fields_needed list specifically. You can read more about this in the identity verification documentation, but to obtain this from the event you retrieved you’ll add the below to your webhook.rb file:

    ...
    # Determine if identity verification is needed
    unless event.data.object.verification.fields_needed.nil?
      # Send a notification to the connected account
    
    end
    ...

    This line checks to see if any fields are needed; if so, you’ll want to contact the connected account to let them know.

    Emailing the connected account owner

    Use Mailgun to email the account owner by adding the below code to the same webhook.rb file:

    ...
    # Send a notification to the connected account
      message_params = {
        from: 'you@example.com', # Your domain or Mailgun Sandbox domain
        to: event.data.object.email, # Email address of the connected account
        subject: 'Please update your account information',
        text: 'Hi there! We need some additional information about your account
        to continue sending you payouts. You can get this to us by following
        the link here: https://example.com/account/submit_info'
       }
       result = mg_client.send_message('example.com', message_params).to_h!
    ...

    Note: You’ll want to be sure to update all of the example.com pointers as necessary to reflect your own site or the settings you find in your Mailgun configuration.

    To think through each step a bit:

    1. When Stripe sends an event to your webhook endpoint at example.com/webhook, the webhook script first retrieves the event from Stripe to validate its authenticity.

    2. The script checks to determine if the event type is account.updated. If not, it returns a 200. If it is, it looks for any fields_needed in the verification hash.

    3. If there are fields found there, Mailgun sends an email to the owner of the connected account indicating that additional information is needed along with a link to your site. Hooray!

    Now that your webhook is ready to go, you’ll be able to start the server by setting the environmental variables. You can test this locally with the following command:

    SECRET_KEY=sk_test_BQokikJOvBiI2HlWgH4olfQ2 MAILGUN_KEY=mg_key ruby webhook.rb

    Testing

    The webhook endpoint needs to be available publicly on the web for Stripe to communicate with it. You can deploy this webhook handler to a server or test this locally on your computer using a service like Ngrok.

    Once your webhook endpoint is accessible on the internet, you’ll want to configure this endpoint in the Dashboard. Select Connect as the endpoint type, since this event occurs on the connected account.

    To test account verification stages, use the Connect verification testing guide. This triggers verification stages for a connected test account, sends events to your webhook handler. You can learn more about working with Custom accounts in the Connect documentation.

    Extending this recipe

    • This webhook script can only listen for account information that’s needed, and send notifications. You also need to provide a form on your website or app where your connected users can update this information. You can learn more about updating accounts in the Connect documentation as well.

    • The verification hash may contain a due_by timestamp representing the date that this information needs to be submitted by. Payouts are typically disabled if the information is provided by that date, so you may also want to communicate this with your connected account users. You can read more on this in the updating accounts section of the Connect documentation.

    • The email doesn’t specify which fields are needed. You could include this when notifying the connected account owner by inspecting the fields_needed property (event.data.object.verification.fields_needed).

    • You can examine the charges_enabled and transfers_enabled properties of this event to understand the account’s current capabilities.