paypal_adaptive 0.0.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/.gitignore +22 -0
- data/LICENSE +20 -0
- data/README.markdown +68 -0
- data/Rakefile +55 -0
- data/VERSION +1 -0
- data/lib/config.rb +53 -0
- data/lib/ipn_notification.rb +32 -0
- data/lib/pay_request.rb +85 -0
- data/lib/pay_request_schema.json +39 -0
- data/lib/pay_response.rb +32 -0
- data/lib/paypal_adaptive.rb +4 -0
- data/paypal_adaptive.gemspec +71 -0
- data/templates/paypal_ipn.rb +25 -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_simple_pay_request_1.json +8 -0
- data/test/data/valid_chain_pay_request.json +13 -0
- data/test/data/valid_parallel_pay_request.json +14 -0
- data/test/data/valid_simple_pay_request_1.json +9 -0
- data/test/helper.rb +5 -0
- data/test/pay_request_schema_test.rb +49 -0
- data/test/pay_request_test.rb +100 -0
- metadata +99 -0
data/.gitignore
ADDED
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,68 @@
|
|
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, download pp_adaptivepayments.pdf and IPNGuide.pdf from the Paypal's dev site http://x.com
|
7
|
+
It'll be invaluable in determining how certain things work and error messages.
|
8
|
+
|
9
|
+
## HOWTO
|
10
|
+
Create paypal_adaptive.yml to your config folder:
|
11
|
+
development:
|
12
|
+
environment: "sandbox"
|
13
|
+
username: "sandbox_username"
|
14
|
+
password: "sandbox_password"
|
15
|
+
signature: "sandbox_signature"
|
16
|
+
application_id: "sandbox_app_id"
|
17
|
+
|
18
|
+
test:
|
19
|
+
environment: "sandbox"
|
20
|
+
username: "sandbox_username"
|
21
|
+
password: "sandbox_password"
|
22
|
+
signature: "sandbox_signature"
|
23
|
+
application_id: "sandbox_app_id"
|
24
|
+
|
25
|
+
production:
|
26
|
+
environment: "production"
|
27
|
+
username: "my_production_username"
|
28
|
+
password: "my_production_password"
|
29
|
+
signature: "my_production_signature"
|
30
|
+
application_id: "my_production_app_id"
|
31
|
+
|
32
|
+
Make the payment request:
|
33
|
+
|
34
|
+
pay_request = PaypalAdaptive::PayRequest.new
|
35
|
+
|
36
|
+
data = {
|
37
|
+
"returnUrl" => "http://testserver.com/payments/completed_payment_request",
|
38
|
+
"requestEnvelope" => {"errorLanguage" => "en_US"},
|
39
|
+
"currencyCode"=>"USD",
|
40
|
+
"receiverList"=>{"receiver"=>[{"email"=>"testpp_1261697850_per@nextsprocket.com", "amount"=>"10.00"}]},
|
41
|
+
"cancelUrl"=>"http://testserver.com/payments/canceled_payment_request",
|
42
|
+
"actionType"=>"PAY",
|
43
|
+
"ipnNotificationUrl"=>"http://testserver.com/payments/ipn_notification"
|
44
|
+
}
|
45
|
+
|
46
|
+
pp_response = pay_request.pay(data)
|
47
|
+
|
48
|
+
if pp_response.success?
|
49
|
+
redirect_to pp_response.approve_paypal_payment_url
|
50
|
+
else
|
51
|
+
puts pp_response.errors.first['message']
|
52
|
+
redirect_to failed_payment
|
53
|
+
end
|
54
|
+
|
55
|
+
---
|
56
|
+
Once the user goes to pp_response.approve_paypal_payment_url, they will be prompted to login to Paypal for payment.
|
57
|
+
|
58
|
+
Upon payment completion page, they will be redirected to http://testserver.com/payments/completed_payment_request.
|
59
|
+
|
60
|
+
They can also click cancel to go to http://testserver.com/payments/canceled_payment_request
|
61
|
+
|
62
|
+
The actual payment details will be sent to your server via "ipnNotificationUrl"
|
63
|
+
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 callbcak.
|
64
|
+
|
65
|
+
|
66
|
+
## Copyright
|
67
|
+
|
68
|
+
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 = "paypal_adaptive"
|
9
|
+
gem.summary = %Q{initial import}
|
10
|
+
gem.description = %Q{Lightweight wrapper for Paypal's Adaptive Payments API.}
|
11
|
+
gem.email = "tommy.chheng@gmail.com"
|
12
|
+
gem.homepage = "http://github.com/tc/paypal_adaptive"
|
13
|
+
gem.authors = ["Tommy Chheng"]
|
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 = "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.0.1
|
data/lib/config.rb
ADDED
@@ -0,0 +1,53 @@
|
|
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
|
+
}
|
8
|
+
API_BASE_URL_MAPPING= {
|
9
|
+
:production => "https://svcs.paypal.com",
|
10
|
+
:sandbox => "https://svcs.sandbox.paypal.com",
|
11
|
+
:beta_sandbox => "https://svcs.beta-sandbox.paypal.com"
|
12
|
+
}
|
13
|
+
|
14
|
+
attr_accessor :config_filepath, :paypal_base_url, :api_base_url, :headers
|
15
|
+
|
16
|
+
def initialize(env=nil)
|
17
|
+
if env
|
18
|
+
#non-rails env
|
19
|
+
@config_filepath = "../config/paypal_adaptive.yml"
|
20
|
+
load(env)
|
21
|
+
else
|
22
|
+
@config_filepath = File.join(Rails.root, "config/paypal_adaptive.yml")
|
23
|
+
load(Rails.env)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def load(rails_env)
|
28
|
+
config= YAML.load_file(@config_filepath)[rails_env]
|
29
|
+
|
30
|
+
if config["retain_requests_for_test"] == true
|
31
|
+
@retain_requests_for_test = true
|
32
|
+
else
|
33
|
+
pp_env = config['environment'].to_sym
|
34
|
+
|
35
|
+
@paypal_base_url = PAYPAL_BASE_URL_MAPPING[pp_env]
|
36
|
+
@api_base_url = API_BASE_URL_MAPPING[pp_env]
|
37
|
+
@headers = {
|
38
|
+
"X-PAYPAL-SECURITY-USERID" => config['username'],
|
39
|
+
"X-PAYPAL-SECURITY-PASSWORD" => config['password'],
|
40
|
+
"X-PAYPAL-SECURITY-SIGNATURE" => config['signature'],
|
41
|
+
"X-PAYPAL-APPLICATION-ID" => config['application_id'],
|
42
|
+
"X-PAYPAL-REQUEST-DATA-FORMAT" => "JSON",
|
43
|
+
"X-PAYPAL-RESPONSE-DATA-FORMAT" => "JSON"
|
44
|
+
}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def retain_requests_for_test?
|
49
|
+
!!@retain_requests_for_test
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
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
|
data/lib/pay_request.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
require 'json'
|
4
|
+
require 'config'
|
5
|
+
require 'pay_response'
|
6
|
+
|
7
|
+
module PaypalAdaptive
|
8
|
+
class NoDataError < Exception
|
9
|
+
end
|
10
|
+
|
11
|
+
class PayRequest
|
12
|
+
attr_accessor :pay_key
|
13
|
+
attr_accessor :errors
|
14
|
+
attr_accessor :env
|
15
|
+
|
16
|
+
def initialize(env = nil)
|
17
|
+
@env = env
|
18
|
+
@@config ||= PaypalAdaptive::Config.new(@env)
|
19
|
+
@@api_base_url ||= @@config.api_base_url
|
20
|
+
@@headers ||= @@config.headers
|
21
|
+
end
|
22
|
+
|
23
|
+
def validate
|
24
|
+
#TODO the receiverList field not validating properly
|
25
|
+
|
26
|
+
# @@schema_filepath = "../lib/pay_request_schema.json"
|
27
|
+
# @@schema = File.open(@@schema_filepath, "rb"){|f| JSON.parse(f.read)}
|
28
|
+
# see page 42 of PP Adaptive Payments PDF for explanation of all fields.
|
29
|
+
#JSON::Schema.validate(@data, @@schema)
|
30
|
+
end
|
31
|
+
|
32
|
+
def pay(data)
|
33
|
+
raise NoDataError unless data
|
34
|
+
|
35
|
+
call_api(data, "/AdaptivePayments/Pay")
|
36
|
+
end
|
37
|
+
|
38
|
+
def payment_details(data)
|
39
|
+
raise NoDataError unless data
|
40
|
+
|
41
|
+
call_api(data, "/AdaptivePayments/PaymentDetails")
|
42
|
+
end
|
43
|
+
|
44
|
+
def preapproval(data)
|
45
|
+
raise NoDataError unless data
|
46
|
+
|
47
|
+
call_api(data, "/AdaptivePayments/Preapproval")
|
48
|
+
end
|
49
|
+
|
50
|
+
def preapproval_details(data)
|
51
|
+
raise NoDataError unless data
|
52
|
+
|
53
|
+
call_api(data, "/AdaptivePayments/PreapprovalDetails")
|
54
|
+
end
|
55
|
+
|
56
|
+
def cancel_preapproval(data)
|
57
|
+
raise NoDataError unless data
|
58
|
+
|
59
|
+
call_api(data, "/AdaptivePayments/CancelPreapproval")
|
60
|
+
end
|
61
|
+
|
62
|
+
def convert_currency(data)
|
63
|
+
raise NoDataError unless data
|
64
|
+
|
65
|
+
call_api(data, "/AdaptivePayments/ConvertCurrency")
|
66
|
+
end
|
67
|
+
|
68
|
+
def refund(data)
|
69
|
+
raise NoDataError unless data
|
70
|
+
|
71
|
+
call_api(data, "/AdaptivePayments/Refund")
|
72
|
+
end
|
73
|
+
|
74
|
+
def call_api(data, path)
|
75
|
+
#hack fix: JSON.unparse doesn't work in Rails 2.3.5; only {}.to_json does..
|
76
|
+
api_request_data = JSON.unparse(data) rescue data.to_json
|
77
|
+
url = URI.parse @@api_base_url
|
78
|
+
http = Net::HTTP.new(url.host, 443)
|
79
|
+
http.use_ssl = (url.scheme == 'https')
|
80
|
+
|
81
|
+
resp, response_data = http.post(path, api_request_data, @@headers)
|
82
|
+
pp_response = PaypalAdaptive::PayResponse.new(response_data, @env)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
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
|
+
}
|
data/lib/pay_response.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module PaypalAdaptive
|
4
|
+
class PayResponse
|
5
|
+
def initialize(response, env=nil)
|
6
|
+
@@config ||= PaypalAdaptive::Config.new(env)
|
7
|
+
@@paypal_base_url ||= @@config.paypal_base_url
|
8
|
+
|
9
|
+
@json_response = JSON.parse(response)
|
10
|
+
end
|
11
|
+
|
12
|
+
def success?
|
13
|
+
@json_response['responseEnvelope']['ack'] == 'Success'
|
14
|
+
end
|
15
|
+
|
16
|
+
def pay_key
|
17
|
+
@json_response['payKey']
|
18
|
+
end
|
19
|
+
|
20
|
+
def errors
|
21
|
+
if success?
|
22
|
+
return []
|
23
|
+
else
|
24
|
+
@json_response['error']
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def approve_paypal_payment_url
|
29
|
+
"#{@@paypal_base_url}/webscr?cmd=_ap-payment&paykey=#{pay_key}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -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__), "pay_request"))
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "pay_response"))
|
4
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "ipn_notification"))
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{paypal_adaptive}
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Tommy Chheng"]
|
12
|
+
s.date = %q{2009-12-25}
|
13
|
+
s.description = %q{Lightweight wrapper for Paypal's Adaptive Payments API.}
|
14
|
+
s.email = %q{tommy.chheng@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.markdown"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".gitignore",
|
21
|
+
"LICENSE",
|
22
|
+
"README.markdown",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"config/paypal_adaptive.yml",
|
26
|
+
"lib/config.rb",
|
27
|
+
"lib/ipn_notification.rb",
|
28
|
+
"lib/pay_request.rb",
|
29
|
+
"lib/pay_request_schema.json",
|
30
|
+
"lib/pay_response.rb",
|
31
|
+
"lib/paypal_adaptive.rb",
|
32
|
+
"paypal_adaptive.gemspec",
|
33
|
+
"templates/paypal_ipn.rb",
|
34
|
+
"test/data/invalid_chain_pay_request.json",
|
35
|
+
"test/data/invalid_parallel_pay_request.json",
|
36
|
+
"test/data/invalid_simple_pay_request_1.json",
|
37
|
+
"test/data/valid_chain_pay_request.json",
|
38
|
+
"test/data/valid_parallel_pay_request.json",
|
39
|
+
"test/data/valid_simple_pay_request_1.json",
|
40
|
+
"test/helper.rb",
|
41
|
+
"test/pay_request_schema_test.rb",
|
42
|
+
"test/pay_request_test.rb"
|
43
|
+
]
|
44
|
+
s.homepage = %q{http://github.com/tc/paypal_adaptive}
|
45
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
46
|
+
s.require_paths = ["lib"]
|
47
|
+
s.rubygems_version = %q{1.3.5}
|
48
|
+
s.summary = %q{initial import}
|
49
|
+
s.test_files = [
|
50
|
+
"test/helper.rb",
|
51
|
+
"test/pay_request_schema_test.rb",
|
52
|
+
"test/pay_request_test.rb"
|
53
|
+
]
|
54
|
+
|
55
|
+
if s.respond_to? :specification_version then
|
56
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
57
|
+
s.specification_version = 3
|
58
|
+
|
59
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
60
|
+
s.add_development_dependency(%q<json>, [">= 0"])
|
61
|
+
s.add_development_dependency(%q<jsonschema>, [">= 0"])
|
62
|
+
else
|
63
|
+
s.add_dependency(%q<json>, [">= 0"])
|
64
|
+
s.add_dependency(%q<jsonschema>, [">= 0"])
|
65
|
+
end
|
66
|
+
else
|
67
|
+
s.add_dependency(%q<json>, [">= 0"])
|
68
|
+
s.add_dependency(%q<jsonschema>, [">= 0"])
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
@@ -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['QUERY_STRING'])
|
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,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,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,13 @@
|
|
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":"sender_1261713739_per@nextsprocket.com", "amount":"50.00", "primary": "false"},
|
8
|
+
{"email":"ppsell_1261697921_biz@nextsprocket.com", "amount":"50.00", "primary": "false"}
|
9
|
+
]},
|
10
|
+
"cancelUrl":"http://127.0.0.1:3000/payments/canceled_payment_request",
|
11
|
+
"actionType":"PAY"
|
12
|
+
}
|
13
|
+
|
@@ -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
|
+
"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,49 @@
|
|
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 test_valid_simple_pay
|
12
|
+
data_filepath = "data/valid_simple_pay_request_1.json"
|
13
|
+
data = read_json_file(data_filepath)
|
14
|
+
|
15
|
+
#receiverList not validating correctly, is it due to the schema or jsonschema parsing?
|
16
|
+
assert_nothing_raised do
|
17
|
+
JSON::Schema.validate(data, @schema)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_invalid_simple_pay
|
22
|
+
data_filepath = "data/invalid_simple_pay_request_1.json"
|
23
|
+
data = read_json_file(data_filepath)
|
24
|
+
|
25
|
+
assert_raise JSON::Schema::ValueError do
|
26
|
+
JSON::Schema.validate(data, @schema)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_valid_chain_pay
|
31
|
+
#TODO
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_invalid_chain_pay
|
35
|
+
#TODO
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_valid_parallel_pay
|
39
|
+
#TODO
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_invalid_parallel_pay
|
43
|
+
#TODO
|
44
|
+
end
|
45
|
+
|
46
|
+
def read_json_file(filepath)
|
47
|
+
File.open(filepath, "rb"){|f| JSON.parse(f.read)}
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require '../lib/pay_request'
|
3
|
+
|
4
|
+
class PayRequestTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@pay_request = PaypalAdaptive::PayRequest.new("test")
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_valid_simple_pay
|
10
|
+
puts "-------"
|
11
|
+
puts "simple"
|
12
|
+
|
13
|
+
data_filepath = "../test/data/valid_simple_pay_request_1.json"
|
14
|
+
|
15
|
+
data = read_json_file(data_filepath)
|
16
|
+
pp_response = @pay_request.pay(data)
|
17
|
+
|
18
|
+
puts "redirect url to\n #{pp_response.approve_paypal_payment_url}"
|
19
|
+
assert pp_response.success?
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_invalid_simple_pay
|
23
|
+
data_filepath = "../test/data/invalid_simple_pay_request_1.json"
|
24
|
+
|
25
|
+
data = read_json_file(data_filepath)
|
26
|
+
pp_response = @pay_request.pay(data)
|
27
|
+
puts pp_response.errors
|
28
|
+
assert pp_response.success? == false
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_valid_chain_pay
|
32
|
+
puts "-------"
|
33
|
+
puts "chain"
|
34
|
+
data_filepath = "../test/data/valid_chain_pay_request.json"
|
35
|
+
|
36
|
+
data = read_json_file(data_filepath)
|
37
|
+
pp_response = @pay_request.pay(data)
|
38
|
+
puts "redirect url to\n #{pp_response.approve_paypal_payment_url}"
|
39
|
+
assert pp_response.success?
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_invalid_chain_pay
|
43
|
+
data_filepath = "../test/data/invalid_chain_pay_request.json"
|
44
|
+
|
45
|
+
data = read_json_file(data_filepath)
|
46
|
+
pp_response = @pay_request.pay(data)
|
47
|
+
puts pp_response.errors
|
48
|
+
assert pp_response.success? == false
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_valid_parallel_pay
|
52
|
+
puts "-------"
|
53
|
+
puts "parallel"
|
54
|
+
|
55
|
+
data_filepath = "../test/data/valid_chain_pay_request.json"
|
56
|
+
|
57
|
+
data = read_json_file(data_filepath)
|
58
|
+
pp_response = @pay_request.pay(data)
|
59
|
+
puts "redirect url to\n #{pp_response.approve_paypal_payment_url}"
|
60
|
+
assert pp_response.success?
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_invalid_parallel_pay
|
64
|
+
data_filepath = "../test/data/invalid_parallel_pay_request.json"
|
65
|
+
|
66
|
+
data = read_json_file(data_filepath)
|
67
|
+
pp_response = @pay_request.pay(data)
|
68
|
+
puts pp_response.errors
|
69
|
+
assert pp_response.success? == false
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_payment_details
|
73
|
+
#TODO
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_preapproval
|
77
|
+
#TODO
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_preapproval_details
|
81
|
+
#TODO
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_cancel_preapproval
|
85
|
+
#TODO
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_convert_currency
|
89
|
+
#TODO
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_refund
|
93
|
+
#TODO
|
94
|
+
end
|
95
|
+
|
96
|
+
def read_json_file(filepath)
|
97
|
+
File.open(filepath, "rb"){|f| JSON.parse(f.read)}
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: paypal_adaptive
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tommy Chheng
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-25 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: json
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: jsonschema
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
description: Lightweight wrapper for Paypal's Adaptive Payments API.
|
36
|
+
email: tommy.chheng@gmail.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- LICENSE
|
43
|
+
- README.markdown
|
44
|
+
files:
|
45
|
+
- .gitignore
|
46
|
+
- LICENSE
|
47
|
+
- README.markdown
|
48
|
+
- Rakefile
|
49
|
+
- VERSION
|
50
|
+
- config/paypal_adaptive.yml
|
51
|
+
- lib/config.rb
|
52
|
+
- lib/ipn_notification.rb
|
53
|
+
- lib/pay_request.rb
|
54
|
+
- lib/pay_request_schema.json
|
55
|
+
- lib/pay_response.rb
|
56
|
+
- lib/paypal_adaptive.rb
|
57
|
+
- paypal_adaptive.gemspec
|
58
|
+
- templates/paypal_ipn.rb
|
59
|
+
- test/data/invalid_chain_pay_request.json
|
60
|
+
- test/data/invalid_parallel_pay_request.json
|
61
|
+
- test/data/invalid_simple_pay_request_1.json
|
62
|
+
- test/data/valid_chain_pay_request.json
|
63
|
+
- test/data/valid_parallel_pay_request.json
|
64
|
+
- test/data/valid_simple_pay_request_1.json
|
65
|
+
- test/helper.rb
|
66
|
+
- test/pay_request_schema_test.rb
|
67
|
+
- test/pay_request_test.rb
|
68
|
+
has_rdoc: true
|
69
|
+
homepage: http://github.com/tc/paypal_adaptive
|
70
|
+
licenses: []
|
71
|
+
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options:
|
74
|
+
- --charset=UTF-8
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: "0"
|
82
|
+
version:
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: "0"
|
88
|
+
version:
|
89
|
+
requirements: []
|
90
|
+
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 1.3.5
|
93
|
+
signing_key:
|
94
|
+
specification_version: 3
|
95
|
+
summary: initial import
|
96
|
+
test_files:
|
97
|
+
- test/helper.rb
|
98
|
+
- test/pay_request_schema_test.rb
|
99
|
+
- test/pay_request_test.rb
|