read
Paypal standard website payment service allows online payment transactions for websites.
Before implementing payments inside rails app needs to have following things in place -
Register Paypal sandbox account
Paypal Merchant account api credentials i.e. login, password, signature, application_id
Paypal Buyer account creds to test payments
Bundle Install
<div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'># Gemfile
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'>gem ‘activemerchant </div></div></pre></div>
Gateway config
<div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'># config/gateway.yml
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'>development: &development
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'> mode: test
</div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'> login: rana_1317365002_biz_api1.gmail.com
</div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'> password: ‘1311235050’
</div></div><div data-line='6' class='code-highlight-row numbered'><div class='code-highlight-line'> signature: ACxcVrB3mFChvPIe8aDWQlLhAPN46oPBQCj7rJWPza6CDZmBURg.
</div></div><div data-line='7' class='code-highlight-row numbered'><div class='code-highlight-line'> application_id: APP-76y884485P519543T
</div></div><div data-line='8' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='9' class='code-highlight-row numbered'><div class='code-highlight-line'>production:
</div></div><div data-line='10' class='code-highlight-row numbered'><div class='code-highlight-line'> <<: *development
</div></div><div data-line='11' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='12' class='code-highlight-row numbered'><div class='code-highlight-line'>test:
</div></div><div data-line='13' class='code-highlight-row numbered'><div class='code-highlight-line'> <<: *development</div></div></pre></div>
New Payment Form
<div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'>= form_for @payment ||= Payment . new , :url => pay_bill_url , :html => { :id => :payForm } do | p |
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'> = p . text_field :amount
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'> = p . submit 'Pay' </div></div></pre></div>
Generate & Migrate Payment Model
<div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'>rails g model payment status:string amount:float transaction_number:string
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'>rake db:migrate </div></div></pre></div>
Payment Model
<div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'># app/models/payment.rb
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'>class Payment < ActiveRecord :: Base
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'> PROCESSING , FAILED , SUCCESS = 1 , 2 , 3
</div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='6' class='code-highlight-row numbered'><div class='code-highlight-line'> validates :amount , :presence => true , :numericality => { :greater_than => 0 }
</div></div><div data-line='7' class='code-highlight-row numbered'><div class='code-highlight-line'> def self . conf
</div></div><div data-line='8' class='code-highlight-row numbered'><div class='code-highlight-line'> @@gateway_conf ||= YAML . load_file ( Rails . root . join ( 'config/gateway.yml' ) . to_s ) [ Rails . env ]
</div></div><div data-line='9' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='10' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='11' class='code-highlight-row numbered'><div class='code-highlight-line'> ## Paypal
</div></div><div data-line='12' class='code-highlight-row numbered'><div class='code-highlight-line'> def setup_purchase ( options )
</div></div><div data-line='13' class='code-highlight-row numbered'><div class='code-highlight-line'> gateway . setup_purchase ( amount * 100 , options )
</div></div><div data-line='14' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='15' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='16' class='code-highlight-row numbered'><div class='code-highlight-line'> def redirect_url_for ( token )
</div></div><div data-line='17' class='code-highlight-row numbered'><div class='code-highlight-line'> gateway . redirect_url_for ( token )
</div></div><div data-line='18' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='19' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='20' class='code-highlight-row numbered'><div class='code-highlight-line'> def purchase ( options = {})
</div></div><div data-line='21' class='code-highlight-row numbered'><div class='code-highlight-line'> self . status = PROCESSING
</div></div><div data-line='22' class='code-highlight-row numbered'><div class='code-highlight-line'> #:ip => request.remote_ip,
</div></div><div data-line='23' class='code-highlight-row numbered'><div class='code-highlight-line'> #:payer_id => params[:payer_id],
</div></div><div data-line='24' class='code-highlight-row numbered'><div class='code-highlight-line'> #:token => params[:token]
</div></div><div data-line='25' class='code-highlight-row numbered'><div class='code-highlight-line'> response = gateway . purchase ( amt , options )
</div></div><div data-line='26' class='code-highlight-row numbered'><div class='code-highlight-line'> if response . success?
</div></div><div data-line='27' class='code-highlight-row numbered'><div class='code-highlight-line'> self . transaction_num = response . params [ 'transaction_id' ]
</div></div><div data-line='28' class='code-highlight-row numbered'><div class='code-highlight-line'> self . status = SUCCESS
</div></div><div data-line='29' class='code-highlight-row numbered'><div class='code-highlight-line'> else
</div></div><div data-line='30' class='code-highlight-row numbered'><div class='code-highlight-line'> self . status = FAILED
</div></div><div data-line='31' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='32' class='code-highlight-row numbered'><div class='code-highlight-line'> return self
</div></div><div data-line='33' class='code-highlight-row numbered'><div class='code-highlight-line'> rescue Exception => e
</div></div><div data-line='34' class='code-highlight-row numbered'><div class='code-highlight-line'> self . status = FAILED
</div></div><div data-line='35' class='code-highlight-row numbered'><div class='code-highlight-line'> return self
</div></div><div data-line='36' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='37' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='38' class='code-highlight-row numbered'><div class='code-highlight-line'> private
</div></div><div data-line='39' class='code-highlight-row numbered'><div class='code-highlight-line'> def gateway
</div></div><div data-line='40' class='code-highlight-row numbered'><div class='code-highlight-line'> ActiveMerchant :: Billing :: Base . mode = auth [ 'mode' ]. to_sym
</div></div><div data-line='41' class='code-highlight-row numbered'><div class='code-highlight-line'> ActiveMerchant :: Billing :: PaypalExpressGateway . new (
</div></div><div data-line='42' class='code-highlight-row numbered'><div class='code-highlight-line'> :login => auth [ 'login' ] , :password => auth [ 'password' ] ,
</div></div><div data-line='43' class='code-highlight-row numbered'><div class='code-highlight-line'> :signature => auth [ 'signature' ] )
</div></div><div data-line='44' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='45' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='46' class='code-highlight-row numbered'><div class='code-highlight-line'> def auth
</div></div><div data-line='47' class='code-highlight-row numbered'><div class='code-highlight-line'> self . class . conf
</div></div><div data-line='48' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='49' class='code-highlight-row numbered'><div class='code-highlight-line'>end </div></div></pre></div>
Billing routes
<div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'>## Callback URL
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'>match '/billing/paypal/:id/confirm' , :to => 'billing#paypal' , :as => :confirm_paypal
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'>## Create payment
</div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'>match '/billing' , :to => 'billing#create' , :as => :pay_bill
</div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'>## Request URL
</div></div><div data-line='6' class='code-highlight-row numbered'><div class='code-highlight-line'>match '/billing/paypal/:id' , :to => 'billing#checkout' , :as => :billing
</div></div><div data-line='7' class='code-highlight-row numbered'><div class='code-highlight-line'>match '/billing/thank_you/:id' , :to => 'billing#checkout' , :as => :billing_thank_you </div></div></pre></div>
Billing Controller
<div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'># app/controllers/billing_controller.rb
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'>class BillingController < ApplicationController
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'> before_filter :get_payment , :only => [ :checkout , :paypal , :thank_you ]
</div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'> def create
</div></div><div data-line='6' class='code-highlight-row numbered'><div class='code-highlight-line'> @payment = Payment . new params [ :payment ]
</div></div><div data-line='7' class='code-highlight-row numbered'><div class='code-highlight-line'> if @payment . save
</div></div><div data-line='8' class='code-highlight-row numbered'><div class='code-highlight-line'> ## Paypal Checkout page
</div></div><div data-line='9' class='code-highlight-row numbered'><div class='code-highlight-line'> redirect_to billing_url
</div></div><div data-line='10' class='code-highlight-row numbered'><div class='code-highlight-line'> else
</div></div><div data-line='11' class='code-highlight-row numbered'><div class='code-highlight-line'> render :action => :new
</div></div><div data-line='12' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='13' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='14' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='15' class='code-highlight-row numbered'><div class='code-highlight-line'> # ASSUMPTION # payment is valid i.e. amount is entered
</div></div><div data-line='16' class='code-highlight-row numbered'><div class='code-highlight-line'> def checkout
</div></div><div data-line='17' class='code-highlight-row numbered'><div class='code-highlight-line'> response = @payment . setup_purchase ( :return_url => confirm_paypal_url ( @payment ), :cancel_return_url => root_url )
</div></div><div data-line='18' class='code-highlight-row numbered'><div class='code-highlight-line'> redirect_to @payment . redirect_url_for ( response . token )
</div></div><div data-line='19' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='20' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='21' class='code-highlight-row numbered'><div class='code-highlight-line'> ## CALL BACK
</div></div><div data-line='22' class='code-highlight-row numbered'><div class='code-highlight-line'> def paypal
</div></div><div data-line='23' class='code-highlight-row numbered'><div class='code-highlight-line'> @payment = @payment . purchase ( :token => params [ :token ] , :payer_id => params [ :PayerID ] , :ip => request . remote_ip )
</div></div><div data-line='24' class='code-highlight-row numbered'><div class='code-highlight-line'> @payment . save
</div></div><div data-line='25' class='code-highlight-row numbered'><div class='code-highlight-line'> redirect_to thank_you_billing_url ( @order )
</div></div><div data-line='26' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='27' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='28' class='code-highlight-row numbered'><div class='code-highlight-line'> private
</div></div><div data-line='29' class='code-highlight-row numbered'><div class='code-highlight-line'> def get_payment
</div></div><div data-line='30' class='code-highlight-row numbered'><div class='code-highlight-line'> @payment = Payment . find_by_id ( params [ :id ] )
</div></div><div data-line='31' class='code-highlight-row numbered'><div class='code-highlight-line'> @payment && @payment . valid? || invalid_url
</div></div><div data-line='32' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='33' class='code-highlight-row numbered'><div class='code-highlight-line'>end </div></div></pre></div>
Views
<div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'># app/views/billing/thank_you.html.haml
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'>- if @payment . success?
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'> %p The transaction is successfully completed
</div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'>- else
</div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'> %p The transaction failed</div></div></pre></div>