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