paypal 1.8.0 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +6 -11
- data/Rakefile +11 -10
- data/init.rb +29 -0
- data/lib/notification.rb +2 -0
- data/test/helper_test.rb +154 -0
- data/test/mocks/method_mock.rb +33 -0
- data/test/notification_test.rb +83 -0
- data/test/remote/remote_test.rb +16 -0
- metadata +9 -2
data/README
CHANGED
@@ -17,18 +17,10 @@ business account and tell paypal where to send the IPN ( Instant payment notific
|
|
17
17
|
|
18
18
|
== Installation
|
19
19
|
|
20
|
-
1)
|
21
|
-
|
22
|
-
|
23
|
-
2) Create a new controller which handels the paypal related tasks.
|
24
|
-
script/generate controller payment
|
25
|
-
|
26
|
-
3) Add the Paypal::Helpers to the newly created controller.
|
27
|
-
module PaymentHelper
|
28
|
-
include Paypal::Helpers
|
29
|
-
end
|
20
|
+
1) Install the plugin using ./script/plugin install svn://vault.jadedpixel.com/paypal/trunk/paypal
|
21
|
+
|
30
22
|
|
31
|
-
|
23
|
+
2) Create a paypal_ipn ( or similar ) action like the one in the "Example rails controller" appendix.
|
32
24
|
|
33
25
|
Within the new payment controller you can now create pages from which users can be sent to paypal. You always
|
34
26
|
have to sent users to paypal using a HTTP Post so a standard link won't work (well OK but you need some javascript for that). The +Paypal::Helper+ namespace has some examples of how such a forward page may look.
|
@@ -103,6 +95,9 @@ uninitalized constant Paypal - Make sure your ruby has openssl support
|
|
103
95
|
|
104
96
|
== Changelog
|
105
97
|
|
98
|
+
2006-04-20 -- 1.7.0
|
99
|
+
* Now a rails plugin
|
100
|
+
|
106
101
|
2006-02-10 -- 1.5.1
|
107
102
|
* added complete list of valid paypal options (Paul Hart)
|
108
103
|
|
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ require 'rake/rdoctask'
|
|
5
5
|
require 'rake/gempackagetask'
|
6
6
|
require 'rake/contrib/rubyforgepublisher'
|
7
7
|
|
8
|
-
PKG_VERSION = "1.
|
8
|
+
PKG_VERSION = "1.9.0"
|
9
9
|
PKG_NAME = "paypal"
|
10
10
|
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
11
11
|
|
@@ -49,7 +49,6 @@ end
|
|
49
49
|
Rake::RDocTask.new { |rdoc|
|
50
50
|
rdoc.rdoc_dir = 'doc'
|
51
51
|
rdoc.title = "Paypal library"
|
52
|
-
rdoc.options << '--line-numbers --inline-source'
|
53
52
|
rdoc.rdoc_files.include('README')
|
54
53
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
55
54
|
}
|
@@ -89,8 +88,8 @@ spec = Gem::Specification.new do |s|
|
|
89
88
|
s.description = s.summary = "Paypal IPN integration library for rails and other web applications"
|
90
89
|
s.has_rdoc = true
|
91
90
|
|
92
|
-
s.files = %w(README Rakefile MIT-LICENSE) + Dir['lib/**/*'] + Dir['misc
|
93
|
-
|
91
|
+
s.files = %w(init.rb README Rakefile MIT-LICENSE) + Dir['lib/**/*'] + Dir['misc/**/*'] + Dir['test/**/*']
|
92
|
+
s.files.reject! { |f| /\/\.\_/ }
|
94
93
|
s.require_path = 'lib'
|
95
94
|
s.autorequire = 'paypal'
|
96
95
|
s.author = "Tobias Luetke"
|
@@ -114,12 +113,14 @@ RUBY_FORGE_USER = 'xal'
|
|
114
113
|
RELEASE_NAME = "REL #{PKG_VERSION}"
|
115
114
|
|
116
115
|
desc "Publish the release files to RubyForge."
|
117
|
-
task :release => [:
|
116
|
+
task :release => [:publish] do
|
118
117
|
`rubyforge login`
|
118
|
+
release_command = "rubyforge add_release #{PKG_NAME} #{PKG_NAME} 'REL #{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.gem"
|
119
|
+
puts release_command
|
120
|
+
system(release_command)
|
121
|
+
|
122
|
+
release_command = "rubyforge add_release #{PKG_NAME} #{PKG_NAME} 'REL #{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.zip"
|
123
|
+
puts release_command
|
124
|
+
system(release_command)
|
119
125
|
|
120
|
-
for ext in %w( gem tgz zip )
|
121
|
-
release_command = "rubyforge add_release #{PKG_NAME} #{PKG_NAME} 'REL #{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}"
|
122
|
-
puts release_command
|
123
|
-
system(release_command)
|
124
|
-
end
|
125
126
|
end
|
data/init.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2005 Tobias Luetke
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
|
25
|
+
# Please note: Paypal is by default in *production* mode.
|
26
|
+
# During development you will want to add
|
27
|
+
#
|
28
|
+
|
29
|
+
ActionView::Base.send(:include, Paypal::Helpers)
|
data/lib/notification.rb
CHANGED
data/test/helper_test.rb
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'paypal'
|
5
|
+
|
6
|
+
require_gem 'money'
|
7
|
+
require_gem 'actionpack' rescue LoadError raise(StandardErrror.new("This test needs ActionPack installed as gem to run"))
|
8
|
+
|
9
|
+
|
10
|
+
# Little hack class which pretends to be a active controller
|
11
|
+
class TestController
|
12
|
+
include Paypal::Helpers
|
13
|
+
include ActionView::Helpers::TagHelper
|
14
|
+
include ActionView::Helpers::FormHelper
|
15
|
+
include ActionView::Helpers::UrlHelper
|
16
|
+
include ActionView::Helpers::FormTagHelper
|
17
|
+
|
18
|
+
def url_for(options, *parameters_for_method_reference)
|
19
|
+
"http://www.sandbox.paypal.com/cgi-bin/webscr"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class HelperTest < Test::Unit::TestCase
|
24
|
+
|
25
|
+
|
26
|
+
def assert_inputs(options, text)
|
27
|
+
all = text.scan(/name\=\"(\w+)\"/).flatten
|
28
|
+
|
29
|
+
xor = (options.keys | all) - (options.keys & all)
|
30
|
+
|
31
|
+
# xor
|
32
|
+
assert_equal [], xor, "options do not match expectations does not have keys #{xor.inspect} only appear in one of both sides in \n\n#{text}"
|
33
|
+
|
34
|
+
text.scan(/name\=\"([^"]+).*?value\=\"([^"]+)/) do |key, value|
|
35
|
+
if options.has_key?(key)
|
36
|
+
assert_equal options[key], value, "key #{key} was '#{options[key]}' and not '#{value}' in \n\n#{text}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def setup
|
42
|
+
@helpers = TestController.new
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_paypal_form_start
|
46
|
+
assert_equal %{<form action="http://www.sandbox.paypal.com/cgi-bin/webscr" method="post">}, @helpers.paypal_form_tag
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_paypal_setup_with_money
|
50
|
+
actual = @helpers.paypal_setup("100", Money.us_dollar(50000), "bob@bigbusiness.com")
|
51
|
+
assert_inputs({ "amount" => "500.00",
|
52
|
+
"business" => "bob@bigbusiness.com",
|
53
|
+
"charset" => "utf-8",
|
54
|
+
"cmd" => "_xclick",
|
55
|
+
"currency_code" => "USD",
|
56
|
+
"item_name" => "Store purchase",
|
57
|
+
"item_number" => "100",
|
58
|
+
"no_note" => "1",
|
59
|
+
"no_shipping" => "1",
|
60
|
+
"quantity" => "1"}, actual)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_paypal_setup_with_money_and_tax
|
64
|
+
actual = @helpers.paypal_setup("100", Money.us_dollar(50000), "bob@bigbusiness.com", :tax => Money.us_dollar(500))
|
65
|
+
assert_inputs({ "amount" => "500.00",
|
66
|
+
"business" => "bob@bigbusiness.com",
|
67
|
+
"charset" => "utf-8",
|
68
|
+
"cmd" => "_xclick",
|
69
|
+
"currency_code" => "USD",
|
70
|
+
"item_name" => "Store purchase",
|
71
|
+
"item_number" => "100",
|
72
|
+
"no_note" => "1",
|
73
|
+
"no_shipping" => "1",
|
74
|
+
"quantity" => "1",
|
75
|
+
"tax" => "5.00"}, actual)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_paypal_setup_with_money_and_invoice
|
79
|
+
actual = @helpers.paypal_setup("100", Money.us_dollar(50000), "bob@bigbusiness.com", :invoice => "Cool invoice!")
|
80
|
+
assert_inputs({ "amount" => "500.00",
|
81
|
+
"business" => "bob@bigbusiness.com",
|
82
|
+
"charset" => "utf-8",
|
83
|
+
"cmd" => "_xclick",
|
84
|
+
"currency_code" => "USD",
|
85
|
+
"invoice" => "Cool invoice!",
|
86
|
+
"item_name" => "Store purchase",
|
87
|
+
"item_number" => "100",
|
88
|
+
"no_note" => "1",
|
89
|
+
"no_shipping" => "1",
|
90
|
+
"quantity" => "1"}, actual)
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_paypal_setup_with_money_and_custom
|
94
|
+
actual = @helpers.paypal_setup("100", Money.us_dollar(50000), "bob@bigbusiness.com", :custom => "Custom")
|
95
|
+
assert_inputs({ "amount" => "500.00",
|
96
|
+
"business" => "bob@bigbusiness.com",
|
97
|
+
"charset" => "utf-8",
|
98
|
+
"cmd" => "_xclick",
|
99
|
+
"currency_code" => "USD",
|
100
|
+
"custom" => "Custom",
|
101
|
+
"item_name" => "Store purchase",
|
102
|
+
"item_number" => "100",
|
103
|
+
"no_note" => "1",
|
104
|
+
"no_shipping" => "1",
|
105
|
+
"quantity" => "1"}, actual)
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_paypal_setup_with_float
|
109
|
+
actual = @helpers.paypal_setup("100", 50.00, "bob@bigbusiness.com", :currency => 'CAD')
|
110
|
+
assert_inputs({ "amount" => "50.00",
|
111
|
+
"business" => "bob@bigbusiness.com",
|
112
|
+
"charset" => "utf-8",
|
113
|
+
"cmd" => "_xclick",
|
114
|
+
"currency_code" => "CAD",
|
115
|
+
"item_name" => "Store purchase",
|
116
|
+
"item_number" => "100",
|
117
|
+
"no_note" => "1",
|
118
|
+
"no_shipping" => "1",
|
119
|
+
"quantity" => "1"}, actual)
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_paypal_setup_with_string
|
123
|
+
actual = @helpers.paypal_setup("100", "50.00", "bob@bigbusiness.com", :currency => 'CAD')
|
124
|
+
assert_inputs({ "amount" => "50.00",
|
125
|
+
"business" => "bob@bigbusiness.com",
|
126
|
+
"charset" => "utf-8",
|
127
|
+
"cmd" => "_xclick",
|
128
|
+
"currency_code" => "CAD",
|
129
|
+
"item_name" => "Store purchase",
|
130
|
+
"item_number" => "100",
|
131
|
+
"no_note" => "1",
|
132
|
+
"no_shipping" => "1",
|
133
|
+
"quantity" => "1"}, actual)
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_paypal_setup_options
|
137
|
+
actual = @helpers.paypal_setup("100", Money.us_dollar(100), "bob@bigbusiness.com", :item_name => "MegaBob's shop purchase", :return => 'http://www.bigbusiness.com', :cancel_return => 'http://www.bigbusiness.com', :notify_url => 'http://www.bigbusiness.com', :no_shipping => 0, :no_note => 0 )
|
138
|
+
assert_inputs({ "amount" => "1.00",
|
139
|
+
"business" => "bob@bigbusiness.com",
|
140
|
+
"cancel_return" => "http://www.bigbusiness.com",
|
141
|
+
"charset" => "utf-8",
|
142
|
+
"cmd" => "_xclick",
|
143
|
+
"currency_code" => "USD",
|
144
|
+
"item_name" => "MegaBob's shop purchase",
|
145
|
+
"item_number" => "100",
|
146
|
+
"no_note" => "0",
|
147
|
+
"no_shipping" => "0",
|
148
|
+
"notify_url" => "http://www.bigbusiness.com",
|
149
|
+
"quantity" => "1",
|
150
|
+
"return" => "http://www.bigbusiness.com"}, actual )
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Module
|
2
|
+
def mock_methods(mock_methods)
|
3
|
+
raise "mock methods needs a block" unless block_given?
|
4
|
+
|
5
|
+
original = self
|
6
|
+
namespace = original.name.split("::")
|
7
|
+
class_name = namespace.last
|
8
|
+
|
9
|
+
mod = namespace[0..-2].inject(Object) { |mod, part| mod.const_get(part) }
|
10
|
+
|
11
|
+
klass = (original.is_a?(Class) ? Class : Module).new(self) do
|
12
|
+
|
13
|
+
instance_eval do
|
14
|
+
mock_methods.each do |method, proc|
|
15
|
+
define_method("mocked_#{method}", &proc)
|
16
|
+
alias_method method, "mocked_#{method}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
begin
|
23
|
+
mod.send(:remove_const, class_name)
|
24
|
+
mod.const_set(class_name, klass)
|
25
|
+
|
26
|
+
yield
|
27
|
+
ensure
|
28
|
+
mod.send(:remove_const, class_name)
|
29
|
+
mod.const_set(class_name, original)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
|
+
|
3
|
+
require 'openssl'
|
4
|
+
require 'net/http'
|
5
|
+
require File.dirname(__FILE__) + '/mocks/method_mock'
|
6
|
+
require 'test/unit'
|
7
|
+
require 'paypal'
|
8
|
+
|
9
|
+
$paypal_success = Class.new do
|
10
|
+
def body; "VERIFIED"; end
|
11
|
+
end
|
12
|
+
|
13
|
+
$paypal_failure = Class.new do
|
14
|
+
def body; "INVALID"; end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
class NotificationTest < Test::Unit::TestCase
|
19
|
+
|
20
|
+
def setup
|
21
|
+
Paypal::Notification.ipn_url = "http://www.paypal.com/some/address"
|
22
|
+
|
23
|
+
@paypal = Paypal::Notification.new(http_raw_data)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_raw
|
27
|
+
assert_equal http_raw_data, @paypal.raw
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_parse
|
31
|
+
@paypal = Paypal::Notification.new(http_raw_data)
|
32
|
+
assert_equal "500.00", @paypal.params['mc_gross']
|
33
|
+
assert_equal "confirmed", @paypal.params['address_status']
|
34
|
+
assert_equal "EVMXCLDZJV77Q", @paypal.params['payer_id']
|
35
|
+
assert_equal "Completed", @paypal.params['payment_status']
|
36
|
+
assert_equal CGI.unescape("15%3A23%3A54+Apr+15%2C+2005+PDT"), @paypal.params['payment_date']
|
37
|
+
# ...
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_accessors
|
41
|
+
assert @paypal.complete?
|
42
|
+
assert_equal "Completed", @paypal.status
|
43
|
+
assert_equal "6G996328CK404320L", @paypal.transaction_id
|
44
|
+
assert_equal "web_accept", @paypal.type
|
45
|
+
assert_equal "500.00", @paypal.gross
|
46
|
+
assert_equal "15.05", @paypal.fee
|
47
|
+
assert_equal "CAD", @paypal.currency
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_compositions
|
51
|
+
assert_equal Money.ca_dollar(50000), @paypal.amount
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_acknowledgement
|
55
|
+
|
56
|
+
|
57
|
+
Net::HTTP.mock_methods( :request => Proc.new { |r, b| $paypal_success.new } ) do
|
58
|
+
assert @paypal.acknowledge
|
59
|
+
end
|
60
|
+
|
61
|
+
Net::HTTP.mock_methods( :request => Proc.new { |r, b| $paypal_failure.new } ) do
|
62
|
+
assert !@paypal.acknowledge
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_send_acknowledgement
|
68
|
+
request, body = nil
|
69
|
+
|
70
|
+
Net::HTTP.mock_methods( :request => Proc.new { |r, b| request = r; body = b; $paypal_success.new } ) do
|
71
|
+
assert @paypal.acknowledge
|
72
|
+
end
|
73
|
+
|
74
|
+
assert_equal '/some/address?cmd=_notify-validate', request.path
|
75
|
+
assert_equal http_raw_data, body
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def http_raw_data
|
81
|
+
"mc_gross=500.00&address_status=confirmed&payer_id=EVMXCLDZJV77Q&tax=0.00&address_street=164+Waverley+Street&payment_date=15%3A23%3A54+Apr+15%2C+2005+PDT&payment_status=Completed&address_zip=K2P0V6&first_name=Tobias&mc_fee=15.05&address_country_code=CA&address_name=Tobias+Luetke¬ify_version=1.7&custom=&payer_status=unverified&business=tobi%40leetsoft.com&address_country=Canada&address_city=Ottawa&quantity=1&payer_email=tobi%40snowdevil.ca&verify_sign=AEt48rmhLYtkZ9VzOGAtwL7rTGxUAoLNsuf7UewmX7UGvcyC3wfUmzJP&txn_id=6G996328CK404320L&payment_type=instant&last_name=Luetke&address_state=Ontario&receiver_email=tobi%40leetsoft.com&payment_fee=&receiver_id=UQ8PDYXJZQD9Y&txn_type=web_accept&item_name=Store+Purchase&mc_currency=CAD&item_number=&test_ipn=1&payment_gross=&shipping=0.00"
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + '/../../lib')
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'paypal'
|
5
|
+
|
6
|
+
class RemoteTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def test_raw
|
9
|
+
Paypal::Notification.ipn_url = "https://www.sandbox.paypal.com/cgi-bin/webscr"
|
10
|
+
@paypal = Paypal::Notification.new('')
|
11
|
+
|
12
|
+
assert_nothing_raised do
|
13
|
+
assert_equal false, @paypal.acknowledge
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: paypal
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.
|
7
|
-
date: 2006-04-
|
6
|
+
version: 1.9.0
|
7
|
+
date: 2006-04-29 00:00:00 -04:00
|
8
8
|
summary: Paypal IPN integration library for rails and other web applications
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -28,6 +28,7 @@ cert_chain:
|
|
28
28
|
authors:
|
29
29
|
- Tobias Luetke
|
30
30
|
files:
|
31
|
+
- init.rb
|
31
32
|
- README
|
32
33
|
- Rakefile
|
33
34
|
- MIT-LICENSE
|
@@ -36,6 +37,12 @@ files:
|
|
36
37
|
- lib/paypal.rb
|
37
38
|
- misc/PayPal - Instant Payment Notification - Technical Overview.pdf
|
38
39
|
- misc/paypal.psd
|
40
|
+
- test/helper_test.rb
|
41
|
+
- test/mocks
|
42
|
+
- test/notification_test.rb
|
43
|
+
- test/remote
|
44
|
+
- test/mocks/method_mock.rb
|
45
|
+
- test/remote/remote_test.rb
|
39
46
|
test_files: []
|
40
47
|
|
41
48
|
rdoc_options: []
|