You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
digital-rmb-backend/docs/superpowers/plans/2026-08-04-api-messages-enc...

6.8 KiB

后端中文提示与 UTF-8 响应实施计划

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: 所有 API 对外提示使用中文,并以 UTF-8 JSON 返回,避免 Swagger 和前端出现乱码。

Architecture: 通过 ApiResponse 统一成功提示,通过 Spring Security 的异常写入器统一鉴权提示,通过业务服务中文化可回传的校验信息。应用配置与响应写入器共同确保 UTF-8错误码保持不变。

Tech Stack: Java 8、Spring Boot 2.7、Spring Security、Springdoc OpenAPI、JUnit 5、MockMvc。

Global Constraints

  • 保持现有 ErrorCode 枚举值不变。
  • 所有面向前端的 message 必须为中文。
  • JSON 响应必须使用 UTF-8。
  • 保留业务校验的具体中文原因;框架参数校验使用统一中文提示。

Task 1: 统一响应和安全异常提示

Files:

  • Modify: src/main/java/com/yau/digitalrmb/shared/api/ApiResponse.java
  • Modify: src/main/java/com/yau/digitalrmb/security/config/SecurityConfig.java
  • Modify: src/main/resources/application.yml
  • Test: src/test/java/com/yau/digitalrmb/security/SecurityConfigTest.java

Interfaces:

  • Produces: 成功响应的 message 为“操作成功”401、403 响应分别为“未登录或登录已失效”“无访问权限”。

  • Produces: 安全异常响应头为 application/json;charset=UTF-8

  • Step 1: 写失败测试

mockMvc.perform(get("/api/v1/commercial-banks/issuance/inventory"))
    .andExpect(status().isUnauthorized())
    .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
    .andExpect(content().encoding(StandardCharsets.UTF_8))
    .andExpect(jsonPath("$.message").value("未登录或登录已失效"));
  • Step 2: 运行失败测试

Run: mvn -B -Dtest=SecurityConfigTest test

Expected: FAIL当前消息为 UNAUTHORIZED 或响应编码不是 UTF-8。

  • Step 3: 最小实现
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.getWriter().write(... "未登录或登录已失效" ...);

并将 ApiResponse.success 的消息改为“操作成功”,在 application.yml 添加:

server:
  servlet:
    encoding:
      charset: UTF-8
      enabled: true
      force: true
  • Step 4: 运行测试验证通过

Run: mvn -B -Dtest=SecurityConfigTest test

Expected: PASS。

  • Step 5: 提交
git add src/main/java/com/yau/digitalrmb/shared/api/ApiResponse.java src/main/java/com/yau/digitalrmb/security/config/SecurityConfig.java src/main/resources/application.yml src/test/java/com/yau/digitalrmb/security/SecurityConfigTest.java
git commit -m "fix: return Chinese security messages in UTF-8"

Task 2: 中文化发行模块对外业务提示

Files:

  • Modify: src/main/java/com/yau/digitalrmb/issuance/application/service/DenominationPlanService.java
  • Modify: src/main/java/com/yau/digitalrmb/issuance/application/service/CommercialBankIssuanceApplicationService.java
  • Modify: src/main/java/com/yau/digitalrmb/issuance/application/service/CentralBankIssuanceQueryService.java
  • Modify: src/main/java/com/yau/digitalrmb/issuance/interfaces/rest/CommercialBankIssuanceController.java
  • Modify: src/main/java/com/yau/digitalrmb/security/interfaces/AuthController.java
  • Test: src/test/java/com/yau/digitalrmb/issuance/interfaces/rest/IssuanceControllerTest.java

Interfaces:

  • Produces: 面额总额不一致时 VALIDATION_ERROR 消息为“各面额小计之和必须等于申请总金额”。

  • Produces: 当前用户审计声明缺失或非法时返回中文未授权提示。

  • Step 1: 写失败测试

mockMvc.perform(post("/api/v1/commercial-banks/issuance/denomination-plan/validate")
        .with(issuanceJwt()).contentType(MediaType.APPLICATION_JSON)
        .content(invalidPlanJson))
    .andExpect(jsonPath("$.code").value("VALIDATION_ERROR"))
    .andExpect(jsonPath("$.message").value("各面额小计之和必须等于申请总金额"));
  • Step 2: 运行失败测试

Run: mvn -B -Dtest=IssuanceControllerTest test

Expected: FAIL当前消息为 denomination total must equal totalAmount

  • Step 3: 最小实现

将所有会经 BusinessException 或校验转换返回前端的英文文本替换为对应中文,包括申请不存在、申请 ID 为空、库存配置不存在、JWT 缺失 userIdpreferred_username、金额和面额规则。

  • Step 4: 运行测试验证通过

Run: mvn -B -Dtest=IssuanceControllerTest test

Expected: PASS。

  • Step 5: 提交
git add src/main/java/com/yau/digitalrmb/issuance src/main/java/com/yau/digitalrmb/security/interfaces/AuthController.java src/test/java/com/yau/digitalrmb/issuance/interfaces/rest/IssuanceControllerTest.java
git commit -m "fix: translate issuance API messages to Chinese"

Task 3: 统一全局校验和验证

Files:

  • Modify: src/main/java/com/yau/digitalrmb/shared/web/GlobalExceptionHandler.java
  • Modify: src/main/java/com/yau/digitalrmb/platformintegration/application/PlatformTokenVerifier.java
  • Test: src/test/java/com/yau/digitalrmb/shared/GlobalExceptionHandlerTest.java

Interfaces:

  • Produces: 框架参数校验统一返回“请求参数校验失败”。

  • Produces: 无效平台令牌返回“平台登录凭据无效”。

  • Step 1: 写失败测试

mockMvc.perform(post("/api/v1/auth/login").contentType(MediaType.APPLICATION_JSON).content("{}"))
    .andExpect(jsonPath("$.code").value("VALIDATION_ERROR"))
    .andExpect(jsonPath("$.message").value("请求参数校验失败"));
  • Step 2: 运行失败测试

Run: mvn -B -Dtest=GlobalExceptionHandlerTest test

Expected: FAIL当前返回框架英文校验文本。

  • Step 3: 最小实现
return ApiResponse.failure(ErrorCode.VALIDATION_ERROR, "请求参数校验失败", traceId());

并把平台令牌异常内部消息改为中文,避免任何异常链的英文文本进入 API 响应。

  • Step 4: 执行完整验证

Run: mvn -B test

Expected: 全部测试通过;新增中文/UTF-8 断言通过。

  • Step 5: 重启与人工验证

Run: mvn -B package -DskipTests,重启本地 8081 后端;在 Swagger 调用面额校验接口,确认响应体中文且响应头为 UTF-8。

  • Step 6: 提交
git add src/main/java/com/yau/digitalrmb/shared/web/GlobalExceptionHandler.java src/main/java/com/yau/digitalrmb/platformintegration/application/PlatformTokenVerifier.java src/test/java/com/yau/digitalrmb/shared/GlobalExceptionHandlerTest.java
git commit -m "fix: standardize Chinese validation messages"