Skip to content

Commit

Permalink
selfstarter now works with stripe :)
Browse files Browse the repository at this point in the history
  • Loading branch information
paterson committed Nov 23, 2013
1 parent 8987286 commit d573a83
Show file tree
Hide file tree
Showing 13 changed files with 102 additions and 99 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ ruby '2.0.0'

gem 'rails', '4.0.0'
gem 'json', '~> 1.7.7'
gem 'stripe'

group :development do
gem 'sqlite3'
Expand Down
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ GEM
activesupport (>= 3.0)
sprockets (~> 2.8)
sqlite3 (1.3.8)
stripe (1.8.8)
multi_json (>= 1.0.4, < 2)
rest-client (~> 1.4)
thin (1.6.1)
daemons (>= 1.0.9)
eventmachine (>= 1.0.0)
Expand Down Expand Up @@ -156,5 +159,6 @@ DEPENDENCIES
sass-rails (~> 4.0.0)
shoulda
sqlite3
stripe
thin
uglifier (>= 1.0.3)
1 change: 1 addition & 0 deletions app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@
//= require jquery.textchange
//= require preorder
//= require_tree .
//= require checkout
24 changes: 24 additions & 0 deletions app/assets/javascripts/checkout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
$(document).ready(function () {
$('#checkout').submit(function (e) {
$('#stripe_errors').hide()
e.preventDefault();
var _this = this
Stripe.card.createToken({
number: $('#card_number').val().replace(/ /g, ''),
exp_month: $('#expires').val().split('/')[0],
exp_year: $('#expires').val().split('/')[1],
cvc: $('#cvv').val()
}, function (error, result) {
if (error == 200) {
$('#stripe_token').val(result.id);
console.log('stripe token added')
_this.submit();
}
else {
//error
$('#stripe_errors').show()
return false;
}
});
});
});
14 changes: 10 additions & 4 deletions app/assets/stylesheets/checkout.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
}
#checkout
{
#email
input
{
padding: 15px;
padding: 10px;
border-radius: 10px;
border: 1px solid #CCC;
width: 350px;
Expand All @@ -26,13 +26,19 @@
{
border: 1px solid orange;
}
#amazon_button
#stripe_button
{
margin-top: 5px;
padding: 15px;
border: none;
width: 350px;
}
}
#stripe_errors
{
display: none;
color: red;
}
}

.main_content.payment_options
Expand Down Expand Up @@ -64,7 +70,7 @@
}
}
}
#amazon_button
#stripe_button
{
display: inline !important;
}
Expand Down
60 changes: 27 additions & 33 deletions app/controllers/preorder_controller.rb
Original file line number Diff line number Diff line change
@@ -1,48 +1,42 @@
class PreorderController < ApplicationController
skip_before_action :verify_authenticity_token, :only => :ipn

require "stripe"
Stripe.api_key = Settings.stripe_api_key

def index
end

def checkout
end

def prefill
def order
@user = User.find_or_create_by(:email => params[:email])

if Settings.use_payment_options
payment_option_id = params['payment_option']
raise Exception.new("No payment option was selected") if payment_option_id.nil?
payment_option = PaymentOption.find(payment_option_id)
price = payment_option.amount
else
price = Settings.price
end

@order = Order.prefill!(:name => Settings.product_name, :price => price, :user_id => @user.id, :payment_option => payment_option)

# This is where all the magic happens. We create a multi-use token with Amazon, letting us charge the user's Amazon account
# Then, if they confirm the payment, Amazon POSTs us their shipping details and phone number
# From there, we save it, and voila, we got ourselves a preorder!
port = Rails.env.production? ? "" : ":3000"
callback_url = "#{request.scheme}://#{request.host}#{port}/preorder/postfill"
redirect_to AmazonFlexPay.multi_use_pipeline(@order.uuid, callback_url,
:transaction_amount => price,
:global_amount_limit => price + Settings.charge_limit,
:collect_shipping_address => "True",
:payment_reason => Settings.payment_description)
client = Stripe::Customer.create(
:email => params[:email]
)
card = client.cards.create(:card => params[:stripe_token])
client.default_card = card.id

charge = Stripe::Charge.create(
:amount => self.amount,
:currency => Settings.currency,
:customer => client.id,
:description => Settings.payment_description
)

raise Exception.new("Couldn't charge Card. Please try again") unless charge.paid
options = {
:user_id => @user.id,
:price => Settings.price,
:name => Settings.product_name
}
@order = Order.fill!(options)
redirect_to :action => :share, :uuid => @order.uuid
end

def postfill
unless params[:callerReference].blank?
@order = Order.postfill!(params)
end
# "A" means the user cancelled the preorder before clicking "Confirm" on Amazon Payments.
if params['status'] != 'A' && @order.present?
redirect_to :action => :share, :uuid => @order.uuid
else
redirect_to root_url
end
def amount
(Settings.price * 100).to_i
end

def share
Expand Down
31 changes: 5 additions & 26 deletions app/models/order.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,21 @@ class Order < ActiveRecord::Base
before_validation :generate_uuid!, :on => :create
belongs_to :user
belongs_to :payment_option
scope :completed, -> { where("token != ? OR token != ?", "", nil) }
self.primary_key = 'uuid'

# This is where we create our Caller Reference for Amazon Payments, and prefill some other information.
def self.prefill!(options = {})
# note - completed scope removed, because any entries in Order *have* to be completed ones.

def self.fill!(options = {})
@order = Order.new
@order.name = options[:name]
@order.user_id = options[:user_id]
@order.price = options[:price]
@order.number = Order.next_order_number
@order.payment_option = options[:payment_option] if !options[:payment_option].nil?
@order.save!

@order
end

# After authenticating with Amazon, we get the rest of the details
def self.postfill!(options = {})
@order = Order.find_by!(:uuid => options[:callerReference])
@order.token = options[:tokenID]
if @order.token.present?
@order.address_one = options[:addressLine1]
@order.address_two = options[:addressLine2]
@order.city = options[:city]
@order.state = options[:state]
@order.status = options[:status]
@order.zip = options[:zip]
@order.phone = options[:phoneNumber]
@order.country = options[:country]
@order.expiration = Date.parse(options[:expiry])
@order.save!

@order
end
end

def self.next_order_number
if Order.count > 0
Order.order("number DESC").limit(1).first.number.to_i + 1
Expand All @@ -64,14 +43,14 @@ def self.percent

# See what it looks like when you have some backers! Drop in a number instead of Order.count
def self.backers
Order.completed.count
Order.count
end

def self.revenue
if Settings.use_payment_options
PaymentOption.joins(:orders).where("token != ? OR token != ?", "", nil).pluck('sum(amount)')[0].to_f
else
Order.completed.sum(:price).to_f
Order.sum(:price).to_f
end
end

Expand Down
5 changes: 4 additions & 1 deletion app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title><%= Settings.product_name %></title>
<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag "application" %>
<%= javascript_include_tag "https://js.stripe.com/v1/", "application" %>
<script>
Stripe.setPublishableKey("<%= Settings.stripe_public_key %>")
</script>
</head>
<!--[if lt IE 9 ]><body class="lt-ie9"><![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--> <body><!--<![endif]-->
Expand Down
24 changes: 13 additions & 11 deletions app/views/preorder/checkout.html.erb
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
<div class="gray_background">
<div class="wrapper clearfix">
<div class="main_content <%= "payment_options" if Settings.use_payment_options %>">
<h3>Check out</h3>
<h3>Preorder</h3>
<p>
All of your payment information will be secured and stored with Amazon Payments. If you don't have an Amazon account, simply select "I'm a new Customer" on the next page.
All of your payment information will be secured and stored with Stripe.
<br />
<br />
<% if Settings.use_payment_options %>
Select a payment option and enter your email address below.
<% else %>
Enter your email address below.
<% end %>
Please Enter your details below.

</p>
<%= form_tag "/preorder/prefill", :id => "checkout" do %>
<%= form_tag "/preorder/order", :id => "checkout" do %>
<%= render 'preorder/payment_options' %>
<div class="checkout_controls">
<div class="checkout_controls_wrapper">
<div class="checkout_controls_inner">
<%= email_field_tag "email", nil, :placeholder => "Email address", :required => "required", :id => "email" %>
<%= hidden_field_tag "preorder", true %>
<%= hidden_field_tag "quantity", params[:quantity] %>
<%= submit_tag "Checkout", :class => "blue_button disabled", :id => "amazon_button" %>
<%= text_field_tag "card_number", nil, :placeholder => "Card Number", :required => "required", :id => "card_number" %>
<%= text_field_tag "cvv", nil, :placeholder => "CVV", :required => "required", :id => "cvv" %>
<%= text_field_tag "expires", nil, :placeholder => "Expires mm/yyyy", :required => "required", :id => "expires" %>
<%= hidden_field_tag :stripe_token %>
<%= submit_tag "Order!", :class => "blue_button", :id => "stripe_button" %>
</div>
</div>
</div>
<% end %>
<br />
<div id="stripe_errors">
Something went wrong, please check all your details are correct
</div>
</div>
<%= render 'preorder/checkout/sidebar' %>
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/views/preorder/homepage/_middle_reserve.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="big_wrapper">
<div class="wrapper center" id="middle_reserve">
<h2><%= Settings.ships %></h2>
<a href="/preorder/checkout" class="blue_button reserve"><%= Settings.middle_reserve_text %></a>
<a href="/preorder/order" class="blue_button reserve"><%= Settings.middle_reserve_text %></a>
</div>
</div>
2 changes: 1 addition & 1 deletion app/views/preorder/homepage/_stats.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@

<div id="reserve_container">
<p id="ship_date"><%= Settings.ships %></p>
<a href="/preorder/checkout" class="blue_button reserve"><%= Settings.call_to_action %></a>
<a href="/preorder/order" class="blue_button reserve"><%= Settings.call_to_action %></a>
<p id="price"><%= Settings.price_human %></p>
<p><%= Settings.dont_give_them_a_reason_to_say_no %></p>
<%= like_button %>
Expand Down
12 changes: 6 additions & 6 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
Selfstarter::Application.routes.draw do
root :to => 'preorder#index'
match '/preorder' => 'preorder#index', :via => [:get,:post]
get 'preorder/checkout'
match '/preorder/share/:uuid' => 'preorder#share', :via => :get
match '/preorder/ipn' => 'preorder#ipn', :via => :post
match '/preorder/prefill' => 'preorder#prefill', :via => [:get,:post]
match '/preorder/postfill' => 'preorder#postfill', :via => [:get,:post]
match '/preorder' => 'preorder#index', :via => [:get,:post]
get 'preorder/order' => 'preorder#checkout'
post 'preorder/order' => 'preorder#order'

match '/preorder/share/:uuid' => 'preorder#share', :via => :get
match '/preorder/ipn' => 'preorder#ipn', :via => :post
end
21 changes: 5 additions & 16 deletions config/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,13 @@ video_embed_url: "https://www.youtube.com/v/D1L3o88GKew"
# NOTE: this only works for youtube video at the moment. If its not for youtube, then just leave this property blank
use_video_placeholder: true

# Amazon settings -- you'll need an Amazon Payments account, sign up here --> http://bit.ly/SGksTv
# Stripe stuff. Stripe.com

# To find your access key and secret key, head over to here --> http://bit.ly/R4I4ky (Follow that guide in the Seller Central page)
amazon_access_key: "YOUR_AMAZON_ACCESS_KEY"
amazon_secret_key: "YOUR_AMAZON_SECRET_KEY"
stripe_api_key: "YOUR_STRIPE_API_KEY"
stripe_public_key: "YOUR_STRIPE_PUBLIC_KEY"
currency: "usd" # usd, eur etc
price: 19.95

# if use_payment_options is set to true, then a set of radio buttons will be displayed with various payment options.
# There is a PaymentOption model for storing info about payment options. To set up your payment options you should
# put code in seeds.rb, then run rake db:seed
use_payment_options: false

payment_description: "You really should change this text because people will see it on Amazon's order page!!!!!"

# Amazon limits how much we can charge people with their Multi-Use tokens.
# You probably should add some leeway to account for international shipping
# this value will be added to the price to create a charge limit
charge_limit: 25.00
payment_description: "You really should change this text because people will see it on their list of transactions!"

# Stats settings

Expand Down

2 comments on commit d573a83

@paterson
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • URL structure is different now. I think it's more logical.
  • Removed the whole payment_option thing (for now).

@thiagocifani
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey man, I found this branch from the original one. What do you think about move all this business logic to some PORO. Maybe we could build a public api from a interface to make available some basic methods to help with another payment gateways. You can follow my last commit.

apigy#83

Please sign in to comment.