129 lines
5.4 KiB
Java
129 lines
5.4 KiB
Java
package com.rj.service;
|
||
|
||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
|
||
import com.rj.config.HxrAdminProperties;
|
||
import com.rj.dto.hxr.HxrOrderRow;
|
||
import com.rj.dto.hxr.HxrOrderSelectResponse;
|
||
import lombok.RequiredArgsConstructor;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
import org.springframework.stereotype.Service;
|
||
import org.springframework.web.util.UriComponentsBuilder;
|
||
|
||
import java.net.URI;
|
||
import java.net.http.HttpClient;
|
||
import java.net.http.HttpRequest;
|
||
import java.net.http.HttpResponse;
|
||
import java.time.Duration;
|
||
import java.util.Optional;
|
||
|
||
/**
|
||
* 调用 hxrd 后台订单列表接口并解析 JSON。
|
||
*/
|
||
@Slf4j
|
||
@Service
|
||
@RequiredArgsConstructor
|
||
public class HxrAdminOrderSelectService {
|
||
|
||
private static final ObjectMapper JSON = new ObjectMapper()
|
||
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
|
||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||
|
||
private final HxrAdminProperties properties;
|
||
|
||
/**
|
||
* 拉取订单列表;配置未就绪或 HTTP 非 2xx 时返回 empty。
|
||
* <p>使用 {@link HxrAdminProperties#getOrderSelectUrl()} 原样请求(与定时任务一致)。
|
||
*/
|
||
public Optional<HxrOrderSelectResponse> fetchOrderSelect() throws Exception {
|
||
return fetchOrderSelectInternal(properties.getOrderSelectUrl());
|
||
}
|
||
|
||
/**
|
||
* 按购买时间区间、转卖状态等条件拉取订单列表(在配置的 {@code orderSelectUrl} 上覆盖查询参数)。
|
||
*
|
||
* @param buyTimeStart 购买时间起,对应 {@code buy_time[0]},可为 null 或空串表示不限制
|
||
* @param buyTimeEnd 购买时间止,对应 {@code buy_time[1]}
|
||
* @param isResell 转卖筛选,对应 {@code is_resell};为 null 时不改写该参数
|
||
*/
|
||
public Optional<HxrOrderSelectResponse> fetchOrderSelect(
|
||
String buyTimeStart, String buyTimeEnd, Integer isResell) throws Exception {
|
||
return fetchOrderSelectInternal(buildOrderSelectUrl(buyTimeStart, buyTimeEnd, isResell));
|
||
}
|
||
|
||
private Optional<HxrOrderSelectResponse> fetchOrderSelectInternal(String requestUri) throws Exception {
|
||
String cookieHeader = properties.resolveCookieHeader();
|
||
if (cookieHeader == null || cookieHeader.isBlank()) {
|
||
log.warn("hxr.admin 未配置 cookie 或 phpsid,跳过拉取");
|
||
return Optional.empty();
|
||
}
|
||
|
||
HttpClient client = HttpClient.newBuilder()
|
||
.connectTimeout(Duration.ofSeconds(35))
|
||
.followRedirects(HttpClient.Redirect.NORMAL)
|
||
.build();
|
||
|
||
HttpRequest request = HttpRequest.newBuilder()
|
||
.uri(URI.create(requestUri))
|
||
.timeout(Duration.ofSeconds(160))
|
||
.header("Accept", "application/json, text/javascript, */*; q=0.01")
|
||
.header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")
|
||
.header("Cookie", cookieHeader)
|
||
.header("Priority", "u=1, i")
|
||
.header("Referer", "https://hxrdhoutai.hxrdsm.cn/app/admin/order/index")
|
||
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36 Edg/148.0.0.0")
|
||
.GET()
|
||
.build();
|
||
|
||
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||
int status = response.statusCode();
|
||
if (status < 200 || status >= 300) {
|
||
log.warn("hxr admin order/select HTTP {} bodyPrefix={}", status, abbreviate(response.body(), 500));
|
||
return Optional.empty();
|
||
}
|
||
|
||
HxrOrderSelectResponse body = JSON.readValue(response.body(), HxrOrderSelectResponse.class);
|
||
if (body.code() != 0) {
|
||
log.warn("hxr admin order/select api code={} msg={}", body.code(), body.msg());
|
||
return Optional.empty();
|
||
}
|
||
return Optional.of(body);
|
||
}
|
||
|
||
/**
|
||
* 在 {@link HxrAdminProperties#getOrderSelectUrl()} 上覆盖 {@code buy_time[0]}、{@code buy_time[1]}、{@code is_resell}。
|
||
*/
|
||
private String buildOrderSelectUrl(String buyTimeStart, String buyTimeEnd, Integer isResell) {
|
||
UriComponentsBuilder b = UriComponentsBuilder.fromUriString(properties.getOrderSelectUrl());
|
||
b.replaceQueryParam("buy_time[0]", buyTimeStart == null ? "" : buyTimeStart);
|
||
b.replaceQueryParam("buy_time[1]", buyTimeEnd == null ? "" : buyTimeEnd);
|
||
if (isResell != null) {
|
||
b.replaceQueryParam("is_resell", isResell);
|
||
}
|
||
return b.build().encode().toUriString();
|
||
}
|
||
|
||
/**
|
||
* 拉取并逐条打日志(一行一条 JSON)。
|
||
*/
|
||
public void fetchAndLogEachOrder() throws Exception {
|
||
Optional<HxrOrderSelectResponse> opt = fetchOrderSelect();
|
||
if (opt.isEmpty()) {
|
||
return;
|
||
}
|
||
HxrOrderSelectResponse body = opt.get();
|
||
log.info("未寄卖 order/select ok count={} allMoney={}", body.count(), body.allMoney());
|
||
for (HxrOrderRow row : body.data()) {
|
||
log.info("hxr order row {}", JSON.writeValueAsString(row));
|
||
}
|
||
}
|
||
|
||
private static String abbreviate(String s, int maxLen) {
|
||
if (s == null) {
|
||
return "";
|
||
}
|
||
return s.length() <= maxLen ? s : s.substring(0, maxLen) + "...";
|
||
}
|
||
}
|