pay 7.2.1 → 8.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.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/app/controllers/pay/webhooks/lemon_squeezy_controller.rb +45 -0
- data/app/controllers/pay/webhooks/stripe_controller.rb +2 -1
- data/app/jobs/pay/customer_sync_job.rb +1 -1
- data/app/models/concerns/pay/routing.rb +13 -0
- data/{lib → app/models}/pay/braintree/charge.rb +5 -12
- data/{lib/pay/braintree/billable.rb → app/models/pay/braintree/customer.rb} +31 -71
- data/{lib → app/models}/pay/braintree/payment_method.rb +1 -9
- data/{lib → app/models}/pay/braintree/subscription.rb +14 -52
- data/app/models/pay/charge.rb +8 -27
- data/app/models/pay/customer.rb +2 -15
- data/app/models/pay/fake_processor/charge.rb +13 -0
- data/{lib/pay/fake_processor/billable.rb → app/models/pay/fake_processor/customer.rb} +22 -35
- data/{lib → app/models}/pay/fake_processor/merchant.rb +2 -9
- data/app/models/pay/fake_processor/payment_method.rb +11 -0
- data/app/models/pay/fake_processor/subscription.rb +60 -0
- data/app/models/pay/lemon_squeezy/charge.rb +86 -0
- data/app/models/pay/lemon_squeezy/customer.rb +78 -0
- data/app/models/pay/lemon_squeezy/payment_method.rb +27 -0
- data/app/models/pay/lemon_squeezy/subscription.rb +129 -0
- data/app/models/pay/merchant.rb +0 -11
- data/{lib → app/models}/pay/paddle_billing/charge.rb +2 -8
- data/{lib/pay/paddle_billing/billable.rb → app/models/pay/paddle_billing/customer.rb} +18 -35
- data/{lib → app/models}/pay/paddle_billing/payment_method.rb +2 -12
- data/{lib → app/models}/pay/paddle_billing/subscription.rb +9 -33
- data/{lib → app/models}/pay/paddle_classic/charge.rb +13 -18
- data/{lib/pay/paddle_classic/billable.rb → app/models/pay/paddle_classic/customer.rb} +9 -31
- data/{lib → app/models}/pay/paddle_classic/payment_method.rb +1 -11
- data/{lib → app/models}/pay/paddle_classic/subscription.rb +11 -36
- data/app/models/pay/payment_method.rb +0 -5
- data/{lib → app/models}/pay/stripe/charge.rb +6 -22
- data/{lib/pay/stripe/billable.rb → app/models/pay/stripe/customer.rb} +73 -108
- data/{lib → app/models}/pay/stripe/merchant.rb +2 -11
- data/{lib → app/models}/pay/stripe/payment_method.rb +2 -10
- data/{lib → app/models}/pay/stripe/subscription.rb +37 -71
- data/app/models/pay/subscription.rb +7 -37
- data/app/models/pay/webhook.rb +2 -0
- data/config/routes.rb +1 -0
- data/db/migrate/2_add_pay_sti_columns.rb +24 -0
- data/lib/pay/attributes.rb +11 -3
- data/lib/pay/braintree.rb +25 -6
- data/lib/pay/engine.rb +2 -0
- data/lib/pay/fake_processor.rb +2 -6
- data/lib/pay/lemon_squeezy/webhooks/order.rb +11 -0
- data/lib/pay/lemon_squeezy/webhooks/subscription.rb +3 -3
- data/lib/pay/lemon_squeezy/webhooks/subscription_payment.rb +11 -0
- data/lib/pay/lemon_squeezy.rb +56 -104
- data/lib/pay/paddle_billing.rb +15 -6
- data/lib/pay/paddle_classic.rb +11 -9
- data/lib/pay/receipts.rb +6 -6
- data/lib/pay/stripe/webhooks/checkout_session_completed.rb +1 -1
- data/lib/pay/stripe/webhooks/customer_updated.rb +1 -1
- data/lib/pay/stripe/webhooks/subscription_trial_will_end.rb +1 -1
- data/lib/pay/stripe.rb +21 -7
- data/lib/pay/version.rb +1 -1
- data/lib/pay.rb +12 -1
- metadata +34 -38
- data/app/views/pay/stripe/_checkout_button.html.erb +0 -21
- data/lib/pay/braintree/authorization_error.rb +0 -9
- data/lib/pay/braintree/error.rb +0 -23
- data/lib/pay/fake_processor/charge.rb +0 -21
- data/lib/pay/fake_processor/error.rb +0 -6
- data/lib/pay/fake_processor/payment_method.rb +0 -21
- data/lib/pay/fake_processor/subscription.rb +0 -90
- data/lib/pay/lemon_squeezy/billable.rb +0 -90
- data/lib/pay/lemon_squeezy/charge.rb +0 -68
- data/lib/pay/lemon_squeezy/error.rb +0 -7
- data/lib/pay/lemon_squeezy/payment_method.rb +0 -40
- data/lib/pay/lemon_squeezy/subscription.rb +0 -185
- data/lib/pay/lemon_squeezy/webhooks/transaction_completed.rb +0 -11
- data/lib/pay/paddle_billing/error.rb +0 -7
- data/lib/pay/paddle_classic/error.rb +0 -7
- data/lib/pay/stripe/error.rb +0 -7
@@ -1,185 +0,0 @@
|
|
1
|
-
module Pay
|
2
|
-
module PaddleBilling
|
3
|
-
class Subscription
|
4
|
-
attr_reader :pay_subscription
|
5
|
-
|
6
|
-
delegate :active?,
|
7
|
-
:canceled?,
|
8
|
-
:on_grace_period?,
|
9
|
-
:on_trial?,
|
10
|
-
:ends_at,
|
11
|
-
:name,
|
12
|
-
:owner,
|
13
|
-
:pause_starts_at,
|
14
|
-
:pause_starts_at?,
|
15
|
-
:processor_id,
|
16
|
-
:processor_plan,
|
17
|
-
:processor_subscription,
|
18
|
-
:prorate,
|
19
|
-
:prorate?,
|
20
|
-
:quantity,
|
21
|
-
:quantity?,
|
22
|
-
:trial_ends_at,
|
23
|
-
to: :pay_subscription
|
24
|
-
|
25
|
-
def self.sync_from_transaction(transaction_id)
|
26
|
-
transaction = ::Paddle::Transaction.retrieve(id: transaction_id)
|
27
|
-
sync(transaction.subscription_id) if transaction.subscription_id
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.sync(subscription_id, object: nil, name: Pay.default_product_name)
|
31
|
-
# Passthrough is not return from this API, so we can't use that
|
32
|
-
object ||= ::Paddle::Subscription.retrieve(id: subscription_id)
|
33
|
-
|
34
|
-
pay_customer = Pay::Customer.find_by(processor: :paddle_billing, processor_id: object.customer_id)
|
35
|
-
return unless pay_customer
|
36
|
-
|
37
|
-
attributes = {
|
38
|
-
current_period_end: object.current_billing_period&.ends_at,
|
39
|
-
current_period_start: object.current_billing_period&.starts_at,
|
40
|
-
ends_at: (object.canceled_at ? Time.parse(object.canceled_at) : nil),
|
41
|
-
metadata: object.custom_data,
|
42
|
-
paddle_cancel_url: object.management_urls&.cancel,
|
43
|
-
paddle_update_url: object.management_urls&.update_payment_method,
|
44
|
-
pause_starts_at: (object.paused_at ? Time.parse(object.paused_at) : nil),
|
45
|
-
status: object.status
|
46
|
-
}
|
47
|
-
|
48
|
-
if object.items&.first
|
49
|
-
item = object.items.first
|
50
|
-
attributes[:processor_plan] = item.price.id
|
51
|
-
attributes[:quantity] = item.quantity
|
52
|
-
end
|
53
|
-
|
54
|
-
case attributes[:status]
|
55
|
-
when "canceled"
|
56
|
-
# Remove payment methods since customer cannot be reused after cancelling
|
57
|
-
Pay::PaymentMethod.where(customer_id: object.customer_id).destroy_all
|
58
|
-
when "trialing"
|
59
|
-
attributes[:trial_ends_at] = Time.parse(object.next_billed_at)
|
60
|
-
when "paused"
|
61
|
-
attributes[:pause_starts_at] = Time.parse(object.paused_at)
|
62
|
-
end
|
63
|
-
|
64
|
-
case object.scheduled_change&.action
|
65
|
-
when "cancel"
|
66
|
-
attributes[:ends_at] = Time.parse(object.scheduled_change.effective_at)
|
67
|
-
when "pause"
|
68
|
-
attributes[:pause_starts_at] = Time.parse(object.scheduled_change.effective_at)
|
69
|
-
when "resume"
|
70
|
-
attributes[:pause_resumes_at] = Time.parse(object.scheduled_change.effective_at)
|
71
|
-
end
|
72
|
-
|
73
|
-
# Update or create the subscription
|
74
|
-
if (pay_subscription = pay_customer.subscriptions.find_by(processor_id: subscription_id))
|
75
|
-
pay_subscription.with_lock do
|
76
|
-
pay_subscription.update!(attributes)
|
77
|
-
end
|
78
|
-
pay_subscription
|
79
|
-
else
|
80
|
-
pay_customer.subscriptions.create!(attributes.merge(name: name, processor_id: subscription_id))
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def initialize(pay_subscription)
|
85
|
-
@pay_subscription = pay_subscription
|
86
|
-
end
|
87
|
-
|
88
|
-
def subscription(**options)
|
89
|
-
@paddle_billing_subscription ||= ::Paddle::Subscription.retrieve(id: processor_id, **options)
|
90
|
-
end
|
91
|
-
|
92
|
-
# Get a transaction to update payment method
|
93
|
-
def payment_method_transaction
|
94
|
-
::Paddle::Subscription.get_transaction(id: processor_id)
|
95
|
-
end
|
96
|
-
|
97
|
-
# If a subscription is paused, cancel immediately
|
98
|
-
# Otherwise, cancel at period end
|
99
|
-
def cancel(**options)
|
100
|
-
return if canceled?
|
101
|
-
|
102
|
-
response = ::Paddle::Subscription.cancel(
|
103
|
-
id: processor_id,
|
104
|
-
effective_from: options.fetch(:effective_from, (paused? ? "immediately" : "next_billing_period"))
|
105
|
-
)
|
106
|
-
pay_subscription.update(
|
107
|
-
status: response.status,
|
108
|
-
ends_at: response.scheduled_change.effective_at
|
109
|
-
)
|
110
|
-
rescue ::Paddle::Error => e
|
111
|
-
raise Pay::PaddleBilling::Error, e
|
112
|
-
end
|
113
|
-
|
114
|
-
def cancel_now!(**options)
|
115
|
-
cancel(options.merge(effective_from: "immediately"))
|
116
|
-
rescue ::Paddle::Error => e
|
117
|
-
raise Pay::PaddleBilling::Error, e
|
118
|
-
end
|
119
|
-
|
120
|
-
def change_quantity(quantity, **options)
|
121
|
-
items = [{
|
122
|
-
price_id: processor_plan,
|
123
|
-
quantity: quantity
|
124
|
-
}]
|
125
|
-
|
126
|
-
::Paddle::Subscription.update(id: processor_id, items: items, proration_billing_mode: "prorated_immediately")
|
127
|
-
rescue ::Paddle::Error => e
|
128
|
-
raise Pay::PaddleBilling::Error, e
|
129
|
-
end
|
130
|
-
|
131
|
-
# A subscription could be set to cancel or pause in the future
|
132
|
-
# It is considered on grace period until the cancel or pause time begins
|
133
|
-
def on_grace_period?
|
134
|
-
(canceled? && Time.current < ends_at) || (paused? && pause_starts_at? && Time.current < pause_starts_at)
|
135
|
-
end
|
136
|
-
|
137
|
-
def paused?
|
138
|
-
pay_subscription.status == "paused"
|
139
|
-
end
|
140
|
-
|
141
|
-
def pause
|
142
|
-
response = ::Paddle::Subscription.pause(id: processor_id)
|
143
|
-
pay_subscription.update!(status: :paused, pause_starts_at: response.scheduled_change.effective_at)
|
144
|
-
rescue ::Paddle::Error => e
|
145
|
-
raise Pay::PaddleBilling::Error, e
|
146
|
-
end
|
147
|
-
|
148
|
-
def resumable?
|
149
|
-
paused?
|
150
|
-
end
|
151
|
-
|
152
|
-
def resume
|
153
|
-
unless resumable?
|
154
|
-
raise StandardError, "You can only resume paused subscriptions."
|
155
|
-
end
|
156
|
-
|
157
|
-
# Paddle Billing API only allows "resuming" subscriptions when they are paused
|
158
|
-
# So cancel the scheduled change if it is in the future
|
159
|
-
if paused? && pause_starts_at? && Time.current < pause_starts_at
|
160
|
-
::Paddle::Subscription.update(id: processor_id, scheduled_change: nil)
|
161
|
-
else
|
162
|
-
::Paddle::Subscription.resume(id: processor_id, effective_from: "immediately")
|
163
|
-
end
|
164
|
-
|
165
|
-
pay_subscription.update(status: :active, pause_starts_at: nil)
|
166
|
-
rescue ::Paddle::Error => e
|
167
|
-
raise Pay::PaddleBilling::Error, e
|
168
|
-
end
|
169
|
-
|
170
|
-
def swap(plan, **options)
|
171
|
-
items = [{
|
172
|
-
price_id: plan,
|
173
|
-
quantity: quantity || 1
|
174
|
-
}]
|
175
|
-
|
176
|
-
::Paddle::Subscription.update(id: processor_id, items: items, proration_billing_mode: "prorated_immediately")
|
177
|
-
pay_subscription.update(processor_plan: plan, ends_at: nil, status: :active)
|
178
|
-
end
|
179
|
-
|
180
|
-
# Retries the latest invoice for a Past Due subscription
|
181
|
-
def retry_failed_payment
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|