Paid signups/registration

What would you guys think is the best way to handle a signup form that includes making a payment?

I was thinking of a Registration.changest where the module looks like

defmodule App.Store.Registration do
  use Ecto.Schema

  import Ecto.Changeset
  import App.Repo, only: [preload: 1]

  alias App.Accounts.User

  schema "registrations" do
    belongs_to :customer, App.Store.Customer
    belongs_to :purchase, App.Store.Purchase
    belongs_to :user, App.Accounts.User
    timestamps()
  end

  def register_changeset(%__MODULE__{} = registration, attrs) do
    registration
    |> preload([:customer, :purchase])
    |> cast(attrs)
    |> cast_assoc(:customer, required: true)
    |> cast_assoc(:purchase, required: true)
  end

  def complete_changeset(%__MODULE__{} = registration, attrs) do
    registration
    |> preload(:user)
    |> cast(attrs)
    |> cast_assoc(:user, required: true, with: &User.register_changeset/2)
  end
end

Where you first complete a form that corresponds to register_changeset and then once that is done and the payment is processed show a form for the complete_changeset to create the user account w/ password, etc.

So, for the payment part, I was thinking App.Customer would have a payment_method field which would be an embed, or assoc or something that included a stripe token that is generated as part of filling out the signup form payment details.

Does this seem like a good way to do it? If not, what would you do?

Where would you guys put the payment processing step?

If the payment failed, I’d like to return a changeset error ideally, since then the response would all be the same no matter the error, but then we have the issue of a possible succeeding payment but an invalid changeset overall. therefore we could have a resubmission and possible double-charge.

I’d do it similar to a double-opt-in registration process where a client has to click those links in an email. But instead of clicking that link he has to pay the bill.

  1. After submitting the registration form create the user, but have a flag tagging it as inactive
  2. Send email containing payment information/send them to the payment processor of your choice
  3. Await confirmation of payment (via processor or by manually checking your bank-account)
  4. Remove the flag that tags inactive and therefore have it active now.