Files
ubicloud/migrate/20230810_add_billing_info.rb
Enes Cakir 6dbf0d1d39 Introduce billing details
We need to get billing information from user to charge them at end of the
month.

We decided to use Stripe as payment provider. It has lots of features.
We can use low level APIs or some predefined UI from Stripe. We can keep
some of the information on our database too or keep all data at Stripe
and just keep Stripe identifier. I tried to find balance between them.
Then decided to keep all personal data on Stripe and we only keep Stripe
resource identifiers. It helps us to avoid GDPR issues. Also it helps to
keep service secure, it prevent to leak confidential data in dump or
logs.

Stripe has two resources: customer and payment method. We need to save
credit card information of users before they create any resource. Then
we will charge them using these information.

We have new two models: BillingInfo and PaymentMethod. BillingInfo is
corresponding for customer on Stripe side. We keep stripe_id for both
objects.

Each project has a BillingInfo. BillingInfo can be shared by projects.
So user can associate same BillingInfo with multiple project. But
currently I designed UI and models as each BillingInfo attached to
single project. We can relax it based on customer feedbacks.

BillingInfo has invoice details such as name, address, country etc. at
Stripe. PaymentMethod has metadata about credit card at Stripe.
PaymentMethod has order column, users can set a priority for payment
methods. We can try to charge them in order.

We collect initial BillingInfo and PaymentMethod details on Stripe's UI.
We tried to decrease friction for new users. We create Checkout session
with setup mode. It's Stripe's UI for saving customer and credit card
details. Stripe returns success url with session id.

After creation we use our UI to update customer details. Stripe's
Checkout session doesn't support updating customer details.

If STRIPE_SECRET_KEY isn't provided, billing is disabled.
2023-08-11 11:33:06 +03:00

22 lines
633 B
Ruby

# frozen_string_literal: true
Sequel.migration do
change do
create_table(:billing_info) do
column :id, :uuid, primary_key: true, default: nil
column :stripe_id, :text, collate: '"C"', null: false, unique: true
end
create_table(:payment_method) do
column :id, :uuid, primary_key: true, default: nil
column :stripe_id, :text, collate: '"C"', null: false, unique: true
column :order, Integer
foreign_key :billing_info_id, :billing_info, type: :uuid
end
alter_table(:project) do
add_foreign_key :billing_info_id, :billing_info, type: :uuid, null: true
end
end
end