astrails-paypal_adaptive 0.1.1
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/LICENSE +20 -0
- data/README.markdown +107 -0
- data/Rakefile +55 -0
- data/VERSION +1 -0
- data/astrails-paypal_adaptive.gemspec +78 -0
- data/config/paypal_adaptive.yml +22 -0
- data/lib/config.rb +58 -0
- data/lib/ipn_notification.rb +32 -0
- data/lib/pay_request_schema.json +39 -0
- data/lib/paypal_adaptive.rb +4 -0
- data/lib/request.rb +95 -0
- data/lib/response.rb +38 -0
- data/templates/paypal_ipn.rb +25 -0
- data/test/create_account_test.rb +30 -0
- data/test/data/invalid_chain_pay_request.json +13 -0
- data/test/data/invalid_parallel_pay_request.json +13 -0
- data/test/data/invalid_preapproval.json +12 -0
- data/test/data/invalid_simple_pay_request_1.json +8 -0
- data/test/data/valid_chain_pay_request.json +12 -0
- data/test/data/valid_create_account_request.json +22 -0
- data/test/data/valid_parallel_pay_request.json +14 -0
- data/test/data/valid_preapproval.json +9 -0
- data/test/data/valid_simple_pay_request_1.json +9 -0
- data/test/helper.rb +16 -0
- data/test/pay_request_schema_test.rb +44 -0
- data/test/pay_request_test.rb +85 -0
- data/test/payment_details_test.rb +28 -0
- data/test/preapproval_test.rb +64 -0
- metadata +129 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Tommy Chheng
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# paypal_adaptive
|
2
|
+
This gem is a lightweight wrapper for the paypal adaptive payments API.
|
3
|
+
|
4
|
+
This is very much a work in progress! Use at your own risk or submit bug fixes :)
|
5
|
+
|
6
|
+
Before you need start, read the API manual https://www.x.com/docs/DOC-1531 and check out the forums on http://x.com
|
7
|
+
It'll be invaluable for parameters and error messages. The gem keeps the request/response as hashes so you will have to
|
8
|
+
read the manual to make the proper calls. I made a few test cases for further examples at http://github.com/tc/paypal_adaptive/tree/master/test/
|
9
|
+
|
10
|
+
## Changes to the Lottay Version
|
11
|
+
This branch adds support for PayPal Adaptive Accounts. An Adaptive Accounts request looks very similar to the Pay Request.
|
12
|
+
You simply post a hash of signup parameters to PayPal using the "create_account" method, and receive a URL to which you redirect the user to finish signup.
|
13
|
+
|
14
|
+
See the unit tests in "create_account_test.rb" for a good example.
|
15
|
+
|
16
|
+
###Installation Instructions
|
17
|
+
Install the gem:
|
18
|
+
sudo gem install lottay-paypal_adaptive --source http://gemcutter.org
|
19
|
+
In environment.rb:
|
20
|
+
require 'paypal_adaptive'
|
21
|
+
|
22
|
+
## HOWTO
|
23
|
+
Create paypal_adaptive.yml to your config folder:
|
24
|
+
development:
|
25
|
+
environment: "sandbox"
|
26
|
+
username: "sandbox_username"
|
27
|
+
password: "sandbox_password"
|
28
|
+
signature: "sandbox_signature"
|
29
|
+
application_id: "sandbox_app_id"
|
30
|
+
sandbox_email: "paypal_account_email_with_your_sandbox_account"
|
31
|
+
|
32
|
+
test:
|
33
|
+
environment: "sandbox"
|
34
|
+
username: "sandbox_username"
|
35
|
+
password: "sandbox_password"
|
36
|
+
signature: "sandbox_signature"
|
37
|
+
application_id: "sandbox_app_id"
|
38
|
+
sandbox_email: "paypal_account_email_with_your_sandbox_account"
|
39
|
+
|
40
|
+
production:
|
41
|
+
environment: "production"
|
42
|
+
username: "my_production_username"
|
43
|
+
password: "my_production_password"
|
44
|
+
signature: "my_production_signature"
|
45
|
+
application_id: "my_production_app_id"
|
46
|
+
|
47
|
+
Make the payment request:
|
48
|
+
|
49
|
+
pay_request = PaypalAdaptive::Request.new
|
50
|
+
|
51
|
+
data = {
|
52
|
+
"returnUrl" => "http://testserver.com/payments/completed_payment_request",
|
53
|
+
"requestEnvelope" => {"errorLanguage" => "en_US"},
|
54
|
+
"currencyCode"=>"USD",
|
55
|
+
"receiverList"=>{"receiver"=>[{"email"=>"testpp_1261697850_per@nextsprocket.com", "amount"=>"10.00"}]},
|
56
|
+
"cancelUrl"=>"http://testserver.com/payments/canceled_payment_request",
|
57
|
+
"actionType"=>"PAY",
|
58
|
+
"ipnNotificationUrl"=>"http://testserver.com/payments/ipn_notification"
|
59
|
+
}
|
60
|
+
|
61
|
+
pay_response = pay_request.pay(data)
|
62
|
+
|
63
|
+
if pay_response.success?
|
64
|
+
redirect_to pay_response.approve_paypal_payment_url
|
65
|
+
else
|
66
|
+
puts pay_response.errors.first['message']
|
67
|
+
redirect_to failed_payment_url
|
68
|
+
end
|
69
|
+
|
70
|
+
---
|
71
|
+
Once the user goes to pay_response.approve_paypal_payment_url, they will be prompted to login to Paypal for payment.
|
72
|
+
|
73
|
+
Upon payment completion page, they will be redirected to http://testserver.com/payments/completed_payment_request.
|
74
|
+
|
75
|
+
They can also click cancel to go to http://testserver.com/payments/canceled_payment_request
|
76
|
+
|
77
|
+
The actual payment details will be sent to your server via "ipnNotificationUrl"
|
78
|
+
You have to create a listener to receive POST messages from paypal. I added a Rails metal template in the templates folder which handles the callback.
|
79
|
+
|
80
|
+
Additionally, you can make calls to Paypal Adaptive's other APIs:
|
81
|
+
payment_details, preapproval, preapproval_details, cancel_preapproval, convert_currency, refund
|
82
|
+
|
83
|
+
Input is just a Hash just like the pay method. Refer to the Paypal manual for more details.
|
84
|
+
|
85
|
+
## Changelog
|
86
|
+
0.1.0
|
87
|
+
Fixed IPN rails metal template by sending the correct params back: ipn.send_back(env['rack.request.form_vars'])
|
88
|
+
Thanks to github.com/JoN1oP for fixing this.
|
89
|
+
|
90
|
+
0.0.5
|
91
|
+
Added Preapproval preapproval_paypal_payment_url along with test case.
|
92
|
+
|
93
|
+
0.0.4
|
94
|
+
Preapproval now returns a PaypalAdaptive::Response class. Added preapproval test cases.
|
95
|
+
|
96
|
+
0.0.3
|
97
|
+
Renamed PayRequest, PayResponse into Request, Response since other api calls use the class as well.
|
98
|
+
|
99
|
+
0.0.2
|
100
|
+
Fixed initialized constant warning.
|
101
|
+
|
102
|
+
0.0.1
|
103
|
+
First release.
|
104
|
+
|
105
|
+
## Copyright
|
106
|
+
|
107
|
+
Copyright (c) 2009 Tommy Chheng. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |gem|
|
8
|
+
gem.name = "astrails-paypal_adaptive"
|
9
|
+
gem.summary = %Q{initial import}
|
10
|
+
gem.description = %Q{Lightweight wrapper for Paypal's Adaptive Payments API.}
|
11
|
+
gem.email = "boris@astrails.com"
|
12
|
+
gem.homepage = "http://github.com/astrails/paypal_adaptive"
|
13
|
+
gem.authors = ["Tommy Chheng", "Ross Hale", "Boris Nadion"]
|
14
|
+
gem.add_development_dependency "json", ">= 0"
|
15
|
+
gem.add_development_dependency "jsonschema", ">= 0"
|
16
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
|
+
end
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'rake/testtask'
|
24
|
+
Rake::TestTask.new(:test) do |test|
|
25
|
+
test.libs << 'lib' << 'test'
|
26
|
+
test.pattern = 'test/**/*_test.rb'
|
27
|
+
test.verbose = true
|
28
|
+
end
|
29
|
+
|
30
|
+
begin
|
31
|
+
require 'rcov/rcovtask'
|
32
|
+
Rcov::RcovTask.new do |test|
|
33
|
+
test.libs << 'test'
|
34
|
+
test.pattern = 'test/**/*_test.rb'
|
35
|
+
test.verbose = true
|
36
|
+
end
|
37
|
+
rescue LoadError
|
38
|
+
task :rcov do
|
39
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
task :test => :check_dependencies
|
44
|
+
|
45
|
+
task :default => :test
|
46
|
+
|
47
|
+
require 'rake/rdoctask'
|
48
|
+
Rake::RDocTask.new do |rdoc|
|
49
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
50
|
+
|
51
|
+
rdoc.rdoc_dir = 'rdoc'
|
52
|
+
rdoc.title = "lottay-paypal_adaptive #{version}"
|
53
|
+
rdoc.rdoc_files.include('README*')
|
54
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
55
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{astrails-paypal_adaptive}
|
8
|
+
s.version = "0.1.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Tommy Chheng", "Ross Hale", "Boris Nadion"]
|
12
|
+
s.date = %q{2011-02-09}
|
13
|
+
s.description = %q{Lightweight wrapper for Paypal's Adaptive Payments API.}
|
14
|
+
s.email = %q{boris@astrails.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.markdown"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
"LICENSE",
|
21
|
+
"README.markdown",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION",
|
24
|
+
"astrails-paypal_adaptive.gemspec",
|
25
|
+
"config/paypal_adaptive.yml",
|
26
|
+
"lib/config.rb",
|
27
|
+
"lib/ipn_notification.rb",
|
28
|
+
"lib/pay_request_schema.json",
|
29
|
+
"lib/paypal_adaptive.rb",
|
30
|
+
"lib/request.rb",
|
31
|
+
"lib/response.rb",
|
32
|
+
"templates/paypal_ipn.rb",
|
33
|
+
"test/create_account_test.rb",
|
34
|
+
"test/data/invalid_chain_pay_request.json",
|
35
|
+
"test/data/invalid_parallel_pay_request.json",
|
36
|
+
"test/data/invalid_preapproval.json",
|
37
|
+
"test/data/invalid_simple_pay_request_1.json",
|
38
|
+
"test/data/valid_chain_pay_request.json",
|
39
|
+
"test/data/valid_create_account_request.json",
|
40
|
+
"test/data/valid_parallel_pay_request.json",
|
41
|
+
"test/data/valid_preapproval.json",
|
42
|
+
"test/data/valid_simple_pay_request_1.json",
|
43
|
+
"test/helper.rb",
|
44
|
+
"test/pay_request_schema_test.rb",
|
45
|
+
"test/pay_request_test.rb",
|
46
|
+
"test/payment_details_test.rb",
|
47
|
+
"test/preapproval_test.rb"
|
48
|
+
]
|
49
|
+
s.homepage = %q{http://github.com/astrails/paypal_adaptive}
|
50
|
+
s.require_paths = ["lib"]
|
51
|
+
s.rubygems_version = %q{1.3.7}
|
52
|
+
s.summary = %q{initial import}
|
53
|
+
s.test_files = [
|
54
|
+
"test/create_account_test.rb",
|
55
|
+
"test/helper.rb",
|
56
|
+
"test/pay_request_schema_test.rb",
|
57
|
+
"test/pay_request_test.rb",
|
58
|
+
"test/payment_details_test.rb",
|
59
|
+
"test/preapproval_test.rb"
|
60
|
+
]
|
61
|
+
|
62
|
+
if s.respond_to? :specification_version then
|
63
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
64
|
+
s.specification_version = 3
|
65
|
+
|
66
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
67
|
+
s.add_development_dependency(%q<json>, [">= 0"])
|
68
|
+
s.add_development_dependency(%q<jsonschema>, [">= 0"])
|
69
|
+
else
|
70
|
+
s.add_dependency(%q<json>, [">= 0"])
|
71
|
+
s.add_dependency(%q<jsonschema>, [">= 0"])
|
72
|
+
end
|
73
|
+
else
|
74
|
+
s.add_dependency(%q<json>, [">= 0"])
|
75
|
+
s.add_dependency(%q<jsonschema>, [">= 0"])
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
test:
|
2
|
+
environment: "sandbox"
|
3
|
+
username: "andy_1246488382_biz_api1.lottay.com"
|
4
|
+
password: "1246488389"
|
5
|
+
signature: "AHCkey.eVc0sNgG3SP.iiLKXx5EmALu43DmEPM6wmWg.snEFzyBrSfE2"
|
6
|
+
application_id: "APP-80W284485P519543T"
|
7
|
+
sandbox_email: "andy@lottay.com"
|
8
|
+
|
9
|
+
development:
|
10
|
+
environment: "sandbox"
|
11
|
+
username: "signupforuseratsandboxpaypal"
|
12
|
+
password: "signupforuseratsandboxpaypal"
|
13
|
+
signature: "signupforuseratsandboxpaypal"
|
14
|
+
application_id: "APP-TEST"
|
15
|
+
sandbox_email: "paypal_sandbox_email"
|
16
|
+
|
17
|
+
production:
|
18
|
+
environment: "production"
|
19
|
+
username: "my_production_username"
|
20
|
+
password: "my_production_password"
|
21
|
+
signature: "my_production_signature"
|
22
|
+
application_id: "my_production_app_id"
|
data/lib/config.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
module PaypalAdaptive
|
2
|
+
class Config
|
3
|
+
PAYPAL_BASE_URL_MAPPING = {
|
4
|
+
:production => "https://www.paypal.com",
|
5
|
+
:sandbox => "https://www.sandbox.paypal.com",
|
6
|
+
:beta_sandbox => "https://www.beta-sandbox.paypal.com"
|
7
|
+
} unless defined? PAYPAL_BASE_URL_MAPPING
|
8
|
+
|
9
|
+
API_BASE_URL_MAPPING = {
|
10
|
+
:production => "https://svcs.paypal.com",
|
11
|
+
:sandbox => "https://svcs.sandbox.paypal.com",
|
12
|
+
:beta_sandbox => "https://svcs.beta-sandbox.paypal.com"
|
13
|
+
} unless defined? API_BASE_URL_MAPPING
|
14
|
+
|
15
|
+
attr_accessor :config_filepath, :paypal_base_url, :api_base_url, :headers
|
16
|
+
|
17
|
+
def initialize(env=nil)
|
18
|
+
if env
|
19
|
+
#non-rails env
|
20
|
+
@config_filepath = "./config/paypal_adaptive.yml"
|
21
|
+
load(env)
|
22
|
+
else
|
23
|
+
@config_filepath = File.join(Rails.root, "config/paypal_adaptive.yml")
|
24
|
+
load(Rails.env)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def load(rails_env)
|
29
|
+
config= YAML.load_file(@config_filepath)[rails_env]
|
30
|
+
|
31
|
+
if config["retain_requests_for_test"] == true
|
32
|
+
@retain_requests_for_test = true
|
33
|
+
else
|
34
|
+
pp_env = config['environment'].to_sym
|
35
|
+
|
36
|
+
@paypal_base_url = PAYPAL_BASE_URL_MAPPING[pp_env]
|
37
|
+
@api_base_url = API_BASE_URL_MAPPING[pp_env]
|
38
|
+
@headers = {
|
39
|
+
"X-PAYPAL-SECURITY-USERID" => config['username'],
|
40
|
+
"X-PAYPAL-SECURITY-PASSWORD" => config['password'],
|
41
|
+
"X-PAYPAL-SECURITY-SIGNATURE" => config['signature'],
|
42
|
+
"X-PAYPAL-APPLICATION-ID" => config['application_id'],
|
43
|
+
"X-PAYPAL-REQUEST-DATA-FORMAT" => "JSON",
|
44
|
+
"X-PAYPAL-RESPONSE-DATA-FORMAT" => "JSON",
|
45
|
+
"X-PAYPAL-DEVICE-IPADDRESS" => "0.0.0.0"
|
46
|
+
}
|
47
|
+
|
48
|
+
@headers["X-PAYPAL-SANDBOX-EMAIL-ADDRESS"] = config['sandbox_email'] if pp_env == :sandbox
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def retain_requests_for_test?
|
54
|
+
!!@retain_requests_for_test
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
require 'json'
|
4
|
+
require 'config'
|
5
|
+
|
6
|
+
module PaypalAdaptive
|
7
|
+
class IpnNotification
|
8
|
+
|
9
|
+
def initialize(env=nil)
|
10
|
+
@env = env
|
11
|
+
@@config ||= PaypalAdaptive::Config.new(@env)
|
12
|
+
@@paypal_base_url ||= @@config.paypal_base_url
|
13
|
+
end
|
14
|
+
|
15
|
+
def send_back(data)
|
16
|
+
data = "cmd=_notify-validate&#{data}"
|
17
|
+
url = URI.parse @@paypal_base_url
|
18
|
+
http = Net::HTTP.new(url.host, 443)
|
19
|
+
http.use_ssl = (url.scheme == 'https')
|
20
|
+
|
21
|
+
path = "#{@@paypal_base_url}/cgi-bin/webscr"
|
22
|
+
resp, response_data = http.post(path, data)
|
23
|
+
|
24
|
+
@verified = response_data == "VERIFIED"
|
25
|
+
end
|
26
|
+
|
27
|
+
def verified?
|
28
|
+
@verified
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
{"description":"Paypal PayRequest API",
|
2
|
+
"type":"object",
|
3
|
+
"properties":
|
4
|
+
{
|
5
|
+
"actionType": {"type":"string", "options":[{"value":"PAY", "label":"PAY"}]},
|
6
|
+
"cancelUrl": {"type":"string"},
|
7
|
+
"clientDetails": {"type":"object", "optional": true},
|
8
|
+
"currencyCode": {"type":"string"},
|
9
|
+
"feesPayer": {"type":"string", "optional":true,
|
10
|
+
"options":[
|
11
|
+
{"value":"SENDER", "label":"SENDER"},
|
12
|
+
{"value":"PRIMARYRECEIVER", "label":"PRIMARYRECEIVER"},
|
13
|
+
{"value":"EACHRECEIVER", "label":"EACHRECEIVER"},
|
14
|
+
{"value":"SECONDARYONLY", "label":"SECONDARYONLY"}
|
15
|
+
]},
|
16
|
+
"fundingConstraint": {"type":"object", "optional": true},
|
17
|
+
"ipnNotificationUrl": {"type":"string", "optional": true},
|
18
|
+
"memo": {"type":"string", "optional": true},
|
19
|
+
"pin": {"type":"string", "optional": true},
|
20
|
+
"preapprovalKey": {"type":"string", "optional": true},
|
21
|
+
"receiverList": {
|
22
|
+
"type":"object", "properties":{
|
23
|
+
"receiver":{
|
24
|
+
"type":"array",
|
25
|
+
"items":{
|
26
|
+
"email":{"type":"string"},
|
27
|
+
"amount":{"type":"string"},
|
28
|
+
"primary":{"type":"string","optional": true}}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
},
|
32
|
+
|
33
|
+
"requestEnvelope": {"type":"object", "properties":{"errorLanguage":{"type":"string"}}},
|
34
|
+
"returnUrl": {"type":"string"},
|
35
|
+
"reverseAllParallelPaymentsOnError": {"type":"boolean", "optional": true},
|
36
|
+
"senderEmail": {"type":"string", "optional": true},
|
37
|
+
"trackingId": {"type":"string", "optional": true}
|
38
|
+
}
|
39
|
+
}
|
@@ -0,0 +1,4 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "config"))
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "request"))
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "response"))
|
4
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "ipn_notification"))
|
data/lib/request.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'config'
|
3
|
+
require 'net/http'
|
4
|
+
require 'net/https'
|
5
|
+
require 'response'
|
6
|
+
|
7
|
+
module PaypalAdaptive
|
8
|
+
class NoDataError < Exception
|
9
|
+
end
|
10
|
+
|
11
|
+
class Request
|
12
|
+
def initialize(env = nil)
|
13
|
+
@env = env
|
14
|
+
@@config ||= PaypalAdaptive::Config.new(@env)
|
15
|
+
@@api_base_url ||= @@config.api_base_url
|
16
|
+
@@headers ||= @@config.headers
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate
|
20
|
+
#TODO the receiverList field not validating properly
|
21
|
+
|
22
|
+
# @@schema_filepath = "../lib/pay_request_schema.json"
|
23
|
+
# @@schema = File.open(@@schema_filepath, "rb"){|f| JSON.parse(f.read)}
|
24
|
+
# see page 42 of PP Adaptive Payments PDF for explanation of all fields.
|
25
|
+
#JSON::Schema.validate(@data, @@schema)
|
26
|
+
end
|
27
|
+
|
28
|
+
def pay(data)
|
29
|
+
raise NoDataError unless data
|
30
|
+
|
31
|
+
response_data = call_api(data, "/AdaptivePayments/Pay")
|
32
|
+
PaypalAdaptive::Response.new(response_data, @env)
|
33
|
+
end
|
34
|
+
|
35
|
+
def payment_details(data)
|
36
|
+
raise NoDataError unless data
|
37
|
+
|
38
|
+
call_api(data, "/AdaptivePayments/PaymentDetails")
|
39
|
+
end
|
40
|
+
|
41
|
+
def preapproval(data)
|
42
|
+
raise NoDataError unless data
|
43
|
+
|
44
|
+
response_data = call_api(data, "/AdaptivePayments/Preapproval")
|
45
|
+
PaypalAdaptive::Response.new(response_data, @env)
|
46
|
+
end
|
47
|
+
|
48
|
+
def preapproval_details(data)
|
49
|
+
raise NoDataError unless data
|
50
|
+
|
51
|
+
call_api(data, "/AdaptivePayments/PreapprovalDetails")
|
52
|
+
end
|
53
|
+
|
54
|
+
def cancel_preapproval(data)
|
55
|
+
raise NoDataError unless data
|
56
|
+
|
57
|
+
call_api(data, "/AdaptivePayments/CancelPreapproval")
|
58
|
+
end
|
59
|
+
|
60
|
+
def convert_currency(data)
|
61
|
+
raise NoDataError unless data
|
62
|
+
|
63
|
+
call_api(data, "/AdaptivePayments/ConvertCurrency")
|
64
|
+
end
|
65
|
+
|
66
|
+
def refund(data)
|
67
|
+
raise NoDataError unless data
|
68
|
+
|
69
|
+
call_api(data, "/AdaptivePayments/Refund")
|
70
|
+
end
|
71
|
+
|
72
|
+
def create_account(data)
|
73
|
+
raise NoDataError unless data
|
74
|
+
|
75
|
+
response_data = call_api(data, "/AdaptiveAccounts/CreateAccount")
|
76
|
+
PaypalAdaptive::Response.new(response_data, @env)
|
77
|
+
end
|
78
|
+
|
79
|
+
def call_api(data, path)
|
80
|
+
logger = data.delete(:logger) || data.delete("logger")
|
81
|
+
#hack fix: JSON.unparse doesn't work in Rails 2.3.5; only {}.to_json does..
|
82
|
+
api_request_data = JSON.unparse(data) rescue data.to_json
|
83
|
+
url = URI.parse @@api_base_url
|
84
|
+
http = Net::HTTP.new(url.host, 443)
|
85
|
+
http.use_ssl = (url.scheme == 'https')
|
86
|
+
|
87
|
+
logger.request(path, api_request_data, @@headers) if logger
|
88
|
+
resp, response_data = http.post(path, api_request_data, @@headers)
|
89
|
+
logger.response(resp, response_data) if logger
|
90
|
+
|
91
|
+
JSON.parse(response_data)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
data/lib/response.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module PaypalAdaptive
|
2
|
+
class Response < Hash
|
3
|
+
def initialize(response, env=nil)
|
4
|
+
@@config ||= PaypalAdaptive::Config.new(env)
|
5
|
+
@@paypal_base_url ||= @@config.paypal_base_url
|
6
|
+
|
7
|
+
self.merge!(response)
|
8
|
+
end
|
9
|
+
|
10
|
+
def success?
|
11
|
+
self['responseEnvelope']['ack'] == 'Success'
|
12
|
+
end
|
13
|
+
|
14
|
+
def errors
|
15
|
+
if success?
|
16
|
+
return []
|
17
|
+
else
|
18
|
+
self['error']
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def error_message
|
23
|
+
if success?
|
24
|
+
return nil
|
25
|
+
else
|
26
|
+
self['error'].first['message'] rescue nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def approve_paypal_payment_url
|
31
|
+
self['payKey'].nil? ? nil : "#{@@paypal_base_url}/webscr?cmd=_ap-payment&paykey=#{self['payKey']}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def preapproval_paypal_payment_url
|
35
|
+
self['preapprovalKey'].nil? ? nil : "#{@@paypal_base_url}/webscr?cmd=_ap-preapproval&preapprovalkey=#{self['preapprovalKey']}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Allow the metal piece to run in isolation
|
2
|
+
require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails)
|
3
|
+
|
4
|
+
class PaypalIpn
|
5
|
+
def self.call(env)
|
6
|
+
if env["PATH_INFO"] =~ /^\/paypal_ipn/
|
7
|
+
request = Rack::Request.new(env)
|
8
|
+
params = request.params
|
9
|
+
|
10
|
+
ipn = PaypalAdaptive::IpnNotification.new
|
11
|
+
ipn.send_back(env['rack.request.form_vars'])
|
12
|
+
if ipn.verified?
|
13
|
+
#mark transaction as completed in your DB
|
14
|
+
output = "Verified."
|
15
|
+
else
|
16
|
+
output = "Not Verified."
|
17
|
+
end
|
18
|
+
|
19
|
+
[200, {"Content-Type" => "text/html"}, [output]]
|
20
|
+
else
|
21
|
+
[404, {"Content-Type" => "text/html"}, ["Not Found"]]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class CreateAccountTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@account_request = PaypalAdaptive::Request.new("test")
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_valid_create_account
|
9
|
+
data = read_json_file("valid_create_account_request")
|
10
|
+
|
11
|
+
data["emailAddress"] = "joetester_#{Time.now.to_i}@example.com"
|
12
|
+
|
13
|
+
pp_response = @account_request.create_account(data)
|
14
|
+
|
15
|
+
assert pp_response.success?
|
16
|
+
assert pp_response["redirectURL"]
|
17
|
+
end
|
18
|
+
|
19
|
+
# TODO: this test fails, seems you can create as many emails as you want
|
20
|
+
def test_create_account_email_address_already_an_account
|
21
|
+
data = read_json_file("valid_create_account_request")
|
22
|
+
|
23
|
+
data["emailAddress"] = "joetester@example.com"
|
24
|
+
pp_response = @account_request.create_account(data)
|
25
|
+
|
26
|
+
assert !pp_response.success?
|
27
|
+
assert_equal "An account already exists for the specified email address", pp_response["error"].first["message"]
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
{
|
2
|
+
"returnUrl":"http://127.0.0.1:3000/payments/completed_payment",
|
3
|
+
"requestEnvelope":{"errorLanguage":"en_US"},
|
4
|
+
"currencyCode":"USD",
|
5
|
+
"receiverList":{"receiver":[
|
6
|
+
{"email":"testpp_1261697850_per@nextsprocket.com", "amount":"50.00", "primary": "true"},
|
7
|
+
{"email":"sender_1261713739_per@nextsprocket.com", "amount":"100.00", "primary": "false"},
|
8
|
+
{"email":"ppsell_1261697921_biz@nextsprocket.com", "amount":"100.00", "primary": "false"}
|
9
|
+
]},
|
10
|
+
"cancelUrl":"http://127.0.0.1:3000/payments/cancelled_payment",
|
11
|
+
"actionType":"PAY"
|
12
|
+
}
|
13
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
{
|
2
|
+
"returnUrl":"http://127.0.0.1:3000/payments/completed_payment",
|
3
|
+
"requestEnvelope":{"errorLanguage":"en_US"},
|
4
|
+
"currencyCode":"USD",
|
5
|
+
"receiverList":{"receiver":[
|
6
|
+
{"email":"dummy@account.com", "amount":"100.00"},
|
7
|
+
{"email":"dummy@account.com", "amount":"50.00"},
|
8
|
+
{"email":"dummy@account.com", "amount":"50.00"}
|
9
|
+
]},
|
10
|
+
"cancelUrl":"http://127.0.0.1:3000/payments/cancelled_payment",
|
11
|
+
"actionType":"PAY"
|
12
|
+
}
|
13
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
{
|
2
|
+
"returnUrl":"http://127.0.0.1:3000/payments/completed_payment_request",
|
3
|
+
"requestEnvelope":{"errorLanguage":"en_US"},
|
4
|
+
"currencyCode":"USD",
|
5
|
+
"cancelUrl":"http://127.0.0.1:3000/payments/canceled_payment_request",
|
6
|
+
"actionType":"PAY",
|
7
|
+
"maxTotalAmountOfAllPayments": "1500.00",
|
8
|
+
"maxNumberOfPayments":"30",
|
9
|
+
"startingDate":"2010-07-13T07sdf00.000Z",
|
10
|
+
"endingDate":"2010-12-13T07dfg0000.000Z"
|
11
|
+
}
|
12
|
+
|
@@ -0,0 +1,8 @@
|
|
1
|
+
{
|
2
|
+
"returnUrl":"http://127.0.0.1:3000/payments/completed_payment",
|
3
|
+
"requestEnvelope":{"errorLanguage":"en_US"},
|
4
|
+
"currencyCode":"USD",
|
5
|
+
"receiverList":{"receiver":[{"email":"testpp_1261697850_per@nextsprocket.com", "amount":"10.0"}]},
|
6
|
+
"cancelUrl":"http://127.0.0.1:3000/payments/canceled_payment",
|
7
|
+
"actionType":1
|
8
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
{
|
2
|
+
"returnUrl":"http://127.0.0.1:3000/payments/completed_payment_request",
|
3
|
+
"requestEnvelope":{"errorLanguage":"en_US"},
|
4
|
+
"currencyCode":"USD",
|
5
|
+
"receiverList":{"receiver":[
|
6
|
+
{"email":"testpp_1261697850_per@nextsprocket.com", "amount":"100.00", "primary": "true"},
|
7
|
+
{"email":"ppsell_1261697921_biz@nextsprocket.com", "amount":"90.00", "primary": "false"}
|
8
|
+
]},
|
9
|
+
"cancelUrl":"http://127.0.0.1:3000/payments/canceled_payment_request",
|
10
|
+
"actionType":"PAY"
|
11
|
+
}
|
12
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
{
|
2
|
+
"name":{"firstName":"Joe", "lastName":"Tester"},
|
3
|
+
"preferredLanguageCode":"en_US",
|
4
|
+
"address": {
|
5
|
+
"line1":"1234 Imaginary Ln",
|
6
|
+
"line2":"",
|
7
|
+
"city":"Ventura",
|
8
|
+
"state":"CA",
|
9
|
+
"postalCode":"93001",
|
10
|
+
"countryCode":"US"
|
11
|
+
},
|
12
|
+
"accountType":"Personal",
|
13
|
+
"citizenshipCountryCode":"US",
|
14
|
+
"contactPhoneNumber":"805-555-5555",
|
15
|
+
"createAccountWebOptions":{"returnUrl":"http://127.0.0.1:3000/payments/completed_payment_request"},
|
16
|
+
"emailAddress":"joetester@example.com",
|
17
|
+
"requestEnvelope":{"errorLanguage":"en_US"},
|
18
|
+
"currencyCode":"USD",
|
19
|
+
"registrationType":"WEB",
|
20
|
+
"cancelUrl":"http://127.0.0.1:3000/payments/canceled_payment_request",
|
21
|
+
"notificationURL":"http://127.0.0.1:3000/payments/ipn_notification"
|
22
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
{
|
2
|
+
"returnUrl":"http://127.0.0.1:3000/payments/completed_payment_request",
|
3
|
+
"requestEnvelope":{"errorLanguage":"en_US"},
|
4
|
+
"currencyCode":"USD",
|
5
|
+
"receiverList":{"receiver":[
|
6
|
+
{"email":"testpp_1261697850_per@nextsprocket.com", "amount":"100.00"},
|
7
|
+
{"email":"sender_1261713739_per@nextsprocket.com", "amount":"50.00"},
|
8
|
+
{"email":"ppsell_1261697921_biz@nextsprocket.com", "amount":"50.00"}
|
9
|
+
]},
|
10
|
+
"cancelUrl":"http://127.0.0.1:3000/payments/canceled_payment_request",
|
11
|
+
"actionType":"PAY",
|
12
|
+
"senderEmail": "a@a.com"
|
13
|
+
}
|
14
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
{
|
2
|
+
"returnUrl":"http://127.0.0.1:3000/payments/completed_payment_request",
|
3
|
+
"requestEnvelope":{"errorLanguage":"en_US"},
|
4
|
+
"currencyCode":"USD",
|
5
|
+
"cancelUrl":"http://127.0.0.1:3000/payments/canceled_payment_request",
|
6
|
+
"maxTotalAmountOfAllPayments": "1500.00",
|
7
|
+
"maxNumberOfPayments":"30"
|
8
|
+
}
|
9
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
{
|
2
|
+
"returnUrl":"http://127.0.0.1:3000/payments/completed_payment_request",
|
3
|
+
"requestEnvelope":{"errorLanguage":"en_US"},
|
4
|
+
"currencyCode":"USD",
|
5
|
+
"receiverList":{"receiver":[{"email":"testpp_1261697850_per@nextsprocket.com", "amount":"10.00"}]},
|
6
|
+
"cancelUrl":"http://127.0.0.1:3000/payments/canceled_payment_request",
|
7
|
+
"actionType":"PAY",
|
8
|
+
"ipnNotificationUrl":"http://127.0.0.1:3000/payments/ipn_notification"
|
9
|
+
}
|
data/test/helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require "yaml"
|
3
|
+
require 'JSON'
|
4
|
+
require 'test/unit'
|
5
|
+
require "request"
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
8
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
9
|
+
|
10
|
+
class Test::Unit::TestCase
|
11
|
+
|
12
|
+
def read_json_file(filepath)
|
13
|
+
File.open("./test/data/#{filepath}.json", "rb"){|f| JSON.parse(f.read)}
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'json'
|
3
|
+
require 'jsonschema'
|
4
|
+
|
5
|
+
class PayRequestSchemaTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@schema_filepath = "./lib/pay_request_schema.json"
|
8
|
+
@schema = File.open(@schema_filepath, "rb"){|f| JSON.parse(f.read)}
|
9
|
+
end
|
10
|
+
|
11
|
+
def xtest_valid_simple_pay
|
12
|
+
data = read_json_file("valid_simple_pay_request_1")
|
13
|
+
|
14
|
+
#receiverList not validating correctly, is it due to the schema or jsonschema parsing?
|
15
|
+
assert_nothing_raised do
|
16
|
+
JSON::Schema.validate(data, @schema)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_invalid_simple_pay
|
21
|
+
data = read_json_file("invalid_simple_pay_request_1")
|
22
|
+
|
23
|
+
assert_raise JSON::Schema::ValueError do
|
24
|
+
JSON::Schema.validate(data, @schema)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_valid_chain_pay
|
29
|
+
#TODO
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_invalid_chain_pay
|
33
|
+
#TODO
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_valid_parallel_pay
|
37
|
+
#TODO
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_invalid_parallel_pay
|
41
|
+
#TODO
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class PayRequestTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@pay_request = PaypalAdaptive::Request.new("test")
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_valid_simple_pay
|
9
|
+
puts "-------"
|
10
|
+
puts "simple"
|
11
|
+
|
12
|
+
data = read_json_file("valid_simple_pay_request_1")
|
13
|
+
pp_response = @pay_request.pay(data)
|
14
|
+
|
15
|
+
puts "redirect url to\n #{pp_response.approve_paypal_payment_url}"
|
16
|
+
assert pp_response.success?
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_invalid_simple_pay
|
20
|
+
data = read_json_file("invalid_simple_pay_request_1")
|
21
|
+
pp_response = @pay_request.pay(data)
|
22
|
+
puts pp_response.errors
|
23
|
+
assert pp_response.success? == false
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_valid_chain_pay
|
27
|
+
puts "-------"
|
28
|
+
puts "chain"
|
29
|
+
data = read_json_file("valid_chain_pay_request")
|
30
|
+
pp_response = @pay_request.pay(data)
|
31
|
+
puts "redirect url to\n #{pp_response.approve_paypal_payment_url}"
|
32
|
+
|
33
|
+
unless pp_response.success?
|
34
|
+
puts pp_response.errors
|
35
|
+
end
|
36
|
+
|
37
|
+
assert pp_response.success?
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_invalid_chain_pay
|
41
|
+
data = read_json_file("invalid_chain_pay_request")
|
42
|
+
pp_response = @pay_request.pay(data)
|
43
|
+
puts pp_response.errors
|
44
|
+
assert pp_response.success? == false
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_valid_parallel_pay
|
48
|
+
puts "-------"
|
49
|
+
puts "parallel"
|
50
|
+
|
51
|
+
data = read_json_file("valid_chain_pay_request")
|
52
|
+
pp_response = @pay_request.pay(data)
|
53
|
+
puts "redirect url to\n #{pp_response.approve_paypal_payment_url}"
|
54
|
+
assert pp_response.success?
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_invalid_parallel_pay
|
58
|
+
data = read_json_file("invalid_parallel_pay_request")
|
59
|
+
pp_response = @pay_request.pay(data)
|
60
|
+
puts pp_response.errors
|
61
|
+
assert pp_response.success? == false
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
def test_preapproval
|
66
|
+
#TODO
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_preapproval_details
|
70
|
+
#TODO
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_cancel_preapproval
|
74
|
+
#TODO
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_convert_currency
|
78
|
+
#TODO
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_refund
|
82
|
+
#TODO
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class PaymentDetailsTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@pay_request = PaypalAdaptive::Request.new("test")
|
6
|
+
@payment_details_request = PaypalAdaptive::Request.new("test")
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_payment_details
|
10
|
+
puts "-------"
|
11
|
+
puts "payment details"
|
12
|
+
data = read_json_file("valid_chain_pay_request")
|
13
|
+
pp_response = @pay_request.pay(data)
|
14
|
+
puts "redirect url to\n #{pp_response.approve_paypal_payment_url}"
|
15
|
+
|
16
|
+
unless pp_response.success?
|
17
|
+
puts pp_response.errors
|
18
|
+
end
|
19
|
+
|
20
|
+
assert pp_response.success?
|
21
|
+
|
22
|
+
data = {"requestEnvelope"=>{"errorLanguage"=>"en_US"}, "payKey" => pp_response['payKey']}
|
23
|
+
|
24
|
+
response = @payment_details_request.payment_details(data)
|
25
|
+
assert_equal 'CREATED', response['status']
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "time"
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
class PreapprovalTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@preapproval_request = PaypalAdaptive::Request.new("test")
|
7
|
+
end
|
8
|
+
|
9
|
+
def set_dates(data)
|
10
|
+
data["startingDate"] = Time.now.utc.iso8601
|
11
|
+
data["endingDate"] = (Time.now.utc + 20*24*3600).iso8601
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_preapproval
|
15
|
+
puts "-------"
|
16
|
+
puts "valid test"
|
17
|
+
data = read_json_file("valid_preapproval")
|
18
|
+
set_dates(data)
|
19
|
+
|
20
|
+
pp_response = @preapproval_request.preapproval(data)
|
21
|
+
puts "preapproval code is #{pp_response['preapprovalKey']}"
|
22
|
+
|
23
|
+
assert pp_response.success?
|
24
|
+
assert_not_nil pp_response.preapproval_paypal_payment_url
|
25
|
+
assert_not_nil pp_response['preapprovalKey']
|
26
|
+
end
|
27
|
+
|
28
|
+
class Logger
|
29
|
+
attr_accessor :path, :request_data, :headers, :status, :response_data
|
30
|
+
def request(path, request_data, headers)
|
31
|
+
@path, @request_data, @headers = path, request_data, headers
|
32
|
+
end
|
33
|
+
|
34
|
+
def response(status, response_data)
|
35
|
+
@status, @response_data = status.code.to_i, response_data
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_invalid_preapproval_with_logger
|
40
|
+
data = read_json_file("invalid_preapproval")
|
41
|
+
logger = Logger.new
|
42
|
+
pp_response = @preapproval_request.preapproval(data.merge(:logger => logger))
|
43
|
+
|
44
|
+
assert pp_response.success? == false
|
45
|
+
assert logger.path == "/AdaptivePayments/Preapproval"
|
46
|
+
assert logger.request_data == "{\"cancelUrl\":\"http://127.0.0.1:3000/payments/canceled_payment_request\",\"endingDate\":\"2010-12-13T07dfg0000.000Z\",\"returnUrl\":\"http://127.0.0.1:3000/payments/completed_payment_request\",\"maxTotalAmountOfAllPayments\":\"1500.00\",\"startingDate\":\"2010-07-13T07sdf00.000Z\",\"maxNumberOfPayments\":\"30\",\"requestEnvelope\":{\"errorLanguage\":\"en_US\"},\"actionType\":\"PAY\",\"currencyCode\":\"USD\"}"
|
47
|
+
assert logger.headers == {"X-PAYPAL-RESPONSE-DATA-FORMAT"=>"JSON", "X-PAYPAL-SANDBOX-EMAIL-ADDRESS"=>"andy@lottay.com", "X-PAYPAL-REQUEST-DATA-FORMAT"=>"JSON", "X-PAYPAL-SECURITY-USERID"=>"andy_1246488382_biz_api1.lottay.com", "X-PAYPAL-DEVICE-IPADDRESS"=>"0.0.0.0", "X-PAYPAL-SECURITY-PASSWORD"=>"1246488389", "X-PAYPAL-APPLICATION-ID"=>"APP-80W284485P519543T", "X-PAYPAL-SECURITY-SIGNATURE"=>"AHCkey.eVc0sNgG3SP.iiLKXx5EmALu43DmEPM6wmWg.snEFzyBrSfE2"}
|
48
|
+
assert logger.status == 200
|
49
|
+
assert logger.response_data =~ /responseEnvelope/
|
50
|
+
assert logger.response_data =~ /Error in parsing time zone/
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_invalid_preapproval
|
54
|
+
puts "-------"
|
55
|
+
puts "invalid"
|
56
|
+
data = read_json_file("invalid_preapproval")
|
57
|
+
pp_response = @preapproval_request.preapproval(data)
|
58
|
+
puts "error message is #{pp_response.error_message}"
|
59
|
+
|
60
|
+
assert pp_response.success? == false
|
61
|
+
assert_nil pp_response.preapproval_paypal_payment_url
|
62
|
+
assert_nil pp_response['preapprovalKey']
|
63
|
+
end
|
64
|
+
end
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: astrails-paypal_adaptive
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 25
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Tommy Chheng
|
14
|
+
- Ross Hale
|
15
|
+
- Boris Nadion
|
16
|
+
autorequire:
|
17
|
+
bindir: bin
|
18
|
+
cert_chain: []
|
19
|
+
|
20
|
+
date: 2011-02-09 00:00:00 +02:00
|
21
|
+
default_executable:
|
22
|
+
dependencies:
|
23
|
+
- !ruby/object:Gem::Dependency
|
24
|
+
name: json
|
25
|
+
prerelease: false
|
26
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
27
|
+
none: false
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
hash: 3
|
32
|
+
segments:
|
33
|
+
- 0
|
34
|
+
version: "0"
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: jsonschema
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 3
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
version: "0"
|
49
|
+
type: :development
|
50
|
+
version_requirements: *id002
|
51
|
+
description: Lightweight wrapper for Paypal's Adaptive Payments API.
|
52
|
+
email: boris@astrails.com
|
53
|
+
executables: []
|
54
|
+
|
55
|
+
extensions: []
|
56
|
+
|
57
|
+
extra_rdoc_files:
|
58
|
+
- LICENSE
|
59
|
+
- README.markdown
|
60
|
+
files:
|
61
|
+
- LICENSE
|
62
|
+
- README.markdown
|
63
|
+
- Rakefile
|
64
|
+
- VERSION
|
65
|
+
- astrails-paypal_adaptive.gemspec
|
66
|
+
- config/paypal_adaptive.yml
|
67
|
+
- lib/config.rb
|
68
|
+
- lib/ipn_notification.rb
|
69
|
+
- lib/pay_request_schema.json
|
70
|
+
- lib/paypal_adaptive.rb
|
71
|
+
- lib/request.rb
|
72
|
+
- lib/response.rb
|
73
|
+
- templates/paypal_ipn.rb
|
74
|
+
- test/create_account_test.rb
|
75
|
+
- test/data/invalid_chain_pay_request.json
|
76
|
+
- test/data/invalid_parallel_pay_request.json
|
77
|
+
- test/data/invalid_preapproval.json
|
78
|
+
- test/data/invalid_simple_pay_request_1.json
|
79
|
+
- test/data/valid_chain_pay_request.json
|
80
|
+
- test/data/valid_create_account_request.json
|
81
|
+
- test/data/valid_parallel_pay_request.json
|
82
|
+
- test/data/valid_preapproval.json
|
83
|
+
- test/data/valid_simple_pay_request_1.json
|
84
|
+
- test/helper.rb
|
85
|
+
- test/pay_request_schema_test.rb
|
86
|
+
- test/pay_request_test.rb
|
87
|
+
- test/payment_details_test.rb
|
88
|
+
- test/preapproval_test.rb
|
89
|
+
has_rdoc: true
|
90
|
+
homepage: http://github.com/astrails/paypal_adaptive
|
91
|
+
licenses: []
|
92
|
+
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
hash: 3
|
104
|
+
segments:
|
105
|
+
- 0
|
106
|
+
version: "0"
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
none: false
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
hash: 3
|
113
|
+
segments:
|
114
|
+
- 0
|
115
|
+
version: "0"
|
116
|
+
requirements: []
|
117
|
+
|
118
|
+
rubyforge_project:
|
119
|
+
rubygems_version: 1.3.7
|
120
|
+
signing_key:
|
121
|
+
specification_version: 3
|
122
|
+
summary: initial import
|
123
|
+
test_files:
|
124
|
+
- test/create_account_test.rb
|
125
|
+
- test/helper.rb
|
126
|
+
- test/pay_request_schema_test.rb
|
127
|
+
- test/pay_request_test.rb
|
128
|
+
- test/payment_details_test.rb
|
129
|
+
- test/preapproval_test.rb
|