Stripe Elements Basics

Stripe Elements is a pre-built UI component provided by Stripe to securely collect sensitive credit card details. The stripe gem version used in this article is 2.0.1. We will use Rails 5 and Ruby 2.3.3. The subscriptions controller prints the params to the log file.

class SubscriptionsController < ApplicationController
  def new
  end

  def create
    logger.info "*" * 80
    logger.info params
    logger.info "*" * 80
  end
end

The application layout file has reference to the Stripe.js version 3.

<!DOCTYPE html>
<html>
  <head>
    <title>Strip</title>
    <%= csrf_meta_tags %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
    <script src="https://js.stripe.com/v3/"></script>

    <%= tag :meta, :name => "stripe-key", :content => STRIPE_PUBLIC_KEY %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>

The config/initializers/stripe.rb is as shown below.

Rails.configuration.stripe = {
  publishable_key: ENV['STRIPE_PUBLISHABLE_KEY'],
  secret_key:      ENV['STRIPE_SECRET_KEY']
}

Stripe.api_key = Rails.configuration.stripe[:secret_key]
STRIPE_PUBLIC_KEY = Rails.configuration.stripe[:publishable_key]

You must set the environment variables for the Stripe credentials. The payment form is as shown below in app/views/subscriptions/new.html.erb.

<form action="/subscriptions/create" method="post" id="payment-form">
    <%= hidden_field_tag :authenticity_token, form_authenticity_token -%>
  <div class="form-row">
    <label for="card-element">
      Credit or debit card
    </label>
    <div id="card-element">
      <!-- a Stripe Element will be inserted here. -->
    </div>

    <!-- Used to display form errors -->
    <div id="card-errors"></div>
  </div>

  <button>Submit Payment</button>
</form> 
    <script type="text/javascript">
    // Create a Stripe client

    var stripe = Stripe($('meta[name="stripe-key"]').attr('content'));

    // Create an instance of Elements
    var elements = stripe.elements();

    // Custom styling can be passed to options when creating an Element.
    // (Note that this demo uses a wider set of styles than the guide below.)
    var style = {
      base: {
        color: '#32325d',
        lineHeight: '24px',
        fontFamily: 'Helvetica Neue',
        fontSmoothing: 'antialiased',
        fontSize: '16px',
        '::placeholder': {
          color: '#aab7c4'
        }
      },
      invalid: {
        color: '#fa755a',
        iconColor: '#fa755a'
      }
    };

    // Create an instance of the card Element
    var card = elements.create('card', {style: style});

    // Add an instance of the card Element into the `card-element` <div>
    card.mount('#card-element');

    // Handle real-time validation errors from the card Element.
    card.addEventListener('change', function(event) {
      const displayError = document.getElementById('card-errors');
      if (event.error) {
        displayError.textContent = event.error.message;
      } else {
        displayError.textContent = '';
      }
    });

    // Handle form submission
    var form = document.getElementById('payment-form');
    form.addEventListener('submit', function(event) {
      event.preventDefault();

      stripe.createToken(card).then(function(result) {
        if (result.error) {
          // Inform the user if there was an error
          var errorElement = document.getElementById('card-errors');
          errorElement.textContent = result.error.message;
          console.log(result.error.message);
        } else {
          // Send the token to your server
            alert(JSON.stringify(result.token));
            console.log(JSON.stringify(result.token));

      // Insert the token ID into the form so it gets submitted to the server

      var form = document.getElementById('payment-form');
      var hiddenInput = document.createElement('input');
      hiddenInput.setAttribute('type', 'hidden');
      hiddenInput.setAttribute('name', 'stripeToken');
      hiddenInput.setAttribute('value', result.token.id);
      form.appendChild(hiddenInput);
      alert(result.token.id);
      alert('submitting form');
      // Submit the form
      form.submit();

        }
      });
    });
    </script>   

The credit card details is sent to Stripe servers and we get stripe token that represents the credit card, this token is submitted to our server. This token can be used to subscribe a customer to a given plan. The css used for the payment form in the application.css is shown below.

.StripeElement {
  background-color: white;
  padding: 8px 12px;
  border-radius: 4px;
  border: 1px solid transparent;
  box-shadow: 0 1px 3px 0 #e6ebf1;
  -webkit-transition: box-shadow 150ms ease;
  transition: box-shadow 150ms ease;
}

.StripeElement--focus {
  box-shadow: 0 1px 3px 0 #cfd7df;
}

.StripeElement--invalid {
  border-color: #fa755a;
}

.StripeElement--webkit-autofill {
  background-color: #fefde5 !important;
}

Trouble Shooting Tips

Make sure you add the javascript after the form, otherwise you will get the following Integration error.

Stripe Elements

You can view the logs in your Stripe dashboard by going to https://dashboard.stripe.com/logs. This will show you whether your request was received by the Stripe servers.

Stripe Logs

You can download the source code for this article from Stripe Rails 5.


Related Articles

Watch this Article as Screencast

You can watch this as a screencast Stripe Elements Basics


Create your own user feedback survey