pay 2.4.2 → 2.6.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pay might be problematic. Click here for more details.

Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -4
  3. data/app/controllers/pay/webhooks/braintree_controller.rb +7 -53
  4. data/app/controllers/pay/webhooks/paddle_controller.rb +19 -18
  5. data/app/controllers/pay/webhooks/stripe_controller.rb +47 -0
  6. data/app/models/pay/charge.rb +22 -3
  7. data/app/models/pay/subscription.rb +23 -24
  8. data/app/views/pay/stripe/_checkout_button.html.erb +21 -0
  9. data/config/routes.rb +1 -1
  10. data/lib/pay.rb +13 -12
  11. data/lib/pay/billable.rb +33 -33
  12. data/lib/pay/billable/sync_email.rb +1 -1
  13. data/lib/pay/braintree.rb +34 -15
  14. data/lib/pay/braintree/authorization_error.rb +9 -0
  15. data/lib/pay/braintree/billable.rb +33 -30
  16. data/lib/pay/braintree/charge.rb +8 -10
  17. data/lib/pay/braintree/error.rb +9 -0
  18. data/lib/pay/braintree/subscription.rb +34 -15
  19. data/lib/pay/braintree/webhooks/subscription_canceled.rb +19 -0
  20. data/lib/pay/braintree/webhooks/subscription_charged_successfully.rb +24 -0
  21. data/lib/pay/braintree/webhooks/subscription_charged_unsuccessfully.rb +24 -0
  22. data/lib/pay/braintree/webhooks/subscription_expired.rb +19 -0
  23. data/lib/pay/braintree/webhooks/subscription_trial_ended.rb +19 -0
  24. data/lib/pay/braintree/webhooks/subscription_went_active.rb +19 -0
  25. data/lib/pay/braintree/webhooks/subscription_went_past_due.rb +19 -0
  26. data/lib/pay/engine.rb +0 -23
  27. data/lib/pay/errors.rb +0 -44
  28. data/lib/pay/paddle.rb +30 -16
  29. data/lib/pay/paddle/billable.rb +26 -22
  30. data/lib/pay/paddle/charge.rb +8 -12
  31. data/lib/pay/paddle/error.rb +9 -0
  32. data/lib/pay/paddle/subscription.rb +29 -18
  33. data/lib/pay/paddle/webhooks/subscription_cancelled.rb +3 -3
  34. data/lib/pay/paddle/webhooks/subscription_created.rb +15 -15
  35. data/lib/pay/paddle/webhooks/subscription_payment_refunded.rb +3 -3
  36. data/lib/pay/paddle/webhooks/subscription_payment_succeeded.rb +11 -11
  37. data/lib/pay/paddle/webhooks/subscription_updated.rb +11 -11
  38. data/lib/pay/stripe.rb +65 -15
  39. data/lib/pay/stripe/billable.rb +136 -69
  40. data/lib/pay/stripe/charge.rb +9 -15
  41. data/lib/pay/stripe/error.rb +9 -0
  42. data/lib/pay/stripe/subscription.rb +27 -11
  43. data/lib/pay/stripe/webhooks/charge_succeeded.rb +1 -20
  44. data/lib/pay/stripe/webhooks/subscription_created.rb +1 -0
  45. data/lib/pay/version.rb +1 -1
  46. data/lib/pay/webhooks.rb +13 -0
  47. data/lib/pay/webhooks/delegator.rb +61 -0
  48. metadata +20 -69
  49. data/lib/pay/paddle/webhooks.rb +0 -1
  50. data/lib/pay/stripe/webhooks.rb +0 -39
@@ -1,29 +1,23 @@
1
1
  module Pay
2
2
  module Stripe
3
- module Charge
4
- extend ActiveSupport::Concern
3
+ class Charge
4
+ attr_reader :pay_charge
5
5
 
6
- included do
7
- scope :stripe, -> { where(processor: :stripe) }
8
- end
6
+ delegate :processor_id, :owner, to: :pay_charge
9
7
 
10
- def stripe?
11
- processor == "stripe"
8
+ def initialize(pay_charge)
9
+ @pay_charge = pay_charge
12
10
  end
13
11
 
14
- def stripe_charge
12
+ def charge
15
13
  ::Stripe::Charge.retrieve(processor_id)
16
14
  rescue ::Stripe::StripeError => e
17
15
  raise Pay::Stripe::Error, e
18
16
  end
19
17
 
20
- def stripe_refund!(amount_to_refund)
21
- ::Stripe::Refund.create(
22
- charge: processor_id,
23
- amount: amount_to_refund
24
- )
25
-
26
- update(amount_refunded: amount_to_refund)
18
+ def refund!(amount_to_refund)
19
+ ::Stripe::Refund.create(charge: processor_id, amount: amount_to_refund)
20
+ pay_charge.update(amount_refunded: amount_to_refund)
27
21
  rescue ::Stripe::StripeError => e
28
22
  raise Pay::Stripe::Error, e
29
23
  end
@@ -0,0 +1,9 @@
1
+ module Pay
2
+ module Stripe
3
+ class Error < Pay::Error
4
+ def message
5
+ I18n.t("errors.stripe.#{result.code}", default: result.message)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,39 +1,55 @@
1
1
  module Pay
2
2
  module Stripe
3
- module Subscription
4
- extend ActiveSupport::Concern
3
+ class Subscription
4
+ attr_reader :pay_subscription
5
5
 
6
- def stripe_cancel
6
+ delegate :canceled?,
7
+ :ends_at,
8
+ :on_trial?,
9
+ :owner,
10
+ :processor_subscription,
11
+ :processor_id,
12
+ :prorate,
13
+ :processor_plan,
14
+ :quantity?,
15
+ :quantity,
16
+ to: :pay_subscription
17
+
18
+ def initialize(pay_subscription)
19
+ @pay_subscription = pay_subscription
20
+ end
21
+
22
+ def cancel
7
23
  subscription = processor_subscription
8
24
  subscription.cancel_at_period_end = true
9
25
  subscription.save
10
26
 
11
27
  new_ends_at = on_trial? ? trial_ends_at : Time.at(subscription.current_period_end)
12
- update(ends_at: new_ends_at)
28
+ pay_subscription.update(ends_at: new_ends_at)
13
29
  rescue ::Stripe::StripeError => e
14
30
  raise Pay::Stripe::Error, e
15
31
  end
16
32
 
17
- def stripe_cancel_now!
33
+ def cancel_now!
18
34
  processor_subscription.delete
19
- update(ends_at: Time.zone.now, status: :canceled)
35
+ pay_subscription.update(ends_at: Time.zone.now, status: :canceled)
20
36
  rescue ::Stripe::StripeError => e
21
37
  raise Pay::Stripe::Error, e
22
38
  end
23
39
 
24
- def stripe_on_grace_period?
40
+ def on_grace_period?
25
41
  canceled? && Time.zone.now < ends_at
26
42
  end
27
43
 
28
- def stripe_paused?
44
+ def paused?
29
45
  false
30
46
  end
31
47
 
32
- def stripe_pause
48
+ def pause
33
49
  raise NotImplementedError, "Stripe does not support pausing subscriptions"
34
50
  end
35
51
 
36
- def stripe_resume
52
+ def resume
37
53
  unless on_grace_period?
38
54
  raise StandardError, "You can only resume subscriptions within their grace period."
39
55
  end
@@ -47,7 +63,7 @@ module Pay
47
63
  raise Pay::Stripe::Error, e
48
64
  end
49
65
 
50
- def stripe_swap(plan)
66
+ def swap(plan)
51
67
  subscription = processor_subscription
52
68
  subscription.cancel_at_period_end = false
53
69
  subscription.plan = plan
@@ -9,27 +9,8 @@ module Pay
9
9
  return unless billable.present?
10
10
  return if billable.charges.where(processor_id: object.id).any?
11
11
 
12
- create_charge(billable, object)
13
- end
14
-
15
- def create_charge(billable, object)
16
- charge = billable.charges.find_or_initialize_by(
17
- processor: :stripe,
18
- processor_id: object.id
19
- )
20
-
21
- charge.update(
22
- amount: object.amount,
23
- card_last4: object.payment_method_details.card.last4,
24
- card_type: object.payment_method_details.card.brand,
25
- card_exp_month: object.payment_method_details.card.exp_month,
26
- card_exp_year: object.payment_method_details.card.exp_year,
27
- created_at: Time.zone.at(object.created)
28
- )
29
-
12
+ charge = Pay::Stripe::Billable.new(billable).save_pay_charge(object)
30
13
  notify_user(billable, charge)
31
-
32
- charge
33
14
  end
34
15
 
35
16
  def notify_user(billable, charge)
@@ -22,6 +22,7 @@ module Pay
22
22
  end
23
23
 
24
24
  subscription.quantity = object.quantity
25
+ subscription.status = object.status
25
26
  subscription.processor_plan = object.plan.id
26
27
  subscription.trial_ends_at = Time.at(object.trial_end) if object.trial_end.present?
27
28
 
data/lib/pay/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Pay
2
- VERSION = "2.4.2"
2
+ VERSION = "2.6.1"
3
3
  end
@@ -0,0 +1,13 @@
1
+ module Pay
2
+ module Webhooks
3
+ autoload :Delegator, "pay/webhooks/delegator"
4
+
5
+ class << self
6
+ delegate :configure, :instrument, to: :delegator
7
+
8
+ def delegator
9
+ @delegator ||= Delegator.new
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,61 @@
1
+ module Pay
2
+ module Webhooks
3
+ class Delegator
4
+ attr_reader :backend
5
+
6
+ def initialize
7
+ @backend = ActiveSupport::Notifications
8
+ end
9
+
10
+ # Configure DSL
11
+ def configure(&block)
12
+ raise ArgumentError, "must provide a block" unless block
13
+ block.arity.zero? ? instance_eval(&block) : yield(self)
14
+ end
15
+
16
+ # Subscribe to specific events
17
+ def subscribe(name, callable = nil, &block)
18
+ callable ||= block
19
+ backend.subscribe to_regexp(name), NotificationAdapter.new(callable)
20
+ end
21
+
22
+ # Listen to all events
23
+ def all(callable = nil, &block)
24
+ callable ||= block
25
+ subscribe nil, callable
26
+ end
27
+
28
+ # Unsubscribe
29
+ def unsubscribe(name)
30
+ backend.unsubscribe name
31
+ end
32
+
33
+ # Called to process an event
34
+ def instrument(event:, type:)
35
+ backend.instrument name_with_namespace(type), event
36
+ end
37
+
38
+ # Strips down to event data only
39
+ class NotificationAdapter
40
+ def initialize(subscriber)
41
+ @subscriber = subscriber
42
+ end
43
+
44
+ def call(*args)
45
+ payload = args.last
46
+ @subscriber.call(payload)
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def to_regexp(name)
53
+ %r{^#{Regexp.escape name_with_namespace(name)}}
54
+ end
55
+
56
+ def name_with_namespace(name, delimiter: ".")
57
+ [:pay, name].join(delimiter)
58
+ end
59
+ end
60
+ end
61
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pay
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.2
4
+ version: 2.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Charnes
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-01-22 00:00:00.000000000 Z
12
+ date: 2021-02-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -25,68 +25,6 @@ dependencies:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: '4.2'
28
- - !ruby/object:Gem::Dependency
29
- name: braintree
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - ">="
33
- - !ruby/object:Gem::Version
34
- version: 2.92.0
35
- - - "<"
36
- - !ruby/object:Gem::Version
37
- version: '4.0'
38
- type: :development
39
- prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- requirements:
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- version: 2.92.0
45
- - - "<"
46
- - !ruby/object:Gem::Version
47
- version: '4.0'
48
- - !ruby/object:Gem::Dependency
49
- name: stripe
50
- requirement: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '2.8'
55
- type: :development
56
- prerelease: false
57
- version_requirements: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '2.8'
62
- - !ruby/object:Gem::Dependency
63
- name: stripe_event
64
- requirement: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '2.3'
69
- type: :development
70
- prerelease: false
71
- version_requirements: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '2.3'
76
- - !ruby/object:Gem::Dependency
77
- name: paddle_pay
78
- requirement: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: 0.0.1
83
- type: :development
84
- prerelease: false
85
- version_requirements: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: 0.0.1
90
28
  - !ruby/object:Gem::Dependency
91
29
  name: minitest-rails
92
30
  requirement: !ruby/object:Gem::Requirement
@@ -163,7 +101,7 @@ dependencies:
163
101
  - - ">="
164
102
  - !ruby/object:Gem::Version
165
103
  version: '0'
166
- description: A Ruby on Rails subscription engine.
104
+ description: Stripe, Paddle, and Braintree payments for Ruby on Rails apps
167
105
  email:
168
106
  - jason@thecharnes.com
169
107
  - excid3@gmail.com
@@ -181,6 +119,7 @@ files:
181
119
  - app/controllers/pay/payments_controller.rb
182
120
  - app/controllers/pay/webhooks/braintree_controller.rb
183
121
  - app/controllers/pay/webhooks/paddle_controller.rb
122
+ - app/controllers/pay/webhooks/stripe_controller.rb
184
123
  - app/helpers/pay/application_helper.rb
185
124
  - app/jobs/pay/application_job.rb
186
125
  - app/jobs/pay/email_sync_job.rb
@@ -191,6 +130,7 @@ files:
191
130
  - app/models/pay/subscription.rb
192
131
  - app/views/layouts/pay/application.html.erb
193
132
  - app/views/pay/payments/show.html.erb
133
+ - app/views/pay/stripe/_checkout_button.html.erb
194
134
  - app/views/pay/user_mailer/payment_action_required.html.erb
195
135
  - app/views/pay/user_mailer/receipt.html.erb
196
136
  - app/views/pay/user_mailer/refund.html.erb
@@ -211,17 +151,26 @@ files:
211
151
  - lib/pay/billable.rb
212
152
  - lib/pay/billable/sync_email.rb
213
153
  - lib/pay/braintree.rb
154
+ - lib/pay/braintree/authorization_error.rb
214
155
  - lib/pay/braintree/billable.rb
215
156
  - lib/pay/braintree/charge.rb
157
+ - lib/pay/braintree/error.rb
216
158
  - lib/pay/braintree/subscription.rb
159
+ - lib/pay/braintree/webhooks/subscription_canceled.rb
160
+ - lib/pay/braintree/webhooks/subscription_charged_successfully.rb
161
+ - lib/pay/braintree/webhooks/subscription_charged_unsuccessfully.rb
162
+ - lib/pay/braintree/webhooks/subscription_expired.rb
163
+ - lib/pay/braintree/webhooks/subscription_trial_ended.rb
164
+ - lib/pay/braintree/webhooks/subscription_went_active.rb
165
+ - lib/pay/braintree/webhooks/subscription_went_past_due.rb
217
166
  - lib/pay/engine.rb
218
167
  - lib/pay/env.rb
219
168
  - lib/pay/errors.rb
220
169
  - lib/pay/paddle.rb
221
170
  - lib/pay/paddle/billable.rb
222
171
  - lib/pay/paddle/charge.rb
172
+ - lib/pay/paddle/error.rb
223
173
  - lib/pay/paddle/subscription.rb
224
- - lib/pay/paddle/webhooks.rb
225
174
  - lib/pay/paddle/webhooks/signature_verifier.rb
226
175
  - lib/pay/paddle/webhooks/subscription_cancelled.rb
227
176
  - lib/pay/paddle/webhooks/subscription_created.rb
@@ -233,8 +182,8 @@ files:
233
182
  - lib/pay/stripe.rb
234
183
  - lib/pay/stripe/billable.rb
235
184
  - lib/pay/stripe/charge.rb
185
+ - lib/pay/stripe/error.rb
236
186
  - lib/pay/stripe/subscription.rb
237
- - lib/pay/stripe/webhooks.rb
238
187
  - lib/pay/stripe/webhooks/charge_refunded.rb
239
188
  - lib/pay/stripe/webhooks/charge_succeeded.rb
240
189
  - lib/pay/stripe/webhooks/customer_deleted.rb
@@ -246,7 +195,9 @@ files:
246
195
  - lib/pay/stripe/webhooks/subscription_renewing.rb
247
196
  - lib/pay/stripe/webhooks/subscription_updated.rb
248
197
  - lib/pay/version.rb
249
- homepage: https://github.com/jasoncharnes/pay
198
+ - lib/pay/webhooks.rb
199
+ - lib/pay/webhooks/delegator.rb
200
+ homepage: https://github.com/pay-rails/pay
250
201
  licenses:
251
202
  - MIT
252
203
  metadata: {}
@@ -268,5 +219,5 @@ requirements: []
268
219
  rubygems_version: 3.2.3
269
220
  signing_key:
270
221
  specification_version: 4
271
- summary: A Ruby on Rails subscription engine.
222
+ summary: Payments engine for Ruby on Rails
272
223
  test_files: []
@@ -1 +0,0 @@
1
- Dir[File.join(__dir__, "webhooks", "**", "*.rb")].sort.each { |file| require file }
@@ -1,39 +0,0 @@
1
- require "stripe_event"
2
- Dir[File.join(__dir__, "webhooks", "**", "*.rb")].sort.each { |file| require file }
3
-
4
- StripeEvent.configure do |events|
5
- # Listen to the charge event to make sure we get non-subscription
6
- # purchases as well. Invoice is only for subscriptions and manual creation
7
- # so it does not include individual charges.
8
- events.subscribe "charge.succeeded", Pay::Stripe::Webhooks::ChargeSucceeded.new
9
- events.subscribe "charge.refunded", Pay::Stripe::Webhooks::ChargeRefunded.new
10
-
11
- # Warn user of upcoming charges for their subscription. This is handy for
12
- # notifying annual users their subscription will renew shortly.
13
- # This probably should be ignored for monthly subscriptions.
14
- events.subscribe "invoice.upcoming", Pay::Stripe::Webhooks::SubscriptionRenewing.new
15
-
16
- # Payment action is required to process an invoice
17
- events.subscribe "invoice.payment_action_required", Pay::Stripe::Webhooks::PaymentActionRequired.new
18
-
19
- # If a subscription is manually created on Stripe, we want to sync
20
- events.subscribe "customer.subscription.created", Pay::Stripe::Webhooks::SubscriptionCreated.new
21
-
22
- # If the plan, quantity, or trial ending date is updated on Stripe, we want to sync
23
- events.subscribe "customer.subscription.updated", Pay::Stripe::Webhooks::SubscriptionUpdated.new
24
-
25
- # When a customers subscription is canceled, we want to update our records
26
- events.subscribe "customer.subscription.deleted", Pay::Stripe::Webhooks::SubscriptionDeleted.new
27
-
28
- # Monitor changes for customer's default card changing
29
- events.subscribe "customer.updated", Pay::Stripe::Webhooks::CustomerUpdated.new
30
-
31
- # If a customer was deleted in Stripe, their subscriptions should be cancelled
32
- events.subscribe "customer.deleted", Pay::Stripe::Webhooks::CustomerDeleted.new
33
-
34
- # If a customer's payment source was deleted in Stripe, we should update as well
35
- events.subscribe "payment_method.attached", Pay::Stripe::Webhooks::PaymentMethodUpdated.new
36
- events.subscribe "payment_method.updated", Pay::Stripe::Webhooks::PaymentMethodUpdated.new
37
- events.subscribe "payment_method.card_automatically_updated", Pay::Stripe::Webhooks::PaymentMethodUpdated.new
38
- events.subscribe "payment_method.detached", Pay::Stripe::Webhooks::PaymentMethodUpdated.new
39
- end