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 Logger.info("Aani registration called with params: #{inspect(params)}") # 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, 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 Logger.info("Aani inquiry called with params: #{inspect(params)}") alias DaProductApp.MerchantStaticQr.MerchantStoreQr alias DaProductApp.Repo alias DaProductApp.Groups.Group alias DaProductApp.Brands.Brand merchant_id = params["merchantId"] # Get merchant tag from database merchant_tag = case Repo.get_by(Brand, merchant_reference_id: merchant_id) do %Brand{merchant_tag: tag} when not is_nil(tag) -> tag _ -> "" end # Extract required params - RequestId should be unique for each inquiry request_id = params["requestId"] || "REQ_INQUIRY_#{DateTime.utc_now() |> DateTime.to_unix()}" # Get the original RequestUserId from registration params stored in database original_request_user_id = case Repo.get_by(Brand, merchant_reference_id: merchant_id) do %Brand{group_id: group_id} when not is_nil(group_id) -> case Repo.get(Group, group_id) do %Group{params: %{"original_params" => %{"requestId" => orig_req_id}}} -> orig_req_id _ -> "REQ_TEST_824" # fallback to known working value end _ -> "REQ_TEST_824" # fallback to known working value end request_user_id = params["requestUserId"] || original_request_user_id bank_user_id = String.upcase(merchant_id) # Ensure uppercase like in registration response # Build GET URL with path parameters base_url = "https://npss.services.shukria.ae/NPSS_Channel_Onboard_API/api/AutoMerchant/RetrieveMerchantDetails" url = "#{base_url}/#{request_id}/#{request_user_id}/#{bank_user_id}/#{merchant_tag}" # Generate authentication token (same as registration) auth_header = case generate_token(nil) do {:ok, token} -> {"Authorization", "Bearer #{token}"} {:error, _reason} -> {"Authorization", "Bearer "} end # Build headers for GET request - only Authorization needed headers = [ {"Accept", "application/json"}, auth_header ] Logger.debug("Calling Aani inquiry GET: #{url}") Logger.debug("Inquiry headers: #{inspect(headers)}") # Make GET request with authorization headers case HTTPoison.get(url, 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} -> # Parse and save static QR details for each store save_static_qr_details(decoded) # Transform Aani response to match Alipay format transformed_response = transform_aani_inquiry_response(decoded) {:ok, transformed_response} {: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 # Save static QR details for each store in the response defp save_static_qr_details(%{"merchant" => merchant_data}) do alias DaProductApp.MerchantStaticQr.MerchantStoreQr alias DaProductApp.Repo merchant_id = merchant_data["bankUserId"] merchant_static_qr = merchant_data["staticQrCode"] shops = merchant_data["shops"] || [] # Save merchant-level static QR if it exists if merchant_id && merchant_static_qr do upsert_merchant_store_qr(merchant_id, "MERCHANT_LEVEL", merchant_static_qr) end # Save store-level static QRs Enum.each(shops, fn shop -> shop_id = to_string(shop["id"] || shop["mid"]) shop_static_qr = shop["staticQrCode"] # If shops have individual QR codes if merchant_id && shop_id && (merchant_static_qr || shop_static_qr) do # Use shop-specific QR if available, otherwise use merchant QR qr_code_to_save = shop_static_qr || merchant_static_qr upsert_merchant_store_qr(merchant_id, shop_id, qr_code_to_save) end end) end defp save_static_qr_details(_), do: :ok # MySQL-compatible upsert function defp upsert_merchant_store_qr(merchant_id, store_id, static_qr_code) do alias DaProductApp.MerchantStaticQr.MerchantStoreQr alias DaProductApp.Repo case Repo.get_by(MerchantStoreQr, merchant_id: merchant_id, store_id: store_id) do nil -> # Record doesn't exist, insert new one %MerchantStoreQr{} |> MerchantStoreQr.changeset(%{ merchant_id: merchant_id, store_id: store_id, static_qr_code: static_qr_code }) |> Repo.insert() existing_record -> # Record exists, update it existing_record |> MerchantStoreQr.changeset(%{ static_qr_code: static_qr_code }) |> Repo.update() end end # Transform Aani inquiry response to match Alipay format for consistent controller handling defp transform_aani_inquiry_response(aani_response) do Logger.info("Transforming Aani response to Alipay format. Original response: #{inspect(aani_response)}") # Extract the result information from Aani response result = aani_response["result"] || %{} code = result["code"] success = result["result"] Logger.info("Extracted result data - code: #{inspect(code)}, success: #{inspect(success)}") # Determine registrationStatus based on Aani result registration_status = cond do code == "00000" && success == true -> "APPROVED" code != "00000" -> "REJECTED" success == false -> "REJECTED" true -> "PENDING" end Logger.info("Determined registrationStatus: #{registration_status}") # Determine resultStatus and resultMessage based on Aani result for controller compatibility {result_status, result_message} = cond do code == "00000" && success == true -> {"S", "Success"} code != "00000" -> {"F", "Registration failed"} success == false -> {"F", "Registration failed"} true -> {"F", "Registration pending"} end # Create Alipay-compatible response structure while preserving original data transformed_response = %{ "registrationResult" => %{ "registrationStatus" => registration_status }, # Add Alipay-compatible result structure for controller compatibility "result" => %{ "resultStatus" => result_status, "resultMessage" => result_message, "resultCode" => if(result_status == "S", do: "SUCCESS", else: "FAILED") }, # Preserve original Aani data for reference "merchant" => aani_response["merchant"], "originalAaniResult" => aani_response["result"], # Add original response for debugging/reference "originalAaniResponse" => aani_response } Logger.info("Final transformed response: #{inspect(transformed_response)}") transformed_response end @doc """ Generate authentication token for Aani API calls (using QRProviders.Aani logic) """ def generate_token(_headers \\ nil) do # Environment config (simulator/prod) environment = Application.get_env(:da_product_app, :aani_env, "prod") config = %{ "simulator" => %{ token_url: "https://demo.ctrmv.com/prasanna/aani/aanigenerateqr.php", channel_id: "ipp_qr_merchant", client_id: "mercury-live-channel-mpp", client_secret: "bWVyY3VyeS5saXZlLjIwMjUubXBw" }, "prod" => %{ token_url: "https://npss.services.shukria.ae/UAEIPP_Jwt_Token_API/auth/get-token", channel_id: "ipp_qr_merchant", client_id: "mercury-live-channel-mpp", client_secret: "bWVyY3VyeS5saXZlLjIwMjUubXBw" } }[environment] url = config[:token_url] headers = [ {"Content-Type", "application/x-www-form-urlencoded"} ] body = URI.encode_query(%{ "channel_id" => config[:channel_id], "client_id" => config[:client_id], "client_secret" => config[:client_secret] }) Logger.info("Requesting Aani token from: #{url}") case HTTPoison.post(url, body, 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" => token}} -> {:ok, token} {:ok, %{"access_token" => token}} -> {:ok, token} {:ok, %{"token" => token}} -> {:ok, token} {:ok, parsed_response} -> Logger.error("Token not found in response: #{inspect(parsed_response)}") {:error, "Token not found in response"} {:error, reason} -> Logger.error("Failed to parse token response: #{inspect(reason)}") {:error, reason} end {:ok, %HTTPoison.Response{} = resp} -> Logger.error("Aani token API non-200 response: #{inspect(resp)}") Logger.error("Error response from Aani token API: #{resp.status_code} - #{resp.body}") {:error, %{status_code: resp.status_code, body: resp.body, headers: resp.headers}} {:error, %HTTPoison.Error{reason: reason}} -> Logger.error("Failed to connect to Aani token API: #{inspect(reason)}") {:error, reason} end end @doc """ Generic merchant update method that dispatches based on update type """ def update_merchant(params, headers) do Logger.info("Aani update_merchant called with params: #{inspect(params)} and headers: #{inspect(headers)}") # 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) "delete" -> Logger.info("Routing to delete_merchant for update type: #{update_type}") delete_merchant(params, headers) "add_bank_account" -> Logger.info("Routing to add_merchant_bank_account for update type: #{update_type}") add_merchant_bank_account(params, headers) "remove_bank_account" -> Logger.info("Routing to remove_merchant_bank_account for update type: #{update_type}") remove_merchant_bank_account(params, headers) "block_bank_account" -> Logger.info("Routing to block_merchant_bank_account for update type: #{update_type}") block_merchant_bank_account(params, headers) "add_shop" -> Logger.info("Routing to add_merchant_shop for update type: #{update_type}") add_merchant_shop(params, headers) "update_shop" -> Logger.info("Routing to update_merchant_shop for update type: #{update_type}") update_merchant_shop(params, headers) "delete_shop" -> Logger.info("Routing to delete_merchant_shop for update type: #{update_type}") delete_merchant_shop(params, headers) "add_cash_desk" -> Logger.info("Routing to add_merchant_shop_cash_desk for update type: #{update_type}") add_merchant_shop_cash_desk(params, headers) "update_cash_desk" -> Logger.info("Routing to update_merchant_shop_cash_desk for update type: #{update_type}") update_merchant_shop_cash_desk(params, headers) "delete_cash_desk" -> Logger.info("Routing to delete_merchant_shop_cash_desk for update type: #{update_type}") delete_merchant_shop_cash_desk(params, headers) other -> Logger.error("Unknown update type: #{other}") {:error, "Unsupported update type: #{other}. Supported types: updateprofile, mobile, mcc, delete, add_bank_account, remove_bank_account, block_bank_account, add_shop, update_shop, delete_shop, add_cash_desk, update_cash_desk, delete_cash_desk"} 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 Logger.info("Starting transformation from generic to Aani format") Logger.info("Input generic params: #{inspect(params)}") merchant = params["merchant"] || %{} store = params["store"] || %{} # Extract cash desk ID from params or generate cash_desk_id = params["cashDeskId"] || generate_cash_desk_id(store["id"]) # Extract store ID from params (prefer storeId over store.id) store_id = params["storeId"] || store["id"] # Extract owner name parts for name/surname split owner_name = get_in(merchant, ["ownerInfo", "name"]) || merchant["displayName"] name_parts = String.split(owner_name || "", " ", parts: 2) first_name = Enum.at(name_parts, 0) surname = Enum.at(name_parts, 1) Logger.info("Name transformation: owner_name='#{owner_name}' -> first_name='#{first_name}', surname='#{surname}'") Logger.info("IBAN parameter received: #{inspect(params["iban"])}") # Build shops array (with cashDesks) shops = [ %{ "label" => store["name"], "mid" => store_id, "type" => "PHYSICAL", "mcc" => store["mcc"] || merchant["mcc"], "bankAccount" => %{ "IBAN" => params["iban"] }, "address" => transform_address_for_aani(store["address"]), "cashDesks" => [ %{ "identification" => cash_desk_id } ] } ] aani_params = %{ "merchant" => %{ "bankUserId" => merchant["id"], "name" => first_name, "surname" => surname, "denomination" => merchant["displayName"], "vatNumber" => get_in(merchant, ["legalInfo", "registrationNumber"]) || merchant["id"], "mcc" => merchant["mcc"], "mobile" => get_in(merchant, ["contactInfo", "phone"]), "proxies" => [ %{ "type" => "document-id", "value" => merchant["proxyId"] || get_in(merchant, ["ownerInfo", "id"]) } ], "channelName" => nil, "bankAccounts" => [ %{ "IBAN" => params["iban"], "currency" => "AED" } ], "logo" => merchant["logo"], "shops" => shops } } Logger.info("IBAN values being sent - Merchant bankAccounts IBAN: #{inspect(params["iban"])}") Logger.info("IBAN values being sent - Shop bankAccount IBAN: #{inspect(params["iban"])}") Logger.info("Transformation complete. Output Aani params: #{inspect(aani_params)}") aani_params end # Call the Aani API (mock or real) defp call_aani_api(aani_params, original_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 "} end # Generate request headers according to Aani specification request_id = original_params["requestId"] || generate_unique_request_id() bank_user_id = get_in(aani_params, ["merchant", "bankUserId"]) headers = [ {"Content-Type", "application/json"}, {"RequestId", request_id}, {"BankUserId", bank_user_id}, {"RequestUserId", request_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 {"Authorization", Map.get(headers, "authorization", "Bearer ")} 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, _} -> nil end # Extract required fields bank_user_id = Map.get(headers, "bankuserid") mobile_number = Map.get(params, "mobileNumber") # Build API endpoint URL aani_base_url = "https://npss.services.shukria.ae/NPSS_Channel_Onboard_API/api/AutoMerchant" update_mobile_path = Application.get_env(:da_product_app, :aani_update_mobile_path, "/UpdateMerchantMobile") 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, _} -> nil end # Extract required fields bank_user_id = Map.get(headers, "bankuserid") mcc = Map.get(params, "mcc") # Build API endpoint URL aani_base_url = "https://npss.services.shukria.ae/NPSS_Channel_Onboard_API/api/AutoMerchant" update_mcc_path = Application.get_env(:da_product_app, :aani_update_mcc_path, "/UpdateMerchantMcc") 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")}, {"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 @doc """ Aani-specific merchant deletion logic """ def delete_merchant(params, headers) do # Call the Aani delete API case call_aani_delete_api(params, headers) do {:ok, response} -> Logger.info("Aani merchant deletion successful: #{inspect(response)}") # Save deletion log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_delete_log_to_db(bank_user_id, params, headers, response) end {:ok, response} {:error, reason} -> Logger.error("Aani merchant deletion failed: #{inspect(reason)}") # Save failed deletion log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_delete_log_to_db(bank_user_id, params, headers, %{"error" => reason}) end {:error, reason} end end @doc """ Aani-specific add merchant bank account logic """ def add_merchant_bank_account(params, headers) do # Call the Aani add bank account API case call_aani_add_bank_account_api(params, headers) do {:ok, response} -> Logger.info("Aani merchant bank account addition successful: #{inspect(response)}") # Save bank account addition log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_bank_account_log_to_db(bank_user_id, params, headers, response) end {:ok, response} {:error, reason} -> Logger.error("Aani merchant bank account addition failed: #{inspect(reason)}") # Save failed bank account addition log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_bank_account_log_to_db(bank_user_id, params, headers, %{"error" => reason}) end {:error, reason} end end @doc """ Aani-specific remove merchant bank account logic """ def remove_merchant_bank_account(params, headers) do # Call the Aani remove bank account API case call_aani_remove_bank_account_api(params, headers) do {:ok, response} -> Logger.info("Aani merchant bank account removal successful: #{inspect(response)}") # Save bank account removal log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_bank_account_removal_log_to_db(bank_user_id, params, headers, response) end {:ok, response} {:error, reason} -> Logger.error("Aani merchant bank account removal failed: #{inspect(reason)}") # Save failed bank account removal log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_bank_account_removal_log_to_db(bank_user_id, params, headers, %{"error" => reason}) end {:error, reason} end end @doc """ Aani-specific block merchant bank account logic """ def block_merchant_bank_account(params, headers) do # Call the Aani block bank account API case call_aani_block_bank_account_api(params, headers) do {:ok, response} -> Logger.info("Aani merchant bank account blocking successful: #{inspect(response)}") # Save bank account blocking log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_bank_account_block_log_to_db(bank_user_id, params, headers, response) end {:ok, response} {:error, reason} -> Logger.error("Aani merchant bank account blocking failed: #{inspect(reason)}") # Save failed bank account blocking log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_bank_account_block_log_to_db(bank_user_id, params, headers, %{"error" => reason}) end {:error, reason} end end @doc """ Aani-specific add merchant shop logic """ def add_merchant_shop(params, headers) do # Call the Aani add merchant shop API case call_aani_add_shop_api(params, headers) do {:ok, response} -> Logger.info("Aani merchant shop addition successful: #{inspect(response)}") # Save shop addition log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_shop_addition_log_to_db(bank_user_id, params, headers, response) end {:ok, response} {:error, reason} -> Logger.error("Aani merchant shop addition failed: #{inspect(reason)}") # Save failed shop addition log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_shop_addition_log_to_db(bank_user_id, params, headers, %{"error" => reason}) end {:error, reason} end end @doc """ Aani-specific update merchant shop logic """ def update_merchant_shop(params, headers) do # Call the Aani update merchant shop API case call_aani_update_shop_api(params, headers) do {:ok, response} -> Logger.info("Aani merchant shop update successful: #{inspect(response)}") # Save shop update log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_shop_update_log_to_db(bank_user_id, params, headers, response) end {:ok, response} {:error, reason} -> Logger.error("Aani merchant shop update failed: #{inspect(reason)}") # Save failed shop update log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_shop_update_log_to_db(bank_user_id, params, headers, %{"error" => reason}) end {:error, reason} end end @doc """ Aani-specific delete merchant shop logic """ def delete_merchant_shop(params, headers) do # Call the Aani delete merchant shop API case call_aani_delete_shop_api(params, headers) do {:ok, response} -> Logger.info("Aani merchant shop deletion successful: #{inspect(response)}") # Save shop deletion log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_shop_deletion_log_to_db(bank_user_id, params, headers, response) end {:ok, response} {:error, reason} -> Logger.error("Aani merchant shop deletion failed: #{inspect(reason)}") # Save failed shop deletion log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_shop_deletion_log_to_db(bank_user_id, params, headers, %{"error" => reason}) end {:error, reason} end end @doc """ Aani-specific add merchant shop cash desk logic """ def add_merchant_shop_cash_desk(params, headers) do # Call the Aani add merchant shop cash desk API case call_aani_add_cash_desk_api(params, headers) do {:ok, response} -> Logger.info("Aani merchant shop cash desk addition successful: #{inspect(response)}") # Save cash desk addition log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_cash_desk_addition_log_to_db(bank_user_id, params, headers, response) end {:ok, response} {:error, reason} -> Logger.error("Aani merchant shop cash desk addition failed: #{inspect(reason)}") # Save failed cash desk addition log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_cash_desk_addition_log_to_db(bank_user_id, params, headers, %{"error" => reason}) end {:error, reason} end end @doc """ Aani-specific update merchant shop cash desk logic """ def update_merchant_shop_cash_desk(params, headers) do # Call the Aani update merchant shop cash desk API case call_aani_update_cash_desk_api(params, headers) do {:ok, response} -> Logger.info("Aani merchant shop cash desk update successful: #{inspect(response)}") # Save cash desk update log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_cash_desk_update_log_to_db(bank_user_id, params, headers, response) end {:ok, response} {:error, reason} -> Logger.error("Aani merchant shop cash desk update failed: #{inspect(reason)}") # Save failed cash desk update log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_cash_desk_update_log_to_db(bank_user_id, params, headers, %{"error" => reason}) end {:error, reason} end end @doc """ Aani-specific delete merchant shop cash desk logic """ def delete_merchant_shop_cash_desk(params, headers) do # Call the Aani delete merchant shop cash desk API case call_aani_delete_cash_desk_api(params, headers) do {:ok, response} -> Logger.info("Aani merchant shop cash desk deletion successful: #{inspect(response)}") # Save cash desk deletion log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_cash_desk_deletion_log_to_db(bank_user_id, params, headers, response) end {:ok, response} {:error, reason} -> Logger.error("Aani merchant shop cash desk deletion failed: #{inspect(reason)}") # Save failed cash desk deletion log to database bank_user_id = Map.get(headers, "bankuserid") if bank_user_id do save_cash_desk_deletion_log_to_db(bank_user_id, params, headers, %{"error" => reason}) end {:error, reason} end end @doc """ Call the Aani API to delete merchant """ def call_aani_delete_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, _} -> nil end # Extract required fields bank_user_id = Map.get(headers, "bankuserid") request_id = Map.get(headers, "requestid") || generate_unique_request_id() request_user_id = Map.get(headers, "requestuserid") merchant_tag = Map.get(headers, "merchanttag", "") # Build API endpoint URL aani_base_url = "https://npss.services.shukria.ae/NPSS_Channel_Onboard_API/api/AutoMerchant" delete_path = "/DeleteMerchant" delete_url = aani_base_url <> delete_path # Prepare headers according to Aani specification http_headers = [ {"Content-Type", "application/json"}, {"RequestId", request_id}, {"BankUserId", bank_user_id}, {"RequestUserId", request_user_id}, {"MerchantTag", merchant_tag}, {"Authorization", "Bearer #{token || ""}"} ] # Empty payload for delete operation (all info is in headers) payload = %{} # Log request details Logger.info("Aani merchant delete request: URL=#{delete_url}, Headers=#{inspect(http_headers)}, Payload=#{inspect(payload)}") # Make the API call case HTTPoison.post(delete_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 merchant deletion 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 merchant deletion failed with status #{status_code}: #{body}") {:error, %{status_code: status_code, body: body}} {:error, %HTTPoison.Error{reason: reason}} -> # HTTP client error Logger.error("Aani merchant deletion request failed: #{inspect(reason)}") {:error, reason} end end @doc """ Call the Aani API to add merchant bank account """ def call_aani_add_bank_account_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, _} -> nil end # Extract required fields bank_user_id = Map.get(headers, "bankuserid") request_id = Map.get(headers, "requestid") || generate_unique_request_id() request_user_id = Map.get(headers, "requestuserid") merchant_tag = Map.get(headers, "merchanttag", "") # Build API endpoint URL aani_base_url = "https://npss.services.shukria.ae/NPSS_Channel_Onboard_API/api/AutoMerchant" add_bank_account_path = "/AddMerchantBankAccount" add_bank_account_url = aani_base_url <> add_bank_account_path # Prepare headers according to Aani specification http_headers = [ {"Content-Type", "application/json"}, {"RequestId", request_id}, {"BankUserId", bank_user_id}, {"RequestUserId", request_user_id}, {"MerchantTag", merchant_tag}, {"Authorization", "Bearer #{token || ""}"} ] # Prepare request payload with bank accounts bank_accounts = Map.get(params, "bankAccounts", []) payload = %{ "bankAccounts" => bank_accounts } # Log request details Logger.info("Aani add bank account request: URL=#{add_bank_account_url}, Headers=#{inspect(http_headers)}, Payload=#{inspect(payload)}") # Make the API call case HTTPoison.post(add_bank_account_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 add bank account 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 add bank account failed with status #{status_code}: #{body}") {:error, %{status_code: status_code, body: body}} {:error, %HTTPoison.Error{reason: reason}} -> # HTTP client error Logger.error("Aani add bank account request failed: #{inspect(reason)}") {:error, reason} end end @doc """ Call the Aani API to remove merchant bank account """ def call_aani_remove_bank_account_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, _} -> nil end # Extract required fields bank_user_id = Map.get(headers, "bankuserid") request_id = Map.get(headers, "requestid") || generate_unique_request_id() request_user_id = Map.get(headers, "requestuserid") merchant_tag = Map.get(headers, "merchanttag", "") # Build API endpoint URL aani_base_url = "https://npss.services.shukria.ae/NPSS_Channel_Onboard_API/api/AutoMerchant" remove_bank_account_path = "/RemoveMerchantBankAccount" remove_bank_account_url = aani_base_url <> remove_bank_account_path # Prepare headers according to Aani specification http_headers = [ {"Content-Type", "application/json"}, {"RequestId", request_id}, {"BankUserId", bank_user_id}, {"RequestUserId", request_user_id}, {"MerchantTag", merchant_tag}, {"Authorization", "Bearer #{token || ""}"} ] # Prepare request payload - extract bank account identifiers from params # Expected format: [{"ibaNorAccountIdentifier": "AE08273527616218612232"}] bank_account_identifiers = Map.get(params, "bankAccountIdentifiers", []) payload = bank_account_identifiers # Log request details Logger.info("Aani remove bank account request: URL=#{remove_bank_account_url}, Headers=#{inspect(http_headers)}, Payload=#{inspect(payload)}") # Make the API call case HTTPoison.post(remove_bank_account_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 remove bank account 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 remove bank account failed with status #{status_code}: #{body}") {:error, %{status_code: status_code, body: body}} {:error, %HTTPoison.Error{reason: reason}} -> # HTTP client error Logger.error("Aani remove bank account request failed: #{inspect(reason)}") {:error, reason} end end @doc """ Call the Aani API to block merchant bank account """ def call_aani_block_bank_account_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, _} -> nil end # Extract required fields bank_user_id = Map.get(headers, "bankuserid") request_id = Map.get(headers, "requestid") || generate_unique_request_id() request_user_id = Map.get(headers, "requestuserid") merchant_tag = Map.get(headers, "merchanttag", "") # Build API endpoint URL aani_base_url = "https://npss.services.shukria.ae/NPSS_Channel_Onboard_API/api/AutoMerchant" block_bank_account_path = "/BlockMerchantBankAccount" block_bank_account_url = aani_base_url <> block_bank_account_path # Prepare headers according to Aani specification http_headers = [ {"Content-Type", "application/json"}, {"RequestId", request_id}, {"BankUserId", bank_user_id}, {"RequestUserId", request_user_id}, {"MerchantTag", merchant_tag}, {"Authorization", "Bearer #{token || ""}"} ] # Prepare request payload with bank accounts # Support both IBAN and accountIdentifier formats bank_accounts = Map.get(params, "bankAccounts", []) payload = %{ "bankAccounts" => bank_accounts } # Log request details Logger.info("Aani block bank account request: URL=#{block_bank_account_url}, Headers=#{inspect(http_headers)}, Payload=#{inspect(payload)}") # Make the API call case HTTPoison.post(block_bank_account_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 block bank account 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 block bank account failed with status #{status_code}: #{body}") {:error, %{status_code: status_code, body: body}} {:error, %HTTPoison.Error{reason: reason}} -> # HTTP client error Logger.error("Aani block bank account request failed: #{inspect(reason)}") {:error, reason} end end @doc """ Call the Aani API to add merchant shop """ def call_aani_add_shop_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, _} -> nil end # Extract required fields bank_user_id = Map.get(headers, "bankuserid") request_id = Map.get(headers, "requestid") || generate_unique_request_id() request_user_id = Map.get(headers, "requestuserid") merchant_tag = Map.get(headers, "merchanttag", "") # Build API endpoint URL aani_base_url = "https://npss.services.shukria.ae/NPSS_Channel_Onboard_API/api/AutoMerchant" add_shop_path = "/AddMerchantShop" add_shop_url = aani_base_url <> add_shop_path # Prepare headers according to Aani specification http_headers = [ {"Content-Type", "application/json"}, {"RequestId", request_id}, {"BankUserId", bank_user_id}, {"RequestUserId", request_user_id}, {"MerchantTag", merchant_tag}, {"Authorization", "Bearer #{token || ""}"} ] # Prepare request payload with shop information shop_data = Map.get(params, "shop", %{}) payload = %{ "shop" => shop_data } # Log request details Logger.info("Aani add shop request: URL=#{add_shop_url}, Headers=#{inspect(http_headers)}, Payload=#{inspect(payload)}") # Make the API call case HTTPoison.post(add_shop_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 add shop 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 add shop failed with status #{status_code}: #{body}") {:error, %{status_code: status_code, body: body}} {:error, %HTTPoison.Error{reason: reason}} -> # HTTP client error Logger.error("Aani add shop request failed: #{inspect(reason)}") {:error, reason} end end @doc """ Save delete operation log to merchant_enrollments table """ def save_delete_log_to_db(bank_user_id, delete_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 delete 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 delete log entry delete_log_entry = %{ timestamp: DateTime.utc_now(), operation: "delete_merchant", request_params: delete_params, request_headers: request_headers, response: response, request_id: Map.get(request_headers, "requestid") } new_update_logs = [delete_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 delete logs for group_id #{group.id}") :ok {:error, err} -> Logger.error("Failed to update MerchantEnrollment delete logs: #{inspect(err)}") :error end end end end @doc """ Save bank account addition operation log to merchant_enrollments table """ def save_bank_account_log_to_db(bank_user_id, bank_account_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 bank account 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 bank account addition log entry bank_account_log_entry = %{ timestamp: DateTime.utc_now(), operation: "add_merchant_bank_account", request_params: bank_account_params, request_headers: request_headers, response: response, request_id: Map.get(request_headers, "requestid") } new_update_logs = [bank_account_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 bank account logs for group_id #{group.id}") :ok {:error, err} -> Logger.error("Failed to update MerchantEnrollment bank account logs: #{inspect(err)}") :error end end end end @doc """ Save bank account removal operation log to merchant_enrollments table """ def save_bank_account_removal_log_to_db(bank_user_id, bank_account_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 bank account removal 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 bank account removal log entry bank_account_removal_log_entry = %{ timestamp: DateTime.utc_now(), operation: "remove_merchant_bank_account", request_params: bank_account_params, request_headers: request_headers, response: response, request_id: Map.get(request_headers, "requestid") } new_update_logs = [bank_account_removal_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 bank account removal logs for group_id #{group.id}") :ok {:error, err} -> Logger.error("Failed to update MerchantEnrollment bank account removal logs: #{inspect(err)}") :error end end end end @doc """ Save bank account blocking operation log to merchant_enrollments table """ def save_bank_account_block_log_to_db(bank_user_id, bank_account_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 bank account blocking 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 bank account blocking log entry bank_account_block_log_entry = %{ timestamp: DateTime.utc_now(), operation: "block_merchant_bank_account", request_params: bank_account_params, request_headers: request_headers, response: response, request_id: Map.get(request_headers, "requestid") } new_update_logs = [bank_account_block_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 bank account blocking logs for group_id #{group.id}") :ok {:error, err} -> Logger.error("Failed to update MerchantEnrollment bank account blocking logs: #{inspect(err)}") :error end end end end @doc """ Save shop addition operation log to merchant_enrollments table """ def save_shop_addition_log_to_db(bank_user_id, shop_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 shop addition 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 shop addition log entry shop_addition_log_entry = %{ timestamp: DateTime.utc_now(), operation: "add_merchant_shop", request_params: shop_params, request_headers: request_headers, response: response, request_id: Map.get(request_headers, "requestid") } new_update_logs = [shop_addition_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 shop addition logs for group_id #{group.id}") :ok {:error, err} -> Logger.error("Failed to update MerchantEnrollment shop addition logs: #{inspect(err)}") :error end end end end # Get base URL for Aani service (registration) defp get_aani_base_url do # Use the new onboarding endpoint for all environments "https://npss.services.shukria.ae/NPSS_Channel_Onboard_API/api/AutoMerchant/EnrollMerchant" 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://api.aani.ae/merchant/inquiry" # Use real API for all environments 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://api.aani.ae/merchant/update" # Use real API for all environments # _ -> "https://demo.ctrmv.com:4004/aani_update_details.php" # Local PHP mock for updates - COMMENTED OUT end end @doc """ Call the Aani API to update merchant shop """ def call_aani_update_shop_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, _} -> nil end # Extract shop ID from params shop_id = Map.get(params, "shopId") # Extract shop data from params shop_data = Map.get(params, "shop", %{}) # Build API endpoint URL with shop ID aani_base_url = "https://npss.services.shukria.ae/NPSS_Channel_Onboard_API/api/AutoMerchant" update_shop_path = "/UpdateMerchantShop/#{shop_id}" update_url = aani_base_url <> update_shop_path # Prepare request payload according to Aani specification payload = %{ "shop" => shop_data } 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", Map.get(headers, "bankuserid")}, {"RequestUserId", Map.get(headers, "requestuserid")}, {"MerchantTag", Map.get(headers, "merchanttag", "")}, {"Authorization", "Bearer #{token || ""}"} ] # Log request details Logger.info("Aani shop 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 shop 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 shop 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 shop update request failed: #{inspect(reason)}") {:error, reason} end end @doc """ Save shop update operation log to merchant_enrollments table """ def save_shop_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 bank_user_id: #{bank_user_id}") :error group -> # Check if merchant enrollment exists for this group and Aani provider case Repo.get_by(MerchantEnrollment, group_id: group.id, provider: "aani") do nil -> Logger.warning("No Aani merchant enrollment found for group_id: #{group.id}") :error enrollment -> # Update existing enrollment with shop update operation current_history = Map.get(enrollment.inquiry_history, "results", []) new_operation = %{ "operation" => "update_shop", "shop_id" => Map.get(update_params, "shopId"), "shop_data" => Map.get(update_params, "shop", %{}), "headers" => request_headers, "response" => response, "timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(), "status" => "success" } updated_history = %{ "results" => [new_operation | current_history] } update_attrs = %{ inquiry_history: updated_history } case Repo.update(Ecto.Changeset.change(enrollment, update_attrs)) do {:ok, updated_enrollment} -> Logger.info("Shop update operation logged for enrollment_id: #{updated_enrollment.id}") {:ok, updated_enrollment} {:error, changeset} -> Logger.error("Failed to log shop update operation: #{inspect(changeset.errors)}") {:error, changeset} end end end end @doc """ Call the Aani API to delete merchant shop """ def call_aani_delete_shop_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, _} -> nil end # Extract shop ID from params shop_id = Map.get(params, "shopId") # Build API endpoint URL with shop ID aani_base_url = "https://npss.services.shukria.ae/NPSS_Channel_Onboard_API/api/AutoMerchant" delete_shop_path = "/DeleteMerchantShop/#{shop_id}" delete_url = aani_base_url <> delete_shop_path 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", Map.get(headers, "bankuserid")}, {"RequestUserId", Map.get(headers, "requestuserid")}, {"MerchantTag", Map.get(headers, "merchanttag", "")}, {"Authorization", "Bearer #{token || ""}"} ] # Log request details Logger.info("Aani shop deletion request: URL=#{delete_url}, Headers=#{inspect(http_headers)}") # Make the API call (DELETE request with no body) case HTTPoison.delete(delete_url, http_headers, []) do {:ok, %HTTPoison.Response{status_code: status_code, body: body}} when status_code in 200..299 -> # Success response Logger.info("Aani shop deletion 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 shop deletion failed with status #{status_code}: #{body}") {:error, %{status_code: status_code, body: body}} {:error, %HTTPoison.Error{reason: reason}} -> # HTTP client error Logger.error("Aani shop deletion request failed: #{inspect(reason)}") {:error, reason} end end @doc """ Save shop deletion operation log to merchant_enrollments table """ def save_shop_deletion_log_to_db(bank_user_id, delete_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 bank_user_id: #{bank_user_id}") :error group -> # Check if merchant enrollment exists for this group and Aani provider case Repo.get_by(MerchantEnrollment, group_id: group.id, provider: "aani") do nil -> Logger.warning("No Aani merchant enrollment found for group_id: #{group.id}") :error enrollment -> # Update existing enrollment with shop deletion operation current_history = Map.get(enrollment.inquiry_history, "results", []) new_operation = %{ "operation" => "delete_shop", "shop_id" => Map.get(delete_params, "shopId"), "headers" => request_headers, "response" => response, "timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(), "status" => "success" } updated_history = %{ "results" => [new_operation | current_history] } update_attrs = %{ inquiry_history: updated_history } case Repo.update(Ecto.Changeset.change(enrollment, update_attrs)) do {:ok, updated_enrollment} -> Logger.info("Shop deletion operation logged for enrollment_id: #{updated_enrollment.id}") {:ok, updated_enrollment} {:error, changeset} -> Logger.error("Failed to log shop deletion operation: #{inspect(changeset.errors)}") {:error, changeset} end end end end @doc """ Call the Aani API to add merchant shop cash desk """ def call_aani_add_cash_desk_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, _} -> nil end # Extract shop ID from params shop_id = Map.get(params, "shopId") # Extract cash desks data from params cash_desks_data = Map.get(params, "cashDesks", []) # Build API endpoint URL with shop ID aani_base_url = "https://npss.services.shukria.ae/NPSS_Channel_Onboard_API/api/AutoMerchant" add_cash_desk_path = "/AddMerchantShopCashDesk/#{shop_id}" add_url = aani_base_url <> add_cash_desk_path # Prepare request payload according to Aani specification payload = %{ "cashDesks" => cash_desks_data } 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", Map.get(headers, "bankuserid")}, {"RequestUserId", Map.get(headers, "requestuserid")}, {"MerchantTag", Map.get(headers, "merchanttag", "")}, {"Authorization", "Bearer #{token || ""}"} ] # Log request details Logger.info("Aani cash desk addition request: URL=#{add_url}, Headers=#{inspect(http_headers)}, Payload=#{inspect(payload)}") # Make the API call case HTTPoison.post(add_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 cash desk addition 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 cash desk addition failed with status #{status_code}: #{body}") {:error, %{status_code: status_code, body: body}} {:error, %HTTPoison.Error{reason: reason}} -> # HTTP client error Logger.error("Aani cash desk addition request failed: #{inspect(reason)}") {:error, reason} end end @doc """ Save cash desk addition operation log to merchant_enrollments table """ def save_cash_desk_addition_log_to_db(bank_user_id, addition_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 bank_user_id: #{bank_user_id}") :error group -> # Check if merchant enrollment exists for this group and Aani provider case Repo.get_by(MerchantEnrollment, group_id: group.id, provider: "aani") do nil -> Logger.warning("No Aani merchant enrollment found for group_id: #{group.id}") :error enrollment -> # Update existing enrollment with cash desk addition operation current_history = Map.get(enrollment.inquiry_history, "results", []) new_operation = %{ "operation" => "add_cash_desk", "shop_id" => Map.get(addition_params, "shopId"), "cash_desks" => Map.get(addition_params, "cashDesks", []), "headers" => request_headers, "response" => response, "timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(), "status" => "success" } updated_history = %{ "results" => [new_operation | current_history] } update_attrs = %{ inquiry_history: updated_history } case Repo.update(Ecto.Changeset.change(enrollment, update_attrs)) do {:ok, updated_enrollment} -> Logger.info("Cash desk addition operation logged for enrollment_id: #{updated_enrollment.id}") {:ok, updated_enrollment} {:error, changeset} -> Logger.error("Failed to log cash desk addition operation: #{inspect(changeset.errors)}") {:error, changeset} end end end end @doc """ Call the Aani API to update merchant shop cash desk """ def call_aani_update_cash_desk_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, _} -> nil end # Extract shop ID from params shop_id = Map.get(params, "shopId") # Extract cash desks data from params cash_desks_data = Map.get(params, "cashDesks", []) # Build API endpoint URL with shop ID aani_base_url = "https://npss.services.shukria.ae/NPSS_Channel_Onboard_API/api/AutoMerchant" update_cash_desk_path = "/UpdateMerchantShopCashDesk/#{shop_id}" update_url = aani_base_url <> update_cash_desk_path # Prepare request payload according to Aani specification payload = %{ "cashDesks" => cash_desks_data } 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", Map.get(headers, "bankuserid")}, {"RequestUserId", Map.get(headers, "requestuserid")}, {"MerchantTag", Map.get(headers, "merchanttag", "")}, {"Authorization", "Bearer #{token || ""}"} ] # Log request details Logger.info("Aani cash desk update request: URL=#{update_url}, Headers=#{inspect(http_headers)}, Payload=#{inspect(payload)}") # Make the API call using PUT method for update case HTTPoison.put(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 cash desk 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 cash desk 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 cash desk update request failed: #{inspect(reason)}") {:error, reason} end end @doc """ Save cash desk update operation log to merchant_enrollments table """ def save_cash_desk_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 bank_user_id: #{bank_user_id}") :error group -> # Check if merchant enrollment exists for this group and Aani provider case Repo.get_by(MerchantEnrollment, group_id: group.id, provider: "aani") do nil -> Logger.warning("No Aani merchant enrollment found for group_id: #{group.id}") :error enrollment -> # Update existing enrollment with cash desk update operation current_history = Map.get(enrollment.inquiry_history, "results", []) new_operation = %{ "operation" => "update_cash_desk", "shop_id" => Map.get(update_params, "shopId"), "cash_desks" => Map.get(update_params, "cashDesks", []), "headers" => request_headers, "response" => response, "timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(), "status" => "success" } updated_history = %{ "results" => [new_operation | current_history] } update_attrs = %{ inquiry_history: updated_history } case Repo.update(Ecto.Changeset.change(enrollment, update_attrs)) do {:ok, updated_enrollment} -> Logger.info("Cash desk update operation logged for enrollment_id: #{updated_enrollment.id}") {:ok, updated_enrollment} {:error, changeset} -> Logger.error("Failed to log cash desk update operation: #{inspect(changeset.errors)}") {:error, changeset} end end end end @doc """ Call the Aani API to delete merchant shop cash desk """ def call_aani_delete_cash_desk_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, _} -> nil end # Extract shop ID from params shop_id = Map.get(params, "shopId") # Extract cash desks data from params cash_desks_data = Map.get(params, "cashDesks", []) # Build API endpoint URL with shop ID aani_base_url = "https://npss.services.shukria.ae/NPSS_Channel_Onboard_API/api/AutoMerchant" delete_cash_desk_path = "/DeleteMerchantShopCashDesk/#{shop_id}" delete_url = aani_base_url <> delete_cash_desk_path # Prepare request payload according to Aani specification payload = %{ "cashDesks" => cash_desks_data } 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", Map.get(headers, "bankuserid")}, {"RequestUserId", Map.get(headers, "requestuserid")}, {"MerchantTag", Map.get(headers, "merchanttag", "")}, {"Authorization", "Bearer #{token || ""}"} ] # Log request details Logger.info("Aani cash desk deletion request: URL=#{delete_url}, Headers=#{inspect(http_headers)}, Payload=#{inspect(payload)}") # Make the API call using DELETE method with body case HTTPoison.request(:delete, delete_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 cash desk deletion 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 cash desk deletion failed with status #{status_code}: #{body}") {:error, %{status_code: status_code, body: body}} {:error, %HTTPoison.Error{reason: reason}} -> # HTTP client error Logger.error("Aani cash desk deletion request failed: #{inspect(reason)}") {:error, reason} end end @doc """ Save cash desk deletion operation log to merchant_enrollments table """ def save_cash_desk_deletion_log_to_db(bank_user_id, deletion_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 bank_user_id: #{bank_user_id}") :error group -> # Check if merchant enrollment exists for this group and Aani provider case Repo.get_by(MerchantEnrollment, group_id: group.id, provider: "aani") do nil -> Logger.warning("No Aani merchant enrollment found for group_id: #{group.id}") :error enrollment -> # Update existing enrollment with cash desk deletion operation current_history = Map.get(enrollment.inquiry_history, "results", []) new_operation = %{ "operation" => "delete_cash_desk", "shop_id" => Map.get(deletion_params, "shopId"), "cash_desks" => Map.get(deletion_params, "cashDesks", []), "headers" => request_headers, "response" => response, "timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(), "status" => "success" } updated_history = %{ "results" => [new_operation | current_history] } update_attrs = %{ inquiry_history: updated_history } case Repo.update(Ecto.Changeset.change(enrollment, update_attrs)) do {:ok, updated_enrollment} -> Logger.info("Cash desk deletion operation logged for enrollment_id: #{updated_enrollment.id}") {:ok, updated_enrollment} {:error, changeset} -> Logger.error("Failed to log cash desk deletion operation: #{inspect(changeset.errors)}") {:error, changeset} end end end end # Transform address to Aani format defp transform_address_for_aani(nil), do: nil defp transform_address_for_aani(address) do Logger.info("Transforming address: #{inspect(address)}") transformed = %{ "building" => address["building"] || address["street"], "street" => address["street"], "city" => address["city"], "postalCode" => address["postalCode"], "county" => address["state"] || address["city"], "country" => address["country"] } Logger.info("Transformed address: #{inspect(transformed)}") transformed end # Get primary IBAN from merchant data 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"] true -> nil end 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 nil end # Determine channel name from services defp get_channel_name_from_services(nil), do: nil 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 -> nil end end defp get_channel_name_from_services(_), do: nil # 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" @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") } } {:ok, generic_params} end end