fixed capture and credit due to spree 1.1 changes cf payment processing

This commit is contained in:
Bounmy Stephane 2012-06-01 00:06:16 +02:00
parent 26da577090
commit b11a9dd9f2
3 changed files with 151 additions and 71 deletions

View File

@ -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

View File

@ -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

View File

@ -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