|
| 1 | +defmodule CodeCorps.StripeService.WebhookProcessing.EventHandler do |
| 2 | + alias CodeCorps.{StripeEvent, Repo} |
| 3 | + alias CodeCorps.StripeService.Adapters.StripeEventAdapter |
| 4 | + alias CodeCorps.StripeService.WebhookProcessing.{ |
| 5 | + ConnectEventHandler, IgnoredEventHandler, PlatformEventHandler |
| 6 | + } |
| 7 | + |
| 8 | + def handle(%Stripe.Event{type: type} = api_event, handler) do |
| 9 | + with {:ok, endpoint} <- infer_endpoint_from_handler(handler), |
| 10 | + {:ok, %StripeEvent{} = local_event} <- find_or_create_event(api_event, endpoint) |
| 11 | + do |
| 12 | + case IgnoredEventHandler.should_handle?(type) do |
| 13 | + true -> call_ignored_handler(local_event) |
| 14 | + false -> call_handler(api_event, local_event, handler) |
| 15 | + end |
| 16 | + else |
| 17 | + failure -> failure |
| 18 | + end |
| 19 | + end |
| 20 | + |
| 21 | + defp infer_endpoint_from_handler(ConnectEventHandler), do: {:ok, "connect"} |
| 22 | + defp infer_endpoint_from_handler(PlatformEventHandler), do: {:ok, "platform"} |
| 23 | + |
| 24 | + defp find_or_create_event(%Stripe.Event{} = api_event, endpoint) do |
| 25 | + case find_event(api_event.id) do |
| 26 | + %StripeEvent{status: "processing"} -> {:error, :already_processing} |
| 27 | + %StripeEvent{} = local_event -> {:ok, local_event} |
| 28 | + nil -> create_event(api_event, endpoint) |
| 29 | + end |
| 30 | + end |
| 31 | + |
| 32 | + defp find_event(id_from_stripe) do |
| 33 | + Repo.get_by(StripeEvent, id_from_stripe: id_from_stripe) |
| 34 | + end |
| 35 | + |
| 36 | + defp create_event(%Stripe.Event{} = api_event, endpoint) do |
| 37 | + with {:ok, params} <- StripeEventAdapter.to_params(api_event, %{"endpoint" => endpoint}) do |
| 38 | + %StripeEvent{} |> StripeEvent.create_changeset(params) |> Repo.insert |
| 39 | + end |
| 40 | + end |
| 41 | + |
| 42 | + defp call_ignored_handler(local_event), do: IgnoredEventHandler.handle(local_event) |
| 43 | + |
| 44 | + defp call_handler(api_event, local_event, handler) do |
| 45 | + # results are multiple, so we convert the tuple to list for easier matching |
| 46 | + case api_event |> handler.handle_event |> Tuple.to_list do |
| 47 | + [:ok, :unhandled_event] -> local_event |> set_unhandled |
| 48 | + [:ok | _results] -> local_event |> set_processed |
| 49 | + [:error | _error] -> local_event |> set_errored |
| 50 | + end |
| 51 | + end |
| 52 | + |
| 53 | + defp set_errored(%StripeEvent{} = local_event) do |
| 54 | + local_event |> StripeEvent.update_changeset(%{status: "errored"}) |> Repo.update |
| 55 | + end |
| 56 | + |
| 57 | + defp set_processed(%StripeEvent{} = local_event) do |
| 58 | + local_event |> StripeEvent.update_changeset(%{status: "processed"}) |> Repo.update |
| 59 | + end |
| 60 | + |
| 61 | + defp set_unhandled(%StripeEvent{} = local_event) do |
| 62 | + local_event |> StripeEvent.update_changeset(%{status: "unhandled"}) |> Repo.update |
| 63 | + end |
| 64 | +end |
0 commit comments