diff --git a/lib/stripe_mock/api.ex b/lib/stripe_mock/api.ex index 7bf1b98..f601d0b 100644 --- a/lib/stripe_mock/api.ex +++ b/lib/stripe_mock/api.ex @@ -26,6 +26,15 @@ defmodule StripeMock.API do # defdelegate attach_source(source, customer), to: Ops.Source # defdelegate detach_source(source, customer), to: Ops.Source + # PaymentIntents + defdelegate list_payment_intents(), to: Ops.PaymentIntent + defdelegate get_payment_intent(id), to: Ops.PaymentIntent + defdelegate get_payment_intent!(id), to: Ops.PaymentIntent + defdelegate create_payment_intent(attrs \\ %{}), to: Ops.PaymentIntent + defdelegate update_payment_intent(payment_intent, attrs \\ %{}), to: Ops.PaymentIntent + defdelegate confirm_payment_intent(payment_intent), to: Ops.PaymentIntent + defdelegate capture_payment_intent(payment_intent), to: Ops.PaymentIntent + # Charges defdelegate list_charges(), to: Ops.Charge defdelegate get_charge(id), to: Ops.Charge diff --git a/lib/stripe_mock/api/charge.ex b/lib/stripe_mock/api/charge.ex index 0dc45f8..427e095 100644 --- a/lib/stripe_mock/api/charge.ex +++ b/lib/stripe_mock/api/charge.ex @@ -47,6 +47,10 @@ defmodule StripeMock.API.Charge do |> validate_required([:amount, :currency]) end + @doc false + def capture_changeset(payment_intent, charge) do + end + defp set_customer_and_source(changeset) do customer = with customer_id when not is_nil(customer_id) <- get_field(changeset, :customer_id) do diff --git a/lib/stripe_mock/api/operations/payment_intent.ex b/lib/stripe_mock/api/operations/payment_intent.ex new file mode 100644 index 0000000..01bca31 --- /dev/null +++ b/lib/stripe_mock/api/operations/payment_intent.ex @@ -0,0 +1,40 @@ +defmodule StripeMock.API.Operations.PaymentIntent do + alias StripeMock.Repo + alias StripeMock.API.{Charge, PaymentIntent} + + def list_payment_intents() do + Repo.all(PaymentIntent) + end + + def get_payment_intent(id), do: Repo.fetch(PaymentIntent, id) + def get_payment_intent!(id), do: Repo.get!(PaymentIntent, id) + + def create_payment_intent(attrs \\ %{}) do + %PaymentIntent{} + |> PaymentIntent.changeset(attrs) + |> Repo.insert() + end + + def update_payment_intent(%PaymentIntent{} = payment_intent, attrs) do + payment_intent + |> PaymentIntent.changeset(attrs) + |> Repo.update() + end + + def confirm_payment_intent(%PaymentIntent{} = payment_intent) do + payment_intent + |> PaymentIntent.status_changeset("requires_capture") + |> Repo.update() + end + + def capture_payment_intent(%PaymentIntent{} = payment_intent) do + charge = + %Charge{} + |> Charge.payment_intent_changeset(payment_intent) + |> Repo.insert!() + + payment_intent + |> PaymentIntent.capture_changeset(charge) + |> Repo.update!() + end +end diff --git a/lib/stripe_mock/api/payment_intent.ex b/lib/stripe_mock/api/payment_intent.ex new file mode 100644 index 0000000..610648c --- /dev/null +++ b/lib/stripe_mock/api/payment_intent.ex @@ -0,0 +1,32 @@ +defmodule StripeMock.API.PaymentIntent do + use StripeMock.Schema + + @primary_key {:id, :binary_id, autogenerate: false} + schema "payment_intents" do + field :amount, :integer + field :capture, :boolean, default: false + field :capture_method, :string + field :confirmation_method, :string + field :currency, :string + field :description, :string + field :metadata, StripeMock.Type.Metadata, default: %{} + field :payment_method_types, {:array, :string}, default: ["card"] + field :statement_descriptor, :string + field :transfer_group, :string + end + + @doc false + def changeset(payment_intent, attrs) do + payment_intent + |> cast(attrs, [:amount, :confirm, :confirmation_method, :currency]) + end + + @doc false + def status_changeset(payment_intent, status) do + change(payment_intent, %{status: status}) + end + + @doc false + def capture_changeset(payment_intent, charge) do + end +end diff --git a/lib/stripe_mock/repo.ex b/lib/stripe_mock/repo.ex index 322e410..843d2d9 100644 --- a/lib/stripe_mock/repo.ex +++ b/lib/stripe_mock/repo.ex @@ -191,12 +191,14 @@ defmodule StripeMock.Repo do def type(API.Card), do: :card def type(API.Charge), do: :charge def type(API.Customer), do: :customer + def type(API.PaymentIntent), do: :payment_intent def type(API.Refund), do: :refund def type(API.Token), do: :token def prefix(%API.Card{}), do: "card" def prefix(%API.Charge{}), do: "ch" def prefix(%API.Customer{}), do: "cus" + def prefix(%API.PaymentIntent{}), do: "pi" def prefix(%API.Refund{}), do: "re" def prefix(%API.Token{}), do: "tok" end diff --git a/lib/stripe_mock_web/controllers/payment_intent_controller.ex b/lib/stripe_mock_web/controllers/payment_intent_controller.ex new file mode 100644 index 0000000..70ffff2 --- /dev/null +++ b/lib/stripe_mock_web/controllers/payment_intent_controller.ex @@ -0,0 +1,53 @@ +defmodule StripeMockWeb.PaymentIntentController do + use StripeMockWeb, :controller + + alias StripeMock.API + alias StripeMock.API.PaymentIntent + + action_fallback StripeMockWeb.FallbackController + + def index(conn, params) do + page = API.list_payment_intents() |> paginate(params) + render(conn, "index.json", page: page) + end + + def create(conn, payment_intent_params) do + with {:ok, payment_intent} <- API.create_payment_intent(payment_intent_params) do + conn + |> put_status(:created) + |> put_resp_header("location", Routes.payment_intent_path(conn, :show, payment_intent)) + |> render("show.json", payment_intent: payment_intent) + end + end + + def show(conn, %{"id" => id}) do + with {:ok, payment_intent} <- API.get_payment_intent(id) do + render(conn, "show.json", payment_intent: payment_intent) + end + end + + def update(conn, %{"id" => id} = payment_intent_params) do + payment_intent = API.get_payment_intent!(id) + + with {:ok, payment_intent} <- + API.update_payment_intent(payment_intent, payment_intent_params) do + render(conn, "show.json", payment_intent: payment_intent) + end + end + + def confirm(conn, %{"id" => id} = payment_intent_params) do + payment_intent = API.get_payment_intent!(id) + + with {:ok, payment_intent} <- API.confirm_payment_intent(payment_intent) do + render(conn, "show.json", payment_intent: payment_intent) + end + end + + def capture(conn, %{"id" => id} = payment_intent_params) do + payment_intent = API.get_payment_intent!(id) + + with {:ok, payment_intent} <- API.capture_payment_intent(payment_intent) do + render(conn, "show.json", payment_intent: payment_intent) + end + end +end diff --git a/lib/stripe_mock_web/router.ex b/lib/stripe_mock_web/router.ex index 13f2d9f..52ba46a 100644 --- a/lib/stripe_mock_web/router.ex +++ b/lib/stripe_mock_web/router.ex @@ -16,6 +16,7 @@ defmodule StripeMockWeb.Router do resources "/charges", ChargeController, except: [:delete] resources "/refunds", RefundController, except: [:delete] + resources "/payment_intents", PaymentIntentController, except: [:delete] resources "/sources", SourceController, only: [:show] resources "/tokens", TokenController, only: [:create, :show]