Codestudio Codestudio - 5 months ago 15
Ruby Question

Stripe Payment Amount

I have integrated stripe payments into my application. It is configured in a way so that the user can input the price for an item they want to sell as a decimal on a pin model. When the price is inputed in the form it is displayed as a dollar amount in the view. However, when you select the buy now button for that item and the stripe payments modal pops-up it displays the price in cents (i.e. I input "10.0" and submit it so it displays "Price $: 10.0 but when I select buy now Stripe interprets it as cents and displays "Pay $.10" in the stripe payment modal.)

I thought about changing the input price to cents for users that way Stripe could interpret it better but that would result in a bad UI.

Is there any simple way to fix this so that the amount displayed is uniform for both the input and output?

app/views/pins/

<%= form_tag charges_path, id: 'chargesForm' do %>
<script src="https://checkout.stripe.com/checkout.js"></script>
<%= hidden_field_tag 'stripeToken' %>
<%= hidden_field_tag 'stripeEmail' %>
<button id="btn-buy" type="button" class="btn btn-success btn-lg btn-block"><span class="glyphicon glyphicon-heart"></span> Buy Now!</button>

<script>
var handler = StripeCheckout.configure({
key: '<%= Rails.configuration.stripe[:publishable_key] %>',
token: function(token, arg) {
document.getElementById("stripeToken").value = token.id;
document.getElementById("stripeEmail").value = token.email;
document.getElementById("chargesForm").submit();
}
});
document.getElementById('btn-buy').addEventListener('click', function(e) {
handler.open({
name: <%= @pin.manufacturer %>',
description: '<%= @pin.description %>',
amount: '<%= @pin.price %>'
});
e.preventDefault();
})
</script>
<% end %>


app/views/pins/index.html.erb

<div id="pins" class="transitions-enabled">
<% @pins.each do |pin| %>
<div class="box panel panel-default">
<div class="panel-body">
<%= link_to (image_tag pin.image.url(:medium)), pin %>
<p></p>
<strong>Manufacturer:</strong>
<%= pin.manufacturer %>
<p></p>
<strong>Price:</strong>
<%= pin.price %>
<p></p>
<strong>Description:</strong>
<%= pin.description %>
<% if pin.is_multi? %>
<strong>Quantity:</strong>
<%= pin.quantity %>
<% end %>
<p></p>


app/db/migrate

class AddPriceToPins < ActiveRecord::Migration
def change
add_column :pins, :price, :decimal
end
end


pin/controller

class PinsController < ApplicationController
before_action :set_pin, only: [:show, :edit, :update, :destroy, :bid]
before_action :correct_user, only: [:edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]

def index
@pins = Pin.all.order("created_at DESC").paginate(:page => params[:page], :per_page => 9)
end

def pin_params
params.require(:pin).permit(:description, :price, :image, :image2, :image3, :image4, :image5, :manufacturer, :model)
end
end

Answer

Stripe's API always expects you to pass amounts in the smallest currency unit. In USD it means passing the amount as cents.

You don't need to change your UI here, you simply need to change your code to pass the amount as cents when you call handler.open. Since you have the amount already in @pin.price you'll want to multiply it by 100 and round the value:

handler.open({
  name: '<%= @pin.manufacturer %>',
  description: '<%= @pin.description %>',
  amount: '<%= (@pin.price * 100).floor %>'
});