修复bug;完善错误信息提示机制
This commit is contained in:
@@ -3,3 +3,4 @@ web/dist/
|
|||||||
log/
|
log/
|
||||||
server/src/main/resources/dist/
|
server/src/main/resources/dist/
|
||||||
doc/票通Demo/untitled/.idea/
|
doc/票通Demo/untitled/.idea/
|
||||||
|
server/.kotlin/
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
$VERSION = "1.1"
|
$VERSION = "1.2"
|
||||||
|
|
||||||
$IMAGE = "docker.bbitcn.net/bbit_invoice/server"
|
$IMAGE = "docker.bbitcn.net/bbit_invoice/server"
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ enum class ErrorCode(val code: String, val message: String) {
|
|||||||
UNAUTHORIZED("AUTH.UNAUTHORIZED", "未登录或登录已失效"),
|
UNAUTHORIZED("AUTH.UNAUTHORIZED", "未登录或登录已失效"),
|
||||||
FORBIDDEN("AUTH.FORBIDDEN", "无权限访问"),
|
FORBIDDEN("AUTH.FORBIDDEN", "无权限访问"),
|
||||||
USERNAME_OR_PASSWORD_INVALID("AUTH.USERNAME_OR_PASSWORD_INVALID", "用户名或密码错误"),
|
USERNAME_OR_PASSWORD_INVALID("AUTH.USERNAME_OR_PASSWORD_INVALID", "用户名或密码错误"),
|
||||||
|
ACCOUNT_NOT_FOUND("AUTH.ACCOUNT_NOT_FOUND", "账号不存在"),
|
||||||
|
PASSWORD_INVALID("AUTH.PASSWORD_INVALID", "密码错误"),
|
||||||
USER_DISABLED("AUTH.USER_DISABLED", "用户已禁用"),
|
USER_DISABLED("AUTH.USER_DISABLED", "用户已禁用"),
|
||||||
USER_NOT_FOUND("SYSTEM.USER_NOT_FOUND", "用户不存在"),
|
USER_NOT_FOUND("SYSTEM.USER_NOT_FOUND", "用户不存在"),
|
||||||
ROLE_NOT_FOUND("SYSTEM.ROLE_NOT_FOUND", "角色不存在"),
|
ROLE_NOT_FOUND("SYSTEM.ROLE_NOT_FOUND", "角色不存在"),
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ fun Route.registerUserRoutes() {
|
|||||||
val id = parseUuid(call.parameters["id"] ?: "", "id")
|
val id = parseUuid(call.parameters["id"] ?: "", "id")
|
||||||
val request = call.receive<UpdateUserStatusRequest>()
|
val request = call.receive<UpdateUserStatusRequest>()
|
||||||
runCatching {
|
runCatching {
|
||||||
UserService.updateStatus(id, request)
|
UserService.updateStatus(id, currentUser.id, request)
|
||||||
call.respond(ok<Unit>(message = "状态更新成功"))
|
call.respond(ok<Unit>(message = "状态更新成功"))
|
||||||
OperationLogService.success(call, currentUser, "UPDATE_STATUS", "更新用户状态", start.elapsedNow().inWholeMilliseconds)
|
OperationLogService.success(call, currentUser, "UPDATE_STATUS", "更新用户状态", start.elapsedNow().inWholeMilliseconds)
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
|
|||||||
@@ -30,31 +30,31 @@ object AuthService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val user = dbQuery { UserDao.findByUsername(username) } ?: throw BizException(
|
val user = dbQuery { UserDao.findByUsername(username) } ?: throw BizException(
|
||||||
ErrorCode.USERNAME_OR_PASSWORD_INVALID.code,
|
ErrorCode.ACCOUNT_NOT_FOUND.code,
|
||||||
ErrorCode.USERNAME_OR_PASSWORD_INVALID.message,
|
ErrorCode.ACCOUNT_NOT_FOUND.message,
|
||||||
HttpStatusCode.BadRequest,
|
HttpStatusCode.BadRequest,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!PasswordService.matches(request.password, user[com.bbit.ticket.database.system.SysUserTable.passwordHash])) {
|
if (!PasswordService.matches(request.password, user[SysUserTable.passwordHash])) {
|
||||||
throw BizException(
|
throw BizException(
|
||||||
ErrorCode.USERNAME_OR_PASSWORD_INVALID.code,
|
ErrorCode.PASSWORD_INVALID.code,
|
||||||
ErrorCode.USERNAME_OR_PASSWORD_INVALID.message,
|
ErrorCode.PASSWORD_INVALID.message,
|
||||||
HttpStatusCode.BadRequest,
|
HttpStatusCode.BadRequest,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user[com.bbit.ticket.database.system.SysUserTable.status] != "ENABLED") {
|
if (user[SysUserTable.status] != "ENABLED") {
|
||||||
throw BizException(ErrorCode.USER_DISABLED.code, ErrorCode.USER_DISABLED.message, HttpStatusCode.BadRequest)
|
throw BizException(ErrorCode.USER_DISABLED.code, ErrorCode.USER_DISABLED.message, HttpStatusCode.BadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
val userId = user[com.bbit.ticket.database.system.SysUserTable.id]
|
val userId = user[SysUserTable.id]
|
||||||
val roleCodes = dbQuery { UserDao.findEnabledRoleCodes(userId) }
|
val roleCodes = dbQuery { UserDao.findEnabledRoleCodes(userId) }
|
||||||
|
|
||||||
val (accessToken, expiresIn) = JwtService.issueAccessToken(
|
val (accessToken, expiresIn) = JwtService.issueAccessToken(
|
||||||
userId = userId.toString(),
|
userId = userId.toString(),
|
||||||
username = user[com.bbit.ticket.database.system.SysUserTable.username],
|
username = user[SysUserTable.username],
|
||||||
roles = roleCodes,
|
roles = roleCodes,
|
||||||
tokenVersion = user[com.bbit.ticket.database.system.SysUserTable.tokenVersion],
|
tokenVersion = user[SysUserTable.tokenVersion],
|
||||||
)
|
)
|
||||||
|
|
||||||
dbQuery { UserDao.updateLoginInfo(userId, loginIp) }
|
dbQuery { UserDao.updateLoginInfo(userId, loginIp) }
|
||||||
|
|||||||
@@ -63,7 +63,10 @@ object UserService {
|
|||||||
UserDao.softDelete(id)
|
UserDao.softDelete(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateStatus(id: Uuid, request: UpdateUserStatusRequest) = dbQuery {
|
suspend fun updateStatus(id: Uuid, currentUserId: Uuid, request: UpdateUserStatusRequest) = dbQuery {
|
||||||
|
if (id == currentUserId && request.status != "ENABLED") {
|
||||||
|
throw BizException(ErrorCode.BAD_REQUEST.code, "不能禁用当前登录账号")
|
||||||
|
}
|
||||||
UserDao.requireActive(id)
|
UserDao.requireActive(id)
|
||||||
UserDao.updateStatus(id, request.status)
|
UserDao.updateStatus(id, request.status)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import java.time.OffsetDateTime
|
|||||||
import java.time.ZoneId
|
import java.time.ZoneId
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
private val defaultZone: ZoneId = ZoneId.systemDefault()
|
private val defaultZone: ZoneId = ZoneId.of("Asia/Shanghai")
|
||||||
private val dateTimeFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
|
private val dateTimeFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
|
||||||
|
|
||||||
fun formatDateTime(value: OffsetDateTime?): String? {
|
fun formatDateTime(value: OffsetDateTime?): String? {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ object PTApi {
|
|||||||
|
|
||||||
/** 发送登录短信验证码 2.4 */
|
/** 发送登录短信验证码 2.4 */
|
||||||
suspend fun sendLoginSmsCode(req: GetLoginSmsCodeRequest): LoginSmsCodeResponse =
|
suspend fun sendLoginSmsCode(req: GetLoginSmsCodeRequest): LoginSmsCodeResponse =
|
||||||
PTClient.ptPost("sendLoginSmsCode.pt", req)
|
PTClient.ptPost("sendLoginSmsCode.pt", req, successResultCodes = setOf("0000", "6666"))
|
||||||
|
|
||||||
/** 短信验证码登录 2.5 */
|
/** 短信验证码登录 2.5 */
|
||||||
suspend fun smsLogin(req: SmsLoginRequest): SMSLoginResponse =
|
suspend fun smsLogin(req: SmsLoginRequest): SMSLoginResponse =
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ object PTClient {
|
|||||||
val logger = LoggerFactory.getLogger(PTClient::class.java)
|
val logger = LoggerFactory.getLogger(PTClient::class.java)
|
||||||
private const val CONNECT_TIMEOUT_MS = 10_000
|
private const val CONNECT_TIMEOUT_MS = 10_000
|
||||||
private const val READ_TIMEOUT_MS = 60_000
|
private const val READ_TIMEOUT_MS = 60_000
|
||||||
|
private const val SHANGHAI_TIME_ZONE = "Asia/Shanghai"
|
||||||
val wireJson = Json {
|
val wireJson = Json {
|
||||||
explicitNulls = false
|
explicitNulls = false
|
||||||
ignoreUnknownKeys = true
|
ignoreUnknownKeys = true
|
||||||
@@ -54,7 +55,8 @@ object PTClient {
|
|||||||
suspend inline fun <reified Req, reified Resp> ptGet(
|
suspend inline fun <reified Req, reified Resp> ptGet(
|
||||||
url: String,
|
url: String,
|
||||||
queryParams: Req,
|
queryParams: Req,
|
||||||
headers: Map<String, String> = emptyMap()
|
headers: Map<String, String> = emptyMap(),
|
||||||
|
successResultCodes: Set<String> = setOf("0000"),
|
||||||
): Resp {
|
): Resp {
|
||||||
|
|
||||||
// query -> json
|
// query -> json
|
||||||
@@ -128,6 +130,7 @@ object PTClient {
|
|||||||
message = "response content is null",
|
message = "response content is null",
|
||||||
serialNo = result.serialNo
|
serialNo = result.serialNo
|
||||||
)
|
)
|
||||||
|
ensureInnerResultOk(content, successResultCodes, result.serialNo)
|
||||||
|
|
||||||
return myJson.decodeFromJsonElement(content)
|
return myJson.decodeFromJsonElement(content)
|
||||||
}
|
}
|
||||||
@@ -135,7 +138,8 @@ object PTClient {
|
|||||||
suspend inline fun <reified Req, reified Resp> ptPost(
|
suspend inline fun <reified Req, reified Resp> ptPost(
|
||||||
url: String,
|
url: String,
|
||||||
body: Req,
|
body: Req,
|
||||||
headers: Map<String, String> = emptyMap()
|
headers: Map<String, String> = emptyMap(),
|
||||||
|
successResultCodes: Set<String> = setOf("0000"),
|
||||||
): Resp {
|
): Resp {
|
||||||
// req json
|
// req json
|
||||||
val reqJson = wireJson.encodeToString(body)
|
val reqJson = wireJson.encodeToString(body)
|
||||||
@@ -150,6 +154,7 @@ object PTClient {
|
|||||||
|
|
||||||
val decrypted = disposeResponse(response)
|
val decrypted = disposeResponse(response)
|
||||||
val result = myJson.decodeFromString<PTResponse<JsonElement>>(decrypted)
|
val result = myJson.decodeFromString<PTResponse<JsonElement>>(decrypted)
|
||||||
|
logger.info("res = $result")
|
||||||
if (result.code != "0000") {
|
if (result.code != "0000") {
|
||||||
throw PTException(
|
throw PTException(
|
||||||
code = result.code,
|
code = result.code,
|
||||||
@@ -157,8 +162,14 @@ object PTClient {
|
|||||||
serialNo = result.serialNo
|
serialNo = result.serialNo
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
logger.info("res = $result")
|
val content = result.content
|
||||||
return myJson.decodeFromJsonElement<Resp>(result.content!!)
|
?: throw PTException(
|
||||||
|
code = "CONTENT_NULL",
|
||||||
|
message = "response content is null",
|
||||||
|
serialNo = result.serialNo
|
||||||
|
)
|
||||||
|
ensureInnerResultOk(content, successResultCodes, result.serialNo)
|
||||||
|
return myJson.decodeFromJsonElement<Resp>(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun postJsonRaw(
|
suspend fun postJsonRaw(
|
||||||
@@ -220,7 +231,7 @@ object PTClient {
|
|||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun buildRequestData(content: String): String {
|
fun buildRequestData(content: String): String {
|
||||||
val reqContent: String = SecurityUtil.encrypt3DES(content) ?: ""
|
val reqContent: String = SecurityUtil.encrypt3DES(content) ?: ""
|
||||||
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
|
val sdf = shanghaiDateFormat("yyyy-MM-dd HH:mm:ss")
|
||||||
val map = HashMap<String, String>()
|
val map = HashMap<String, String>()
|
||||||
map["platformCode"] = Global.ptPlatformCode
|
map["platformCode"] = Global.ptPlatformCode
|
||||||
map["signType"] = "RSA"
|
map["signType"] = "RSA"
|
||||||
@@ -287,10 +298,36 @@ object PTClient {
|
|||||||
|
|
||||||
fun ptDate(): String {
|
fun ptDate(): String {
|
||||||
val date = Date()
|
val date = Date()
|
||||||
val sdf = SimpleDateFormat("YYYYMMddHHmmss")
|
val sdf = shanghaiDateFormat("yyyyMMddHHmmss")
|
||||||
val str = Global.ptPlatformAlias + sdf.format(date) + (Math.random() * 90 + 10).toInt()
|
val str = Global.ptPlatformAlias + sdf.format(date) + (Math.random() * 90 + 10).toInt()
|
||||||
println(str)
|
println(str)
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
|
internal fun ensureInnerResultOk(
|
||||||
|
content: JsonElement,
|
||||||
|
successResultCodes: Set<String>,
|
||||||
|
serialNo: String?,
|
||||||
|
) {
|
||||||
|
val contentObject = content as? JsonObject ?: return
|
||||||
|
val resultCode = contentObject.stringOrNull("resultCode") ?: return
|
||||||
|
if (resultCode !in successResultCodes) {
|
||||||
|
throw PTException(
|
||||||
|
code = resultCode,
|
||||||
|
message = contentObject.stringOrNull("resultMsg") ?: "票通业务处理失败",
|
||||||
|
serialNo = serialNo,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
|
internal fun JsonObject.stringOrNull(key: String): String? =
|
||||||
|
(this[key] as? JsonPrimitive)?.content?.trim()?.takeIf { it.isNotEmpty() }
|
||||||
|
|
||||||
|
private fun shanghaiDateFormat(pattern: String): SimpleDateFormat =
|
||||||
|
SimpleDateFormat(pattern).apply {
|
||||||
|
timeZone = TimeZone.getTimeZone(SHANGHAI_TIME_ZONE)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{traceId}] %logger{40} - %msg%n</pattern>
|
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS, Asia/Shanghai} [%thread] %-5level [%X{traceId}] %logger{40} - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
@@ -14,10 +14,10 @@
|
|||||||
<appender name="PT_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
<appender name="PT_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
<file>../log/pt-request.log</file>
|
<file>../log/pt-request.log</file>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %msg%n</pattern>
|
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS, Asia/Shanghai} %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
<fileNamePattern>../log/pt-request.%d{yyyy-MM-dd}.log</fileNamePattern>
|
<fileNamePattern>../log/pt-request.%d{yyyy-MM-dd, Asia/Shanghai}.log</fileNamePattern>
|
||||||
<maxHistory>60</maxHistory>
|
<maxHistory>60</maxHistory>
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
</appender>
|
</appender>
|
||||||
|
|||||||
Reference in New Issue
Block a user