package com.yunhai.userbase.controller.oapi; import com.yunhai.platform.appauth.AppAuthProperties; import com.yunhai.userbase.config.Config; import com.yunhai.userbase.entity.ApplicationInfo; import com.yunhai.userbase.repository.ApplicationInfoRepository; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.LinkedHashMap; import java.util.Map; /** * 验签兜底端点:供其他业务服务在「共享 Redis 宕机且本地缓存也未命中」时直连获取某应用的密钥。

* 直接从 MySQL 读(绕过可能同宕的共享 Redis),是密钥的权威源;写入侧仍由 * {@code SignKeyCacheService} 同步到 Redis。返回形状与 BasePlatform 读侧解析契约一致:
* {@code {"appKey":"100616","secret":"...","enabled":true}}。

* 解析优先级:
* 1) 本库 application_info(覆盖全部「已颁发」应用的实时密钥);
* 2) 配置式受信应用 {@code yh.app-auth.trusted-apps}(平台自身默认密钥,如 应用中心 100616, * 即便尚未落库也可解析,避免「默认 appKey 未建行」时此处返回 404 导致验签链路失败);
* 两者皆无 → 404。

* 注意:此端点返回的是应用密钥,必须仅内网可达(由部署网络隔离保障),切勿暴露到公网。 */ @RestController @RequestMapping(Config.OPEN_API_PATH + "internal") public class SignKeyInternalController { private final ApplicationInfoRepository applicationInfoRepository; private final AppAuthProperties appAuthProperties; public SignKeyInternalController(ApplicationInfoRepository applicationInfoRepository, AppAuthProperties appAuthProperties) { this.applicationInfoRepository = applicationInfoRepository; this.appAuthProperties = appAuthProperties; } @GetMapping("sign-key/{appId}") public ResponseEntity> signKey(@PathVariable String appId) { Integer key; try { key = Integer.parseInt(appId.trim()); } catch (NumberFormatException e) { return ResponseEntity.notFound().build(); } ApplicationInfo info = applicationInfoRepository.findByAppKey(key); if (info != null && info.getAppSecret() != null && !info.getAppSecret().trim().isEmpty()) { return ok(info.getAppKey() == null ? appId : String.valueOf(info.getAppKey()), info.getAppSecret()); } // 库内无此应用密钥:回退到配置式受信应用(平台自身默认密钥 100616 等), // 避免「应用中心默认 appKey 未落库」时兜底查询返回 404。 String cfgSecret = appAuthProperties.getTrustedApps().get(appId); if (cfgSecret != null && !cfgSecret.trim().isEmpty()) { return ok(appId, cfgSecret); } return ResponseEntity.notFound().build(); } private static ResponseEntity> ok(String appKey, String secret) { Map body = new LinkedHashMap<>(); body.put("appKey", appKey); body.put("secret", secret); body.put("enabled", true); return ResponseEntity.ok(body); } }