Code development platform for open source projects from the European Union institutions

Skip to content
Snippets Groups Projects
Commit 12eb7dd7 authored by Joze RIHTARSIC's avatar Joze RIHTARSIC
Browse files

Pull request #136: [EDELIVERY-13839] fix redirection on invalid reset password

Merge in EDELIVERY/smp from bugfix/EDELIVERY-13839-rest-error-fix-redirection to development

* commit '119394ea':
  [EDELIVERY-13839] fix redirection on invalid reset password
parents dc0e31b5 119394ea
No related branches found
No related tags found
No related merge requests found
Showing
with 71 additions and 28 deletions
/**
* The used SMP error codes in the application. The SMP can send different error codes in the repponse,
* but the application only uses a subset of them.
*
* @since 5.1
* @author Joze RIHTARSIC
*/
export enum SmpErrorCode {
ERROR_CODE_INVALID_NEW_PASSWORD = 'SMP:010',
}
...@@ -15,6 +15,7 @@ import {MatDialog} from "@angular/material/dialog"; ...@@ -15,6 +15,7 @@ import {MatDialog} from "@angular/material/dialog";
import {Router} from "@angular/router"; import {Router} from "@angular/router";
import {TranslateService} from "@ngx-translate/core"; import {TranslateService} from "@ngx-translate/core";
import {WindowSpinnerService} from "../common/services/window-spinner.service"; import {WindowSpinnerService} from "../common/services/window-spinner.service";
import {SmpErrorCode} from "../common/enums/smp-error-code.enum";
@Injectable() @Injectable()
export class SecurityService { export class SecurityService {
...@@ -122,7 +123,11 @@ export class SecurityService { ...@@ -122,7 +123,11 @@ export class SecurityService {
}, // completeHandler }, // completeHandler
error: (error: any) => { error: (error: any) => {
this.windowSpinnerService.showSpinner = false; this.windowSpinnerService.showSpinner = false;
this.router.navigate(['/login']); // if the error is not related to the password, we redirect to the login page
console
if (error.error?.errorCode !== SmpErrorCode.ERROR_CODE_INVALID_NEW_PASSWORD) {
this.router.navigate(['/login']);
}
this.alertService.error(error); this.alertService.error(error);
}, // errorHandler }, // errorHandler
next: async () => { next: async () => {
...@@ -194,13 +199,15 @@ export class SecurityService { ...@@ -194,13 +199,15 @@ export class SecurityService {
let subject = new ReplaySubject<boolean>(); let subject = new ReplaySubject<boolean>();
if (callServer) { if (callServer) {
//we get the username from the server to trigger the redirection to the login screen in case the user is not authenticated //we get the username from the server to trigger the redirection to the login screen in case the user is not authenticated
this.getCurrentUsernameFromServer().subscribe((user: User) => { this.getCurrentUsernameFromServer().subscribe({
if (!user) { next: (user: User) => {
this.clearLocalStorage(); if (!user) {
this.clearLocalStorage();
}
subject.next(user !== null);
}, error: (user: any) => {
subject.next(false);
} }
subject.next(user !== null);
}, (user: string) => {
subject.next(false);
}); });
} else { } else {
......
...@@ -28,6 +28,7 @@ import java.util.Objects; ...@@ -28,6 +28,7 @@ import java.util.Objects;
*/ */
public class ErrorResponseRO { public class ErrorResponseRO {
protected String businessCode; protected String businessCode;
protected String errorCode;
protected String errorDescription; protected String errorDescription;
protected String errorUniqueId; protected String errorUniqueId;
...@@ -67,6 +68,13 @@ public class ErrorResponseRO { ...@@ -67,6 +68,13 @@ public class ErrorResponseRO {
this.errorDescription = value; this.errorDescription = value;
} }
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getErrorUniqueId() { public String getErrorUniqueId() {
return errorUniqueId; return errorUniqueId;
......
...@@ -34,6 +34,9 @@ public enum ErrorCode { ...@@ -34,6 +34,9 @@ public enum ErrorCode {
UNAUTHORIZED_INVALID_IDENTIFIER(401, "SMP:005",ErrorBusinessCode.UNAUTHORIZED, "Invalid entity identifier! User not authorized to access the entity data"), UNAUTHORIZED_INVALID_IDENTIFIER(401, "SMP:005",ErrorBusinessCode.UNAUTHORIZED, "Invalid entity identifier! User not authorized to access the entity data"),
UNAUTHORIZED_INVALID_RESET_TOKEN(401, "SMP:006",ErrorBusinessCode.UNAUTHORIZED, "The reset token it is invalid or not active any more. Please try to reset your password again."), UNAUTHORIZED_INVALID_RESET_TOKEN(401, "SMP:006",ErrorBusinessCode.UNAUTHORIZED, "The reset token it is invalid or not active any more. Please try to reset your password again."),
USER_CHANGE_INVALID_NEW_CREDENTIAL(400, "SMP:010",ErrorBusinessCode.INVALID_INPUT_DATA, "Password change failed. %s"),
INVALID_ENCODING (500, "SMP:100",ErrorBusinessCode.TECHNICAL, "Unsupported or invalid encoding for %s!"), INVALID_ENCODING (500, "SMP:100",ErrorBusinessCode.TECHNICAL, "Unsupported or invalid encoding for %s!"),
SML_INVALID_IDENTIFIER (400,"SMP:101",ErrorBusinessCode.FORMAT_ERROR,"Malformed identifier, scheme and id should be delimited by double colon: %s "), SML_INVALID_IDENTIFIER (400,"SMP:101",ErrorBusinessCode.FORMAT_ERROR,"Malformed identifier, scheme and id should be delimited by double colon: %s "),
...@@ -79,6 +82,7 @@ public enum ErrorCode { ...@@ -79,6 +82,7 @@ public enum ErrorCode {
// SML integration // SML integration
SML_INTEGRATION_EXCEPTION (500,"SMP:150",ErrorBusinessCode.TECHNICAL,"SML integration error! Error: %s "), SML_INTEGRATION_EXCEPTION (500,"SMP:150",ErrorBusinessCode.TECHNICAL,"SML integration error! Error: %s "),
XML_SIGNING_EXCEPTION (500,"SMP:500",ErrorBusinessCode.TECHNICAL,"Error occurred while signing response!"), XML_SIGNING_EXCEPTION (500,"SMP:500",ErrorBusinessCode.TECHNICAL,"Error occurred while signing response!"),
INTERNAL_ERROR_GENERIC (500,"SMP:501",ErrorBusinessCode.TECHNICAL, "Internal error!"),
JAXB_INITIALIZATION (500,"SMP:511",ErrorBusinessCode.TECHNICAL, "Could not create Unmarshaller for class [%s]!"), JAXB_INITIALIZATION (500,"SMP:511",ErrorBusinessCode.TECHNICAL, "Could not create Unmarshaller for class [%s]!"),
XML_PARSE_EXCEPTION (500,"SMP:512",ErrorBusinessCode.TECHNICAL, "Error occurred while parsing input stream for [%s]. Error: %s!"), XML_PARSE_EXCEPTION (500,"SMP:512",ErrorBusinessCode.TECHNICAL, "Error occurred while parsing input stream for [%s]. Error: %s!"),
INVALID_REQUEST(400,"SMP:513",ErrorBusinessCode.TECHNICAL, "Invalid request [%s]. Error: %s!"), INVALID_REQUEST(400,"SMP:513",ErrorBusinessCode.TECHNICAL, "Invalid request [%s]. Error: %s!"),
......
...@@ -366,23 +366,24 @@ public class CredentialService { ...@@ -366,23 +366,24 @@ public class CredentialService {
// retrieve user Optional credentials by username // retrieve user Optional credentials by username
Optional<DBCredential> optCredential = getActiveCredentialsForUsernameToReset(username, false); Optional<DBCredential> optCredential = getActiveCredentialsForUsernameToReset(username, false);
if (!optCredential.isPresent()) { if (!optCredential.isPresent()) {
LOG.warn("User [{}] does not have active reset token!", username);
throw UNAUTHORIZED_INVALID_RESET_TOKEN; throw UNAUTHORIZED_INVALID_RESET_TOKEN;
} }
DBCredential dbCredential = optCredential.get(); DBCredential dbCredential = optCredential.get();
if (!resetToken.equals(dbCredential.getResetToken())) { if (!resetToken.equals(dbCredential.getResetToken())) {
LOG.warn("User [{}] reset token does not match the active reset token! The request is ignored", username); LOG.warn("User [{}] reset token does not match the active reset token!", username);
return; throw UNAUTHORIZED_INVALID_RESET_TOKEN;
} }
Pattern pattern = configurationService.getPasswordPolicyRexExp(); Pattern pattern = configurationService.getPasswordPolicyRexExp();
if (pattern != null && !pattern.matcher(newPassword).matches()) { if (pattern != null && !pattern.matcher(newPassword).matches()) {
LOG.info(SMPLogger.SECURITY_MARKER, "Change/set password failed because it does not match password policy!: [{}]", username); LOG.info(SMPLogger.SECURITY_MARKER, "Change/set password failed because it does not match password policy!: [{}]", username);
throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "PasswordChange", configurationService.getPasswordPolicyValidationMessage()); throw new SMPRuntimeException(ErrorCode.USER_CHANGE_INVALID_NEW_CREDENTIAL, configurationService.getPasswordPolicyValidationMessage());
} }
if (StringUtils.isNotBlank(dbCredential.getValue()) && BCrypt.checkpw(newPassword, dbCredential.getValue())) { if (StringUtils.isNotBlank(dbCredential.getValue()) && BCrypt.checkpw(newPassword, dbCredential.getValue())) {
LOG.info(SMPLogger.SECURITY_MARKER, "Change/set password failed because 'new' password match the old password for user: [{}]", username); LOG.info(SMPLogger.SECURITY_MARKER, "Change/set password failed because 'new' password match the old password for user: [{}]", username);
throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "PasswordChange", configurationService.getPasswordPolicyValidationMessage()); throw new SMPRuntimeException(ErrorCode.USER_CHANGE_INVALID_NEW_CREDENTIAL, configurationService.getPasswordPolicyValidationMessage());
} }
OffsetDateTime now = OffsetDateTime.now(); OffsetDateTime now = OffsetDateTime.now();
......
...@@ -114,7 +114,6 @@ public class SMPAuthenticationService { ...@@ -114,7 +114,6 @@ public class SMPAuthenticationService {
credentialService.delayResponse(CredentialType.USERNAME_PASSWORD, startTime); credentialService.delayResponse(CredentialType.USERNAME_PASSWORD, startTime);
throw e; throw e;
} }
credentialService.validatePasswordResetToken(resetToken);
} }
public void logout(HttpServletRequest request, HttpServletResponse response) { public void logout(HttpServletRequest request, HttpServletResponse response) {
......
...@@ -21,9 +21,9 @@ package eu.europa.ec.edelivery.smp.error; ...@@ -21,9 +21,9 @@ package eu.europa.ec.edelivery.smp.error;
import eu.europa.ec.dynamicdiscovery.exception.MalformedIdentifierException; import eu.europa.ec.dynamicdiscovery.exception.MalformedIdentifierException;
import eu.europa.ec.edelivery.smp.data.ui.exceptions.ErrorResponseRO; import eu.europa.ec.edelivery.smp.data.ui.exceptions.ErrorResponseRO;
import eu.europa.ec.edelivery.smp.error.exceptions.SMPResponseStatusException;
import eu.europa.ec.edelivery.smp.exceptions.BadRequestException; import eu.europa.ec.edelivery.smp.exceptions.BadRequestException;
import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode; import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException; import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -43,10 +43,7 @@ abstract class AbstractErrorControllerAdvice { ...@@ -43,10 +43,7 @@ abstract class AbstractErrorControllerAdvice {
ResponseEntity response; ResponseEntity response;
if (runtimeException instanceof SMPRuntimeException) { if (runtimeException instanceof SMPRuntimeException) {
SMPRuntimeException ex = (SMPRuntimeException)runtimeException; SMPRuntimeException ex = (SMPRuntimeException)runtimeException;
response = buildAndLog(HttpStatus.resolve(ex.getErrorCode().getHttpCode()), ex.getErrorCode().getErrorBusinessCode(), ex.getMessage(), ex); response = buildAndLog(HttpStatus.resolve(ex.getErrorCode().getHttpCode()), ex.getErrorCode(), ex.getMessage(), ex);
} else if (runtimeException instanceof SMPResponseStatusException ){
SMPResponseStatusException ex = (SMPResponseStatusException)runtimeException;
response = buildAndLog(ex.getStatus(), ex.getErrorBusinessCode(), ex.getMessage(), ex);
} else if (runtimeException instanceof AuthenticationException ){ } else if (runtimeException instanceof AuthenticationException ){
AuthenticationException ex = (AuthenticationException)runtimeException; AuthenticationException ex = (AuthenticationException)runtimeException;
response = buildAndLog(UNAUTHORIZED, ErrorBusinessCode.UNAUTHORIZED, ex.getMessage(), ex); response = buildAndLog(UNAUTHORIZED, ErrorBusinessCode.UNAUTHORIZED, ex.getMessage(), ex);
...@@ -66,7 +63,7 @@ abstract class AbstractErrorControllerAdvice { ...@@ -66,7 +63,7 @@ abstract class AbstractErrorControllerAdvice {
} }
String errorCodeId = response.getBody() instanceof ErrorResponseRO? String errorCodeId = response.getBody()!=null && response.getBody() instanceof ErrorResponseRO?
((ErrorResponseRO) response.getBody()).getErrorUniqueId(): null; ((ErrorResponseRO) response.getBody()).getErrorUniqueId(): null;
...@@ -74,5 +71,16 @@ abstract class AbstractErrorControllerAdvice { ...@@ -74,5 +71,16 @@ abstract class AbstractErrorControllerAdvice {
return response; return response;
} }
abstract ResponseEntity buildAndLog(HttpStatus status, ErrorBusinessCode businessCode, String msg, Exception exception);
ResponseEntity buildAndLog(HttpStatus status, ErrorBusinessCode businessCode, String msg, Exception exception) {
return buildAndLog(status, ErrorCode.INTERNAL_ERROR_GENERIC, businessCode, msg, exception);
}
ResponseEntity buildAndLog(HttpStatus status, ErrorCode errorCode, String msg, Exception exception) {
return buildAndLog(status, errorCode, errorCode.getErrorBusinessCode(), msg, exception);
}
abstract ResponseEntity buildAndLog(HttpStatus status, ErrorCode errorCode,
ErrorBusinessCode businessCode,
String msg, Exception exception);
} }
...@@ -24,6 +24,7 @@ package eu.europa.ec.edelivery.smp.error; ...@@ -24,6 +24,7 @@ package eu.europa.ec.edelivery.smp.error;
import eu.europa.ec.edelivery.smp.data.ui.exceptions.ErrorResponseRO; import eu.europa.ec.edelivery.smp.data.ui.exceptions.ErrorResponseRO;
import eu.europa.ec.edelivery.smp.error.xml.ErrorResponse; import eu.europa.ec.edelivery.smp.error.xml.ErrorResponse;
import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode; import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
...@@ -42,11 +43,10 @@ import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; ...@@ -42,11 +43,10 @@ import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
*/ */
public class ErrorResponseBuilder { public class ErrorResponseBuilder {
private static final Logger LOG = LoggerFactory.getLogger(ErrorResponseBuilder.class);
public static final MediaType CONTENT_TYPE_TEXT_XML_UTF8 = MediaType.valueOf("text/xml; charset=UTF-8"); public static final MediaType CONTENT_TYPE_TEXT_XML_UTF8 = MediaType.valueOf("text/xml; charset=UTF-8");
private HttpStatus status = INTERNAL_SERVER_ERROR; private HttpStatus status = INTERNAL_SERVER_ERROR;
private ErrorBusinessCode errorBusinessCode = TECHNICAL; private ErrorBusinessCode errorBusinessCode = TECHNICAL;
private ErrorCode errorCode = ErrorCode.INTERNAL_ERROR_GENERIC;
private String strErrorDescription = "Unexpected technical error occurred."; private String strErrorDescription = "Unexpected technical error occurred.";
private static String getErrorUniqueId() { private static String getErrorUniqueId() {
...@@ -78,6 +78,7 @@ public class ErrorResponseBuilder { ...@@ -78,6 +78,7 @@ public class ErrorResponseBuilder {
public ErrorResponseRO buildJSonBody() { public ErrorResponseRO buildJSonBody() {
ErrorResponseRO err = new ErrorResponseRO(); ErrorResponseRO err = new ErrorResponseRO();
err.setBusinessCode(errorBusinessCode.name()); err.setBusinessCode(errorBusinessCode.name());
err.setErrorCode(errorCode.getErrorCode());
err.setErrorDescription(strErrorDescription); err.setErrorDescription(strErrorDescription);
err.setErrorUniqueId(getErrorUniqueId()); err.setErrorUniqueId(getErrorUniqueId());
return err; return err;
...@@ -88,6 +89,11 @@ public class ErrorResponseBuilder { ...@@ -88,6 +89,11 @@ public class ErrorResponseBuilder {
return this; return this;
} }
public ErrorResponseBuilder errorCode(ErrorCode errorCode) {
this.errorCode = errorCode;
return this;
}
public ErrorResponseBuilder errorDescription(String newErrorDescription) { public ErrorResponseBuilder errorDescription(String newErrorDescription) {
this.strErrorDescription = newErrorDescription; this.strErrorDescription = newErrorDescription;
return this; return this;
......
...@@ -19,10 +19,10 @@ ...@@ -19,10 +19,10 @@
package eu.europa.ec.edelivery.smp.error; package eu.europa.ec.edelivery.smp.error;
import eu.europa.ec.edelivery.smp.error.exceptions.SMPResponseStatusException;
import eu.europa.ec.edelivery.smp.error.xml.ErrorResponse; import eu.europa.ec.edelivery.smp.error.xml.ErrorResponse;
import eu.europa.ec.edelivery.smp.exceptions.BadRequestException; import eu.europa.ec.edelivery.smp.exceptions.BadRequestException;
import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode; import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException; import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
...@@ -44,7 +44,7 @@ import static org.springframework.http.HttpStatus.UNAUTHORIZED; ...@@ -44,7 +44,7 @@ import static org.springframework.http.HttpStatus.UNAUTHORIZED;
public class ServiceErrorControllerAdvice extends AbstractErrorControllerAdvice { public class ServiceErrorControllerAdvice extends AbstractErrorControllerAdvice {
@Override @Override
@ExceptionHandler({RuntimeException.class, SMPRuntimeException.class, SMPResponseStatusException.class, AuthenticationException.class,}) @ExceptionHandler({RuntimeException.class, SMPRuntimeException.class, AuthenticationException.class,})
public ResponseEntity handleRuntimeException(RuntimeException ex) { public ResponseEntity handleRuntimeException(RuntimeException ex) {
return super.handleRuntimeException(ex); return super.handleRuntimeException(ex);
} }
...@@ -64,16 +64,16 @@ public class ServiceErrorControllerAdvice extends AbstractErrorControllerAdvice ...@@ -64,16 +64,16 @@ public class ServiceErrorControllerAdvice extends AbstractErrorControllerAdvice
return buildAndLog(UNAUTHORIZED, ErrorBusinessCode.UNAUTHORIZED, ex.getMessage() + " - Only SMP Admin or owner of given ServiceGroup is allowed to perform this action", ex); return buildAndLog(UNAUTHORIZED, ErrorBusinessCode.UNAUTHORIZED, ex.getMessage() + " - Only SMP Admin or owner of given ServiceGroup is allowed to perform this action", ex);
} }
ResponseEntity buildAndLog(HttpStatus status, ErrorBusinessCode businessCode, String msg, Exception exception) { ResponseEntity buildAndLog(HttpStatus status, ErrorCode errorCode, ErrorBusinessCode businessCode, String msg, Exception exception) {
ResponseEntity response = ErrorResponseBuilder.status(status) ResponseEntity response = ErrorResponseBuilder.status(status)
.businessCode(businessCode) .businessCode(businessCode)
.errorCode(errorCode)
.errorDescription(msg) .errorDescription(msg)
.build(); .build();
String errorUniqueId = ((ErrorResponse) response.getBody()).getErrorUniqueId(); String errorUniqueId = ((ErrorResponse) response.getBody()).getErrorUniqueId();
String logMsg = errorUniqueId == null ? "Null Error ID" : format("UI Error unique ID: %s", errorUniqueId); String logMsg = errorUniqueId == null ? "Null Error ID" : format("UI Error unique ID: %s", errorUniqueId);
LOG.warn(logMsg, exception); LOG.warn(logMsg, exception);
return response; return response;
} }
......
...@@ -19,9 +19,9 @@ ...@@ -19,9 +19,9 @@
package eu.europa.ec.edelivery.smp.error; package eu.europa.ec.edelivery.smp.error;
import eu.europa.ec.edelivery.smp.data.ui.exceptions.ErrorResponseRO; import eu.europa.ec.edelivery.smp.data.ui.exceptions.ErrorResponseRO;
import eu.europa.ec.edelivery.smp.error.exceptions.SMPResponseStatusException;
import eu.europa.ec.edelivery.smp.exceptions.BadRequestException; import eu.europa.ec.edelivery.smp.exceptions.BadRequestException;
import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode; import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException; import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
...@@ -47,17 +47,17 @@ public class UIErrorControllerAdvice extends AbstractErrorControllerAdvice { ...@@ -47,17 +47,17 @@ public class UIErrorControllerAdvice extends AbstractErrorControllerAdvice {
@ExceptionHandler({BadCredentialsException.class, @ExceptionHandler({BadCredentialsException.class,
RuntimeException.class, RuntimeException.class,
SMPRuntimeException.class, SMPRuntimeException.class,
SMPResponseStatusException.class,
AuthenticationException.class, AuthenticationException.class,
BadRequestException.class}) BadRequestException.class})
public ResponseEntity handleRuntimeException(RuntimeException ex) { public ResponseEntity handleRuntimeException(RuntimeException ex) {
return super.handleRuntimeException(ex); return super.handleRuntimeException(ex);
} }
ResponseEntity buildAndLog(HttpStatus status, ErrorBusinessCode businessCode, String msg, Exception exception) { protected ResponseEntity buildAndLog(HttpStatus status, ErrorCode errorCode, ErrorBusinessCode businessCode, String msg, Exception exception) {
ResponseEntity response = ErrorResponseBuilder.status(status) ResponseEntity response = ErrorResponseBuilder.status(status)
.businessCode(businessCode) .businessCode(businessCode)
.errorCode(errorCode)
.errorDescription(msg) .errorDescription(msg)
.buildJSon(); .buildJSon();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment