stateless-systems-paypal 2.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +22 -0
- data/README +151 -0
- data/Rakefile +126 -0
- data/init.rb +29 -0
- data/lib/helper.rb +315 -0
- data/lib/notification.rb +271 -0
- data/lib/paypal.rb +31 -0
- data/misc/PayPal - Instant Payment Notification - Technical Overview.pdf +0 -0
- data/misc/paypal.psd +0 -0
- data/test/helper_test.rb +197 -0
- data/test/mocks/http_mock.rb +47 -0
- data/test/mocks/method_mock.rb +33 -0
- data/test/notification_test.rb +99 -0
- data/test/remote/remote_test.rb +16 -0
- data/test/sample.ipn.response.txt +1 -0
- metadata +78 -0
data/lib/notification.rb
ADDED
@@ -0,0 +1,271 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Paypal
|
4
|
+
# Parser and handler for incoming Instant payment notifications from paypal.
|
5
|
+
# The Example shows a typical handler in a rails application. Note that this
|
6
|
+
# is an example, please read the Paypal API documentation for all the details
|
7
|
+
# on creating a safe payment controller.
|
8
|
+
#
|
9
|
+
# Example
|
10
|
+
#
|
11
|
+
# class BackendController < ApplicationController
|
12
|
+
#
|
13
|
+
# def paypal_ipn
|
14
|
+
# notify = Paypal::Notification.new(request.raw_post)
|
15
|
+
#
|
16
|
+
# order = Order.find(notify.item_id)
|
17
|
+
#
|
18
|
+
# if notify.acknowledge
|
19
|
+
# begin
|
20
|
+
#
|
21
|
+
# if notify.complete? and order.total == notify.amount and notify.business == 'sales@myshop.com'
|
22
|
+
# order.status = 'success'
|
23
|
+
#
|
24
|
+
# shop.ship(order)
|
25
|
+
# else
|
26
|
+
# logger.error("Failed to verify Paypal's notification, please investigate")
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# rescue => e
|
30
|
+
# order.status = 'failed'
|
31
|
+
# raise
|
32
|
+
# ensure
|
33
|
+
# order.save
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# render :nothing
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
class Notification
|
41
|
+
attr_accessor :params
|
42
|
+
attr_accessor :raw
|
43
|
+
|
44
|
+
# Overwrite this url. It points to the Paypal sandbox by default.
|
45
|
+
# Please note that the Paypal technical overview (doc directory)
|
46
|
+
# speaks of a https:// address for production use. In my tests
|
47
|
+
# this https address does not in fact work.
|
48
|
+
#
|
49
|
+
# Example:
|
50
|
+
# Paypal::Notification.ipn_url = http://www.paypal.com/cgi-bin/webscr
|
51
|
+
#
|
52
|
+
cattr_accessor :ipn_url
|
53
|
+
@@ipn_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr'
|
54
|
+
|
55
|
+
|
56
|
+
# Overwrite this certificate. It contains the Paypal sandbox certificate by default.
|
57
|
+
#
|
58
|
+
# Example:
|
59
|
+
# Paypal::Notification.paypal_cert = File::read("paypal_cert.pem")
|
60
|
+
cattr_accessor :paypal_cert
|
61
|
+
@@paypal_cert = """
|
62
|
+
-----BEGIN CERTIFICATE-----
|
63
|
+
MIIDoTCCAwqgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBmDELMAkGA1UEBhMCVVMx
|
64
|
+
EzARBgNVBAgTCkNhbGlmb3JuaWExETAPBgNVBAcTCFNhbiBKb3NlMRUwEwYDVQQK
|
65
|
+
EwxQYXlQYWwsIEluYy4xFjAUBgNVBAsUDXNhbmRib3hfY2VydHMxFDASBgNVBAMU
|
66
|
+
C3NhbmRib3hfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tMB4XDTA0
|
67
|
+
MDQxOTA3MDI1NFoXDTM1MDQxOTA3MDI1NFowgZgxCzAJBgNVBAYTAlVTMRMwEQYD
|
68
|
+
VQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9zZTEVMBMGA1UEChMMUGF5
|
69
|
+
UGFsLCBJbmMuMRYwFAYDVQQLFA1zYW5kYm94X2NlcnRzMRQwEgYDVQQDFAtzYW5k
|
70
|
+
Ym94X2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTCBnzANBgkqhkiG
|
71
|
+
9w0BAQEFAAOBjQAwgYkCgYEAt5bjv/0N0qN3TiBL+1+L/EjpO1jeqPaJC1fDi+cC
|
72
|
+
6t6tTbQ55Od4poT8xjSzNH5S48iHdZh0C7EqfE1MPCc2coJqCSpDqxmOrO+9QXsj
|
73
|
+
HWAnx6sb6foHHpsPm7WgQyUmDsNwTWT3OGR398ERmBzzcoL5owf3zBSpRP0NlTWo
|
74
|
+
nPMCAwEAAaOB+DCB9TAdBgNVHQ4EFgQUgy4i2asqiC1rp5Ms81Dx8nfVqdIwgcUG
|
75
|
+
A1UdIwSBvTCBuoAUgy4i2asqiC1rp5Ms81Dx8nfVqdKhgZ6kgZswgZgxCzAJBgNV
|
76
|
+
BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9zZTEV
|
77
|
+
MBMGA1UEChMMUGF5UGFsLCBJbmMuMRYwFAYDVQQLFA1zYW5kYm94X2NlcnRzMRQw
|
78
|
+
EgYDVQQDFAtzYW5kYm94X2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNv
|
79
|
+
bYIBADAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAFc288DYGX+GX2+W
|
80
|
+
P/dwdXwficf+rlG+0V9GBPJZYKZJQ069W/ZRkUuWFQ+Opd2yhPpneGezmw3aU222
|
81
|
+
CGrdKhOrBJRRcpoO3FjHHmXWkqgbQqDWdG7S+/l8n1QfDPp+jpULOrcnGEUY41Im
|
82
|
+
jZJTylbJQ1b5PBBjGiP0PpK48cdF
|
83
|
+
-----END CERTIFICATE-----
|
84
|
+
"""
|
85
|
+
|
86
|
+
# Creates a new paypal object. Pass the raw html you got from paypal in.
|
87
|
+
# In a rails application this looks something like this
|
88
|
+
#
|
89
|
+
# def paypal_ipn
|
90
|
+
# paypal = Paypal::Notification.new(request.raw_post)
|
91
|
+
# ...
|
92
|
+
# end
|
93
|
+
def initialize(post)
|
94
|
+
empty!
|
95
|
+
parse(post)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Was the transaction complete?
|
99
|
+
def complete?
|
100
|
+
status == "Completed"
|
101
|
+
end
|
102
|
+
|
103
|
+
def failed?
|
104
|
+
status == "Failed"
|
105
|
+
end
|
106
|
+
|
107
|
+
def denied?
|
108
|
+
status == "Denied"
|
109
|
+
end
|
110
|
+
|
111
|
+
# When was this payment received by the client.
|
112
|
+
# sometimes it can happen that we get the notification much later.
|
113
|
+
# One possible scenario is that our web application was down. In this case paypal tries several
|
114
|
+
# times an hour to inform us about the notification
|
115
|
+
def received_at
|
116
|
+
Time.parse params['payment_date']
|
117
|
+
end
|
118
|
+
|
119
|
+
# Whats the status of this transaction?
|
120
|
+
def status
|
121
|
+
params['payment_status']
|
122
|
+
end
|
123
|
+
|
124
|
+
# Id of this transaction (paypal number)
|
125
|
+
def transaction_id
|
126
|
+
params['txn_id']
|
127
|
+
end
|
128
|
+
|
129
|
+
# What type of transaction are we dealing with?
|
130
|
+
# "cart" "send_money" "web_accept" are possible here.
|
131
|
+
def type
|
132
|
+
params['txn_type']
|
133
|
+
end
|
134
|
+
|
135
|
+
# the money amount we received in X.2 decimal.
|
136
|
+
def gross
|
137
|
+
params['mc_gross']
|
138
|
+
end
|
139
|
+
|
140
|
+
# the markup paypal charges for the transaction
|
141
|
+
def fee
|
142
|
+
params['mc_fee']
|
143
|
+
end
|
144
|
+
|
145
|
+
# What currency have we been dealing with
|
146
|
+
def currency
|
147
|
+
params['mc_currency']
|
148
|
+
end
|
149
|
+
|
150
|
+
# This is the item number which we submitted to paypal
|
151
|
+
def item_id
|
152
|
+
params['item_number']
|
153
|
+
end
|
154
|
+
|
155
|
+
# This is the email address associated to the paypal account that recieved
|
156
|
+
# the payment.
|
157
|
+
def business
|
158
|
+
params['business']
|
159
|
+
end
|
160
|
+
|
161
|
+
# This is the item_name which you passed to paypal
|
162
|
+
def item_name
|
163
|
+
params['item_name']
|
164
|
+
end
|
165
|
+
|
166
|
+
# This is the invocie which you passed to paypal
|
167
|
+
def invoice
|
168
|
+
params['invoice']
|
169
|
+
end
|
170
|
+
|
171
|
+
# This is the invocie which you passed to paypal
|
172
|
+
def test?
|
173
|
+
params['test_ipn'] == '1'
|
174
|
+
end
|
175
|
+
|
176
|
+
# This is the custom field which you passed to paypal
|
177
|
+
def custom
|
178
|
+
params['custom']
|
179
|
+
end
|
180
|
+
|
181
|
+
# Reason for pending status, nil if status is not pending.
|
182
|
+
def pending_reason
|
183
|
+
params['pending_reason']
|
184
|
+
end
|
185
|
+
|
186
|
+
# Reason for reversed status, nil if status is not reversed.
|
187
|
+
def reason_code
|
188
|
+
params['reason_code']
|
189
|
+
end
|
190
|
+
|
191
|
+
# Memo entered by customer if any
|
192
|
+
def memo
|
193
|
+
params['memo']
|
194
|
+
end
|
195
|
+
|
196
|
+
# Well, the payment type.
|
197
|
+
def payment_type
|
198
|
+
params['payment_type']
|
199
|
+
end
|
200
|
+
|
201
|
+
# The exchange rate used if there was a conversion.
|
202
|
+
def exchange_rate
|
203
|
+
params['exchange_rate']
|
204
|
+
end
|
205
|
+
|
206
|
+
def gross_cents
|
207
|
+
(gross.to_f * 100.0).round
|
208
|
+
end
|
209
|
+
|
210
|
+
# This combines the gross and currency and returns a proper Money object.
|
211
|
+
# this requires the money library located at http://dist.leetsoft.com/api/money
|
212
|
+
def amount
|
213
|
+
return Money.new(gross_cents, currency) rescue ArgumentError
|
214
|
+
return Money.new(gross_cents) # maybe you have an own money object which doesn't take a currency?
|
215
|
+
end
|
216
|
+
|
217
|
+
# reset the notification.
|
218
|
+
def empty!
|
219
|
+
@params = Hash.new
|
220
|
+
@raw = ""
|
221
|
+
end
|
222
|
+
|
223
|
+
# Acknowledge the transaction to paypal. This method has to be called after a new
|
224
|
+
# ipn arrives. Paypal will verify that all the information we received are correct and will return a
|
225
|
+
# ok or a fail.
|
226
|
+
#
|
227
|
+
# Example:
|
228
|
+
#
|
229
|
+
# def paypal_ipn
|
230
|
+
# notify = PaypalNotification.new(request.raw_post)
|
231
|
+
#
|
232
|
+
# if notify.acknowledge
|
233
|
+
# ... process order ... if notify.complete?
|
234
|
+
# else
|
235
|
+
# ... log possible hacking attempt ...
|
236
|
+
# end
|
237
|
+
def acknowledge
|
238
|
+
payload = raw
|
239
|
+
|
240
|
+
uri = URI.parse(self.class.ipn_url)
|
241
|
+
request_path = "#{uri.path}?cmd=_notify-validate"
|
242
|
+
|
243
|
+
request = Net::HTTP::Post.new(request_path)
|
244
|
+
request['Content-Length'] = "#{payload.size}"
|
245
|
+
request['User-Agent'] = "paypal-ruby -- http://rubyforge.org/projects/paypal/"
|
246
|
+
|
247
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
248
|
+
|
249
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless @ssl_strict
|
250
|
+
http.use_ssl = true
|
251
|
+
|
252
|
+
request = http.request(request, payload)
|
253
|
+
|
254
|
+
raise StandardError.new("Faulty paypal result: #{request.body}") unless ["VERIFIED", "INVALID"].include?(request.body)
|
255
|
+
|
256
|
+
request.body == "VERIFIED"
|
257
|
+
end
|
258
|
+
|
259
|
+
private
|
260
|
+
|
261
|
+
# Take the posted data and move the relevant data into a hash
|
262
|
+
def parse(post)
|
263
|
+
@raw = post
|
264
|
+
for line in post.split('&')
|
265
|
+
key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten
|
266
|
+
params[key] = CGI.unescape(value)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
end
|
271
|
+
end
|
data/lib/paypal.rb
ADDED
@@ -0,0 +1,31 @@
|
|
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
|
+
require 'cgi'
|
25
|
+
require 'net/http'
|
26
|
+
require 'net/https'
|
27
|
+
require 'active_support'
|
28
|
+
|
29
|
+
|
30
|
+
require File.dirname(__FILE__) + '/notification'
|
31
|
+
require File.dirname(__FILE__) + '/helper'
|
Binary file
|
data/misc/paypal.psd
ADDED
Binary file
|
data/test/helper_test.rb
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'paypal'
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'actionpack' rescue LoadError raise(StandardErrror.new("This test needs ActionPack installed as gem to run"))
|
8
|
+
require 'action_controller'
|
9
|
+
require 'action_view'
|
10
|
+
require 'money'
|
11
|
+
|
12
|
+
|
13
|
+
# Little hack class which pretends to be a active controller
|
14
|
+
class TestController < ActionController::Base
|
15
|
+
allow_forgery_protection
|
16
|
+
include Paypal::Helpers
|
17
|
+
include ActionView::Helpers::TagHelper
|
18
|
+
include ActionView::Helpers::FormHelper
|
19
|
+
include ActionView::Helpers::UrlHelper
|
20
|
+
include ActionView::Helpers::FormTagHelper
|
21
|
+
|
22
|
+
def url_for(options, *parameters_for_method_reference)
|
23
|
+
"http://www.sandbox.paypal.com/cgi-bin/webscr"
|
24
|
+
end
|
25
|
+
|
26
|
+
# Used for testing paypal_form_start using a block (test_paypal_form_start_with_block)
|
27
|
+
def capture(&block)
|
28
|
+
return yield
|
29
|
+
end
|
30
|
+
|
31
|
+
# Used for testing paypal_form_start using a block (test_paypal_form_start_with_block)
|
32
|
+
def concat(one, two)
|
33
|
+
return eval("self", two)+one
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class HelperTest < Test::Unit::TestCase
|
38
|
+
|
39
|
+
|
40
|
+
def assert_inputs(options, text)
|
41
|
+
all = text.scan(/name\=\"(\w+)\"/).flatten
|
42
|
+
|
43
|
+
xor = (options.keys | all) - (options.keys & all)
|
44
|
+
|
45
|
+
# xor
|
46
|
+
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}"
|
47
|
+
|
48
|
+
text.scan(/name\=\"([^"]+).*?value\=\"([^"]+)/) do |key, value|
|
49
|
+
if options.has_key?(key)
|
50
|
+
assert_equal options[key], value, "key #{key} was '#{options[key]}' and not '#{value}' in \n\n#{text}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def setup
|
56
|
+
@helpers = TestController.new
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_paypal_form_start
|
60
|
+
assert_equal %{<form action="http://www.sandbox.paypal.com/cgi-bin/webscr" method="post">}, @helpers.paypal_form_tag
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_paypal_form_start_with_block
|
64
|
+
strTest = "OriginalString"
|
65
|
+
assert_equal %Q(OriginalString<form action="http://www.sandbox.paypal.com/cgi-bin/webscr" method="post">SomeTextHere</form>),
|
66
|
+
strTest.instance_eval(%Q(TestController.new.paypal_form_tag do
|
67
|
+
"SomeTextHere"
|
68
|
+
end))
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_paypal_setup_with_money
|
72
|
+
actual = @helpers.paypal_setup("100", Money.us_dollar(50000), "bob@bigbusiness.com")
|
73
|
+
assert_inputs({ "amount" => "500.00",
|
74
|
+
"business" => "bob@bigbusiness.com",
|
75
|
+
"charset" => "utf-8",
|
76
|
+
"cmd" => "_xclick",
|
77
|
+
"currency_code" => "USD",
|
78
|
+
"item_name" => "Store purchase",
|
79
|
+
"item_number" => "100",
|
80
|
+
"no_note" => "1",
|
81
|
+
"no_shipping" => "1",
|
82
|
+
"quantity" => "1"}, actual)
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_paypal_setup_with_money_and_tax
|
86
|
+
actual = @helpers.paypal_setup("100", Money.us_dollar(50000), "bob@bigbusiness.com", :tax => Money.us_dollar(500))
|
87
|
+
assert_inputs({ "amount" => "500.00",
|
88
|
+
"business" => "bob@bigbusiness.com",
|
89
|
+
"charset" => "utf-8",
|
90
|
+
"cmd" => "_xclick",
|
91
|
+
"currency_code" => "USD",
|
92
|
+
"item_name" => "Store purchase",
|
93
|
+
"item_number" => "100",
|
94
|
+
"no_note" => "1",
|
95
|
+
"no_shipping" => "1",
|
96
|
+
"quantity" => "1",
|
97
|
+
"tax" => "5.00"}, actual)
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_paypal_setup_with_money_and_invoice
|
101
|
+
actual = @helpers.paypal_setup("100", Money.us_dollar(50000), "bob@bigbusiness.com", :invoice => "Cool invoice!")
|
102
|
+
assert_inputs({ "amount" => "500.00",
|
103
|
+
"business" => "bob@bigbusiness.com",
|
104
|
+
"charset" => "utf-8",
|
105
|
+
"cmd" => "_xclick",
|
106
|
+
"currency_code" => "USD",
|
107
|
+
"invoice" => "Cool invoice!",
|
108
|
+
"item_name" => "Store purchase",
|
109
|
+
"item_number" => "100",
|
110
|
+
"no_note" => "1",
|
111
|
+
"no_shipping" => "1",
|
112
|
+
"quantity" => "1"}, actual)
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_paypal_setup_with_money_and_custom
|
116
|
+
actual = @helpers.paypal_setup("100", Money.us_dollar(50000), "bob@bigbusiness.com", :custom => "Custom")
|
117
|
+
assert_inputs({ "amount" => "500.00",
|
118
|
+
"business" => "bob@bigbusiness.com",
|
119
|
+
"charset" => "utf-8",
|
120
|
+
"cmd" => "_xclick",
|
121
|
+
"currency_code" => "USD",
|
122
|
+
"custom" => "Custom",
|
123
|
+
"item_name" => "Store purchase",
|
124
|
+
"item_number" => "100",
|
125
|
+
"no_note" => "1",
|
126
|
+
"no_shipping" => "1",
|
127
|
+
"quantity" => "1",
|
128
|
+
}, actual)
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_paypal_setup_with_float
|
132
|
+
actual = @helpers.paypal_setup("100", 50.00, "bob@bigbusiness.com", :currency => 'CAD')
|
133
|
+
assert_inputs({ "amount" => "50.00",
|
134
|
+
"business" => "bob@bigbusiness.com",
|
135
|
+
"charset" => "utf-8",
|
136
|
+
"cmd" => "_xclick",
|
137
|
+
"currency_code" => "CAD",
|
138
|
+
"item_name" => "Store purchase",
|
139
|
+
"item_number" => "100",
|
140
|
+
"no_note" => "1",
|
141
|
+
"no_shipping" => "1",
|
142
|
+
"quantity" => "1"}, actual)
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_paypal_setup_with_string
|
146
|
+
actual = @helpers.paypal_setup("100", "50.00", "bob@bigbusiness.com", :currency => 'CAD')
|
147
|
+
assert_inputs({ "amount" => "50.00",
|
148
|
+
"business" => "bob@bigbusiness.com",
|
149
|
+
"charset" => "utf-8",
|
150
|
+
"cmd" => "_xclick",
|
151
|
+
"currency_code" => "CAD",
|
152
|
+
"item_name" => "Store purchase",
|
153
|
+
"item_number" => "100",
|
154
|
+
"no_note" => "1",
|
155
|
+
"no_shipping" => "1",
|
156
|
+
"quantity" => "1"}, actual)
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_paypal_setup_options
|
160
|
+
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 )
|
161
|
+
assert_inputs({ "amount" => "1.00",
|
162
|
+
"business" => "bob@bigbusiness.com",
|
163
|
+
"cancel_return" => "http://www.bigbusiness.com",
|
164
|
+
"charset" => "utf-8",
|
165
|
+
"cmd" => "_xclick",
|
166
|
+
"currency_code" => "USD",
|
167
|
+
"item_name" => "MegaBob's shop purchase",
|
168
|
+
"item_number" => "100",
|
169
|
+
"no_note" => "0",
|
170
|
+
"no_shipping" => "0",
|
171
|
+
"notify_url" => "http://www.bigbusiness.com",
|
172
|
+
"quantity" => "1",
|
173
|
+
"return" => "http://www.bigbusiness.com"}, actual )
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_paypal_setup_subscription
|
177
|
+
actual = @helpers.paypal_setup("100", Money.us_dollar(2800), "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, :subscription => { :recurring => true, :period => :monthly, :retry => true })
|
178
|
+
assert_inputs({ "a3" => "28.00",
|
179
|
+
"business" => "bob@bigbusiness.com",
|
180
|
+
"cancel_return" => "http://www.bigbusiness.com",
|
181
|
+
"charset" => "utf-8",
|
182
|
+
"cmd" => "_ext-enter",
|
183
|
+
"redirect_cmd" => "_xclick-subscriptions",
|
184
|
+
"currency_code" => "USD",
|
185
|
+
"item_name" => "MegaBob's shop purchase",
|
186
|
+
"item_number" => "100",
|
187
|
+
"no_note" => "0",
|
188
|
+
"no_shipping" => "0",
|
189
|
+
"notify_url" => "http://www.bigbusiness.com",
|
190
|
+
"quantity" => "1",
|
191
|
+
"src" => "1",
|
192
|
+
"sra" => "1",
|
193
|
+
"t3" => "M",
|
194
|
+
"return" => "http://www.bigbusiness.com"}, actual )
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|