pay 2.7.1 → 3.0.2

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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +34 -715
  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 +1 -5
  8. data/app/models/pay/charge.rb +54 -17
  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 +42 -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 +108 -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/generators/active_record/templates/billable_migration.rb +1 -0
  21. data/lib/pay/attributes.rb +74 -0
  22. data/lib/pay/billable/sync_customer.rb +30 -0
  23. data/lib/pay/braintree/billable.rb +133 -110
  24. data/lib/pay/braintree/payment_method.rb +42 -0
  25. data/lib/pay/braintree/subscription.rb +9 -12
  26. data/lib/pay/braintree/webhooks/subscription_canceled.rb +1 -1
  27. data/lib/pay/braintree/webhooks/subscription_charged_successfully.rb +4 -4
  28. data/lib/pay/braintree/webhooks/subscription_charged_unsuccessfully.rb +1 -1
  29. data/lib/pay/braintree/webhooks/subscription_expired.rb +1 -1
  30. data/lib/pay/braintree/webhooks/subscription_trial_ended.rb +2 -2
  31. data/lib/pay/braintree/webhooks/subscription_went_active.rb +1 -1
  32. data/lib/pay/braintree/webhooks/subscription_went_past_due.rb +1 -1
  33. data/lib/pay/braintree.rb +3 -2
  34. data/lib/pay/engine.rb +6 -1
  35. data/lib/pay/fake_processor/billable.rb +45 -21
  36. data/lib/pay/fake_processor/payment_method.rb +21 -0
  37. data/lib/pay/fake_processor/subscription.rb +11 -8
  38. data/lib/pay/fake_processor.rb +2 -1
  39. data/lib/pay/nano_id.rb +13 -0
  40. data/lib/pay/paddle/billable.rb +18 -48
  41. data/lib/pay/paddle/charge.rb +5 -5
  42. data/lib/pay/paddle/payment_method.rb +60 -0
  43. data/lib/pay/paddle/response.rb +0 -0
  44. data/lib/pay/paddle/subscription.rb +49 -8
  45. data/lib/pay/paddle/webhooks/subscription_cancelled.rb +6 -3
  46. data/lib/pay/paddle/webhooks/subscription_created.rb +1 -40
  47. data/lib/pay/paddle/webhooks/subscription_payment_refunded.rb +3 -3
  48. data/lib/pay/paddle/webhooks/subscription_payment_succeeded.rb +26 -28
  49. data/lib/pay/paddle/webhooks/subscription_updated.rb +2 -2
  50. data/lib/pay/paddle.rb +7 -3
  51. data/lib/pay/payment.rb +1 -1
  52. data/lib/pay/receipts.rb +35 -7
  53. data/lib/pay/stripe/billable.rb +75 -76
  54. data/lib/pay/stripe/charge.rb +44 -17
  55. data/lib/pay/stripe/merchant.rb +10 -10
  56. data/lib/pay/stripe/payment_method.rb +61 -0
  57. data/lib/pay/stripe/subscription.rb +55 -22
  58. data/lib/pay/stripe/webhooks/account_updated.rb +2 -3
  59. data/lib/pay/stripe/webhooks/charge_refunded.rb +1 -1
  60. data/lib/pay/stripe/webhooks/charge_succeeded.rb +2 -2
  61. data/lib/pay/stripe/webhooks/checkout_session_async_payment_succeeded.rb +3 -1
  62. data/lib/pay/stripe/webhooks/checkout_session_completed.rb +3 -1
  63. data/lib/pay/stripe/webhooks/customer_deleted.rb +7 -15
  64. data/lib/pay/stripe/webhooks/customer_updated.rb +10 -3
  65. data/lib/pay/stripe/webhooks/payment_action_required.rb +2 -2
  66. data/lib/pay/stripe/webhooks/payment_intent_succeeded.rb +6 -8
  67. data/lib/pay/stripe/webhooks/payment_method_attached.rb +15 -0
  68. data/lib/pay/stripe/webhooks/payment_method_detached.rb +12 -0
  69. data/lib/pay/stripe/webhooks/payment_method_updated.rb +10 -4
  70. data/lib/pay/stripe/webhooks/subscription_created.rb +1 -1
  71. data/lib/pay/stripe/webhooks/subscription_deleted.rb +2 -1
  72. data/lib/pay/stripe/webhooks/subscription_renewing.rb +12 -2
  73. data/lib/pay/stripe.rb +6 -3
  74. data/lib/pay/version.rb +1 -1
  75. data/lib/pay/webhooks/delegator.rb +4 -0
  76. data/lib/pay/webhooks/process_job.rb +9 -0
  77. data/lib/pay/webhooks.rb +1 -0
  78. data/lib/pay.rb +7 -78
  79. data/lib/tasks/pay.rake +20 -0
  80. metadata +23 -36
  81. data/app/models/pay.rb +0 -5
  82. data/db/migrate/20170205020145_create_pay_subscriptions.rb +0 -17
  83. data/db/migrate/20170727235816_create_pay_charges.rb +0 -18
  84. data/db/migrate/20190816015720_add_status_to_pay_subscriptions.rb +0 -14
  85. data/db/migrate/20200603134434_add_data_to_pay_models.rb +0 -6
  86. data/db/migrate/20210309004259_add_data_to_pay_billable.rb +0 -10
  87. data/db/migrate/20210406215234_add_currency_to_pay_charges.rb +0 -5
  88. data/db/migrate/20210406215506_add_application_fee_to_pay_models.rb +0 -7
  89. data/lib/pay/billable/sync_email.rb +0 -40
  90. data/lib/pay/billable.rb +0 -172
data/app/models/pay.rb DELETED
@@ -1,5 +0,0 @@
1
- module Pay
2
- def self.table_name_prefix
3
- "pay_"
4
- end
5
- end
@@ -1,17 +0,0 @@
1
- class CreatePaySubscriptions < ActiveRecord::Migration[4.2]
2
- def change
3
- create_table :pay_subscriptions do |t|
4
- # Some Billable objects use string as ID, add `type: :string` if needed
5
- t.references :owner, polymorphic: true
6
- t.string :name, null: false
7
- t.string :processor, null: false
8
- t.string :processor_id, null: false
9
- t.string :processor_plan, null: false
10
- t.integer :quantity, default: 1, null: false
11
- t.datetime :trial_ends_at
12
- t.datetime :ends_at
13
-
14
- t.timestamps
15
- end
16
- end
17
- end
@@ -1,18 +0,0 @@
1
- class CreatePayCharges < ActiveRecord::Migration[4.2]
2
- def change
3
- create_table :pay_charges do |t|
4
- # Some Billable objects use string as ID, add `type: :string` if needed
5
- t.references :owner, polymorphic: true
6
- t.string :processor, null: false
7
- t.string :processor_id, null: false
8
- t.integer :amount, null: false
9
- t.integer :amount_refunded
10
- t.string :card_type
11
- t.string :card_last4
12
- t.string :card_exp_month
13
- t.string :card_exp_year
14
-
15
- t.timestamps
16
- end
17
- end
18
- end
@@ -1,14 +0,0 @@
1
- class AddStatusToPaySubscriptions < ActiveRecord::Migration[4.2]
2
- def self.up
3
- add_column :pay_subscriptions, :status, :string
4
-
5
- # Any existing subscriptions should be marked as 'active'
6
- # This won't actually make them active if their ends_at column is expired
7
- Pay::Subscription.reset_column_information
8
- Pay::Subscription.update_all(status: :active)
9
- end
10
-
11
- def self.down
12
- remove_column :pay_subscriptions, :status
13
- end
14
- end
@@ -1,6 +0,0 @@
1
- class AddDataToPayModels < ActiveRecord::Migration[4.2]
2
- def change
3
- add_column :pay_subscriptions, :data, Pay::Adapter.json_column_type
4
- add_column :pay_charges, :data, Pay::Adapter.json_column_type
5
- end
6
- end
@@ -1,10 +0,0 @@
1
- class AddDataToPayBillable < ActiveRecord::Migration[4.2]
2
- def change
3
- # Load all the billable models
4
- Rails.application.eager_load!
5
-
6
- Pay.billable_models.each do |model|
7
- add_column model.table_name, :pay_data, Pay::Adapter.json_column_type
8
- end
9
- end
10
- end
@@ -1,5 +0,0 @@
1
- class AddCurrencyToPayCharges < ActiveRecord::Migration[4.2]
2
- def change
3
- add_column :pay_charges, :currency, :string
4
- end
5
- end
@@ -1,7 +0,0 @@
1
- class AddApplicationFeeToPayModels < ActiveRecord::Migration[4.2]
2
- def change
3
- add_column :pay_charges, :application_fee_amount, :integer
4
- add_column :pay_subscriptions, :application_fee_percent, :decimal, precision: 8, scale: 2
5
- add_column :pay_charges, :pay_subscription_id, :integer
6
- end
7
- end
@@ -1,40 +0,0 @@
1
- module Pay
2
- module Billable
3
- module SyncEmail
4
- # Sync email address changes from the model to the processor.
5
- # This way they're kept in sync and email notifications are
6
- # always sent to the correct email address after an update.
7
- #
8
- # Processor classes simply need to implement a method named:
9
- #
10
- # update_PROCESSOR_email!
11
- #
12
- # This method should take the email address on the billable
13
- # object and update the associated API record.
14
-
15
- extend ActiveSupport::Concern
16
-
17
- included do
18
- after_update :enqeue_sync_email_job, if: :should_sync_email_with_processor?
19
- end
20
-
21
- def should_sync_email_with_processor?
22
- try(:saved_change_to_email?)
23
- end
24
-
25
- def sync_email_with_processor
26
- payment_processor.update_email!
27
- end
28
-
29
- private
30
-
31
- def enqeue_sync_email_job
32
- # Only update if the processor id is the same
33
- # This prevents duplicate API hits if this is their first time
34
- if processor_id? && !saved_change_to_processor_id? && saved_change_to_email?
35
- EmailSyncJob.perform_later(id, self.class.name)
36
- end
37
- end
38
- end
39
- end
40
- end
data/lib/pay/billable.rb DELETED
@@ -1,172 +0,0 @@
1
- require "pay/billable/sync_email"
2
-
3
- module Pay
4
- module Billable
5
- extend ActiveSupport::Concern
6
-
7
- # Keep track of which Billable models we have
8
- class << self
9
- attr_reader :includers
10
- end
11
-
12
- def self.included(base = nil, &block)
13
- @includers ||= []
14
- @includers << base if base
15
- super
16
- end
17
-
18
- included do |base|
19
- include Pay::Billable::SyncEmail
20
-
21
- has_many :charges, class_name: Pay.chargeable_class, foreign_key: :owner_id, inverse_of: :owner, as: :owner
22
- has_many :subscriptions, class_name: Pay.subscription_class, foreign_key: :owner_id, inverse_of: :owner, as: :owner
23
-
24
- attribute :plan, :string
25
- attribute :quantity, :integer
26
- attribute :card_token, :string
27
- attribute :pay_fake_processor_allowed, :boolean, default: false
28
-
29
- # Account(s) for marketplace payments
30
- store_accessor :pay_data, :stripe_account
31
- store_accessor :pay_data, :braintree_account
32
-
33
- validate :pay_fake_processor_is_allowed, if: :processor_changed?
34
- end
35
-
36
- def payment_processor
37
- @payment_processor ||= payment_processor_for(processor).new(self)
38
- end
39
-
40
- def payment_processor_for(name)
41
- raise Error, "No payment processor set. Assign a payment processor with 'object.processor = :stripe' or any supported processor." if name.blank?
42
- "Pay::#{name.to_s.classify}::Billable".constantize
43
- end
44
-
45
- # Reset the payment processor when it changes
46
- def processor=(value)
47
- super(value)
48
- self.processor_id = nil if processor_changed?
49
- @payment_processor = nil
50
- end
51
-
52
- def processor
53
- super&.inquiry
54
- end
55
-
56
- delegate :charge, to: :payment_processor
57
- delegate :subscribe, to: :payment_processor
58
- delegate :update_card, to: :payment_processor
59
-
60
- def customer
61
- raise Pay::Error, I18n.t("errors.email_required") if email.nil?
62
-
63
- customer = payment_processor.customer
64
- payment_processor.update_card(card_token) if card_token.present?
65
- customer
66
- end
67
-
68
- def customer_name
69
- [try(:first_name), try(:last_name)].compact.join(" ")
70
- end
71
-
72
- def create_setup_intent
73
- ActiveSupport::Deprecation.warn("This method will be removed in the next release. Use `@billable.payment_processor.create_setup_intent` instead.")
74
- payment_processor.create_setup_intent
75
- end
76
-
77
- def on_trial?(name: Pay.default_product_name, plan: nil)
78
- return true if default_generic_trial?(name, plan)
79
-
80
- sub = subscription(name: name)
81
- return sub&.on_trial? if plan.nil?
82
-
83
- sub&.on_trial? && sub.processor_plan == plan
84
- end
85
-
86
- def on_generic_trial?
87
- trial_ends_at? && trial_ends_at > Time.zone.now
88
- end
89
-
90
- def processor_subscription(subscription_id, options = {})
91
- payment_processor.processor_subscription(subscription_id, options)
92
- end
93
-
94
- def subscribed?(name: Pay.default_product_name, processor_plan: nil)
95
- subscription = subscription(name: name)
96
-
97
- return false if subscription.nil?
98
- return subscription.active? if processor_plan.nil?
99
-
100
- subscription.active? && subscription.processor_plan == processor_plan
101
- end
102
-
103
- def on_trial_or_subscribed?(name: Pay.default_product_name, processor_plan: nil)
104
- on_trial?(name: name, plan: processor_plan) ||
105
- subscribed?(name: name, processor_plan: processor_plan)
106
- end
107
-
108
- def subscription(name: Pay.default_product_name)
109
- subscriptions.loaded? ? subscriptions.reverse.detect { |s| s.name == name } : subscriptions.for_name(name).last
110
- end
111
-
112
- def invoice!(options = {})
113
- ActiveSupport::Deprecation.warn("This will be removed in the next release. Use `@billable.payment_processor.invoice!` instead.")
114
- payment_processor.invoice!(options)
115
- end
116
-
117
- def upcoming_invoice
118
- ActiveSupport::Deprecation.warn("This will be removed in the next release. Use `@billable.payment_processor.upcoming_invoice` instead.")
119
- payment_processor.upcoming_invoice
120
- end
121
-
122
- def stripe?
123
- ActiveSupport::Deprecation.warn("This will be removed in the next release. Use `@billable.processor.stripe?` instead.")
124
- processor == "stripe"
125
- end
126
-
127
- def braintree?
128
- ActiveSupport::Deprecation.warn("This will be removed in the next release. Use `@billable.processor.braintree?` instead.")
129
- processor == "braintree"
130
- end
131
-
132
- def paypal?
133
- card_type == "PayPal"
134
- end
135
-
136
- def paddle?
137
- ActiveSupport::Deprecation.warn("This will be removed in the next release. Use `@billable.processor.paddle?` instead.")
138
- processor == "paddle"
139
- end
140
-
141
- def has_incomplete_payment?(name: Pay.default_product_name)
142
- subscription(name: name)&.has_incomplete_payment?
143
- end
144
-
145
- # Used for creating a Pay::Subscription in the database
146
- def create_pay_subscription(subscription, processor, name, plan, options = {})
147
- options[:quantity] ||= 1
148
-
149
- options.merge!(
150
- name: name || "default",
151
- processor: processor,
152
- processor_id: subscription.id,
153
- processor_plan: plan,
154
- trial_ends_at: payment_processor.trial_end_date(subscription),
155
- ends_at: nil
156
- )
157
- subscriptions.create!(options)
158
- end
159
-
160
- private
161
-
162
- def default_generic_trial?(name, plan)
163
- # Generic trials don't have plans or custom names
164
- plan.nil? && name == "default" && on_generic_trial?
165
- end
166
-
167
- def pay_fake_processor_is_allowed
168
- return unless processor == "fake_processor"
169
- errors.add(:processor, "must be a valid payment processor") unless pay_fake_processor_allowed?
170
- end
171
- end
172
- end