Skip to content

Instantly share code, notes, and snippets.

@dohoonk
Last active May 4, 2017 00:01
Show Gist options
  • Save dohoonk/7b0e683db72ccdb8b72e to your computer and use it in GitHub Desktop.
Save dohoonk/7b0e683db72ccdb8b72e to your computer and use it in GitHub Desktop.
Stripe

Create an account at Stripe 2. Account Setting/Api Key Grab your Api key here 3. Put your Key in secrets.yml as

stripe_secret_key: your key here
stripe_publishable_key: your key here

We are going to use Fundsy as an example We would need to implement a transaction table to store some of the information we will get from stripe For the simplicity we are going to use pledge table

Setting Up the database

bin/rails g migration add_stripe_fields_to_db
def chagnge
  add_column :pledges, :stripe_txn_id, :string
  
  add_column :users, stripe_customer_id, :string
  add_column :users, stripe_last_4, :string
  add_column :users, stripe_card_type, :string
  add_column :users, stripe_card_expiry, :string
end
bin/rake db:migrate

Look at pledges controller for more info Campaigns controller

@pledge = Pledge.new

After We will start by adding pledge to campaign show.html.erb

<h2>Pledge</h2>
<%= Simple_form_for [@campaign,@pledge] do |f| %>
  <%= f.input :amount %>
  <%= f.button :submit, :class " btn btn-priamry"%>
<%end%>

After a uesr makes a pledge let's send the user to payment page

Lets start by creating the controller

bin/rails g controller payments

In the case of transaction we need 3 information pledge/campaign/user

we can get user from current_user and campaign is accessible from pledge Thus, in your routes we are going to nest the payment route under pledges

resources :pledges, only: [] do
  resources :payments, only: [:new, :create]
end

In your Payments controller

before_action :authenticate_user

def new

end

def create

end

We need to create view files

view/payments

create new.html.erb

we now can create a path from campaign show cage to redirect the user to new payment page In your campaign controller

redirect_to new_pledge_payment_path(@pledge)

Now we need to build a ajax form 2 forms are needed

<%= form_tag "" do%>
  <div class="form-group"> 
    <%=label_tag :card_number%>
    <%=text_field_tag :card_number,"", class: "form-control"%>
  </div>
  <div class="form-group">
    <%=label_tag :cvc%>
    <%=text_field_tag :cvc,"", class: "form-control"%>
  </div>
<% end %>

Now we need drop down bar for exp date for the card

<%= select_month Date.today, {add_month_numbers: true}, {class: "form-control"}%>
<%= select_year Date.today, {start_year: Time.now.year, end_year: Time.now.year}, {class: "form-control"}%>
<%= submit_tag "make payment", class: "btn btn-primary"%>

Now we have the form we need to work with Ajax to receive the token from Stripe google stripe javascript api Place the code in application.html.erb

<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
#This code is needed to send our public key
<meta name="stripe-publishable-key" content="<%= Rails.application.secrets.stripe_publishable_key %>"

The next step is to sent a file in js to send the key

publishable key is a public key

Assets/payments.js

$(document).ready(function(){
  Stripe.setPublishableKey('pk_test_Ir3Dz5nsnoiWv8lrKIclpNvF');
});

in the js function we need to grab the public key so

$(document).ready(function(){
  var stripPublishableKey = $("meta[name='stripe-publishable-key']").attr("content");
  Stripe.setPublishableKey(stripPublishableKey);
});
var stripPublishableKey = $("meta[name='stripe-publishable-key']").attr("content");

this is the added line.

<div class="form-group">
    <%= label_tag :card_expiry %>
    <%= select_month Date.today, {add_month_numbers: true}, {class: "form-control", data: {stripe: "exp-month"}} %>
    <%= select_year Date.today, {start_year: Time.now.year, end_year: Time.now.year + 10}, {class: "form-control", data: {stripe: "exp-year"}} %>
</div>
<%= form_tag "", id: "payment-form" do %>

add this line

  $("#payment-form").on("submit", function(event){
    event.preventDefault();
    Stripe.card.createToken($("#payment-form"), stripeResponseHandler);
  });

your js file should look like this

$(document).ready(function(){
  var stripPublishableKey = $("meta[name='stripe-publishable-key']").attr("content");
  Stripe.setPublishableKey(stripPublishableKey);

  $("#payment-form").on("submit", function(event){
    event.preventDefault();
    Stripe.card.createToken($("#payment-form"), stripeResponseHandler);
  });

});

We need to add another line

$("#payment-form").find("input:submit").attr("disabled", true);
$(document).ready(function(){
  var stripPublishableKey = $("meta[name='stripe-publishable-key']").attr("content");
  Stripe.setPublishableKey(stripPublishableKey);

  $("#payment-form").on("submit", function(event){
    event.preventDefault();
    $("#payment-form").find("input:submit").attr("disabled", true);
    Stripe.card.createToken($("#payment-form"), stripeResponseHandler);
  });

});
 var stripeResponseHandler = function(status, data) {
    if(status === 200) {
      // successful => submit second form to the server
      var token = data.id;
    } else {
      var errMessage = data.error.message;
      $("#payment-form").find("input:submit").attr("disabled", false);
    }
  }
  var stripeResponseHandler = function(status, data) {
    if(status === 200) {
      // successful => submit second form to the server
      var token = data.id;
    } else {
      var errMessage = data.error.message;
      $("#stripe-error-message").html(errMessage);
      $("#payment-form").find("input:submit").attr("disabled", false);
    }
  }

To display error message

<div class="alert alert-danger" id="stripe-error-message"></div>
$(document).ready(function(){
  var stripPublishableKey = $("meta[name='stripe-publishable-key']").attr("content");
  Stripe.setPublishableKey(stripPublishableKey);

  $("#payment-form").on("submit", function(event){
    event.preventDefault();
    $("#stripe-error-message").addClass("hide");
    $("#payment-form").find("input:submit").attr("disabled", true);
    Stripe.card.createToken($("#payment-form"), stripeResponseHandler);
  });

  var stripeResponseHandler = function(status, data) {
    if(status === 200) {
      // successful => submit second form to the server
      var token = data.id;
      alert("Wohooo! " + token);
    } else {
      var errMessage = data.error.message;
      $("#stripe-error-message").html(errMessage);
      $("#stripe-error-message").removeClass("hide");
      $("#payment-form").find("input:submit").attr("disabled", false);
    }
  }

});

payment controller

class PaymentsController < ApplicationController
  before_action :authenticate_user

  def new
    @pledge = current_user.pledges.find params[:pledge_id]
  end

  def create
    render text: "Got the token #{params[:stripe_token]}"
  end

end
<h1>Make a Payment</h1>

<div class="alert alert-danger hide" id="stripe-error-message"></div>
<%= form_tag "", id: "payment-form" do %>
  <div class="form-group">
    <%= label_tag :card_number %>
    <%= text_field_tag :card_number, "", class: "form-control", data: {stripe: "number"} %>
  </div>
  <div class="form-group">
    <%= label_tag :cvc %>
    <%= text_field_tag :cvc, "", class: "form-control", data: {stripe: "cvc"} %>
  </div>
  <div class="form-group">
    <%= label_tag :card_expiry %>
    <%= select_month Date.today, {add_month_numbers: true}, {class: "form-control", data: {stripe: "exp-month"}} %>
    <%= select_year Date.today, {start_year: Time.now.year, end_year: Time.now.year + 10}, {class: "form-control", data: {stripe: "exp-year"}} %>
  </div>

  <%= submit_tag "Make the Payment", class: "btn btn-primary" %>
<% end %>

<%= form_tag pledge_payments_path(@pledge) do %>
  <%= hidden_field_tag :stripe_token %>
<% end %>

We need two types of code Stripe Javascript Stripe Ruby Rails

Stripe Ruby Gem gem 'stripe'

config/initializer/stripe.rb

stripe.api_key = Rails.application.secrets.stripe_secret_key

bin/rake db:rollback

class AddStripeFieldsToDb < ActiveRecord::Migration
  def change
    add_column :pledges, :stripe_txn_id, :string

    add_column :users, :stripe_customer_id, :string
    add_column :users, :stripe_last_4, :string
    add_column :users, :stripe_card_type, :string
    add_column :users, :stripe_card_expiry_month, :integer
    add_column :users, :stripe_card_expiry_year, :integer
  end
end
class PaymentsController < ApplicationController
  before_action :authenticate_user
  before_action :find_pledge

  def new
  end

  def create
    stripe_customer = Stripe::Customer.create(
                        description: "Customer for #{current_user.email}",
                        source: params[:stripe_token]
                      )

    current_user.stripe_customer_id       = stripe_customer.id
    current_user.stripe_last_4            = stripe_customer.sources.data[0].last4
    current_user.stripe_card_type         = stripe_customer.sources.data[0].brand
    current_user.stripe_card_expiry_month = stripe_customer.sources.data[0].exp_month
    current_user.stripe_card_expiry_year  = stripe_customer.sources.data[0].exp_year

    current_user.save

    charge = Stripe::Charge.create(
                amount:      @pledge.amount * 100,
                currency:    "cad",
                customer:    current_user.stripe_customer_id,
                description: "Charge for pledge id: #{@pledge.id}"
              )

    @pledge.stripe_txn_id = charge.id
    @pledge.save

    redirect_to @pledge.campaign, notice: "Thanks for completing the payment"
  end

  private

  def find_pledge
    @pledge = current_user.pledges.find params[:pledge_id]
  end

end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment