删除品牌
This commit is contained in:
+1
-3
@@ -6,13 +6,11 @@ import com.nanri.aiimage.modules.ziniao.model.vo.ZiniaoStaffItemVo;
|
||||
import java.util.List;
|
||||
|
||||
public interface ZiniaoClient {
|
||||
String getAppToken();
|
||||
|
||||
Long getCompanyIdByApiKey();
|
||||
|
||||
List<ZiniaoStaffItemVo> listStaff(Long companyId);
|
||||
|
||||
List<ZiniaoShopCacheDto> listUserStores(Long companyId, Long userId, String userToken);
|
||||
List<ZiniaoShopCacheDto> listUserStores(Long companyId, Long userId);
|
||||
|
||||
String getUserLoginToken(Long companyId, Long userId);
|
||||
}
|
||||
|
||||
+56
-54
@@ -6,8 +6,8 @@ import com.nanri.aiimage.common.exception.BusinessException;
|
||||
import com.nanri.aiimage.config.ZiniaoProperties;
|
||||
import com.nanri.aiimage.modules.ziniao.model.cache.ZiniaoShopCacheDto;
|
||||
import com.nanri.aiimage.modules.ziniao.model.vo.ZiniaoStaffItemVo;
|
||||
import com.nanri.aiimage.modules.ziniao.service.ZiniaoSessionCacheService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatusCode;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -24,35 +24,6 @@ public class ZiniaoClientImpl implements ZiniaoClient {
|
||||
|
||||
private final ZiniaoProperties ziniaoProperties;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final ZiniaoSessionCacheService ziniaoSessionCacheService;
|
||||
|
||||
@Override
|
||||
public String getAppToken() {
|
||||
String cachedToken = ziniaoSessionCacheService.getAppToken();
|
||||
if (cachedToken != null && !cachedToken.isBlank()) {
|
||||
return cachedToken;
|
||||
}
|
||||
String raw = postWithApiKeyEmptyJsonBody(ziniaoProperties.getAppTokenPath(), "获取 appToken");
|
||||
try {
|
||||
JsonNode root = objectMapper.readTree(raw);
|
||||
JsonNode data = firstNonNull(root.get("data"), root.get("result"), root);
|
||||
String token = text(firstNonNull(
|
||||
data == null ? null : data.get("appAuthToken"),
|
||||
data == null ? null : data.get("appToken"),
|
||||
root.get("appAuthToken"),
|
||||
root.get("appToken")
|
||||
));
|
||||
if (token == null || token.isBlank()) {
|
||||
throw new BusinessException("紫鸟 appToken 响应缺少 token");
|
||||
}
|
||||
ziniaoSessionCacheService.saveAppToken(token);
|
||||
return token;
|
||||
} catch (BusinessException ex) {
|
||||
throw ex;
|
||||
} catch (Exception ex) {
|
||||
throw new BusinessException("解析紫鸟 appToken 响应失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getCompanyIdByApiKey() {
|
||||
@@ -104,14 +75,14 @@ public class ZiniaoClientImpl implements ZiniaoClient {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ZiniaoShopCacheDto> listUserStores(Long companyId, Long userId, String userToken) {
|
||||
String raw = postWithAuthorization(ziniaoProperties.getUserStoresPath(), userToken, Map.of(
|
||||
"companyId", companyId,
|
||||
"userId", userId,
|
||||
public List<ZiniaoShopCacheDto> listUserStores(Long companyId, Long userId) {
|
||||
String raw = postWithApiKey(ziniaoProperties.getUserStoresPath(), Map.of(
|
||||
"companyId", String.valueOf(companyId),
|
||||
"isAccurate", "",
|
||||
"limit", "100",
|
||||
"storeName", "",
|
||||
"isAccurate", 1,
|
||||
"page", 1,
|
||||
"limit", 10
|
||||
"page", "1",
|
||||
"userId", String.valueOf(userId)
|
||||
), "获取员工店铺列表");
|
||||
return parseUserStores(raw);
|
||||
}
|
||||
@@ -128,7 +99,15 @@ public class ZiniaoClientImpl implements ZiniaoClient {
|
||||
throw new BusinessException("获取紫鸟员工登录 token 失败: " + Objects.toString(text(root.get("msg")), "未知错误"));
|
||||
}
|
||||
JsonNode data = firstNonNull(root.get("data"), root.get("result"));
|
||||
JsonNode payload = firstNonNull(
|
||||
data == null ? null : data.get("data"),
|
||||
data == null ? null : data.get("result"),
|
||||
data,
|
||||
root
|
||||
);
|
||||
String token = text(firstNonNull(
|
||||
payload == null ? null : payload.get("token"),
|
||||
payload == null ? null : payload.get("loginToken"),
|
||||
data == null ? null : data.get("token"),
|
||||
data == null ? null : data.get("loginToken"),
|
||||
root.get("token"),
|
||||
@@ -152,21 +131,9 @@ public class ZiniaoClientImpl implements ZiniaoClient {
|
||||
.uri(joinUrl(ziniaoProperties.getBaseUrl(), path))
|
||||
.headers(headers -> headers.setBearerAuth(apiKey))
|
||||
.retrieve()
|
||||
.body(String.class);
|
||||
validateSuccess(raw, action, path);
|
||||
return raw;
|
||||
}
|
||||
|
||||
private String postWithApiKeyEmptyJsonBody(String path, String action) {
|
||||
String apiKey = requireText(ziniaoProperties.getApiKey(), "紫鸟 apiKey 未配置");
|
||||
String raw = getRestClient().post()
|
||||
.uri(joinUrl(ziniaoProperties.getBaseUrl(), path))
|
||||
.headers(headers -> {
|
||||
headers.setBearerAuth(apiKey);
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
.onStatus(HttpStatusCode::isError, (req, res) -> {
|
||||
// 保留响应体,交给后续 validateSuccess 统一解析
|
||||
})
|
||||
.body("")
|
||||
.retrieve()
|
||||
.body(String.class);
|
||||
validateSuccess(raw, action, path);
|
||||
return raw;
|
||||
@@ -185,6 +152,9 @@ public class ZiniaoClientImpl implements ZiniaoClient {
|
||||
}
|
||||
String raw = request
|
||||
.retrieve()
|
||||
.onStatus(HttpStatusCode::isError, (req, res) -> {
|
||||
// 保留响应体,交给后续 validateSuccess 统一解析 code/sub_code/sub_msg
|
||||
})
|
||||
.body(String.class);
|
||||
validateSuccess(raw, action, path);
|
||||
return raw;
|
||||
@@ -195,7 +165,11 @@ public class ZiniaoClientImpl implements ZiniaoClient {
|
||||
RestClient.RequestBodySpec request = getRestClient().post()
|
||||
.uri(joinUrl(ziniaoProperties.getBaseUrl(), path))
|
||||
.headers(headers -> {
|
||||
headers.set("Authorization", token);
|
||||
if (token.regionMatches(true, 0, "Bearer ", 0, 7)) {
|
||||
headers.set("Authorization", token);
|
||||
} else {
|
||||
headers.setBearerAuth(token);
|
||||
}
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
});
|
||||
if (body != null) {
|
||||
@@ -212,7 +186,29 @@ public class ZiniaoClientImpl implements ZiniaoClient {
|
||||
try {
|
||||
JsonNode root = objectMapper.readTree(raw);
|
||||
if (!success(root)) {
|
||||
throw new BusinessException("紫鸟接口返回失败(" + action + ", " + path + "): " + Objects.toString(text(root.get("msg")), "未知错误"));
|
||||
String code = Objects.toString(text(root.get("code")), "");
|
||||
String msg = Objects.toString(text(root.get("msg")), "未知错误");
|
||||
String subCode = Objects.toString(text(root.get("sub_code")), "");
|
||||
String subMsg = Objects.toString(text(root.get("sub_msg")), "");
|
||||
|
||||
StringBuilder detail = new StringBuilder();
|
||||
if (!code.isBlank()) {
|
||||
detail.append("code=").append(code);
|
||||
}
|
||||
if (!subCode.isBlank()) {
|
||||
if (!detail.isEmpty()) detail.append(", ");
|
||||
detail.append("sub_code=").append(subCode);
|
||||
}
|
||||
if (!subMsg.isBlank()) {
|
||||
if (!detail.isEmpty()) detail.append(", ");
|
||||
detail.append("sub_msg=").append(subMsg);
|
||||
}
|
||||
if (!detail.isEmpty()) {
|
||||
detail.append(", ");
|
||||
}
|
||||
detail.append("msg=").append(msg);
|
||||
|
||||
throw new BusinessException("紫鸟接口返回失败(" + action + ", " + path + "): " + detail);
|
||||
}
|
||||
} catch (BusinessException ex) {
|
||||
throw ex;
|
||||
@@ -284,7 +280,13 @@ public class ZiniaoClientImpl implements ZiniaoClient {
|
||||
private List<ZiniaoShopCacheDto> parseUserStores(String raw) {
|
||||
try {
|
||||
JsonNode root = objectMapper.readTree(raw);
|
||||
JsonNode itemsNode = firstNonNull(root.get("data"), root.get("result"));
|
||||
JsonNode wrapper = firstNonNull(root.get("data"), root.get("result"), root);
|
||||
JsonNode itemsNode = firstNonNull(
|
||||
wrapper == null ? null : wrapper.get("data"),
|
||||
wrapper == null ? null : wrapper.get("items"),
|
||||
wrapper
|
||||
);
|
||||
|
||||
List<ZiniaoShopCacheDto> items = new ArrayList<>();
|
||||
if (itemsNode != null && itemsNode.isArray()) {
|
||||
for (JsonNode itemNode : itemsNode) {
|
||||
|
||||
+76
-12
@@ -26,6 +26,75 @@ import java.util.UUID;
|
||||
@RequiredArgsConstructor
|
||||
public class ZiniaoAuthService {
|
||||
|
||||
public StoreMatchResult matchStoreByNameAcrossStaff(String targetShopName, Long preferUserId) {
|
||||
ensureEnabled();
|
||||
String normalizedTarget = normalizeShopName(targetShopName);
|
||||
if (normalizedTarget.isBlank()) {
|
||||
return new StoreMatchResult(false, null, null, null, null, null);
|
||||
}
|
||||
|
||||
Long companyId = resolveCompanyId();
|
||||
List<ZiniaoStaffItemVo> staff = ziniaoClient.listStaff(companyId);
|
||||
|
||||
List<Long> userIds = new java.util.ArrayList<>();
|
||||
if (preferUserId != null && preferUserId > 0) {
|
||||
userIds.add(preferUserId);
|
||||
}
|
||||
for (ZiniaoStaffItemVo item : staff) {
|
||||
if (item != null && item.getUserId() != null && item.getUserId() > 0 && (userIds.isEmpty() || !userIds.contains(item.getUserId()))) {
|
||||
userIds.add(item.getUserId());
|
||||
}
|
||||
}
|
||||
|
||||
for (Long staffUserId : userIds) {
|
||||
if (staffUserId == null || staffUserId <= 0) {
|
||||
continue;
|
||||
}
|
||||
List<ZiniaoShopCacheDto> stores;
|
||||
try {
|
||||
stores = ziniaoClient.listUserStores(companyId, staffUserId);
|
||||
} catch (BusinessException ex) {
|
||||
if (isSkippableUserStoresError(ex)) {
|
||||
continue;
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
|
||||
for (ZiniaoShopCacheDto store : stores) {
|
||||
String storeName = normalizeShopName(store == null ? null : store.getShopName());
|
||||
if (!storeName.isBlank() && storeName.equals(normalizedTarget)) {
|
||||
String openStoreUrl = buildOpenStoreUrl(store.getShopId(), staffUserId, ziniaoClient.getUserLoginToken(companyId, staffUserId));
|
||||
return new StoreMatchResult(true, store.getShopId(), store.getShopName(), store.getPlatform(), staffUserId, openStoreUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new StoreMatchResult(false, null, null, null, null, null);
|
||||
}
|
||||
|
||||
private boolean isSkippableUserStoresError(BusinessException ex) {
|
||||
String message = ex == null ? null : ex.getMessage();
|
||||
if (message == null || message.isBlank()) {
|
||||
return false;
|
||||
}
|
||||
return message.contains("code=40004")
|
||||
|| message.contains("userId存在无效的参数值")
|
||||
|| message.contains("无权限")
|
||||
|| message.contains("没有权限");
|
||||
}
|
||||
|
||||
private String normalizeShopName(String value) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
return value.replace("\u3000", " ")
|
||||
.trim();
|
||||
}
|
||||
|
||||
public record StoreMatchResult(boolean matched, String shopId, String shopName, String platform, Long matchedUserId,
|
||||
String openStoreUrl) {
|
||||
}
|
||||
|
||||
private final ZiniaoProperties ziniaoProperties;
|
||||
private final ZiniaoClient ziniaoClient;
|
||||
private final ZiniaoSessionCacheService ziniaoSessionCacheService;
|
||||
@@ -36,13 +105,13 @@ public class ZiniaoAuthService {
|
||||
ZiniaoSessionVo vo = new ZiniaoSessionVo();
|
||||
vo.setSessionId(session.getSessionId());
|
||||
vo.setEnabled(ziniaoProperties.isEnabled());
|
||||
vo.setAuthenticated(session.getAccessToken() != null && !session.getAccessToken().isBlank());
|
||||
vo.setAuthenticated(Boolean.TRUE);
|
||||
vo.setCompanyId(session.getCompanyId());
|
||||
vo.setCurrentUserId(session.getCurrentUserId());
|
||||
vo.setZiniaoUserId(session.getZiniaoUserId());
|
||||
vo.setNickname(session.getNickname());
|
||||
vo.setAppToken(session.getAccessToken());
|
||||
vo.setTokenType(session.getTokenType());
|
||||
vo.setAppToken(null);
|
||||
vo.setTokenType(null);
|
||||
vo.setExpireAt(session.getExpireAt());
|
||||
vo.setShopCount(ziniaoSessionCacheService.getShops(session.getSessionId()).size());
|
||||
vo.setCurrentShopId(session.getDefaultShopId());
|
||||
@@ -61,8 +130,7 @@ public class ZiniaoAuthService {
|
||||
public ZiniaoShopListVo listShops(String sessionId, Long userId) {
|
||||
ZiniaoSessionCacheDto session = requireOrInitSession(sessionId, userId);
|
||||
Long currentUserId = requireUserId(session.getCurrentUserId());
|
||||
String userToken = ziniaoClient.getUserLoginToken(resolveCompanyId(), currentUserId);
|
||||
List<ZiniaoShopCacheDto> shops = ziniaoClient.listUserStores(resolveCompanyId(), currentUserId, userToken);
|
||||
List<ZiniaoShopCacheDto> shops = ziniaoClient.listUserStores(resolveCompanyId(), currentUserId);
|
||||
ziniaoSessionCacheService.saveShops(session.getSessionId(), shops);
|
||||
if (!shops.isEmpty() && (session.getDefaultShopId() == null || session.getDefaultShopId().isBlank())) {
|
||||
session.setDefaultShopId(shops.get(0).getShopId());
|
||||
@@ -86,7 +154,7 @@ public class ZiniaoAuthService {
|
||||
String userToken = ziniaoClient.getUserLoginToken(resolveCompanyId(), currentUserId);
|
||||
List<ZiniaoShopCacheDto> shops = ziniaoSessionCacheService.getShops(session.getSessionId());
|
||||
if (shops.isEmpty()) {
|
||||
shops = ziniaoClient.listUserStores(resolveCompanyId(), currentUserId, userToken);
|
||||
shops = ziniaoClient.listUserStores(resolveCompanyId(), currentUserId);
|
||||
ziniaoSessionCacheService.saveShops(session.getSessionId(), shops);
|
||||
}
|
||||
ZiniaoShopCacheDto targetShop = shops.stream()
|
||||
@@ -110,8 +178,7 @@ public class ZiniaoAuthService {
|
||||
public List<ZiniaoShopCacheDto> listShopsForConfiguredUser() {
|
||||
ensureEnabled();
|
||||
Long userId = parseConfiguredOpenStoreUserId();
|
||||
String userToken = ziniaoClient.getUserLoginToken(resolveCompanyId(), userId);
|
||||
return ziniaoClient.listUserStores(resolveCompanyId(), userId, userToken);
|
||||
return ziniaoClient.listUserStores(resolveCompanyId(), userId);
|
||||
}
|
||||
|
||||
public String buildOpenStoreUrlForShop(ZiniaoShopCacheDto shop) {
|
||||
@@ -128,9 +195,6 @@ public class ZiniaoAuthService {
|
||||
String sessionId = "ziniao_" + UUID.randomUUID().toString().replace("-", "");
|
||||
ZiniaoSessionCacheDto session = new ZiniaoSessionCacheDto();
|
||||
session.setSessionId(sessionId);
|
||||
String appToken = ziniaoClient.getAppToken();
|
||||
session.setAccessToken(maskToken(appToken));
|
||||
session.setTokenType("Bearer");
|
||||
session.setExpireAt(Instant.now().plusSeconds(ziniaoProperties.getSessionTtlHours() * 3600).toEpochMilli());
|
||||
session.setCompanyId(resolveCompanyId());
|
||||
session.setCurrentUserId(userId);
|
||||
@@ -186,7 +250,7 @@ public class ZiniaoAuthService {
|
||||
if (ziniaoProperties.getOpenStoreExtraArgs() != null && !ziniaoProperties.getOpenStoreExtraArgs().isBlank()) {
|
||||
builder.queryParam("extraArgs", ziniaoProperties.getOpenStoreExtraArgs());
|
||||
}
|
||||
return builder.build(true).toUriString();
|
||||
return builder.build().encode().toUriString();
|
||||
}
|
||||
|
||||
private void ensureEnabled() {
|
||||
|
||||
-17
@@ -17,27 +17,10 @@ import java.util.List;
|
||||
@RequiredArgsConstructor
|
||||
public class ZiniaoSessionCacheService {
|
||||
|
||||
private static final String APP_TOKEN_KEY = "ziniao:app-token";
|
||||
|
||||
private final StringRedisTemplate stringRedisTemplate;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final ZiniaoProperties ziniaoProperties;
|
||||
|
||||
public void saveAppToken(String appToken) {
|
||||
if (appToken == null || appToken.isBlank()) {
|
||||
return;
|
||||
}
|
||||
stringRedisTemplate.opsForValue().set(APP_TOKEN_KEY, appToken.trim(), Duration.ofHours(ziniaoProperties.getSessionTtlHours()));
|
||||
}
|
||||
|
||||
public String getAppToken() {
|
||||
String value = stringRedisTemplate.opsForValue().get(APP_TOKEN_KEY);
|
||||
if (value == null || value.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
return value.trim();
|
||||
}
|
||||
|
||||
public void saveSession(ZiniaoSessionCacheDto session) {
|
||||
try {
|
||||
stringRedisTemplate.opsForValue().set(buildSessionKey(session.getSessionId()), objectMapper.writeValueAsString(session), Duration.ofHours(ziniaoProperties.getSessionTtlHours()));
|
||||
|
||||
Reference in New Issue
Block a user