pay 6.4.0 → 6.6.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.
- checksums.yaml +4 -4
- data/app/models/pay/subscription.rb +0 -17
- data/lib/pay/attributes.rb +2 -0
- data/lib/pay/braintree/subscription.rb +5 -1
- data/lib/pay/fake_processor/subscription.rb +2 -1
- data/lib/pay/paddle/billable.rb +4 -2
- data/lib/pay/paddle/subscription.rb +4 -1
- data/lib/pay/stripe/subscription.rb +15 -1
- data/lib/pay/stripe/webhooks/checkout_session_completed.rb +4 -4
- data/lib/pay/stripe/webhooks/customer_deleted.rb +4 -1
- data/lib/pay/stripe.rb +23 -0
- data/lib/pay/version.rb +1 -1
- data/lib/pay.rb +14 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48b9300fb2d1eaaff0b5f8f52a7e16483e1b528e31eaa142f6ce6715cb49b29e
|
4
|
+
data.tar.gz: 4c67d04f2e0e04e723f7af6314ced1e3edbd57dd6b41d4eceb579db5f5ec3d8c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2859a3b93d305d940d21518a7684db3f80dce911a787728fbfbd6dfb99703647be2097b66a02662c230889c44087131fe0576680fd39f44ada37bda33fbc44da
|
7
|
+
data.tar.gz: ab54ba319c7143fafe7d2b2bad7d6c84431ec1c07fa630350e5fde3967fb75422677a8ca96b2838dec4e444fc5e8b0aada38be104c50e49a5eadffc10eb3c3d6
|
@@ -104,23 +104,6 @@ module Pay
|
|
104
104
|
ends_at? && ends_at <= Time.current
|
105
105
|
end
|
106
106
|
|
107
|
-
def on_grace_period?
|
108
|
-
(ends_at? && ends_at > Time.current) ||
|
109
|
-
((status == "paused" || pause_behavior == "void") && will_pause?)
|
110
|
-
end
|
111
|
-
|
112
|
-
def will_pause?
|
113
|
-
pause_starts_at? && Time.current < pause_starts_at
|
114
|
-
end
|
115
|
-
|
116
|
-
def pause_active?
|
117
|
-
if status == "paused" # Paddle
|
118
|
-
true
|
119
|
-
elsif pause_behavior == "void"
|
120
|
-
pause_starts_at.nil? || Time.current.after?(pause_starts_at)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
107
|
# If you cancel during a trial, you should still retain access until the end of the trial
|
125
108
|
# Otherwise a subscription is active unless it has ended or is currently paused
|
126
109
|
# Check the subscription status so we don't accidentally consider "incomplete", "past_due", or other statuses as active
|
data/lib/pay/attributes.rb
CHANGED
@@ -18,6 +18,8 @@ module Pay
|
|
18
18
|
has_one :payment_processor, -> { where(default: true, deleted_at: nil) }, class_name: "Pay::Customer", as: :owner, inverse_of: :owner
|
19
19
|
|
20
20
|
after_commit :cancel_active_pay_subscriptions!, on: [:destroy]
|
21
|
+
|
22
|
+
Pay::Stripe.model_names << name if Pay::Stripe.enabled?
|
21
23
|
end
|
22
24
|
|
23
25
|
# Changes a user's payment processor
|
@@ -5,7 +5,7 @@ module Pay
|
|
5
5
|
|
6
6
|
delegate :active?,
|
7
7
|
:canceled?,
|
8
|
-
:
|
8
|
+
:ends_at?,
|
9
9
|
:customer,
|
10
10
|
:ends_at,
|
11
11
|
:name,
|
@@ -100,6 +100,10 @@ module Pay
|
|
100
100
|
raise NotImplementedError, "Braintree does not support setting quantity on subscriptions"
|
101
101
|
end
|
102
102
|
|
103
|
+
def on_grace_period?
|
104
|
+
ends_at? && ends_at > Time.current
|
105
|
+
end
|
106
|
+
|
103
107
|
def paused?
|
104
108
|
false
|
105
109
|
end
|
@@ -8,6 +8,7 @@ module Pay
|
|
8
8
|
:on_grace_period?,
|
9
9
|
:on_trial?,
|
10
10
|
:ends_at,
|
11
|
+
:ends_at?,
|
11
12
|
:owner,
|
12
13
|
:processor_subscription,
|
13
14
|
:processor_id,
|
@@ -49,7 +50,7 @@ module Pay
|
|
49
50
|
end
|
50
51
|
|
51
52
|
def on_grace_period?
|
52
|
-
|
53
|
+
ends_at? && ends_at > Time.current
|
53
54
|
end
|
54
55
|
|
55
56
|
def paused?
|
data/lib/pay/paddle/billable.rb
CHANGED
@@ -49,8 +49,10 @@ module Pay
|
|
49
49
|
# pass
|
50
50
|
end
|
51
51
|
|
52
|
-
|
53
|
-
|
52
|
+
# Paddle does not use payment method tokens. The method signature has it here
|
53
|
+
# to have a uniform API with the other payment processors.
|
54
|
+
def add_payment_method(token = nil, default: true)
|
55
|
+
Pay::Paddle::PaymentMethod.sync(pay_customer: pay_customer)
|
54
56
|
end
|
55
57
|
|
56
58
|
def trial_end_date(subscription)
|
@@ -11,6 +11,7 @@ module Pay
|
|
11
11
|
:name,
|
12
12
|
:owner,
|
13
13
|
:pause_starts_at,
|
14
|
+
:pause_starts_at?,
|
14
15
|
:processor_id,
|
15
16
|
:processor_plan,
|
16
17
|
:processor_subscription,
|
@@ -107,8 +108,10 @@ module Pay
|
|
107
108
|
raise NotImplementedError, "Paddle does not support setting quantity on subscriptions"
|
108
109
|
end
|
109
110
|
|
111
|
+
# A subscription could be set to cancel or pause in the future
|
112
|
+
# It is considered on grace period until the cancel or pause time begins
|
110
113
|
def on_grace_period?
|
111
|
-
canceled? && Time.current < ends_at || paused? && Time.current <
|
114
|
+
(canceled? && Time.current < ends_at) || (paused? && pause_starts_at? && Time.current < pause_starts_at)
|
112
115
|
end
|
113
116
|
|
114
117
|
def paused?
|
@@ -6,10 +6,12 @@ module Pay
|
|
6
6
|
|
7
7
|
delegate :active?,
|
8
8
|
:canceled?,
|
9
|
-
:
|
9
|
+
:ends_at?,
|
10
10
|
:ends_at,
|
11
11
|
:name,
|
12
12
|
:on_trial?,
|
13
|
+
:pause_starts_at,
|
14
|
+
:pause_starts_at?,
|
13
15
|
:processor_id,
|
14
16
|
:processor_plan,
|
15
17
|
:processor_subscription,
|
@@ -184,6 +186,18 @@ module Pay
|
|
184
186
|
raise Pay::Stripe::Error, e
|
185
187
|
end
|
186
188
|
|
189
|
+
def on_grace_period?
|
190
|
+
(ends_at? && ends_at > Time.current) || (paused? && will_pause?)
|
191
|
+
end
|
192
|
+
|
193
|
+
def pause_active?
|
194
|
+
paused? && (pause_starts_at.nil? || Time.current.after?(pause_starts_at))
|
195
|
+
end
|
196
|
+
|
197
|
+
def will_pause?
|
198
|
+
pause_starts_at? && Time.current < pause_starts_at
|
199
|
+
end
|
200
|
+
|
187
201
|
def paused?
|
188
202
|
pause_behavior == "void"
|
189
203
|
end
|
@@ -5,6 +5,9 @@ module Pay
|
|
5
5
|
def call(event)
|
6
6
|
locate_owner(event.data.object)
|
7
7
|
|
8
|
+
# By the time CheckoutSessionCompleted is fired, we probably missed the original events
|
9
|
+
# Instead, we can sync the payment intent or subscription during this event to ensure they're in the database
|
10
|
+
|
8
11
|
if (payment_intent_id = event.data.object.payment_intent)
|
9
12
|
payment_intent = ::Stripe::PaymentIntent.retrieve({id: payment_intent_id}, {stripe_account: event.try(:account)}.compact)
|
10
13
|
Pay::Stripe::Charge.sync(payment_intent.latest_charge, stripe_account: event.try(:account))
|
@@ -18,11 +21,8 @@ module Pay
|
|
18
21
|
def locate_owner(object)
|
19
22
|
return if object.client_reference_id.nil?
|
20
23
|
|
21
|
-
|
22
|
-
owner = GlobalID::Locator.locate_signed(object.client_reference_id)
|
24
|
+
owner = Pay::Stripe.find_by_client_reference_id(object.client_reference_id)
|
23
25
|
owner&.add_payment_processor(:stripe, processor_id: object.customer)
|
24
|
-
rescue
|
25
|
-
Rails.logger.debug "[Pay] Unable to locate record with SGID: #{object.client_reference_id}"
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -6,6 +6,9 @@ module Pay
|
|
6
6
|
object = event.data.object
|
7
7
|
pay_customer = Pay::Customer.find_by(processor: :stripe, processor_id: object.id)
|
8
8
|
|
9
|
+
# Skip processing if this customer is not in the database
|
10
|
+
return unless pay_customer
|
11
|
+
|
9
12
|
# Mark all subscriptions as canceled
|
10
13
|
pay_customer.subscriptions.active.update_all(ends_at: Time.current, status: "canceled")
|
11
14
|
|
@@ -13,7 +16,7 @@ module Pay
|
|
13
16
|
pay_customer.payment_methods.destroy_all
|
14
17
|
|
15
18
|
# Mark customer as deleted
|
16
|
-
pay_customer
|
19
|
+
pay_customer.update!(default: false, deleted_at: Time.current)
|
17
20
|
end
|
18
21
|
end
|
19
22
|
end
|
data/lib/pay/stripe.rb
CHANGED
@@ -30,6 +30,10 @@ module Pay
|
|
30
30
|
|
31
31
|
extend Env
|
32
32
|
|
33
|
+
# A list of database model names that include Pay
|
34
|
+
# Used for safely looking up models with client_reference_id
|
35
|
+
mattr_accessor :model_names, default: Set.new
|
36
|
+
|
33
37
|
def self.enabled?
|
34
38
|
return false unless Pay.enabled_processors.include?(:stripe) && defined?(::Stripe)
|
35
39
|
|
@@ -114,5 +118,24 @@ module Pay
|
|
114
118
|
events.subscribe "stripe.checkout.session.async_payment_succeeded", Pay::Stripe::Webhooks::CheckoutSessionAsyncPaymentSucceeded.new
|
115
119
|
end
|
116
120
|
end
|
121
|
+
|
122
|
+
def self.to_client_reference_id(record)
|
123
|
+
raise ArgumentError, "#{record.class.name} does not include Pay. Allowed models: #{model_names.to_a.join(", ")}" unless model_names.include?(record.class.name)
|
124
|
+
[record.class.name, record.id].join("/")
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.find_by_client_reference_id(client_reference_id)
|
128
|
+
# If there is a client reference ID, make sure we have a Pay::Customer record
|
129
|
+
# client_reference_id should be in the format of "User/1"
|
130
|
+
model_name, id = client_reference_id.split("/", 2)
|
131
|
+
|
132
|
+
# Only allow model names that use Pay
|
133
|
+
return unless model_names.include?(model_name)
|
134
|
+
|
135
|
+
model_name.constantize.find(id)
|
136
|
+
rescue ActiveRecord::RecordNotFound
|
137
|
+
Rails.logger.error "[Pay] Unable to locate record with: #{client_reference_id}"
|
138
|
+
nil
|
139
|
+
end
|
117
140
|
end
|
118
141
|
end
|
data/lib/pay/version.rb
CHANGED
data/lib/pay.rb
CHANGED
@@ -57,6 +57,9 @@ module Pay
|
|
57
57
|
mattr_accessor :enabled_processors
|
58
58
|
@@enabled_processors = [:stripe, :braintree, :paddle]
|
59
59
|
|
60
|
+
mattr_accessor :send_emails
|
61
|
+
@@send_emails = true
|
62
|
+
|
60
63
|
mattr_accessor :emails
|
61
64
|
@@emails = ActiveSupport::OrderedOptions.new
|
62
65
|
@@emails.payment_action_required = true
|
@@ -111,12 +114,19 @@ module Pay
|
|
111
114
|
end
|
112
115
|
|
113
116
|
def self.send_email?(email_option, *remaining_args)
|
114
|
-
|
117
|
+
if resolve_option(send_emails, *remaining_args)
|
118
|
+
email_config_option_enabled = emails.send(email_option)
|
119
|
+
resolve_option(email_config_option_enabled, *remaining_args)
|
120
|
+
else
|
121
|
+
false
|
122
|
+
end
|
123
|
+
end
|
115
124
|
|
116
|
-
|
117
|
-
|
125
|
+
def self.resolve_option(option, *remaining_args)
|
126
|
+
if option.respond_to?(:call)
|
127
|
+
option.call(*remaining_args)
|
118
128
|
else
|
119
|
-
|
129
|
+
option
|
120
130
|
end
|
121
131
|
end
|
122
132
|
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: 6.
|
4
|
+
version: 6.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Charnes
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-
|
13
|
+
date: 2023-06-02 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rails
|
@@ -168,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
168
|
- !ruby/object:Gem::Version
|
169
169
|
version: '0'
|
170
170
|
requirements: []
|
171
|
-
rubygems_version: 3.4.
|
171
|
+
rubygems_version: 3.4.13
|
172
172
|
signing_key:
|
173
173
|
specification_version: 4
|
174
174
|
summary: Payments engine for Ruby on Rails
|