berrypod/lib/simpleshop_theme_web/controllers/checkout_controller.ex

95 lines
2.5 KiB
Elixir
Raw Normal View History

defmodule SimpleshopThemeWeb.CheckoutController do
use SimpleshopThemeWeb, :controller
alias SimpleshopTheme.Cart
alias SimpleshopTheme.Orders
require Logger
def create(conn, _params) do
cart_items = Cart.get_from_session(get_session(conn))
hydrated = Cart.hydrate(cart_items)
cond do
hydrated == [] ->
conn
|> put_flash(:error, "Your basket is empty")
|> redirect(to: ~p"/cart")
true ->
create_checkout(conn, hydrated)
end
end
defp create_checkout(conn, hydrated_items) do
# Create a pending order with price snapshots
case Orders.create_order(%{items: hydrated_items}) do
{:ok, order} ->
create_stripe_session(conn, order, hydrated_items)
{:error, _changeset} ->
Logger.error("Failed to create order")
conn
|> put_flash(:error, "Something went wrong. Please try again.")
|> redirect(to: ~p"/cart")
end
end
defp create_stripe_session(conn, order, hydrated_items) do
line_items =
Enum.map(hydrated_items, fn item ->
product_name =
if item.variant,
do: "#{item.name}#{item.variant}",
else: item.name
%{
price_data: %{
currency: "gbp",
unit_amount: item.price,
product_data: %{name: product_name}
},
quantity: item.quantity
}
end)
base_url = SimpleshopThemeWeb.Endpoint.url()
params = %{
mode: "payment",
line_items: line_items,
success_url: "#{base_url}/checkout/success?session_id={CHECKOUT_SESSION_ID}",
cancel_url: "#{base_url}/cart",
metadata: %{"order_id" => order.id},
shipping_address_collection: %{
allowed_countries: ["GB", "US", "CA", "AU", "DE", "FR", "NL", "IE", "AT", "BE"]
}
}
case Stripe.Checkout.Session.create(params) do
{:ok, session} ->
{:ok, _order} = Orders.set_stripe_session(order, session.id)
conn
|> redirect(external: session.url)
{:error, %Stripe.Error{message: message}} ->
Logger.error("Stripe session creation failed: #{message}")
Orders.mark_failed(order)
conn
|> put_flash(:error, "Payment setup failed. Please try again.")
|> redirect(to: ~p"/cart")
{:error, reason} ->
Logger.error("Stripe session creation failed: #{inspect(reason)}")
Orders.mark_failed(order)
conn
|> put_flash(:error, "Payment setup failed. Please try again.")
|> redirect(to: ~p"/cart")
end
end
end