Files
ubicloud/model/billing_info.rb
Enes Cakir a8de712b1b Try to charge the latest payment method
The payment method has an `order` column. I intended to add this feature
initially to allow customers to prioritize their payment methods, so
they can select a primary and a backup option. However, we haven't added
it to the UI yet, so all `order` columns are currently nil.

When a payment fails, customers simply log in to the console and add a
new payment method while keeping the old one. When we try to charge the
invoice, we start with the oldest method, which probably isn't working
anymore. We should charge from the newest method to the oldest to reduce
our payment failure rate.
2025-03-29 09:49:33 +03:00

70 lines
2.1 KiB
Ruby

# frozen_string_literal: true
require_relative "../model"
require "stripe"
require "countries"
require "excon"
class BillingInfo < Sequel::Model
one_to_many :payment_methods, order: Sequel.desc(:created_at)
one_to_one :project
include ResourceMethods
def stripe_data
if (Stripe.api_key = Config.stripe_secret_key)
@stripe_data ||= begin
data = Stripe::Customer.retrieve(stripe_id)
address = data["address"]
{
"name" => data["name"],
"email" => data["email"],
"address" => [address["line1"], address["line2"]].compact.join(" "),
"country" => address["country"],
"city" => address["city"],
"state" => address["state"],
"postal_code" => address["postal_code"],
"tax_id" => data["metadata"]["tax_id"],
"company_name" => data["metadata"]["company_name"]
}
end
end
end
def country
ISO3166::Country.new(stripe_data["country"])
end
def after_destroy
if (Stripe.api_key = Config.stripe_secret_key)
Stripe::Customer.delete(stripe_id)
end
super
end
def validate_vat
response = Excon.get("https://ec.europa.eu/taxation_customs/vies/rest-api/ms/#{stripe_data["country"]}/vat/#{stripe_data["tax_id"]}", expects: 200)
status = JSON.parse(response.body)["userError"]
if status == "VALID"
true
elsif status == "INVALID" || status == "INVALID_INPUT"
false
else
fail "Unexpected response from VAT service: #{status}"
end
end
end
# Table: billing_info
# Columns:
# id | uuid | PRIMARY KEY
# stripe_id | text | NOT NULL
# created_at | timestamp with time zone | NOT NULL DEFAULT now()
# valid_vat | boolean |
# Indexes:
# billing_info_pkey | PRIMARY KEY btree (id)
# billing_info_stripe_id_key | UNIQUE btree (stripe_id)
# Referenced By:
# payment_method | payment_method_billing_info_id_fkey | (billing_info_id) REFERENCES billing_info(id)
# project | project_billing_info_id_fkey | (billing_info_id) REFERENCES billing_info(id)