paypal-recurring 0.1.0 → 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/Gemfile.lock +1 -1
- data/lib/paypal/recurring.rb +8 -5
- data/lib/paypal/recurring/base.rb +8 -8
- data/lib/paypal/recurring/notification.rb +75 -0
- data/lib/paypal/recurring/request.rb +20 -6
- data/lib/paypal/recurring/version.rb +1 -1
- data/spec/fixtures/notification/failure.yml +32 -0
- data/spec/fixtures/notification/success.yml +32 -0
- data/spec/paypal/notification_spec.rb +23 -0
- data/spec/paypal/recurring_spec.rb +0 -6
- data/spec/paypal/request_spec.rb +1 -1
- metadata +11 -4
data/Gemfile.lock
CHANGED
data/lib/paypal/recurring.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
require "net/https"
|
2
2
|
require "cgi"
|
3
3
|
require "uri"
|
4
|
-
require "logger"
|
5
4
|
require "ostruct"
|
6
5
|
require "time"
|
7
6
|
|
8
7
|
module PayPal
|
9
8
|
module Recurring
|
10
9
|
autoload :Base, "paypal/recurring/base"
|
10
|
+
autoload :Notification, "paypal/recurring/notification"
|
11
11
|
autoload :Request, "paypal/recurring/request"
|
12
12
|
autoload :Response, "paypal/recurring/response"
|
13
13
|
autoload :Version, "paypal/recurring/version"
|
@@ -44,12 +44,15 @@ module PayPal
|
|
44
44
|
#
|
45
45
|
attr_accessor :signature
|
46
46
|
|
47
|
-
# Set
|
47
|
+
# Set seller id. Will be used to verify IPN.
|
48
48
|
#
|
49
|
-
|
50
|
-
|
49
|
+
#
|
50
|
+
attr_accessor :seller_id
|
51
51
|
|
52
|
-
|
52
|
+
# The seller e-mail. Will be used to verify IPN.
|
53
|
+
#
|
54
|
+
attr_accessor :email
|
55
|
+
end
|
53
56
|
|
54
57
|
# Just a shortcut for <tt>PayPal::Recurring::Base.new</tt>.
|
55
58
|
#
|
@@ -44,7 +44,7 @@ module PayPal
|
|
44
44
|
#
|
45
45
|
def checkout
|
46
46
|
params = collect(:amount, :return_url, :cancel_url, :currency, :description, :ipn_url).merge(:payment_action => "Authorization", :no_shipping => 1, :L_BILLINGTYPE0 => "RecurringPayments")
|
47
|
-
request.
|
47
|
+
request.run(:checkout, params)
|
48
48
|
end
|
49
49
|
|
50
50
|
# Suspend a recurring profile.
|
@@ -54,7 +54,7 @@ module PayPal
|
|
54
54
|
# response = ppr.suspend
|
55
55
|
#
|
56
56
|
def suspend
|
57
|
-
request.
|
57
|
+
request.run(:manage_profile, :action => :suspend, :profile_id => profile_id)
|
58
58
|
end
|
59
59
|
|
60
60
|
# Reactivate a suspended recurring profile.
|
@@ -63,7 +63,7 @@ module PayPal
|
|
63
63
|
# response = ppr.reactivate
|
64
64
|
#
|
65
65
|
def reactivate
|
66
|
-
request.
|
66
|
+
request.run(:manage_profile, :action => :reactivate, :profile_id => profile_id)
|
67
67
|
end
|
68
68
|
|
69
69
|
# Cancel a recurring profile.
|
@@ -73,7 +73,7 @@ module PayPal
|
|
73
73
|
# response = ppr.cancel
|
74
74
|
#
|
75
75
|
def cancel
|
76
|
-
request.
|
76
|
+
request.run(:manage_profile, :action => :cancel, :profile_id => profile_id)
|
77
77
|
end
|
78
78
|
|
79
79
|
# Return checkout details.
|
@@ -82,7 +82,7 @@ module PayPal
|
|
82
82
|
# response = ppr.checkout_details
|
83
83
|
#
|
84
84
|
def checkout_details
|
85
|
-
request.
|
85
|
+
request.run(:details, :token => token)
|
86
86
|
end
|
87
87
|
|
88
88
|
# Request payment.
|
@@ -98,7 +98,7 @@ module PayPal
|
|
98
98
|
#
|
99
99
|
def request_payment
|
100
100
|
params = collect(:amount, :return_url, :cancel_url, :ipn_url, :currency, :description, :payer_id, :token).merge(:payment_action => "Sale")
|
101
|
-
request.
|
101
|
+
request.run(:payment, params)
|
102
102
|
end
|
103
103
|
|
104
104
|
# Create a recurring billing profile.
|
@@ -122,7 +122,7 @@ module PayPal
|
|
122
122
|
#
|
123
123
|
def create_recurring_profile
|
124
124
|
params = collect(:amount, :currency, :description, :payer_id, :token, :reference, :start_at, :failed, :outstanding, :ipn_url, :frequency, :period, :email)
|
125
|
-
request.
|
125
|
+
request.run(:create_profile, params)
|
126
126
|
end
|
127
127
|
|
128
128
|
# Retrieve information about existing recurring profile.
|
@@ -131,7 +131,7 @@ module PayPal
|
|
131
131
|
# response = ppr.profile
|
132
132
|
#
|
133
133
|
def profile
|
134
|
-
request.
|
134
|
+
request.run(:profile, :profile_id => profile_id)
|
135
135
|
end
|
136
136
|
|
137
137
|
private
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module PayPal
|
2
|
+
module Recurring
|
3
|
+
class Notification
|
4
|
+
attr_reader :params
|
5
|
+
|
6
|
+
def initialize(params = {})
|
7
|
+
self.params = params
|
8
|
+
end
|
9
|
+
|
10
|
+
def params=(params)
|
11
|
+
@params = params.inject({}) do |buffer, (name,value)|
|
12
|
+
buffer.merge(name.to_sym => value)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def request
|
17
|
+
@request ||= PayPal::Recurring::Request.new.tap do |request|
|
18
|
+
request.uri = URI.parse("#{PayPal::Recurring.site_endpoint}?cmd=_notify-validate")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def response
|
23
|
+
@response ||= request.post(params.merge(:cmd => "_notify-validate"))
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid?
|
27
|
+
completed? && verified? && params[:receiver_email] == PayPal::Recurring.email && params[:receiver_id] == PayPal::Recurring.seller_id && params[:txn_type] == "recurring_payment"
|
28
|
+
end
|
29
|
+
|
30
|
+
def completed?
|
31
|
+
status == "Completed"
|
32
|
+
end
|
33
|
+
|
34
|
+
def transaction_id
|
35
|
+
params[:txn_id]
|
36
|
+
end
|
37
|
+
|
38
|
+
def fee
|
39
|
+
params[:mc_currency]
|
40
|
+
end
|
41
|
+
|
42
|
+
def reference
|
43
|
+
params[:rp_invoice_id]
|
44
|
+
end
|
45
|
+
|
46
|
+
def payment_id
|
47
|
+
params[:recurring_payment_id]
|
48
|
+
end
|
49
|
+
|
50
|
+
def next_payment_date
|
51
|
+
Time.parse(params[:next_payment_date]) if params[:next_payment_date]
|
52
|
+
end
|
53
|
+
|
54
|
+
def paid_at
|
55
|
+
Time.parse params[:time_created] if params[:time_created]
|
56
|
+
end
|
57
|
+
|
58
|
+
def amount
|
59
|
+
params[:amount]
|
60
|
+
end
|
61
|
+
|
62
|
+
def currency
|
63
|
+
params[:mc_currency]
|
64
|
+
end
|
65
|
+
|
66
|
+
def status
|
67
|
+
params[:payment_status]
|
68
|
+
end
|
69
|
+
|
70
|
+
def verified?
|
71
|
+
response.body == "VERIFIED"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -57,12 +57,14 @@ module PayPal
|
|
57
57
|
|
58
58
|
CA_FILE = File.dirname(__FILE__) + "/cacert.pem"
|
59
59
|
|
60
|
+
attr_accessor :uri
|
61
|
+
|
60
62
|
# Do a POST request to PayPal API.
|
61
63
|
# The +method+ argument is the name of the API method you want to invoke.
|
62
64
|
# For instance, if you want to request a new checkout token, you may want
|
63
65
|
# to do something like:
|
64
66
|
#
|
65
|
-
# response = request.
|
67
|
+
# response = request.run(:express_checkout)
|
66
68
|
#
|
67
69
|
# We normalize the methods name. For a list of what's being covered, refer to
|
68
70
|
# PayPal::Recurring::Request::METHODS constant.
|
@@ -70,15 +72,27 @@ module PayPal
|
|
70
72
|
# The params hash can use normalized names. For a list, check the
|
71
73
|
# PayPal::Recurring::Request::ATTRIBUTES constant.
|
72
74
|
#
|
73
|
-
def
|
75
|
+
def run(method, params = {})
|
74
76
|
params = prepare_params(params.merge(:method => METHODS.fetch(method, method.to_s)))
|
75
|
-
|
76
|
-
request["User-Agent"] = "PayPal::Recurring/#{PayPal::Recurring::Version::STRING}"
|
77
|
-
request.form_data = params
|
78
|
-
response = client.request(request)
|
77
|
+
response = post(params)
|
79
78
|
Response.process(method, response)
|
80
79
|
end
|
81
80
|
|
81
|
+
#
|
82
|
+
#
|
83
|
+
def request
|
84
|
+
@request ||= Net::HTTP::Post.new(uri.request_uri).tap do |http|
|
85
|
+
http["User-Agent"] = "PayPal::Recurring/#{PayPal::Recurring::Version::STRING}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
#
|
91
|
+
def post(params = {})
|
92
|
+
request.form_data = params
|
93
|
+
client.request(request)
|
94
|
+
end
|
95
|
+
|
82
96
|
# Join params and normalize attribute names.
|
83
97
|
#
|
84
98
|
def prepare_params(params) # :nodoc:
|
@@ -0,0 +1,32 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
4
|
+
method: :post
|
5
|
+
uri: https://www.sandbox.paypal.com:443/cgi-bin/webscr?cmd=_notify-validate
|
6
|
+
body: cmd=_notify-validate
|
7
|
+
headers:
|
8
|
+
user-agent:
|
9
|
+
- PayPal::Recurring/0.1.0
|
10
|
+
content-type:
|
11
|
+
- application/x-www-form-urlencoded
|
12
|
+
response: !ruby/struct:VCR::Response
|
13
|
+
status: !ruby/struct:VCR::ResponseStatus
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
date:
|
18
|
+
- Mon, 27 Jun 2011 17:39:42 GMT
|
19
|
+
server:
|
20
|
+
- Apache
|
21
|
+
set-cookie:
|
22
|
+
- c9MWDuvPtT9GIMyPc3jwol1VSlO=FYMA2gxaecqXl8Q9SSeevuaQcqfcQcwNGw_shFaqV4wYiWT3ZUcQ4O8NLvXqevPJfliR0yse8Z4bzZ8A37MQKM6Q_ci6wnYOkfGZSxZYa_hNLMvR6QHnGyW6u94YxhYQpgu0VG%7cySXso7WZVjU8pXiTJS488DAO3YqW5S6DsAZMY8TN22H5J8gW1As5DlqX1pm60R5dWee5wm%7cdMLFsFZz_xjN2U4nbQ71pdvMUEch5_rqq4NReBSNMz7j3ry9JJhQ1J0X6pqjinKs-kO5NG%7c1309196387; domain=.paypal.com; path=/; Secure; HttpOnly
|
23
|
+
- cookie_check=yes; expires=Thu, 24-Jun-2021 17:39:47 GMT; domain=.paypal.com; path=/; Secure; HttpOnly
|
24
|
+
- navcmd=_notify-validate; domain=.paypal.com; path=/; Secure; HttpOnly
|
25
|
+
- navlns=0.0; expires=Sun, 22-Jun-2031 17:39:47 GMT; domain=.paypal.com; path=/; Secure; HttpOnly
|
26
|
+
- Apache=10.72.109.11.1309196382543853; path=/; expires=Wed, 19-Jun-41 17:39:42 GMT
|
27
|
+
transfer-encoding:
|
28
|
+
- chunked
|
29
|
+
content-type:
|
30
|
+
- text/html; charset=UTF-8
|
31
|
+
body: INVALID
|
32
|
+
http_version: "1.1"
|
@@ -0,0 +1,32 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
4
|
+
method: :post
|
5
|
+
uri: https://www.sandbox.paypal.com:443/cgi-bin/webscr?cmd=_notify-validate
|
6
|
+
body: test_ipn=1&payment_type=echeck&payment_date=06%3a16%3a11%20Jun%2027%2c%202011%20PDT&payment_status=Completed&pending_reason=echeck&address_status=confirmed&payer_status=verified&first_name=John&last_name=Smith&payer_email=buyer%40paypalsandbox.com&payer_id=TESTBUYERID01&address_name=John%20Smith&address_country=United%20States&address_country_code=US&address_zip=95131&address_state=CA&address_city=San%20Jose&address_street=123%2c%20any%20street&business=seller%40paypalsandbox.com&receiver_email=seller%40paypalsandbox.com&receiver_id=TESTSELLERID1&residence_country=US&item_name=something&item_number=AK-1234&quantity=1&shipping=3.04&tax=2.02&mc_currency=USD&mc_fee=0.44&mc_gross=12.34&txn_type=web_accept&txn_id=116271316¬ify_version=2.1&custom=xyz123&invoice=abc1234&charset=windows-1252&verify_sign=AvgHA1TpBJYQMa-x3XsZYuQd7MkKAMUFy7f2a9G4UNFmNHHXGnfAFi3l&cmd=_notify-validate
|
7
|
+
headers:
|
8
|
+
user-agent:
|
9
|
+
- PayPal::Recurring/0.1.0
|
10
|
+
content-type:
|
11
|
+
- application/x-www-form-urlencoded
|
12
|
+
response: !ruby/struct:VCR::Response
|
13
|
+
status: !ruby/struct:VCR::ResponseStatus
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
date:
|
18
|
+
- Mon, 27 Jun 2011 17:37:09 GMT
|
19
|
+
server:
|
20
|
+
- Apache
|
21
|
+
set-cookie:
|
22
|
+
- c9MWDuvPtT9GIMyPc3jwol1VSlO=EShGvdSJTkQTmhIi4jIAvW9REPYfLjRSo3BqPdRvBymVBvHIai4jnMHE9UzQDrz7FgAtLCUw0V0VroudhtcfoaNLca2TZq61mMSzEHPHgwAj5ON8rmHCr_IjY_AkKI885AFFLW%7c-PiLEQg9LK_E6xg7biKrMLHv97B5cP5yT2R1l6g_ZNq-3SDSCAm-9VQdvpJSnrGNtfsrrG%7cvdBU3UXz8sDrfFIOKP_zwmNkSm8nNcKCATxNvMpGb4VOdGI4Sjia0YCorXMBWxpjKuAip0%7c1309196230; domain=.paypal.com; path=/; Secure; HttpOnly
|
23
|
+
- cookie_check=yes; expires=Thu, 24-Jun-2021 17:37:10 GMT; domain=.paypal.com; path=/; Secure; HttpOnly
|
24
|
+
- navcmd=_notify-validate; domain=.paypal.com; path=/; Secure; HttpOnly
|
25
|
+
- navlns=0.0; expires=Sun, 22-Jun-2031 17:37:10 GMT; domain=.paypal.com; path=/; Secure; HttpOnly
|
26
|
+
- Apache=10.72.109.11.1309196229102128; path=/; expires=Wed, 19-Jun-41 17:37:09 GMT
|
27
|
+
transfer-encoding:
|
28
|
+
- chunked
|
29
|
+
content-type:
|
30
|
+
- text/html; charset=UTF-8
|
31
|
+
body: VERIFIED
|
32
|
+
http_version: "1.1"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe PayPal::Recurring::Notification do
|
4
|
+
context "when successful" do
|
5
|
+
use_vcr_cassette "notification/success"
|
6
|
+
|
7
|
+
it "verifies notification" do
|
8
|
+
subject.params = {"test_ipn"=>"1", "payment_type"=>"echeck", "payment_date"=>"06:16:11 Jun 27, 2011 PDT", "payment_status"=>"Completed", "pending_reason"=>"echeck", "address_status"=>"confirmed", "payer_status"=>"verified", "first_name"=>"John", "last_name"=>"Smith", "payer_email"=>"buyer@paypalsandbox.com", "payer_id"=>"TESTBUYERID01", "address_name"=>"John Smith", "address_country"=>"United States", "address_country_code"=>"US", "address_zip"=>"95131", "address_state"=>"CA", "address_city"=>"San Jose", "address_street"=>"123, any street", "business"=>"seller@paypalsandbox.com", "receiver_email"=>"seller@paypalsandbox.com", "receiver_id"=>"TESTSELLERID1", "residence_country"=>"US", "item_name"=>"something", "item_number"=>"AK-1234", "quantity"=>"1", "shipping"=>"3.04", "tax"=>"2.02", "mc_currency"=>"USD", "mc_fee"=>"0.44", "mc_gross"=>"12.34", "txn_type"=>"web_accept", "txn_id"=>"116271316", "notify_version"=>"2.1", "custom"=>"xyz123", "invoice"=>"abc1234", "charset"=>"windows-1252", "verify_sign"=>"A12AYqq6LElPcpXaQx48GiroLHnMAoQPnK0Z7aRwXUOpg1GfDaE15mFN"}
|
9
|
+
subject.should be_verified
|
10
|
+
subject.should be_completed
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when failure" do
|
15
|
+
use_vcr_cassette "notification/failure"
|
16
|
+
|
17
|
+
it "verifies notification" do
|
18
|
+
subject.params = {}
|
19
|
+
subject.should_not be_verified
|
20
|
+
subject.should_not be_completed
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,12 +1,6 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe PayPal::Recurring do
|
4
|
-
describe ".logger" do
|
5
|
-
it "has a default logging" do
|
6
|
-
PayPal::Recurring.logger.should be_a(Logger)
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
4
|
describe ".new" do
|
11
5
|
it "instantiates PayPal::Recurring::Base" do
|
12
6
|
PayPal::Recurring.new.should be_a(PayPal::Recurring::Base)
|
data/spec/paypal/request_spec.rb
CHANGED
@@ -19,7 +19,7 @@ describe PayPal::Recurring::Request do
|
|
19
19
|
describe "#post" do
|
20
20
|
let(:request) {
|
21
21
|
FakeWeb.register_uri :post, "https://api-3t.sandbox.paypal.com/nvp", :status => 200
|
22
|
-
subject.
|
22
|
+
subject.run(:checkout)
|
23
23
|
CGI.parse(FakeWeb.last_request.body)
|
24
24
|
}
|
25
25
|
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: paypal-recurring
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.1.
|
5
|
+
version: 0.1.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Nando Vieira
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-06-
|
13
|
+
date: 2011-06-28 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
@@ -89,6 +89,7 @@ files:
|
|
89
89
|
- lib/paypal/recurring.rb
|
90
90
|
- lib/paypal/recurring/base.rb
|
91
91
|
- lib/paypal/recurring/cacert.pem
|
92
|
+
- lib/paypal/recurring/notification.rb
|
92
93
|
- lib/paypal/recurring/request.rb
|
93
94
|
- lib/paypal/recurring/response.rb
|
94
95
|
- lib/paypal/recurring/response/base.rb
|
@@ -106,6 +107,8 @@ files:
|
|
106
107
|
- spec/fixtures/details/cancelled.yml
|
107
108
|
- spec/fixtures/details/failure.yml
|
108
109
|
- spec/fixtures/details/success.yml
|
110
|
+
- spec/fixtures/notification/failure.yml
|
111
|
+
- spec/fixtures/notification/success.yml
|
109
112
|
- spec/fixtures/payment/failure.yml
|
110
113
|
- spec/fixtures/payment/success.yml
|
111
114
|
- spec/fixtures/profile/cancel/failure.yml
|
@@ -116,6 +119,7 @@ files:
|
|
116
119
|
- spec/fixtures/profile/success.yml
|
117
120
|
- spec/fixtures/profile/suspend/failure.yml
|
118
121
|
- spec/fixtures/profile/suspend/success.yml
|
122
|
+
- spec/paypal/notification_spec.rb
|
119
123
|
- spec/paypal/recurring_spec.rb
|
120
124
|
- spec/paypal/request_spec.rb
|
121
125
|
- spec/paypal/response/checkout_details_spec.rb
|
@@ -138,7 +142,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
138
142
|
requirements:
|
139
143
|
- - ">="
|
140
144
|
- !ruby/object:Gem::Version
|
141
|
-
hash: -
|
145
|
+
hash: -1456604981268972750
|
142
146
|
segments:
|
143
147
|
- 0
|
144
148
|
version: "0"
|
@@ -147,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
151
|
requirements:
|
148
152
|
- - ">="
|
149
153
|
- !ruby/object:Gem::Version
|
150
|
-
hash: -
|
154
|
+
hash: -1456604981268972750
|
151
155
|
segments:
|
152
156
|
- 0
|
153
157
|
version: "0"
|
@@ -166,6 +170,8 @@ test_files:
|
|
166
170
|
- spec/fixtures/details/cancelled.yml
|
167
171
|
- spec/fixtures/details/failure.yml
|
168
172
|
- spec/fixtures/details/success.yml
|
173
|
+
- spec/fixtures/notification/failure.yml
|
174
|
+
- spec/fixtures/notification/success.yml
|
169
175
|
- spec/fixtures/payment/failure.yml
|
170
176
|
- spec/fixtures/payment/success.yml
|
171
177
|
- spec/fixtures/profile/cancel/failure.yml
|
@@ -176,6 +182,7 @@ test_files:
|
|
176
182
|
- spec/fixtures/profile/success.yml
|
177
183
|
- spec/fixtures/profile/suspend/failure.yml
|
178
184
|
- spec/fixtures/profile/suspend/success.yml
|
185
|
+
- spec/paypal/notification_spec.rb
|
179
186
|
- spec/paypal/recurring_spec.rb
|
180
187
|
- spec/paypal/request_spec.rb
|
181
188
|
- spec/paypal/response/checkout_details_spec.rb
|