pay 2.4.4 → 2.6.3
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.
Potentially problematic release.
This version of pay might be problematic. Click here for more details.
- checksums.yaml +4 -4
 - data/README.md +10 -4
 - data/app/controllers/pay/webhooks/braintree_controller.rb +7 -53
 - data/app/controllers/pay/webhooks/paddle_controller.rb +19 -18
 - data/app/controllers/pay/webhooks/stripe_controller.rb +47 -0
 - data/app/models/pay/charge.rb +22 -3
 - data/app/models/pay/subscription.rb +23 -24
 - data/app/views/pay/stripe/_checkout_button.html.erb +21 -0
 - data/config/routes.rb +1 -1
 - data/lib/pay.rb +12 -12
 - data/lib/pay/billable.rb +36 -33
 - data/lib/pay/billable/sync_email.rb +1 -1
 - data/lib/pay/braintree.rb +34 -15
 - data/lib/pay/braintree/authorization_error.rb +9 -0
 - data/lib/pay/braintree/billable.rb +33 -30
 - data/lib/pay/braintree/charge.rb +8 -10
 - data/lib/pay/braintree/error.rb +9 -0
 - data/lib/pay/braintree/subscription.rb +34 -15
 - data/lib/pay/braintree/webhooks/subscription_canceled.rb +19 -0
 - data/lib/pay/braintree/webhooks/subscription_charged_successfully.rb +24 -0
 - data/lib/pay/braintree/webhooks/subscription_charged_unsuccessfully.rb +24 -0
 - data/lib/pay/braintree/webhooks/subscription_expired.rb +19 -0
 - data/lib/pay/braintree/webhooks/subscription_trial_ended.rb +19 -0
 - data/lib/pay/braintree/webhooks/subscription_went_active.rb +19 -0
 - data/lib/pay/braintree/webhooks/subscription_went_past_due.rb +19 -0
 - data/lib/pay/engine.rb +0 -23
 - data/lib/pay/errors.rb +0 -44
 - data/lib/pay/paddle.rb +30 -16
 - data/lib/pay/paddle/billable.rb +26 -22
 - data/lib/pay/paddle/charge.rb +8 -12
 - data/lib/pay/paddle/error.rb +9 -0
 - data/lib/pay/paddle/subscription.rb +29 -18
 - data/lib/pay/paddle/webhooks/subscription_cancelled.rb +3 -3
 - data/lib/pay/paddle/webhooks/subscription_created.rb +15 -15
 - data/lib/pay/paddle/webhooks/subscription_payment_refunded.rb +3 -3
 - data/lib/pay/paddle/webhooks/subscription_payment_succeeded.rb +11 -11
 - data/lib/pay/paddle/webhooks/subscription_updated.rb +11 -11
 - data/lib/pay/stripe.rb +62 -15
 - data/lib/pay/stripe/billable.rb +136 -69
 - data/lib/pay/stripe/charge.rb +9 -15
 - data/lib/pay/stripe/error.rb +9 -0
 - data/lib/pay/stripe/subscription.rb +27 -11
 - data/lib/pay/stripe/webhooks/charge_succeeded.rb +1 -20
 - data/lib/pay/stripe/webhooks/customer_updated.rb +1 -1
 - data/lib/pay/stripe/webhooks/payment_method_updated.rb +1 -1
 - data/lib/pay/stripe/webhooks/subscription_created.rb +1 -0
 - data/lib/pay/version.rb +1 -1
 - data/lib/pay/webhooks.rb +13 -0
 - data/lib/pay/webhooks/delegator.rb +61 -0
 - metadata +20 -69
 - data/lib/pay/paddle/webhooks.rb +0 -1
 - data/lib/pay/stripe/webhooks.rb +0 -39
 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # A subscription successfully moves to the next billing cycle. This will also occur when either a new transaction is created mid-cycle due to proration on an upgrade or a billing cycle is skipped due to the presence of a negative balance that covers the cost of the subscription.
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Pay
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Braintree
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Webhooks
         
     | 
| 
      
 6 
     | 
    
         
            +
                  class SubscriptionChargedSuccessfully
         
     | 
| 
      
 7 
     | 
    
         
            +
                    def call(event)
         
     | 
| 
      
 8 
     | 
    
         
            +
                      subscription = event.subscription
         
     | 
| 
      
 9 
     | 
    
         
            +
                      return if subscription.nil?
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                      pay_subscription = Pay.subscription_model.find_by(processor: :braintree, processor_id: subscription.id)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      return unless pay_subscription.present?
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                      billable = pay_subscription.owner
         
     | 
| 
      
 15 
     | 
    
         
            +
                      charge = Pay::Braintree::Billable.new(billable).save_transaction(subscription.transactions.first)
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                      if Pay.send_emails
         
     | 
| 
      
 18 
     | 
    
         
            +
                        Pay::UserMailer.with(billable: billable, charge: charge).receipt.deliver_later
         
     | 
| 
      
 19 
     | 
    
         
            +
                      end
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # A subscription successfully moves to the next billing cycle. This will also occur when either a new transaction is created mid-cycle due to proration on an upgrade or a billing cycle is skipped due to the presence of a negative balance that covers the cost of the subscription.
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Pay
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Braintree
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Webhooks
         
     | 
| 
      
 6 
     | 
    
         
            +
                  class SubscriptionChargedUnsuccessfully
         
     | 
| 
      
 7 
     | 
    
         
            +
                    def call(event)
         
     | 
| 
      
 8 
     | 
    
         
            +
                      subscription = event.subscription
         
     | 
| 
      
 9 
     | 
    
         
            +
                      return if subscription.nil?
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                      pay_subscription = Pay.subscription_model.find_by(processor: :braintree, processor_id: subscription.id)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      return unless pay_subscription.present?
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                      # billable = pay_subscription.owner
         
     | 
| 
      
 15 
     | 
    
         
            +
                      # charge = Pay::Braintree::Billable.new(billable).save_transaction(subscription.transactions.first)
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                      # if Pay.send_emails
         
     | 
| 
      
 18 
     | 
    
         
            +
                      #  Pay::UserMailer.with(billable: billable, charge: charge).receipt.deliver_later
         
     | 
| 
      
 19 
     | 
    
         
            +
                      # end
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # A subscription reaches the specified number of billing cycles and expires.
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Pay
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Braintree
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Webhooks
         
     | 
| 
      
 6 
     | 
    
         
            +
                  class SubscriptionExpired
         
     | 
| 
      
 7 
     | 
    
         
            +
                    def call(event)
         
     | 
| 
      
 8 
     | 
    
         
            +
                      subscription = event.subscription
         
     | 
| 
      
 9 
     | 
    
         
            +
                      return if subscription.nil?
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                      pay_subscription = Pay.subscription_model.find_by(processor: :braintree, processor_id: subscription.id)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      return unless pay_subscription.present?
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                      pay_subscription.update!(ends_at: Time.current, status: :canceled)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # A subscription's trial period ends.
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Pay
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Braintree
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Webhooks
         
     | 
| 
      
 6 
     | 
    
         
            +
                  class SubscriptionTrialEnded
         
     | 
| 
      
 7 
     | 
    
         
            +
                    def call(event)
         
     | 
| 
      
 8 
     | 
    
         
            +
                      subscription = event.subscription
         
     | 
| 
      
 9 
     | 
    
         
            +
                      return if subscription.nil?
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                      pay_subscription = Pay.subscription_model.find_by(processor: :braintree, processor_id: subscription.id)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      return unless pay_subscription.present?
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                      pay_subscription.update(trial_ends_at: Time.zone.now)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # A subscription's first authorized transaction is created, or a successful transaction moves a subscription from the Past Due status to the Active status. Subscriptions with trial periods will not trigger this notification when they move from the trial period into the first billing cycle.
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Pay
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Braintree
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Webhooks
         
     | 
| 
      
 6 
     | 
    
         
            +
                  class SubscriptionWentActive
         
     | 
| 
      
 7 
     | 
    
         
            +
                    def call(event)
         
     | 
| 
      
 8 
     | 
    
         
            +
                      subscription = event.subscription
         
     | 
| 
      
 9 
     | 
    
         
            +
                      return if subscription.nil?
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                      pay_subscription = Pay.subscription_model.find_by(processor: :braintree, processor_id: subscription.id)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      return unless pay_subscription.present?
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                      pay_subscription.update!(status: :active)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # A subscription has moved from the Active status to the Past Due status. This will only be triggered when the initial transaction in a billing cycle is declined. Once the status moves to past due, it will not be triggered again in that billing cycle.
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Pay
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Braintree
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Webhooks
         
     | 
| 
      
 6 
     | 
    
         
            +
                  class SubscriptionWentPastDue
         
     | 
| 
      
 7 
     | 
    
         
            +
                    def call(event)
         
     | 
| 
      
 8 
     | 
    
         
            +
                      subscription = event.subscription
         
     | 
| 
      
 9 
     | 
    
         
            +
                      return if subscription.nil?
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                      pay_subscription = Pay.subscription_model.find_by(processor: :braintree, processor_id: subscription.id)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      return unless pay_subscription.present?
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                      pay_subscription.update!(status: :past_due)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/pay/engine.rb
    CHANGED
    
    | 
         @@ -1,33 +1,10 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            # rubocop:disable Lint/HandleExceptions
         
     | 
| 
       4 
     | 
    
         
            -
            begin
         
     | 
| 
       5 
     | 
    
         
            -
              require "braintree"
         
     | 
| 
       6 
     | 
    
         
            -
            rescue LoadError
         
     | 
| 
       7 
     | 
    
         
            -
            end
         
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
            begin
         
     | 
| 
       10 
     | 
    
         
            -
              require "stripe"
         
     | 
| 
       11 
     | 
    
         
            -
              require "stripe_event"
         
     | 
| 
       12 
     | 
    
         
            -
            rescue LoadError
         
     | 
| 
       13 
     | 
    
         
            -
            end
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
            begin
         
     | 
| 
       16 
     | 
    
         
            -
              require "paddle_pay"
         
     | 
| 
       17 
     | 
    
         
            -
            rescue LoadError
         
     | 
| 
       18 
     | 
    
         
            -
            end
         
     | 
| 
       19 
     | 
    
         
            -
            # rubocop:enable Lint/HandleExceptions
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
3 
     | 
    
         
             
            module Pay
         
     | 
| 
       22 
4 
     | 
    
         
             
              class Engine < ::Rails::Engine
         
     | 
| 
       23 
5 
     | 
    
         
             
                engine_name "pay"
         
     | 
| 
       24 
6 
     | 
    
         | 
| 
       25 
7 
     | 
    
         
             
                initializer "pay.processors" do |app|
         
     | 
| 
       26 
     | 
    
         
            -
                  # Include processor backends
         
     | 
| 
       27 
     | 
    
         
            -
                  require "pay/stripe" if defined? ::Stripe
         
     | 
| 
       28 
     | 
    
         
            -
                  require "pay/braintree" if defined? ::Braintree
         
     | 
| 
       29 
     | 
    
         
            -
                  require "pay/paddle" if defined? ::PaddlePay
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
8 
     | 
    
         
             
                  if Pay.automount_routes
         
     | 
| 
       32 
9 
     | 
    
         
             
                    app.routes.append do
         
     | 
| 
       33 
10 
     | 
    
         
             
                      mount Pay::Engine, at: Pay.routes_path, as: "pay"
         
     | 
    
        data/lib/pay/errors.rb
    CHANGED
    
    | 
         @@ -26,48 +26,4 @@ module Pay 
     | 
|
| 
       26 
26 
     | 
    
         
             
                  I18n.t("errors.invalid_payment")
         
     | 
| 
       27 
27 
     | 
    
         
             
                end
         
     | 
| 
       28 
28 
     | 
    
         
             
              end
         
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
              module Braintree
         
     | 
| 
       31 
     | 
    
         
            -
                class Error < Error
         
     | 
| 
       32 
     | 
    
         
            -
                  def message
         
     | 
| 
       33 
     | 
    
         
            -
                    result.message
         
     | 
| 
       34 
     | 
    
         
            -
                  end
         
     | 
| 
       35 
     | 
    
         
            -
                end
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                class AuthorizationError < Braintree::Error
         
     | 
| 
       38 
     | 
    
         
            -
                  def message
         
     | 
| 
       39 
     | 
    
         
            -
                    I18n.t("errors.braintree.authorization")
         
     | 
| 
       40 
     | 
    
         
            -
                  end
         
     | 
| 
       41 
     | 
    
         
            -
                end
         
     | 
| 
       42 
     | 
    
         
            -
              end
         
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
              module Stripe
         
     | 
| 
       45 
     | 
    
         
            -
                class Error < Error
         
     | 
| 
       46 
     | 
    
         
            -
                  def message
         
     | 
| 
       47 
     | 
    
         
            -
                    I18n.t("errors.stripe.#{result.code}", default: result.message)
         
     | 
| 
       48 
     | 
    
         
            -
                  end
         
     | 
| 
       49 
     | 
    
         
            -
                end
         
     | 
| 
       50 
     | 
    
         
            -
              end
         
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
              module Paddle
         
     | 
| 
       53 
     | 
    
         
            -
                class Error < Error
         
     | 
| 
       54 
     | 
    
         
            -
                  def message
         
     | 
| 
       55 
     | 
    
         
            -
                    I18n.t("errors.paddle.#{result.code}", default: result.message)
         
     | 
| 
       56 
     | 
    
         
            -
                  end
         
     | 
| 
       57 
     | 
    
         
            -
                end
         
     | 
| 
       58 
     | 
    
         
            -
              end
         
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
              class BraintreeError < Braintree::Error
         
     | 
| 
       61 
     | 
    
         
            -
                def message
         
     | 
| 
       62 
     | 
    
         
            -
                  ActiveSupport::Deprecation.warn("Pay::BraintreeError is deprecated. Instead, use `Pay::Braintree::Error`.")
         
     | 
| 
       63 
     | 
    
         
            -
                  super
         
     | 
| 
       64 
     | 
    
         
            -
                end
         
     | 
| 
       65 
     | 
    
         
            -
              end
         
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
       67 
     | 
    
         
            -
              class BraintreeAuthorizationError < BraintreeError
         
     | 
| 
       68 
     | 
    
         
            -
                def message
         
     | 
| 
       69 
     | 
    
         
            -
                  ActiveSupport::Deprecation.warn("Pay::BraintreeAuthorizationError is deprecated. Instead, use `Pay::Braintree::AuthorizationError`.")
         
     | 
| 
       70 
     | 
    
         
            -
                  I18n.t("errors.braintree.authorization")
         
     | 
| 
       71 
     | 
    
         
            -
                end
         
     | 
| 
       72 
     | 
    
         
            -
              end
         
     | 
| 
       73 
29 
     | 
    
         
             
            end
         
     | 
    
        data/lib/pay/paddle.rb
    CHANGED
    
    | 
         @@ -1,38 +1,52 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require "pay/env"
         
     | 
| 
       2 
     | 
    
         
            -
            require "pay/paddle/billable"
         
     | 
| 
       3 
     | 
    
         
            -
            require "pay/paddle/charge"
         
     | 
| 
       4 
     | 
    
         
            -
            require "pay/paddle/subscription"
         
     | 
| 
       5 
     | 
    
         
            -
            require "pay/paddle/webhooks"
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
1 
     | 
    
         
             
            module Pay
         
     | 
| 
       8 
2 
     | 
    
         
             
              module Paddle
         
     | 
| 
       9 
     | 
    
         
            -
                 
     | 
| 
      
 3 
     | 
    
         
            +
                autoload :Billable, "pay/paddle/billable"
         
     | 
| 
      
 4 
     | 
    
         
            +
                autoload :Charge, "pay/paddle/charge"
         
     | 
| 
      
 5 
     | 
    
         
            +
                autoload :Subscription, "pay/paddle/subscription"
         
     | 
| 
      
 6 
     | 
    
         
            +
                autoload :Error, "pay/paddle/error"
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                module Webhooks
         
     | 
| 
      
 9 
     | 
    
         
            +
                  autoload :SignatureVerifier, "pay/paddle/webhooks/signature_verifier"
         
     | 
| 
      
 10 
     | 
    
         
            +
                  autoload :SubscriptionCreated, "pay/paddle/webhooks/subscription_created"
         
     | 
| 
      
 11 
     | 
    
         
            +
                  autoload :SubscriptionCancelled, "pay/paddle/webhooks/subscription_cancelled"
         
     | 
| 
      
 12 
     | 
    
         
            +
                  autoload :SubscriptionPaymentRefunded, "pay/paddle/webhooks/subscription_payment_refunded"
         
     | 
| 
      
 13 
     | 
    
         
            +
                  autoload :SubscriptionPaymentSucceeded, "pay/paddle/webhooks/subscription_payment_succeeded"
         
     | 
| 
      
 14 
     | 
    
         
            +
                  autoload :SubscriptionUpdated, "pay/paddle/webhooks/subscription_updated"
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
       10 
16 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
                extend  
     | 
| 
      
 17 
     | 
    
         
            +
                extend Env
         
     | 
| 
       12 
18 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
                def setup
         
     | 
| 
      
 19 
     | 
    
         
            +
                def self.setup
         
     | 
| 
       14 
20 
     | 
    
         
             
                  ::PaddlePay.config.vendor_id = vendor_id
         
     | 
| 
       15 
21 
     | 
    
         
             
                  ::PaddlePay.config.vendor_auth_code = vendor_auth_code
         
     | 
| 
       16 
22 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                   
     | 
| 
       18 
     | 
    
         
            -
                  Pay.subscription_model.include Pay::Paddle::Subscription
         
     | 
| 
       19 
     | 
    
         
            -
                  Pay.billable_models.each { |model| model.include Pay::Paddle::Billable }
         
     | 
| 
      
 23 
     | 
    
         
            +
                  configure_webhooks
         
     | 
| 
       20 
24 
     | 
    
         
             
                end
         
     | 
| 
       21 
25 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
                def vendor_id
         
     | 
| 
      
 26 
     | 
    
         
            +
                def self.vendor_id
         
     | 
| 
       23 
27 
     | 
    
         
             
                  find_value_by_name(:paddle, :vendor_id)
         
     | 
| 
       24 
28 
     | 
    
         
             
                end
         
     | 
| 
       25 
29 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
                def vendor_auth_code
         
     | 
| 
      
 30 
     | 
    
         
            +
                def self.vendor_auth_code
         
     | 
| 
       27 
31 
     | 
    
         
             
                  find_value_by_name(:paddle, :vendor_auth_code)
         
     | 
| 
       28 
32 
     | 
    
         
             
                end
         
     | 
| 
       29 
33 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                def public_key_base64
         
     | 
| 
      
 34 
     | 
    
         
            +
                def self.public_key_base64
         
     | 
| 
       31 
35 
     | 
    
         
             
                  find_value_by_name(:paddle, :public_key_base64)
         
     | 
| 
       32 
36 
     | 
    
         
             
                end
         
     | 
| 
       33 
37 
     | 
    
         | 
| 
       34 
     | 
    
         
            -
                def passthrough(owner:, **options)
         
     | 
| 
      
 38 
     | 
    
         
            +
                def self.passthrough(owner:, **options)
         
     | 
| 
       35 
39 
     | 
    
         
             
                  options.merge(owner_sgid: owner.to_sgid.to_s).to_json
         
     | 
| 
       36 
40 
     | 
    
         
             
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def self.configure_webhooks
         
     | 
| 
      
 43 
     | 
    
         
            +
                  Pay::Webhooks.configure do |events|
         
     | 
| 
      
 44 
     | 
    
         
            +
                    events.subscribe "paddle.subscription_created", Pay::Paddle::Webhooks::SubscriptionCreated.new
         
     | 
| 
      
 45 
     | 
    
         
            +
                    events.subscribe "paddle.subscription_updated", Pay::Paddle::Webhooks::SubscriptionUpdated.new
         
     | 
| 
      
 46 
     | 
    
         
            +
                    events.subscribe "paddle.subscription_cancelled", Pay::Paddle::Webhooks::SubscriptionCancelled.new
         
     | 
| 
      
 47 
     | 
    
         
            +
                    events.subscribe "paddle.subscription_payment_succeeded", Pay::Paddle::Webhooks::SubscriptionPaymentSucceeded.new
         
     | 
| 
      
 48 
     | 
    
         
            +
                    events.subscribe "paddle.subscription_payment_refunded", Pay::Paddle::Webhooks::SubscriptionPaymentRefunded.new
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
       37 
51 
     | 
    
         
             
              end
         
     | 
| 
       38 
52 
     | 
    
         
             
            end
         
     | 
    
        data/lib/pay/paddle/billable.rb
    CHANGED
    
    | 
         @@ -1,27 +1,32 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Pay
         
     | 
| 
       2 
2 
     | 
    
         
             
              module Paddle
         
     | 
| 
       3 
     | 
    
         
            -
                 
     | 
| 
       4 
     | 
    
         
            -
                   
     | 
| 
      
 3 
     | 
    
         
            +
                class Billable
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :billable
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
                   
     | 
| 
       7 
     | 
    
         
            -
                     
     | 
| 
      
 6 
     | 
    
         
            +
                  delegate :processor_id,
         
     | 
| 
      
 7 
     | 
    
         
            +
                    :processor_id?,
         
     | 
| 
      
 8 
     | 
    
         
            +
                    :email,
         
     | 
| 
      
 9 
     | 
    
         
            +
                    :customer_name,
         
     | 
| 
      
 10 
     | 
    
         
            +
                    :card_token,
         
     | 
| 
      
 11 
     | 
    
         
            +
                    to: :billable
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def initialize(billable)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @billable = billable
         
     | 
| 
       8 
15 
     | 
    
         
             
                  end
         
     | 
| 
       9 
16 
     | 
    
         | 
| 
       10 
     | 
    
         
            -
                  def  
     | 
| 
      
 17 
     | 
    
         
            +
                  def customer
         
     | 
| 
       11 
18 
     | 
    
         
             
                    # pass
         
     | 
| 
       12 
19 
     | 
    
         
             
                  end
         
     | 
| 
       13 
20 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                  def  
     | 
| 
      
 21 
     | 
    
         
            +
                  def charge(amount, options = {})
         
     | 
| 
      
 22 
     | 
    
         
            +
                    subscription = billable.subscription
         
     | 
| 
       15 
23 
     | 
    
         
             
                    return unless subscription.processor_id
         
     | 
| 
       16 
24 
     | 
    
         
             
                    raise Pay::Error, "A charge_name is required to create a one-time charge" if options[:charge_name].nil?
         
     | 
| 
       17 
25 
     | 
    
         
             
                    response = PaddlePay::Subscription::Charge.create(subscription.processor_id, amount.to_f / 100, options[:charge_name], options)
         
     | 
| 
       18 
     | 
    
         
            -
                    charge = charges.find_or_initialize_by(
         
     | 
| 
       19 
     | 
    
         
            -
                      processor: :paddle,
         
     | 
| 
       20 
     | 
    
         
            -
                      processor_id: response[:invoice_id]
         
     | 
| 
       21 
     | 
    
         
            -
                    )
         
     | 
| 
      
 26 
     | 
    
         
            +
                    charge = billable.charges.find_or_initialize_by(processor: :paddle, processor_id: response[:invoice_id])
         
     | 
| 
       22 
27 
     | 
    
         
             
                    charge.update(
         
     | 
| 
       23 
28 
     | 
    
         
             
                      amount: Integer(response[:amount].to_f * 100),
         
     | 
| 
       24 
     | 
    
         
            -
                      card_type: subscription. 
     | 
| 
      
 29 
     | 
    
         
            +
                      card_type: processor_subscription(subscription.processor_id).payment_information[:payment_method],
         
     | 
| 
       25 
30 
     | 
    
         
             
                      paddle_receipt_url: response[:receipt_url],
         
     | 
| 
       26 
31 
     | 
    
         
             
                      created_at: Time.zone.parse(response[:payment_date])
         
     | 
| 
       27 
32 
     | 
    
         
             
                    )
         
     | 
| 
         @@ -30,46 +35,45 @@ module Pay 
     | 
|
| 
       30 
35 
     | 
    
         
             
                    raise Pay::Paddle::Error, e
         
     | 
| 
       31 
36 
     | 
    
         
             
                  end
         
     | 
| 
       32 
37 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
                  def  
     | 
| 
      
 38 
     | 
    
         
            +
                  def subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, **options)
         
     | 
| 
       34 
39 
     | 
    
         
             
                    # pass
         
     | 
| 
       35 
40 
     | 
    
         
             
                  end
         
     | 
| 
       36 
41 
     | 
    
         | 
| 
       37 
     | 
    
         
            -
                  def  
     | 
| 
      
 42 
     | 
    
         
            +
                  def update_card(token)
         
     | 
| 
       38 
43 
     | 
    
         
             
                    sync_payment_information_from_paddle
         
     | 
| 
       39 
44 
     | 
    
         
             
                  end
         
     | 
| 
       40 
45 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
                  def  
     | 
| 
      
 46 
     | 
    
         
            +
                  def update_email!
         
     | 
| 
       42 
47 
     | 
    
         
             
                    # pass
         
     | 
| 
       43 
48 
     | 
    
         
             
                  end
         
     | 
| 
       44 
49 
     | 
    
         | 
| 
       45 
     | 
    
         
            -
                  def  
     | 
| 
      
 50 
     | 
    
         
            +
                  def trial_end_date(subscription)
         
     | 
| 
       46 
51 
     | 
    
         
             
                    return unless subscription.state == "trialing"
         
     | 
| 
       47 
52 
     | 
    
         
             
                    Time.zone.parse(subscription.next_payment[:date]).end_of_day
         
     | 
| 
       48 
53 
     | 
    
         
             
                  end
         
     | 
| 
       49 
54 
     | 
    
         | 
| 
       50 
     | 
    
         
            -
                  def  
     | 
| 
      
 55 
     | 
    
         
            +
                  def processor_subscription(subscription_id, options = {})
         
     | 
| 
       51 
56 
     | 
    
         
             
                    hash = PaddlePay::Subscription::User.list({subscription_id: subscription_id}, options).try(:first)
         
     | 
| 
       52 
57 
     | 
    
         
             
                    OpenStruct.new(hash)
         
     | 
| 
       53 
58 
     | 
    
         
             
                  rescue ::PaddlePay::PaddlePayError => e
         
     | 
| 
       54 
59 
     | 
    
         
             
                    raise Pay::Paddle::Error, e
         
     | 
| 
       55 
60 
     | 
    
         
             
                  end
         
     | 
| 
       56 
61 
     | 
    
         | 
| 
       57 
     | 
    
         
            -
                  def  
     | 
| 
      
 62 
     | 
    
         
            +
                  def invoice!(options = {})
         
     | 
| 
       58 
63 
     | 
    
         
             
                    # pass
         
     | 
| 
       59 
64 
     | 
    
         
             
                  end
         
     | 
| 
       60 
65 
     | 
    
         | 
| 
       61 
     | 
    
         
            -
                  def  
     | 
| 
      
 66 
     | 
    
         
            +
                  def upcoming_invoice
         
     | 
| 
       62 
67 
     | 
    
         
             
                    # pass
         
     | 
| 
       63 
68 
     | 
    
         
             
                  end
         
     | 
| 
       64 
69 
     | 
    
         | 
| 
       65 
     | 
    
         
            -
                  def  
     | 
| 
       66 
     | 
    
         
            -
                    payment_information 
     | 
| 
       67 
     | 
    
         
            -
                    update!(payment_information) unless payment_information.empty?
         
     | 
| 
      
 70 
     | 
    
         
            +
                  def sync_payment_information
         
     | 
| 
      
 71 
     | 
    
         
            +
                    billable.update!(payment_information(billable.subscription.processor_id))
         
     | 
| 
       68 
72 
     | 
    
         
             
                  rescue ::PaddlePay::PaddlePayError => e
         
     | 
| 
       69 
73 
     | 
    
         
             
                    raise Pay::Paddle::Error, e
         
     | 
| 
       70 
74 
     | 
    
         
             
                  end
         
     | 
| 
       71 
75 
     | 
    
         | 
| 
       72 
     | 
    
         
            -
                  def  
     | 
| 
      
 76 
     | 
    
         
            +
                  def payment_information(subscription_id)
         
     | 
| 
       73 
77 
     | 
    
         
             
                    subscription_user = PaddlePay::Subscription::User.list({subscription_id: subscription_id}).try(:first)
         
     | 
| 
       74 
78 
     | 
    
         
             
                    payment_information = subscription_user ? subscription_user[:payment_information] : nil
         
     | 
| 
       75 
79 
     | 
    
         
             
                    return {} if payment_information.nil?
         
     | 
    
        data/lib/pay/paddle/charge.rb
    CHANGED
    
    | 
         @@ -1,19 +1,15 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Pay
         
     | 
| 
       2 
2 
     | 
    
         
             
              module Paddle
         
     | 
| 
       3 
     | 
    
         
            -
                 
     | 
| 
       4 
     | 
    
         
            -
                   
     | 
| 
      
 3 
     | 
    
         
            +
                class Charge
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :pay_charge
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
                   
     | 
| 
       7 
     | 
    
         
            -
                    scope :paddle, -> { where(processor: :paddle) }
         
     | 
| 
      
 6 
     | 
    
         
            +
                  delegate :processor_id, :owner, to: :pay_charge
         
     | 
| 
       8 
7 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def initialize(pay_charge)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @pay_charge = pay_charge
         
     | 
| 
       10 
10 
     | 
    
         
             
                  end
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
                  def  
     | 
| 
       13 
     | 
    
         
            -
                    processor == "paddle"
         
     | 
| 
       14 
     | 
    
         
            -
                  end
         
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
                  def paddle_charge
         
     | 
| 
      
 12 
     | 
    
         
            +
                  def charge
         
     | 
| 
       17 
13 
     | 
    
         
             
                    return unless owner.subscription
         
     | 
| 
       18 
14 
     | 
    
         
             
                    payments = PaddlePay::Subscription::Payment.list({subscription_id: owner.subscription.processor_id})
         
     | 
| 
       19 
15 
     | 
    
         
             
                    charges = payments.select { |p| p[:id].to_s == processor_id }
         
     | 
| 
         @@ -22,12 +18,12 @@ module Pay 
     | 
|
| 
       22 
18 
     | 
    
         
             
                    raise Pay::Paddle::Error, e
         
     | 
| 
       23 
19 
     | 
    
         
             
                  end
         
     | 
| 
       24 
20 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                  def  
     | 
| 
      
 21 
     | 
    
         
            +
                  def refund!(amount_to_refund)
         
     | 
| 
       26 
22 
     | 
    
         
             
                    return unless owner.subscription
         
     | 
| 
       27 
23 
     | 
    
         
             
                    payments = PaddlePay::Subscription::Payment.list({subscription_id: owner.subscription.processor_id, is_paid: 1})
         
     | 
| 
       28 
24 
     | 
    
         
             
                    if payments.count > 0
         
     | 
| 
       29 
25 
     | 
    
         
             
                      PaddlePay::Subscription::Payment.refund(payments.last[:id], {amount: amount_to_refund})
         
     | 
| 
       30 
     | 
    
         
            -
                      update(amount_refunded: amount_to_refund)
         
     | 
| 
      
 26 
     | 
    
         
            +
                      pay_charge.update(amount_refunded: amount_to_refund)
         
     | 
| 
       31 
27 
     | 
    
         
             
                    else
         
     | 
| 
       32 
28 
     | 
    
         
             
                      raise Error, "Payment not found"
         
     | 
| 
       33 
29 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -1,62 +1,73 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Pay
         
     | 
| 
       2 
2 
     | 
    
         
             
              module Paddle
         
     | 
| 
       3 
     | 
    
         
            -
                 
     | 
| 
       4 
     | 
    
         
            -
                   
     | 
| 
      
 3 
     | 
    
         
            +
                class Subscription
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :pay_subscription
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
                   
     | 
| 
       7 
     | 
    
         
            -
                     
     | 
| 
       8 
     | 
    
         
            -
                     
     | 
| 
       9 
     | 
    
         
            -
                     
     | 
| 
      
 6 
     | 
    
         
            +
                  delegate :canceled?,
         
     | 
| 
      
 7 
     | 
    
         
            +
                    :ends_at,
         
     | 
| 
      
 8 
     | 
    
         
            +
                    :on_trial?,
         
     | 
| 
      
 9 
     | 
    
         
            +
                    :owner,
         
     | 
| 
      
 10 
     | 
    
         
            +
                    :paddle_paused_from,
         
     | 
| 
      
 11 
     | 
    
         
            +
                    :processor_id,
         
     | 
| 
      
 12 
     | 
    
         
            +
                    :processor_plan,
         
     | 
| 
      
 13 
     | 
    
         
            +
                    :processor_subscription,
         
     | 
| 
      
 14 
     | 
    
         
            +
                    :prorate,
         
     | 
| 
      
 15 
     | 
    
         
            +
                    :quantity,
         
     | 
| 
      
 16 
     | 
    
         
            +
                    :quantity?,
         
     | 
| 
      
 17 
     | 
    
         
            +
                    to: :pay_subscription
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def initialize(pay_subscription)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    @pay_subscription = pay_subscription
         
     | 
| 
       10 
21 
     | 
    
         
             
                  end
         
     | 
| 
       11 
22 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
                  def  
     | 
| 
      
 23 
     | 
    
         
            +
                  def cancel
         
     | 
| 
       13 
24 
     | 
    
         
             
                    subscription = processor_subscription
         
     | 
| 
       14 
25 
     | 
    
         
             
                    PaddlePay::Subscription::User.cancel(processor_id)
         
     | 
| 
       15 
26 
     | 
    
         
             
                    if on_trial?
         
     | 
| 
       16 
     | 
    
         
            -
                      update(status: :canceled, ends_at: trial_ends_at)
         
     | 
| 
      
 27 
     | 
    
         
            +
                      pay_subscription.update(status: :canceled, ends_at: trial_ends_at)
         
     | 
| 
       17 
28 
     | 
    
         
             
                    else
         
     | 
| 
       18 
     | 
    
         
            -
                      update(status: :canceled, ends_at: Time.zone.parse(subscription.next_payment[:date]))
         
     | 
| 
      
 29 
     | 
    
         
            +
                      pay_subscription.update(status: :canceled, ends_at: Time.zone.parse(subscription.next_payment[:date]))
         
     | 
| 
       19 
30 
     | 
    
         
             
                    end
         
     | 
| 
       20 
31 
     | 
    
         
             
                  rescue ::PaddlePay::PaddlePayError => e
         
     | 
| 
       21 
32 
     | 
    
         
             
                    raise Pay::Paddle::Error, e
         
     | 
| 
       22 
33 
     | 
    
         
             
                  end
         
     | 
| 
       23 
34 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
                  def  
     | 
| 
      
 35 
     | 
    
         
            +
                  def cancel_now!
         
     | 
| 
       25 
36 
     | 
    
         
             
                    PaddlePay::Subscription::User.cancel(processor_id)
         
     | 
| 
       26 
     | 
    
         
            -
                    update(status: :canceled, ends_at: Time.zone.now)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    pay_subscription.update(status: :canceled, ends_at: Time.zone.now)
         
     | 
| 
       27 
38 
     | 
    
         
             
                  rescue ::PaddlePay::PaddlePayError => e
         
     | 
| 
       28 
39 
     | 
    
         
             
                    raise Pay::Paddle::Error, e
         
     | 
| 
       29 
40 
     | 
    
         
             
                  end
         
     | 
| 
       30 
41 
     | 
    
         | 
| 
       31 
     | 
    
         
            -
                  def  
     | 
| 
      
 42 
     | 
    
         
            +
                  def on_grace_period?
         
     | 
| 
       32 
43 
     | 
    
         
             
                    canceled? && Time.zone.now < ends_at || paused? && Time.zone.now < paddle_paused_from
         
     | 
| 
       33 
44 
     | 
    
         
             
                  end
         
     | 
| 
       34 
45 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
                  def  
     | 
| 
      
 46 
     | 
    
         
            +
                  def paused?
         
     | 
| 
       36 
47 
     | 
    
         
             
                    paddle_paused_from.present?
         
     | 
| 
       37 
48 
     | 
    
         
             
                  end
         
     | 
| 
       38 
49 
     | 
    
         | 
| 
       39 
     | 
    
         
            -
                  def  
     | 
| 
      
 50 
     | 
    
         
            +
                  def pause
         
     | 
| 
       40 
51 
     | 
    
         
             
                    attributes = {pause: true}
         
     | 
| 
       41 
52 
     | 
    
         
             
                    response = PaddlePay::Subscription::User.update(processor_id, attributes)
         
     | 
| 
       42 
     | 
    
         
            -
                    update(paddle_paused_from: Time.zone.parse(response[:next_payment][:date]))
         
     | 
| 
      
 53 
     | 
    
         
            +
                    pay_subscription.update(paddle_paused_from: Time.zone.parse(response[:next_payment][:date]))
         
     | 
| 
       43 
54 
     | 
    
         
             
                  rescue ::PaddlePay::PaddlePayError => e
         
     | 
| 
       44 
55 
     | 
    
         
             
                    raise Pay::Paddle::Error, e
         
     | 
| 
       45 
56 
     | 
    
         
             
                  end
         
     | 
| 
       46 
57 
     | 
    
         | 
| 
       47 
     | 
    
         
            -
                  def  
     | 
| 
      
 58 
     | 
    
         
            +
                  def resume
         
     | 
| 
       48 
59 
     | 
    
         
             
                    unless paused?
         
     | 
| 
       49 
60 
     | 
    
         
             
                      raise StandardError, "You can only resume paused subscriptions."
         
     | 
| 
       50 
61 
     | 
    
         
             
                    end
         
     | 
| 
       51 
62 
     | 
    
         | 
| 
       52 
63 
     | 
    
         
             
                    attributes = {pause: false}
         
     | 
| 
       53 
64 
     | 
    
         
             
                    PaddlePay::Subscription::User.update(processor_id, attributes)
         
     | 
| 
       54 
     | 
    
         
            -
                    update(status: :active, paddle_paused_from: nil)
         
     | 
| 
      
 65 
     | 
    
         
            +
                    pay_subscription.update(status: :active, paddle_paused_from: nil)
         
     | 
| 
       55 
66 
     | 
    
         
             
                  rescue ::PaddlePay::PaddlePayError => e
         
     | 
| 
       56 
67 
     | 
    
         
             
                    raise Pay::Paddle::Error, e
         
     | 
| 
       57 
68 
     | 
    
         
             
                  end
         
     | 
| 
       58 
69 
     | 
    
         | 
| 
       59 
     | 
    
         
            -
                  def  
     | 
| 
      
 70 
     | 
    
         
            +
                  def swap(plan)
         
     | 
| 
       60 
71 
     | 
    
         
             
                    attributes = {plan_id: plan, prorate: prorate}
         
     | 
| 
       61 
72 
     | 
    
         
             
                    attributes[:quantity] = quantity if quantity?
         
     | 
| 
       62 
73 
     | 
    
         
             
                    PaddlePay::Subscription::User.update(processor_id, attributes)
         
     |