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.
- checksums.yaml +4 -4
- data/README.md +34 -715
- 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 +54 -17
- 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 +108 -81
- data/app/views/pay/user_mailer/receipt.html.erb +2 -2
- data/app/views/pay/user_mailer/refund.html.erb +2 -2
- data/config/locales/en.yml +1 -1
- data/db/migrate/1_create_pay_tables.rb +72 -0
- data/lib/generators/active_record/templates/billable_migration.rb +1 -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/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 +75 -76
- data/lib/pay/stripe/charge.rb +44 -17
- data/lib/pay/stripe/merchant.rb +10 -10
- data/lib/pay/stripe/payment_method.rb +61 -0
- data/lib/pay/stripe/subscription.rb +55 -22
- data/lib/pay/stripe/webhooks/account_updated.rb +2 -3
- data/lib/pay/stripe/webhooks/charge_refunded.rb +1 -1
- data/lib/pay/stripe/webhooks/charge_succeeded.rb +2 -2
- data/lib/pay/stripe/webhooks/checkout_session_async_payment_succeeded.rb +3 -1
- data/lib/pay/stripe/webhooks/checkout_session_completed.rb +3 -1
- data/lib/pay/stripe/webhooks/customer_deleted.rb +7 -15
- data/lib/pay/stripe/webhooks/customer_updated.rb +10 -3
- data/lib/pay/stripe/webhooks/payment_action_required.rb +2 -2
- data/lib/pay/stripe/webhooks/payment_intent_succeeded.rb +6 -8
- data/lib/pay/stripe/webhooks/payment_method_attached.rb +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 -1
- data/lib/pay/stripe/webhooks/subscription_deleted.rb +2 -1
- data/lib/pay/stripe/webhooks/subscription_renewing.rb +12 -2
- data/lib/pay/stripe.rb +6 -3
- data/lib/pay/version.rb +1 -1
- data/lib/pay/webhooks/delegator.rb +4 -0
- data/lib/pay/webhooks/process_job.rb +9 -0
- data/lib/pay/webhooks.rb +1 -0
- data/lib/pay.rb +7 -78
- data/lib/tasks/pay.rake +20 -0
- metadata +23 -36
- 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 -6
- data/db/migrate/20210309004259_add_data_to_pay_billable.rb +0 -10
- data/db/migrate/20210406215234_add_currency_to_pay_charges.rb +0 -5
- data/db/migrate/20210406215506_add_application_fee_to_pay_models.rb +0 -7
- data/lib/pay/billable/sync_email.rb +0 -40
- data/lib/pay/billable.rb +0 -172
@@ -0,0 +1,30 @@
|
|
1
|
+
module Pay
|
2
|
+
module Billable
|
3
|
+
module SyncCustomer
|
4
|
+
# Syncs customer details to the payment 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
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
after_update :enqeue_sync_email_job, if: :pay_should_sync_customer?
|
12
|
+
end
|
13
|
+
|
14
|
+
def pay_should_sync_customer?
|
15
|
+
try(:saved_change_to_email?)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def enqeue_sync_email_job
|
21
|
+
if saved_change_to_email?
|
22
|
+
# Queue job to update each payment processor for this customer
|
23
|
+
pay_customers.pluck(:id).each do |pay_customer_id|
|
24
|
+
CustomerSyncJob.perform_later(id)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,40 +1,42 @@
|
|
1
1
|
module Pay
|
2
2
|
module Braintree
|
3
3
|
class Billable
|
4
|
-
attr_reader :
|
4
|
+
attr_reader :pay_customer
|
5
5
|
|
6
6
|
delegate :processor_id,
|
7
7
|
:processor_id?,
|
8
8
|
:email,
|
9
9
|
:customer_name,
|
10
|
-
:
|
11
|
-
|
10
|
+
:payment_method_token,
|
11
|
+
:payment_method_token?,
|
12
|
+
to: :pay_customer
|
12
13
|
|
13
|
-
def initialize(
|
14
|
-
@
|
14
|
+
def initialize(pay_customer)
|
15
|
+
@pay_customer = pay_customer
|
15
16
|
end
|
16
17
|
|
17
|
-
#
|
18
|
+
# Retrieve the Braintree::Customer object
|
18
19
|
#
|
19
|
-
#
|
20
|
+
# - If no processor_id is present, creates a Customer.
|
21
|
+
# - When 'payment_method_token' is present, it will also set the default payment method
|
20
22
|
def customer
|
21
23
|
if processor_id?
|
22
24
|
customer = gateway.customer.find(processor_id)
|
23
|
-
|
25
|
+
|
26
|
+
if payment_method_token?
|
27
|
+
add_payment_method(payment_method_token, default: true)
|
28
|
+
pay_customer.payment_method_token = nil
|
29
|
+
end
|
30
|
+
|
24
31
|
customer
|
25
32
|
else
|
26
|
-
result = gateway.customer.create(
|
27
|
-
email: email,
|
28
|
-
first_name: try(:first_name),
|
29
|
-
last_name: try(:last_name),
|
30
|
-
payment_method_nonce: card_token
|
31
|
-
)
|
33
|
+
result = gateway.customer.create(email: email, first_name: try(:first_name), last_name: try(:last_name), payment_method_nonce: payment_method_token)
|
32
34
|
raise Pay::Braintree::Error, result unless result.success?
|
35
|
+
pay_customer.update!(processor_id: result.customer.id)
|
33
36
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
update_card_on_file result.customer.payment_methods.last
|
37
|
+
if payment_method_token?
|
38
|
+
save_payment_method(result.customer.payment_methods.last, default: true)
|
39
|
+
pay_customer.payment_method_token = nil
|
38
40
|
end
|
39
41
|
|
40
42
|
result.customer
|
@@ -45,14 +47,12 @@ module Pay
|
|
45
47
|
raise Pay::Braintree::Error, e
|
46
48
|
end
|
47
49
|
|
48
|
-
# Handles Billable#charge
|
49
|
-
#
|
50
|
-
# Returns a Pay::Charge
|
51
50
|
def charge(amount, options = {})
|
52
51
|
args = {
|
53
52
|
amount: amount.to_i / 100.0,
|
54
53
|
customer_id: customer.id,
|
55
|
-
options: {submit_for_settlement: true}
|
54
|
+
options: {submit_for_settlement: true},
|
55
|
+
custom_fields: options.delete(:metadata)
|
56
56
|
}.merge(options)
|
57
57
|
|
58
58
|
result = gateway.transaction.sale(args)
|
@@ -65,9 +65,6 @@ module Pay
|
|
65
65
|
raise Pay::Braintree::Error, e
|
66
66
|
end
|
67
67
|
|
68
|
-
# Handles Billable#subscribe
|
69
|
-
#
|
70
|
-
# Returns Pay::Subscription
|
71
68
|
def subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, **options)
|
72
69
|
token = customer.payment_methods.find(&:default?).try(:token)
|
73
70
|
raise Pay::Error, "Customer has no default payment method" if token.nil?
|
@@ -77,6 +74,7 @@ module Pay
|
|
77
74
|
options.merge!(trial_period: true, trial_duration: trial_period_days, trial_duration_unit: :day)
|
78
75
|
end
|
79
76
|
|
77
|
+
metadata = options.delete(:metadata)
|
80
78
|
subscription_options = options.merge(
|
81
79
|
payment_method_token: token,
|
82
80
|
plan_id: plan
|
@@ -85,32 +83,44 @@ module Pay
|
|
85
83
|
result = gateway.subscription.create(subscription_options)
|
86
84
|
raise Pay::Braintree::Error, result unless result.success?
|
87
85
|
|
88
|
-
|
86
|
+
pay_customer.subscriptions.create!(
|
87
|
+
name: name,
|
88
|
+
processor_id: result.subscription.id,
|
89
|
+
processor_plan: plan,
|
90
|
+
status: :active,
|
91
|
+
trial_ends_at: trial_end_date(result.subscription),
|
92
|
+
ends_at: nil,
|
93
|
+
metadata: metadata
|
94
|
+
)
|
89
95
|
rescue ::Braintree::AuthorizationError => e
|
90
96
|
raise Pay::Braintree::AuthorizationError, e
|
91
97
|
rescue ::Braintree::BraintreeError => e
|
92
98
|
raise Pay::Braintree::Error, e
|
93
99
|
end
|
94
100
|
|
95
|
-
|
96
|
-
#
|
97
|
-
# Returns true if successful
|
98
|
-
def update_card(token)
|
101
|
+
def add_payment_method(token, default: false)
|
99
102
|
customer unless processor_id?
|
100
103
|
|
101
104
|
result = gateway.payment_method.create(
|
102
105
|
customer_id: processor_id,
|
103
106
|
payment_method_nonce: token,
|
104
107
|
options: {
|
105
|
-
make_default:
|
108
|
+
make_default: default,
|
106
109
|
verify_card: true
|
107
110
|
}
|
108
111
|
)
|
109
112
|
raise Pay::Braintree::Error, result unless result.success?
|
110
113
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
+
pay_payment_method = save_payment_method(result.payment_method, default: default)
|
115
|
+
|
116
|
+
# Update existing subscriptions to the new payment method
|
117
|
+
pay_customer.subscriptions.each do |subscription|
|
118
|
+
if subscription.active?
|
119
|
+
gateway.subscription.update(subscription.processor_id, {payment_method_token: token})
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
pay_payment_method
|
114
124
|
rescue ::Braintree::AuthorizationError => e
|
115
125
|
raise Pay::Braintree::AuthorizationError, e
|
116
126
|
rescue ::Braintree::BraintreeError => e
|
@@ -127,119 +137,132 @@ module Pay
|
|
127
137
|
subscription.first_billing_date.end_of_day
|
128
138
|
end
|
129
139
|
|
130
|
-
def update_subscriptions_to_payment_method(token)
|
131
|
-
billable.subscriptions.braintree.each do |subscription|
|
132
|
-
if subscription.active?
|
133
|
-
gateway.subscription.update(subscription.processor_id, {payment_method_token: token})
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
140
|
def processor_subscription(subscription_id, options = {})
|
139
141
|
gateway.subscription.find(subscription_id)
|
140
142
|
end
|
141
143
|
|
142
|
-
def braintree_invoice!(options = {})
|
143
|
-
# pass
|
144
|
-
end
|
145
|
-
|
146
|
-
def braintree_upcoming_invoice
|
147
|
-
# pass
|
148
|
-
end
|
149
|
-
|
150
144
|
def save_transaction(transaction)
|
151
145
|
attrs = card_details_for_braintree_transaction(transaction)
|
152
146
|
attrs[:amount] = transaction.amount.to_f * 100
|
147
|
+
attrs[:metadata] = transaction.custom_fields
|
148
|
+
attrs[:currency] = transaction.currency_iso_code
|
149
|
+
attrs[:application_fee_amount] = transaction.service_fee_amount
|
153
150
|
|
154
151
|
# Associate charge with subscription if we can
|
155
152
|
if transaction.subscription_id
|
156
|
-
|
153
|
+
pay_subscription = pay_customer.subscriptions.find_by(processor_id: transaction.subscription_id)
|
154
|
+
attrs[:subscription] = pay_subscription
|
155
|
+
attrs[:metadata] = pay_subscription.metadata
|
157
156
|
end
|
158
157
|
|
159
|
-
charge =
|
160
|
-
|
161
|
-
processor_id: transaction.id,
|
162
|
-
currency: transaction.currency_iso_code,
|
163
|
-
application_fee_amount: transaction.service_fee_amount
|
164
|
-
)
|
165
|
-
charge.update(attrs)
|
158
|
+
charge = pay_customer.charges.find_or_initialize_by(processor_id: transaction.id)
|
159
|
+
charge.update!(attrs)
|
166
160
|
charge
|
167
161
|
end
|
168
162
|
|
169
|
-
private
|
170
|
-
|
171
163
|
def gateway
|
172
164
|
Pay.braintree_gateway
|
173
165
|
end
|
174
166
|
|
175
|
-
def
|
176
|
-
case payment_method
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
167
|
+
def save_payment_method(payment_method, default:)
|
168
|
+
attributes = case payment_method
|
169
|
+
when ::Braintree::CreditCard, ::Braintree::ApplePayCard, ::Braintree::GooglePayCard, ::Braintree::SamsungPayCard, ::Braintree::VisaCheckoutCard
|
170
|
+
{
|
171
|
+
payment_method_type: :card,
|
172
|
+
brand: payment_method.card_type,
|
173
|
+
last4: payment_method.last_4,
|
174
|
+
exp_month: payment_method.expiration_month,
|
175
|
+
exp_year: payment_method.expiration_year
|
176
|
+
}
|
177
|
+
|
178
|
+
when ::Braintree::PayPalAccount
|
179
|
+
{
|
180
|
+
payment_method_type: :paypal,
|
181
|
+
brand: "PayPal",
|
182
|
+
email: payment_method.email
|
183
|
+
}
|
184
|
+
when ::Braintree::VenmoAccount
|
185
|
+
{
|
186
|
+
payment_method_type: :venmo,
|
187
|
+
brand: "Venmo",
|
188
|
+
username: payment_method.username
|
189
|
+
}
|
190
|
+
when ::Braintree::UsBankAccount
|
191
|
+
{
|
192
|
+
payment_method_type: "us_bank_account",
|
193
|
+
bank: payment_method.bank_name,
|
194
|
+
last4: payment_method.last_4
|
195
|
+
}
|
196
|
+
else
|
197
|
+
{
|
198
|
+
payment_method_type: payment_method.class.name.demodulize.underscore,
|
199
|
+
brand: payment_method.try(:card_type),
|
200
|
+
last4: payment_method.try(:last_4),
|
201
|
+
exp_month: payment_method.try(:expiration_month),
|
202
|
+
exp_year: payment_method.try(:expiration_year),
|
203
|
+
bank: payment_method.try(:bank_name),
|
204
|
+
username: payment_method.try(:username),
|
205
|
+
email: payment_method.try(:email)
|
206
|
+
}
|
190
207
|
end
|
191
208
|
|
192
|
-
|
193
|
-
|
209
|
+
pay_payment_method = pay_customer.payment_methods.where(processor_id: payment_method.token).first_or_initialize
|
210
|
+
|
211
|
+
pay_customer.payment_methods.update_all(default: false) if default
|
212
|
+
pay_payment_method.update!(attributes.merge(default: default))
|
213
|
+
|
214
|
+
# Reload the Rails association
|
215
|
+
pay_customer.reload_default_payment_method if default
|
216
|
+
|
217
|
+
pay_payment_method
|
194
218
|
end
|
195
219
|
|
196
220
|
def card_details_for_braintree_transaction(transaction)
|
197
221
|
case transaction.payment_instrument_type
|
198
|
-
when "credit_card", "
|
199
|
-
|
200
|
-
|
201
|
-
card_type: payment_method.card_type,
|
202
|
-
card_last4: payment_method.last_4,
|
203
|
-
card_exp_month: payment_method.expiration_month,
|
204
|
-
card_exp_year: payment_method.expiration_year
|
205
|
-
}
|
222
|
+
when "android_pay_card", "apple_pay_card", "credit_card", "google_pay_card", "samsung_pay_card", "visa_checkout_card"
|
223
|
+
# Lookup the attribute with the payment method details by name
|
224
|
+
attribute_name = transaction.payment_instrument_type
|
206
225
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
226
|
+
# The attribute name for Apple and Google Pay don't include _card for some reason
|
227
|
+
if ["apple_pay_card", "google_pay_card"].include?(transaction.payment_instrument_type)
|
228
|
+
attribute_name = attribute_name.split("_card").first
|
229
|
+
|
230
|
+
# Android Pay was renamed to Google Pay, but test nonces still use android_pay_card
|
231
|
+
elsif attribute_name == "android_pay_card"
|
232
|
+
attribute_name = "google_pay"
|
233
|
+
end
|
234
|
+
|
235
|
+
# Retrieve payment method details from transaction
|
236
|
+
payment_method = transaction.send("#{attribute_name}_details")
|
214
237
|
|
215
|
-
when "android_pay_card"
|
216
|
-
payment_method = transaction.android_pay_details
|
217
238
|
{
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
239
|
+
payment_method_type: :card,
|
240
|
+
brand: payment_method.card_type,
|
241
|
+
last4: payment_method.last_4,
|
242
|
+
exp_month: payment_method.expiration_month,
|
243
|
+
exp_year: payment_method.expiration_year
|
222
244
|
}
|
223
245
|
|
224
|
-
when "
|
246
|
+
when "paypal_account"
|
225
247
|
{
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
248
|
+
payment_method_type: :paypal,
|
249
|
+
brand: "PayPal",
|
250
|
+
last4: transaction.paypal_details.payer_email,
|
251
|
+
exp_month: nil,
|
252
|
+
exp_year: nil
|
230
253
|
}
|
231
254
|
|
232
|
-
when "
|
233
|
-
payment_method = transaction.apple_pay_details
|
255
|
+
when "venmo_account"
|
234
256
|
{
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
257
|
+
payment_method_type: :venmo,
|
258
|
+
brand: "Venmo",
|
259
|
+
last4: transaction.venmo_account_details.username,
|
260
|
+
exp_month: nil,
|
261
|
+
exp_year: nil
|
239
262
|
}
|
240
263
|
|
241
264
|
else
|
242
|
-
{}
|
265
|
+
{payment_method_type: "unknown"}
|
243
266
|
end
|
244
267
|
end
|
245
268
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Pay
|
2
|
+
module Braintree
|
3
|
+
class PaymentMethod
|
4
|
+
attr_reader :pay_payment_method
|
5
|
+
|
6
|
+
delegate :customer, :processor_id, to: :pay_payment_method
|
7
|
+
|
8
|
+
def self.sync(id, object: nil, try: 0, retries: 1)
|
9
|
+
object ||= gateway.payment_method.find(id)
|
10
|
+
|
11
|
+
pay_customer = Pay::Customer.find_by(processor: :braintree, processor_id: object.customer_id)
|
12
|
+
return unless pay_customer
|
13
|
+
|
14
|
+
pay_customer.save_payment_method(object, default: object.default?)
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(pay_payment_method)
|
18
|
+
@pay_payment_method = pay_payment_method
|
19
|
+
end
|
20
|
+
|
21
|
+
# Sets payment method as default on Stripe
|
22
|
+
def make_default!
|
23
|
+
result = gateway.customer.update(customer.processor_id, default_payment_method_token: processor_id)
|
24
|
+
raise Pay::Braintree::Error, result unless result.success?
|
25
|
+
result.success?
|
26
|
+
end
|
27
|
+
|
28
|
+
# Remove payment method
|
29
|
+
def detach
|
30
|
+
result = gateway.payment_method.delete(processor_id)
|
31
|
+
raise Pay::Braintree::Error, result unless result.success?
|
32
|
+
result.success?
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def gateway
|
38
|
+
Pay.braintree_gateway
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -4,11 +4,11 @@ module Pay
|
|
4
4
|
attr_reader :pay_subscription
|
5
5
|
|
6
6
|
delegate :active?,
|
7
|
+
:customer,
|
7
8
|
:canceled?,
|
8
9
|
:ends_at,
|
9
10
|
:name,
|
10
11
|
:on_trial?,
|
11
|
-
:owner,
|
12
12
|
:processor_id,
|
13
13
|
:processor_plan,
|
14
14
|
:processor_subscription,
|
@@ -45,13 +45,13 @@ module Pay
|
|
45
45
|
|
46
46
|
def cancel_now!
|
47
47
|
gateway.subscription.cancel(processor_subscription.id)
|
48
|
-
pay_subscription.update(status: :canceled, ends_at: Time.
|
48
|
+
pay_subscription.update(status: :canceled, ends_at: Time.current)
|
49
49
|
rescue ::Braintree::BraintreeError => e
|
50
50
|
raise Pay::Braintree::Error, e
|
51
51
|
end
|
52
52
|
|
53
53
|
def on_grace_period?
|
54
|
-
canceled? && Time.
|
54
|
+
canceled? && Time.current < ends_at
|
55
55
|
end
|
56
56
|
|
57
57
|
def paused?
|
@@ -70,7 +70,7 @@ module Pay
|
|
70
70
|
if canceled? && on_trial?
|
71
71
|
duration = trial_ends_at.to_date - Date.today
|
72
72
|
|
73
|
-
|
73
|
+
customer.subscribe(
|
74
74
|
name: name,
|
75
75
|
plan: processor_plan,
|
76
76
|
trial_period: true,
|
@@ -92,13 +92,15 @@ module Pay
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def swap(plan)
|
95
|
+
raise ArgumentError, "plan must be a string" unless plan.is_a?(String)
|
96
|
+
|
95
97
|
if on_grace_period? && processor_plan == plan
|
96
98
|
resume
|
97
99
|
return
|
98
100
|
end
|
99
101
|
|
100
102
|
unless active?
|
101
|
-
|
103
|
+
customer.subscribe(name: name, plan: plan, trial_period: false)
|
102
104
|
return
|
103
105
|
end
|
104
106
|
|
@@ -120,12 +122,7 @@ module Pay
|
|
120
122
|
prorate_charges: prorate?
|
121
123
|
}
|
122
124
|
})
|
123
|
-
|
124
|
-
if result.success?
|
125
|
-
pay_subscription.update(status: :active, processor_plan: braintree_plan.id, ends_at: nil)
|
126
|
-
else
|
127
|
-
raise Error, "Braintree failed to swap plans: #{result.message}"
|
128
|
-
end
|
125
|
+
raise Error, "Braintree failed to swap plans: #{result.message}" unless result.success?
|
129
126
|
rescue ::Braintree::BraintreeError => e
|
130
127
|
raise Pay::Braintree::Error, e
|
131
128
|
end
|
@@ -205,7 +202,7 @@ module Pay
|
|
205
202
|
|
206
203
|
cancel_now!
|
207
204
|
|
208
|
-
|
205
|
+
customer.subscribe(**options.merge(name: name, plan: plan.id))
|
209
206
|
end
|
210
207
|
end
|
211
208
|
end
|