stripe_model_callbacks 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/Rakefile +1 -1
- data/app/models/stripe_model_callbacks/application_record.rb +28 -14
- data/app/services/stripe_model_callbacks/account/external_account/updated_service.rb +1 -1
- data/app/services/stripe_model_callbacks/attributes_assigner_service.rb +154 -8
- data/app/services/stripe_model_callbacks/base_service.rb +9 -6
- data/app/services/stripe_model_callbacks/charge/dispute_updated_service.rb +3 -3
- data/app/services/stripe_model_callbacks/charge/updated_service.rb +5 -5
- data/app/services/stripe_model_callbacks/configure_service.rb +58 -27
- data/app/services/stripe_model_callbacks/customer/bank_account/deleted_service.rb +1 -1
- data/app/services/stripe_model_callbacks/customer/discount_updated_service.rb +1 -1
- data/app/services/stripe_model_callbacks/customer/source_updated_service.rb +3 -3
- data/app/services/stripe_model_callbacks/customer/subscription/updated_service.rb +2 -2
- data/app/services/stripe_model_callbacks/customer/updated_service.rb +2 -2
- data/app/services/stripe_model_callbacks/event_mocker_service.rb +14 -8
- data/app/services/stripe_model_callbacks/invoice/updated_service.rb +4 -4
- data/app/services/stripe_model_callbacks/payment_intent/updated_service.rb +19 -0
- data/app/services/stripe_model_callbacks/payment_method/updated_service.rb +19 -0
- data/app/services/stripe_model_callbacks/payout/updated_service.rb +3 -3
- data/app/services/stripe_model_callbacks/plan/updated_service.rb +1 -1
- data/app/services/stripe_model_callbacks/price/updated_service.rb +1 -1
- data/app/services/stripe_model_callbacks/product/updated_service.rb +1 -1
- data/app/services/stripe_model_callbacks/recipient/updated_service.rb +1 -1
- data/app/services/stripe_model_callbacks/review/updated_service.rb +1 -1
- data/app/services/stripe_model_callbacks/setup_intent/updated_service.rb +8 -0
- data/app/services/stripe_model_callbacks/sku/updated_service.rb +1 -1
- data/app/services/stripe_model_callbacks/source/transaction_created_service.rb +17 -0
- data/app/services/stripe_model_callbacks/source/updated_service.rb +4 -4
- data/app/services/stripe_model_callbacks/subscription/state_checker_service.rb +1 -1
- data/app/services/stripe_model_callbacks/subscription_schedule/updated_service.rb +1 -1
- data/app/services/stripe_model_callbacks/sync_everything.rb +17 -2
- data/app/services/stripe_model_callbacks/sync_from_stripe.rb +1 -1
- data/app/services/stripe_model_callbacks/tax_rate/updated_service.rb +3 -3
- data/app/services/stripe_model_callbacks/transfer/updated_service.rb +1 -1
- data/config/rails_best_practices.yml +1 -0
- data/db/migrate/20180206151132_change_activities_trackable_id_to_string.rb +1 -1
- data/db/migrate/20180208091647_change_stripe_subscription_items_quantity_to_integer.rb +1 -1
- data/db/migrate/20181219121712_add_new_primary_id_and_rename_old.rb +2 -2
- data/db/migrate/20230210081405_create_stripe_setup_intents.rb +28 -0
- data/db/migrate/20230331182902_add_amount_captured_to_stripe_charges.rb +6 -0
- data/db/migrate/20230420092307_create_stripe_payment_methods.rb +15 -0
- data/db/migrate/20230421072509_create_stripe_payment_intents.rb +44 -0
- data/db/migrate/20230422074329_add_payment_intent_to_stripe_charges.rb +6 -0
- data/db/migrate/20230422175529_add_payment_intent_to_stripe_refunds.rb +6 -0
- data/db/migrate/20230422180602_change_stripe_refunds_stripe_charge_id_to_nullable.rb +5 -0
- data/db/migrate/20230518072538_change_stripe_setup_intents_payment_method_to_string.rb +7 -0
- data/lib/stripe_model_callbacks/configuration.rb +1 -1
- data/lib/stripe_model_callbacks/event_mocker.rb +1 -1
- data/lib/stripe_model_callbacks/factories/stripe_charges.rb +10 -0
- data/lib/stripe_model_callbacks/factories/stripe_coupons.rb +10 -9
- data/lib/stripe_model_callbacks/factories/stripe_customers.rb +6 -4
- data/lib/stripe_model_callbacks/factories/stripe_invoice_items.rb +1 -0
- data/lib/stripe_model_callbacks/factories/stripe_invoices.rb +1 -0
- data/lib/stripe_model_callbacks/factories/stripe_payment_intents.rb +17 -0
- data/lib/stripe_model_callbacks/factories/stripe_payment_methods.rb +15 -0
- data/lib/stripe_model_callbacks/factories/stripe_plans.rb +9 -12
- data/lib/stripe_model_callbacks/factories/stripe_products.rb +9 -8
- data/lib/stripe_model_callbacks/factories/stripe_recipients.rb +2 -0
- data/lib/stripe_model_callbacks/factories/stripe_reviews.rb +2 -0
- data/lib/stripe_model_callbacks/factories/stripe_setup_intents.rb +7 -0
- data/lib/stripe_model_callbacks/factories/stripe_skus.rb +1 -0
- data/lib/stripe_model_callbacks/factories/stripe_subscription_items.rb +7 -7
- data/lib/stripe_model_callbacks/factories/stripe_subscriptions.rb +10 -12
- data/lib/stripe_model_callbacks/factories/stripe_tax_rates.rb +10 -0
- data/lib/stripe_model_callbacks/factories/stripe_transfers.rb +2 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/charge/charge.refunded.json +1 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/invoice/invoice.upcoming.json +0 -1
- data/lib/stripe_model_callbacks/fixtures/stripe_events/payment_intent/payment_intent.amount_capturable_updated.json +66 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/payment_intent/payment_intent.canceled.json +66 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/payment_intent/payment_intent.created.json +66 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/payment_intent/payment_intent.partially_funded.json +66 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/payment_intent/payment_intent.payment_failed.json +66 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/payment_intent/payment_intent.processing.json +66 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/payment_intent/payment_intent.requires_action.json +66 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/payment_intent/payment_intent.succeeded.json +66 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/payment_method/payment_method.attached.json +63 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/payment_method/payment_method.automatically_updated.json +63 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/payment_method/payment_method.card_automatically_updated.json +63 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/payment_method/payment_method.detached.json +63 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/payment_method/payment_method.updated.json +63 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/setup_intent/setup_intent.created.json +47 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/setup_intent/setup_intent.updated.json +47 -0
- data/lib/stripe_model_callbacks/fixtures/stripe_events/source/{source.transaction_created.json → source.transaction.created.json} +2 -1
- data/lib/stripe_model_callbacks/models/stripe_charge.rb +51 -4
- data/lib/stripe_model_callbacks/models/stripe_coupon.rb +12 -0
- data/lib/stripe_model_callbacks/models/stripe_customer.rb +12 -0
- data/lib/stripe_model_callbacks/models/stripe_invoice.rb +17 -1
- data/lib/stripe_model_callbacks/models/stripe_payment_intent.rb +125 -0
- data/lib/stripe_model_callbacks/models/stripe_payment_method.rb +31 -0
- data/lib/stripe_model_callbacks/models/stripe_plan.rb +13 -0
- data/lib/stripe_model_callbacks/models/stripe_product.rb +10 -0
- data/lib/stripe_model_callbacks/models/stripe_recipient.rb +1 -1
- data/lib/stripe_model_callbacks/models/stripe_refund.rb +3 -1
- data/lib/stripe_model_callbacks/models/stripe_setup_intent.rb +21 -0
- data/lib/stripe_model_callbacks/models/stripe_source.rb +2 -1
- data/lib/stripe_model_callbacks/models/stripe_subscription.rb +23 -4
- data/lib/stripe_model_callbacks/models/stripe_subscription_item.rb +28 -2
- data/lib/stripe_model_callbacks/models/stripe_subscription_schedule.rb +2 -2
- data/lib/stripe_model_callbacks/models/stripe_subscription_schedule_phase.rb +1 -1
- data/lib/stripe_model_callbacks/models/stripe_tax_rate.rb +6 -0
- data/lib/stripe_model_callbacks/version.rb +1 -1
- data/lib/stripe_model_callbacks.rb +1 -1
- metadata +47 -14
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 00d4ab8c0fd0b78be1ebca4dae1507afacb17d06812e3cf76d62f1999cee23eb
|
|
4
|
+
data.tar.gz: 77e3fd6aa86bea4217294b30a8a570747c7688f9e3bf583a21adbe7b3524780e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c60062b0347c8c843ea108dda2d871925afd5b644cc0affc2ff8db6945f51b4014c3f82c930be7057dbcc1fb0b37780806188fc407ea257333e6b9adb1e0ef3e
|
|
7
|
+
data.tar.gz: 93a37540a9c8f7a3ebc1e087a6d777e71a28f977433bb2861828afa63b2120ec4fb55ef56472fa968a96ce936f9a06fc4884a14fca9a279336811bf95d96f5c8
|
data/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# StripeModelCallbacks
|
|
2
|
-
Stripe database models using ActiveRecord, Stripe event webhooks synchronization and
|
|
2
|
+
Stripe database models using ActiveRecord, Stripe event webhooks synchronization and ActiveRecordAuditable.
|
|
3
3
|
|
|
4
4
|
This is supposed to make it easier implementing a full blown Stripe implementation into your application,
|
|
5
5
|
so that you can code your app using ActiveRecord and all your favorite gems without having to mess around
|
|
@@ -20,11 +20,11 @@ And then execute:
|
|
|
20
20
|
bundle
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
You also need to install and setup the gems `
|
|
23
|
+
You also need to install and setup the gems `active_record_auditable`, `stripe` and `stripe_event`. Do this:
|
|
24
24
|
|
|
25
25
|
Install the migration for Public Activity, which will provide logging:
|
|
26
26
|
```bash
|
|
27
|
-
rails
|
|
27
|
+
rails active_record_auditable:install:migrations
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
You can install the migrations (or update an existing installation) with this command:
|
data/Rakefile
CHANGED
|
@@ -20,7 +20,7 @@ load "rails/tasks/statistics.rake"
|
|
|
20
20
|
|
|
21
21
|
require "bundler/gem_tasks"
|
|
22
22
|
|
|
23
|
-
if Rails.env.development? || Rails.env.test?
|
|
23
|
+
if Rails.env.development? || Rails.env.test? # rubocop:disable Rails/EnvLocal
|
|
24
24
|
require "best_practice_project"
|
|
25
25
|
BestPracticeProject.load_tasks
|
|
26
26
|
end
|
|
@@ -1,16 +1,31 @@
|
|
|
1
1
|
class StripeModelCallbacks::ApplicationRecord < ActiveRecord::Base
|
|
2
|
-
include PublicActivity::Model
|
|
3
|
-
tracked
|
|
4
|
-
|
|
5
2
|
self.abstract_class = true
|
|
6
3
|
|
|
7
|
-
|
|
4
|
+
attr_accessor :stripe_object
|
|
5
|
+
|
|
6
|
+
def self.inherited(child)
|
|
7
|
+
super
|
|
8
|
+
child.include ActiveRecordAuditable::Audited
|
|
9
|
+
apply_json_attribute_types(child)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.apply_json_attribute_types(model_class)
|
|
13
|
+
json_columns = StripeModelCallbacks::AttributesAssignerService::JSON_COLUMNS_BY_TABLE.fetch(
|
|
14
|
+
model_class.table_name,
|
|
15
|
+
[]
|
|
16
|
+
)
|
|
17
|
+
return if json_columns.empty?
|
|
18
|
+
|
|
19
|
+
json_columns.each do |column_name|
|
|
20
|
+
model_class.attribute(column_name, :json)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
8
23
|
|
|
9
24
|
def self.check_object_is_stripe_class(object, allowed = nil)
|
|
10
25
|
raise "'stripe_class' not defined on #{name}" unless respond_to?(:stripe_class)
|
|
11
26
|
|
|
12
27
|
# Ignore general objects
|
|
13
|
-
return if object.class.name == "Stripe::StripeObject" # rubocop:disable Style/ClassEqualityComparison
|
|
28
|
+
return if object.class.name == "Stripe::StripeObject" # rubocop:disable Style/ClassEqualityComparison
|
|
14
29
|
|
|
15
30
|
allowed ||= [stripe_class]
|
|
16
31
|
|
|
@@ -45,18 +60,15 @@ class StripeModelCallbacks::ApplicationRecord < ActiveRecord::Base
|
|
|
45
60
|
save!
|
|
46
61
|
end
|
|
47
62
|
|
|
48
|
-
def reload!(*args, &
|
|
63
|
+
def reload!(*args, &)
|
|
49
64
|
@to_stripe = nil
|
|
50
65
|
super
|
|
51
66
|
end
|
|
52
67
|
|
|
53
|
-
def update_on_stripe(attributes)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
to_stripe.save
|
|
59
|
-
reload_from_stripe!
|
|
68
|
+
def update_on_stripe(attributes) # rubocop:disable Naming/PredicateMethod
|
|
69
|
+
updated_object = self.class.stripe_class.update(stripe_id, attributes)
|
|
70
|
+
assign_from_stripe(updated_object)
|
|
71
|
+
save!
|
|
60
72
|
true
|
|
61
73
|
end
|
|
62
74
|
|
|
@@ -64,7 +76,9 @@ class StripeModelCallbacks::ApplicationRecord < ActiveRecord::Base
|
|
|
64
76
|
raise ActiveRecord::RecordInvalid, self unless update_on_stripe(attributes)
|
|
65
77
|
end
|
|
66
78
|
|
|
67
|
-
def destroy_on_stripe
|
|
79
|
+
def destroy_on_stripe # rubocop:disable Naming/PredicateMethod
|
|
80
|
+
raise "Can't delete #{self.class.name} on Stripe because it isn't supported" unless to_stripe.respond_to?(:delete)
|
|
81
|
+
|
|
68
82
|
to_stripe.delete
|
|
69
83
|
update!(deleted_at: Time.zone.now) if respond_to?(:deleted_at)
|
|
70
84
|
reload_from_stripe!
|
|
@@ -4,7 +4,7 @@ class StripeModelCallbacks::Account::ExternalAccount::UpdatedService < StripeMod
|
|
|
4
4
|
bank_account.assign_from_stripe(object)
|
|
5
5
|
|
|
6
6
|
if bank_account.save
|
|
7
|
-
bank_account.
|
|
7
|
+
bank_account.create_audit!(action: :deleted) if event.type == "account.external_account.deleted"
|
|
8
8
|
succeed!
|
|
9
9
|
else
|
|
10
10
|
fail! bank_account.errors.full_messages
|
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
class StripeModelCallbacks::AttributesAssignerService < ServicePattern::Service
|
|
2
2
|
attr_reader :attributes, :model, :stripe_model
|
|
3
3
|
|
|
4
|
+
SKIP_VALUE = Object.new
|
|
5
|
+
JSON_COLUMNS_BY_TABLE = {
|
|
6
|
+
"audits" => %w[audited_changes params],
|
|
7
|
+
"stripe_payment_intents" => %w[
|
|
8
|
+
amount_details
|
|
9
|
+
automatic_payment_methods
|
|
10
|
+
last_payment_error
|
|
11
|
+
metadata
|
|
12
|
+
next_action
|
|
13
|
+
payment_method_options
|
|
14
|
+
payment_method_types
|
|
15
|
+
processing
|
|
16
|
+
shipping
|
|
17
|
+
transfer_data
|
|
18
|
+
],
|
|
19
|
+
"stripe_payment_methods" => %w[billing_details card metadata],
|
|
20
|
+
"stripe_setup_intents" => %w[
|
|
21
|
+
flow_directions
|
|
22
|
+
mandate
|
|
23
|
+
payment_method_old
|
|
24
|
+
payment_method_options
|
|
25
|
+
payment_method_types
|
|
26
|
+
]
|
|
27
|
+
}.freeze
|
|
28
|
+
|
|
4
29
|
def initialize(attributes:, model:, stripe_model:)
|
|
5
30
|
@attributes = attributes
|
|
6
31
|
@model = model
|
|
@@ -9,15 +34,10 @@ class StripeModelCallbacks::AttributesAssignerService < ServicePattern::Service
|
|
|
9
34
|
|
|
10
35
|
def perform
|
|
11
36
|
attributes.each do |attribute|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
value = stripe_model.__send__(attribute)
|
|
37
|
+
value = value_for_attribute(attribute)
|
|
38
|
+
next if value == SKIP_VALUE
|
|
15
39
|
|
|
16
|
-
|
|
17
|
-
value = JSON.generate(value)
|
|
18
|
-
elsif attribute == "created" && value
|
|
19
|
-
value = Time.zone.at(value)
|
|
20
|
-
end
|
|
40
|
+
value = normalize_value(attribute, value)
|
|
21
41
|
|
|
22
42
|
model.__send__(setter_method(attribute), value)
|
|
23
43
|
end
|
|
@@ -25,6 +45,132 @@ class StripeModelCallbacks::AttributesAssignerService < ServicePattern::Service
|
|
|
25
45
|
succeed!
|
|
26
46
|
end
|
|
27
47
|
|
|
48
|
+
def value_for_attribute(attribute)
|
|
49
|
+
return value_from_stripe(attribute) if stripe_model.respond_to?(attribute)
|
|
50
|
+
|
|
51
|
+
return nil if allow_nil_attribute?(attribute)
|
|
52
|
+
return SKIP_VALUE unless model_value(attribute).nil?
|
|
53
|
+
|
|
54
|
+
default_value = default_value_for(attribute)
|
|
55
|
+
return SKIP_VALUE if default_value.nil?
|
|
56
|
+
|
|
57
|
+
default_value
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def value_from_stripe(attribute)
|
|
61
|
+
return nil if allow_nil_attribute?(attribute) && stripe_attribute_missing?(attribute)
|
|
62
|
+
|
|
63
|
+
value = stripe_model.__send__(attribute)
|
|
64
|
+
return nil if value.nil? && allow_nil_attribute?(attribute)
|
|
65
|
+
return default_value_for(attribute) if value.nil?
|
|
66
|
+
|
|
67
|
+
value
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def stripe_attribute_missing?(attribute)
|
|
71
|
+
return false unless stripe_model.respond_to?(:to_hash)
|
|
72
|
+
|
|
73
|
+
values = stripe_model.instance_variable_get(:@values)
|
|
74
|
+
return !values.key?(attribute.to_sym) && !values.key?(attribute.to_s) if values.is_a?(Hash)
|
|
75
|
+
|
|
76
|
+
stripe_values = stripe_model.to_hash
|
|
77
|
+
!stripe_values.key?(attribute.to_sym) && !stripe_values.key?(attribute.to_s)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def normalize_value(attribute, value)
|
|
81
|
+
if attribute == "created" && value
|
|
82
|
+
Time.zone.at(value)
|
|
83
|
+
elsif (converted_value = datetime_column_value(attribute, value))
|
|
84
|
+
converted_value
|
|
85
|
+
elsif json_column?(attribute)
|
|
86
|
+
normalize_json_value(value)
|
|
87
|
+
elsif attribute == "metadata"
|
|
88
|
+
JSON.generate(normalize_json_value(value))
|
|
89
|
+
else
|
|
90
|
+
value
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def model_value(attribute)
|
|
95
|
+
model.__send__(column_name_for(attribute))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def default_value_for(attribute)
|
|
99
|
+
default_value = model.class.column_defaults[column_name_for(attribute)]
|
|
100
|
+
|
|
101
|
+
return default_value unless default_value.nil?
|
|
102
|
+
|
|
103
|
+
nil
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def allow_nil_attribute?(attribute)
|
|
107
|
+
attribute == "auto_advance"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def json_column?(attribute)
|
|
111
|
+
column_name = column_name_for(attribute)
|
|
112
|
+
return true if json_columns_for_table.include?(column_name)
|
|
113
|
+
|
|
114
|
+
column = model.class.columns_hash[column_name]
|
|
115
|
+
return false unless column
|
|
116
|
+
return true if column.type == :json
|
|
117
|
+
|
|
118
|
+
false
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def json_columns_for_table
|
|
122
|
+
JSON_COLUMNS_BY_TABLE.fetch(model.class.table_name, [])
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def datetime_column_value(attribute, value)
|
|
126
|
+
return false unless value
|
|
127
|
+
|
|
128
|
+
column = model.class.columns_hash[column_name_for(attribute)]
|
|
129
|
+
return false unless column&.type == :datetime
|
|
130
|
+
|
|
131
|
+
timestamp = numeric_timestamp_value(value)
|
|
132
|
+
return Time.zone.at(timestamp) if timestamp
|
|
133
|
+
|
|
134
|
+
value
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def numeric_timestamp_value(value)
|
|
138
|
+
return value.to_i if value.is_a?(Integer) || value.is_a?(Float)
|
|
139
|
+
|
|
140
|
+
value.to_i if value.is_a?(String) && value.match?(/\A\d+\z/)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def normalize_json_value(value)
|
|
144
|
+
return value if value.nil?
|
|
145
|
+
|
|
146
|
+
return normalize_json_string(value) if value.is_a?(String)
|
|
147
|
+
|
|
148
|
+
return value.map { |item| normalize_json_value(item) } if value.is_a?(Array)
|
|
149
|
+
|
|
150
|
+
return value.transform_values { |item| normalize_json_value(item) } if value.is_a?(Hash)
|
|
151
|
+
|
|
152
|
+
return normalize_json_value(value.to_hash) if value.respond_to?(:to_hash)
|
|
153
|
+
|
|
154
|
+
value
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def normalize_json_string(value)
|
|
158
|
+
sanitized_value = value.tr("\u00A0", " ")
|
|
159
|
+
stripped_value = sanitized_value.strip
|
|
160
|
+
return value unless stripped_value.start_with?("{", "[")
|
|
161
|
+
|
|
162
|
+
begin
|
|
163
|
+
parsed_value = JSON.parse(sanitized_value)
|
|
164
|
+
normalize_json_value(parsed_value)
|
|
165
|
+
rescue JSON::ParserError
|
|
166
|
+
value
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def column_name_for(attribute)
|
|
171
|
+
attribute == "id" ? "stripe_id" : attribute
|
|
172
|
+
end
|
|
173
|
+
|
|
28
174
|
def setter_method(attribute)
|
|
29
175
|
if attribute == "id"
|
|
30
176
|
"stripe_id="
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
class StripeModelCallbacks::BaseService < ServicePattern::Service
|
|
2
|
-
def self.reported_execute!(
|
|
2
|
+
def self.reported_execute!(...)
|
|
3
3
|
with_exception_notifications do
|
|
4
|
-
response = execute(
|
|
4
|
+
response = execute(...)
|
|
5
5
|
raise response.errors.join(". ") unless response.success?
|
|
6
6
|
|
|
7
7
|
response
|
|
@@ -25,13 +25,16 @@ class StripeModelCallbacks::BaseService < ServicePattern::Service
|
|
|
25
25
|
raise e
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
def self.execute_with_advisory_lock!(
|
|
29
|
-
# The difference between the
|
|
28
|
+
def self.execute_with_advisory_lock!(*, **, &)
|
|
29
|
+
# The difference between the Stripe events is about a few milliseconds - with advisory_lock
|
|
30
30
|
# we will prevent from creating duplicated objects due to race condition.
|
|
31
31
|
# https://stripe.com/docs/webhooks/best-practices#event-ordering
|
|
32
32
|
with_exception_notifications do
|
|
33
|
-
StripeModelCallbacks::ApplicationRecord.with_advisory_lock(
|
|
34
|
-
|
|
33
|
+
StripeModelCallbacks::ApplicationRecord.with_advisory_lock!(
|
|
34
|
+
advisory_lock_name(*, **),
|
|
35
|
+
timeout_seconds: 10
|
|
36
|
+
) do
|
|
37
|
+
response = execute(*, **, &)
|
|
35
38
|
raise response.errors.join(". ") unless response.success?
|
|
36
39
|
|
|
37
40
|
response
|
|
@@ -19,11 +19,11 @@ private
|
|
|
19
19
|
def create_activity
|
|
20
20
|
case event.type
|
|
21
21
|
when "charge.dispute.closed"
|
|
22
|
-
dispute.
|
|
22
|
+
dispute.create_audit!(action: :closed)
|
|
23
23
|
when "charge.dispute.funds_reinstated"
|
|
24
|
-
dispute.
|
|
24
|
+
dispute.create_audit!(action: :funds_reinstated)
|
|
25
25
|
when "charge.dispute.funds_withdrawn"
|
|
26
|
-
dispute.
|
|
26
|
+
dispute.create_audit!(action: :funds_withdrawn)
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
end
|
|
@@ -19,15 +19,15 @@ private
|
|
|
19
19
|
def create_activity
|
|
20
20
|
case event.type
|
|
21
21
|
when "charge.captured"
|
|
22
|
-
charge.
|
|
22
|
+
charge.create_audit!(action: :captured)
|
|
23
23
|
when "charge.failed"
|
|
24
|
-
charge.
|
|
24
|
+
charge.create_audit!(action: :failed)
|
|
25
25
|
when "charge.pending"
|
|
26
|
-
charge.
|
|
26
|
+
charge.create_audit!(action: :pending)
|
|
27
27
|
when "charge.refunded"
|
|
28
|
-
charge.
|
|
28
|
+
charge.create_audit!(action: :refunded)
|
|
29
29
|
when "charge.succeeded"
|
|
30
|
-
charge.
|
|
30
|
+
charge.create_audit!(action: :succeeded)
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
end
|
|
@@ -20,12 +20,15 @@ class StripeModelCallbacks::ConfigureService < StripeModelCallbacks::BaseEventSe
|
|
|
20
20
|
invoice_events
|
|
21
21
|
order_events
|
|
22
22
|
recipient_events
|
|
23
|
+
payment_intent_events
|
|
24
|
+
payment_method_events
|
|
23
25
|
payout_events
|
|
24
26
|
plan_events
|
|
25
27
|
price_events
|
|
26
28
|
product_events
|
|
27
29
|
refund_events
|
|
28
30
|
review_events
|
|
31
|
+
setup_intent_events
|
|
29
32
|
sku_events
|
|
30
33
|
source_events
|
|
31
34
|
subscription_events
|
|
@@ -41,35 +44,35 @@ private
|
|
|
41
44
|
def account_external_account_events
|
|
42
45
|
%w[created deleted updated].each do |external_account_event|
|
|
43
46
|
subscribe "account.external_account.#{external_account_event}" do |event|
|
|
44
|
-
StripeModelCallbacks::Account::ExternalAccount::UpdatedService.execute_with_advisory_lock!(event:
|
|
47
|
+
StripeModelCallbacks::Account::ExternalAccount::UpdatedService.execute_with_advisory_lock!(event:)
|
|
45
48
|
end
|
|
46
49
|
end
|
|
47
50
|
end
|
|
48
51
|
|
|
49
52
|
def all_events
|
|
50
53
|
events.all do |event|
|
|
51
|
-
StripeModelCallbacks::NotifierService.execute_with_advisory_lock!(event:
|
|
54
|
+
StripeModelCallbacks::NotifierService.execute_with_advisory_lock!(event:)
|
|
52
55
|
end
|
|
53
56
|
end
|
|
54
57
|
|
|
55
58
|
def charge_events
|
|
56
59
|
%w[captured failed pending refunded updated succeeded].each do |charge_event|
|
|
57
60
|
subscribe "charge.#{charge_event}" do |event|
|
|
58
|
-
StripeModelCallbacks::Charge::UpdatedService.execute_with_advisory_lock!(event:
|
|
61
|
+
StripeModelCallbacks::Charge::UpdatedService.execute_with_advisory_lock!(event:)
|
|
59
62
|
end
|
|
60
63
|
end
|
|
61
64
|
end
|
|
62
65
|
|
|
63
66
|
def charge_refund_events
|
|
64
67
|
subscribe "charge.refund.updated" do |event|
|
|
65
|
-
StripeModelCallbacks::Refund::UpdatedService.execute_with_advisory_lock!(event:
|
|
68
|
+
StripeModelCallbacks::Refund::UpdatedService.execute_with_advisory_lock!(event:)
|
|
66
69
|
end
|
|
67
70
|
end
|
|
68
71
|
|
|
69
72
|
def charge_dispute_events
|
|
70
73
|
%w[closed created funds_reinstated funds_withdrawn updated].each do |charge_event|
|
|
71
74
|
subscribe "charge.dispute.#{charge_event}" do |event|
|
|
72
|
-
StripeModelCallbacks::Charge::DisputeUpdatedService.execute_with_advisory_lock!(event:
|
|
75
|
+
StripeModelCallbacks::Charge::DisputeUpdatedService.execute_with_advisory_lock!(event:)
|
|
73
76
|
end
|
|
74
77
|
end
|
|
75
78
|
end
|
|
@@ -77,21 +80,21 @@ private
|
|
|
77
80
|
def coupon_events
|
|
78
81
|
%w[created deleted updated].each do |coupon_event|
|
|
79
82
|
subscribe "coupon.#{coupon_event}" do |event|
|
|
80
|
-
StripeModelCallbacks::Coupon::UpdatedService.execute_with_advisory_lock!(event:
|
|
83
|
+
StripeModelCallbacks::Coupon::UpdatedService.execute_with_advisory_lock!(event:)
|
|
81
84
|
end
|
|
82
85
|
end
|
|
83
86
|
end
|
|
84
87
|
|
|
85
88
|
def customer_bank_account_events
|
|
86
89
|
subscribe "customer.bank_account.deleted" do |event|
|
|
87
|
-
StripeModelCallbacks::Customer::BankAccount::DeletedService.execute_with_advisory_lock!(event:
|
|
90
|
+
StripeModelCallbacks::Customer::BankAccount::DeletedService.execute_with_advisory_lock!(event:)
|
|
88
91
|
end
|
|
89
92
|
end
|
|
90
93
|
|
|
91
94
|
def customer_discount_events
|
|
92
95
|
%w[created deleted updated].each do |customer_event|
|
|
93
96
|
subscribe "customer.discount.#{customer_event}" do |event|
|
|
94
|
-
StripeModelCallbacks::Customer::DiscountUpdatedService.execute_with_advisory_lock!(event:
|
|
97
|
+
StripeModelCallbacks::Customer::DiscountUpdatedService.execute_with_advisory_lock!(event:)
|
|
95
98
|
end
|
|
96
99
|
end
|
|
97
100
|
end
|
|
@@ -99,7 +102,7 @@ private
|
|
|
99
102
|
def customer_events
|
|
100
103
|
%w[created deleted updated].each do |customer_event|
|
|
101
104
|
subscribe "customer.#{customer_event}" do |event|
|
|
102
|
-
StripeModelCallbacks::Customer::UpdatedService.execute_with_advisory_lock!(event:
|
|
105
|
+
StripeModelCallbacks::Customer::UpdatedService.execute_with_advisory_lock!(event:)
|
|
103
106
|
end
|
|
104
107
|
end
|
|
105
108
|
end
|
|
@@ -107,7 +110,7 @@ private
|
|
|
107
110
|
def customer_source_events
|
|
108
111
|
%w[created deleted expiring updated].each do |customer_event|
|
|
109
112
|
subscribe "customer.source.#{customer_event}" do |event|
|
|
110
|
-
StripeModelCallbacks::Customer::SourceUpdatedService.execute_with_advisory_lock!(event:
|
|
113
|
+
StripeModelCallbacks::Customer::SourceUpdatedService.execute_with_advisory_lock!(event:)
|
|
111
114
|
end
|
|
112
115
|
end
|
|
113
116
|
end
|
|
@@ -119,7 +122,7 @@ private
|
|
|
119
122
|
# https://stripe.com/docs/billing/invoices/overview#invoice-status-transition-endpoints-and-webhooks
|
|
120
123
|
%w[created deleted marked_uncollectible payment_failed payment_succeeded sent updated voided].each do |invoice_event|
|
|
121
124
|
subscribe "invoice.#{invoice_event}" do |event|
|
|
122
|
-
StripeModelCallbacks::Invoice::UpdatedService.execute_with_advisory_lock!(event:
|
|
125
|
+
StripeModelCallbacks::Invoice::UpdatedService.execute_with_advisory_lock!(event:)
|
|
123
126
|
end
|
|
124
127
|
end
|
|
125
128
|
end
|
|
@@ -127,7 +130,7 @@ private
|
|
|
127
130
|
def invoice_item_events
|
|
128
131
|
%w[created deleted updated].each do |event_type|
|
|
129
132
|
subscribe "invoiceitem.#{event_type}" do |event|
|
|
130
|
-
StripeModelCallbacks::InvoiceItem::UpdatedService.execute_with_advisory_lock!(event:
|
|
133
|
+
StripeModelCallbacks::InvoiceItem::UpdatedService.execute_with_advisory_lock!(event:)
|
|
131
134
|
end
|
|
132
135
|
end
|
|
133
136
|
end
|
|
@@ -135,7 +138,7 @@ private
|
|
|
135
138
|
def order_events
|
|
136
139
|
%w[created updated].each do |order_event|
|
|
137
140
|
subscribe "order.#{order_event}" do |event|
|
|
138
|
-
StripeModelCallbacks::Order::UpdatedService.execute_with_advisory_lock!(event:
|
|
141
|
+
StripeModelCallbacks::Order::UpdatedService.execute_with_advisory_lock!(event:)
|
|
139
142
|
end
|
|
140
143
|
end
|
|
141
144
|
end
|
|
@@ -143,7 +146,7 @@ private
|
|
|
143
146
|
def payout_events
|
|
144
147
|
%w[canceled created failed paid updated].each do |payout_event|
|
|
145
148
|
subscribe "payout.#{payout_event}" do |event|
|
|
146
|
-
StripeModelCallbacks::Payout::UpdatedService.execute_with_advisory_lock!(event:
|
|
149
|
+
StripeModelCallbacks::Payout::UpdatedService.execute_with_advisory_lock!(event:)
|
|
147
150
|
end
|
|
148
151
|
end
|
|
149
152
|
end
|
|
@@ -151,7 +154,7 @@ private
|
|
|
151
154
|
def recipient_events
|
|
152
155
|
%w[created deleted updated].each do |recipient_event|
|
|
153
156
|
subscribe "recipient.#{recipient_event}" do |event|
|
|
154
|
-
StripeModelCallbacks::Recipient::UpdatedService.execute_with_advisory_lock!(event:
|
|
157
|
+
StripeModelCallbacks::Recipient::UpdatedService.execute_with_advisory_lock!(event:)
|
|
155
158
|
end
|
|
156
159
|
end
|
|
157
160
|
end
|
|
@@ -159,7 +162,23 @@ private
|
|
|
159
162
|
def refund_events
|
|
160
163
|
%w[created updated].each do |refund_event|
|
|
161
164
|
subscribe "refund.#{refund_event}" do |event|
|
|
162
|
-
StripeModelCallbacks::Refund::UpdatedService.execute_with_advisory_lock!(event:
|
|
165
|
+
StripeModelCallbacks::Refund::UpdatedService.execute_with_advisory_lock!(event:)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def payment_intent_events
|
|
171
|
+
%w[amount_capturable_updated canceled created partially_funded payment_failed processing requires_action succeeded].each do |plan_event|
|
|
172
|
+
subscribe "payment_intent.#{plan_event}" do |event|
|
|
173
|
+
StripeModelCallbacks::PaymentIntent::UpdatedService.execute_with_advisory_lock!(event:)
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def payment_method_events
|
|
179
|
+
%w[attached automatically_updated card_automatically_updated detached updated].each do |plan_event|
|
|
180
|
+
subscribe "payment_method.#{plan_event}" do |event|
|
|
181
|
+
StripeModelCallbacks::PaymentMethod::UpdatedService.execute_with_advisory_lock!(event:)
|
|
163
182
|
end
|
|
164
183
|
end
|
|
165
184
|
end
|
|
@@ -167,7 +186,7 @@ private
|
|
|
167
186
|
def plan_events
|
|
168
187
|
%w[created deleted updated].each do |plan_event|
|
|
169
188
|
subscribe "plan.#{plan_event}" do |event|
|
|
170
|
-
StripeModelCallbacks::Plan::UpdatedService.execute_with_advisory_lock!(event:
|
|
189
|
+
StripeModelCallbacks::Plan::UpdatedService.execute_with_advisory_lock!(event:)
|
|
171
190
|
end
|
|
172
191
|
end
|
|
173
192
|
end
|
|
@@ -175,7 +194,7 @@ private
|
|
|
175
194
|
def sku_events
|
|
176
195
|
%w[created deleted updated].each do |sku_event|
|
|
177
196
|
subscribe "sku.#{sku_event}" do |event|
|
|
178
|
-
StripeModelCallbacks::Sku::UpdatedService.execute_with_advisory_lock!(event:
|
|
197
|
+
StripeModelCallbacks::Sku::UpdatedService.execute_with_advisory_lock!(event:)
|
|
179
198
|
end
|
|
180
199
|
end
|
|
181
200
|
end
|
|
@@ -183,7 +202,7 @@ private
|
|
|
183
202
|
def price_events
|
|
184
203
|
%w[created deleted updated].each do |price_event|
|
|
185
204
|
subscribe "price.#{price_event}" do |event|
|
|
186
|
-
StripeModelCallbacks::Price::UpdatedService.execute_with_advisory_lock!(event:
|
|
205
|
+
StripeModelCallbacks::Price::UpdatedService.execute_with_advisory_lock!(event:)
|
|
187
206
|
end
|
|
188
207
|
end
|
|
189
208
|
end
|
|
@@ -191,7 +210,7 @@ private
|
|
|
191
210
|
def product_events
|
|
192
211
|
%w[created deleted updated].each do |product_event|
|
|
193
212
|
subscribe "product.#{product_event}" do |event|
|
|
194
|
-
StripeModelCallbacks::Product::UpdatedService.execute_with_advisory_lock!(event:
|
|
213
|
+
StripeModelCallbacks::Product::UpdatedService.execute_with_advisory_lock!(event:)
|
|
195
214
|
end
|
|
196
215
|
end
|
|
197
216
|
end
|
|
@@ -199,7 +218,15 @@ private
|
|
|
199
218
|
def review_events
|
|
200
219
|
%w[opened closed].each do |review_event|
|
|
201
220
|
subscribe "review.#{review_event}" do |event|
|
|
202
|
-
StripeModelCallbacks::Review::UpdatedService.execute_with_advisory_lock!(event:
|
|
221
|
+
StripeModelCallbacks::Review::UpdatedService.execute_with_advisory_lock!(event:)
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def setup_intent_events
|
|
227
|
+
%w[created updated].each do |product_event|
|
|
228
|
+
subscribe "setup_intent.#{product_event}" do |event|
|
|
229
|
+
StripeModelCallbacks::SetupIntent::UpdatedService.execute_with_advisory_lock!(event:)
|
|
203
230
|
end
|
|
204
231
|
end
|
|
205
232
|
end
|
|
@@ -207,14 +234,18 @@ private
|
|
|
207
234
|
def source_events
|
|
208
235
|
%w[canceled chargeable failed mandate_notification].each do |source_event|
|
|
209
236
|
subscribe "source.#{source_event}" do |event|
|
|
210
|
-
StripeModelCallbacks::Source::UpdatedService.execute_with_advisory_lock!(event:
|
|
237
|
+
StripeModelCallbacks::Source::UpdatedService.execute_with_advisory_lock!(event:)
|
|
211
238
|
end
|
|
212
239
|
end
|
|
240
|
+
|
|
241
|
+
subscribe "source.transaction.created" do |event|
|
|
242
|
+
StripeModelCallbacks::Source::TransactionCreatedService.execute_with_advisory_lock!(event:)
|
|
243
|
+
end
|
|
213
244
|
end
|
|
214
245
|
|
|
215
246
|
def subscribe(event_name)
|
|
216
247
|
events.subscribe(event_name) do |event|
|
|
217
|
-
StripeModelCallbacks::Configuration.current.with_error_handling(args: {event:
|
|
248
|
+
StripeModelCallbacks::Configuration.current.with_error_handling(args: {event:}) do
|
|
218
249
|
yield event
|
|
219
250
|
end
|
|
220
251
|
end
|
|
@@ -223,7 +254,7 @@ private
|
|
|
223
254
|
def subscription_events
|
|
224
255
|
%w[created deleted trial_will_end updated].each do |subscription_event|
|
|
225
256
|
subscribe "customer.subscription.#{subscription_event}" do |event|
|
|
226
|
-
StripeModelCallbacks::Customer::Subscription::UpdatedService.execute_with_advisory_lock!(event:
|
|
257
|
+
StripeModelCallbacks::Customer::Subscription::UpdatedService.execute_with_advisory_lock!(event:)
|
|
227
258
|
end
|
|
228
259
|
end
|
|
229
260
|
end
|
|
@@ -231,7 +262,7 @@ private
|
|
|
231
262
|
def subscription_schedule_events
|
|
232
263
|
%w[canceled created updated].each do |subscription_event|
|
|
233
264
|
subscribe "subscription_schedule.#{subscription_event}" do |event|
|
|
234
|
-
StripeModelCallbacks::SubscriptionSchedule::UpdatedService.execute_with_advisory_lock!(event:
|
|
265
|
+
StripeModelCallbacks::SubscriptionSchedule::UpdatedService.execute_with_advisory_lock!(event:)
|
|
235
266
|
end
|
|
236
267
|
end
|
|
237
268
|
end
|
|
@@ -239,7 +270,7 @@ private
|
|
|
239
270
|
def tax_rate_events
|
|
240
271
|
%w[created updated].each do |transfer_event|
|
|
241
272
|
subscribe "tax_rate.#{transfer_event}" do |event|
|
|
242
|
-
StripeModelCallbacks::TaxRate::UpdatedService.execute_with_advisory_lock!(event:
|
|
273
|
+
StripeModelCallbacks::TaxRate::UpdatedService.execute_with_advisory_lock!(event:)
|
|
243
274
|
end
|
|
244
275
|
end
|
|
245
276
|
end
|
|
@@ -247,7 +278,7 @@ private
|
|
|
247
278
|
def transfer_events
|
|
248
279
|
%w[created reversed updated].each do |transfer_event|
|
|
249
280
|
subscribe "transfer.#{transfer_event}" do |event|
|
|
250
|
-
StripeModelCallbacks::Transfer::UpdatedService.execute_with_advisory_lock!(event:
|
|
281
|
+
StripeModelCallbacks::Transfer::UpdatedService.execute_with_advisory_lock!(event:)
|
|
251
282
|
end
|
|
252
283
|
end
|
|
253
284
|
end
|
|
@@ -4,7 +4,7 @@ class StripeModelCallbacks::Customer::BankAccount::DeletedService < StripeModelC
|
|
|
4
4
|
bank_account.assign_from_stripe(object)
|
|
5
5
|
|
|
6
6
|
if bank_account.save
|
|
7
|
-
bank_account.
|
|
7
|
+
bank_account.create_audit!(action: :customer_bank_account_deleted) if event.type == "customer.bank_account.deleted"
|
|
8
8
|
succeed!
|
|
9
9
|
else
|
|
10
10
|
fail! bank_account.errors.full_messages
|
|
@@ -14,7 +14,7 @@ class StripeModelCallbacks::Customer::DiscountUpdatedService < StripeModelCallba
|
|
|
14
14
|
private
|
|
15
15
|
|
|
16
16
|
def create_activity
|
|
17
|
-
discount.
|
|
17
|
+
discount.create_audit!(action: :deleted) if event&.type == "customer.discount.deleted"
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def coupon_id_look_up_by
|