pay 2.7.2 → 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.

Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +34 -731
  3. data/app/controllers/pay/webhooks/braintree_controller.rb +10 -3
  4. data/app/controllers/pay/webhooks/paddle_controller.rb +7 -8
  5. data/app/controllers/pay/webhooks/stripe_controller.rb +6 -3
  6. data/app/jobs/pay/{email_sync_job.rb → customer_sync_job.rb} +3 -4
  7. data/app/models/pay/application_record.rb +0 -5
  8. data/app/models/pay/charge.rb +31 -18
  9. data/app/models/pay/customer.rb +87 -0
  10. data/app/models/pay/merchant.rb +19 -0
  11. data/app/models/pay/payment_method.rb +41 -0
  12. data/app/models/pay/subscription.rb +32 -30
  13. data/app/models/pay/webhook.rb +36 -0
  14. data/app/views/layouts/pay/application.html.erb +2 -3
  15. data/app/views/pay/payments/show.html.erb +109 -81
  16. data/app/views/pay/user_mailer/receipt.html.erb +2 -2
  17. data/app/views/pay/user_mailer/refund.html.erb +2 -2
  18. data/config/locales/en.yml +1 -1
  19. data/db/migrate/1_create_pay_tables.rb +72 -0
  20. data/lib/pay/attributes.rb +74 -0
  21. data/lib/pay/billable/sync_customer.rb +30 -0
  22. data/lib/pay/braintree/billable.rb +126 -108
  23. data/lib/pay/braintree/payment_method.rb +33 -0
  24. data/lib/pay/braintree/subscription.rb +7 -12
  25. data/lib/pay/braintree/webhooks/subscription_canceled.rb +1 -1
  26. data/lib/pay/braintree/webhooks/subscription_charged_successfully.rb +4 -4
  27. data/lib/pay/braintree/webhooks/subscription_charged_unsuccessfully.rb +1 -1
  28. data/lib/pay/braintree/webhooks/subscription_expired.rb +1 -1
  29. data/lib/pay/braintree/webhooks/subscription_trial_ended.rb +2 -2
  30. data/lib/pay/braintree/webhooks/subscription_went_active.rb +1 -1
  31. data/lib/pay/braintree/webhooks/subscription_went_past_due.rb +1 -1
  32. data/lib/pay/braintree.rb +3 -2
  33. data/lib/pay/engine.rb +6 -1
  34. data/lib/pay/fake_processor/billable.rb +45 -21
  35. data/lib/pay/fake_processor/payment_method.rb +21 -0
  36. data/lib/pay/fake_processor/subscription.rb +11 -10
  37. data/lib/pay/fake_processor.rb +2 -1
  38. data/lib/pay/nano_id.rb +13 -0
  39. data/lib/pay/paddle/billable.rb +18 -48
  40. data/lib/pay/paddle/charge.rb +5 -5
  41. data/lib/pay/paddle/payment_method.rb +58 -0
  42. data/lib/pay/paddle/response.rb +0 -0
  43. data/lib/pay/paddle/subscription.rb +47 -8
  44. data/lib/pay/paddle/webhooks/subscription_cancelled.rb +6 -3
  45. data/lib/pay/paddle/webhooks/subscription_created.rb +1 -40
  46. data/lib/pay/paddle/webhooks/subscription_payment_refunded.rb +3 -3
  47. data/lib/pay/paddle/webhooks/subscription_payment_succeeded.rb +26 -28
  48. data/lib/pay/paddle/webhooks/subscription_updated.rb +2 -2
  49. data/lib/pay/paddle.rb +7 -3
  50. data/lib/pay/payment.rb +1 -1
  51. data/lib/pay/receipts.rb +35 -7
  52. data/lib/pay/stripe/billable.rb +50 -64
  53. data/lib/pay/stripe/charge.rb +18 -15
  54. data/lib/pay/stripe/merchant.rb +10 -10
  55. data/lib/pay/stripe/payment_method.rb +61 -0
  56. data/lib/pay/stripe/subscription.rb +22 -17
  57. data/lib/pay/stripe/webhooks/account_updated.rb +2 -3
  58. data/lib/pay/stripe/webhooks/charge_refunded.rb +1 -1
  59. data/lib/pay/stripe/webhooks/charge_succeeded.rb +2 -2
  60. data/lib/pay/stripe/webhooks/checkout_session_async_payment_succeeded.rb +3 -1
  61. data/lib/pay/stripe/webhooks/checkout_session_completed.rb +3 -1
  62. data/lib/pay/stripe/webhooks/customer_deleted.rb +7 -15
  63. data/lib/pay/stripe/webhooks/customer_updated.rb +10 -3
  64. data/lib/pay/stripe/webhooks/payment_action_required.rb +2 -2
  65. data/lib/pay/stripe/webhooks/payment_intent_succeeded.rb +6 -8
  66. data/lib/pay/stripe/webhooks/payment_method_attached.rb +2 -4
  67. data/lib/pay/stripe/webhooks/payment_method_detached.rb +1 -6
  68. data/lib/pay/stripe/webhooks/payment_method_updated.rb +10 -4
  69. data/lib/pay/stripe/webhooks/subscription_created.rb +1 -1
  70. data/lib/pay/stripe/webhooks/subscription_deleted.rb +2 -1
  71. data/lib/pay/stripe/webhooks/subscription_renewing.rb +12 -2
  72. data/lib/pay/stripe.rb +6 -3
  73. data/lib/pay/version.rb +1 -1
  74. data/lib/pay/webhooks/delegator.rb +4 -0
  75. data/lib/pay/webhooks/process_job.rb +9 -0
  76. data/lib/pay/webhooks.rb +1 -0
  77. data/lib/pay.rb +7 -78
  78. metadata +20 -37
  79. data/db/migrate/20170205020145_create_pay_subscriptions.rb +0 -17
  80. data/db/migrate/20170727235816_create_pay_charges.rb +0 -18
  81. data/db/migrate/20190816015720_add_status_to_pay_subscriptions.rb +0 -14
  82. data/db/migrate/20200603134434_add_data_to_pay_models.rb +0 -6
  83. data/db/migrate/20210309004259_add_data_to_pay_billable.rb +0 -10
  84. data/db/migrate/20210406215234_add_currency_to_pay_charges.rb +0 -5
  85. data/db/migrate/20210406215506_add_application_fee_to_pay_models.rb +0 -7
  86. data/db/migrate/20210714175351_add_uniqueness_to_pay_models.rb +0 -6
  87. data/lib/pay/billable/sync_email.rb +0 -40
  88. data/lib/pay/billable.rb +0 -172
  89. data/lib/pay/stripe/webhooks/payment_method_automatically_updated.rb +0 -17
@@ -3,43 +3,46 @@ module Pay
3
3
  class Charge
4
4
  attr_reader :pay_charge
5
5
 
6
- delegate :processor_id, :owner, :stripe_account, to: :pay_charge
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(id: charge_id)
10
+ object ||= ::Stripe::Charge.retrieve(charge_id, {stripe_account: stripe_account}.compact)
11
11
 
12
- owner = Pay.find_billable(processor: :stripe, processor_id: object.customer)
13
- return unless owner
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: owner.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] = Pay::Subscription.find_by(processor: :stripe, processor_id: invoice.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
- processor_details = {processor: :stripe, processor_id: object.id}
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
- owner.charges.create!(attrs.merge(processor_details))
45
+ pay_customer.charges.create!(attrs.merge(processor_id: object.id))
43
46
  end
44
47
  rescue ActiveRecord::RecordInvalid
45
48
  try += 1
@@ -1,13 +1,13 @@
1
1
  module Pay
2
2
  module Stripe
3
3
  class Merchant
4
- attr_reader :merchant
4
+ attr_reader :pay_merchant
5
5
 
6
- delegate :stripe_connect_account_id,
7
- to: :merchant
6
+ delegate :processor_id,
7
+ to: :pay_merchant
8
8
 
9
- def initialize(merchant)
10
- @merchant = merchant
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
- merchant.update(stripe_connect_account_id: stripe_account.id)
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(stripe_connect_account_id)
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: stripe_connect_account_id,
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(stripe_connect_account_id)
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: stripe_connect_account_id
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
- owner = Pay.find_billable(processor: :stripe, processor_id: object.customer)
28
- return unless owner
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: owner.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
- processor_details = {processor: :stripe, processor_id: object.id}
53
- if (pay_subscription = owner.subscriptions.find_by(processor_details))
54
- pay_subscription.with_lock do
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
- owner.subscriptions.create!(attributes.merge(processor_details))
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
- ::Stripe::Subscription.retrieve(options.merge(id: processor_id))
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.zone.now < ends_at
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.find_merchant("stripe_connect_account_id", object.id)
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
- billable = Pay.find_billable(processor: :stripe, processor_id: object.id)
7
+ pay_customer = Pay::Customer.find_by(processor: :stripe, processor_id: object.id)
8
8
 
9
- # Couldn't find user, we can skip
10
- return unless billable.present?
9
+ # Mark all subscriptions as canceled
10
+ pay_customer.subscriptions.active.update_all(ends_at: Time.current, status: "canceled")
11
11
 
12
- billable.update(
13
- processor_id: nil,
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
- billable.subscriptions.update_all(
22
- trial_ends_at: nil,
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
- billable = Pay.find_billable(processor: :stripe, processor_id: object.id)
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 billable.present?
10
+ return unless pay_customer.present?
11
11
 
12
- Pay::Stripe::Billable.new(billable).sync_card_from_stripe
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.subscription_model.find_by(processor: :stripe, processor_id: object.subscription)
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
- pay_charge = Pay::Stripe::Charge.sync(charge.id)
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
- # 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)
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
- pay_customer = Pay::Customer.find_by(processor: :stripe, processor_id: object.customer)
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