From dc6b20ef6a50c6462e44f4e23f581a8ba3f115d7 Mon Sep 17 00:00:00 2001 From: Hifza Awais Date: Fri, 20 Dec 2024 23:56:53 +0500 Subject: [PATCH] Add payment form --- .../api_client/flutterwave.ex | 23 ++++++ .../live/payment_live/new.ex | 71 +++++++++++++++++++ lib/distributed_orders_web/router.ex | 1 + mix.exs | 4 +- mix.lock | 3 +- 5 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 lib/distributed_orders/api_client/flutterwave.ex create mode 100644 lib/distributed_orders_web/live/payment_live/new.ex diff --git a/lib/distributed_orders/api_client/flutterwave.ex b/lib/distributed_orders/api_client/flutterwave.ex new file mode 100644 index 0000000..5041ee4 --- /dev/null +++ b/lib/distributed_orders/api_client/flutterwave.ex @@ -0,0 +1,23 @@ +defmodule DistributedOrders.ApiClient.Flutterwave do + use Tesla + require Logger + + plug Tesla.Middleware.BaseUrl, get_endpoint() + + plug Tesla.Middleware.Headers, [ + {"Content-Type", "application/json"}, + {"Authorization", "Bearer " <> auth_token()} + ] + + plug Tesla.Middleware.DecodeJson + plug Tesla.Middleware.JSON + + def transfer_money(params) do + post!("/payments", params) + end + + defp get_endpoint(), do: "https://api.flutterwave.com/v3" + + def auth_token, do: "FLWSECK_TEST-2fe55e264ee7c70dff7747bf327dcdac-X" + +end diff --git a/lib/distributed_orders_web/live/payment_live/new.ex b/lib/distributed_orders_web/live/payment_live/new.ex new file mode 100644 index 0000000..9fd198c --- /dev/null +++ b/lib/distributed_orders_web/live/payment_live/new.ex @@ -0,0 +1,71 @@ +defmodule DistributedOrdersWeb.PaymentLive.New do + use DistributedOrdersWeb, :live_view + alias DistributedOrders.ApiClient.Flutterwave + + @available_countries [ + %{ + country: "South Africa", + currency: "ZAR" + }, + %{ + country: "Ghana", + currency: "GHS" + }, + %{ + country: "Kenya", + currency: "KES" + } + ] + + @impl true + def mount(_params, _session, socket) do + socket = + socket + |> assign(:page_title, "New Payment") + |> assign(:available_countries, @available_countries) + |> assign(:payment_link, nil) + |> assign(:payment_form, to_form(%{}, as: "payment")) + + {:ok, socket} + end + + @impl true + def render(assigns) do + ~H""" + <.simple_form for={@payment_form} phx-submit="save_payment"> +

+ Payment Details +

+ <.input field={@payment_form[:name]} type="text" label="Name" /> + <.input field={@payment_form[:email]} type="email" label="Email" /> + <.input field={@payment_form[:amount]} type="number" label="Amount" /> + <.input field={@payment_form[:currency]} type="select" label="Currency" prompt="Select a Currency" options={Enum.map(@available_countries, & &1.currency)} /> + <:actions> + <.button phx-disable-with="Saving..." value="add_manufacturer" class="mt-4 btn btn-primary">Get Payment Link + + + <%= if @payment_link do %> +
+ Pay Now +
+ <% end %> + """ + end + + @impl true + def handle_event("save_payment", %{"payment" => payment_params}, socket) do + params = %{ + "tx_ref" => "ref" <> UUID.uuid4(), + "currency" => payment_params["currency"], + "amount" => payment_params["amount"], + "customer" => %{ + "email" => payment_params["email"], + "name" => payment_params["name"] + }, + "redirect_url" => "/" + } + response = Flutterwave.transfer_money(params) + + {:noreply, assign(socket, :payment_link, response.body["data"]["link"])} + end +end diff --git a/lib/distributed_orders_web/router.ex b/lib/distributed_orders_web/router.ex index d0d4079..4c2cd3c 100644 --- a/lib/distributed_orders_web/router.ex +++ b/lib/distributed_orders_web/router.ex @@ -20,6 +20,7 @@ defmodule DistributedOrdersWeb.Router do get "/about", PageController, :about live "/", HomeLive.Index + live "/payment", PaymentLive.New, :index # live "/orders", OrderLive.Index, :index live "/orders/new", OrderLive.New, :new diff --git a/mix.exs b/mix.exs index cf705ba..8ab4ea7 100644 --- a/mix.exs +++ b/mix.exs @@ -59,7 +59,9 @@ defmodule DistributedOrders.MixProject do {:jason, "~> 1.4"}, {:dns_cluster, "~> 0.1.1"}, {:req, "~> 0.5.0"}, - {:bandit, "~> 1.5"} + {:bandit, "~> 1.5"}, + {:tesla, "~> 1.13"}, + {:uuid, "~> 1.1"} ] end diff --git a/mix.lock b/mix.lock index 1fa441c..022dbdf 100644 --- a/mix.lock +++ b/mix.lock @@ -12,7 +12,7 @@ "finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"}, "floki": {:hex, :floki, "0.36.3", "1102f93b16a55bc5383b85ae3ec470f82dee056eaeff9195e8afdf0ef2a43c30", [:mix], [], "hexpm", "fe0158bff509e407735f6d40b3ee0d7deb47f3f3ee7c6c182ad28599f9f6b27a"}, "gettext": {:hex, :gettext, "0.26.1", "38e14ea5dcf962d1fc9f361b63ea07c0ce715a8ef1f9e82d3dfb8e67e0416715", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "01ce56f188b9dc28780a52783d6529ad2bc7124f9744e571e1ee4ea88bf08734"}, - "heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "88ab3a0d790e6a47404cba02800a6b25d2afae50", [tag: "v2.1.1", sparse: "optimized", depth: 1]}, + "heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "88ab3a0d790e6a47404cba02800a6b25d2afae50", [tag: "v2.1.1", sparse: "optimized"]}, "hpax": {:hex, :hpax, "1.0.0", "28dcf54509fe2152a3d040e4e3df5b265dcb6cb532029ecbacf4ce52caea3fd2", [:mix], [], "hexpm", "7f1314731d711e2ca5fdc7fd361296593fc2542570b3105595bb0bc6d0fad601"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"}, @@ -38,6 +38,7 @@ "telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"}, "tesla": {:hex, :tesla, "1.13.0", "24a068a48d107080dd7c943a593997eee265977a38020eb2ab657cca78a12502", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:mox, "~> 1.0", [hex: :mox, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "7b8fc8f6b0640fa0d090af7889d12eb396460e044b6f8688a8e55e30406a2200"}, "thousand_island": {:hex, :thousand_island, "1.3.5", "6022b6338f1635b3d32406ff98d68b843ba73b3aa95cfc27154223244f3a6ca5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2be6954916fdfe4756af3239fb6b6d75d0b8063b5df03ba76fd8a4c87849e180"}, + "uuid": {:hex, :uuid, "1.1.8", "e22fc04499de0de3ed1116b770c7737779f226ceefa0badb3592e64d5cfb4eb9", [:mix], [], "hexpm", "c790593b4c3b601f5dc2378baae7efaf5b3d73c4c6456ba85759905be792f2ac"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock_adapter": {:hex, :websock_adapter, "0.5.7", "65fa74042530064ef0570b75b43f5c49bb8b235d6515671b3d250022cb8a1f9e", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "d0f478ee64deddfec64b800673fd6e0c8888b079d9f3444dd96d2a98383bdbd1"}, }