pay 2.6.11 → 3.0.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 +35 -693
- data/app/controllers/pay/webhooks/braintree_controller.rb +10 -3
- data/app/controllers/pay/webhooks/paddle_controller.rb +7 -8
- data/app/controllers/pay/webhooks/stripe_controller.rb +6 -3
- data/app/jobs/pay/{email_sync_job.rb → customer_sync_job.rb} +3 -4
- data/app/models/pay/application_record.rb +1 -5
- data/app/models/pay/charge.rb +32 -17
- data/app/models/pay/customer.rb +87 -0
- data/app/models/pay/merchant.rb +19 -0
- data/app/models/pay/payment_method.rb +41 -0
- data/app/models/pay/subscription.rb +34 -30
- data/app/models/pay/webhook.rb +36 -0
- data/app/views/layouts/pay/application.html.erb +2 -3
- data/app/views/pay/payments/show.html.erb +109 -81
- data/app/views/pay/user_mailer/receipt.html.erb +2 -2
- data/app/views/pay/user_mailer/refund.html.erb +2 -2
- data/config/locales/en.yml +1 -1
- data/db/migrate/1_create_pay_tables.rb +72 -0
- data/lib/generators/active_record/billable_generator.rb +44 -0
- data/lib/generators/active_record/merchant_generator.rb +44 -0
- data/lib/generators/active_record/templates/billable_migration.rb +17 -0
- data/lib/generators/active_record/templates/merchant_migration.rb +12 -0
- data/lib/generators/pay/{pay_generator.rb → billable_generator.rb} +2 -3
- data/lib/generators/pay/merchant_generator.rb +17 -0
- data/lib/generators/pay/orm_helpers.rb +10 -6
- data/lib/pay/adapter.rb +22 -0
- data/lib/pay/attributes.rb +74 -0
- data/lib/pay/billable/sync_customer.rb +30 -0
- data/lib/pay/braintree/billable.rb +130 -105
- data/lib/pay/braintree/payment_method.rb +33 -0
- data/lib/pay/braintree/subscription.rb +9 -12
- data/lib/pay/braintree/webhooks/subscription_canceled.rb +1 -1
- data/lib/pay/braintree/webhooks/subscription_charged_successfully.rb +4 -4
- data/lib/pay/braintree/webhooks/subscription_charged_unsuccessfully.rb +1 -1
- data/lib/pay/braintree/webhooks/subscription_expired.rb +1 -1
- data/lib/pay/braintree/webhooks/subscription_trial_ended.rb +2 -2
- data/lib/pay/braintree/webhooks/subscription_went_active.rb +1 -1
- data/lib/pay/braintree/webhooks/subscription_went_past_due.rb +1 -1
- data/lib/pay/braintree.rb +3 -2
- data/lib/pay/engine.rb +6 -1
- data/lib/pay/env.rb +8 -0
- data/lib/pay/fake_processor/billable.rb +45 -21
- data/lib/pay/fake_processor/payment_method.rb +21 -0
- data/lib/pay/fake_processor/subscription.rb +11 -8
- data/lib/pay/fake_processor.rb +2 -1
- data/lib/pay/merchant.rb +37 -0
- data/lib/pay/nano_id.rb +13 -0
- data/lib/pay/paddle/billable.rb +18 -48
- data/lib/pay/paddle/charge.rb +5 -5
- data/lib/pay/paddle/payment_method.rb +58 -0
- data/lib/pay/paddle/response.rb +0 -0
- data/lib/pay/paddle/subscription.rb +49 -8
- data/lib/pay/paddle/webhooks/subscription_cancelled.rb +6 -3
- data/lib/pay/paddle/webhooks/subscription_created.rb +1 -40
- data/lib/pay/paddle/webhooks/subscription_payment_refunded.rb +3 -3
- data/lib/pay/paddle/webhooks/subscription_payment_succeeded.rb +23 -23
- data/lib/pay/paddle/webhooks/subscription_updated.rb +2 -2
- data/lib/pay/paddle.rb +7 -3
- data/lib/pay/payment.rb +1 -1
- data/lib/pay/receipts.rb +35 -7
- data/lib/pay/stripe/billable.rb +82 -93
- data/lib/pay/stripe/charge.rb +65 -4
- data/lib/pay/stripe/merchant.rb +66 -0
- data/lib/pay/stripe/payment_method.rb +61 -0
- data/lib/pay/stripe/subscription.rb +91 -24
- data/lib/pay/stripe/webhooks/account_updated.rb +16 -0
- data/lib/pay/stripe/webhooks/charge_refunded.rb +2 -7
- data/lib/pay/stripe/webhooks/charge_succeeded.rb +2 -8
- data/lib/pay/stripe/webhooks/checkout_session_async_payment_succeeded.rb +15 -0
- data/lib/pay/stripe/webhooks/checkout_session_completed.rb +15 -0
- data/lib/pay/stripe/webhooks/customer_deleted.rb +7 -15
- data/lib/pay/stripe/webhooks/customer_updated.rb +10 -3
- data/lib/pay/stripe/webhooks/payment_action_required.rb +2 -2
- data/lib/pay/stripe/webhooks/payment_intent_succeeded.rb +6 -14
- data/lib/pay/stripe/webhooks/payment_method_attached.rb +15 -0
- data/lib/pay/stripe/webhooks/payment_method_detached.rb +12 -0
- data/lib/pay/stripe/webhooks/payment_method_updated.rb +10 -4
- data/lib/pay/stripe/webhooks/subscription_created.rb +1 -35
- data/lib/pay/stripe/webhooks/subscription_deleted.rb +2 -9
- data/lib/pay/stripe/webhooks/subscription_renewing.rb +14 -6
- data/lib/pay/stripe/webhooks/subscription_updated.rb +1 -28
- data/lib/pay/stripe.rb +17 -3
- data/lib/pay/version.rb +1 -1
- data/lib/pay/webhooks/delegator.rb +4 -0
- data/lib/pay/webhooks/process_job.rb +9 -0
- data/lib/pay/webhooks.rb +1 -0
- data/lib/pay.rb +8 -57
- metadata +34 -36
- data/db/migrate/20170205020145_create_pay_subscriptions.rb +0 -17
- data/db/migrate/20170727235816_create_pay_charges.rb +0 -18
- data/db/migrate/20190816015720_add_status_to_pay_subscriptions.rb +0 -14
- data/db/migrate/20200603134434_add_data_to_pay_models.rb +0 -22
- data/db/migrate/20210423235138_add_currency_to_pay_charges.rb +0 -5
- data/lib/generators/active_record/pay_generator.rb +0 -58
- data/lib/generators/active_record/templates/migration.rb +0 -9
- data/lib/pay/billable/sync_email.rb +0 -40
- data/lib/pay/billable.rb +0 -168
@@ -0,0 +1,66 @@
|
|
1
|
+
module Pay
|
2
|
+
module Stripe
|
3
|
+
class Merchant
|
4
|
+
attr_reader :pay_merchant
|
5
|
+
|
6
|
+
delegate :processor_id,
|
7
|
+
to: :pay_merchant
|
8
|
+
|
9
|
+
def initialize(pay_merchant)
|
10
|
+
@pay_merchant = pay_merchant
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_account(**options)
|
14
|
+
defaults = {
|
15
|
+
type: "express",
|
16
|
+
capabilities: {
|
17
|
+
card_payments: {requested: true},
|
18
|
+
transfers: {requested: true}
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
stripe_account = ::Stripe::Account.create(defaults.merge(options))
|
23
|
+
pay_merchant.update(processor_id: stripe_account.id)
|
24
|
+
stripe_account
|
25
|
+
rescue ::Stripe::StripeError => e
|
26
|
+
raise Pay::Stripe::Error, e
|
27
|
+
end
|
28
|
+
|
29
|
+
def account
|
30
|
+
::Stripe::Account.retrieve(processor_id)
|
31
|
+
rescue ::Stripe::StripeError => e
|
32
|
+
raise Pay::Stripe::Error, e
|
33
|
+
end
|
34
|
+
|
35
|
+
def account_link(refresh_url:, return_url:, type: "account_onboarding", **options)
|
36
|
+
::Stripe::AccountLink.create({
|
37
|
+
account: processor_id,
|
38
|
+
refresh_url: refresh_url,
|
39
|
+
return_url: return_url,
|
40
|
+
type: type
|
41
|
+
})
|
42
|
+
rescue ::Stripe::StripeError => e
|
43
|
+
raise Pay::Stripe::Error, e
|
44
|
+
end
|
45
|
+
|
46
|
+
# A single-use login link for Express accounts to access their Stripe dashboard
|
47
|
+
def login_link(**options)
|
48
|
+
::Stripe::Account.create_login_link(processor_id)
|
49
|
+
rescue ::Stripe::StripeError => e
|
50
|
+
raise Pay::Stripe::Error, e
|
51
|
+
end
|
52
|
+
|
53
|
+
# Transfer money from the platform to this connected account
|
54
|
+
# https://stripe.com/docs/connect/charges-transfers#transfer-availability
|
55
|
+
def transfer(amount:, currency: "usd", **options)
|
56
|
+
::Stripe::Transfer.create({
|
57
|
+
amount: amount,
|
58
|
+
currency: currency,
|
59
|
+
destination: processor_id
|
60
|
+
}.merge(options))
|
61
|
+
rescue ::Stripe::StripeError => e
|
62
|
+
raise Pay::Stripe::Error, e
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Pay
|
2
|
+
module Stripe
|
3
|
+
class PaymentMethod
|
4
|
+
attr_reader :pay_payment_method
|
5
|
+
|
6
|
+
delegate :customer, :processor_id, to: :pay_payment_method
|
7
|
+
|
8
|
+
def initialize(pay_payment_method)
|
9
|
+
@pay_payment_method = pay_payment_method
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.sync(id, object: nil, stripe_account: nil, try: 0, retries: 1)
|
13
|
+
object ||= ::Stripe::PaymentMethod.retrieve(id, {stripe_account: stripe_account}.compact)
|
14
|
+
|
15
|
+
pay_customer = Pay::Customer.find_by(processor: :stripe, processor_id: object.customer)
|
16
|
+
return unless pay_customer
|
17
|
+
|
18
|
+
default_payment_method_id = pay_customer.customer.invoice_settings.default_payment_method
|
19
|
+
default = (id == default_payment_method_id)
|
20
|
+
|
21
|
+
attributes = extract_attributes(object).merge(default: default)
|
22
|
+
|
23
|
+
pay_customer.payment_methods.update_all(default: false) if default
|
24
|
+
pay_payment_method = pay_customer.payment_methods.where(processor_id: object.id).first_or_initialize
|
25
|
+
pay_payment_method.update!(attributes)
|
26
|
+
pay_payment_method
|
27
|
+
end
|
28
|
+
|
29
|
+
# Extracts payment method details from a Stripe::PaymentMethod object
|
30
|
+
def self.extract_attributes(payment_method)
|
31
|
+
details = payment_method.send(payment_method.type)
|
32
|
+
|
33
|
+
{
|
34
|
+
payment_method_type: payment_method.type,
|
35
|
+
brand: details.try(:brand)&.capitalize,
|
36
|
+
last4: details.try(:last4).to_s,
|
37
|
+
exp_month: details.try(:exp_month).to_s,
|
38
|
+
exp_year: details.try(:exp_year).to_s,
|
39
|
+
bank: details.try(:bank_name) || details.try(:bank) # eps, fpx, ideal, p24, acss_debit, etc
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
# Sets payment method as default
|
44
|
+
def make_default!
|
45
|
+
::Stripe::Customer.update(customer.processor_id, {invoice_settings: {default_payment_method: processor_id}}, stripe_options)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Remove payment method
|
49
|
+
def detach
|
50
|
+
::Stripe::PaymentMethod.detach(processor_id, stripe_options)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# Options for Stripe requests
|
56
|
+
def stripe_options
|
57
|
+
{stripe_account: customer.stripe_account}.compact
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -8,7 +8,6 @@ module Pay
|
|
8
8
|
:ends_at,
|
9
9
|
:name,
|
10
10
|
:on_trial?,
|
11
|
-
:owner,
|
12
11
|
:processor_id,
|
13
12
|
:processor_plan,
|
14
13
|
:processor_subscription,
|
@@ -16,43 +15,94 @@ module Pay
|
|
16
15
|
:prorate?,
|
17
16
|
:quantity,
|
18
17
|
:quantity?,
|
18
|
+
:stripe_account,
|
19
19
|
:trial_ends_at,
|
20
20
|
to: :pay_subscription
|
21
21
|
|
22
|
+
def self.sync(subscription_id, object: nil, name: Pay.default_product_name, stripe_account: nil, try: 0, retries: 1)
|
23
|
+
# Skip loading the latest subscription details from the API if we already have it
|
24
|
+
object ||= ::Stripe::Subscription.retrieve({id: subscription_id, expand: ["pending_setup_intent", "latest_invoice.payment_intent", "latest_invoice.charge.invoice"]}, {stripe_account: stripe_account}.compact)
|
25
|
+
|
26
|
+
pay_customer = Pay::Customer.find_by(processor: :stripe, processor_id: object.customer)
|
27
|
+
return unless pay_customer
|
28
|
+
|
29
|
+
attributes = {
|
30
|
+
application_fee_percent: object.application_fee_percent,
|
31
|
+
processor_plan: object.plan.id,
|
32
|
+
quantity: object.quantity,
|
33
|
+
status: object.status,
|
34
|
+
stripe_account: pay_customer.stripe_account,
|
35
|
+
trial_ends_at: (object.trial_end ? Time.at(object.trial_end) : nil),
|
36
|
+
metadata: object.metadata
|
37
|
+
}
|
38
|
+
|
39
|
+
attributes[:ends_at] = if object.ended_at
|
40
|
+
# Fully cancelled subscription
|
41
|
+
Time.at(object.ended_at)
|
42
|
+
elsif object.cancel_at
|
43
|
+
# subscription cancelling in the future
|
44
|
+
Time.at(object.cancel_at)
|
45
|
+
elsif object.cancel_at_period_end
|
46
|
+
# Subscriptions cancelling in the future
|
47
|
+
Time.at(object.current_period_end)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Update or create the subscription
|
51
|
+
pay_subscription = pay_customer.subscriptions.find_by(processor_id: object.id)
|
52
|
+
if pay_subscription
|
53
|
+
pay_subscription.with_lock { pay_subscription.update!(attributes) }
|
54
|
+
else
|
55
|
+
pay_subscription = pay_customer.subscriptions.create!(attributes.merge(name: name, processor_id: object.id))
|
56
|
+
end
|
57
|
+
|
58
|
+
# Sync the latest charge if we already have it loaded (like during subscrbe), otherwise, let webhooks take care of creating it
|
59
|
+
if (charge = object.try(:latest_invoice).try(:charge)) && charge.try(:status) == "succeeded"
|
60
|
+
Pay::Stripe::Charge.sync(charge.id, object: charge)
|
61
|
+
end
|
62
|
+
|
63
|
+
pay_subscription
|
64
|
+
rescue ActiveRecord::RecordInvalid
|
65
|
+
try += 1
|
66
|
+
if try <= retries
|
67
|
+
sleep 0.1
|
68
|
+
retry
|
69
|
+
else
|
70
|
+
raise
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
22
74
|
def initialize(pay_subscription)
|
23
75
|
@pay_subscription = pay_subscription
|
24
76
|
end
|
25
77
|
|
26
78
|
def subscription(**options)
|
27
|
-
|
79
|
+
options[:id] = processor_id
|
80
|
+
options[:expand] ||= ["pending_setup_intent", "latest_invoice.payment_intent", "latest_invoice.charge.invoice"]
|
81
|
+
::Stripe::Subscription.retrieve(options, {stripe_account: stripe_account}.compact)
|
28
82
|
end
|
29
83
|
|
30
84
|
def cancel
|
31
|
-
|
32
|
-
|
33
|
-
subscription.save
|
34
|
-
|
35
|
-
new_ends_at = on_trial? ? trial_ends_at : Time.at(subscription.current_period_end)
|
36
|
-
pay_subscription.update(ends_at: new_ends_at)
|
85
|
+
stripe_sub = ::Stripe::Subscription.update(processor_id, {cancel_at_period_end: true}, stripe_options)
|
86
|
+
pay_subscription.update(ends_at: (on_trial? ? trial_ends_at : Time.at(stripe_sub.current_period_end)))
|
37
87
|
rescue ::Stripe::StripeError => e
|
38
88
|
raise Pay::Stripe::Error, e
|
39
89
|
end
|
40
90
|
|
41
91
|
def cancel_now!
|
42
|
-
|
43
|
-
pay_subscription.update(ends_at: Time.
|
92
|
+
::Stripe::Subscription.delete(processor_id, {}, stripe_options)
|
93
|
+
pay_subscription.update(ends_at: Time.current, status: :canceled)
|
44
94
|
rescue ::Stripe::StripeError => e
|
45
95
|
raise Pay::Stripe::Error, e
|
46
96
|
end
|
47
97
|
|
48
98
|
def change_quantity(quantity)
|
49
|
-
::Stripe::Subscription.update(processor_id, quantity: quantity)
|
99
|
+
::Stripe::Subscription.update(processor_id, {quantity: quantity}, stripe_options)
|
50
100
|
rescue ::Stripe::StripeError => e
|
51
101
|
raise Pay::Stripe::Error, e
|
52
102
|
end
|
53
103
|
|
54
104
|
def on_grace_period?
|
55
|
-
canceled? && Time.
|
105
|
+
canceled? && Time.current < ends_at
|
56
106
|
end
|
57
107
|
|
58
108
|
def paused?
|
@@ -68,26 +118,43 @@ module Pay
|
|
68
118
|
raise StandardError, "You can only resume subscriptions within their grace period."
|
69
119
|
end
|
70
120
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
121
|
+
::Stripe::Subscription.update(
|
122
|
+
processor_id,
|
123
|
+
{
|
124
|
+
plan: processor_plan,
|
125
|
+
trial_end: (on_trial? ? trial_ends_at.to_i : "now"),
|
126
|
+
cancel_at_period_end: false
|
127
|
+
},
|
128
|
+
stripe_options
|
129
|
+
)
|
76
130
|
rescue ::Stripe::StripeError => e
|
77
131
|
raise Pay::Stripe::Error, e
|
78
132
|
end
|
79
133
|
|
80
134
|
def swap(plan)
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
135
|
+
raise ArgumentError, "plan must be a string" unless plan.is_a?(String)
|
136
|
+
|
137
|
+
::Stripe::Subscription.update(
|
138
|
+
processor_id,
|
139
|
+
{
|
140
|
+
cancel_at_period_end: false,
|
141
|
+
plan: plan,
|
142
|
+
proration_behavior: (prorate ? "create_prorations" : "none"),
|
143
|
+
trial_end: (on_trial? ? trial_ends_at.to_i : "now"),
|
144
|
+
quantity: quantity
|
145
|
+
},
|
146
|
+
stripe_options
|
147
|
+
)
|
88
148
|
rescue ::Stripe::StripeError => e
|
89
149
|
raise Pay::Stripe::Error, e
|
90
150
|
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
# Options for Stripe requests
|
155
|
+
def stripe_options
|
156
|
+
{stripe_account: stripe_account}.compact
|
157
|
+
end
|
91
158
|
end
|
92
159
|
end
|
93
160
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Pay
|
2
|
+
module Stripe
|
3
|
+
module Webhooks
|
4
|
+
class AccountUpdated
|
5
|
+
def call(event)
|
6
|
+
object = event.data.object
|
7
|
+
|
8
|
+
merchant = Pay::Merchant.find_by(processor: :stripe, processor_id: object.id)
|
9
|
+
return unless merchant
|
10
|
+
|
11
|
+
merchant.update(onboarding_complete: object.charges_enabled)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -3,13 +3,8 @@ module Pay
|
|
3
3
|
module Webhooks
|
4
4
|
class ChargeRefunded
|
5
5
|
def call(event)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
return unless charge.present?
|
10
|
-
|
11
|
-
charge.update(amount_refunded: object.amount_refunded)
|
12
|
-
notify_user(charge.owner, charge)
|
6
|
+
pay_charge = Pay::Stripe::Charge.sync(event.data.object.id, stripe_account: event.try(:account))
|
7
|
+
notify_user(pay_charge.owner, pay_charge) if pay_charge
|
13
8
|
end
|
14
9
|
|
15
10
|
def notify_user(billable, charge)
|
@@ -3,14 +3,8 @@ module Pay
|
|
3
3
|
module Webhooks
|
4
4
|
class ChargeSucceeded
|
5
5
|
def call(event)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
return unless billable.present?
|
10
|
-
return if billable.charges.where(processor_id: object.id).any?
|
11
|
-
|
12
|
-
charge = Pay::Stripe::Billable.new(billable).save_pay_charge(object)
|
13
|
-
notify_user(billable, charge)
|
6
|
+
pay_charge = Pay::Stripe::Charge.sync(event.data.object.id, stripe_account: event.try(:account))
|
7
|
+
notify_user(pay_charge.customer.owner, pay_charge) if pay_charge
|
14
8
|
end
|
15
9
|
|
16
10
|
def notify_user(billable, charge)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Pay
|
2
|
+
module Stripe
|
3
|
+
module Webhooks
|
4
|
+
class CheckoutSessionAsyncPaymentSucceeded
|
5
|
+
def call(event)
|
6
|
+
# TODO: Also handle payment intents
|
7
|
+
|
8
|
+
if event.data.object.subscription
|
9
|
+
Pay::Stripe::Subscription.sync(event.data.object.subscription, stripe_account: event.try(:account))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Pay
|
2
|
+
module Stripe
|
3
|
+
module Webhooks
|
4
|
+
class CheckoutSessionCompleted
|
5
|
+
def call(event)
|
6
|
+
# TODO: Also handle payment intents
|
7
|
+
|
8
|
+
if event.data.object.subscription
|
9
|
+
Pay::Stripe::Subscription.sync(event.data.object.subscription, stripe_account: event.try(:account))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -4,24 +4,16 @@ module Pay
|
|
4
4
|
class CustomerDeleted
|
5
5
|
def call(event)
|
6
6
|
object = event.data.object
|
7
|
-
|
7
|
+
pay_customer = Pay::Customer.find_by(processor: :stripe, processor_id: object.id)
|
8
8
|
|
9
|
-
#
|
10
|
-
|
9
|
+
# Mark all subscriptions as canceled
|
10
|
+
pay_customer.subscriptions.active.update_all(ends_at: Time.current, status: "canceled")
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
trial_ends_at: nil,
|
15
|
-
card_type: nil,
|
16
|
-
card_last4: nil,
|
17
|
-
card_exp_month: nil,
|
18
|
-
card_exp_year: nil
|
19
|
-
)
|
12
|
+
# Remove all payment methods
|
13
|
+
pay_customer.payment_methods.destroy_all
|
20
14
|
|
21
|
-
|
22
|
-
|
23
|
-
ends_at: Time.zone.now
|
24
|
-
)
|
15
|
+
# Mark customer as deleted
|
16
|
+
pay_customer&.update!(default: false, deleted_at: Time.current)
|
25
17
|
end
|
26
18
|
end
|
27
19
|
end
|
@@ -4,12 +4,19 @@ module Pay
|
|
4
4
|
class CustomerUpdated
|
5
5
|
def call(event)
|
6
6
|
object = event.data.object
|
7
|
-
|
7
|
+
pay_customer = Pay::Customer.find_by(processor: :stripe, processor_id: object.id)
|
8
8
|
|
9
9
|
# Couldn't find user, we can skip
|
10
|
-
return unless
|
10
|
+
return unless pay_customer.present?
|
11
11
|
|
12
|
-
|
12
|
+
# Sync default card
|
13
|
+
if (payment_method_id = pay_customer.customer.invoice_settings.default_payment_method)
|
14
|
+
Pay::Stripe::PaymentMethod.sync(payment_method_id, {stripe_account: event.account}.compact)
|
15
|
+
|
16
|
+
else
|
17
|
+
# No default payment method set
|
18
|
+
pay_customer.payment_methods.update_all(default: false)
|
19
|
+
end
|
13
20
|
end
|
14
21
|
end
|
15
22
|
end
|
@@ -8,9 +8,9 @@ module Pay
|
|
8
8
|
|
9
9
|
object = event.data.object
|
10
10
|
|
11
|
-
subscription = Pay.
|
11
|
+
subscription = Pay::Subscription.find_by_processor_and_id(:stripe, object.subscription)
|
12
12
|
return if subscription.nil?
|
13
|
-
billable = subscription.owner
|
13
|
+
billable = subscription.customer.owner
|
14
14
|
|
15
15
|
notify_user(billable, event.data.object.payment_intent, subscription)
|
16
16
|
end
|