Request: Some more documentation about how billing works
Hello 👋
I was wondering if it was possible to have some more documentation about how the billing system works, especially edge cases. Where should we rely on the payment processor and what does and doesn't the Pay gem do?
Some questions I have (all in context of Stripe, but could be generic)
- What happens if a payment fails? How does that reflect in the subscription?
- Is Stripe considered the single source of truth? E.g. if I change the Plan, change the next billing date, or cancel a subscription in the Stripe UI, will this mess up the jumpstart app or will jumpstart recognise these changes and execute them?
- In the SCA description it says Jumpstart will send emails for further authentication. I'm guessing this means we need to turn those emails off in Stripe, so the user does not receive two emails?
Apologies if this is described somewhere and I missed it.
I was wondering if it was possible to have some more documentation about how the billing system works, especially edge cases. Where should we rely on the payment processor and what does and doesn't the Pay gem do?
Some questions I have (all in context of Stripe, but could be generic)
- What happens if a payment fails? How does that reflect in the subscription?
- Is Stripe considered the single source of truth? E.g. if I change the Plan, change the next billing date, or cancel a subscription in the Stripe UI, will this mess up the jumpstart app or will jumpstart recognise these changes and execute them?
- In the SCA description it says Jumpstart will send emails for further authentication. I'm guessing this means we need to turn those emails off in Stripe, so the user does not receive two emails?
Apologies if this is described somewhere and I missed it.
I think the first question can be easily tested as Jim suggested. "I don't know what I don't know ...but I know how I can change that".
however the second and third questions are legitimately the sort of thing one would prefer to hear from someone with experience, since they depend on "I don't know what I don't know ... and I don't think I know how to change that"
however the second and third questions are legitimately the sort of thing one would prefer to hear from someone with experience, since they depend on "I don't know what I don't know ... and I don't think I know how to change that"
What happens if a payment fails? How does that reflect in the subscription?
Stripe marks it as "past_due" and retries payments a few times. If the card doesn't get updated and the charges continue to fail, the subscription is automatically cancelled.
Is Stripe considered the single source of truth? E.g. if I change the Plan, change the next billing date, or cancel a subscription in the Stripe UI, will this mess up the jumpstart app or will jumpstart recognise these changes and execute them?
Yep, you'll just want to make sure any updates are synced via webhook to the Pay::Subscription model. We already save most of them automatically. All that's done using the Pay gem.
In the SCA description it says Jumpstart will send emails for further authentication. I'm guessing this means we need to turn those emails off in Stripe, so the user does not receive two emails?
Yep, or turn off the emails in Pay. Up to you.
I observed a different error today:
KeyError in ChargesController#show
key not found: :details
Debugging this shows that the @charge variable is set and there is a receipt filename, but there is no @charge.receipt value present:
↳ app/controllers/charges_controller.rb:31:in `set_charge'
[2, 11] in ~/ritual-moon/app/controllers/charges_controller.rb
2| before_action :authenticate_user!
3| before_action :set_charge
4|
5| def show
6| respond_to do |format|
=> 7| debugger
8| format.pdf {
9| send_data @charge.receipt,
10| filename: @charge.filename,
11| type: "application/pdf",
=>#0 block {|format=#<ActionController::MimeResponds::Collec...|} in show at ~/ritual-moon/app/controllers/charges_controller.rb:7
#1 ActionController::MimeResponds#respond_to(mimes=[]) at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2.2/lib/action_controller/metal/mime_responds.rb:205
# and 80 frames (use `bt' command for all frames)
(rdbg) @charge.receipt # ruby
Pay::Customer Load (0.4ms) SELECT "pay_customers".* FROM "pay_customers" WHERE "pay_customers"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
↳ (rdbg)//Users/marknelson/ritual-moon/app/controllers/charges_controller.rb:1:in `block in show'
Account Load (0.4ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT $2 [["id", 5], ["LIMIT", 1]]
↳ (rdbg)//Users/marknelson/ritual-moon/app/controllers/charges_controller.rb:1:in `block in show'
AccountUser Load (0.5ms) SELECT "account_users".* FROM "account_users" WHERE "account_users"."account_id" = $1 ORDER BY "account_users"."created_at" ASC LIMIT $2 [["account_id", 5], ["LIMIT", 1]]
↳ app/models/account.rb:48:in `email'
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 [["id", 5]]
↳ app/models/account.rb:48:in `email'
eval error: key not found: :details
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/receipts-2.0.0/lib/receipts/base.rb:23:in `fetch'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/receipts-2.0.0/lib/receipts/base.rb:23:in `generate_from'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/receipts-2.0.0/lib/receipts/base.rb:15:in `initialize'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/pay-3.0.24/lib/pay/receipts.rb:39:in `new'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/pay-3.0.24/lib/pay/receipts.rb:39:in `receipt_pdf'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/pay-3.0.24/lib/pay/receipts.rb:13:in `receipt'
(rdbg)//Users/marknelson/ritual-moon/app/controllers/charges_controller.rb:1:in `block in show'
nil
(rdbg) @charge # ruby
#<Pay::Charge:0x0000000119f25bb0
id: 2,
processor_id: "ch_3KaWlOIjBtlieNXS19qmH53k",
amount: 700,
amount_refunded: 0,
created_at: Mon, 07 Mar 2022 10:57:34.000000000 CST +08:00,
updated_at: Mon, 07 Mar 2022 10:57:38.028238000 CST +08:00,
data:
{"brand"=>"Visa",
"last4"=>"1111",
"exp_year"=>"2023",
"exp_month"=>"7",
"payment_method_type"=>"card"},
application_fee_amount: nil,
currency: "usd",
metadata: {},
subscription_id: 2,
customer_id: 2>
(rdbg) @charge.filename # ruby
"receipt-2022-03-07.pdf"
(rdbg) @charge.receipt # ruby
CACHE AccountUser Load (0.0ms) SELECT "account_users".* FROM "account_users" WHERE "account_users"."account_id" = $1 ORDER BY "account_users"."created_at" ASC LIMIT $2 [["account_id", 5], ["LIMIT", 1]]
↳ app/models/account.rb:48:in `email'
CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 [["id", 5]]
↳ app/models/account.rb:48:in `email'
eval error: key not found: :details
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/receipts-2.0.0/lib/receipts/base.rb:23:in `fetch'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/receipts-2.0.0/lib/receipts/base.rb:23:in `generate_from'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/receipts-2.0.0/lib/receipts/base.rb:15:in `initialize'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/pay-3.0.24/lib/pay/receipts.rb:39:in `new'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/pay-3.0.24/lib/pay/receipts.rb:39:in `receipt_pdf'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/pay-3.0.24/lib/pay/receipts.rb:13:in `receipt'
(rdbg)//Users/marknelson/ritual-moon/app/controllers/charges_controller.rb:1:in `block in show'
nil
Debugging this shows that the @charge variable is set and there is a receipt filename, but there is no @charge.receipt value present:
↳ app/controllers/charges_controller.rb:31:in `set_charge'
[2, 11] in ~/ritual-moon/app/controllers/charges_controller.rb
2| before_action :authenticate_user!
3| before_action :set_charge
4|
5| def show
6| respond_to do |format|
=> 7| debugger
8| format.pdf {
9| send_data @charge.receipt,
10| filename: @charge.filename,
11| type: "application/pdf",
=>#0 block {|format=#<ActionController::MimeResponds::Collec...|} in show at ~/ritual-moon/app/controllers/charges_controller.rb:7
#1 ActionController::MimeResponds#respond_to(mimes=[]) at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2.2/lib/action_controller/metal/mime_responds.rb:205
# and 80 frames (use `bt' command for all frames)
(rdbg) @charge.receipt # ruby
Pay::Customer Load (0.4ms) SELECT "pay_customers".* FROM "pay_customers" WHERE "pay_customers"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
↳ (rdbg)//Users/marknelson/ritual-moon/app/controllers/charges_controller.rb:1:in `block in show'
Account Load (0.4ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT $2 [["id", 5], ["LIMIT", 1]]
↳ (rdbg)//Users/marknelson/ritual-moon/app/controllers/charges_controller.rb:1:in `block in show'
AccountUser Load (0.5ms) SELECT "account_users".* FROM "account_users" WHERE "account_users"."account_id" = $1 ORDER BY "account_users"."created_at" ASC LIMIT $2 [["account_id", 5], ["LIMIT", 1]]
↳ app/models/account.rb:48:in `email'
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 [["id", 5]]
↳ app/models/account.rb:48:in `email'
eval error: key not found: :details
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/receipts-2.0.0/lib/receipts/base.rb:23:in `fetch'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/receipts-2.0.0/lib/receipts/base.rb:23:in `generate_from'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/receipts-2.0.0/lib/receipts/base.rb:15:in `initialize'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/pay-3.0.24/lib/pay/receipts.rb:39:in `new'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/pay-3.0.24/lib/pay/receipts.rb:39:in `receipt_pdf'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/pay-3.0.24/lib/pay/receipts.rb:13:in `receipt'
(rdbg)//Users/marknelson/ritual-moon/app/controllers/charges_controller.rb:1:in `block in show'
nil
(rdbg) @charge # ruby
#<Pay::Charge:0x0000000119f25bb0
id: 2,
processor_id: "ch_3KaWlOIjBtlieNXS19qmH53k",
amount: 700,
amount_refunded: 0,
created_at: Mon, 07 Mar 2022 10:57:34.000000000 CST +08:00,
updated_at: Mon, 07 Mar 2022 10:57:38.028238000 CST +08:00,
data:
{"brand"=>"Visa",
"last4"=>"1111",
"exp_year"=>"2023",
"exp_month"=>"7",
"payment_method_type"=>"card"},
application_fee_amount: nil,
currency: "usd",
metadata: {},
subscription_id: 2,
customer_id: 2>
(rdbg) @charge.filename # ruby
"receipt-2022-03-07.pdf"
(rdbg) @charge.receipt # ruby
CACHE AccountUser Load (0.0ms) SELECT "account_users".* FROM "account_users" WHERE "account_users"."account_id" = $1 ORDER BY "account_users"."created_at" ASC LIMIT $2 [["account_id", 5], ["LIMIT", 1]]
↳ app/models/account.rb:48:in `email'
CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 [["id", 5]]
↳ app/models/account.rb:48:in `email'
eval error: key not found: :details
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/receipts-2.0.0/lib/receipts/base.rb:23:in `fetch'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/receipts-2.0.0/lib/receipts/base.rb:23:in `generate_from'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/receipts-2.0.0/lib/receipts/base.rb:15:in `initialize'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/pay-3.0.24/lib/pay/receipts.rb:39:in `new'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/pay-3.0.24/lib/pay/receipts.rb:39:in `receipt_pdf'
/Users/marknelson/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/pay-3.0.24/lib/pay/receipts.rb:13:in `receipt'
(rdbg)//Users/marknelson/ritual-moon/app/controllers/charges_controller.rb:1:in `block in show'
nil
Notifications
You’re not receiving notifications from this thread.