feat: 优化异常返回
diff --git a/payapi-spec/definitions.yaml b/payapi-spec/definitions.yaml
index 89e374d..d45a0d7 100644
--- a/payapi-spec/definitions.yaml
+++ b/payapi-spec/definitions.yaml
@@ -16,6 +16,9 @@
       required:
         - message
       properties:
+        timestamp:
+          type: string
+          format: date-time
         code:
           type: string
           title: 错误码
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/exception/BadRequestError.java b/payapi/src/main/java/com/supwisdom/dlpay/exception/BadRequestError.java
index a32465a..a217fb7 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/exception/BadRequestError.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/exception/BadRequestError.java
@@ -4,23 +4,24 @@
 import org.springframework.web.bind.annotation.ResponseStatus;
 
 @ResponseStatus(HttpStatus.BAD_REQUEST)
-public class BadRequestError extends RuntimeException {
-  public BadRequestError() {
-  }
-
+public class BadRequestError extends BaseRequestError {
   public BadRequestError(String message) {
     super(message);
   }
 
-  public BadRequestError(String message, Throwable cause) {
-    super(message, cause);
+  public BadRequestError(String message, String code) {
+    super(message, code);
   }
 
-  public BadRequestError(Throwable cause) {
-    super(cause);
+  public BadRequestError(String message, Throwable cause, String code) {
+    super(message, cause, code);
   }
 
-  public BadRequestError(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
-    super(message, cause, enableSuppression, writableStackTrace);
+  public BadRequestError(Throwable cause, String code) {
+    super(cause, code);
+  }
+
+  public BadRequestError(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, String code) {
+    super(message, cause, enableSuppression, writableStackTrace, code);
   }
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/exception/BaseRequestError.java b/payapi/src/main/java/com/supwisdom/dlpay/exception/BaseRequestError.java
new file mode 100644
index 0000000..6f181ef
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/exception/BaseRequestError.java
@@ -0,0 +1,38 @@
+package com.supwisdom.dlpay.exception;
+
+public class BaseRequestError extends RuntimeException {
+  private String code;
+
+  public BaseRequestError(String message) {
+    super(message);
+    this.code = "";
+  }
+
+  public BaseRequestError(String message, String code) {
+    super(message);
+    this.code = code;
+  }
+
+  public BaseRequestError(String message, Throwable cause, String code) {
+    super(message, cause);
+    this.code = code;
+  }
+
+  public BaseRequestError(Throwable cause, String code) {
+    super(cause);
+    this.code = code;
+  }
+
+  public BaseRequestError(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, String code) {
+    super(message, cause, enableSuppression, writableStackTrace);
+    this.code = code;
+  }
+
+  public String getCode() {
+    return code;
+  }
+
+  public void setCode(String code) {
+    this.code = code;
+  }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/exception/ConflictError.java b/payapi/src/main/java/com/supwisdom/dlpay/exception/ConflictError.java
index 2cc0de5..3e31f6c 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/exception/ConflictError.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/exception/ConflictError.java
@@ -4,23 +4,24 @@
 import org.springframework.web.bind.annotation.ResponseStatus;
 
 @ResponseStatus(HttpStatus.CONFLICT)
-public class ConflictError extends RuntimeException {
-  public ConflictError() {
-  }
-
+public class ConflictError extends BaseRequestError {
   public ConflictError(String message) {
     super(message);
   }
 
-  public ConflictError(String message, Throwable cause) {
-    super(message, cause);
+  public ConflictError(String message, String code) {
+    super(message, code);
   }
 
-  public ConflictError(Throwable cause) {
-    super(cause);
+  public ConflictError(String message, Throwable cause, String code) {
+    super(message, cause, code);
   }
 
-  public ConflictError(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
-    super(message, cause, enableSuppression, writableStackTrace);
+  public ConflictError(Throwable cause, String code) {
+    super(cause, code);
+  }
+
+  public ConflictError(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, String code) {
+    super(message, cause, enableSuppression, writableStackTrace, code);
   }
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/exception/InternalServerError.java b/payapi/src/main/java/com/supwisdom/dlpay/exception/InternalServerError.java
index 4eb5168..639caf2 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/exception/InternalServerError.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/exception/InternalServerError.java
@@ -4,23 +4,24 @@
 import org.springframework.web.bind.annotation.ResponseStatus;
 
 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
-public class InternalServerError extends RuntimeException {
-  public InternalServerError() {
-  }
-
+public class InternalServerError extends BaseRequestError {
   public InternalServerError(String message) {
     super(message);
   }
 
-  public InternalServerError(String message, Throwable cause) {
-    super(message, cause);
+  public InternalServerError(String message, String code) {
+    super(message, code);
   }
 
-  public InternalServerError(Throwable cause) {
-    super(cause);
+  public InternalServerError(String message, Throwable cause, String code) {
+    super(message, cause, code);
   }
 
-  public InternalServerError(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
-    super(message, cause, enableSuppression, writableStackTrace);
+  public InternalServerError(Throwable cause, String code) {
+    super(cause, code);
+  }
+
+  public InternalServerError(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, String code) {
+    super(message, cause, enableSuppression, writableStackTrace, code);
   }
 }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt
index a939feb..6faa51b 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt
@@ -2,6 +2,7 @@
 
 import com.supwisdom.dlpay.api.bean.JsonResult
 import com.supwisdom.dlpay.api.exception.RequestParamCheckException
+import com.supwisdom.dlpay.exception.BaseRequestError
 import com.supwisdom.dlpay.exception.TransactionException
 import com.supwisdom.dlpay.framework.ResponseBodyBuilder
 import com.supwisdom.dlpay.framework.service.CommonService
@@ -10,6 +11,7 @@
 import org.aspectj.lang.annotation.Around
 import org.aspectj.lang.annotation.Aspect
 import org.aspectj.lang.annotation.Pointcut
+import org.codehaus.jackson.map.Serializers
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.beans.factory.annotation.Value
 import org.springframework.boot.web.servlet.error.ErrorAttributes
@@ -29,6 +31,7 @@
 import org.springframework.web.context.request.WebRequest
 import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler
 import java.lang.reflect.UndeclaredThrowableException
+import java.util.*
 import javax.servlet.http.HttpServletRequest
 import javax.validation.ConstraintViolationException
 
@@ -37,7 +40,7 @@
 class RestControllerAdvice(private val errorAttributes: ErrorAttributes) {
     val logger = KotlinLogging.logger { }
 
-    protected fun getStatus(request: HttpServletRequest): HttpStatus {
+    private fun getStatus(request: HttpServletRequest): HttpStatus {
         val statusCode = request.getAttribute("javax.servlet.error.status_code")
                 ?: return HttpStatus.INTERNAL_SERVER_ERROR
         return try {
@@ -47,6 +50,19 @@
         }
     }
 
+    private fun getBody(ex: Exception, request: HttpServletRequest)
+            : Map<String, Any> {
+        val attributes = this.errorAttributes.getErrorAttributes(ServletWebRequest(request),
+                false)
+        val code = if (ex is BaseRequestError) {
+            ex.code
+        } else {
+            ""
+        }
+        return mapOf("code" to code, "message" to (attributes["message"] ?: ""),
+                "timestamp" to (attributes["timestamp"] ?: Date()))
+    }
+
     @ExceptionHandler
     fun handleException(ex: Exception, request: HttpServletRequest): ResponseEntity<*> {
         logger.error { "Request unhandler exception, url<${request.requestURI}>, ex<${ex.cause}>" }
@@ -59,8 +75,7 @@
                     .exception(undeclared.code(), undeclared, "业务处理错误"))
         }
 
-        val body = this.errorAttributes.getErrorAttributes(ServletWebRequest(request),
-                false)
+        val body = getBody(ex, request)
         val responseStatus = AnnotationUtils.findAnnotation(ex.javaClass, ResponseStatus::class.java)
         val status = responseStatus?.code ?: getStatus(request)
         return ResponseEntity<Map<String, Any>>(body, status)