<%= render :partial => 'spree/shared/order_details', :locals => {:order => @order} -%>
+
<%= button_to t(:place_order), paypal_finish_order_checkout_url(@order, {:token => params[:token] , :PayerID => params[:PayerID], :payment_method_id =>
params[:payment_method_id] } ), :class => "button primary" %>
From 4b1def8643a3ab49801debec6b9d52bf31ac8537 Mon Sep 17 00:00:00 2001
From: Bounmy Stephane
Date: Fri, 25 May 2012 20:44:20 +0200
Subject: [PATCH 12/16] fixed consume_users_credit call
---
app/controllers/spree/checkout_controller_decorator.rb | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/app/controllers/spree/checkout_controller_decorator.rb b/app/controllers/spree/checkout_controller_decorator.rb
index 48cad1c..3db3054 100644
--- a/app/controllers/spree/checkout_controller_decorator.rb
+++ b/app/controllers/spree/checkout_controller_decorator.rb
@@ -149,7 +149,11 @@ module Spree
@order.update_attribute(:state, "complete")
state_callback(:after) # So that after_complete is called, setting session[:order_id] to nil
- @order.send(:consume_users_credit) if @order.respond_to?(:consume_users_credit, true)#since we dont rely on state machine callback, we just explicitly call this method for spree_store_credits
+
+ # Since we dont rely on state machine callback, we just explicitly call this method for spree_store_credits
+ if @order.respond_to?(:consume_users_credit, true)
+ @order.send(:consume_users_credit)
+ end
@order.finalize!
flash[:notice] = I18n.t(:order_processed_successfully)
From 3d5af5bdafcfc8c2fb6ebcc3c94f972ed1d80726 Mon Sep 17 00:00:00 2001
From: Bounmy Stephane
Date: Fri, 25 May 2012 21:26:19 +0200
Subject: [PATCH 13/16] set completed_at
---
app/controllers/spree/checkout_controller_decorator.rb | 3 ++-
spec/controllers/checkout_controller_spec.rb | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/app/controllers/spree/checkout_controller_decorator.rb b/app/controllers/spree/checkout_controller_decorator.rb
index 3db3054..890429a 100644
--- a/app/controllers/spree/checkout_controller_decorator.rb
+++ b/app/controllers/spree/checkout_controller_decorator.rb
@@ -147,7 +147,8 @@ module Spree
Rails.logger.error ppx_auth_response.to_yaml
end
- @order.update_attribute(:state, "complete")
+ @order.update_attributes({:state => "complete", :completed_at => Time.now}, :without_protection => true)
+
state_callback(:after) # So that after_complete is called, setting session[:order_id] to nil
# Since we dont rely on state machine callback, we just explicitly call this method for spree_store_credits
diff --git a/spec/controllers/checkout_controller_spec.rb b/spec/controllers/checkout_controller_spec.rb
index 90d75a3..1c4fa22 100644
--- a/spec/controllers/checkout_controller_spec.rb
+++ b/spec/controllers/checkout_controller_spec.rb
@@ -97,6 +97,7 @@ module Spree
order.reload
order.state.should == "complete"
+ order.completed_at.should_not be_nil
order.payments.size.should == 1
order.payment_state.should == "paid"
end
From 26da5770907c396aa8e9d16d5e7685311e3b7240 Mon Sep 17 00:00:00 2001
From: Bounmy Stephane
Date: Thu, 31 May 2012 08:54:05 +0200
Subject: [PATCH 14/16] using a base class for paypal express
---
.../billing_integration/paypal_express.rb | 18 +-----------------
.../paypal_express_base.rb | 19 +++++++++++++++++++
.../billing_integration/paypal_express_uk.rb | 18 +-----------------
3 files changed, 21 insertions(+), 34 deletions(-)
create mode 100644 app/models/spree/billing_integration/paypal_express_base.rb
diff --git a/app/models/spree/billing_integration/paypal_express.rb b/app/models/spree/billing_integration/paypal_express.rb
index 389e162..572f19e 100644
--- a/app/models/spree/billing_integration/paypal_express.rb
+++ b/app/models/spree/billing_integration/paypal_express.rb
@@ -1,19 +1,3 @@
-class Spree::BillingIntegration::PaypalExpress < Spree::BillingIntegration
- preference :login, :string
- preference :password, :password
- preference :signature, :string
- preference :review, :boolean, :default => false
- preference :no_shipping, :boolean, :default => false
+class Spree::BillingIntegration::PaypalExpress < Spree::BillingIntegration::PaypalExpressBase
preference :currency, :string, :default => 'USD'
- preference :allow_guest_checkout, :boolean, :default => false
-
- attr_accessible :preferred_login, :preferred_password, :preferred_signature, :preferred_review, :preferred_no_shipping, :preferred_currency, :preferred_allow_guest_checkout, :preferred_server, :preferred_test_mode
-
- def provider_class
- ActiveMerchant::Billing::PaypalExpressGateway
- end
-
- def payment_profiles_supported?
- !!preferred_review
- end
end
diff --git a/app/models/spree/billing_integration/paypal_express_base.rb b/app/models/spree/billing_integration/paypal_express_base.rb
new file mode 100644
index 0000000..4a81256
--- /dev/null
+++ b/app/models/spree/billing_integration/paypal_express_base.rb
@@ -0,0 +1,19 @@
+class Spree::BillingIntegration::PaypalExpressBase < Spree::BillingIntegration
+ preference :login, :string
+ preference :password, :password
+ preference :signature, :string
+ preference :review, :boolean, :default => false
+ preference :no_shipping, :boolean, :default => false
+ preference :currency, :string, :default => 'USD'
+ preference :allow_guest_checkout, :boolean, :default => false
+
+ attr_accessible :preferred_login, :preferred_password, :preferred_signature, :preferred_review, :preferred_no_shipping, :preferred_currency, :preferred_allow_guest_checkout, :preferred_server, :preferred_test_mode
+
+ def provider_class
+ ActiveMerchant::Billing::PaypalExpressGateway
+ end
+
+ def payment_profiles_supported?
+ !!preferred_review
+ end
+end
\ No newline at end of file
diff --git a/app/models/spree/billing_integration/paypal_express_uk.rb b/app/models/spree/billing_integration/paypal_express_uk.rb
index 2c18503..3dc9a79 100644
--- a/app/models/spree/billing_integration/paypal_express_uk.rb
+++ b/app/models/spree/billing_integration/paypal_express_uk.rb
@@ -1,19 +1,3 @@
-class Spree::BillingIntegration::PaypalExpressUk < Spree::BillingIntegration
- preference :login, :string
- preference :password, :password
- preference :signature, :string
- preference :review, :boolean, :default => false
- preference :no_shipping, :boolean, :default => false
+class Spree::BillingIntegration::PaypalExpressUk < Spree::BillingIntegration::PaypalExpressBase
preference :currency, :string, :default => 'GBP'
- preference :allow_guest_checkout, :boolean, :default => false
-
- attr_accessible :preferred_login, :preferred_password, :preferred_signature, :preferred_review, :preferred_currency, :preferred_no_shipping, :preferred_server, :preferred_test_mode
-
- def provider_class
- ActiveMerchant::Billing::PaypalExpressGateway
- end
-
- def payment_profiles_supported?
- !!preferred_review
- end
end
From b11a9dd9f2a7072b5299175e74ec05bf96a8d854 Mon Sep 17 00:00:00 2001
From: Bounmy Stephane
Date: Fri, 1 Jun 2012 00:06:16 +0200
Subject: [PATCH 15/16] fixed capture and credit due to spree 1.1 changes cf
payment processing
---
.../paypal_express_base.rb | 42 +++++++
app/models/spree/paypal_account.rb | 72 +-----------
.../paypal_express_base_spec.rb | 108 ++++++++++++++++++
3 files changed, 151 insertions(+), 71 deletions(-)
create mode 100644 spec/models/billing_integration/paypal_express_base_spec.rb
diff --git a/app/models/spree/billing_integration/paypal_express_base.rb b/app/models/spree/billing_integration/paypal_express_base.rb
index 4a81256..d694f4f 100644
--- a/app/models/spree/billing_integration/paypal_express_base.rb
+++ b/app/models/spree/billing_integration/paypal_express_base.rb
@@ -16,4 +16,46 @@ class Spree::BillingIntegration::PaypalExpressBase < Spree::BillingIntegration
def payment_profiles_supported?
!!preferred_review
end
+
+ def capture(payment_or_amount, account_or_response_code, gateway_options)
+ if payment_or_amount.is_a?(Spree::Payment)
+ authorization = find_authorization(payment_or_amount)
+ provider.capture(amount_in_cents(payment_or_amount.amount), authorization.params["transaction_id"], :currency => preferred_currency)
+ else
+ provider.capture(payment_or_amount, account_or_response_code, :currency => preferred_currency)
+ end
+ end
+
+ def credit(amount, account, response_code, gateway_options)
+ provider.credit(amount, response_code, :currency => preferred_currency)
+ end
+
+
+ def find_authorization(payment)
+ logs = payment.log_entries.all(:order => 'created_at DESC')
+ logs.each do |log|
+ details = YAML.load(log.details) # return the transaction details
+ if (details.params['payment_status'] == 'Pending' && details.params['pending_reason'] == 'authorization')
+ return details
+ end
+ end
+ return nil
+ end
+
+ def find_capture(payment)
+ #find the transaction associated with the original authorization/capture
+ logs = payment.log_entries.all(:order => 'created_at DESC')
+ logs.each do |log|
+ details = YAML.load(log.details) # return the transaction details
+ if details.params['payment_status'] == 'Completed'
+ return details
+ end
+ end
+ return nil
+ end
+
+ def amount_in_cents(amount)
+ (100 * amount).to_i
+ end
+
end
\ No newline at end of file
diff --git a/app/models/spree/paypal_account.rb b/app/models/spree/paypal_account.rb
index cc09d6a..8980ab1 100644
--- a/app/models/spree/paypal_account.rb
+++ b/app/models/spree/paypal_account.rb
@@ -6,46 +6,15 @@ class Spree::PaypalAccount < ActiveRecord::Base
%w{capture credit}
end
- def capture(payment)
- authorization = find_authorization(payment)
-
- ppx_response = payment.payment_method.provider.capture(amount_in_cents(payment.amount), authorization.params["transaction_id"], :currency => payment.payment_method.preferred_currency)
- if ppx_response.success?
- record_log payment, ppx_response
- payment.complete
- else
- gateway_error(ppx_response.message)
- end
-
- end
-
def can_capture?(payment)
!echeck?(payment) && payment.state == "pending"
end
- def credit(payment, amount=nil)
- authorization = find_capture(payment)
-
- amount = payment.credit_allowed >= payment.order.outstanding_balance.abs ? payment.order.outstanding_balance : payment.credit_allowed
- amount=amount.abs if amount
-
- ppx_response = payment.payment_method.provider.credit(amount.nil? ? amount_in_cents(amount) : amount_in_cents(amount), authorization.params['transaction_id'], :currency => payment.payment_method.preferred_currency)
-
- if ppx_response.success?
- record_log payment, ppx_response
- payment.update_attribute(:amount, payment.amount - amount)
- payment.complete
- payment.order.update!
- else
- gateway_error(ppx_response.message)
- end
- end
-
def can_credit?(payment)
return false unless payment.state == "completed"
return false unless payment.order.payment_state == "credit_owed"
payment.credit_allowed > 0
- !find_capture(payment).nil?
+ !payment.payment_method.find_capture(payment).nil?
end
# fix for Payment#payment_profiles_supported?
@@ -64,43 +33,4 @@ class Spree::PaypalAccount < ActiveRecord::Base
return false
end
- def record_log(payment, response)
- payment.log_entries.create(:details => response.to_yaml)
- end
-
- private
- def find_authorization(payment)
- logs = payment.log_entries.all(:order => 'created_at DESC')
- logs.each do |log|
- details = YAML.load(log.details) # return the transaction details
- if (details.params['payment_status'] == 'Pending' && details.params['pending_reason'] == 'authorization')
- return details
- end
- end
- return nil
- end
-
- def find_capture(payment)
- #find the transaction associated with the original authorization/capture
- logs = payment.log_entries.all(:order => 'created_at DESC')
- logs.each do |log|
- details = YAML.load(log.details) # return the transaction details
- if details.params['payment_status'] == 'Completed'
- return details
- end
- end
- return nil
- end
-
- def gateway_error(text)
- msg = "#{I18n.t('gateway_error')} ... #{text}"
- logger.error(msg)
- raise Spree::Core::GatewayError.new(msg)
- end
-
- private
-
- def amount_in_cents(amount)
- (100 * amount).to_i
- end
end
diff --git a/spec/models/billing_integration/paypal_express_base_spec.rb b/spec/models/billing_integration/paypal_express_base_spec.rb
new file mode 100644
index 0000000..85aa463
--- /dev/null
+++ b/spec/models/billing_integration/paypal_express_base_spec.rb
@@ -0,0 +1,108 @@
+require 'spec_helper'
+
+describe Spree::BillingIntegration::PaypalExpressBase do
+ let(:order) do
+ order = Spree::Order.new(:bill_address => Spree::Address.new,
+ :ship_address => Spree::Address.new)
+ end
+
+ let(:gateway) do
+ gateway = Spree::BillingIntegration::PaypalExpressBase.new({:environment => 'test', :active => true, :preferred_currency => "EUR"}, :without_protection => true)
+ gateway.stub :source_required => true
+ gateway.stub :provider => mock('paypal provider')
+ gateway.stub :find_authorization => mock('authorization', :params => authorization_params)
+ gateway
+ end
+
+ let(:authorization_params) { {'transaction_id' => '123'} }
+ let(:provider) { gateway.provider }
+
+ let(:account) do
+ mock_model(Spree::PaypalAccount)
+ end
+
+ let(:payment) do
+ payment = Spree::Payment.new
+ payment.source = account
+ payment.order = order
+ payment.payment_method = gateway
+ payment.amount = 10.0
+ payment
+ end
+
+ let(:amount_in_cents) { payment.amount.to_f * 100 }
+
+ let!(:success_response) do
+ mock('success_response', :success? => true,
+ :authorization => '123',
+ :avs_result => { 'code' => 'avs-code' })
+ end
+
+ let(:failed_response) { mock('gateway_response', :success? => false) }
+
+ before(:each) do
+ # So it doesn't create log entries every time a processing method is called
+ payment.log_entries.stub(:create)
+ end
+
+ describe "#capture" do
+ before { payment.state = 'pending' }
+
+ context "when payment_profiles_supported = true" do
+ before { gateway.stub :payment_profiles_supported? => true }
+
+ context "if sucessful" do
+ before do
+ provider.should_receive(:capture).with(amount_in_cents, '123', :currency => 'EUR').and_return(success_response)
+ end
+
+ it "should store the response_code" do
+ payment.capture!
+ payment.response_code.should == '123'
+ end
+ end
+
+ context "if unsucessful" do
+ before do
+ gateway.should_receive(:capture).with(payment, account, anything).and_return(failed_response)
+ end
+
+ it "should not make payment complete" do
+ lambda { payment.capture! }.should raise_error(Spree::Core::GatewayError)
+ payment.state.should == "failed"
+ end
+ end
+ end
+
+ context "when payment_profiles_supported = false" do
+ before do
+ payment.stub :response_code => '123'
+ gateway.stub :payment_profiles_supported? => false
+ end
+
+ context "if sucessful" do
+ before do
+ provider.should_receive(:capture).with(amount_in_cents, '123', anything).and_return(success_response)
+ end
+
+ it "should store the response_code" do
+ payment.capture!
+ payment.response_code.should == '123'
+ end
+ end
+
+ context "if unsucessful" do
+ before do
+ provider.should_receive(:capture).with(amount_in_cents, '123', anything).and_return(failed_response)
+ end
+
+ it "should not make payment complete" do
+ lambda { payment.capture! }.should raise_error(Spree::Core::GatewayError)
+ payment.state.should == "failed"
+ end
+ end
+
+ end
+ end
+
+end
From e11a8e4d5f0b4192d8adb6437fd38978eb4d2b7a Mon Sep 17 00:00:00 2001
From: Bounmy Stephane
Date: Fri, 1 Jun 2012 00:36:42 +0200
Subject: [PATCH 16/16] fixed credit when no payment_profiles_supported
---
.../paypal_express_base.rb | 5 ++--
.../paypal_express_base_spec.rb | 27 +++++++++++++++++++
2 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/app/models/spree/billing_integration/paypal_express_base.rb b/app/models/spree/billing_integration/paypal_express_base.rb
index d694f4f..d2e9820 100644
--- a/app/models/spree/billing_integration/paypal_express_base.rb
+++ b/app/models/spree/billing_integration/paypal_express_base.rb
@@ -26,11 +26,12 @@ class Spree::BillingIntegration::PaypalExpressBase < Spree::BillingIntegration
end
end
- def credit(amount, account, response_code, gateway_options)
+ def credit(*args)
+ amount = args.shift
+ response_code = args.first.is_a?(String) ? args.first : args[1]
provider.credit(amount, response_code, :currency => preferred_currency)
end
-
def find_authorization(payment)
logs = payment.log_entries.all(:order => 'created_at DESC')
logs.each do |log|
diff --git a/spec/models/billing_integration/paypal_express_base_spec.rb b/spec/models/billing_integration/paypal_express_base_spec.rb
index 85aa463..a346839 100644
--- a/spec/models/billing_integration/paypal_express_base_spec.rb
+++ b/spec/models/billing_integration/paypal_express_base_spec.rb
@@ -105,4 +105,31 @@ describe Spree::BillingIntegration::PaypalExpressBase do
end
end
+ describe "#credit" do
+ before { payment.stub :response_code => '123' }
+ context "when payment_profiles_supported = true" do
+ before { gateway.stub :payment_profiles_supported? => true }
+
+
+ it "should receive correct params" do
+ provider.should_receive(:credit).with(1000, '123', :currency => 'EUR').and_return(success_response)
+ payment.credit!(10.0)
+ payment.response_code.should == '123'
+ end
+ end
+
+ context "when payment_profiles_supported = false" do
+ before do
+ payment.stub :response_code => '123'
+ gateway.stub :payment_profiles_supported? => false
+ end
+
+ it "should receive correct params" do
+ provider.should_receive(:credit).with(amount_in_cents, '123', :currency => 'EUR').and_return(success_response)
+ payment.credit!(10.0)
+ payment.response_code.should == '123'
+ end
+
+ end
+ end
end