spree_payflow 0.60.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,9 @@
1
+ \#*
2
+ *~
3
+ .#*
4
+ .DS_Store
5
+ .idea
6
+ .project
7
+ tmp
8
+ nbproject
9
+ *.swp
data/Gemfile ADDED
@@ -0,0 +1,33 @@
1
+ source 'http://rubygems.org'
2
+
3
+ group :test do
4
+ gem 'rspec-rails', '= 2.5.0'
5
+ gem 'factory_girl', '= 1.3.3'
6
+ gem 'factory_girl_rails', '= 1.0.1'
7
+ gem 'rcov'
8
+ gem 'shoulda'
9
+ gem 'faker'
10
+ if RUBY_VERSION < "1.9"
11
+ gem "ruby-debug"
12
+ else
13
+ gem "ruby-debug19"
14
+ end
15
+ end
16
+
17
+ group :cucumber do
18
+ gem 'cucumber-rails'
19
+ gem 'database_cleaner', '= 0.6.7'
20
+ gem 'nokogiri'
21
+ gem 'capybara', '= 0.4.1.2'
22
+ gem 'factory_girl', '= 1.3.3'
23
+ gem 'factory_girl_rails', '= 1.0.1'
24
+ gem 'faker'
25
+ gem 'launchy'
26
+
27
+ if RUBY_VERSION < "1.9"
28
+ gem "ruby-debug"
29
+ else
30
+ gem "ruby-debug19"
31
+ end
32
+ end
33
+ gem 'sqlite3-ruby'
@@ -0,0 +1,139 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ abstract (1.0.0)
5
+ actionpack (3.0.9)
6
+ activemodel (= 3.0.9)
7
+ activesupport (= 3.0.9)
8
+ builder (~> 2.1.2)
9
+ erubis (~> 2.6.6)
10
+ i18n (~> 0.5.0)
11
+ rack (~> 1.2.1)
12
+ rack-mount (~> 0.6.14)
13
+ rack-test (~> 0.5.7)
14
+ tzinfo (~> 0.3.23)
15
+ activemodel (3.0.9)
16
+ activesupport (= 3.0.9)
17
+ builder (~> 2.1.2)
18
+ i18n (~> 0.5.0)
19
+ activesupport (3.0.9)
20
+ archive-tar-minitar (0.5.2)
21
+ builder (2.1.2)
22
+ capybara (0.4.1.2)
23
+ celerity (>= 0.7.9)
24
+ culerity (>= 0.2.4)
25
+ mime-types (>= 1.16)
26
+ nokogiri (>= 1.3.3)
27
+ rack (>= 1.0.0)
28
+ rack-test (>= 0.5.4)
29
+ selenium-webdriver (>= 0.0.27)
30
+ xpath (~> 0.1.3)
31
+ celerity (0.8.9)
32
+ childprocess (0.1.9)
33
+ ffi (~> 1.0.6)
34
+ columnize (0.3.4)
35
+ configuration (1.3.1)
36
+ cucumber (1.0.0)
37
+ builder (>= 2.1.2)
38
+ diff-lcs (>= 1.1.2)
39
+ gherkin (~> 2.4.1)
40
+ json (>= 1.4.6)
41
+ term-ansicolor (>= 1.0.5)
42
+ cucumber-rails (0.4.1)
43
+ cucumber (>= 0.10.1)
44
+ nokogiri (>= 1.4.4)
45
+ rack-test (>= 0.5.7)
46
+ culerity (0.2.15)
47
+ database_cleaner (0.6.7)
48
+ diff-lcs (1.1.2)
49
+ erubis (2.6.6)
50
+ abstract (>= 1.0.0)
51
+ factory_girl (1.3.3)
52
+ factory_girl_rails (1.0.1)
53
+ factory_girl (~> 1.3)
54
+ railties (>= 3.0.0)
55
+ faker (0.9.5)
56
+ i18n (~> 0.4)
57
+ ffi (1.0.9)
58
+ gherkin (2.4.1)
59
+ json (>= 1.4.6)
60
+ i18n (0.5.0)
61
+ json (1.5.3)
62
+ json_pure (1.5.3)
63
+ launchy (0.4.0)
64
+ configuration (>= 0.0.5)
65
+ rake (>= 0.8.1)
66
+ linecache19 (0.5.12)
67
+ ruby_core_source (>= 0.1.4)
68
+ mime-types (1.16)
69
+ nokogiri (1.5.0)
70
+ rack (1.2.3)
71
+ rack-mount (0.6.14)
72
+ rack (>= 1.0.0)
73
+ rack-test (0.5.7)
74
+ rack (>= 1.0)
75
+ railties (3.0.9)
76
+ actionpack (= 3.0.9)
77
+ activesupport (= 3.0.9)
78
+ rake (>= 0.8.7)
79
+ rdoc (~> 3.4)
80
+ thor (~> 0.14.4)
81
+ rake (0.9.2)
82
+ rcov (0.9.9)
83
+ rdoc (3.8)
84
+ rspec (2.5.0)
85
+ rspec-core (~> 2.5.0)
86
+ rspec-expectations (~> 2.5.0)
87
+ rspec-mocks (~> 2.5.0)
88
+ rspec-core (2.5.2)
89
+ rspec-expectations (2.5.0)
90
+ diff-lcs (~> 1.1.2)
91
+ rspec-mocks (2.5.0)
92
+ rspec-rails (2.5.0)
93
+ actionpack (~> 3.0)
94
+ activesupport (~> 3.0)
95
+ railties (~> 3.0)
96
+ rspec (~> 2.5.0)
97
+ ruby-debug-base19 (0.11.25)
98
+ columnize (>= 0.3.1)
99
+ linecache19 (>= 0.5.11)
100
+ ruby_core_source (>= 0.1.4)
101
+ ruby-debug19 (0.11.6)
102
+ columnize (>= 0.3.1)
103
+ linecache19 (>= 0.5.11)
104
+ ruby-debug-base19 (>= 0.11.19)
105
+ ruby_core_source (0.1.5)
106
+ archive-tar-minitar (>= 0.5.2)
107
+ rubyzip (0.9.4)
108
+ selenium-webdriver (2.0.0)
109
+ childprocess (>= 0.1.9)
110
+ ffi (>= 1.0.7)
111
+ json_pure
112
+ rubyzip
113
+ shoulda (2.11.3)
114
+ sqlite3 (1.3.3)
115
+ sqlite3-ruby (1.3.3)
116
+ sqlite3 (>= 1.3.3)
117
+ term-ansicolor (1.0.5)
118
+ thor (0.14.6)
119
+ tzinfo (0.3.29)
120
+ xpath (0.1.4)
121
+ nokogiri (~> 1.3)
122
+
123
+ PLATFORMS
124
+ ruby
125
+
126
+ DEPENDENCIES
127
+ capybara (= 0.4.1.2)
128
+ cucumber-rails
129
+ database_cleaner (= 0.6.7)
130
+ factory_girl (= 1.3.3)
131
+ factory_girl_rails (= 1.0.1)
132
+ faker
133
+ launchy
134
+ nokogiri
135
+ rcov
136
+ rspec-rails (= 2.5.0)
137
+ ruby-debug19
138
+ shoulda
139
+ sqlite3-ruby
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Redistribution and use in source and binary forms, with or without modification,
2
+ are permitted provided that the following conditions are met:
3
+
4
+ * Redistributions of source code must retain the above copyright notice,
5
+ this list of conditions and the following disclaimer.
6
+ * Redistributions in binary form must reproduce the above copyright notice,
7
+ this list of conditions and the following disclaimer in the documentation
8
+ and/or other materials provided with the distribution.
9
+ * Neither the name of the Rails Dog LLC nor the names of its
10
+ contributors may be used to endorse or promote products derived from this
11
+ software without specific prior written permission.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,13 @@
1
+ SpreePayflow
2
+ ============
3
+
4
+ Introduction goes here.
5
+
6
+
7
+ Example
8
+ =======
9
+
10
+ Example goes here.
11
+
12
+
13
+ Copyright (c) 2011 Chad Nantais, released under the New BSD License
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'rake/testtask'
5
+
6
+ desc "Default Task"
7
+ task :default => [ :spec ]
8
+
9
+ gemfile = File.expand_path('../spec/test_app/Gemfile', __FILE__)
10
+ if File.exists?(gemfile) && %w(rcov spec cucumber).include?(ARGV.first.to_s)
11
+ require 'bundler'
12
+ ENV['BUNDLE_GEMFILE'] = gemfile
13
+ Bundler.setup
14
+
15
+ require 'rspec/core/rake_task'
16
+ RSpec::Core::RakeTask.new
17
+
18
+ require 'cucumber/rake/task'
19
+ Cucumber::Rake::Task.new do |t|
20
+ t.cucumber_opts = %w{--format pretty}
21
+ end
22
+
23
+ desc "Run specs with RCov"
24
+ RSpec::Core::RakeTask.new(:rcov) do |t|
25
+ t.rcov = true
26
+ t.rcov_opts = %w{ --exclude gems\/,spec\/,features\/}
27
+ t.verbose = true
28
+ end
29
+
30
+ end
31
+
32
+ desc "Regenerates a rails 3 app for testing"
33
+ task :test_app do
34
+ SPREE_PATH = ENV['SPREE_PATH']
35
+ raise "SPREE_PATH should be specified" unless SPREE_PATH
36
+ require File.join(SPREE_PATH, 'lib/generators/spree/test_app_generator')
37
+ class AuthTestAppGenerator < Spree::Generators::TestAppGenerator
38
+ def tweak_gemfile
39
+ append_file 'Gemfile' do
40
+ <<-gems
41
+ gem 'spree_core', :path => '#{File.join(SPREE_PATH, 'core')}'
42
+ gem 'spree_auth', :path => '#{File.join(SPREE_PATH, 'auth')}'
43
+ gem 'spree_payflow', :path => '#{File.dirname(__FILE__)}'
44
+ gems
45
+ end
46
+ end
47
+
48
+ def install_gems
49
+ inside "test_app" do
50
+ run 'rake spree_core:install'
51
+ run 'rake spree_auth:install'
52
+ run 'rake spree_payflow:install'
53
+ end
54
+ end
55
+
56
+ def migrate_db
57
+ run_migrations
58
+ end
59
+ end
60
+ AuthTestAppGenerator.start
61
+ end
62
+
63
+ namespace :test_app do
64
+ desc 'Rebuild test and cucumber databases'
65
+ task :rebuild_dbs do
66
+ system("cd spec/test_app && rake db:drop db:migrate RAILS_ENV=test && rake db:drop db:migrate RAILS_ENV=cucumber")
67
+ end
68
+ end
@@ -0,0 +1,3 @@
1
+ "0.60.x" => { :branch => "master" }
2
+
3
+
@@ -0,0 +1,9 @@
1
+ class Gateway::Payflow < Gateway
2
+ preference :login, :string
3
+ preference :password, :password
4
+ preference :partner, :string
5
+
6
+ def provider_class
7
+ ActiveMerchant::Billing::PayflowGateway
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ # Add your extension routes here
3
+ end
@@ -0,0 +1,23 @@
1
+ require 'spree_core'
2
+ require 'spree_payflow_hooks'
3
+
4
+ module SpreePayflow
5
+ class Engine < Rails::Engine
6
+
7
+ config.autoload_paths += %W(#{config.root}/lib)
8
+
9
+ def self.activate
10
+
11
+ require 'active_merchant'
12
+ ActiveMerchant::Billing::PayflowGateway
13
+
14
+ Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*_decorator*.rb")) do |c|
15
+ Rails.env.production? ? require(c) : load(c)
16
+ end
17
+
18
+ Gateway::Payflow.register
19
+ end
20
+
21
+ config.to_prepare &method(:activate).to_proc
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ class SpreePayflowHooks < Spree::ThemeSupport::HookListener
2
+ # custom hooks go here
3
+ end
@@ -0,0 +1,25 @@
1
+ namespace :spree_payflow do
2
+ desc "Copies all migrations and assets (NOTE: This will be obsolete with Rails 3.1)"
3
+ task :install do
4
+ Rake::Task['spree_payflow:install:migrations'].invoke
5
+ Rake::Task['spree_payflow:install:assets'].invoke
6
+ end
7
+
8
+ namespace :install do
9
+ desc "Copies all migrations (NOTE: This will be obsolete with Rails 3.1)"
10
+ task :migrations do
11
+ source = File.join(File.dirname(__FILE__), '..', '..', 'db')
12
+ destination = File.join(Rails.root, 'db')
13
+ Spree::FileUtilz.mirror_files(source, destination)
14
+ end
15
+
16
+ desc "Copies all assets (NOTE: This will be obsolete with Rails 3.1)"
17
+ task :assets do
18
+ source = File.join(File.dirname(__FILE__), '..', '..', 'public')
19
+ destination = File.join(Rails.root, 'public')
20
+ puts "INFO: Mirroring assets from #{source} to #{destination}"
21
+ Spree::FileUtilz.mirror_files(source, destination)
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1 @@
1
+ # add custom rake tasks here
@@ -0,0 +1,277 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe CheckoutController do
4
+ let(:token) { "EC-2OPN7UJGFWK9OYFV" }
5
+ let(:order) { Factory(:ppx_order_with_totals, :state => "payment") }
6
+ let(:order_total) { (order.total * 100).to_i }
7
+ let(:gateway_provider) { mock(ActiveMerchant::Billing::PaypalExpressGateway) }
8
+ let(:paypal_gateway) { mock(BillingIntegration::PaypalExpress, :id => 123, :preferred_review => false, :preferred_no_shipping => true, :provider => gateway_provider) }
9
+
10
+ let(:details_for_response) { mock(ActiveMerchant::Billing::PaypalExpressResponse, :success? => true,
11
+ :params => {"payer" => order.user.email, "payer_id" => "FWRVKNRRZ3WUC"}, :address => {}) }
12
+
13
+ let(:purchase_response) { mock(ActiveMerchant::Billing::PaypalExpressResponse, :success? => true,
14
+ :params => {"payer" => order.user.email, "payer_id" => "FWRVKNRRZ3WUC", "gross_amount" => order_total, "payment_status" => "Completed"},
15
+ :avs_result => "F",
16
+ :to_yaml => "fake") }
17
+
18
+
19
+ before do
20
+ Spree::Auth::Config.set(:registration_step => false)
21
+ controller.stub(:current_order => order, :check_authorization => true, :current_user => order.user)
22
+ order.stub(:checkout_allowed? => true, :completed? => false)
23
+ order.update!
24
+ end
25
+
26
+ it "should understand paypal routes" do
27
+ assert_routing("/orders/#{order.number}/checkout/paypal_payment", {:controller => "checkout", :action => "paypal_payment", :order_id => order.number })
28
+ assert_routing("/orders/#{order.number}/checkout/paypal_confirm", {:controller => "checkout", :action => "paypal_confirm", :order_id => order.number })
29
+ end
30
+
31
+ context "paypal_checkout" do
32
+ #feature not implemented
33
+ end
34
+
35
+ context "paypal_payment without auto_capture" do
36
+ let(:redirect_url) { "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=#{token}&useraction=commit" }
37
+
38
+ before { Spree::Config.set(:auto_capture => false) }
39
+
40
+ it "should setup an authorize transaction and redirect to sandbox" do
41
+ PaymentMethod.should_receive(:find).at_least(1).with('123').and_return(paypal_gateway)
42
+
43
+ gateway_provider.should_receive(:redirect_url_for).with(token, {:review => false}).and_return redirect_url
44
+ paypal_gateway.provider.should_receive(:setup_authorization).with(order_total, anything()).and_return(mock(:success? => true, :token => token))
45
+
46
+ get :paypal_payment, {:order_id => order.number, :payment_method_id => "123" }
47
+
48
+ response.should redirect_to "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=#{assigns[:ppx_response].token}&useraction=commit"
49
+ end
50
+
51
+ end
52
+
53
+ context "paypal_payment with auto_capture" do
54
+ let(:redirect_url) { "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=#{token}&useraction=commit" }
55
+
56
+ before { Spree::Config.set(:auto_capture => true) }
57
+
58
+ it "should setup a purchase transaction and redirect to sandbox" do
59
+ PaymentMethod.should_receive(:find).at_least(1).with("123").and_return(paypal_gateway)
60
+
61
+ gateway_provider.should_receive(:redirect_url_for).with(token, {:review => false}).and_return redirect_url
62
+ paypal_gateway.provider.should_receive(:setup_purchase).with(order_total, anything()).and_return(mock(:success? => true, :token => token))
63
+
64
+ get :paypal_payment, {:order_id => order.number, :payment_method_id => "123" }
65
+
66
+ response.should redirect_to "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=#{assigns[:ppx_response].token}&useraction=commit"
67
+ end
68
+
69
+ end
70
+
71
+ context "paypal_confirm" do
72
+ before { PaymentMethod.should_receive(:find).at_least(1).with("123").and_return(paypal_gateway) }
73
+
74
+ context "with auto_capture and no review" do
75
+ before do
76
+ Spree::Config.set(:auto_capture => true)
77
+ paypal_gateway.stub(:preferred_review => false)
78
+ end
79
+
80
+ it "should capture payment" do
81
+ paypal_gateway.provider.should_receive(:details_for).with(token).and_return(details_for_response)
82
+
83
+ paypal_gateway.provider.should_receive(:purchase).with(order_total, anything()).and_return(purchase_response)
84
+
85
+ get :paypal_confirm, {:order_id => order.number, :payment_method_id => "123", :token => token, :PayerID => "FWRVKNRRZ3WUC" }
86
+
87
+ response.should redirect_to order_url(order)
88
+
89
+ order.reload
90
+ order.state.should == "complete"
91
+ order.payments.size.should == 1
92
+ order.payment_state.should == "paid"
93
+ end
94
+ end
95
+
96
+ context "with review" do
97
+ before { paypal_gateway.stub(:preferred_review => true) }
98
+
99
+ it "should render review" do
100
+ paypal_gateway.provider.should_receive(:details_for).with(token).and_return(details_for_response)
101
+
102
+ get :paypal_confirm, {:order_id => order.number, :payment_method_id => "123", :token => token, :PayerID => "FWRVKNRRZ3WUC" }
103
+
104
+ response.should render_template("shared/paypal_express_confirm")
105
+
106
+ end
107
+ end
108
+
109
+ context "with review and shipping update" do
110
+ before do
111
+ paypal_gateway.stub(:preferred_review => true)
112
+ paypal_gateway.stub(:preferred_no_shipping => false)
113
+
114
+ details_for_response.stub(:params => details_for_response.params.merge({'first_name' => 'Dr.', 'last_name' => 'Evil'}),
115
+ :address => {'address1' => 'Apt. 187', 'address2'=> 'Some Str.', 'city' => 'Chevy Chase', 'country' => 'US', 'zip' => '20815', 'state' => 'MD' })
116
+
117
+ end
118
+
119
+ it "should update ship_address and render review" do
120
+ paypal_gateway.provider.should_receive(:details_for).with(token).and_return(details_for_response)
121
+
122
+ get :paypal_confirm, {:order_id => order.number, :payment_method_id => "123", :token => token, :PayerID => "FWRVKNRRZ3WUC" }
123
+
124
+ order.ship_address.address1.should == "Apt. 187"
125
+ response.should render_template("shared/paypal_express_confirm")
126
+ end
127
+ end
128
+
129
+ context "with un-successful repsonse" do
130
+ before { details_for_response.stub(:success? => false) }
131
+
132
+ it "should log error and redirect to payment step" do
133
+ paypal_gateway.provider.should_receive(:details_for).with(token).and_return(details_for_response)
134
+
135
+ controller.should_receive(:gateway_error).with(details_for_response)
136
+
137
+ get :paypal_confirm, {:order_id => order.number, :payment_method_id => "123", :token => token, :PayerID => "FWRVKNRRZ3WUC" }
138
+
139
+ response.should redirect_to edit_order_checkout_url(order, :state => 'payment')
140
+ end
141
+ end
142
+
143
+ end
144
+
145
+ context "paypal_finish" do
146
+ let(:paypal_account) { stub_model(PaypalAccount, :payer_id => "FWRVKNRRZ3WUC", :email => order.email ) }
147
+ let(:authorize_response) { mock(ActiveMerchant::Billing::PaypalExpressResponse, :success? => true,
148
+ :params => {"payer" => order.user.email, "payer_id" => "FWRVKNRRZ3WUC", "gross_amount" => order_total, "payment_status" => "Pending"},
149
+ :avs_result => "F",
150
+ :to_yaml => "fake") }
151
+
152
+ before do
153
+ PaymentMethod.should_receive(:find).at_least(1).with("123").and_return(paypal_gateway)
154
+ PaypalAccount.should_receive(:find_by_payer_id).with("FWRVKNRRZ3WUC").and_return(paypal_account)
155
+ end
156
+
157
+ context "with auto_capture" do
158
+ before { Spree::Config.set(:auto_capture => true) }
159
+
160
+ it "should capture payment" do
161
+
162
+ paypal_gateway.provider.should_receive(:purchase).with(order_total, anything()).and_return(purchase_response)
163
+
164
+ get :paypal_finish, {:order_id => order.number, :payment_method_id => "123", :token => token, :PayerID => "FWRVKNRRZ3WUC" }
165
+
166
+ response.should redirect_to order_url(order)
167
+
168
+ order.reload
169
+ order.update!
170
+ order.payments.size.should == 1
171
+ order.payment_state.should == "paid"
172
+ end
173
+ end
174
+
175
+ context "with auto_capture and pending(echeck) response" do
176
+ before do
177
+ Spree::Config.set(:auto_capture => true)
178
+ purchase_response.params["payment_status"] = "pending"
179
+ end
180
+
181
+ it "should authorize payment" do
182
+
183
+ paypal_gateway.provider.should_receive(:purchase).with(order_total, anything()).and_return(purchase_response)
184
+
185
+ get :paypal_finish, {:order_id => order.number, :payment_method_id => "123", :token => token, :PayerID => "FWRVKNRRZ3WUC" }
186
+
187
+ response.should redirect_to order_url(order)
188
+
189
+ order.reload
190
+ order.update!
191
+ order.payments.size.should == 1
192
+ order.payment_state.should == "balance_due"
193
+ order.payment.state.should == "pending"
194
+ end
195
+ end
196
+
197
+ context "without auto_capture" do
198
+ before { Spree::Config.set(:auto_capture => false) }
199
+
200
+ it "should authorize payment" do
201
+
202
+ paypal_gateway.provider.should_receive(:authorize).with(order_total, anything()).and_return(authorize_response)
203
+
204
+ get :paypal_finish, {:order_id => order.number, :payment_method_id => "123", :token => token, :PayerID => "FWRVKNRRZ3WUC" }
205
+
206
+ response.should redirect_to order_url(order)
207
+
208
+ order.reload
209
+ order.update!
210
+ order.payments.size.should == 1
211
+ order.payment_state.should == "balance_due"
212
+ order.payment.state.should == "pending"
213
+ end
214
+ end
215
+
216
+ context "with un-successful repsonse" do
217
+ before do
218
+ Spree::Config.set(:auto_capture => true)
219
+ purchase_response.stub(:success? => false)
220
+ end
221
+
222
+ it "should log error and redirect to payment step" do
223
+ paypal_gateway.provider.should_receive(:purchase).with(order_total, anything()).and_return(purchase_response)
224
+
225
+ controller.should_receive(:gateway_error).with(purchase_response)
226
+
227
+ get :paypal_finish, {:order_id => order.number, :payment_method_id => "123", :token => token, :PayerID => "FWRVKNRRZ3WUC" }
228
+
229
+ response.should redirect_to edit_order_checkout_url(order, :state => 'payment')
230
+
231
+ order.reload
232
+ order.update!
233
+ order.payments.size.should == 1
234
+ order.payment_state.should == "failed"
235
+ order.payment.state.should == "failed"
236
+ end
237
+ end
238
+
239
+ end
240
+
241
+ context "order_opts" do
242
+
243
+ it "should return hash containing basic order details" do
244
+ opts = controller.send(:order_opts, order, paypal_gateway.id, 'payment')
245
+
246
+ opts.class.should == Hash
247
+ opts[:money].should == order_total
248
+ opts[:subtotal].should == (order.item_total * 100).to_i
249
+ opts[:order_id].should == order.number
250
+ opts[:custom].should == order.number
251
+ opts[:handling].should == 0
252
+ opts[:shipping].should == (order.ship_total * 100).to_i
253
+
254
+ opts[:return_url].should == paypal_confirm_order_checkout_url(order, :payment_method_id => paypal_gateway.id)
255
+ opts[:cancel_return_url].should == edit_order_url(order)
256
+
257
+ opts[:items].size.should > 0
258
+ opts[:items].size.should == order.line_items.count
259
+ end
260
+
261
+ it "should include credits in returned hash" do
262
+ order_total #need here so variable is set before credit is created.
263
+ order.adjustments.create(:label => "Credit", :amount => -1)
264
+ order.update!
265
+
266
+ opts = controller.send(:order_opts, order, paypal_gateway.id, 'payment')
267
+
268
+ opts.class.should == Hash
269
+ opts[:money].should == order_total - 100
270
+ opts[:subtotal].should == ((order.item_total * 100) + (order.adjustments.select{|c| c.amount < 0}.sum(&:amount) * 100)).to_i
271
+
272
+ opts[:items].size.should == order.line_items.count + 1
273
+ end
274
+
275
+
276
+ end
277
+ end
@@ -0,0 +1,13 @@
1
+ Factory.define :ppx_address do |f|
2
+ f.firstname 'John'
3
+ f.lastname 'Doe'
4
+ f.address1 '10 Lovely Street'
5
+ f.address2 'Northwest'
6
+ f.city "Herndon"
7
+ f.state { |state| state.association(:ppx_state) }
8
+ f.zipcode '20170'
9
+ f.country { |country| country.association(:country) }
10
+ f.phone '123-456-7890'
11
+ f.state_name "maryland"
12
+ f.alternative_phone "123-456-7899"
13
+ end
@@ -0,0 +1,11 @@
1
+ Factory.define(:ppx_order) do |record|
2
+ # associations:
3
+ record.association(:user, :factory => :user)
4
+ record.association(:bill_address, :factory => :address)
5
+ record.association(:shipping_method, :factory => :shipping_method)
6
+ record.ship_address { |ship_address| Factory(:ppx_address, :city => "Chevy Chase", :zipcode => "20815") }
7
+ end
8
+
9
+ Factory.define :ppx_order_with_totals, :parent => :order do |f|
10
+ f.after_create { |order| Factory(:line_item, :order => order) }
11
+ end
@@ -0,0 +1,42 @@
1
+ # This file is copied to ~/spec when you run 'ruby script/generate rspec'
2
+ # from the project root directory.
3
+ ENV["RAILS_ENV"] ||= 'test'
4
+ require File.expand_path("../test_app/config/environment", __FILE__)
5
+ require 'rspec/rails'
6
+
7
+ #include spree's factories
8
+ require 'spree_core/testing_support/factories'
9
+
10
+ # include local factories
11
+ Dir["#{File.dirname(__FILE__)}/factories/**/*.rb"].each do |f|
12
+ fp = File.expand_path(f)
13
+ require fp
14
+ end
15
+
16
+
17
+ RSpec.configure do |config|
18
+ # == Mock Framework
19
+ #
20
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
21
+ #
22
+ # config.mock_with :mocha
23
+ # config.mock_with :flexmock
24
+ # config.mock_with :rr
25
+ config.mock_with :rspec
26
+
27
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
28
+
29
+ #config.include Devise::TestHelpers, :type => :controller
30
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
31
+ # examples within a transaction, comment the following line or assign false
32
+ # instead of true.
33
+ config.use_transactional_fixtures = true
34
+ end
35
+
36
+ Zone.class_eval do
37
+ def self.global
38
+ find_by_name("GlobalZone") || Factory(:global_zone)
39
+ end
40
+ end
41
+
42
+ @configuration ||= AppConfiguration.find_or_create_by_name("Default configuration")
@@ -0,0 +1,36 @@
1
+ source 'http://rubygems.org'
2
+
3
+ group :test do
4
+ gem 'rspec-rails', '= 2.5.0'
5
+ gem 'factory_girl', '= 1.3.3'
6
+ gem 'factory_girl_rails', '= 1.0.1'
7
+ gem 'rcov'
8
+ gem 'shoulda'
9
+ gem 'faker'
10
+ if RUBY_VERSION < "1.9"
11
+ gem "ruby-debug"
12
+ else
13
+ gem "ruby-debug19"
14
+ end
15
+ end
16
+
17
+ group :cucumber do
18
+ gem 'cucumber-rails'
19
+ gem 'database_cleaner', '= 0.6.7'
20
+ gem 'nokogiri'
21
+ gem 'capybara', '= 0.4.1.2'
22
+ gem 'factory_girl', '= 1.3.3'
23
+ gem 'factory_girl_rails', '= 1.0.1'
24
+ gem 'faker'
25
+ gem 'launchy'
26
+
27
+ if RUBY_VERSION < "1.9"
28
+ gem "ruby-debug"
29
+ else
30
+ gem "ruby-debug19"
31
+ end
32
+ end
33
+ gem 'spree_core', :path => '/Users/bestbuy/.rvm/gems/ruby-1.9.2-p0/gems/spree-0.60.0/core'
34
+ gem 'spree_auth', :path => '/Users/bestbuy/.rvm/gems/ruby-1.9.2-p0/gems/spree-0.60.0/auth'
35
+ gem 'spree_payflow', :path => '/Users/bestbuy/Desktop/chad/airblaster/spree_payflow'
36
+ gem "sqlite3-ruby"
@@ -0,0 +1,17 @@
1
+ development:
2
+ adapter: sqlite3
3
+ database: db/cucumber.sqlite3
4
+ pool: 5
5
+ timeout: 5000
6
+
7
+ test:
8
+ adapter: sqlite3
9
+ database: db/test.sqlite3
10
+ pool: 5
11
+ timeout: 5000
12
+
13
+ cucumber:
14
+ adapter: sqlite3
15
+ database: db/cucumber.sqlite3
16
+ pool: 5
17
+ timeout: 5000
@@ -0,0 +1,38 @@
1
+ TestApp::Application.configure do
2
+ # Settings specified here will take precedence over those in config/environment.rb
3
+
4
+ # The test environment is used exclusively to run your application's
5
+ # test suite. You never need to work with it otherwise. Remember that
6
+ # your test database is "scratch space" for the test suite and is wiped
7
+ # and recreated between test runs. Don't rely on the data there!
8
+ config.cache_classes = true
9
+
10
+ # Log error messages when you accidentally call methods on nil.
11
+ config.whiny_nils = true
12
+
13
+ # Show full error reports and disable caching
14
+ config.consider_all_requests_local = true
15
+ config.action_controller.perform_caching = false
16
+
17
+ # Raise exceptions instead of rendering exception templates
18
+ config.action_dispatch.show_exceptions = false
19
+
20
+ # Disable request forgery protection in test environment
21
+ config.action_controller.allow_forgery_protection = false
22
+
23
+ # Tell Action Mailer not to deliver emails to the real world.
24
+ # The :test delivery method accumulates sent emails in the
25
+ # ActionMailer::Base.deliveries array.
26
+ config.action_mailer.delivery_method = :test
27
+
28
+ # Use SQL instead of Active Record's schema dumper when creating the test database.
29
+ # This is necessary if your schema can't be completely dumped by the schema dumper,
30
+ # like if you have constraints or database-specific column types
31
+ # config.active_record.schema_format = :sql
32
+
33
+ # Print deprecation notices to the stderr
34
+ config.active_support.deprecation = :stderr
35
+
36
+ config.action_mailer.default_url_options = { :host => 'testapp.com' }
37
+
38
+ end
@@ -0,0 +1,20 @@
1
+ Gem::Specification.new do |s|
2
+ s.platform = Gem::Platform::RUBY
3
+ s.name = 'spree_payflow'
4
+ s.version = '0.60.0'
5
+ s.summary = 'Spree Commerce extension for PayPal Payflow gateway'
6
+ s.description = 'Spree Commerce extension for PayPal Payflow gateway'
7
+ s.required_ruby_version = '>= 1.8.7'
8
+
9
+ s.author = 'Chad Nantais'
10
+ s.email = 'cnantais@gmail.com'
11
+ s.homepage = 'http://www.zkron.com'
12
+ s.rubyforge_project = 'spree_payflow'
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.require_path = 'lib'
17
+ s.requirements << 'none'
18
+
19
+ s.add_dependency('spree_core', '>= 0.60.0')
20
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spree_payflow
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 60
8
+ - 0
9
+ version: 0.60.0
10
+ platform: ruby
11
+ authors:
12
+ - Chad Nantais
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-07-07 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: spree_core
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ - 60
31
+ - 0
32
+ version: 0.60.0
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description: Spree Commerce extension for PayPal Payflow gateway
36
+ email: cnantais@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - .gitignore
45
+ - Gemfile
46
+ - Gemfile.lock
47
+ - LICENSE
48
+ - README.md
49
+ - Rakefile
50
+ - Versionfile
51
+ - app/models/gateway/payflow.rb
52
+ - config/routes.rb
53
+ - lib/spree_payflow.rb
54
+ - lib/spree_payflow_hooks.rb
55
+ - lib/tasks/install.rake
56
+ - lib/tasks/spree_payflow.rake
57
+ - spec/controllers/checkout_controller_spec.rb
58
+ - spec/factories/address_factory.rb
59
+ - spec/factories/order_factory.rb
60
+ - spec/spec_helper.rb
61
+ - spec/test_app/Gemfile
62
+ - spec/test_app/config/database.yml
63
+ - spec/test_app/config/environments/cucumber.rb
64
+ - spree_payflow.gemspec
65
+ has_rdoc: true
66
+ homepage: http://www.zkron.com
67
+ licenses: []
68
+
69
+ post_install_message:
70
+ rdoc_options: []
71
+
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ segments:
80
+ - 1
81
+ - 8
82
+ - 7
83
+ version: 1.8.7
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ requirements:
93
+ - none
94
+ rubyforge_project: spree_payflow
95
+ rubygems_version: 1.3.7
96
+ signing_key:
97
+ specification_version: 3
98
+ summary: Spree Commerce extension for PayPal Payflow gateway
99
+ test_files:
100
+ - spec/controllers/checkout_controller_spec.rb
101
+ - spec/factories/address_factory.rb
102
+ - spec/factories/order_factory.rb
103
+ - spec/spec_helper.rb
104
+ - spec/test_app/Gemfile
105
+ - spec/test_app/config/database.yml
106
+ - spec/test_app/config/environments/cucumber.rb