paypal-recurring 0.1.6 → 1.0.0
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 +12 -0
- data/Gemfile.lock +32 -31
- data/README.rdoc +21 -5
- data/lib/paypal/recurring/base.rb +119 -4
- data/lib/paypal/recurring/notification.rb +15 -13
- data/lib/paypal/recurring/request.rb +38 -2
- data/lib/paypal/recurring/response.rb +4 -1
- data/lib/paypal/recurring/response/payment.rb +6 -5
- data/lib/paypal/recurring/response/profile.rb +4 -3
- data/lib/paypal/recurring/response/refund.rb +23 -0
- data/lib/paypal/recurring/version.rb +3 -3
- data/paypal-recurring.gemspec +7 -5
- data/spec/fixtures/checkout/failure.yml +33 -21
- data/spec/fixtures/checkout/success.yml +33 -21
- data/spec/fixtures/create_profile/failure.yml +33 -21
- data/spec/fixtures/create_profile/success.yml +33 -21
- data/spec/fixtures/details/cancelled.yml +33 -21
- data/spec/fixtures/details/failure.yml +33 -21
- data/spec/fixtures/details/success.yml +33 -21
- data/spec/fixtures/ipn/recurring_payment_skipped.json +30 -0
- data/spec/fixtures/notification/failure.yml +43 -25
- data/spec/fixtures/notification/success.yml +33 -15
- data/spec/fixtures/payment/failure.yml +33 -21
- data/spec/fixtures/payment/success.yml +33 -21
- data/spec/fixtures/profile/cancel/failure.yml +33 -21
- data/spec/fixtures/profile/cancel/success.yml +33 -21
- data/spec/fixtures/profile/failure.yml +33 -21
- data/spec/fixtures/profile/reactivate/failure.yml +33 -21
- data/spec/fixtures/profile/reactivate/success.yml +33 -21
- data/spec/fixtures/profile/success.yml +33 -21
- data/spec/fixtures/profile/suspend/failure.yml +33 -21
- data/spec/fixtures/profile/suspend/success.yml +33 -21
- data/spec/fixtures/refund/failure.yml +38 -0
- data/spec/fixtures/refund/success.yml +38 -0
- data/spec/fixtures/update_profile/failure.yml +38 -0
- data/spec/fixtures/update_profile/profile.yml +38 -0
- data/spec/fixtures/update_profile/success.yml +38 -0
- data/spec/paypal/request_spec.rb +17 -0
- data/spec/paypal/response/checkout_details_spec.rb +7 -8
- data/spec/paypal/response/checkout_spec.rb +1 -1
- data/spec/paypal/response/create_recurring_profile_spec.rb +4 -4
- data/spec/paypal/response/manage_profile_spec.rb +11 -11
- data/spec/paypal/response/profile_spec.rb +9 -8
- data/spec/paypal/response/refund_spec.rb +33 -0
- data/spec/paypal/response/request_payment_spec.rb +4 -4
- data/spec/paypal/response/update_recurring_profile_spec.rb +47 -0
- data/spec/spec_helper.rb +8 -7
- metadata +135 -68
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,45 +1,46 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
paypal-recurring (0.
|
4
|
+
paypal-recurring (1.0.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: http://rubygems.org/
|
8
8
|
specs:
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
activesupport (3.2.3)
|
10
|
+
i18n (~> 0.6)
|
11
|
+
multi_json (~> 1.0)
|
12
|
+
awesome_print (1.0.2)
|
13
|
+
coderay (1.0.6)
|
14
|
+
diff-lcs (1.1.3)
|
12
15
|
fakeweb (1.3.0)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
rspec
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
ruby-debug-base19 (>= 0.11.19)
|
32
|
-
ruby_core_source (0.1.5)
|
33
|
-
archive-tar-minitar (>= 0.5.2)
|
34
|
-
vcr (1.10.0)
|
16
|
+
i18n (0.6.0)
|
17
|
+
method_source (0.7.1)
|
18
|
+
multi_json (1.3.2)
|
19
|
+
pry (0.9.9.3)
|
20
|
+
coderay (~> 1.0.5)
|
21
|
+
method_source (~> 0.7.1)
|
22
|
+
slop (>= 2.4.4, < 3)
|
23
|
+
rake (0.9.2.2)
|
24
|
+
rspec (2.9.0)
|
25
|
+
rspec-core (~> 2.9.0)
|
26
|
+
rspec-expectations (~> 2.9.0)
|
27
|
+
rspec-mocks (~> 2.9.0)
|
28
|
+
rspec-core (2.9.0)
|
29
|
+
rspec-expectations (2.9.1)
|
30
|
+
diff-lcs (~> 1.1.3)
|
31
|
+
rspec-mocks (2.9.0)
|
32
|
+
slop (2.4.4)
|
33
|
+
vcr (2.1.0)
|
35
34
|
|
36
35
|
PLATFORMS
|
37
36
|
ruby
|
38
37
|
|
39
38
|
DEPENDENCIES
|
40
|
-
|
39
|
+
activesupport
|
40
|
+
awesome_print
|
41
|
+
fakeweb
|
41
42
|
paypal-recurring!
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
vcr
|
43
|
+
pry
|
44
|
+
rake
|
45
|
+
rspec
|
46
|
+
vcr
|
data/README.rdoc
CHANGED
@@ -77,6 +77,26 @@ Finally, you need to create a new recurring profile.
|
|
77
77
|
response = ppr.create_recurring_profile
|
78
78
|
puts response.profile_id
|
79
79
|
|
80
|
+
(Optionally) You can specify a trial period, frequency, and length.
|
81
|
+
|
82
|
+
ppr = PayPal::Recurring.new({
|
83
|
+
:amount => "9.00",
|
84
|
+
:currency => "USD",
|
85
|
+
:description => "Awesome - Monthly Subscription",
|
86
|
+
:ipn_url => "http://example.com/paypal/ipn",
|
87
|
+
:frequency => 1,
|
88
|
+
:token => "EC-05C46042TU8306821",
|
89
|
+
:period => :monthly,
|
90
|
+
:reference => "1234",
|
91
|
+
:payer_id => "WTTS5KC2T46YU",
|
92
|
+
:start_at => Time.now,
|
93
|
+
:failed => 1,
|
94
|
+
:outstanding => :next_billing,
|
95
|
+
:trial_length => 1,
|
96
|
+
:trial_period => :monthly,
|
97
|
+
:trial_frequency => 1
|
98
|
+
})
|
99
|
+
|
80
100
|
You can manage your recurring profile.
|
81
101
|
|
82
102
|
ppr = PayPal::Recurring.new(:profile_id => "I-VCEL6TRG35CU")
|
@@ -91,15 +111,11 @@ You should save two paramaters to your database: <tt>TOKEN</tt> and <tt>PROFILEI
|
|
91
111
|
<tt>TOKEN</tt> is required when user returns to your website after he authorizes (or not) the billing process. You
|
92
112
|
need to save it so you can find him later. You can remove this info after payment and recurring profile are set.
|
93
113
|
|
94
|
-
The <tt>PROFILEID</tt> allows you to manage the recurring profile, like
|
114
|
+
The <tt>PROFILEID</tt> allows you to manage the recurring profile, like cancelling billing when an user don't
|
95
115
|
want to use your service anymore.
|
96
116
|
|
97
117
|
<b>NOTE:</b> TOKEN will expire after approximately 3 hours.
|
98
118
|
|
99
|
-
== TO-DO
|
100
|
-
|
101
|
-
* handle Instant Payment Notifications (IPN)
|
102
|
-
|
103
119
|
== Maintainer
|
104
120
|
|
105
121
|
* Nando Vieira (http://nandovieira.com.br)
|
@@ -5,6 +5,7 @@ module PayPal
|
|
5
5
|
attr_accessor :cancel_url
|
6
6
|
attr_accessor :currency
|
7
7
|
attr_accessor :description
|
8
|
+
attr_accessor :note
|
8
9
|
attr_accessor :email
|
9
10
|
attr_accessor :failed
|
10
11
|
attr_accessor :frequency
|
@@ -17,9 +18,19 @@ module PayPal
|
|
17
18
|
attr_accessor :period
|
18
19
|
attr_accessor :profile_id
|
19
20
|
attr_accessor :reference
|
21
|
+
attr_accessor :refund_type
|
20
22
|
attr_accessor :return_url
|
21
23
|
attr_accessor :start_at
|
22
24
|
attr_accessor :token
|
25
|
+
attr_accessor :transaction_id
|
26
|
+
attr_accessor :item_category
|
27
|
+
attr_accessor :item_name
|
28
|
+
attr_accessor :item_amount
|
29
|
+
attr_accessor :item_quantity
|
30
|
+
attr_accessor :trial_frequency
|
31
|
+
attr_accessor :trial_length
|
32
|
+
attr_accessor :trial_period
|
33
|
+
attr_accessor :trial_amount
|
23
34
|
|
24
35
|
def initialize(options = {})
|
25
36
|
options.each {|name, value| send("#{name}=", value)}
|
@@ -53,7 +64,11 @@ module PayPal
|
|
53
64
|
:cancel_url,
|
54
65
|
:currency,
|
55
66
|
:description,
|
56
|
-
:ipn_url
|
67
|
+
:ipn_url,
|
68
|
+
:item_category,
|
69
|
+
:item_name,
|
70
|
+
:item_amount,
|
71
|
+
:item_quantity
|
57
72
|
).merge(
|
58
73
|
:payment_action => "Authorization",
|
59
74
|
:no_shipping => 1,
|
@@ -113,7 +128,22 @@ module PayPal
|
|
113
128
|
# response.completed? && response.approved?
|
114
129
|
#
|
115
130
|
def request_payment
|
116
|
-
params = collect(
|
131
|
+
params = collect(
|
132
|
+
:amount,
|
133
|
+
:return_url,
|
134
|
+
:cancel_url,
|
135
|
+
:ipn_url,
|
136
|
+
:currency,
|
137
|
+
:description,
|
138
|
+
:payer_id,
|
139
|
+
:token,
|
140
|
+
:reference,
|
141
|
+
:item_category,
|
142
|
+
:item_name,
|
143
|
+
:item_amount,
|
144
|
+
:item_quantity
|
145
|
+
).merge(:payment_action => "Sale")
|
146
|
+
|
117
147
|
request.run(:payment, params)
|
118
148
|
end
|
119
149
|
|
@@ -133,16 +163,77 @@ module PayPal
|
|
133
163
|
# :payer_id => "WTTS5KC2T46YU",
|
134
164
|
# :start_at => Time.now,
|
135
165
|
# :failed => 1,
|
136
|
-
# :outstanding => :next_billing
|
166
|
+
# :outstanding => :next_billing,
|
167
|
+
# :trial_period => :monthly,
|
168
|
+
# :trial_length => 1,
|
169
|
+
# :trial_frequency => 1,
|
170
|
+
# :trial_amount => 0.00
|
137
171
|
# })
|
138
172
|
#
|
139
173
|
# response = ppr.create_recurring_profile
|
140
174
|
#
|
141
175
|
def create_recurring_profile
|
142
|
-
params = collect(
|
176
|
+
params = collect(
|
177
|
+
:amount,
|
178
|
+
:initial_amount,
|
179
|
+
:initial_amount_action,
|
180
|
+
:currency,
|
181
|
+
:description,
|
182
|
+
:payer_id,
|
183
|
+
:token,
|
184
|
+
:reference,
|
185
|
+
:start_at,
|
186
|
+
:failed,
|
187
|
+
:outstanding,
|
188
|
+
:ipn_url,
|
189
|
+
:frequency,
|
190
|
+
:period,
|
191
|
+
:email,
|
192
|
+
:trial_length,
|
193
|
+
:trial_period,
|
194
|
+
:trial_frequency,
|
195
|
+
:trial_amount,
|
196
|
+
:item_category,
|
197
|
+
:item_name,
|
198
|
+
:item_amount,
|
199
|
+
:item_quantity
|
200
|
+
)
|
143
201
|
request.run(:create_profile, params)
|
144
202
|
end
|
145
203
|
|
204
|
+
# Update a recurring billing profile.
|
205
|
+
#
|
206
|
+
# ppr = PayPal::Recurring.new({
|
207
|
+
# :amount => "99.00",
|
208
|
+
# :currency => "USD",
|
209
|
+
# :description => "Awesome - Monthly Subscription",
|
210
|
+
# :note => "Changed plan to Gold",
|
211
|
+
# :ipn_url => "http://example.com/paypal/ipn",
|
212
|
+
# :reference => "1234",
|
213
|
+
# :profile_id => "I-VCEL6TRG35CU",
|
214
|
+
# :start_at => Time.now,
|
215
|
+
# :outstanding => :next_billing
|
216
|
+
# })
|
217
|
+
#
|
218
|
+
# response = ppr.update_recurring_profile
|
219
|
+
#
|
220
|
+
def update_recurring_profile
|
221
|
+
params = collect(
|
222
|
+
:amount,
|
223
|
+
:currency,
|
224
|
+
:description,
|
225
|
+
:note,
|
226
|
+
:profile_id,
|
227
|
+
:reference,
|
228
|
+
:start_at,
|
229
|
+
:outstanding,
|
230
|
+
:ipn_url,
|
231
|
+
:email
|
232
|
+
)
|
233
|
+
|
234
|
+
request.run(:update_profile, params)
|
235
|
+
end
|
236
|
+
|
146
237
|
# Retrieve information about existing recurring profile.
|
147
238
|
#
|
148
239
|
# ppr = PayPal::Recurring.new(:profile_id => "I-VCEL6TRG35CU")
|
@@ -152,6 +243,30 @@ module PayPal
|
|
152
243
|
request.run(:profile, :profile_id => profile_id)
|
153
244
|
end
|
154
245
|
|
246
|
+
# Request a refund.
|
247
|
+
# ppr = PayPal::Recurring.new({
|
248
|
+
# :profile_id => "I-VCEL6TRG35CU",
|
249
|
+
# :transaction_id => "ABCEDFGH",
|
250
|
+
# :reference => "1234",
|
251
|
+
# :refund_type => :partial,
|
252
|
+
# :amount => "9.00",
|
253
|
+
# :currency => "USD"
|
254
|
+
# })
|
255
|
+
# response = ppr.refund
|
256
|
+
#
|
257
|
+
def refund
|
258
|
+
params = collect(
|
259
|
+
:transaction_id,
|
260
|
+
:reference,
|
261
|
+
:refund_type,
|
262
|
+
:amount,
|
263
|
+
:currency,
|
264
|
+
:note
|
265
|
+
)
|
266
|
+
|
267
|
+
request.run(:refund, params)
|
268
|
+
end
|
269
|
+
|
155
270
|
private
|
156
271
|
# Collect specified attributes and build a hash out of it.
|
157
272
|
#
|
@@ -6,19 +6,21 @@ module PayPal
|
|
6
6
|
attr_reader :params
|
7
7
|
|
8
8
|
mapping({
|
9
|
-
:type
|
10
|
-
:transaction_id
|
11
|
-
:fee
|
12
|
-
:reference
|
13
|
-
:payment_id
|
14
|
-
:amount
|
15
|
-
:currency
|
16
|
-
:status
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
9
|
+
:type => :txn_type,
|
10
|
+
:transaction_id => :txn_id,
|
11
|
+
:fee => [:mc_fee, :payment_fee],
|
12
|
+
:reference => [:rp_invoice_id, :custom, :invoice],
|
13
|
+
:payment_id => :recurring_payment_id,
|
14
|
+
:amount => [:amount, :mc_gross, :payment_gross],
|
15
|
+
:currency => :mc_currency,
|
16
|
+
:status => :payment_status,
|
17
|
+
:pending_reason => :pending_reason,
|
18
|
+
:profile_status => :profile_status,
|
19
|
+
:payment_date => [:time_created, :payment_date],
|
20
|
+
:seller_id => :receiver_id,
|
21
|
+
:email => :receiver_email,
|
22
|
+
:initial_amount => :initial_payment_amount,
|
23
|
+
:payer_email => :payer_email
|
22
24
|
})
|
23
25
|
|
24
26
|
def initialize(params = {})
|
@@ -7,7 +7,9 @@ module PayPal
|
|
7
7
|
:details => "GetExpressCheckoutDetails",
|
8
8
|
:create_profile => "CreateRecurringPaymentsProfile",
|
9
9
|
:profile => "GetRecurringPaymentsProfileDetails",
|
10
|
-
:manage_profile => "ManageRecurringPaymentsProfileStatus"
|
10
|
+
:manage_profile => "ManageRecurringPaymentsProfileStatus",
|
11
|
+
:update_profile => "UpdateRecurringPaymentsProfile",
|
12
|
+
:refund => "RefundTransaction"
|
11
13
|
}
|
12
14
|
|
13
15
|
INITIAL_AMOUNT_ACTIONS = {
|
@@ -23,15 +25,30 @@ module PayPal
|
|
23
25
|
|
24
26
|
PERIOD = {
|
25
27
|
:daily => "Day",
|
28
|
+
:weekly => "Weekly",
|
26
29
|
:monthly => "Month",
|
27
30
|
:yearly => "Year"
|
28
31
|
}
|
29
32
|
|
33
|
+
TRIAL_PERIOD = {
|
34
|
+
:daily => "Day",
|
35
|
+
:weekly => "Weekly",
|
36
|
+
:monthly => "Month",
|
37
|
+
:yearly => "Year"
|
38
|
+
}
|
39
|
+
|
30
40
|
OUTSTANDING = {
|
31
41
|
:next_billing => "AddToNextBilling",
|
32
42
|
:no_auto => "NoAutoBill"
|
33
43
|
}
|
34
44
|
|
45
|
+
REFUND_TYPE = {
|
46
|
+
:full => "Full",
|
47
|
+
:partial => "Partial",
|
48
|
+
:external => "ExternalDispute",
|
49
|
+
:other => "Other"
|
50
|
+
}
|
51
|
+
|
35
52
|
ATTRIBUTES = {
|
36
53
|
:action => "ACTION",
|
37
54
|
:amount => ["PAYMENTREQUEST_0_AMT", "AMT"],
|
@@ -39,6 +56,11 @@ module PayPal
|
|
39
56
|
:cancel_url => "CANCELURL",
|
40
57
|
:currency => ["PAYMENTREQUEST_0_CURRENCYCODE", "CURRENCYCODE"],
|
41
58
|
:description => ["DESC", "PAYMENTREQUEST_0_DESC", "L_BILLINGAGREEMENTDESCRIPTION0"],
|
59
|
+
:note => "NOTE",
|
60
|
+
:item_category => "L_PAYMENTREQUEST_0_ITEMCATEGORY0",
|
61
|
+
:item_name => "L_PAYMENTREQUEST_0_NAME0",
|
62
|
+
:item_amount => "L_PAYMENTREQUEST_0_AMT0",
|
63
|
+
:item_quantity => "L_PAYMENTREQUEST_0_QTY0",
|
42
64
|
:email => "EMAIL",
|
43
65
|
:failed => "MAXFAILEDPAYMENTS",
|
44
66
|
:frequency => "BILLINGFREQUENCY",
|
@@ -55,12 +77,18 @@ module PayPal
|
|
55
77
|
:period => "BILLINGPERIOD",
|
56
78
|
:profile_id => "PROFILEID",
|
57
79
|
:reference => ["PROFILEREFERENCE", "PAYMENTREQUEST_0_CUSTOM", "PAYMENTREQUEST_0_INVNUM"],
|
80
|
+
:refund_type => "REFUNDTYPE",
|
58
81
|
:return_url => "RETURNURL",
|
59
82
|
:signature => "SIGNATURE",
|
60
83
|
:start_at => "PROFILESTARTDATE",
|
61
84
|
:token => "TOKEN",
|
85
|
+
:transaction_id => "TRANSACTIONID",
|
86
|
+
:trial_amount => "TRIALAMT",
|
87
|
+
:trial_frequency => "TRIALBILLINGFREQUENCY",
|
88
|
+
:trial_length => "TRIALTOTALBILLINGCYCLES",
|
89
|
+
:trial_period => "TRIALBILLINGPERIOD",
|
62
90
|
:username => "USER",
|
63
|
-
:version => "VERSION"
|
91
|
+
:version => "VERSION"
|
64
92
|
}
|
65
93
|
|
66
94
|
CA_FILE = File.dirname(__FILE__) + "/cacert.pem"
|
@@ -149,6 +177,10 @@ module PayPal
|
|
149
177
|
PERIOD.fetch(value.to_sym, value) if value
|
150
178
|
end
|
151
179
|
|
180
|
+
def build_trial_period(value)
|
181
|
+
TRIAL_PERIOD.fetch(value.to_sym, value) if value
|
182
|
+
end
|
183
|
+
|
152
184
|
def build_start_at(value) # :nodoc:
|
153
185
|
value.respond_to?(:strftime) ? value.strftime("%Y-%m-%dT%H:%M:%SZ") : value
|
154
186
|
end
|
@@ -157,6 +189,10 @@ module PayPal
|
|
157
189
|
OUTSTANDING.fetch(value.to_sym, value) if value
|
158
190
|
end
|
159
191
|
|
192
|
+
def build_refund_type(value) # :nodoc:
|
193
|
+
REFUND_TYPE.fetch(value.to_sym, value) if value
|
194
|
+
end
|
195
|
+
|
160
196
|
def build_action(value) # :nodoc:
|
161
197
|
ACTIONS.fetch(value.to_sym, value) if value
|
162
198
|
end
|
@@ -7,6 +7,7 @@ module PayPal
|
|
7
7
|
autoload :Payment, "paypal/recurring/response/payment"
|
8
8
|
autoload :ManageProfile, "paypal/recurring/response/manage_profile"
|
9
9
|
autoload :Profile, "paypal/recurring/response/profile"
|
10
|
+
autoload :Refund, "paypal/recurring/response/refund"
|
10
11
|
|
11
12
|
RESPONDERS = {
|
12
13
|
:checkout => "Checkout",
|
@@ -14,7 +15,9 @@ module PayPal
|
|
14
15
|
:payment => "Payment",
|
15
16
|
:profile => "Profile",
|
16
17
|
:create_profile => "ManageProfile",
|
17
|
-
:manage_profile => "ManageProfile"
|
18
|
+
:manage_profile => "ManageProfile",
|
19
|
+
:update_profile => "ManageProfile",
|
20
|
+
:refund => "Refund"
|
18
21
|
}
|
19
22
|
|
20
23
|
def self.process(method, response)
|