pay 2.4.0 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of pay might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +2 -3
- 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 +32 -41
- data/app/views/pay/stripe/_checkout_button.html.erb +21 -0
- data/config/routes.rb +1 -1
- data/db/migrate/20200603134434_add_data_to_pay_models.rb +6 -1
- data/lib/pay.rb +13 -12
- data/lib/pay/billable.rb +33 -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 +43 -20
- 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 +32 -23
- 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 +65 -15
- data/lib/pay/stripe/billable.rb +127 -69
- data/lib/pay/stripe/charge.rb +9 -15
- data/lib/pay/stripe/error.rb +9 -0
- data/lib/pay/stripe/subscription.rb +34 -14
- data/lib/pay/stripe/webhooks/charge_succeeded.rb +1 -20
- 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: f67175eed41645fc10868070414e33e205dc6970be39038715fbde5c18496932
|
4
|
+
data.tar.gz: bd725f34c55707aaf30c1e46ecc111a9c00b69f8275d87c7d94f8640b24d84c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47b06c20aef2c34454f40bb734c4d1bdd648e9f9f4380c7b5c8d246357036f46b92511bc36ebf7b3b1ec00234700848ad3b12b1eb76c2e274a420e5bc650608b
|
7
|
+
data.tar.gz: 033e3b12a1a1a6f9b7b7bb2e447cb4a1acfb0cf3d35da7d5f00e187f6301d5cc59a9a3bec0d1577f8a6764286d93dbfefe16553939fc8c83213ee1c6668b09b9
|
data/README.md
CHANGED
@@ -9,8 +9,8 @@ Pay is a payments engine for Ruby on Rails 4.2 and higher.
|
|
9
9
|
**Current Payment Providers**
|
10
10
|
|
11
11
|
- Stripe ([supports SCA](https://stripe.com/docs/strong-customer-authentication) using API version `2020-08-27`)
|
12
|
-
- Braintree
|
13
|
-
- Paddle
|
12
|
+
- Braintree (supports PayPal)
|
13
|
+
- Paddle (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'
|
@@ -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,8 +27,37 @@ 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
|
|
37
|
+
# Helpers for payment processors
|
38
|
+
%w[braintree stripe paddle].each do |processor_name|
|
39
|
+
define_method "#{processor_name}?" do
|
40
|
+
processor == processor_name
|
41
|
+
end
|
42
|
+
|
43
|
+
scope processor_name, -> { where(processor: processor_name) }
|
44
|
+
end
|
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
|
+
|
32
61
|
def no_prorate
|
33
62
|
self.prorate = false
|
34
63
|
end
|
@@ -49,11 +78,6 @@ module Pay
|
|
49
78
|
canceled?
|
50
79
|
end
|
51
80
|
|
52
|
-
def on_grace_period?
|
53
|
-
return unless processor?
|
54
|
-
send("#{processor}_on_grace_period?")
|
55
|
-
end
|
56
|
-
|
57
81
|
def active?
|
58
82
|
["trialing", "active"].include?(status) && (ends_at.nil? || on_grace_period? || on_trial?)
|
59
83
|
end
|
@@ -70,47 +94,14 @@ module Pay
|
|
70
94
|
past_due? || incomplete?
|
71
95
|
end
|
72
96
|
|
73
|
-
def paused?
|
74
|
-
return unless paddle?
|
75
|
-
send("#{processor}_paused?")
|
76
|
-
end
|
77
|
-
|
78
|
-
def pause
|
79
|
-
return unless paddle?
|
80
|
-
send("#{processor}_pause")
|
81
|
-
end
|
82
|
-
|
83
|
-
def cancel
|
84
|
-
send("#{processor}_cancel")
|
85
|
-
end
|
86
|
-
|
87
|
-
def cancel_now!
|
88
|
-
send("#{processor}_cancel_now!")
|
89
|
-
end
|
90
|
-
|
91
97
|
def resume
|
92
|
-
|
93
|
-
unless paddle?
|
94
|
-
raise StandardError,
|
95
|
-
"You can only resume subscriptions within their grace period."
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
unless paused?
|
100
|
-
if paddle?
|
101
|
-
raise StandardError,
|
102
|
-
"You can only resume paused subscriptions."
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
send("#{processor}_resume")
|
107
|
-
|
98
|
+
payment_processor.resume
|
108
99
|
update(ends_at: nil, status: "active")
|
109
100
|
self
|
110
101
|
end
|
111
102
|
|
112
103
|
def swap(plan)
|
113
|
-
|
104
|
+
payment_processor.swap(plan)
|
114
105
|
update(processor_plan: plan, ends_at: nil)
|
115
106
|
end
|
116
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
|
@@ -5,7 +5,12 @@ class AddDataToPayModels < ActiveRecord::Migration[4.2]
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def data_column_type
|
8
|
-
|
8
|
+
default_hash = ActiveRecord::Base.configurations.default_hash
|
9
|
+
|
10
|
+
# Rails 6.1 uses a symbol key instead of a string
|
11
|
+
adapter = default_hash.dig(:adapter) || default_hash.dig("adapter")
|
12
|
+
|
13
|
+
case adapter
|
9
14
|
when "mysql2"
|
10
15
|
:json
|
11
16
|
when "postgresql"
|
data/lib/pay.rb
CHANGED
@@ -1,10 +1,20 @@
|
|
1
|
+
require "pay/version"
|
1
2
|
require "pay/engine"
|
2
|
-
require "pay/billable"
|
3
|
-
require "pay/receipts"
|
4
|
-
require "pay/payment"
|
5
3
|
require "pay/errors"
|
6
4
|
|
7
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
|
+
|
8
18
|
# Define who owns the subscription
|
9
19
|
mattr_accessor :billable_class
|
10
20
|
mattr_accessor :billable_table
|
@@ -36,15 +46,6 @@ module Pay
|
|
36
46
|
mattr_accessor :send_emails
|
37
47
|
@@send_emails = true
|
38
48
|
|
39
|
-
mattr_accessor :email_receipt_subject
|
40
|
-
@@email_receipt_subject = "Payment receipt"
|
41
|
-
mattr_accessor :email_refund_subject
|
42
|
-
@@email_refund_subject = "Payment refunded"
|
43
|
-
mattr_accessor :email_renewing_subject
|
44
|
-
@@email_renewing_subject = "Your upcoming subscription renewal"
|
45
|
-
mattr_accessor :email_action_required_subject
|
46
|
-
@@email_action_required_subject = "Confirm your payment"
|
47
|
-
|
48
49
|
mattr_accessor :automount_routes
|
49
50
|
@@automount_routes = true
|
50
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,11 +102,13 @@ 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?
|
@@ -116,7 +120,7 @@ module Pay
|
|
116
120
|
end
|
117
121
|
|
118
122
|
def paypal?
|
119
|
-
|
123
|
+
card_type == "PayPal"
|
120
124
|
end
|
121
125
|
|
122
126
|
def paddle?
|
@@ -127,14 +131,8 @@ module Pay
|
|
127
131
|
subscription(name: name)&.has_incomplete_payment?
|
128
132
|
end
|
129
133
|
|
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
134
|
# Used for creating a Pay::Subscription in the database
|
137
|
-
def
|
135
|
+
def create_pay_subscription(subscription, processor, name, plan, options = {})
|
138
136
|
options[:quantity] ||= 1
|
139
137
|
|
140
138
|
options.merge!(
|
@@ -142,12 +140,14 @@ module Pay
|
|
142
140
|
processor: processor,
|
143
141
|
processor_id: subscription.id,
|
144
142
|
processor_plan: plan,
|
145
|
-
trial_ends_at:
|
143
|
+
trial_ends_at: payment_processor.trial_end_date(subscription),
|
146
144
|
ends_at: nil
|
147
145
|
)
|
148
146
|
subscriptions.create!(options)
|
149
147
|
end
|
150
148
|
|
149
|
+
private
|
150
|
+
|
151
151
|
def default_generic_trial?(name, plan)
|
152
152
|
# Generic trials don't have plans or custom names
|
153
153
|
plan.nil? && name == "default" && on_generic_trial?
|