package com.mfsys.uco.service; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.mfsys.comm.exception.ApplicationException; import com.mfsys.comm.exception.ApplicationExceptionMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClientResponseException; import reactor.core.publisher.Mono; import java.io.IOException; @Service @Slf4j public class WebClientDepositService { private final WebClient webClientDeposit; public WebClientDepositService(WebClient webClientDeposit) { this.webClientDeposit = webClientDeposit; } public Object getUcoAccountBalance(String url, String porOrgacode) { return handleResponse(webClientDeposit.get().uri(url).accept(MediaType.APPLICATION_JSON) .header("SUS_USERCODE", porOrgacode) .header("POR_ORGACODE", porOrgacode).retrieve().toEntity(Object.class), null); } public Object getCmpUcoAccounts(String url, String porOrgacode) { return handleResponse(webClientDeposit.get().uri(url).accept(MediaType.APPLICATION_JSON) .header("SUS_USERCODE", porOrgacode) .header("POR_ORGACODE", porOrgacode).retrieve().toEntity(Object.class), null); } public Object postTransaction(Object tranData, String url, String porOrgaCode) { return handleResponse(webClientDeposit.post().uri(url).bodyValue(tranData).accept(MediaType.APPLICATION_JSON) .header("SUS_USERCODE", porOrgaCode) .header("POR_ORGACODE", porOrgaCode).retrieve() .toEntity(Object.class), porOrgaCode); } public String createUcoAccount(Object payload, String url, String porOrgaCode) { return handleResponse(webClientDeposit.post().uri(url).bodyValue(payload).accept(MediaType.APPLICATION_JSON) .header("SUS_USERCODE", porOrgaCode) .header("POR_ORGACODE", porOrgaCode).retrieve() .toEntity(String.class), porOrgaCode); } public Object fetchExchangeRate(String url, String porOrgacode) { return handleResponse(webClientDeposit.get().uri(url).accept(MediaType.APPLICATION_JSON) .header("SUS_USERCODE", porOrgacode) .header("POR_ORGACODE", porOrgacode).retrieve().toEntity(Object.class), null); } public Object fetchUcoDepositProducts(String url, String porOrgacode) { return handleResponse(webClientDeposit.get().uri(url).accept(MediaType.APPLICATION_JSON) .header("SUS_USERCODE", porOrgacode) .header("POR_ORGACODE", porOrgacode).retrieve().toEntity(Object.class), null); } private T handleResponse(Mono> responseMono, String porgaCode) { try { ResponseEntity response = responseMono.block(); return response.getBody(); } catch (WebClientResponseException e) { ApplicationExceptionMapper.APIError errorDetails = parseErrorDetails(e); log.error("UCO Error Status: {}", e.getStatusCode()); log.error("UCO Error Body: {}", e.getResponseBodyAsString()); log.error("UCO Request Headers: {}", e.getRequest().getHeaders()); throw new ApplicationException(porgaCode, errorDetails.getErrorCode(), errorDetails.getArguments()); } } private ApplicationExceptionMapper.APIError parseErrorDetails(WebClientResponseException e) { String errorCode = null; Object[] arguments = new Object[0]; if (e.getResponseBodyAsString() != null) { try { ObjectMapper objectMapper = new ObjectMapper(); JsonNode errorNode = objectMapper.readTree(e.getResponseBodyAsString()); JsonNode errorCodeNode = errorNode.get("errorCode"); if (errorCodeNode != null && !errorCodeNode.isNull()) { errorCode = errorCodeNode.asText(); } else { JsonNode debugNode = errorNode.get("debugMessage"); errorCode = (debugNode != null && !debugNode.isNull()) ? debugNode.asText() : "ERR_REMOTE_" + e.getStatusCode().value(); } JsonNode argsNode = errorNode.get("arguments"); if (argsNode != null && !argsNode.isNull()) { arguments = objectMapper.convertValue(argsNode, String[].class); } } catch (IOException ex) { errorCode = "ERR_REMOTE_" + e.getStatusCode().value(); } } else { errorCode = "ERR_REMOTE_" + e.getStatusCode().value(); } return new ApplicationExceptionMapper.APIError(errorCode, arguments); } }