pay 2.7.0 → 3.0.1
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 -696
- 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 +31 -18
- 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 +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 +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 +9 -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 +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/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 +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 +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 +80 -102
- data/lib/pay/stripe/charge.rb +59 -3
- data/lib/pay/stripe/merchant.rb +10 -10
- data/lib/pay/stripe/payment_method.rb +61 -0
- data/lib/pay/stripe/subscription.rb +70 -8
- data/lib/pay/stripe/webhooks/account_updated.rb +2 -3
- 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 -36
- 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 -29
- data/lib/pay/stripe.rb +12 -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 +20 -0
- metadata +31 -39
- data/app/models/pay.rb +0 -5
- 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 -15
- data/db/migrate/20210309004259_add_data_to_pay_billable.rb +0 -19
- 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/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 -172
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,36 +19,90 @@ module Pay
|
|
20
19
|
:trial_ends_at,
|
21
20
|
to: :pay_subscription
|
22
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
|
+
|
23
74
|
def initialize(pay_subscription)
|
24
75
|
@pay_subscription = pay_subscription
|
25
76
|
end
|
26
77
|
|
27
78
|
def subscription(**options)
|
28
|
-
|
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)
|
29
82
|
end
|
30
83
|
|
31
84
|
def cancel
|
32
|
-
stripe_sub = ::Stripe::Subscription.update(processor_id, {cancel_at_period_end: true},
|
85
|
+
stripe_sub = ::Stripe::Subscription.update(processor_id, {cancel_at_period_end: true}, stripe_options)
|
33
86
|
pay_subscription.update(ends_at: (on_trial? ? trial_ends_at : Time.at(stripe_sub.current_period_end)))
|
34
87
|
rescue ::Stripe::StripeError => e
|
35
88
|
raise Pay::Stripe::Error, e
|
36
89
|
end
|
37
90
|
|
38
91
|
def cancel_now!
|
39
|
-
::Stripe::Subscription.delete(processor_id, {
|
92
|
+
::Stripe::Subscription.delete(processor_id, {}, stripe_options)
|
40
93
|
pay_subscription.update(ends_at: Time.current, status: :canceled)
|
41
94
|
rescue ::Stripe::StripeError => e
|
42
95
|
raise Pay::Stripe::Error, e
|
43
96
|
end
|
44
97
|
|
45
98
|
def change_quantity(quantity)
|
46
|
-
::Stripe::Subscription.update(processor_id, quantity: quantity)
|
99
|
+
::Stripe::Subscription.update(processor_id, {quantity: quantity}, stripe_options)
|
47
100
|
rescue ::Stripe::StripeError => e
|
48
101
|
raise Pay::Stripe::Error, e
|
49
102
|
end
|
50
103
|
|
51
104
|
def on_grace_period?
|
52
|
-
canceled? && Time.
|
105
|
+
canceled? && Time.current < ends_at
|
53
106
|
end
|
54
107
|
|
55
108
|
def paused?
|
@@ -72,13 +125,15 @@ module Pay
|
|
72
125
|
trial_end: (on_trial? ? trial_ends_at.to_i : "now"),
|
73
126
|
cancel_at_period_end: false
|
74
127
|
},
|
75
|
-
|
128
|
+
stripe_options
|
76
129
|
)
|
77
130
|
rescue ::Stripe::StripeError => e
|
78
131
|
raise Pay::Stripe::Error, e
|
79
132
|
end
|
80
133
|
|
81
134
|
def swap(plan)
|
135
|
+
raise ArgumentError, "plan must be a string" unless plan.is_a?(String)
|
136
|
+
|
82
137
|
::Stripe::Subscription.update(
|
83
138
|
processor_id,
|
84
139
|
{
|
@@ -88,11 +143,18 @@ module Pay
|
|
88
143
|
trial_end: (on_trial? ? trial_ends_at.to_i : "now"),
|
89
144
|
quantity: quantity
|
90
145
|
},
|
91
|
-
|
146
|
+
stripe_options
|
92
147
|
)
|
93
148
|
rescue ::Stripe::StripeError => e
|
94
149
|
raise Pay::Stripe::Error, e
|
95
150
|
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
# Options for Stripe requests
|
155
|
+
def stripe_options
|
156
|
+
{stripe_account: stripe_account}.compact
|
157
|
+
end
|
96
158
|
end
|
97
159
|
end
|
98
160
|
end
|
@@ -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,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
|
@@ -2,23 +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
|
-
billable = Pay.find_billable(processor: :stripe, processor_id: object.customer)
|
8
|
-
|
9
|
-
return unless billable.present?
|
10
|
-
|
11
12
|
object.charges.data.each do |charge|
|
12
|
-
|
13
|
-
|
14
|
-
charge = Pay::Stripe::Billable.new(billable).save_pay_charge(charge)
|
15
|
-
notify_user(billable, charge)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def notify_user(billable, charge)
|
20
|
-
if Pay.send_emails && charge.respond_to?(:receipt)
|
21
|
-
Pay::UserMailer.with(billable: billable, charge: charge).receipt.deliver_later
|
13
|
+
Pay::Stripe::Charge.sync(charge.id, stripe_account: event.try(:account))
|
22
14
|
end
|
23
15
|
end
|
24
16
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Pay
|
2
|
+
module Stripe
|
3
|
+
module Webhooks
|
4
|
+
class PaymentMethodAttached
|
5
|
+
def call(event)
|
6
|
+
object = event.data.object
|
7
|
+
pay_customer = Pay::Customer.find_by(processor: :stripe, processor_id: object.customer)
|
8
|
+
return unless pay_customer
|
9
|
+
|
10
|
+
pay_customer.save_payment_method(object, default: false)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|