pay 2.7.2 → 3.0.4
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 +34 -731
- 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 +0 -5
- data/app/models/pay/charge.rb +54 -17
- data/app/models/pay/customer.rb +97 -0
- data/app/models/pay/merchant.rb +19 -0
- data/app/models/pay/payment_method.rb +41 -0
- data/app/models/pay/subscription.rb +42 -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 +108 -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/pay/attributes.rb +74 -0
- data/lib/pay/billable/sync_customer.rb +30 -0
- data/lib/pay/braintree/billable.rb +133 -110
- data/lib/pay/braintree/payment_method.rb +42 -0
- data/lib/pay/braintree/subscription.rb +7 -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/fake_processor/billable.rb +45 -21
- data/lib/pay/fake_processor/payment_method.rb +21 -0
- data/lib/pay/fake_processor/subscription.rb +11 -10
- data/lib/pay/fake_processor.rb +2 -1
- 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 +60 -0
- data/lib/pay/paddle/response.rb +0 -0
- data/lib/pay/paddle/subscription.rb +47 -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 +26 -28
- 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 +50 -64
- data/lib/pay/stripe/charge.rb +18 -15
- data/lib/pay/stripe/merchant.rb +10 -10
- data/lib/pay/stripe/payment_method.rb +61 -0
- data/lib/pay/stripe/subscription.rb +22 -17
- data/lib/pay/stripe/webhooks/account_updated.rb +2 -3
- data/lib/pay/stripe/webhooks/charge_refunded.rb +1 -1
- data/lib/pay/stripe/webhooks/charge_succeeded.rb +2 -2
- data/lib/pay/stripe/webhooks/checkout_session_async_payment_succeeded.rb +3 -1
- data/lib/pay/stripe/webhooks/checkout_session_completed.rb +3 -1
- 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 -8
- data/lib/pay/stripe/webhooks/payment_method_attached.rb +2 -4
- data/lib/pay/stripe/webhooks/payment_method_detached.rb +1 -6
- data/lib/pay/stripe/webhooks/payment_method_updated.rb +10 -4
- data/lib/pay/stripe/webhooks/subscription_created.rb +1 -1
- data/lib/pay/stripe/webhooks/subscription_deleted.rb +2 -1
- data/lib/pay/stripe/webhooks/subscription_renewing.rb +12 -2
- data/lib/pay/stripe.rb +6 -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 +7 -78
- data/lib/tasks/pay.rake +31 -0
- metadata +21 -37
- 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 -6
- data/db/migrate/20210309004259_add_data_to_pay_billable.rb +0 -10
- data/db/migrate/20210406215234_add_currency_to_pay_charges.rb +0 -5
- data/db/migrate/20210406215506_add_application_fee_to_pay_models.rb +0 -7
- data/db/migrate/20210714175351_add_uniqueness_to_pay_models.rb +0 -6
- data/lib/pay/billable/sync_email.rb +0 -40
- data/lib/pay/billable.rb +0 -172
- data/lib/pay/stripe/webhooks/payment_method_automatically_updated.rb +0 -17
data/lib/pay/stripe/charge.rb
CHANGED
@@ -3,43 +3,46 @@ module Pay
|
|
3
3
|
class Charge
|
4
4
|
attr_reader :pay_charge
|
5
5
|
|
6
|
-
delegate :processor_id, :
|
6
|
+
delegate :processor_id, :stripe_account, to: :pay_charge
|
7
7
|
|
8
|
-
def self.sync(charge_id, object: nil, try: 0, retries: 1)
|
8
|
+
def self.sync(charge_id, object: nil, stripe_account: nil, try: 0, retries: 1)
|
9
9
|
# Skip loading the latest charge details from the API if we already have it
|
10
|
-
object ||= ::Stripe::Charge.retrieve(
|
10
|
+
object ||= ::Stripe::Charge.retrieve(charge_id, {stripe_account: stripe_account}.compact)
|
11
11
|
|
12
|
-
|
13
|
-
return unless
|
12
|
+
pay_customer = Pay::Customer.find_by(processor: :stripe, processor_id: object.customer)
|
13
|
+
return unless pay_customer
|
14
14
|
|
15
|
+
payment_method = object.payment_method_details.send(object.payment_method_details.type)
|
15
16
|
attrs = {
|
16
17
|
amount: object.amount,
|
17
18
|
amount_refunded: object.amount_refunded,
|
18
19
|
application_fee_amount: object.application_fee_amount,
|
19
|
-
card_exp_month: object.payment_method_details.card.exp_month,
|
20
|
-
card_exp_year: object.payment_method_details.card.exp_year,
|
21
|
-
card_last4: object.payment_method_details.card.last4,
|
22
|
-
card_type: object.payment_method_details.card.brand,
|
23
20
|
created_at: Time.at(object.created),
|
24
21
|
currency: object.currency,
|
25
|
-
stripe_account:
|
22
|
+
stripe_account: pay_customer.stripe_account,
|
23
|
+
metadata: object.metadata,
|
24
|
+
payment_method_type: object.payment_method_details.type,
|
25
|
+
brand: payment_method.try(:brand)&.capitalize,
|
26
|
+
last4: payment_method.try(:last4).to_s,
|
27
|
+
exp_month: payment_method.try(:exp_month).to_s,
|
28
|
+
exp_year: payment_method.try(:exp_year).to_s,
|
29
|
+
bank: payment_method.try(:bank_name) || payment_method.try(:bank) # eps, fpx, ideal, p24, acss_debit, etc
|
26
30
|
}
|
27
31
|
|
28
32
|
# Associate charge with subscription if we can
|
29
33
|
if object.invoice
|
30
|
-
invoice = (object.invoice.is_a?(::Stripe::Invoice) ? object.invoice : ::Stripe::Invoice.retrieve(object.invoice))
|
31
|
-
attrs[:subscription] =
|
34
|
+
invoice = (object.invoice.is_a?(::Stripe::Invoice) ? object.invoice : ::Stripe::Invoice.retrieve(object.invoice, {stripe_account: stripe_account}.compact))
|
35
|
+
attrs[:subscription] = pay_customer.subscriptions.find_by(processor_id: invoice.subscription)
|
32
36
|
end
|
33
37
|
|
34
38
|
# Update or create the charge
|
35
|
-
|
36
|
-
if (pay_charge = owner.charges.find_by(processor_details))
|
39
|
+
if (pay_charge = pay_customer.charges.find_by(processor_id: object.id))
|
37
40
|
pay_charge.with_lock do
|
38
41
|
pay_charge.update!(attrs)
|
39
42
|
end
|
40
43
|
pay_charge
|
41
44
|
else
|
42
|
-
|
45
|
+
pay_customer.charges.create!(attrs.merge(processor_id: object.id))
|
43
46
|
end
|
44
47
|
rescue ActiveRecord::RecordInvalid
|
45
48
|
try += 1
|
data/lib/pay/stripe/merchant.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
module Pay
|
2
2
|
module Stripe
|
3
3
|
class Merchant
|
4
|
-
attr_reader :
|
4
|
+
attr_reader :pay_merchant
|
5
5
|
|
6
|
-
delegate :
|
7
|
-
to: :
|
6
|
+
delegate :processor_id,
|
7
|
+
to: :pay_merchant
|
8
8
|
|
9
|
-
def initialize(
|
10
|
-
@
|
9
|
+
def initialize(pay_merchant)
|
10
|
+
@pay_merchant = pay_merchant
|
11
11
|
end
|
12
12
|
|
13
13
|
def create_account(**options)
|
@@ -20,21 +20,21 @@ module Pay
|
|
20
20
|
}
|
21
21
|
|
22
22
|
stripe_account = ::Stripe::Account.create(defaults.merge(options))
|
23
|
-
|
23
|
+
pay_merchant.update(processor_id: stripe_account.id)
|
24
24
|
stripe_account
|
25
25
|
rescue ::Stripe::StripeError => e
|
26
26
|
raise Pay::Stripe::Error, e
|
27
27
|
end
|
28
28
|
|
29
29
|
def account
|
30
|
-
::Stripe::Account.retrieve(
|
30
|
+
::Stripe::Account.retrieve(processor_id)
|
31
31
|
rescue ::Stripe::StripeError => e
|
32
32
|
raise Pay::Stripe::Error, e
|
33
33
|
end
|
34
34
|
|
35
35
|
def account_link(refresh_url:, return_url:, type: "account_onboarding", **options)
|
36
36
|
::Stripe::AccountLink.create({
|
37
|
-
account:
|
37
|
+
account: processor_id,
|
38
38
|
refresh_url: refresh_url,
|
39
39
|
return_url: return_url,
|
40
40
|
type: type
|
@@ -45,7 +45,7 @@ module Pay
|
|
45
45
|
|
46
46
|
# A single-use login link for Express accounts to access their Stripe dashboard
|
47
47
|
def login_link(**options)
|
48
|
-
::Stripe::Account.create_login_link(
|
48
|
+
::Stripe::Account.create_login_link(processor_id)
|
49
49
|
rescue ::Stripe::StripeError => e
|
50
50
|
raise Pay::Stripe::Error, e
|
51
51
|
end
|
@@ -56,7 +56,7 @@ module Pay
|
|
56
56
|
::Stripe::Transfer.create({
|
57
57
|
amount: amount,
|
58
58
|
currency: currency,
|
59
|
-
destination:
|
59
|
+
destination: processor_id
|
60
60
|
}.merge(options))
|
61
61
|
rescue ::Stripe::StripeError => e
|
62
62
|
raise Pay::Stripe::Error, e
|
@@ -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,
|
@@ -20,21 +19,21 @@ module Pay
|
|
20
19
|
:trial_ends_at,
|
21
20
|
to: :pay_subscription
|
22
21
|
|
23
|
-
def self.sync(subscription_id, object: nil, name: Pay.default_product_name, try: 0, retries: 1)
|
22
|
+
def self.sync(subscription_id, object: nil, name: Pay.default_product_name, stripe_account: nil, try: 0, retries: 1)
|
24
23
|
# Skip loading the latest subscription details from the API if we already have it
|
25
|
-
object ||= ::Stripe::Subscription.retrieve({id: subscription_id, expand: ["pending_setup_intent", "latest_invoice.payment_intent"]})
|
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)
|
26
25
|
|
27
|
-
|
28
|
-
return unless
|
26
|
+
pay_customer = Pay::Customer.find_by(processor: :stripe, processor_id: object.customer)
|
27
|
+
return unless pay_customer
|
29
28
|
|
30
29
|
attributes = {
|
31
30
|
application_fee_percent: object.application_fee_percent,
|
32
31
|
processor_plan: object.plan.id,
|
33
32
|
quantity: object.quantity,
|
34
|
-
name: name,
|
35
33
|
status: object.status,
|
36
|
-
stripe_account:
|
37
|
-
trial_ends_at: (object.trial_end ? Time.at(object.trial_end) : nil)
|
34
|
+
stripe_account: pay_customer.stripe_account,
|
35
|
+
trial_ends_at: (object.trial_end ? Time.at(object.trial_end) : nil),
|
36
|
+
metadata: object.metadata
|
38
37
|
}
|
39
38
|
|
40
39
|
attributes[:ends_at] = if object.ended_at
|
@@ -49,15 +48,19 @@ module Pay
|
|
49
48
|
end
|
50
49
|
|
51
50
|
# Update or create the subscription
|
52
|
-
|
53
|
-
if
|
54
|
-
pay_subscription.with_lock
|
55
|
-
pay_subscription.update!(attributes)
|
56
|
-
end
|
57
|
-
pay_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) }
|
58
54
|
else
|
59
|
-
|
55
|
+
pay_subscription = pay_customer.subscriptions.create!(attributes.merge(name: name, processor_id: object.id))
|
60
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
|
61
64
|
rescue ActiveRecord::RecordInvalid
|
62
65
|
try += 1
|
63
66
|
if try <= retries
|
@@ -73,7 +76,9 @@ module Pay
|
|
73
76
|
end
|
74
77
|
|
75
78
|
def subscription(**options)
|
76
|
-
|
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)
|
77
82
|
end
|
78
83
|
|
79
84
|
def cancel
|
@@ -97,7 +102,7 @@ module Pay
|
|
97
102
|
end
|
98
103
|
|
99
104
|
def on_grace_period?
|
100
|
-
canceled? && Time.
|
105
|
+
canceled? && Time.current < ends_at
|
101
106
|
end
|
102
107
|
|
103
108
|
def paused?
|
@@ -5,9 +5,8 @@ module Pay
|
|
5
5
|
def call(event)
|
6
6
|
object = event.data.object
|
7
7
|
|
8
|
-
merchant = Pay.
|
9
|
-
|
10
|
-
return unless merchant.present?
|
8
|
+
merchant = Pay::Merchant.find_by(processor: :stripe, processor_id: object.id)
|
9
|
+
return unless merchant
|
11
10
|
|
12
11
|
merchant.update(onboarding_complete: object.charges_enabled)
|
13
12
|
end
|
@@ -3,7 +3,7 @@ module Pay
|
|
3
3
|
module Webhooks
|
4
4
|
class ChargeRefunded
|
5
5
|
def call(event)
|
6
|
-
pay_charge = Pay::Stripe::Charge.sync(event.data.object.id)
|
6
|
+
pay_charge = Pay::Stripe::Charge.sync(event.data.object.id, stripe_account: event.try(:account))
|
7
7
|
notify_user(pay_charge.owner, pay_charge) if pay_charge
|
8
8
|
end
|
9
9
|
|
@@ -3,8 +3,8 @@ module Pay
|
|
3
3
|
module Webhooks
|
4
4
|
class ChargeSucceeded
|
5
5
|
def call(event)
|
6
|
-
pay_charge = Pay::Stripe::Charge.sync(event.data.object.id)
|
7
|
-
notify_user(pay_charge.owner, pay_charge) if pay_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
|
8
8
|
end
|
9
9
|
|
10
10
|
def notify_user(billable, charge)
|
@@ -3,8 +3,10 @@ module Pay
|
|
3
3
|
module Webhooks
|
4
4
|
class CheckoutSessionAsyncPaymentSucceeded
|
5
5
|
def call(event)
|
6
|
+
# TODO: Also handle payment intents
|
7
|
+
|
6
8
|
if event.data.object.subscription
|
7
|
-
Pay::Stripe::Subscription.sync(event.data.object.subscription)
|
9
|
+
Pay::Stripe::Subscription.sync(event.data.object.subscription, stripe_account: event.try(:account))
|
8
10
|
end
|
9
11
|
end
|
10
12
|
end
|
@@ -3,8 +3,10 @@ module Pay
|
|
3
3
|
module Webhooks
|
4
4
|
class CheckoutSessionCompleted
|
5
5
|
def call(event)
|
6
|
+
# TODO: Also handle payment intents
|
7
|
+
|
6
8
|
if event.data.object.subscription
|
7
|
-
Pay::Stripe::Subscription.sync(event.data.object.subscription)
|
9
|
+
Pay::Stripe::Subscription.sync(event.data.object.subscription, stripe_account: event.try(:account))
|
8
10
|
end
|
9
11
|
end
|
10
12
|
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
|
@@ -2,17 +2,15 @@ module Pay
|
|
2
2
|
module Stripe
|
3
3
|
module Webhooks
|
4
4
|
class PaymentIntentSucceeded
|
5
|
+
# This webhook does NOT send notifications because stripe sends both
|
6
|
+
# `charge.succeeded` and `payment_intent.succeeded` events.
|
7
|
+
#
|
8
|
+
# We use `charge.succeeded` as the single place to send notifications
|
9
|
+
|
5
10
|
def call(event)
|
6
11
|
object = event.data.object
|
7
12
|
object.charges.data.each do |charge|
|
8
|
-
|
9
|
-
notify_user(pay_charge.owner, pay_charge) if pay_charge
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def notify_user(billable, charge)
|
14
|
-
if Pay.send_emails && charge.respond_to?(:receipt)
|
15
|
-
Pay::UserMailer.with(billable: billable, charge: charge).receipt.deliver_later
|
13
|
+
Pay::Stripe::Charge.sync(charge.id, stripe_account: event.try(:account))
|
16
14
|
end
|
17
15
|
end
|
18
16
|
end
|
@@ -5,11 +5,9 @@ module Pay
|
|
5
5
|
def call(event)
|
6
6
|
object = event.data.object
|
7
7
|
pay_customer = Pay::Customer.find_by(processor: :stripe, processor_id: object.customer)
|
8
|
+
return unless pay_customer
|
8
9
|
|
9
|
-
|
10
|
-
return unless pay_customer.present?
|
11
|
-
|
12
|
-
Pay::Stripe::Billable.new(pay_customer).sync_payment_method(payment_method_id: object.id)
|
10
|
+
pay_customer.save_payment_method(object, default: false)
|
13
11
|
end
|
14
12
|
end
|
15
13
|
end
|
@@ -4,12 +4,7 @@ module Pay
|
|
4
4
|
class PaymentMethodDetached
|
5
5
|
def call(event)
|
6
6
|
object = event.data.object
|
7
|
-
|
8
|
-
|
9
|
-
# Couldn't find user, we can skip
|
10
|
-
return unless pay_customer.present?
|
11
|
-
|
12
|
-
Pay::Stripe::Billable.new(pay_customer).sync_payment_method(payment_method_id: object.id)
|
7
|
+
Pay::PaymentMethod.find_by_processor_and_id(:stripe, object.id)&.destroy
|
13
8
|
end
|
14
9
|
end
|
15
10
|
end
|