From 8b5e2b6a38640934cad407c16bcb73ce34d018c2 Mon Sep 17 00:00:00 2001 From: BBIT-Kai <2911862937@qq.com> Date: Fri, 10 Jul 2026 14:06:07 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dbug=EF=BC=9B=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E9=94=99=E8=AF=AF=E4=BF=A1=E6=81=AF=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + server/build.ps1 | 2 +- .../bbit/ticket/entity/common/ErrorCode.kt | 2 + .../ticket/route/system/registerUserRoutes.kt | 2 +- .../bbit/ticket/service/system/AuthService.kt | 18 +++---- .../bbit/ticket/service/system/UserService.kt | 5 +- .../com/bbit/ticket/utils/DateTimeFormats.kt | 2 +- .../kotlin/com/bbit/ticket/utils/net/PTApi.kt | 2 +- .../com/bbit/ticket/utils/net/PTClient.kt | 49 ++++++++++++++++--- server/src/main/resources/logback.xml | 6 +-- 10 files changed, 66 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index eb69bff..66a2177 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ web/dist/ log/ server/src/main/resources/dist/ doc/票通Demo/untitled/.idea/ +server/.kotlin/ diff --git a/server/build.ps1 b/server/build.ps1 index 8bda859..9c1f34e 100644 --- a/server/build.ps1 +++ b/server/build.ps1 @@ -1,6 +1,6 @@ $ErrorActionPreference = "Stop" -$VERSION = "1.1" +$VERSION = "1.2" $IMAGE = "docker.bbitcn.net/bbit_invoice/server" diff --git a/server/src/main/kotlin/com/bbit/ticket/entity/common/ErrorCode.kt b/server/src/main/kotlin/com/bbit/ticket/entity/common/ErrorCode.kt index e1c0f3e..c808e9c 100644 --- a/server/src/main/kotlin/com/bbit/ticket/entity/common/ErrorCode.kt +++ b/server/src/main/kotlin/com/bbit/ticket/entity/common/ErrorCode.kt @@ -6,6 +6,8 @@ enum class ErrorCode(val code: String, val message: String) { UNAUTHORIZED("AUTH.UNAUTHORIZED", "未登录或登录已失效"), FORBIDDEN("AUTH.FORBIDDEN", "无权限访问"), 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_NOT_FOUND("SYSTEM.USER_NOT_FOUND", "用户不存在"), ROLE_NOT_FOUND("SYSTEM.ROLE_NOT_FOUND", "角色不存在"), diff --git a/server/src/main/kotlin/com/bbit/ticket/route/system/registerUserRoutes.kt b/server/src/main/kotlin/com/bbit/ticket/route/system/registerUserRoutes.kt index 71f0056..1b0de15 100644 --- a/server/src/main/kotlin/com/bbit/ticket/route/system/registerUserRoutes.kt +++ b/server/src/main/kotlin/com/bbit/ticket/route/system/registerUserRoutes.kt @@ -99,7 +99,7 @@ fun Route.registerUserRoutes() { val id = parseUuid(call.parameters["id"] ?: "", "id") val request = call.receive() runCatching { - UserService.updateStatus(id, request) + UserService.updateStatus(id, currentUser.id, request) call.respond(ok(message = "状态更新成功")) OperationLogService.success(call, currentUser, "UPDATE_STATUS", "更新用户状态", start.elapsedNow().inWholeMilliseconds) }.onFailure { diff --git a/server/src/main/kotlin/com/bbit/ticket/service/system/AuthService.kt b/server/src/main/kotlin/com/bbit/ticket/service/system/AuthService.kt index 545b8b6..249ae16 100644 --- a/server/src/main/kotlin/com/bbit/ticket/service/system/AuthService.kt +++ b/server/src/main/kotlin/com/bbit/ticket/service/system/AuthService.kt @@ -30,31 +30,31 @@ object AuthService { } val user = dbQuery { UserDao.findByUsername(username) } ?: throw BizException( - ErrorCode.USERNAME_OR_PASSWORD_INVALID.code, - ErrorCode.USERNAME_OR_PASSWORD_INVALID.message, + ErrorCode.ACCOUNT_NOT_FOUND.code, + ErrorCode.ACCOUNT_NOT_FOUND.message, 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( - ErrorCode.USERNAME_OR_PASSWORD_INVALID.code, - ErrorCode.USERNAME_OR_PASSWORD_INVALID.message, + ErrorCode.PASSWORD_INVALID.code, + ErrorCode.PASSWORD_INVALID.message, 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) } - val userId = user[com.bbit.ticket.database.system.SysUserTable.id] + val userId = user[SysUserTable.id] val roleCodes = dbQuery { UserDao.findEnabledRoleCodes(userId) } val (accessToken, expiresIn) = JwtService.issueAccessToken( userId = userId.toString(), - username = user[com.bbit.ticket.database.system.SysUserTable.username], + username = user[SysUserTable.username], roles = roleCodes, - tokenVersion = user[com.bbit.ticket.database.system.SysUserTable.tokenVersion], + tokenVersion = user[SysUserTable.tokenVersion], ) dbQuery { UserDao.updateLoginInfo(userId, loginIp) } diff --git a/server/src/main/kotlin/com/bbit/ticket/service/system/UserService.kt b/server/src/main/kotlin/com/bbit/ticket/service/system/UserService.kt index 4628a60..d659323 100644 --- a/server/src/main/kotlin/com/bbit/ticket/service/system/UserService.kt +++ b/server/src/main/kotlin/com/bbit/ticket/service/system/UserService.kt @@ -63,7 +63,10 @@ object UserService { 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.updateStatus(id, request.status) } diff --git a/server/src/main/kotlin/com/bbit/ticket/utils/DateTimeFormats.kt b/server/src/main/kotlin/com/bbit/ticket/utils/DateTimeFormats.kt index 8c80c41..272ac81 100644 --- a/server/src/main/kotlin/com/bbit/ticket/utils/DateTimeFormats.kt +++ b/server/src/main/kotlin/com/bbit/ticket/utils/DateTimeFormats.kt @@ -4,7 +4,7 @@ import java.time.OffsetDateTime import java.time.ZoneId 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") fun formatDateTime(value: OffsetDateTime?): String? { diff --git a/server/src/main/kotlin/com/bbit/ticket/utils/net/PTApi.kt b/server/src/main/kotlin/com/bbit/ticket/utils/net/PTApi.kt index 851dc78..ab18d5b 100644 --- a/server/src/main/kotlin/com/bbit/ticket/utils/net/PTApi.kt +++ b/server/src/main/kotlin/com/bbit/ticket/utils/net/PTApi.kt @@ -40,7 +40,7 @@ object PTApi { /** 发送登录短信验证码 2.4 */ suspend fun sendLoginSmsCode(req: GetLoginSmsCodeRequest): LoginSmsCodeResponse = - PTClient.ptPost("sendLoginSmsCode.pt", req) + PTClient.ptPost("sendLoginSmsCode.pt", req, successResultCodes = setOf("0000", "6666")) /** 短信验证码登录 2.5 */ suspend fun smsLogin(req: SmsLoginRequest): SMSLoginResponse = diff --git a/server/src/main/kotlin/com/bbit/ticket/utils/net/PTClient.kt b/server/src/main/kotlin/com/bbit/ticket/utils/net/PTClient.kt index 33894a5..2c0970a 100644 --- a/server/src/main/kotlin/com/bbit/ticket/utils/net/PTClient.kt +++ b/server/src/main/kotlin/com/bbit/ticket/utils/net/PTClient.kt @@ -34,6 +34,7 @@ object PTClient { val logger = LoggerFactory.getLogger(PTClient::class.java) private const val CONNECT_TIMEOUT_MS = 10_000 private const val READ_TIMEOUT_MS = 60_000 + private const val SHANGHAI_TIME_ZONE = "Asia/Shanghai" val wireJson = Json { explicitNulls = false ignoreUnknownKeys = true @@ -54,7 +55,8 @@ object PTClient { suspend inline fun ptGet( url: String, queryParams: Req, - headers: Map = emptyMap() + headers: Map = emptyMap(), + successResultCodes: Set = setOf("0000"), ): Resp { // query -> json @@ -128,6 +130,7 @@ object PTClient { message = "response content is null", serialNo = result.serialNo ) + ensureInnerResultOk(content, successResultCodes, result.serialNo) return myJson.decodeFromJsonElement(content) } @@ -135,7 +138,8 @@ object PTClient { suspend inline fun ptPost( url: String, body: Req, - headers: Map = emptyMap() + headers: Map = emptyMap(), + successResultCodes: Set = setOf("0000"), ): Resp { // req json val reqJson = wireJson.encodeToString(body) @@ -150,6 +154,7 @@ object PTClient { val decrypted = disposeResponse(response) val result = myJson.decodeFromString>(decrypted) + logger.info("res = $result") if (result.code != "0000") { throw PTException( code = result.code, @@ -157,8 +162,14 @@ object PTClient { serialNo = result.serialNo ) } - logger.info("res = $result") - return myJson.decodeFromJsonElement(result.content!!) + val content = result.content + ?: throw PTException( + code = "CONTENT_NULL", + message = "response content is null", + serialNo = result.serialNo + ) + ensureInnerResultOk(content, successResultCodes, result.serialNo) + return myJson.decodeFromJsonElement(content) } suspend fun postJsonRaw( @@ -220,7 +231,7 @@ object PTClient { @Throws(Exception::class) fun buildRequestData(content: String): String { 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() map["platformCode"] = Global.ptPlatformCode map["signType"] = "RSA" @@ -287,10 +298,36 @@ object PTClient { fun ptDate(): String { val date = Date() - val sdf = SimpleDateFormat("YYYYMMddHHmmss") + val sdf = shanghaiDateFormat("yyyyMMddHHmmss") val str = Global.ptPlatformAlias + sdf.format(date) + (Math.random() * 90 + 10).toInt() println(str) return str } + @PublishedApi + internal fun ensureInnerResultOk( + content: JsonElement, + successResultCodes: Set, + 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) + } + } diff --git a/server/src/main/resources/logback.xml b/server/src/main/resources/logback.xml index 9c6060e..a671cc1 100644 --- a/server/src/main/resources/logback.xml +++ b/server/src/main/resources/logback.xml @@ -1,7 +1,7 @@ - %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{traceId}] %logger{40} - %msg%n + %d{yyyy-MM-dd HH:mm:ss.SSS, Asia/Shanghai} [%thread] %-5level [%X{traceId}] %logger{40} - %msg%n @@ -14,10 +14,10 @@ ../log/pt-request.log - %d{yyyy-MM-dd HH:mm:ss.SSS} %msg%n + %d{yyyy-MM-dd HH:mm:ss.SSS, Asia/Shanghai} %msg%n - ../log/pt-request.%d{yyyy-MM-dd}.log + ../log/pt-request.%d{yyyy-MM-dd, Asia/Shanghai}.log 60