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 -

  1. Register Paypal sandbox account
  2. Paypal Merchant account api credentials i.e. login, password, signature, application_id
  3. 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>

Blog Logo

Sandip Ransing


Published

Image

Fun On Rails

Journal of a Web Developer #ruby #rails #JS

Back to Overview