defmodule DaProductApp.MerchantRegistration.AaniProvider do @moduledoc """ Aani-specific merchant registration and inquiry logic. """ require Logger alias HTTPoison alias DaProductApp.Repo @doc """ Aani-specific merchant registration logic """ def register(params) do # Transform generic format to Aani format aani_params = transform_to_aani_format(params) # Call the mock API or real Aani API case call_aani_api(aani_params) do {:ok, response} -> Logger.info("Aani registration successful: #{inspect(response)}") {:ok, response} {:error, reason} -> Logger.error("Aani registration failed: #{inspect(reason)}") {:error, reason} end end @doc """ Aani-specific merchant inquiry logic """ def inquire(params) do merchant_id = params["merchantId"] # Call the Aani inquiry API base_url = get_aani_inquiry_url() # Generate inquiry headers request_id = generate_unique_request_id() # Generate authentication token auth_header = case generate_token(nil) do {:ok, token} -> {"Authorization", "Bearer #{token}"} {:error, _reason} -> {"Authorization", "Bearer mock_token_for_testing"} # Fallback for testing end headers = [ {"Content-Type", "application/json"}, {"RequestId", request_id}, {"BankUserId", merchant_id}, {"RequestUserId", "SystemUser"}, auth_header ] inquiry_params = %{"merchantId" => merchant_id, "action" => "inquiry"} body = Jason.encode!(inquiry_params) Logger.debug("Calling Aani inquiry with headers: #{inspect(headers)} and body: #{body}") case HTTPoison.post(base_url, body, headers) do {:ok, %HTTPoison.Response{status_code: 200, body: response_body}} -> Logger.info("Inquiry response from Aani: #{response_body}") case Jason.decode(response_body) do {:ok, decoded} -> {:ok, decoded} {:error, _} -> {:error, "Invalid JSON response from Aani"} end {:ok, %HTTPoison.Response{status_code: status_code, body: response_body}} -> Logger.warning("Non-200 inquiry response from Aani: #{response_body}") {:error, %{status_code: status_code, response: response_body}} {:error, %HTTPoison.Error{reason: reason}} -> Logger.error("HTTPoison error during Aani inquiry: #{inspect(reason)}") {:error, "Network error: #{inspect(reason)}"} end end @doc """ Generate authentication token for Aani API calls """ def generate_token(_headers \\ nil) do # Credentials for token generation username = "MBOnline" password_plain = "MbOnline@123" password_base64 = Base.encode64(password_plain) token_url = get_aani_token_url() # If headers are provided, we can extract any additional information if needed # For now, using default headers as the token generation doesn't require custom headers api_headers = [ {"Content-Type", "application/json"} ] body = Jason.encode!(%{ "username" => username, "password" => password_base64 }) Logger.debug("Requesting Aani token from: #{token_url}") case HTTPoison.post(token_url, body, api_headers) do {:ok, %HTTPoison.Response{status_code: 200, body: response_body}} -> Logger.info("Token response from Aani: #{response_body}") case Jason.decode(response_body) do {:ok, %{"accessToken" => access_token}} -> Logger.info("Successfully generated Aani access token") {:ok, access_token} {:ok, decoded} -> Logger.error("Token response missing accessToken: #{inspect(decoded)}") {:error, "Token response missing accessToken"} {:error, _} -> Logger.error("Invalid JSON in token response: #{response_body}") {:error, "Invalid JSON response from Aani token service"} end {:ok, %HTTPoison.Response{status_code: status_code, body: response_body}} -> Logger.error("Non-200 token response from Aani: #{status_code} - #{response_body}") {:error, %{status_code: status_code, response: response_body}} {:error, %HTTPoison.Error{reason: reason}} -> Logger.error("HTTPoison error during Aani token generation: #{inspect(reason)}") {:error, "Network error: #{inspect(reason)}"} end end @doc """ Generic merchant update method that dispatches based on update type """ def update_merchant(params, headers) do # Extract the update type from params update_type = Map.get(params, "type") # Route to the appropriate update method based on the type case update_type do "updateprofile" -> Logger.info("Routing to update_merchant_details for update type: #{update_type}") update_merchant_details(params, headers) "mobile" -> Logger.info("Routing to update_merchant_mobile for update type: #{update_type}") update_merchant_mobile(params, headers) "mcc" -> Logger.info("Routing to update_merchant_mcc for update type: #{update_type}") update_merchant_mcc(params, headers) other -> Logger.error("Unknown update type: #{other}") {:error, "Unsupported update type: #{other}. Supported types: updateprofile, mobile, mcc"} end end @doc """ Aani-specific merchant details update logic """ def update_merchant_details(params, headers) do # Call the Aani update API case call_aani_update_api(params, headers) do {:ok, response} -> Logger.info("Aani merchant details update successful: #{inspect(response)}") # Save update log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_update_log_to_db(bank_user_id, params, headers, response) end {:ok, response} {:error, reason} -> Logger.error("Aani merchant details update failed: #{inspect(reason)}") # Save failed update log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_update_log_to_db(bank_user_id, params, headers, %{"error" => reason}) end {:error, reason} end end @doc """ Aani-specific update merchant mobile logic """ def update_merchant_mobile(params, headers) do # Call the Aani update mobile API case call_aani_update_mobile_api(params, headers) do {:ok, response} -> Logger.info("Aani merchant mobile update successful: #{inspect(response)}") # Save update log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_mobile_update_log_to_db(bank_user_id, params, headers, response) end {:ok, response} {:error, reason} -> Logger.error("Aani merchant mobile update failed: #{inspect(reason)}") # Save failed update log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_mobile_update_log_to_db(bank_user_id, params, headers, %{"error" => reason}) end {:error, reason} end end @doc """ Aani-specific update merchant MCC (Merchant Category Code) logic """ def update_merchant_mcc(params, headers) do # Call the Aani update MCC API case call_aani_update_mcc_api(params, headers) do {:ok, response} -> Logger.info("Aani merchant MCC update successful: #{inspect(response)}") # Save update log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_mcc_update_log_to_db(bank_user_id, params, headers, response) end {:ok, response} {:error, reason} -> Logger.error("Aani merchant MCC update failed: #{inspect(reason)}") # Save failed update log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_mcc_update_log_to_db(bank_user_id, params, headers, %{"error" => reason}) end {:error, reason} end end @doc """ Save update operation log to merchant_enrollments table """ def save_update_log_to_db(bank_user_id, update_params, request_headers, response) do alias DaProductApp.Groups.Group alias DaProductApp.MerchantEnrollment # Find the group by bank_user_id (assuming it's stored in the code field) case Repo.get_by(Group, code: bank_user_id) do nil -> Logger.warning("No group found for bankUserId #{bank_user_id} when saving update log") :not_found group -> # Find the MerchantEnrollment record for this group and Aani provider case Repo.get_by(MerchantEnrollment, group_id: group.id, provider: "aani") do nil -> Logger.warning("No MerchantEnrollment found for group_id #{group.id} and provider aani") :not_found enrollment -> # Get existing update history and add new log current_history = enrollment.inquiry_history || %{} update_logs = Map.get(current_history, "updates", []) # Create new update log entry update_log_entry = %{ timestamp: DateTime.utc_now(), operation: "update_merchant_details", request_params: update_params, request_headers: request_headers, response: response, request_id: Map.get(request_headers, "requestid") } new_update_logs = [update_log_entry | update_logs] new_inquiry_history = Map.put(current_history, "updates", new_update_logs) update_attrs = %{ inquiry_history: new_inquiry_history } case Repo.update(MerchantEnrollment.changeset(enrollment, update_attrs)) do {:ok, _} -> Logger.info("Updated MerchantEnrollment update logs for group_id #{group.id}") :ok {:error, err} -> Logger.error("Failed to update MerchantEnrollment update logs: #{inspect(err)}") :error end end end end @doc """ Save mobile update operation log to merchant_enrollments table """ def save_mobile_update_log_to_db(bank_user_id, update_params, request_headers, response) do alias DaProductApp.Groups.Group alias DaProductApp.MerchantEnrollment # Find the group by bank_user_id (assuming it's stored in the code field) case Repo.get_by(Group, code: bank_user_id) do nil -> Logger.warning("No group found for bankUserId #{bank_user_id} when saving mobile update log") :not_found group -> # Find the MerchantEnrollment record for this group and Aani provider case Repo.get_by(MerchantEnrollment, group_id: group.id, provider: "aani") do nil -> Logger.warning("No MerchantEnrollment found for group_id #{group.id} and provider aani") :not_found enrollment -> # Get existing update history and add new log current_history = enrollment.inquiry_history || %{} update_logs = Map.get(current_history, "updates", []) # Create new update log entry update_log_entry = %{ timestamp: DateTime.utc_now(), operation: "update_merchant_mobile", request_params: update_params, request_headers: request_headers, response: response, request_id: Map.get(request_headers, "requestid") } new_update_logs = [update_log_entry | update_logs] new_inquiry_history = Map.put(current_history, "updates", new_update_logs) update_attrs = %{ inquiry_history: new_inquiry_history } case Repo.update(MerchantEnrollment.changeset(enrollment, update_attrs)) do {:ok, _} -> Logger.info("Updated MerchantEnrollment mobile update logs for group_id #{group.id}") :ok {:error, err} -> Logger.error("Failed to update MerchantEnrollment mobile update logs: #{inspect(err)}") :error end end end end @doc """ Save MCC update operation log to merchant_enrollments table """ def save_mcc_update_log_to_db(bank_user_id, update_params, request_headers, response) do alias DaProductApp.Groups.Group alias DaProductApp.MerchantEnrollment # Find the group by bank_user_id (assuming it's stored in the code field) case Repo.get_by(Group, code: bank_user_id) do nil -> Logger.warning("No group found for bankUserId #{bank_user_id} when saving MCC update log") :not_found group -> # Find the MerchantEnrollment record for this group and Aani provider case Repo.get_by(MerchantEnrollment, group_id: group.id, provider: "aani") do nil -> Logger.warning("No MerchantEnrollment found for group_id #{group.id} and provider aani") :not_found enrollment -> # Get existing update history and add new log current_history = enrollment.inquiry_history || %{} update_logs = Map.get(current_history, "updates", []) # Create new update log entry update_log_entry = %{ timestamp: DateTime.utc_now(), operation: "update_merchant_mcc", request_params: update_params, request_headers: request_headers, response: response, request_id: Map.get(request_headers, "requestid") } new_update_logs = [update_log_entry | update_logs] new_inquiry_history = Map.put(current_history, "updates", new_update_logs) update_attrs = %{ inquiry_history: new_inquiry_history } case Repo.update(MerchantEnrollment.changeset(enrollment, update_attrs)) do {:ok, _} -> Logger.info("Updated MerchantEnrollment MCC update logs for group_id #{group.id}") :ok {:error, err} -> Logger.error("Failed to update MerchantEnrollment MCC update logs: #{inspect(err)}") :error end end end end # Transform generic format to Aani-specific format defp transform_to_aani_format(params) do merchant = params["merchant"] || %{} store = params["store"] || %{} # Extract owner name parts for name/surname split owner_name = get_in(merchant, ["ownerInfo", "name"]) || merchant["displayName"] || "Business Owner" name_parts = String.split(owner_name, " ", parts: 2) first_name = Enum.at(name_parts, 0, "Business") surname = Enum.at(name_parts, 1, "Owner") # Transform merchant info according to exact Aani field mapping from specification %{ "merchant" => %{ "bankUserId" => generate_bank_user_id(merchant["id"]), "name" => first_name, "surname" => surname, "denomination" => merchant["displayName"] || "Business Name", "vatNumber" => get_in(merchant, ["legalInfo", "vatNumber"]) || merchant["id"] || generate_vat_number(), "mcc" => merchant["mcc"] || "9999", "mobile" => get_in(merchant, ["contactInfo", "phone"]) || generate_default_mobile(), "typologyBusinessUser" => "PROFESSIONAL", # Default business type "logo" => generate_default_logo(), # Base64 encoded default logo "channelName" => get_channel_name_from_services(params["services"]), "bankAccounts" => generate_bank_accounts(merchant), "proxies" => generate_proxies(merchant) }, "shops" => [ %{ "label" => store["name"] || "Main Shop", "mid" => store["id"] || generate_merchant_id(), "type" => determine_store_type(params["services"]), "mcc" => store["mcc"] || merchant["mcc"] || "9999", "bankAccount" => %{ "IBAN" => get_primary_iban(merchant) }, "address" => transform_address_for_aani(store["address"]), "cashDesks" => [ %{ "identification" => generate_cash_desk_id(store["id"]) } ] } ] } end # Call the Aani API (mock or real) defp call_aani_api(aani_params) do # Get the base URL for the Aani service base_url = get_aani_base_url() # Generate authentication token auth_header = case generate_token(nil) do {:ok, token} -> {"Authorization", "Bearer #{token}"} {:error, _reason} -> {"Authorization", "Bearer mock_token_for_testing"} # Fallback for testing end # Generate request headers according to Aani specification request_id = generate_unique_request_id() bank_user_id = get_in(aani_params, ["merchant", "bankUserId"]) || "DefaultUserId" request_user_id = "SystemUser" # Default requestor identifier headers = [ {"Content-Type", "application/json"}, {"RequestId", request_id}, {"BankUserId", bank_user_id}, {"RequestUserId", request_user_id}, auth_header ] body = Jason.encode!(aani_params) Logger.debug("Calling Aani API with headers: #{inspect(headers)} and body: #{body}") case HTTPoison.post(base_url, body, headers) do {:ok, %HTTPoison.Response{status_code: 200, body: response_body}} -> Logger.info("Raw response from Aani: #{response_body}") case Jason.decode(response_body) do {:ok, decoded} -> {:ok, decoded} {:error, _} -> {:error, "Invalid JSON response from Aani"} end {:ok, %HTTPoison.Response{status_code: status_code, body: response_body}} -> Logger.warning("Non-200 response from Aani: #{response_body}") {:error, %{status_code: status_code, response: response_body}} {:error, %HTTPoison.Error{reason: reason}} -> Logger.error("HTTPoison error calling Aani: #{inspect(reason)}") {:error, "Network error: #{inspect(reason)}"} end end # Generate unique request ID for Aani API calls defp generate_unique_request_id do :crypto.strong_rand_bytes(16) |> Base.encode16(case: :lower) |> String.slice(0, 16) end # Call the Aani Update API for merchant details defp call_aani_update_api(update_params, headers) do # Get the base URL for the Aani update service base_url = get_aani_update_url() # Generate authentication token auth_header = case generate_token(headers) do {:ok, token} -> {"Authorization", "Bearer #{token}"} {:error, _reason} -> # Try to use the provided authorization header as fallback {"Authorization", Map.get(headers, "authorization", "Bearer mock_token_for_testing")} end # Build headers according to Aani specification api_headers = [ {"Content-Type", "application/json"}, {"RequestId", Map.get(headers, "requestid", generate_unique_request_id())}, {"BankUserId", Map.get(headers, "bankuserid")}, {"RequestUserId", Map.get(headers, "requestuserid")}, {"MerchantTag", Map.get(headers, "merchanttag")}, auth_header ] body = Jason.encode!(update_params) Logger.debug("Calling Aani Update API with headers: #{inspect(api_headers)} and body: #{body}") case HTTPoison.post(base_url, body, api_headers) do {:ok, %HTTPoison.Response{status_code: 200, body: response_body}} -> Logger.info("Raw response from Aani Update API: #{response_body}") case Jason.decode(response_body) do {:ok, decoded} -> {:ok, decoded} {:error, _} -> {:error, "Invalid JSON response from Aani Update API"} end {:ok, %HTTPoison.Response{status_code: status_code, body: response_body}} -> Logger.warning("Non-200 response from Aani Update API: #{response_body}") {:error, %{status_code: status_code, response: response_body}} {:error, %HTTPoison.Error{reason: reason}} -> Logger.error("HTTPoison error calling Aani Update API: #{inspect(reason)}") {:error, "Network error: #{inspect(reason)}"} end end @doc """ Call the Aani API to update merchant mobile number """ def call_aani_update_mobile_api(params, headers) do # Generate authentication token or extract from headers if provided token_result = generate_token(headers) token = case token_result do {:ok, token_value} -> token_value {:error, _} -> "mock_token_for_testing" # Fallback for testing end # Extract required fields bank_user_id = Map.get(headers, "bankuserid") mobile_number = Map.get(params, "mobileNumber") # Build API endpoint URL aani_base_url = Application.get_env(:da_product_app, :aani_base_url) update_mobile_path = Application.get_env(:da_product_app, :aani_update_mobile_path, "/api/merchant/updateMobile") update_url = aani_base_url <> update_mobile_path # Prepare request payload payload = %{ "bankUserId" => bank_user_id, "mobileNumber" => mobile_number } request_id = Map.get(headers, "requestid", generate_unique_request_id()) # Prepare headers http_headers = [ {"Content-Type", "application/json"}, {"Authorization", "Bearer #{token}"}, {"RequestId", request_id} ] # Log request details Logger.info("Aani mobile update request: URL=#{update_url}, Headers=#{inspect(http_headers)}, Payload=#{inspect(payload)}") # Make the API call case HTTPoison.post(update_url, Jason.encode!(payload), http_headers, []) do {:ok, %HTTPoison.Response{status_code: status_code, body: body}} when status_code in 200..299 -> # Success response Logger.info("Aani mobile update successful: #{body}") case Jason.decode(body) do {:ok, decoded} -> {:ok, decoded} {:error, _} -> {:ok, %{"rawResponse" => body}} end {:ok, %HTTPoison.Response{status_code: status_code, body: body}} -> # Error response Logger.error("Aani mobile update failed with status #{status_code}: #{body}") {:error, %{status_code: status_code, body: body}} {:error, %HTTPoison.Error{reason: reason}} -> # HTTP client error Logger.error("Aani mobile update request failed: #{inspect(reason)}") {:error, reason} end end @doc """ Call the Aani API to update merchant MCC (Merchant Category Code) """ def call_aani_update_mcc_api(params, headers) do # Generate authentication token or extract from headers if provided token_result = generate_token(headers) token = case token_result do {:ok, token_value} -> token_value {:error, _} -> "mock_token_for_testing" # Fallback for testing end # Extract required fields bank_user_id = Map.get(headers, "bankuserid") mcc = Map.get(params, "mcc") # Build API endpoint URL aani_base_url = Application.get_env(:da_product_app, :aani_base_url) update_mcc_path = Application.get_env(:da_product_app, :aani_update_mcc_path, "/api/merchant/updateMCC") update_url = aani_base_url <> update_mcc_path # Prepare request payload according to specification payload = %{ "mcc" => mcc } request_id = Map.get(headers, "requestid") || generate_unique_request_id() # Prepare headers according to Aani specification http_headers = [ {"Content-Type", "application/json"}, {"RequestId", request_id}, {"BankUserId", bank_user_id}, {"RequestUserId", Map.get(headers, "requestuserid", "SystemUser")}, {"MerchantTag", Map.get(headers, "merchanttag", "")}, {"Authorization", "Bearer #{token}"} ] # Log request details Logger.info("Aani MCC update request: URL=#{update_url}, Headers=#{inspect(http_headers)}, Payload=#{inspect(payload)}") # Make the API call case HTTPoison.post(update_url, Jason.encode!(payload), http_headers, []) do {:ok, %HTTPoison.Response{status_code: status_code, body: body}} when status_code in 200..299 -> # Success response Logger.info("Aani MCC update successful: #{body}") case Jason.decode(body) do {:ok, decoded} -> {:ok, decoded} {:error, _} -> {:ok, %{"rawResponse" => body}} end {:ok, %HTTPoison.Response{status_code: status_code, body: body}} -> # Error response Logger.error("Aani MCC update failed with status #{status_code}: #{body}") {:error, %{status_code: status_code, body: body}} {:error, %HTTPoison.Error{reason: reason}} -> # HTTP client error Logger.error("Aani MCC update request failed: #{inspect(reason)}") {:error, reason} end end # Get base URL for Aani service (registration) defp get_aani_base_url do case Application.get_env(:da_product_app, :environment) do :prod -> "https://api.aani.ae/merchant/register" # Production Aani API _ -> "https://demo.ctrmv.com:4004/aani_response_creator.php" # Local PHP mock end end # Get inquiry URL for Aani service defp get_aani_inquiry_url do case Application.get_env(:da_product_app, :environment) do :prod -> "https://api.aani.ae/merchant/inquiry" # Production Aani inquiry API _ -> "https://demo.ctrmv.com:4004/aani_response_creator.php" # Local PHP mock handles both end end # Get token URL for Aani service defp get_aani_token_url do case Application.get_env(:da_product_app, :environment) do :prod -> "https://api.aani.ae/auth/token" # Production Aani token API _ -> "https://demo.ctrmv.com:4004/aani_token_generator.php" # Local PHP mock for token end end # Get update URL for Aani service defp get_aani_update_url do case Application.get_env(:da_product_app, :environment) do :prod -> "https://api.aani.ae/merchant/update" # Production Aani update API _ -> "https://demo.ctrmv.com:4004/aani_update_details.php" # Local PHP mock for updates end end # Transform address to Aani format defp transform_address_for_aani(nil), do: generate_default_address() defp transform_address_for_aani(address) do %{ "building" => address["street"] || "Business Center", "street" => address["street"] || "Sheikh Zayed Road", "city" => address["city"] || "Dubai", "postalCode" => address["postalCode"] || "00000", "county" => address["state"] || address["city"] || "Dubai", "country" => address["country"] || "United Arab Emirates" } end # Generate bank user ID (16 characters as per spec) defp generate_bank_user_id(merchant_id) when is_binary(merchant_id) do # Ensure it's 16 characters or less String.slice(merchant_id <> String.duplicate("0", 16), 0, 16) end defp generate_bank_user_id(_) do "AA" <> to_string(Enum.random(10000000000000..99999999999999)) end # Generate VAT number (35 characters max as per spec) defp generate_vat_number do to_string(Enum.random(10000000000..99999999999)) end # Generate bank accounts array with IBAN and currency defp generate_bank_accounts(merchant) do iban = get_primary_iban(merchant) [ %{ "IBAN" => iban, "currency" => "AED" } ] end # Get primary IBAN from merchant data or generate default defp get_primary_iban(merchant) do cond do get_in(merchant, ["bankAccount", "IBAN"]) -> merchant["bankAccount"]["IBAN"] get_in(merchant, ["bankAccounts"]) && is_list(merchant["bankAccounts"]) -> List.first(merchant["bankAccounts"])["IBAN"] || generate_default_iban() true -> generate_default_iban() end end # Generate default IBAN for UAE (35 characters max) defp generate_default_iban do bank_code = "BOIY" account_number = to_string(Enum.random(10000000000000000000..99999999999999999999)) "AE#{Enum.random(10..99)}#{bank_code}#{account_number}" end # Generate proxies array (document-id type) defp generate_proxies(merchant) do document_id = get_in(merchant, ["ownerInfo", "id"]) || generate_document_id() [ %{ "type" => "document-id", "value" => document_id } ] end # Generate document ID defp generate_document_id do to_string(Enum.random(100000000000000..999999999999999)) end # Generate cash desk identification defp generate_cash_desk_id(store_id) when is_binary(store_id) do store_id <> "CD01" end defp generate_cash_desk_id(_) do "DESK" <> to_string(Enum.random(1000..9999)) end # Generate merchant ID if not provided defp generate_merchant_id do "MID" <> to_string(Enum.random(10000..99999)) end # Generate default base64 logo (1x1 transparent PNG) defp generate_default_logo do "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==" end # Generate default mobile if not provided defp generate_default_mobile do "00971" <> to_string(Enum.random(500000000..599999999)) end # Determine channel name from services defp get_channel_name_from_services(nil), do: "Default Channel" defp get_channel_name_from_services(services) when is_list(services) do cond do "ECOMMERCE" in services -> "Online Channel" "QR_PAYMENTS" in services -> "QR Payment Channel" "PAYMENT_PROCESSING" in services -> "Payment Processing Channel" true -> "Default Channel" end end defp get_channel_name_from_services(_), do: "Default Channel" # Determine store type from services defp determine_store_type(nil), do: "PHYSICAL" defp determine_store_type(services) when is_list(services) do if "ECOMMERCE" in services or "ONLINE_PAYMENTS" in services do "ONLINE" else "PHYSICAL" end end defp determine_store_type(_), do: "PHYSICAL" # Generate default address defp generate_default_address do %{ "building" => "Business Center", "street" => "Sheikh Zayed Road", "city" => "Dubai", "postalCode" => "00000", "county" => "Dubai", "country" => "United Arab Emirates" } end @doc """ Convert direct Aani format to generic format for processing """ def convert_direct_to_generic(aani_params) do # Transform Aani-specific parameters to generic format merchant_info = Map.get(aani_params, "merchant", %{}) shops = Map.get(aani_params, "shops", []) first_shop = List.first(shops) || %{} generic_params = %{ "merchant" => %{ "id" => Map.get(merchant_info, "bankUserId"), "displayName" => Map.get(merchant_info, "denomination"), "mcc" => Map.get(merchant_info, "mcc"), "ownerInfo" => %{ "name" => "#{Map.get(merchant_info, "name", "")} #{Map.get(merchant_info, "surname", "")}", "id" => get_in(merchant_info, ["proxies", 0, "value"]) }, "contactInfo" => %{ "phone" => Map.get(merchant_info, "mobile") }, "legalInfo" => %{ "vatNumber" => Map.get(merchant_info, "vatNumber") }, "bankAccount" => %{ "IBAN" => get_in(merchant_info, ["bankAccounts", 0, "IBAN"]) } }, "store" => %{ "id" => Map.get(first_shop, "mid"), "name" => Map.get(first_shop, "label"), "mcc" => Map.get(first_shop, "mcc"), "address" => Map.get(first_shop, "address") }, "services" => ["QR_PAYMENTS", "PAYMENT_PROCESSING"] } {:ok, generic_params} end end