From 00b09ac0fbf01be9cf63cd2ded550b3ebc9996ce Mon Sep 17 00:00:00 2001
From: Will Bradley
Date: Tue, 30 Apr 2013 02:42:53 -0700
Subject: [PATCH] Finished creating sample app
---
.gitignore | 2 +
app/controllers/payments_controller.rb | 229 ++++++++++++++++++++-----
app/models/payment.rb | 1 +
app/views/payments/new.html.erb | 21 ++-
app/views/payments/show.html.erb | 14 ++
config/initializers/paypal.rb | 2 +
config/paypal.yml | 24 ---
config/paypal.yml.dist | 24 +++
config/routes.rb | 1 +
db/schema.rb | 22 +++
10 files changed, 276 insertions(+), 64 deletions(-)
create mode 100644 config/initializers/paypal.rb
delete mode 100644 config/paypal.yml
create mode 100644 config/paypal.yml.dist
create mode 100644 db/schema.rb
diff --git a/.gitignore b/.gitignore
index eb3489a..ad989df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,5 @@
# Ignore all logfiles and tempfiles.
/log/*.log
/tmp
+
+paypal.yml # contains sensitive passwords
diff --git a/app/controllers/payments_controller.rb b/app/controllers/payments_controller.rb
index 995ff6a..b2c1247 100644
--- a/app/controllers/payments_controller.rb
+++ b/app/controllers/payments_controller.rb
@@ -15,9 +15,67 @@ class PaymentsController < ApplicationController
def show
@payment = Payment.find(params[:id])
+ paypal = Paypal.new(APP_CONFIG['username'],APP_CONFIG['password'],APP_CONFIG['signature'],APP_CONFIG['url'].to_sym)
+ @paypal_result = paypal.do_get_recurring_payments_profile_details(@payment.profile, {})
+
+ Rails.logger.debug "PROFILE DETAILS:"+@paypal_result.inspect
+
+ # {"PROFILEID"=>"I-C07L0WXLH25Y",
+ # "STATUS"=>"Active"
+ # "AUTOBILLOUTAMT"=>"NoAutoBill"
+ # "DESC"=>"_Why's Ruby Camping Adventures - Monthly Tips And Tricks For Camping Development"
+ # "MAXFAILEDPAYMENTS"=>"0"
+ # "SUBSCRIBERNAME"=>"Will Bradley"
+ # "PROFILESTARTDATE"=>"2013-05-01T07:00:00Z"
+ # "PROFILEREFERENCE"=>"INV20091122"
+ # "NEXTBILLINGDATE"=>"2013-05-01T10:00:00Z"
+ # "NUMCYCLESCOMPLETED"=>"0"
+ # "NUMCYCLESREMAINING"=>"11"
+ # "OUTSTANDINGBALANCE"=>"0.00"
+ # "FAILEDPAYMENTCOUNT"=>"0"
+ # "TRIALAMTPAID"=>"0.00"
+ # "REGULARAMTPAID"=>"0.00"
+ # "AGGREGATEAMT"=>"0.00"
+ # "AGGREGATEOPTIONALAMT"=>"0.00"
+ # "FINALPAYMENTDUEDATE"=>"2014-03-01T10:00:00Z"
+ # "TIMESTAMP"=>"2013-04-30T08:56:47Z"
+ # "CORRELATIONID"=>"e305cb3e7287c"
+ # "ACK"=>"Success"
+ # "VERSION"=>"74.0"
+ # "BUILD"=>"5650305"
+ # "SHIPTOSTREET"=>"1 Main St"
+ # "SHIPTOCITY"=>"San Jose"
+ # "SHIPTOSTATE"=>"CA"
+ # "SHIPTOZIP"=>"95131"
+ # "SHIPTOCOUNTRYCODE"=>"US"
+ # "SHIPTOCOUNTRY"=>"US"
+ # "SHIPTOCOUNTRYNAME"=>"United States"
+ # "SHIPADDRESSOWNER"=>"PayPal"
+ # "SHIPADDRESSSTATUS"=>"Unconfirmed"
+ # "BILLINGPERIOD"=>"Month"
+ # "BILLINGFREQUENCY"=>"1"
+ # "TOTALBILLINGCYCLES"=>"11"
+ # "CURRENCYCODE"=>"USD"
+ # "AMT"=>"5.00"
+ # "SHIPPINGAMT"=>"0.00"
+ # "TAXAMT"=>"0.00"
+ # "REGULARBILLINGPERIOD"=>"Month"
+ # "REGULARBILLINGFREQUENCY"=>"1"
+ # "REGULARTOTALBILLINGCYCLES"=>"11"
+ # "REGULARCURRENCYCODE"=>"USD"
+ # "REGULARAMT"=>"5.00"
+ # "REGULARSHIPPINGAMT"=>"0.00"
+ # "REGULARTAXAMT"=>"0.00"}
+
+
respond_to do |format|
- format.html # show.html.erb
- format.json { render json: @payment }
+ if @paypal_result['ACK'] == 'Success'
+ format.html # show.html.erb
+ format.json { render json: @payment }
+ else
+ format.html { redirect_to payments_url, notice: 'There was a problem contacting PayPal. This issue has been logged.' }
+ format.json { render json: @payment.errors, status: :unprocessable_entity }
+ end
end
end
@@ -26,58 +84,151 @@ class PaymentsController < ApplicationController
def new
@payment = Payment.new
+ paypal = Paypal.new(APP_CONFIG['username'],APP_CONFIG['password'],APP_CONFIG['signature'],APP_CONFIG['url'].to_sym)
+
+ subscription_request = {
+ "PAYMENTACTION" => "Sale",
+ "L_BILLINGTYPE0" => "RecurringPayments",
+ "DESC" => "_Why's Ruby Camping Adventures",
+ "L_BILLINGAGREEMENTDESCRIPTION0" => "_Why's Ruby Camping Adventures - Monthly Tips And Tricks For Camping Development"
+ }
+
+ response = paypal.set_express_checkout(
+ return_url='http://localhost:3000/payments/confirmed',
+ cancel_url='http://localhost:3000/payments/aborted',
+ amount='5.00',
+ currency='USD',
+ other_params=subscription_request)
+
+ Rails.logger.debug "SETEXPRESSCHECKOUT:"+response.inspect
+
+ @token = (response.ack == 'Success') ? response['TOKEN'] : ''
+
respond_to do |format|
- format.html # new.html.erb
- format.json { render json: @payment }
+ if response['ACK'] == 'Success'
+ format.html # new.html.erb
+ format.json { render json: @payment }
+ else
+ Rails.logger.warn "SETEXPRESSCHECKOUT ERROR:"+response.inspect
+ format.html { redirect_to payments_url, notice: 'There was a problem contacting PayPal. This issue has been logged.' }
+ format.json { render json: @payment.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ def confirmed
+ token = params[:token]
+
+ paypal = Paypal.new(APP_CONFIG['username'],APP_CONFIG['password'],APP_CONFIG['signature'],APP_CONFIG['url'].to_sym)
+
+ response = paypal.do_get_express_checkout_details(token)
+
+ error = false
+
+ if response['ACK'] != 'Success'
+ Rails.logger.warn "GETEXPRESSCHECKOUT ERROR:"+response.inspect
+ error = true
+ else
+ Rails.logger.debug "GETEXPRESSCHECKOUT:"+response.inspect
+
+ response = paypal.do_express_checkout_payment(token=token,
+ payment_action='Sale',
+ payer_id=response['PAYERID'],
+ amount='5.00')
+ #transaction_id = response['TRANSACTIONID']
+
+ if response['ACK'] != 'Success'
+ Rails.logger.warn "DOEXPESSCHECKOUT ERROR:"+response.inspect
+ error = true
+ else
+ Rails.logger.debug "DOEXPESSCHECKOUT:"+response.inspect
+
+ response = paypal.do_create_recurring_payments_profile(token,
+ start_date=(Time.parse(response['TIMESTAMP']) + 1.minute).iso8601, # Start date has to be in the future according to PayPal
+ profile_reference='INV20091122',
+ description="_Why's Ruby Camping Adventures - Monthly Tips And Tricks For Camping Development",
+ billing_period='Month',
+ billing_frequency=1,
+ total_billing_cycles=nil, # nil/0 = infinite
+ amount='5.00',
+ currency='USD')
+
+ if response['ACK'] != 'Success'
+ Rails.logger.warn "CREATERECURRINGPAYMENT ERROR:"+response.inspect
+ error = true
+ else
+ Rails.logger.debug "CREATERECURRINGPAYMENT:"+response.inspect
+
+ profile_id = response['PROFILEID']
+
+ @payment = Payment.new({profile: profile_id})
+
+ unless @payment.save
+ Rails.logger.warn "Payment Save ERROR:"+response.inspect
+ error = true
+ end
+ end
+ end
+ end
+
+ respond_to do |format|
+ unless error
+ format.html { redirect_to payments_url, notice: 'Payment was successfully created.' }
+ format.json { render json: @payment, status: :created, location: @payment }
+ else
+ @payment.errors.add_to_base "There was a problem processing your subscription. This issue has been logged."
+ format.html { redirect_to payments_url }
+ format.json { render json: @payment.errors, status: :unprocessable_entity }
+ end
end
end
# GET /payments/1/edit
- def edit
- @payment = Payment.find(params[:id])
- end
+ # def edit
+ # @payment = Payment.find(params[:id])
+ # end
# POST /payments
# POST /payments.json
- def create
- @payment = Payment.new(params[:payment])
+ # def create
+ # @payment = Payment.new(params[:payment])
- respond_to do |format|
- if @payment.save
- format.html { redirect_to @payment, notice: 'Payment was successfully created.' }
- format.json { render json: @payment, status: :created, location: @payment }
- else
- format.html { render action: "new" }
- format.json { render json: @payment.errors, status: :unprocessable_entity }
- end
- end
- end
+ # respond_to do |format|
+ # if @payment.save
+ # format.html { redirect_to @payment, notice: 'Payment was successfully created.' }
+ # format.json { render json: @payment, status: :created, location: @payment }
+ # else
+ # format.html { render action: "new" }
+ # format.json { render json: @payment.errors, status: :unprocessable_entity }
+ # end
+ # end
+ # end
# PUT /payments/1
# PUT /payments/1.json
- def update
- @payment = Payment.find(params[:id])
+ # def update
+ # @payment = Payment.find(params[:id])
- respond_to do |format|
- if @payment.update_attributes(params[:payment])
- format.html { redirect_to @payment, notice: 'Payment was successfully updated.' }
- format.json { head :no_content }
- else
- format.html { render action: "edit" }
- format.json { render json: @payment.errors, status: :unprocessable_entity }
- end
- end
- end
+ # respond_to do |format|
+ # if @payment.update_attributes(params[:payment])
+ # format.html { redirect_to @payment, notice: 'Payment was successfully updated.' }
+ # format.json { head :no_content }
+ # else
+ # format.html { render action: "edit" }
+ # format.json { render json: @payment.errors, status: :unprocessable_entity }
+ # end
+ # end
+ # end
# DELETE /payments/1
# DELETE /payments/1.json
- def destroy
- @payment = Payment.find(params[:id])
- @payment.destroy
+ # def destroy
+ # @payment = Payment.find(params[:id])
+ # @payment.destroy
- respond_to do |format|
- format.html { redirect_to payments_url }
- format.json { head :no_content }
- end
- end
+ # respond_to do |format|
+ # format.html { redirect_to payments_url }
+ # format.json { head :no_content }
+ # end
+ # end
end
diff --git a/app/models/payment.rb b/app/models/payment.rb
index 2c43fd0..ed0fe8c 100644
--- a/app/models/payment.rb
+++ b/app/models/payment.rb
@@ -1,3 +1,4 @@
class Payment < ActiveRecord::Base
attr_accessible :profile
+ validates_presence_of :profile
end
diff --git a/app/views/payments/new.html.erb b/app/views/payments/new.html.erb
index d96c87c..a42f46f 100644
--- a/app/views/payments/new.html.erb
+++ b/app/views/payments/new.html.erb
@@ -1,5 +1,24 @@
New payment
-<%= render 'form' %>
+<% if @payment.errors.any? %>
+
+
<%= pluralize(@payment.errors.count, "error") %> prohibited this payment from being saved:
+
+
+ <% @payment.errors.full_messages.each do |msg| %>
+ - <%= msg %>
+ <% end %>
+
+
+ <% end %>
+
+<%= form_tag('https://www.sandbox.paypal.com/cgi-bin/webscr', {:method => 'post', :authenticity_token => false } ) do %>
+
+ <%= hidden_field_tag 'cmd', "_express-checkout" %>
+
+ <%= hidden_field_tag 'token', @token %>
+
+ <%= submit_tag 'Subscribe Via PayPal', {:id => 'submit_subscription_request', :name => 'submit'} %>
+<% end %>
<%= link_to 'Back', payments_path %>
diff --git a/app/views/payments/show.html.erb b/app/views/payments/show.html.erb
index cbbf163..da2fb20 100644
--- a/app/views/payments/show.html.erb
+++ b/app/views/payments/show.html.erb
@@ -4,6 +4,20 @@
Profile:
<%= @payment.profile %>
+
+ Status: <%= @paypal_result['STATUS'] %>
+ Last Payment Date: <%= @paypal_result['LASTPAYMENTDATE'] %>
+ Last Payment Amount: <%= @paypal_result['LASTPAYMENTAMT'] %>
+
+
+ # Payments Complete:<%= @paypal_result['NUMCYCLESCOMPLETED'] %>
+ Start date: <%= @paypal_result['PROFILESTARTDATE'] %>
+ Next Billing date: <%= @paypal_result['NEXTBILLINGDATE'] %>
+ Total Amount paid: <%= @paypal_result['REGULARAMTPAID'] %>
+
+
+ PayPal Timestamp: <%= @paypal_result['TIMESTAMP'] %>
+
<%= link_to 'Edit', edit_payment_path(@payment) %> |
diff --git a/config/initializers/paypal.rb b/config/initializers/paypal.rb
new file mode 100644
index 0000000..9137800
--- /dev/null
+++ b/config/initializers/paypal.rb
@@ -0,0 +1,2 @@
+#require File.dirname(__FILE__) + '/../../config/environment.rb'
+APP_CONFIG = YAML.load_file("#{Rails.root}/config/paypal.yml")[Rails.env]
\ No newline at end of file
diff --git a/config/paypal.yml b/config/paypal.yml
deleted file mode 100644
index b616cef..0000000
--- a/config/paypal.yml
+++ /dev/null
@@ -1,24 +0,0 @@
- development:
- username: username
- password: pass
- signature: sig
- url: sandbox
- action: https://www.sandbox.paypal.com/cgi-bin/webscr
- test:
- username: username
- password: pass
- signature: sig
- url: sandbox
- action: https://www.sandbox.paypal.com/cgi-bin/webscr
- staging:
- username: username
- password: pass
- signature: sig
- url: sandbox
- action: https://www.sandbox.paypal.com/cgi-bin/webscr
- production:
- username: "username"
- password: "password"
- signature: "signature"
- url: production
- action: https://wwwpaypal.com/cgi-bin/webscr
diff --git a/config/paypal.yml.dist b/config/paypal.yml.dist
new file mode 100644
index 0000000..617d7ab
--- /dev/null
+++ b/config/paypal.yml.dist
@@ -0,0 +1,24 @@
+development:
+ username: p_api1.paypal.com
+ password: your_password
+ signature: your_signature
+ url: sandbox
+ action: https://www.sandbox.paypal.com/cgi-bin/webscr
+test:
+ username: p_api1.paypal.com
+ password: your_password
+ signature: your_signature
+ url: sandbox
+ action: https://www.sandbox.paypal.com/cgi-bin/webscr
+staging:
+ username: p_api1.paypal.com
+ password: your_password
+ signature: your_signature
+ url: sandbox
+ action: https://www.sandbox.paypal.com/cgi-bin/webscr
+production:
+ username: "username"
+ password: "password"
+ signature: "signature"
+ url: production
+ action: https://wwwpaypal.com/cgi-bin/webscr
diff --git a/config/routes.rb b/config/routes.rb
index bef134f..789438b 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,5 @@
RubyPaypalExample::Application.routes.draw do
+ match 'payments/confirmed' => 'payments#confirmed'
resources :payments
diff --git a/db/schema.rb b/db/schema.rb
new file mode 100644
index 0000000..948c773
--- /dev/null
+++ b/db/schema.rb
@@ -0,0 +1,22 @@
+# encoding: UTF-8
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# Note that this schema.rb definition is the authoritative source for your
+# database schema. If you need to create the application database on another
+# system, you should be using db:schema:load, not running all the migrations
+# from scratch. The latter is a flawed and unsustainable approach (the more migrations
+# you'll amass, the slower it'll run and the greater likelihood for issues).
+#
+# It's strongly recommended to check this file into your version control system.
+
+ActiveRecord::Schema.define(:version => 20130430055458) do
+
+ create_table "payments", :force => true do |t|
+ t.string "profile"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
+end