Permalink
Browse files

Implemented create method and associated tests.

  • Loading branch information...
1 parent 5324937 commit 7fb2df18b51f78eea1c9c18fd6102808228b4fdc @schof schof committed Oct 29, 2008
@@ -1,15 +1,18 @@
class PaypalPaymentsController < Spree::BaseController
include ActiveMerchant::Billing::Integrations
-
-# before_filter :verify_authenticity_token, :except => 'create'
+ skip_before_filter :verify_authenticity_token
+ before_filter :load_object, :only => :successful
layout 'application'
resource_controller :singleton
belongs_to :order
- #protect_from_forgery :except => [:create, :notify]
# NOTE: The Paypal Instant Payment Notification (IPN) results in the creation of a PaypalPayment
create.after do
+ # mark the checkout process as complete (even if the ipn results in a failure - no point in letting the user
+ # edit the order now)
+ @order.update_attribute("checkout_complete", true)
+ object.update_attribute("email", params[:payer_email])
ipn = Paypal::Notification.new(request.raw_post)
# create a transaction which records the details of the notification
@@ -41,12 +44,6 @@ class PaypalPaymentsController < Spree::BaseController
@order.fail_payment!
logger.info("Failed to acknowledge Paypal's notification, please investigate [order: #{@order.number}]")
end
-=begin
- @order.save
-
- # call notify hook (which will email users, etc.)
- after_notify(@payment) if @order.status == Order::Status::PAID
-=end
end
create.response do |wants|
@@ -55,4 +52,31 @@ class PaypalPaymentsController < Spree::BaseController
end
end
+ # Action for handling the "return to site" link after user completes the transaction on the Paypal website.
+ def successful
+ @order.update_attribute("ip_address", request.env['REMOTE_ADDR'] || "unknown")
+ # its possible that the IPN has already been received at this point so that
+ unless @order.paypal_payment
+ # create a payment and record the successful transaction
+ paypal_payment = PaypalPayment.create(:order => @order, :email => params[:payer_email])
+ @order.paypal_payment = paypal_payment
+ paypal_payment.txns.create(:amount => params[:mc_gross].to_d,
+ :status => "Processed",
+ :transaction_id => params[:txn_id],
+ :fee => params[:payment_fee],
+ :currency_type => params[:mc_currency],
+ :received_at => params[:payment_date])
+ # advance the state
+ @order.pend_payment!
+ end
+
+ if logged_in?
+ @order.update_attribute("user", current_user)
+ redirect_to order_url(@order) and return
+ else
+ flash[:notice] = "Please create an account or login so we can associate this order with an account"
+ session[:return_to] = order_url(@order)
+ redirect_to signup_path
+ end
+ end
end
@@ -1,6 +1,6 @@
<% if @order.paypal_payment %>
-<b><%= t("Paypal Transaction") %>: </b> &nbsp; #<%= @order.paypal_payment.reference_hash.upcase %>
+<b><%= t("Paypal Transaction") %></b>
<table class="basic-table">
<tr>
@@ -30,7 +30,7 @@ Zipcode (if you have one): <input id="zip" name="zip" type="text" value="" />
<input id="notify_url" name="notify_url" type="hidden" value="<%= Spree::Paypal::Config[:ipn_notify_host] + order_paypal_payment_path(@order) %>" />
<input type="hidden" name="rm" value ="2"> <!-- tells paypal that the return should be POST instead of GET -->
-<input id="return" name="return" type="hidden" value="<%= order_paypal_payment_url(@order) %>" />
+<input id="return" name="return" type="hidden" value="<%= successful_order_paypal_payment_url(@order) %>" />
<!-- input id="address_override" name="address_override" type="hidden" value="0" />
<input id="charset" name="charset" type="hidden" value="utf-8" />
@@ -0,0 +1 @@
+SUCCESS!
@@ -0,0 +1,13 @@
+class AddEmailField < ActiveRecord::Migration
+ def self.up
+ change_table :paypal_payments do |t|
+ t.string :email
+ end
+ end
+
+ def self.down
+ change_table :paypal_payments do |t|
+ t.remove :email
+ end
+ end
+end
@@ -14,7 +14,12 @@ class PpWebsiteStandardExtension < Spree::Extension
url "http://yourwebsite.com/spree_pp_website_standard"
define_routes do |map|
- map.resources :orders, :has_one => [:paypal_payment]
+ #map.resources :orders, :has_one => [:paypal_payment]
+ map.resources :orders do |order|
+ # we're kind of abusing the notion of a restful collection here but we're in the weird position of
+ # not being able to create the payment before sending the request to paypal
+ order.resource :paypal_payment, :collection => {:successful => :post}
+ end
end
def activate
@@ -33,14 +38,7 @@ def add_pp_standard_txns
fsm.events["pend_payment"] = PluginAWeek::StateMachine::Event.new(fsm, "pend_payment")
fsm.events["fail_payment"].transition(:to => 'payment_failure')
fsm.events["pend_payment"].transition(:to => 'payment_pending')
-
-# OrdersController.class_eval do
-#skip_before_filter :verify_authenticity_token
-# before_filter :verify_authenticity_token, :except => 'notify'
-# before_filter :load_object, :only => [:successful, :notify]
-# include ActiveMerchant::Billing::Integrations
-# include Paypal::PaController
-# end
+ fsm.after_transition :to => 'payment_pending', :do => lambda {|order| order.update_attribute(:checkout_complete, true)}
# add a PaypalPayment association to the Order model
Order.class_eval do
@@ -1,9 +0,0 @@
-require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
-
-describe OrdersController do
-# verify that tax is being added to the order
-# verify that shipping is being added to the order
-
- before(:each) do
- end
-end
@@ -2,7 +2,7 @@
include ActiveMerchant::Billing::Integrations
describe PaypalPaymentsController do
- fixtures :orders
+ fixtures :users
before(:each) do
@order = Order.create(:id => 100, :number => "SAMP-1001", :state => "in_progress", :total => 75.00)
@@ -13,15 +13,28 @@
end
describe "create" do
+
+ def do_create
+ post :create, :order_id => @order.id, :payer_email => "test@example.com"
+ end
+
before(:each) { @ipn.stub!(:acknowledge).and_return(true) }
it "should create a paypal payment associated with the order" do
- post :create, :order_id => @order.id
+ do_create
@order.paypal_payment.should_not be_nil
end
+ it "should set the paypal payment email" do
+ do_create
+ @order.paypal_payment.email.should == "test@example.com"
+ end
it "should create a transaction for the paypal payment" do
- post :create, :order_id => @order.id
+ do_create
@order.paypal_payment.txns.first.should_not be_nil
end
+ it "should mark the checkout as complete" do
+ do_create
+ @order.checkout_complete.should be_true
+ end
# TODO - check that the correct values are being assigned to the transaction
describe "with acknowledge" do
@@ -62,7 +75,58 @@
end
end
- describe "success" do
- it "should set the IP address of the order"
+ describe "successful" do
+ describe "successful in general", :shared => true do
+ def do_successful
+ post :successful, :order_id => @order.id, :mc_gross => @order.total.to_s, :payer_email => "test@example.com"
+ end
+ it "should set the IP address of the order" do
+ request.env['REMOTE_ADDR'] = "1.2.3.4"
+ do_successful
+ @order.ip_address.should == "1.2.3.4"
+ end
+ describe "when logged in" do
+ before(:each) { @user = login(:pp_standard) }
+ it "should store the user with the order" do
+ do_successful
+ @order.user.should == @user
+ end
+ it "should redirect to the order details view" do
+ do_successful
+ response.should redirect_to(order_url(@order))
+ end
+ end
+ it "should redirect to the signup path (if not logged in)" do
+ do_successful
+ response.should redirect_to(signup_path)
+ end
+ end
+ describe "when ipn has not yet been received" do
+ it "should create a payment" do
+ do_successful
+ @order.paypal_payment.should_not be_nil
+ end
+ it "should set the order status to payment_pending" do
+ do_successful
+ @order.state.should == "payment_pending"
+ end
+ it "should mark the checkout as complete" do
+ do_successful
+ @order.checkout_complete.should be_true
+ end
+ it "should set the payment email" do
+ do_successful
+ @order.paypal_payment.email.should == "test@example.com"
+ end
+ it_should_behave_like "successful in general"
+ end
+ describe "when ipn has already been received" do
+ before(:each) { @order.paypal_payment = PaypalPayment.new }
+ it "should not create a new paypal paypment" do
+ PaypalPayment.should_not_receive(:create).with(any_args)
+ do_successful
+ end
+ it_should_behave_like "successful in general"
+ end
end
end
@@ -0,0 +1,5 @@
+pp_standard:
+ email: pp_standard@example.com
+ #salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd
+ #crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1
+ #roles: admin
View
@@ -18,10 +18,10 @@
Dir[File.dirname(__FILE__) + "/matchers/*.rb"].each {|file| require file }
end
-#Spec::Runner.configure do |config|
-# config.use_transactional_fixtures = true
-# config.use_instantiated_fixtures = false
-# config.fixture_path = File.dirname(__FILE__) + '/fixtures'
+Spec::Runner.configure do |config|
+ config.use_transactional_fixtures = true
+ config.use_instantiated_fixtures = false
+ config.fixture_path = File.dirname(__FILE__) + '/fixtures'
# You can declare fixtures for each behaviour like this:
# describe "...." do
@@ -34,4 +34,10 @@
#
# If you declare global fixtures, be aware that they will be declared
# for all of your examples, even those that don't use them.
-#end
+end
+
+def login(username)
+ user = users(username.to_sym)
+ request.session[:user_id] = user.id
+ user
+end

0 comments on commit 7fb2df1

Please sign in to comment.