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
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 429e92c76a90f5de0cec18dce219479de7ea172d6807c3b0d86d0a2fe4994b77
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 85b9e46b65d4ea0fa0e7255cc47e1e5c60e55e14f18fee9c567c4befb0e1dac7
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 577c6792e5ff3f60e01a02de38bdc414aa0c6178ec0927c6b5766051224f632f83d551a787888d196ac57cf7d4299786a5f1afbcfc0376b10b9115ca97c74dc7
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: dc0da5b5df00f672cc621acf89168f7b3c8c1f419aaa7c5802f015cfb3a4c6cf95284310fc776ca67e51da69c803a24d9c66b50407bd08044492abff1444eb00
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -8,9 +8,9 @@ Pay is a payments engine for Ruby on Rails 4.2 and higher. 
     | 
|
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
            **Current Payment Providers**
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
            - Stripe ([ 
     | 
| 
       12 
     | 
    
         
            -
            -  
     | 
| 
       13 
     | 
    
         
            -
            -  
     | 
| 
      
 11 
     | 
    
         
            +
            - Stripe ([SCA Compatible](https://stripe.com/docs/strong-customer-authentication) using API version `2020-08-27`)
         
     | 
| 
      
 12 
     | 
    
         
            +
            - Paddle (SCA Compatible & supports PayPal)
         
     | 
| 
      
 13 
     | 
    
         
            +
            - Braintree (supports PayPal)
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         
             
            Want to add a new payment provider? Contributions are welcome and the instructions [are here](https://github.com/jasoncharnes/pay/wiki/New-Payment-Provider).
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
         @@ -31,7 +31,6 @@ gem 'pay', '~> 2.0' 
     | 
|
| 
       31 
31 
     | 
    
         | 
| 
       32 
32 
     | 
    
         
             
            # To use Stripe, also include:
         
     | 
| 
       33 
33 
     | 
    
         
             
            gem 'stripe', '< 6.0', '>= 2.8'
         
     | 
| 
       34 
     | 
    
         
            -
            gem 'stripe_event', '~> 2.3'
         
     | 
| 
       35 
34 
     | 
    
         | 
| 
       36 
35 
     | 
    
         
             
            # To use Braintree + PayPal, also include:
         
     | 
| 
       37 
36 
     | 
    
         
             
            gem 'braintree', '< 3.0', '>= 2.92.0'
         
     | 
| 
         @@ -49,6 +48,13 @@ And then execute: 
     | 
|
| 
       49 
48 
     | 
    
         
             
            bundle
         
     | 
| 
       50 
49 
     | 
    
         
             
            ```
         
     | 
| 
       51 
50 
     | 
    
         | 
| 
      
 51 
     | 
    
         
            +
            Make sure you've configured your ActionMailer default_url_options so Pay can generate links to for features like Stripe Checkout.
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 54 
     | 
    
         
            +
            # config/application.rb
         
     | 
| 
      
 55 
     | 
    
         
            +
            config.action_mailer.default_url_options = { host: "example.com" }
         
     | 
| 
      
 56 
     | 
    
         
            +
            ```
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
       52 
58 
     | 
    
         
             
            #### Migrations
         
     | 
| 
       53 
59 
     | 
    
         | 
| 
       54 
60 
     | 
    
         
             
            To add the migrations to your application, run the following migration:
         
     | 
| 
         @@ -6,66 +6,20 @@ module Pay 
     | 
|
| 
       6 
6 
     | 
    
         
             
                  end
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
                  def create
         
     | 
| 
       9 
     | 
    
         
            -
                     
     | 
| 
       10 
     | 
    
         
            -
                    when "subscription_charged_successfully"
         
     | 
| 
       11 
     | 
    
         
            -
                      subscription_charged_successfully(webhook_notification)
         
     | 
| 
       12 
     | 
    
         
            -
                    when "subscription_canceled"
         
     | 
| 
       13 
     | 
    
         
            -
                      subscription_canceled(webhook_notification)
         
     | 
| 
       14 
     | 
    
         
            -
                    when "subscription_trial_ended"
         
     | 
| 
       15 
     | 
    
         
            -
                      subscription_trial_ended(webhook_notification)
         
     | 
| 
       16 
     | 
    
         
            -
                    end
         
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
                    render json: {success: true}, status: :ok
         
     | 
| 
       19 
     | 
    
         
            -
                  rescue ::Braintree::InvalidSignature
         
     | 
| 
      
 9 
     | 
    
         
            +
                    delegate_event(verified_event)
         
     | 
| 
       20 
10 
     | 
    
         
             
                    head :ok
         
     | 
| 
      
 11 
     | 
    
         
            +
                  rescue ::Braintree::InvalidSignature
         
     | 
| 
      
 12 
     | 
    
         
            +
                    head :bad_request
         
     | 
| 
       21 
13 
     | 
    
         
             
                  end
         
     | 
| 
       22 
14 
     | 
    
         | 
| 
       23 
15 
     | 
    
         
             
                  private
         
     | 
| 
       24 
16 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                  def  
     | 
| 
       26 
     | 
    
         
            -
                     
     | 
| 
       27 
     | 
    
         
            -
                    return if subscription.nil?
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
                    pay_subscription = Pay.subscription_model.find_by(processor: :braintree, processor_id: subscription.id)
         
     | 
| 
       30 
     | 
    
         
            -
                    return unless pay_subscription.present?
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
                    billable = pay_subscription.owner
         
     | 
| 
       33 
     | 
    
         
            -
                    charge = billable.save_braintree_transaction(subscription.transactions.first)
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
                    if Pay.send_emails
         
     | 
| 
       36 
     | 
    
         
            -
                      Pay::UserMailer.with(billable: billable, charge: charge).receipt.deliver_later
         
     | 
| 
       37 
     | 
    
         
            -
                    end
         
     | 
| 
       38 
     | 
    
         
            -
                  end
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
                  def subscription_canceled(event)
         
     | 
| 
       41 
     | 
    
         
            -
                    subscription = event.subscription
         
     | 
| 
       42 
     | 
    
         
            -
                    return if subscription.nil?
         
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
                    pay_subscription = Pay.subscription_model.find_by(processor: :braintree, processor_id: subscription.id)
         
     | 
| 
       45 
     | 
    
         
            -
                    return unless pay_subscription.present?
         
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
                    billable = pay_subscription.owner
         
     | 
| 
       48 
     | 
    
         
            -
                    return if billable.nil?
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
                    # User canceled or failed to make payments
         
     | 
| 
       51 
     | 
    
         
            -
                    billable.update(braintree_subscription_id: nil)
         
     | 
| 
       52 
     | 
    
         
            -
                  end
         
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
                  def subscription_trial_ended(event)
         
     | 
| 
       55 
     | 
    
         
            -
                    subscription = event.subscription
         
     | 
| 
       56 
     | 
    
         
            -
                    return if subscription.nil?
         
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
                    pay_subscription = Pay.subscription_model.find_by(processor: :braintree, processor_id: subscription.id)
         
     | 
| 
       59 
     | 
    
         
            -
                    return unless pay_subscription.present?
         
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
                    pay_subscription.update(trial_ends_at: Time.zone.now)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  def delegate_event(event)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    Pay::Webhooks.instrument type: "braintree.#{event.kind}", event: event
         
     | 
| 
       62 
19 
     | 
    
         
             
                  end
         
     | 
| 
       63 
20 
     | 
    
         | 
| 
       64 
     | 
    
         
            -
                  def  
     | 
| 
       65 
     | 
    
         
            -
                     
     | 
| 
       66 
     | 
    
         
            -
                      params[:bt_signature],
         
     | 
| 
       67 
     | 
    
         
            -
                      params[:bt_payload]
         
     | 
| 
       68 
     | 
    
         
            -
                    )
         
     | 
| 
      
 21 
     | 
    
         
            +
                  def verified_event
         
     | 
| 
      
 22 
     | 
    
         
            +
                    Pay.braintree_gateway.webhook_notification.parse(params[:bt_signature], params[:bt_payload])
         
     | 
| 
       69 
23 
     | 
    
         
             
                  end
         
     | 
| 
       70 
24 
     | 
    
         
             
                end
         
     | 
| 
       71 
25 
     | 
    
         
             
              end
         
     | 
| 
         @@ -6,28 +6,29 @@ module Pay 
     | 
|
| 
       6 
6 
     | 
    
         
             
                  end
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
                  def create
         
     | 
| 
       9 
     | 
    
         
            -
                     
     | 
| 
       10 
     | 
    
         
            -
                     
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
                        Pay::Paddle::Webhooks::SubscriptionCreated.new(check_params.as_json)
         
     | 
| 
       14 
     | 
    
         
            -
                      when "subscription_updated"
         
     | 
| 
       15 
     | 
    
         
            -
                        Pay::Paddle::Webhooks::SubscriptionUpdated.new(check_params.as_json)
         
     | 
| 
       16 
     | 
    
         
            -
                      when "subscription_cancelled"
         
     | 
| 
       17 
     | 
    
         
            -
                        Pay::Paddle::Webhooks::SubscriptionCancelled.new(check_params.as_json)
         
     | 
| 
       18 
     | 
    
         
            -
                      when "subscription_payment_succeeded"
         
     | 
| 
       19 
     | 
    
         
            -
                        Pay::Paddle::Webhooks::SubscriptionPaymentSucceeded.new(check_params.as_json)
         
     | 
| 
       20 
     | 
    
         
            -
                      when "subscription_payment_refunded"
         
     | 
| 
       21 
     | 
    
         
            -
                        Pay::Paddle::Webhooks::SubscriptionPaymentRefunded.new(check_params.as_json)
         
     | 
| 
       22 
     | 
    
         
            -
                      end
         
     | 
| 
       23 
     | 
    
         
            -
                      render json: {success: true}, status: :ok
         
     | 
| 
       24 
     | 
    
         
            -
                    else
         
     | 
| 
       25 
     | 
    
         
            -
                      head :ok
         
     | 
| 
       26 
     | 
    
         
            -
                    end
         
     | 
| 
      
 9 
     | 
    
         
            +
                    delegate_event(verified_event)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    head :ok
         
     | 
| 
      
 11 
     | 
    
         
            +
                  rescue Pay::Paddle::Error
         
     | 
| 
      
 12 
     | 
    
         
            +
                    head :bad_request
         
     | 
| 
       27 
13 
     | 
    
         
             
                  end
         
     | 
| 
       28 
14 
     | 
    
         | 
| 
       29 
15 
     | 
    
         
             
                  private
         
     | 
| 
       30 
16 
     | 
    
         | 
| 
      
 17 
     | 
    
         
            +
                  def delegate_event(event)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    Pay::Webhooks.instrument type: "paddle.#{type}", event: event
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def type
         
     | 
| 
      
 22 
     | 
    
         
            +
                    params[:alert_name]
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def verified_event
         
     | 
| 
      
 26 
     | 
    
         
            +
                    event = check_params.as_json
         
     | 
| 
      
 27 
     | 
    
         
            +
                    verifier = Pay::Paddle::Webhooks::SignatureVerifier.new(event)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    return event if verifier.verify
         
     | 
| 
      
 29 
     | 
    
         
            +
                    raise Pay::Paddle::Error, "Unable to verify Paddle webhook event"
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
       31 
32 
     | 
    
         
             
                  def check_params
         
     | 
| 
       32 
33 
     | 
    
         
             
                    params.except(:action, :controller).permit!
         
     | 
| 
       33 
34 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Pay
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Webhooks
         
     | 
| 
      
 3 
     | 
    
         
            +
                class StripeController < Pay::ApplicationController
         
     | 
| 
      
 4 
     | 
    
         
            +
                  if Rails.application.config.action_controller.default_protect_from_forgery
         
     | 
| 
      
 5 
     | 
    
         
            +
                    skip_before_action :verify_authenticity_token
         
     | 
| 
      
 6 
     | 
    
         
            +
                  end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def create
         
     | 
| 
      
 9 
     | 
    
         
            +
                    delegate_event(verified_event)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    head :ok
         
     | 
| 
      
 11 
     | 
    
         
            +
                  rescue ::Stripe::SignatureVerificationError => e
         
     | 
| 
      
 12 
     | 
    
         
            +
                    log_error(e)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    head :bad_request
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  private
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def delegate_event(event)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    Pay::Webhooks.instrument type: "stripe.#{event.type}", event: event
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def verified_event
         
     | 
| 
      
 23 
     | 
    
         
            +
                    payload = request.body.read
         
     | 
| 
      
 24 
     | 
    
         
            +
                    signature = request.headers["Stripe-Signature"]
         
     | 
| 
      
 25 
     | 
    
         
            +
                    possible_secrets = secrets(payload, signature)
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    possible_secrets.each_with_index do |secret, i|
         
     | 
| 
      
 28 
     | 
    
         
            +
                      return ::Stripe::Webhook.construct_event(payload, signature, secret.to_s)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    rescue ::Stripe::SignatureVerificationError
         
     | 
| 
      
 30 
     | 
    
         
            +
                      raise if i == possible_secrets.length - 1
         
     | 
| 
      
 31 
     | 
    
         
            +
                      next
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  def secrets(payload, signature)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    secret = Pay::Stripe.signing_secret
         
     | 
| 
      
 37 
     | 
    
         
            +
                    return Array.wrap(secret) if secret
         
     | 
| 
      
 38 
     | 
    
         
            +
                    raise ::Stripe::SignatureVerificationError.new("Cannot verify signature without a Stripe signing secret", signature, http_body: payload)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def log_error(e)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    logger.error e.message
         
     | 
| 
      
 43 
     | 
    
         
            +
                    e.backtrace.each { |line| logger.error "  #{line}" }
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
    
        data/app/models/pay/charge.rb
    CHANGED
    
    | 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Pay
         
     | 
| 
       2 
     | 
    
         
            -
              class Charge < ApplicationRecord
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Charge < Pay::ApplicationRecord
         
     | 
| 
       3 
3 
     | 
    
         
             
                self.table_name = Pay.chargeable_table
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
                # Only serialize for non-json columns
         
     | 
| 
         @@ -18,13 +18,32 @@ module Pay 
     | 
|
| 
       18 
18 
     | 
    
         
             
                validates :processor_id, presence: true
         
     | 
| 
       19 
19 
     | 
    
         
             
                validates :card_type, presence: true
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
      
 21 
     | 
    
         
            +
                store_accessor :data, :paddle_receipt_url
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                # Helpers for payment processors
         
     | 
| 
      
 24 
     | 
    
         
            +
                %w[braintree stripe paddle].each do |processor_name|
         
     | 
| 
      
 25 
     | 
    
         
            +
                  define_method "#{processor_name}?" do
         
     | 
| 
      
 26 
     | 
    
         
            +
                    processor == processor_name
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  scope processor_name, -> { where(processor: processor_name) }
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def payment_processor
         
     | 
| 
      
 33 
     | 
    
         
            +
                  @payment_processor ||= payment_processor_for(processor).new(self)
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                def payment_processor_for(name)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  "Pay::#{name.to_s.classify}::Charge".constantize
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
       21 
40 
     | 
    
         
             
                def processor_charge
         
     | 
| 
       22 
     | 
    
         
            -
                   
     | 
| 
      
 41 
     | 
    
         
            +
                  payment_processor.charge
         
     | 
| 
       23 
42 
     | 
    
         
             
                end
         
     | 
| 
       24 
43 
     | 
    
         | 
| 
       25 
44 
     | 
    
         
             
                def refund!(refund_amount = nil)
         
     | 
| 
       26 
45 
     | 
    
         
             
                  refund_amount ||= amount
         
     | 
| 
       27 
     | 
    
         
            -
                   
     | 
| 
      
 46 
     | 
    
         
            +
                  payment_processor.refund!(refund_amount)
         
     | 
| 
       28 
47 
     | 
    
         
             
                end
         
     | 
| 
       29 
48 
     | 
    
         | 
| 
       30 
49 
     | 
    
         
             
                def charged_to
         
     | 
| 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Pay
         
     | 
| 
       2 
     | 
    
         
            -
              class Subscription < ApplicationRecord
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Subscription < Pay::ApplicationRecord
         
     | 
| 
       3 
3 
     | 
    
         
             
                self.table_name = Pay.subscription_table
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
                STATUSES = %w[incomplete incomplete_expired trialing active past_due canceled unpaid paused]
         
     | 
| 
         @@ -27,6 +27,11 @@ module Pay 
     | 
|
| 
       27 
27 
     | 
    
         
             
                scope :incomplete, -> { where(status: :incomplete) }
         
     | 
| 
       28 
28 
     | 
    
         
             
                scope :past_due, -> { where(status: :past_due) }
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
      
 30 
     | 
    
         
            +
                # TODO: Include these with a module
         
     | 
| 
      
 31 
     | 
    
         
            +
                store_accessor :data, :paddle_update_url
         
     | 
| 
      
 32 
     | 
    
         
            +
                store_accessor :data, :paddle_cancel_url
         
     | 
| 
      
 33 
     | 
    
         
            +
                store_accessor :data, :paddle_paused_from
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
       30 
35 
     | 
    
         
             
                attribute :prorate, :boolean, default: true
         
     | 
| 
       31 
36 
     | 
    
         | 
| 
       32 
37 
     | 
    
         
             
                # Helpers for payment processors
         
     | 
| 
         @@ -38,6 +43,21 @@ module Pay 
     | 
|
| 
       38 
43 
     | 
    
         
             
                  scope processor_name, -> { where(processor: processor_name) }
         
     | 
| 
       39 
44 
     | 
    
         
             
                end
         
     | 
| 
       40 
45 
     | 
    
         | 
| 
      
 46 
     | 
    
         
            +
                def payment_processor
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @payment_processor ||= payment_processor_for(processor).new(self)
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                def payment_processor_for(name)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  "Pay::#{name.to_s.classify}::Subscription".constantize
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                delegate :on_grace_period?,
         
     | 
| 
      
 55 
     | 
    
         
            +
                  :paused?,
         
     | 
| 
      
 56 
     | 
    
         
            +
                  :pause,
         
     | 
| 
      
 57 
     | 
    
         
            +
                  :cancel,
         
     | 
| 
      
 58 
     | 
    
         
            +
                  :cancel_now!,
         
     | 
| 
      
 59 
     | 
    
         
            +
                  to: :payment_processor
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
       41 
61 
     | 
    
         
             
                def no_prorate
         
     | 
| 
       42 
62 
     | 
    
         
             
                  self.prorate = false
         
     | 
| 
       43 
63 
     | 
    
         
             
                end
         
     | 
| 
         @@ -58,11 +78,6 @@ module Pay 
     | 
|
| 
       58 
78 
     | 
    
         
             
                  canceled?
         
     | 
| 
       59 
79 
     | 
    
         
             
                end
         
     | 
| 
       60 
80 
     | 
    
         | 
| 
       61 
     | 
    
         
            -
                def on_grace_period?
         
     | 
| 
       62 
     | 
    
         
            -
                  return unless processor?
         
     | 
| 
       63 
     | 
    
         
            -
                  send("#{processor}_on_grace_period?")
         
     | 
| 
       64 
     | 
    
         
            -
                end
         
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
81 
     | 
    
         
             
                def active?
         
     | 
| 
       67 
82 
     | 
    
         
             
                  ["trialing", "active"].include?(status) && (ends_at.nil? || on_grace_period? || on_trial?)
         
     | 
| 
       68 
83 
     | 
    
         
             
                end
         
     | 
| 
         @@ -79,30 +94,14 @@ module Pay 
     | 
|
| 
       79 
94 
     | 
    
         
             
                  past_due? || incomplete?
         
     | 
| 
       80 
95 
     | 
    
         
             
                end
         
     | 
| 
       81 
96 
     | 
    
         | 
| 
       82 
     | 
    
         
            -
                def paused?
         
     | 
| 
       83 
     | 
    
         
            -
                  send("#{processor}_paused?")
         
     | 
| 
       84 
     | 
    
         
            -
                end
         
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
                def pause
         
     | 
| 
       87 
     | 
    
         
            -
                  send("#{processor}_pause")
         
     | 
| 
       88 
     | 
    
         
            -
                end
         
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
                def cancel
         
     | 
| 
       91 
     | 
    
         
            -
                  send("#{processor}_cancel")
         
     | 
| 
       92 
     | 
    
         
            -
                end
         
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
     | 
    
         
            -
                def cancel_now!
         
     | 
| 
       95 
     | 
    
         
            -
                  send("#{processor}_cancel_now!")
         
     | 
| 
       96 
     | 
    
         
            -
                end
         
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
97 
     | 
    
         
             
                def resume
         
     | 
| 
       99 
     | 
    
         
            -
                   
     | 
| 
      
 98 
     | 
    
         
            +
                  payment_processor.resume
         
     | 
| 
       100 
99 
     | 
    
         
             
                  update(ends_at: nil, status: "active")
         
     | 
| 
       101 
100 
     | 
    
         
             
                  self
         
     | 
| 
       102 
101 
     | 
    
         
             
                end
         
     | 
| 
       103 
102 
     | 
    
         | 
| 
       104 
103 
     | 
    
         
             
                def swap(plan)
         
     | 
| 
       105 
     | 
    
         
            -
                   
     | 
| 
      
 104 
     | 
    
         
            +
                  payment_processor.swap(plan)
         
     | 
| 
       106 
105 
     | 
    
         
             
                  update(processor_plan: plan, ends_at: nil)
         
     | 
| 
       107 
106 
     | 
    
         
             
                end
         
     | 
| 
       108 
107 
     | 
    
         | 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <%= button_tag title,
         
     | 
| 
      
 2 
     | 
    
         
            +
              id: "checkout-#{session.id}",
         
     | 
| 
      
 3 
     | 
    
         
            +
              class: local_assigns[:class],
         
     | 
| 
      
 4 
     | 
    
         
            +
              style: (local_assigns[:class] || local_assigns[:style]) ? local_assigns[:style] : 'background-color:#6772E5;color:#FFF;padding:8px 12px;border:0;border-radius:4px;font-size:1em'
         
     | 
| 
      
 5 
     | 
    
         
            +
            %>
         
     | 
| 
      
 6 
     | 
    
         
            +
            <%= tag.div id: "error-for-#{session.id}" %>
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            <script>
         
     | 
| 
      
 9 
     | 
    
         
            +
              (() => {
         
     | 
| 
      
 10 
     | 
    
         
            +
                const checkoutButton = document.getElementById("checkout-<%= session.id %>");
         
     | 
| 
      
 11 
     | 
    
         
            +
                checkoutButton.addEventListener('click', function () {
         
     | 
| 
      
 12 
     | 
    
         
            +
                  Stripe("<%= Pay::Stripe.public_key %>").redirectToCheckout({
         
     | 
| 
      
 13 
     | 
    
         
            +
                    sessionId: '<%= session.id %>'
         
     | 
| 
      
 14 
     | 
    
         
            +
                  }).then(function (result) {
         
     | 
| 
      
 15 
     | 
    
         
            +
                    if (result.error) {
         
     | 
| 
      
 16 
     | 
    
         
            +
                        document.getElementById('error-message').innerText = result.error.message;
         
     | 
| 
      
 17 
     | 
    
         
            +
                      }
         
     | 
| 
      
 18 
     | 
    
         
            +
                  });
         
     | 
| 
      
 19 
     | 
    
         
            +
                });
         
     | 
| 
      
 20 
     | 
    
         
            +
              })()
         
     | 
| 
      
 21 
     | 
    
         
            +
            </script>
         
     | 
    
        data/config/routes.rb
    CHANGED
    
    | 
         @@ -2,7 +2,7 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            Pay::Engine.routes.draw do
         
     | 
| 
       4 
4 
     | 
    
         
             
              resources :payments, only: [:show], module: :pay
         
     | 
| 
       5 
     | 
    
         
            -
              post "webhooks/stripe", to: " 
     | 
| 
      
 5 
     | 
    
         
            +
              post "webhooks/stripe", to: "pay/webhooks/stripe#create"
         
     | 
| 
       6 
6 
     | 
    
         
             
              post "webhooks/braintree", to: "pay/webhooks/braintree#create"
         
     | 
| 
       7 
7 
     | 
    
         
             
              post "webhooks/paddle", to: "pay/webhooks/paddle#create"
         
     | 
| 
       8 
8 
     | 
    
         
             
            end
         
     | 
    
        data/lib/pay.rb
    CHANGED
    
    | 
         @@ -1,11 +1,20 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require "pay/version"
         
     | 
| 
       2 
2 
     | 
    
         
             
            require "pay/engine"
         
     | 
| 
       3 
     | 
    
         
            -
            require "pay/billable"
         
     | 
| 
       4 
     | 
    
         
            -
            require "pay/receipts"
         
     | 
| 
       5 
     | 
    
         
            -
            require "pay/payment"
         
     | 
| 
       6 
3 
     | 
    
         
             
            require "pay/errors"
         
     | 
| 
       7 
4 
     | 
    
         | 
| 
       8 
5 
     | 
    
         
             
            module Pay
         
     | 
| 
      
 6 
     | 
    
         
            +
              autoload :Billable, "pay/billable"
         
     | 
| 
      
 7 
     | 
    
         
            +
              autoload :Env, "pay/env"
         
     | 
| 
      
 8 
     | 
    
         
            +
              autoload :Payment, "pay/payment"
         
     | 
| 
      
 9 
     | 
    
         
            +
              autoload :Receipts, "pay/receipts"
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              # Payment processors
         
     | 
| 
      
 12 
     | 
    
         
            +
              autoload :Braintree, "pay/braintree"
         
     | 
| 
      
 13 
     | 
    
         
            +
              autoload :Paddle, "pay/paddle"
         
     | 
| 
      
 14 
     | 
    
         
            +
              autoload :Stripe, "pay/stripe"
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              autoload :Webhooks, "pay/webhooks"
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
       9 
18 
     | 
    
         
             
              # Define who owns the subscription
         
     | 
| 
       10 
19 
     | 
    
         
             
              mattr_accessor :billable_class
         
     | 
| 
       11 
20 
     | 
    
         
             
              mattr_accessor :billable_table
         
     | 
| 
         @@ -37,15 +46,6 @@ module Pay 
     | 
|
| 
       37 
46 
     | 
    
         
             
              mattr_accessor :send_emails
         
     | 
| 
       38 
47 
     | 
    
         
             
              @@send_emails = true
         
     | 
| 
       39 
48 
     | 
    
         | 
| 
       40 
     | 
    
         
            -
              mattr_accessor :email_receipt_subject
         
     | 
| 
       41 
     | 
    
         
            -
              @@email_receipt_subject = "Payment receipt"
         
     | 
| 
       42 
     | 
    
         
            -
              mattr_accessor :email_refund_subject
         
     | 
| 
       43 
     | 
    
         
            -
              @@email_refund_subject = "Payment refunded"
         
     | 
| 
       44 
     | 
    
         
            -
              mattr_accessor :email_renewing_subject
         
     | 
| 
       45 
     | 
    
         
            -
              @@email_renewing_subject = "Your upcoming subscription renewal"
         
     | 
| 
       46 
     | 
    
         
            -
              mattr_accessor :email_action_required_subject
         
     | 
| 
       47 
     | 
    
         
            -
              @@email_action_required_subject = "Confirm your payment"
         
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
49 
     | 
    
         
             
              mattr_accessor :automount_routes
         
     | 
| 
       50 
50 
     | 
    
         
             
              @@automount_routes = true
         
     | 
| 
       51 
51 
     | 
    
         | 
    
        data/lib/pay/billable.rb
    CHANGED
    
    | 
         @@ -17,9 +17,6 @@ module Pay 
     | 
|
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
                included do |base|
         
     | 
| 
       19 
19 
     | 
    
         
             
                  include Pay::Billable::SyncEmail
         
     | 
| 
       20 
     | 
    
         
            -
                  include Pay::Stripe::Billable if defined? ::Stripe
         
     | 
| 
       21 
     | 
    
         
            -
                  include Pay::Braintree::Billable if defined? ::Braintree
         
     | 
| 
       22 
     | 
    
         
            -
                  include Pay::Paddle::Billable if defined? ::PaddlePay
         
     | 
| 
       23 
20 
     | 
    
         | 
| 
       24 
21 
     | 
    
         
             
                  has_many :charges, class_name: Pay.chargeable_class, foreign_key: :owner_id, inverse_of: :owner, as: :owner
         
     | 
| 
       25 
22 
     | 
    
         
             
                  has_many :subscriptions, class_name: Pay.subscription_class, foreign_key: :owner_id, inverse_of: :owner, as: :owner
         
     | 
| 
         @@ -29,17 +26,34 @@ module Pay 
     | 
|
| 
       29 
26 
     | 
    
         
             
                  attribute :card_token, :string
         
     | 
| 
       30 
27 
     | 
    
         
             
                end
         
     | 
| 
       31 
28 
     | 
    
         | 
| 
      
 29 
     | 
    
         
            +
                def payment_processor
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @payment_processor ||= payment_processor_for(processor).new(self)
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def payment_processor_for(name)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  "Pay::#{name.to_s.classify}::Billable".constantize
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                # Reset the payment processor when it changes
         
     | 
| 
       32 
38 
     | 
    
         
             
                def processor=(value)
         
     | 
| 
       33 
39 
     | 
    
         
             
                  super(value)
         
     | 
| 
       34 
40 
     | 
    
         
             
                  self.processor_id = nil if processor_changed?
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @payment_processor = nil
         
     | 
| 
       35 
42 
     | 
    
         
             
                end
         
     | 
| 
       36 
43 
     | 
    
         | 
| 
      
 44 
     | 
    
         
            +
                def processor
         
     | 
| 
      
 45 
     | 
    
         
            +
                  super&.inquiry
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                delegate :charge, to: :payment_processor
         
     | 
| 
      
 49 
     | 
    
         
            +
                delegate :subscribe, to: :payment_processor
         
     | 
| 
      
 50 
     | 
    
         
            +
                delegate :update_card, to: :payment_processor
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
       37 
52 
     | 
    
         
             
                def customer
         
     | 
| 
       38 
     | 
    
         
            -
                  check_for_processor
         
     | 
| 
       39 
53 
     | 
    
         
             
                  raise Pay::Error, I18n.t("errors.email_required") if email.nil?
         
     | 
| 
       40 
54 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
                  customer =  
     | 
| 
       42 
     | 
    
         
            -
                  update_card(card_token) if card_token.present?
         
     | 
| 
      
 55 
     | 
    
         
            +
                  customer = payment_processor.customer
         
     | 
| 
      
 56 
     | 
    
         
            +
                  payment_processor.update_card(card_token) if card_token.present?
         
     | 
| 
       43 
57 
     | 
    
         
             
                  customer
         
     | 
| 
       44 
58 
     | 
    
         
             
                end
         
     | 
| 
       45 
59 
     | 
    
         | 
| 
         @@ -47,20 +61,9 @@ module Pay 
     | 
|
| 
       47 
61 
     | 
    
         
             
                  [try(:first_name), try(:last_name)].compact.join(" ")
         
     | 
| 
       48 
62 
     | 
    
         
             
                end
         
     | 
| 
       49 
63 
     | 
    
         | 
| 
       50 
     | 
    
         
            -
                def  
     | 
| 
       51 
     | 
    
         
            -
                   
     | 
| 
       52 
     | 
    
         
            -
                   
     | 
| 
       53 
     | 
    
         
            -
                end
         
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
                def subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, **options)
         
     | 
| 
       56 
     | 
    
         
            -
                  check_for_processor
         
     | 
| 
       57 
     | 
    
         
            -
                  send("create_#{processor}_subscription", name, plan, options)
         
     | 
| 
       58 
     | 
    
         
            -
                end
         
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
                def update_card(token)
         
     | 
| 
       61 
     | 
    
         
            -
                  check_for_processor
         
     | 
| 
       62 
     | 
    
         
            -
                  customer if processor_id.nil?
         
     | 
| 
       63 
     | 
    
         
            -
                  send("update_#{processor}_card", token)
         
     | 
| 
      
 64 
     | 
    
         
            +
                def create_setup_intent
         
     | 
| 
      
 65 
     | 
    
         
            +
                  ActiveSupport::Deprecation.warn("This method will be removed in the next release. Use `@billable.payment_processor.create_setup_intent` instead.")
         
     | 
| 
      
 66 
     | 
    
         
            +
                  payment_processor.create_setup_intent
         
     | 
| 
       64 
67 
     | 
    
         
             
                end
         
     | 
| 
       65 
68 
     | 
    
         | 
| 
       66 
69 
     | 
    
         
             
                def on_trial?(name: Pay.default_product_name, plan: nil)
         
     | 
| 
         @@ -77,8 +80,7 @@ module Pay 
     | 
|
| 
       77 
80 
     | 
    
         
             
                end
         
     | 
| 
       78 
81 
     | 
    
         | 
| 
       79 
82 
     | 
    
         
             
                def processor_subscription(subscription_id, options = {})
         
     | 
| 
       80 
     | 
    
         
            -
                   
     | 
| 
       81 
     | 
    
         
            -
                  send("#{processor}_subscription", subscription_id, options)
         
     | 
| 
      
 83 
     | 
    
         
            +
                  payment_processor.processor_subscription(subscription_id, options)
         
     | 
| 
       82 
84 
     | 
    
         
             
                end
         
     | 
| 
       83 
85 
     | 
    
         | 
| 
       84 
86 
     | 
    
         
             
                def subscribed?(name: Pay.default_product_name, processor_plan: nil)
         
     | 
| 
         @@ -100,26 +102,31 @@ module Pay 
     | 
|
| 
       100 
102 
     | 
    
         
             
                end
         
     | 
| 
       101 
103 
     | 
    
         | 
| 
       102 
104 
     | 
    
         
             
                def invoice!(options = {})
         
     | 
| 
       103 
     | 
    
         
            -
                   
     | 
| 
      
 105 
     | 
    
         
            +
                  ActiveSupport::Deprecation.warn("This will be removed in the next release. Use `@billable.payment_processor.invoice!` instead.")
         
     | 
| 
      
 106 
     | 
    
         
            +
                  payment_processor.invoice!(options)
         
     | 
| 
       104 
107 
     | 
    
         
             
                end
         
     | 
| 
       105 
108 
     | 
    
         | 
| 
       106 
109 
     | 
    
         
             
                def upcoming_invoice
         
     | 
| 
       107 
     | 
    
         
            -
                   
     | 
| 
      
 110 
     | 
    
         
            +
                  ActiveSupport::Deprecation.warn("This will be removed in the next release. Use `@billable.payment_processor.upcoming_invoice` instead.")
         
     | 
| 
      
 111 
     | 
    
         
            +
                  payment_processor.upcoming_invoice
         
     | 
| 
       108 
112 
     | 
    
         
             
                end
         
     | 
| 
       109 
113 
     | 
    
         | 
| 
       110 
114 
     | 
    
         
             
                def stripe?
         
     | 
| 
      
 115 
     | 
    
         
            +
                  ActiveSupport::Deprecation.warn("This will be removed in the next release. Use `@billable.processor.stripe?` instead.")
         
     | 
| 
       111 
116 
     | 
    
         
             
                  processor == "stripe"
         
     | 
| 
       112 
117 
     | 
    
         
             
                end
         
     | 
| 
       113 
118 
     | 
    
         | 
| 
       114 
119 
     | 
    
         
             
                def braintree?
         
     | 
| 
      
 120 
     | 
    
         
            +
                  ActiveSupport::Deprecation.warn("This will be removed in the next release. Use `@billable.processor.braintree?` instead.")
         
     | 
| 
       115 
121 
     | 
    
         
             
                  processor == "braintree"
         
     | 
| 
       116 
122 
     | 
    
         
             
                end
         
     | 
| 
       117 
123 
     | 
    
         | 
| 
       118 
124 
     | 
    
         
             
                def paypal?
         
     | 
| 
       119 
     | 
    
         
            -
                   
     | 
| 
      
 125 
     | 
    
         
            +
                  card_type == "PayPal"
         
     | 
| 
       120 
126 
     | 
    
         
             
                end
         
     | 
| 
       121 
127 
     | 
    
         | 
| 
       122 
128 
     | 
    
         
             
                def paddle?
         
     | 
| 
      
 129 
     | 
    
         
            +
                  ActiveSupport::Deprecation.warn("This will be removed in the next release. Use `@billable.processor.paddle?` instead.")
         
     | 
| 
       123 
130 
     | 
    
         
             
                  processor == "paddle"
         
     | 
| 
       124 
131 
     | 
    
         
             
                end
         
     | 
| 
       125 
132 
     | 
    
         | 
| 
         @@ -127,14 +134,8 @@ module Pay 
     | 
|
| 
       127 
134 
     | 
    
         
             
                  subscription(name: name)&.has_incomplete_payment?
         
     | 
| 
       128 
135 
     | 
    
         
             
                end
         
     | 
| 
       129 
136 
     | 
    
         | 
| 
       130 
     | 
    
         
            -
                private
         
     | 
| 
       131 
     | 
    
         
            -
             
     | 
| 
       132 
     | 
    
         
            -
                def check_for_processor
         
     | 
| 
       133 
     | 
    
         
            -
                  raise StandardError, I18n.t("errors.no_processor", class_name: self.class.name) unless processor
         
     | 
| 
       134 
     | 
    
         
            -
                end
         
     | 
| 
       135 
     | 
    
         
            -
             
     | 
| 
       136 
137 
     | 
    
         
             
                # Used for creating a Pay::Subscription in the database
         
     | 
| 
       137 
     | 
    
         
            -
                def  
     | 
| 
      
 138 
     | 
    
         
            +
                def create_pay_subscription(subscription, processor, name, plan, options = {})
         
     | 
| 
       138 
139 
     | 
    
         
             
                  options[:quantity] ||= 1
         
     | 
| 
       139 
140 
     | 
    
         | 
| 
       140 
141 
     | 
    
         
             
                  options.merge!(
         
     | 
| 
         @@ -142,12 +143,14 @@ module Pay 
     | 
|
| 
       142 
143 
     | 
    
         
             
                    processor: processor,
         
     | 
| 
       143 
144 
     | 
    
         
             
                    processor_id: subscription.id,
         
     | 
| 
       144 
145 
     | 
    
         
             
                    processor_plan: plan,
         
     | 
| 
       145 
     | 
    
         
            -
                    trial_ends_at:  
     | 
| 
      
 146 
     | 
    
         
            +
                    trial_ends_at: payment_processor.trial_end_date(subscription),
         
     | 
| 
       146 
147 
     | 
    
         
             
                    ends_at: nil
         
     | 
| 
       147 
148 
     | 
    
         
             
                  )
         
     | 
| 
       148 
149 
     | 
    
         
             
                  subscriptions.create!(options)
         
     | 
| 
       149 
150 
     | 
    
         
             
                end
         
     | 
| 
       150 
151 
     | 
    
         | 
| 
      
 152 
     | 
    
         
            +
                private
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
       151 
154 
     | 
    
         
             
                def default_generic_trial?(name, plan)
         
     | 
| 
       152 
155 
     | 
    
         
             
                  # Generic trials don't have plans or custom names
         
     | 
| 
       153 
156 
     | 
    
         
             
                  plan.nil? && name == "default" && on_generic_trial?
         
     |