Skip to content

Instantly share code, notes, and snippets.

@janpauldahlke
Created February 1, 2023 15:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save janpauldahlke/ff19ddb80d344a7c1aac0d56f70bac22 to your computer and use it in GitHub Desktop.
Save janpauldahlke/ff19ddb80d344a7c1aac0d56f70bac22 to your computer and use it in GitHub Desktop.
aipi controller help schmu
defmodule PortalWeb.ApiController do
@moduledoc """
The ApiController handles API requests.
"""
use PortalWeb, :controller
alias __MODULE__.ApiControllerHelper
alias PortalWeb.BuyLive
alias PortalWeb.Errors.InvalidProductNameError
alias PortalWeb.Errors.InvalidRequestError
alias PortalWeb.Errors.UnknownResponseTypeError
@fixed_quantity 1
@spec product(Plug.Conn.t(), Plug.Conn.params()) :: Plug.Conn.t()
def product(conn, _params = %{"product_name" => product_name}) do
case String.split(product_name, ".") do
[product_name, "json"] ->
case PortalWeb.Stripe.price_by_product_name(product_name) do
{:error, :not_found} ->
raise InvalidProductNameError
{:ok, price} ->
buy_link = Routes.live_url(PortalWeb.Endpoint, BuyLive, product_name)
product_info =
price
|> get_product_info()
|> Map.put("buyLink", buy_link)
conn
|> put_resp_content_type("application/json")
|> send_resp(200, Jason.encode!(product_info))
end
[_product_name, _unknown_response_type] ->
raise UnknownResponseTypeError
[_invalid_entry] ->
raise InvalidRequestError
end
end
defp get_product_info(price = %Stripe.Price{currency: currency}) do
unit_amount = ApiControllerHelper.amount(price, @fixed_quantity)
currencies =
Map.new([
{price.currency,
%{
netto: unit_amount / 100
}}
])
%{
productName: price.product.name,
productDescription: price.product.description,
standardInterval: price.recurring.interval,
metadata: price.product.metadata,
currencies: currencies
}
end
defmodule ApiControllerHelper do
@moduledoc """
The ApiControllerHelper module contains helper functions for the ApiController.
"""
@spec amount(Stripe.Price.t(), integer()) :: integer()
def amount(price = %Stripe.Price{}, quantity) do
maybe_find_price_in_tiers(price, quantity)
end
defp maybe_find_price_in_tiers(
%Stripe.Price{unit_amount: unit_amount, tiers: nil},
quantity
) do
unit_amount * quantity
end
defp maybe_find_price_in_tiers(
%Stripe.Price{unit_amount: unit_amount, tiers: tiers},
quantity
) do
if Enum.empty?(tiers) do
unit_amount * quantity
else
find_price_in_tiers(tiers, quantity) * quantity
end
end
defp find_price_in_tiers(tiers, quantity) when is_list(tiers) do
tiers
|> Enum.find(&compare_price(&1.up_to, quantity))
|> Map.get(:unit_amount)
end
# the last tier has no upper limit
defp compare_price(_up_to = nil, _quantity) do
true
end
defp compare_price(up_to, quantity) when is_integer(up_to) do
up_to >= quantity
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment