Class: Pay::PaddleBilling::Subscription
- Inherits:
-
Object
- Object
- Pay::PaddleBilling::Subscription
- Defined in:
- 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.
88 89 90 |
# File 'lib/pay/paddle_billing/subscription.rb', line 88 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/paddle_billing/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 83 84 85 86 |
# File 'lib/pay/paddle_billing/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) when "active", "past_due" attributes[:trial_ends_at] = nil attributes[:pause_starts_at] = nil attributes[:ends_at] = nil 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/paddle_billing/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
103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/pay/paddle_billing/subscription.rb', line 103 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
118 119 120 121 122 |
# File 'lib/pay/paddle_billing/subscription.rb', line 118 def cancel_now!(**) cancel(.merge(effective_from: "immediately")) rescue ::Paddle::Error => e raise Pay::PaddleBilling::Error, e end |
#change_quantity(quantity, **options) ⇒ Object
124 125 126 127 128 129 130 131 132 133 |
# File 'lib/pay/paddle_billing/subscription.rb', line 124 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
137 138 139 |
# File 'lib/pay/paddle_billing/subscription.rb', line 137 def on_grace_period? (canceled? && Time.current < ends_at) || (paused? && pause_starts_at? && Time.current < pause_starts_at) end |
#pause ⇒ Object
145 146 147 148 149 150 |
# File 'lib/pay/paddle_billing/subscription.rb', line 145 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
141 142 143 |
# File 'lib/pay/paddle_billing/subscription.rb', line 141 def paused? pay_subscription.status == "paused" end |
#payment_method_transaction ⇒ Object
Get a transaction to update payment method
97 98 99 |
# File 'lib/pay/paddle_billing/subscription.rb', line 97 def payment_method_transaction ::Paddle::Subscription.get_transaction(id: processor_id) end |
#resumable? ⇒ Boolean
152 153 154 |
# File 'lib/pay/paddle_billing/subscription.rb', line 152 def resumable? paused? end |
#resume ⇒ Object
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/pay/paddle_billing/subscription.rb', line 156 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
185 186 |
# File 'lib/pay/paddle_billing/subscription.rb', line 185 def retry_failed_payment end |
#subscription(**options) ⇒ Object
92 93 94 |
# File 'lib/pay/paddle_billing/subscription.rb', line 92 def subscription(**) @paddle_billing_subscription ||= ::Paddle::Subscription.retrieve(id: processor_id, **) end |
#swap(plan, **options) ⇒ Object
174 175 176 177 178 179 180 181 182 |
# File 'lib/pay/paddle_billing/subscription.rb', line 174 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 |