lib/client.ex

defmodule Client do
  @secret_key Application.get_env(:checkout_sdk, :secret_key)

  def get(%{id: id}, url) do
    client()
    |> Tesla.get("#{url}/#{id}")
    |> handle_response()
  end

  def get(url_query, url) when is_binary(url_query) do
    client()
    |> Tesla.get("#{url}?#{url_query}")
    |> handle_response()
  end

  def post(body, url) do
    client()
    |> Tesla.post(url, body)
    |> handle_response()
  end

  def update(%{id: id} = body, url) do
    client()
    |> Tesla.patch("#{url}/#{id}", body)
    |> handle_response()
  end

  def delete(%{id: id}, url) do
    client()
    |> Tesla.delete("#{url}/#{id}")
    |> handle_response()
  end

  defp client do
    middleware = [
      {Tesla.Middleware.BaseUrl, "https://api.sandbox.checkout.com/"},
      Tesla.Middleware.JSON,
      {Tesla.Middleware.Headers,
       [{"Authorization", "Bearer " <> @secret_key}, {"Content-Type", "application/json"}]}
    ]

    Tesla.client(middleware)
  end

  defp handle_response({:ok, %Tesla.Env{status: 204}}), do: {:ok, "Successful"}

  defp handle_response({:ok, %Tesla.Env{status: status, body: body}}) when status in 200..299,
    do: {:ok, body}

  defp handle_response({:ok, %Tesla.Env{status: 401}}), do: {:error, "unauthorized"}

  defp handle_response({:ok, %Tesla.Env{status: 404}}), do: {:error, "object not found"}

  defp handle_response({:ok, %Tesla.Env{status: 422, body: body}}) do
    {:error,
     %{
       request_id: body["request_id"],
       error_type: body["error_type"],
       error_codes: body["error_codes"]
     }}
  end

  defp handle_response({:ok, %Tesla.Env{status: status, body: body}}),
    do: {:error, "Tesla returned status: #{status} with body: #{body}"}

  defp handle_response({:error, message}), do: {:error, message}
end