From af9026d68ed0c86d993169c28c607472cacfb287 Mon Sep 17 00:00:00 2001 From: Nick Kezhaya Date: Fri, 18 Oct 2019 17:58:25 -0500 Subject: [PATCH] Automatic confirm/capture --- .../api/operations/payment_intent.ex | 24 +++++++++++++---- lib/stripe_mock/api/payment_intent.ex | 26 ++++++++++++++++--- .../payment_intent_controller_test.exs | 12 +++++---- test/test_helper.exs | 10 +++++-- 4 files changed, 56 insertions(+), 16 deletions(-) diff --git a/lib/stripe_mock/api/operations/payment_intent.ex b/lib/stripe_mock/api/operations/payment_intent.ex index 138399d..613d7a0 100644 --- a/lib/stripe_mock/api/operations/payment_intent.ex +++ b/lib/stripe_mock/api/operations/payment_intent.ex @@ -24,6 +24,23 @@ defmodule StripeMock.API.Operations.PaymentIntent do %PaymentIntent{} |> PaymentIntent.changeset(attrs) |> Repo.insert() + |> case do + {:ok, payment_intent} = result -> + if payment_intent.confirmation_method == "automatic" do + {:ok, payment_intent} = confirm_payment_intent(payment_intent) + + if payment_intent.capture_method == "automatic" do + {:ok, _payment_intent} = capture_payment_intent(payment_intent) + end + + get_payment_intent(payment_intent.id) + else + result + end + + error -> + error + end |> do_preloads() end @@ -37,10 +54,7 @@ defmodule StripeMock.API.Operations.PaymentIntent do def confirm_payment_intent(%PaymentIntent{} = payment_intent) do Multi.new() |> Multi.insert(:charge, Charge.capture_changeset(%Charge{}, payment_intent)) - |> Multi.update( - :payment_intent, - PaymentIntent.status_changeset(payment_intent, "requires_action") - ) + |> Multi.update(:payment_intent, PaymentIntent.confirm_changeset(payment_intent)) |> Repo.transaction() |> case do {:ok, %{payment_intent: payment_intent}} -> {:ok, payment_intent} @@ -54,7 +68,7 @@ defmodule StripeMock.API.Operations.PaymentIntent do Multi.new() |> Multi.update_all(:charge, query, set: [captured: true]) - |> Multi.update(:payment_intent, PaymentIntent.status_changeset(payment_intent, "succeeded")) + |> Multi.update(:payment_intent, PaymentIntent.capture_changeset(payment_intent)) |> Repo.transaction() |> case do {:ok, %{payment_intent: payment_intent}} -> {:ok, payment_intent} diff --git a/lib/stripe_mock/api/payment_intent.ex b/lib/stripe_mock/api/payment_intent.ex index a79d338..35623ff 100644 --- a/lib/stripe_mock/api/payment_intent.ex +++ b/lib/stripe_mock/api/payment_intent.ex @@ -9,7 +9,7 @@ defmodule StripeMock.API.PaymentIntent do field :currency, :string field :payment_method_types, {:array, :string}, default: ["card"] field :statement_descriptor, :string - field :status, :string + field :status, :string, default: "requires_confirmation" field :transfer_data, :map field :transfer_group, :string @@ -37,20 +37,38 @@ defmodule StripeMock.API.PaymentIntent do :transfer_data, :transfer_group ]) - |> validate_inclusion(:capture_method, ~w(automatic manual)) |> validate_inclusion(:confirmation_method, ~w(automatic manual)) + |> validate_inclusion(:capture_method, ~w(automatic manual)) |> set_payment_method() |> validate_required([:payment_method_id]) |> put_common_fields() end @doc false - def status_changeset(payment_intent, status) do + def confirm_changeset(payment_intent) do + payment_intent + |> change() + |> ensure_status("requires_confirmation") + |> put_change(:status, "requires_capture") + |> put_common_fields() + end + + @doc false + def capture_changeset(payment_intent) do payment_intent - |> change(%{status: status}) + |> change() + |> ensure_status("requires_capture") + |> put_change(:status, "succeeded") |> put_common_fields() end + defp ensure_status(changeset, status) do + case get_field(changeset, :status) do + ^status -> changeset + s -> add_error(changeset, :status, "should be '#{status}', is '#{s}'") + end + end + defp set_payment_method(changeset) do case get_change(changeset, :payment_method_id) do nil -> diff --git a/test/stripe_mock_web/controllers/payment_intent_controller_test.exs b/test/stripe_mock_web/controllers/payment_intent_controller_test.exs index 9e8a28d..bf508bc 100644 --- a/test/stripe_mock_web/controllers/payment_intent_controller_test.exs +++ b/test/stripe_mock_web/controllers/payment_intent_controller_test.exs @@ -93,17 +93,19 @@ defmodule StripeMockWeb.PaymentIntentControllerTest do assert json_response(conn, 422)["errors"] != %{} end + end + + describe "manual update" do + setup [:create_manual_payment_intent] test "confirms payment intent", %{conn: conn, payment_intent: payment_intent} do conn = post(conn, Routes.payment_intent_path(conn, :confirm, payment_intent), %{}) - - assert %{"status" => "requires_action"} = json_response(conn, 200) + assert %{"status" => "requires_capture"} = json_response(conn, 200) end test "captures payment intent", %{conn: conn, payment_intent: payment_intent} do - conn - |> post(Routes.payment_intent_path(conn, :confirm, payment_intent), %{}) - |> json_response(:ok) + conn = post(conn, Routes.payment_intent_path(conn, :confirm, payment_intent), %{}) + assert %{"status" => "requires_capture"} = json_response(conn, 200) conn = post(conn, Routes.payment_intent_path(conn, :capture, payment_intent), %{}) diff --git a/test/test_helper.exs b/test/test_helper.exs index dc7e773..a629cd7 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -49,7 +49,7 @@ defmodule StripeMock.TestHelper do [payment_intent: create_payment_intent(customer)] end - def create_payment_intent(%API.Customer{} = customer) do + def create_payment_intent(%API.Customer{} = customer, manual? \\ false) do [token: token] = create_token() {:ok, charge} = @@ -57,12 +57,18 @@ defmodule StripeMock.TestHelper do amount: 5000, currency: "some currency", customer_id: customer.id, - payment_method_id: token.id + payment_method_id: token.id, + confirmation_method: if(manual?, do: "manual", else: "automatic"), + capture_method: if(manual?, do: "manual", else: "automatic") }) charge end + def create_manual_payment_intent(%{customer: customer}) do + [payment_intent: create_payment_intent(customer, true)] + end + def create_refund(%{charge: charge}) do params = %{ amount: 5000,