Class: Pay::PaddleBilling::Subscription
- Inherits:
-
Object
- Object
- Pay::PaddleBilling::Subscription
- Defined in:
- lib/pay/lemon_squeezy/subscription.rb,
lib/pay/paddle_billing/subscription.rb
Instance Attribute Summary collapse
-
#pay_subscription ⇒ Object
readonly
Returns the value of attribute pay_subscription.
Class Method Summary collapse
- .sync(subscription_id, object: nil, name: Pay.default_product_name) ⇒ Object
- .sync_from_transaction(transaction_id) ⇒ Object
Instance Method Summary collapse
-
#cancel(**options) ⇒ Object
If a subscription is paused, cancel immediately Otherwise, cancel at period end.
- #cancel_now!(**options) ⇒ Object
- #change_quantity(quantity, **options) ⇒ Object
-
#initialize(pay_subscription) ⇒ Subscription
constructor
A new instance of Subscription.
-
#on_grace_period? ⇒ Boolean
A subscription could be set to cancel or pause in the future It is considered on grace period until the cancel or pause time begins.
- #pause ⇒ Object
- #paused? ⇒ Boolean
-
#payment_method_transaction ⇒ Object
Get a transaction to update payment method.
- #resumable? ⇒ Boolean
- #resume ⇒ Object
-
#retry_failed_payment ⇒ Object
Retries the latest invoice for a Past Due subscription.
- #subscription(**options) ⇒ Object
- #swap(plan, **options) ⇒ Object
Constructor Details
#initialize(pay_subscription) ⇒ Subscription
Returns a new instance of Subscription.
84 85 86 |
# File 'lib/pay/lemon_squeezy/subscription.rb', line 84 def initialize(pay_subscription) @pay_subscription = pay_subscription end |
Instance Attribute Details
#pay_subscription ⇒ Object (readonly)
Returns the value of attribute pay_subscription.
4 5 6 |
# File 'lib/pay/lemon_squeezy/subscription.rb', line 4 def pay_subscription @pay_subscription end |
Class Method Details
.sync(subscription_id, object: nil, name: Pay.default_product_name) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/pay/lemon_squeezy/subscription.rb', line 30 def self.sync(subscription_id, object: nil, name: Pay.default_product_name) # Passthrough is not return from this API, so we can't use that object ||= ::Paddle::Subscription.retrieve(id: subscription_id) pay_customer = Pay::Customer.find_by(processor: :paddle_billing, processor_id: object.customer_id) return unless pay_customer attributes = { current_period_end: object.current_billing_period&.ends_at, current_period_start: object.current_billing_period&.starts_at, ends_at: (object.canceled_at ? Time.parse(object.canceled_at) : nil), metadata: object.custom_data, paddle_cancel_url: object.management_urls&.cancel, paddle_update_url: object.management_urls&.update_payment_method, pause_starts_at: (object.paused_at ? Time.parse(object.paused_at) : nil), status: object.status } if object.items&.first item = object.items.first attributes[:processor_plan] = item.price.id attributes[:quantity] = item.quantity end case attributes[:status] when "canceled" # Remove payment methods since customer cannot be reused after cancelling Pay::PaymentMethod.where(customer_id: object.customer_id).destroy_all when "trialing" attributes[:trial_ends_at] = Time.parse(object.next_billed_at) when "paused" attributes[:pause_starts_at] = Time.parse(object.paused_at) end case object.scheduled_change&.action when "cancel" attributes[:ends_at] = Time.parse(object.scheduled_change.effective_at) when "pause" attributes[:pause_starts_at] = Time.parse(object.scheduled_change.effective_at) when "resume" attributes[:pause_resumes_at] = Time.parse(object.scheduled_change.effective_at) end # Update or create the subscription if (pay_subscription = pay_customer.subscriptions.find_by(processor_id: subscription_id)) pay_subscription.with_lock do pay_subscription.update!(attributes) end pay_subscription else pay_customer.subscriptions.create!(attributes.merge(name: name, processor_id: subscription_id)) end end |
.sync_from_transaction(transaction_id) ⇒ Object
25 26 27 28 |
# File 'lib/pay/lemon_squeezy/subscription.rb', line 25 def self.sync_from_transaction(transaction_id) transaction = ::Paddle::Transaction.retrieve(id: transaction_id) sync(transaction.subscription_id) if transaction.subscription_id end |
Instance Method Details
#cancel(**options) ⇒ Object
If a subscription is paused, cancel immediately Otherwise, cancel at period end
99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/pay/lemon_squeezy/subscription.rb', line 99 def cancel(**) return if canceled? response = ::Paddle::Subscription.cancel( id: processor_id, effective_from: .fetch(:effective_from, (paused? ? "immediately" : "next_billing_period")) ) pay_subscription.update( status: response.status, ends_at: response.scheduled_change.effective_at ) rescue ::Paddle::Error => e raise Pay::PaddleBilling::Error, e end |
#cancel_now!(**options) ⇒ Object
114 115 116 117 118 |
# File 'lib/pay/lemon_squeezy/subscription.rb', line 114 def cancel_now!(**) cancel(.merge(effective_from: "immediately")) rescue ::Paddle::Error => e raise Pay::PaddleBilling::Error, e end |
#change_quantity(quantity, **options) ⇒ Object
120 121 122 123 124 125 126 127 128 129 |
# File 'lib/pay/lemon_squeezy/subscription.rb', line 120 def change_quantity(quantity, **) items = [{ price_id: processor_plan, quantity: quantity }] ::Paddle::Subscription.update(id: processor_id, items: items, proration_billing_mode: "prorated_immediately") rescue ::Paddle::Error => e raise Pay::PaddleBilling::Error, e end |
#on_grace_period? ⇒ Boolean
A subscription could be set to cancel or pause in the future It is considered on grace period until the cancel or pause time begins
133 134 135 |
# File 'lib/pay/lemon_squeezy/subscription.rb', line 133 def on_grace_period? (canceled? && Time.current < ends_at) || (paused? && pause_starts_at? && Time.current < pause_starts_at) end |
#pause ⇒ Object
141 142 143 144 145 146 |
# File 'lib/pay/lemon_squeezy/subscription.rb', line 141 def pause response = ::Paddle::Subscription.pause(id: processor_id) pay_subscription.update!(status: :paused, pause_starts_at: response.scheduled_change.effective_at) rescue ::Paddle::Error => e raise Pay::PaddleBilling::Error, e end |
#paused? ⇒ Boolean
137 138 139 |
# File 'lib/pay/lemon_squeezy/subscription.rb', line 137 def paused? pay_subscription.status == "paused" end |
#payment_method_transaction ⇒ Object
Get a transaction to update payment method
93 94 95 |
# File 'lib/pay/lemon_squeezy/subscription.rb', line 93 def payment_method_transaction ::Paddle::Subscription.get_transaction(id: processor_id) end |
#resumable? ⇒ Boolean
148 149 150 |
# File 'lib/pay/lemon_squeezy/subscription.rb', line 148 def resumable? paused? end |
#resume ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/pay/lemon_squeezy/subscription.rb', line 152 def resume unless resumable? raise StandardError, "You can only resume paused subscriptions." end # Paddle Billing API only allows "resuming" subscriptions when they are paused # So cancel the scheduled change if it is in the future if paused? && pause_starts_at? && Time.current < pause_starts_at ::Paddle::Subscription.update(id: processor_id, scheduled_change: nil) else ::Paddle::Subscription.resume(id: processor_id, effective_from: "immediately") end pay_subscription.update(status: :active, pause_starts_at: nil) rescue ::Paddle::Error => e raise Pay::PaddleBilling::Error, e end |
#retry_failed_payment ⇒ Object
Retries the latest invoice for a Past Due subscription
181 182 |
# File 'lib/pay/lemon_squeezy/subscription.rb', line 181 def retry_failed_payment end |
#subscription(**options) ⇒ Object
88 89 90 |
# File 'lib/pay/lemon_squeezy/subscription.rb', line 88 def subscription(**) @paddle_billing_subscription ||= ::Paddle::Subscription.retrieve(id: processor_id, **) end |
#swap(plan, **options) ⇒ Object
170 171 172 173 174 175 176 177 178 |
# File 'lib/pay/lemon_squeezy/subscription.rb', line 170 def swap(plan, **) items = [{ price_id: plan, quantity: quantity || 1 }] ::Paddle::Subscription.update(id: processor_id, items: items, proration_billing_mode: "prorated_immediately") pay_subscription.update(processor_plan: plan, ends_at: nil, status: :active) end |