defmodule DaProductAppWeb.PaymentNotificationController do use DaProductAppWeb, :controller require Logger import Ecto.Query alias DaProductApp.Transactions.Transaction alias DaProductApp.PosTerminals.PosTerminal alias DaProductApp.Repo def process_payment_success(conn, %{"payment_id" => payment_id, "payment_amount" => payment_amount}) do transaction = from(t in Transaction, where: t.payment_reference_id == ^payment_id, select: %{id: t.id, device_id: t.device_id} ) |> Repo.one() case transaction do nil -> Logger.error("[Payment Notification] No transaction found for payment_id: #{payment_id}") conn |> put_status(:not_found) |> json(%{error: "Transaction not found"}) %{id: transaction_id, device_id: device_id} -> # Get device_request_id from PosTerminal (handle multiple results) pos_terminal = from(p in PosTerminal, where: p.serial_number == ^device_id, select: %{id: p.id, device_request_id: p.device_request_id}, limit: 1 ) |> Repo.one() request_id = case pos_terminal do nil -> transaction_id %{device_request_id: nil, id: pos_terminal_id} -> # Generate new device_request_id new_device_request_id = "#{device_id}_device_id_1" # Update PosTerminal with new device_request_id from(p in PosTerminal, where: p.id == ^pos_terminal_id) |> Repo.update_all(set: [device_request_id: new_device_request_id]) new_device_request_id %{device_request_id: device_request_id, id: pos_terminal_id} -> # Extract current number and increment case Regex.run(~r/device_id_(\d+)$/, device_request_id) do [_, num] -> current_num = String.to_integer(num) new_device_request_id = "#{device_id}_device_id_#{current_num + 1}" # Update PosTerminal with incremented device_request_id from(p in PosTerminal, where: p.id == ^pos_terminal_id) |> Repo.update_all(set: [device_request_id: new_device_request_id]) new_device_request_id nil -> device_request_id end end Logger.info("[Payment Notification] Using device_request_id: #{request_id} for transaction_id: #{transaction_id}") datetime = formatted_datetime() topic = "/ota/pFppbioOCKlo5c8E/#{device_id}/update" currency = payment_amount["currency"] || "AED" value = payment_amount["value"] || "0" money = :erlang.float_to_binary(from_smallest_unit(value, currency), decimals: 2) payload = Jason.encode!(%{ broadcast_type: 1, money: money, biz_type: 1, datetime: datetime, ctime: System.system_time(:second), request_id: request_id # Now using device_request_id if available }) Logger.info("[Payment Notification] Publishing to topic: #{topic} with payload: #{payload}") publish_result = Tortoise.publish("phoenix_client_node_devteammiddlelayer", topic, payload, qos: 1) Logger.info("[Payment Notification] Publish result: #{inspect(publish_result)}") json(conn, %{status: "success", message: "Payment notification processed"}) end end defp formatted_datetime do NaiveDateTime.utc_now() |> NaiveDateTime.to_iso8601() |> String.replace(~r/[-:T]/, "") |> String.slice(0..13) end defp from_smallest_unit(amount_str, currency) do value = String.to_integer("#{amount_str}") case currency do "JPY" -> value _ -> value / 100 end end end