配置迁移到数据库表里
This commit is contained in:
@@ -97,7 +97,8 @@ public class LbOrderRowController {
|
|||||||
@PostMapping("/sync-order-from-third")
|
@PostMapping("/sync-order-from-third")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "从 外部系统 同步订单",
|
summary = "从 外部系统 同步订单",
|
||||||
description = "按购买时间区间、租户 id、转卖状态调用后台 order/select,将结果写入 lb_order_row(按 tenant_id + 订单 id upsert)")
|
description = "按购买时间区间、租户 id、转卖状态调用后台 order/select,将结果写入 lb_order_row(按 tenant_id + 订单 id upsert);"
|
||||||
|
+ "cookie、URL、Referer 等从 lb_third_integration_config 按 tenantId 读取")
|
||||||
public ResponseEntity<Map<String, Object>> syncFromHxr(
|
public ResponseEntity<Map<String, Object>> syncFromHxr(
|
||||||
@Parameter(description = "同步条件", required = true) @RequestBody LbOrderRowSyncFromHxrRequest request) {
|
@Parameter(description = "同步条件", required = true) @RequestBody LbOrderRowSyncFromHxrRequest request) {
|
||||||
Map<String, Object> result =
|
Map<String, Object> result =
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class LbThirdIntegrationConfigController {
|
|||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
@Operation(summary = "新增")
|
@Operation(summary = "新增")
|
||||||
public ResponseEntity<Map<String, Object>> add(
|
public ResponseEntity<Map<String, Object>> add(
|
||||||
@Parameter(description = "配置实体(凭证请传 *Plain 明文字段)", required = true)
|
@Parameter(description = "配置实体(凭证请传 cookie、phpsid、goodsApiToken、goodsApiAppStr 明文字段)", required = true)
|
||||||
@RequestBody LbThirdIntegrationConfig entity) {
|
@RequestBody LbThirdIntegrationConfig entity) {
|
||||||
Map<String, Object> result = lbThirdIntegrationConfigService.add(entity);
|
Map<String, Object> result = lbThirdIntegrationConfigService.add(entity);
|
||||||
Boolean success = (Boolean) result.get("success");
|
Boolean success = (Boolean) result.get("success");
|
||||||
@@ -41,7 +41,7 @@ public class LbThirdIntegrationConfigController {
|
|||||||
@PutMapping("/update")
|
@PutMapping("/update")
|
||||||
@Operation(summary = "更新")
|
@Operation(summary = "更新")
|
||||||
public ResponseEntity<Map<String, Object>> update(
|
public ResponseEntity<Map<String, Object>> update(
|
||||||
@Parameter(description = "配置实体(仅传需修改字段;凭证 *Plain 非空时才轮换)", required = true)
|
@Parameter(description = "配置实体(仅传需修改字段;凭证字段非空时才更新)", required = true)
|
||||||
@RequestBody LbThirdIntegrationConfig entity) {
|
@RequestBody LbThirdIntegrationConfig entity) {
|
||||||
Map<String, Object> result = lbThirdIntegrationConfigService.update(entity);
|
Map<String, Object> result = lbThirdIntegrationConfigService.update(entity);
|
||||||
Boolean success = (Boolean) result.get("success");
|
Boolean success = (Boolean) result.get("success");
|
||||||
@@ -97,8 +97,8 @@ public class LbThirdIntegrationConfigController {
|
|||||||
|
|
||||||
@GetMapping("/credential/{tenantId}")
|
@GetMapping("/credential/{tenantId}")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "查询租户凭证(含明文)",
|
summary = "查询租户凭证",
|
||||||
description = "按 tenantId 解密返回 cookie、phpsid、goodsApiToken、goodsApiAppStr 明文,便于管理查看")
|
description = "按 tenantId 返回 cookie、phpsid、goodsApiToken、goodsApiAppStr 明文")
|
||||||
public ResponseEntity<Map<String, Object>> getCredentialStatus(
|
public ResponseEntity<Map<String, Object>> getCredentialStatus(
|
||||||
@Parameter(description = "租户 id", required = true) @PathVariable String tenantId) {
|
@Parameter(description = "租户 id", required = true) @PathVariable String tenantId) {
|
||||||
Map<String, Object> result = lbThirdIntegrationConfigService.getCredentialStatusByTenantId(tenantId);
|
Map<String, Object> result = lbThirdIntegrationConfigService.getCredentialStatusByTenantId(tenantId);
|
||||||
@@ -117,8 +117,8 @@ public class LbThirdIntegrationConfigController {
|
|||||||
summary = "更新租户凭证",
|
summary = "更新租户凭证",
|
||||||
description =
|
description =
|
||||||
"仅更新 cookie/phpsid/goodsApiToken/goodsApiAppStr 凭证列;"
|
"仅更新 cookie/phpsid/goodsApiToken/goodsApiAppStr 凭证列;"
|
||||||
+ "传明文则加密入库并 credential_version+1;"
|
+ "传明文则直接入库并 credential_version+1;"
|
||||||
+ "传 clear* 为 true 则清除对应密文;至少操作一项")
|
+ "传 clear* 为 true 则清除对应凭证;至少操作一项")
|
||||||
public ResponseEntity<Map<String, Object>> updateCredential(
|
public ResponseEntity<Map<String, Object>> updateCredential(
|
||||||
@Parameter(description = "租户 id", required = true) @PathVariable String tenantId,
|
@Parameter(description = "租户 id", required = true) @PathVariable String tenantId,
|
||||||
@Parameter(description = "凭证更新请求", required = true)
|
@Parameter(description = "凭证更新请求", required = true)
|
||||||
|
|||||||
@@ -124,8 +124,8 @@ public class LbUserController {
|
|||||||
@Operation(
|
@Operation(
|
||||||
summary = "从 hxrd 后台同步用户",
|
summary = "从 hxrd 后台同步用户",
|
||||||
description =
|
description =
|
||||||
"分页调用 /app/admin/user/select(每页 limit=90),将 data 解析为 LbUser 后立即 upsert 到 lb_user;"
|
"分页调用 /app/admin/user/select,将 data 解析为 LbUser 后立即 upsert 到 lb_user;"
|
||||||
+ "需配置 hxr.admin.cookie 或 phpsid")
|
+ "cookie、URL、Referer 等从 lb_third_integration_config 按 tenantId 读取")
|
||||||
public ResponseEntity<Map<String, Object>> syncFromHxr(
|
public ResponseEntity<Map<String, Object>> syncFromHxr(
|
||||||
@Parameter(description = "租户 id", required = true) @RequestParam String tenantId) {
|
@Parameter(description = "租户 id", required = true) @RequestParam String tenantId) {
|
||||||
Map<String, Object> result = lbUserService.syncFromHxrAdmin(tenantId);
|
Map<String, Object> result = lbUserService.syncFromHxrAdmin(tenantId);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import lombok.Data;
|
|||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新 {@code lb_third_integration_config} 凭证列的请求体(明文仅用于写入,响应不回显)。
|
* 更新 {@code lb_third_integration_config} 凭证列的请求体。
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Schema(description = "租户第三方集成凭证更新请求")
|
@Schema(description = "租户第三方集成凭证更新请求")
|
||||||
@@ -32,15 +32,15 @@ public class LbThirdIntegrationCredentialUpdateRequest {
|
|||||||
@Schema(description = "操作人(可选,写入 updated_by)")
|
@Schema(description = "操作人(可选,写入 updated_by)")
|
||||||
private String updatedBy;
|
private String updatedBy;
|
||||||
|
|
||||||
@Schema(description = "为 true 时清除 cookie_cipher")
|
@Schema(description = "为 true 时清除 cookie")
|
||||||
private Boolean clearCookie;
|
private Boolean clearCookie;
|
||||||
|
|
||||||
@Schema(description = "为 true 时清除 phpsid_cipher")
|
@Schema(description = "为 true 时清除 phpsid")
|
||||||
private Boolean clearPhpsid;
|
private Boolean clearPhpsid;
|
||||||
|
|
||||||
@Schema(description = "为 true 时清除 goods_api_token_cipher")
|
@Schema(description = "为 true 时清除 goods_api_token")
|
||||||
private Boolean clearGoodsApiToken;
|
private Boolean clearGoodsApiToken;
|
||||||
|
|
||||||
@Schema(description = "为 true 时清除 goods_api_app_str_cipher")
|
@Schema(description = "为 true 时清除 goods_api_app_str")
|
||||||
private Boolean clearGoodsApiAppStr;
|
private Boolean clearGoodsApiAppStr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,21 +100,21 @@ public class LbThirdIntegrationConfig implements Serializable {
|
|||||||
@Schema(description = "Admin 鉴权类型")
|
@Schema(description = "Admin 鉴权类型")
|
||||||
private String authType;
|
private String authType;
|
||||||
|
|
||||||
@TableField("cookie_cipher")
|
@TableField("cookie")
|
||||||
@Schema(description = "完整 Cookie 密文(存储字段,接口不回显)")
|
@Schema(description = "完整 Cookie 明文")
|
||||||
private byte[] cookieCipher;
|
private String cookie;
|
||||||
|
|
||||||
@TableField("phpsid_cipher")
|
@TableField("phpsid")
|
||||||
@Schema(description = "PHPSID 密文(存储字段,接口不回显)")
|
@Schema(description = "PHPSID 明文")
|
||||||
private byte[] phpsidCipher;
|
private String phpsid;
|
||||||
|
|
||||||
@TableField("goods_api_token_cipher")
|
@TableField("goods_api_token")
|
||||||
@Schema(description = "货品/抢购 token 密文(存储字段,接口不回显)")
|
@Schema(description = "货品/抢购 token 明文")
|
||||||
private byte[] goodsApiTokenCipher;
|
private String goodsApiToken;
|
||||||
|
|
||||||
@TableField("goods_api_app_str_cipher")
|
@TableField("goods_api_app_str")
|
||||||
@Schema(description = "签名密钥 appStr 密文(存储字段,接口不回显)")
|
@Schema(description = "签名密钥 appStr 明文")
|
||||||
private byte[] goodsApiAppStrCipher;
|
private String goodsApiAppStr;
|
||||||
|
|
||||||
@TableField("credential_version")
|
@TableField("credential_version")
|
||||||
@Schema(description = "凭证版本号")
|
@Schema(description = "凭证版本号")
|
||||||
@@ -176,37 +176,19 @@ public class LbThirdIntegrationConfig implements Serializable {
|
|||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private LocalDateTime updateTime;
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
// ---------- 明文凭证(仅请求入参,不落库)----------
|
|
||||||
|
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
@Schema(description = "完整 Cookie 明文(保存时加密入库)")
|
@Schema(description = "是否已配置 Cookie")
|
||||||
private String cookiePlain;
|
|
||||||
|
|
||||||
@TableField(exist = false)
|
|
||||||
@Schema(description = "PHPSID 明文(保存时加密入库)")
|
|
||||||
private String phpsidPlain;
|
|
||||||
|
|
||||||
@TableField(exist = false)
|
|
||||||
@Schema(description = "货品/抢购 token 明文(保存时加密入库)")
|
|
||||||
private String goodsApiTokenPlain;
|
|
||||||
|
|
||||||
@TableField(exist = false)
|
|
||||||
@Schema(description = "签名密钥 appStr 明文(保存时加密入库)")
|
|
||||||
private String goodsApiAppStrPlain;
|
|
||||||
|
|
||||||
@TableField(exist = false)
|
|
||||||
@Schema(description = "是否已配置 Cookie 密文")
|
|
||||||
private Boolean cookieConfigured;
|
private Boolean cookieConfigured;
|
||||||
|
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
@Schema(description = "是否已配置 PHPSID 密文")
|
@Schema(description = "是否已配置 PHPSID")
|
||||||
private Boolean phpsidConfigured;
|
private Boolean phpsidConfigured;
|
||||||
|
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
@Schema(description = "是否已配置货品 token 密文")
|
@Schema(description = "是否已配置货品 token")
|
||||||
private Boolean goodsApiTokenConfigured;
|
private Boolean goodsApiTokenConfigured;
|
||||||
|
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
@Schema(description = "是否已配置 appStr 密文")
|
@Schema(description = "是否已配置 appStr")
|
||||||
private Boolean goodsApiAppStrConfigured;
|
private Boolean goodsApiAppStrConfigured;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
|
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
|
||||||
import com.rj.config.HxrAdminProperties;
|
import com.rj.config.HxrAdminProperties;
|
||||||
|
import com.rj.dto.hxr.HxrAdminOrderApiContext;
|
||||||
import com.rj.dto.hxr.HxrOrderRow;
|
import com.rj.dto.hxr.HxrOrderRow;
|
||||||
import com.rj.dto.hxr.HxrOrderSelectResponse;
|
import com.rj.dto.hxr.HxrOrderSelectResponse;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -87,12 +88,75 @@ public class HxrAdminOrderSelectService {
|
|||||||
buildStatusOrderSelectUrl(properties.getOrderSelectPaidUrl(), buyTimeStart, buyTimeEnd, page));
|
buildStatusOrderSelectUrl(properties.getOrderSelectPaidUrl(), buyTimeStart, buyTimeEnd, page));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按购买时间区间、转卖状态及页码拉取订单列表(使用租户 {@code lb_third_integration_config} 解析出的运行时配置)。
|
||||||
|
*/
|
||||||
|
public Optional<HxrOrderSelectResponse> fetchOrderSelect(
|
||||||
|
String buyTimeStart,
|
||||||
|
String buyTimeEnd,
|
||||||
|
Integer isResell,
|
||||||
|
int page,
|
||||||
|
HxrAdminOrderApiContext ctx)
|
||||||
|
throws Exception {
|
||||||
|
return fetchOrderSelectInternal(
|
||||||
|
buildOrderSelectUrl(ctx, buyTimeStart, buyTimeEnd, isResell, null, page),
|
||||||
|
ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按购买时间区间及页码拉取未支付订单({@code status=0})。
|
||||||
|
*/
|
||||||
|
public Optional<HxrOrderSelectResponse> fetchUnpaidOrderSelect(
|
||||||
|
String buyTimeStart, String buyTimeEnd, int page, HxrAdminOrderApiContext ctx)
|
||||||
|
throws Exception {
|
||||||
|
return fetchOrderSelectInternal(
|
||||||
|
buildOrderSelectUrl(ctx, buyTimeStart, buyTimeEnd, null, 0, page), ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按购买时间区间及页码拉取已支付订单({@code status=1})。
|
||||||
|
*/
|
||||||
|
public Optional<HxrOrderSelectResponse> fetchPaidOrderSelect(
|
||||||
|
String buyTimeStart, String buyTimeEnd, int page, HxrAdminOrderApiContext ctx)
|
||||||
|
throws Exception {
|
||||||
|
return fetchOrderSelectInternal(
|
||||||
|
buildOrderSelectUrl(ctx, buyTimeStart, buyTimeEnd, null, 1, page), ctx);
|
||||||
|
}
|
||||||
|
|
||||||
private Optional<HxrOrderSelectResponse> fetchOrderSelectInternal(String requestUri) throws Exception {
|
private Optional<HxrOrderSelectResponse> fetchOrderSelectInternal(String requestUri) throws Exception {
|
||||||
String cookieHeader = properties.resolveCookieHeader();
|
String cookieHeader = properties.resolveCookieHeader();
|
||||||
if (cookieHeader == null || cookieHeader.isBlank()) {
|
if (cookieHeader == null || cookieHeader.isBlank()) {
|
||||||
log.warn("hxr.admin 未配置 cookie 或 phpsid,跳过拉取");
|
log.warn("hxr.admin 未配置 cookie 或 phpsid,跳过拉取");
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
return fetchOrderSelectInternal(requestUri, cookieHeader, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<HxrOrderSelectResponse> fetchOrderSelectInternal(
|
||||||
|
String requestUri, HxrAdminOrderApiContext ctx) throws Exception {
|
||||||
|
if (ctx == null) {
|
||||||
|
log.warn("订单 API 配置为空,跳过 order/select");
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
String cookieHeader = ctx.cookieHeader();
|
||||||
|
if (cookieHeader == null || cookieHeader.isBlank()) {
|
||||||
|
log.warn("未配置 cookie 或 phpsid,跳过 order/select");
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
log.info("requestUri: {}", requestUri);
|
||||||
|
return fetchOrderSelectInternal(requestUri, cookieHeader, ctx.referer());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<HxrOrderSelectResponse> fetchOrderSelectInternal(
|
||||||
|
String requestUri, String cookieHeader, String referer) throws Exception {
|
||||||
|
if (cookieHeader == null || cookieHeader.isBlank()) {
|
||||||
|
log.warn("未配置 cookie 或 phpsid,跳过 order/select");
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
String refererHeader = referer;
|
||||||
|
if (refererHeader == null || refererHeader.isBlank()) {
|
||||||
|
refererHeader = "https://hxrdhoutai.hxrdsm.cn/app/admin/order/index";
|
||||||
|
}
|
||||||
|
|
||||||
HttpClient client = HttpClient.newBuilder()
|
HttpClient client = HttpClient.newBuilder()
|
||||||
.connectTimeout(Duration.ofSeconds(35))
|
.connectTimeout(Duration.ofSeconds(35))
|
||||||
@@ -106,7 +170,7 @@ public class HxrAdminOrderSelectService {
|
|||||||
.header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")
|
.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("Cookie", cookieHeader)
|
||||||
.header("Priority", "u=1, i")
|
.header("Priority", "u=1, i")
|
||||||
.header("Referer", "https://hxrdhoutai.hxrdsm.cn/app/admin/order/index")
|
.header("Referer", refererHeader)
|
||||||
.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")
|
.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()
|
.GET()
|
||||||
.build();
|
.build();
|
||||||
@@ -126,6 +190,28 @@ public class HxrAdminOrderSelectService {
|
|||||||
return Optional.of(body);
|
return Optional.of(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String buildOrderSelectUrl(
|
||||||
|
HxrAdminOrderApiContext ctx,
|
||||||
|
String buyTimeStart,
|
||||||
|
String buyTimeEnd,
|
||||||
|
Integer isResell,
|
||||||
|
Integer status,
|
||||||
|
int page) {
|
||||||
|
int pageLimit = ctx.pageLimit() > 0 ? ctx.pageLimit() : 90;
|
||||||
|
UriComponentsBuilder b = UriComponentsBuilder.fromUriString(ctx.orderSelectBaseUrl());
|
||||||
|
b.replaceQueryParam("page", Math.max(1, page));
|
||||||
|
b.replaceQueryParam("limit", pageLimit);
|
||||||
|
b.replaceQueryParam("buy_time[0]", buyTimeStart == null ? "" : buyTimeStart);
|
||||||
|
b.replaceQueryParam("buy_time[1]", buyTimeEnd == null ? "" : buyTimeEnd);
|
||||||
|
if (isResell != null) {
|
||||||
|
b.replaceQueryParam("is_resell", isResell);
|
||||||
|
}
|
||||||
|
if (status != null) {
|
||||||
|
b.replaceQueryParam("status", status);
|
||||||
|
}
|
||||||
|
return b.build().encode().toUriString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在 {@link HxrAdminProperties#getOrderSelectUrl()} 上覆盖 {@code buy_time[0]}、{@code buy_time[1]}、{@code is_resell}。
|
* 在 {@link HxrAdminProperties#getOrderSelectUrl()} 上覆盖 {@code buy_time[0]}、{@code buy_time[1]}、{@code is_resell}。
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.PropertyNamingStrategies;
|
|||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
import com.rj.config.HxrAdminProperties;
|
import com.rj.config.HxrAdminProperties;
|
||||||
|
import com.rj.dto.hxr.HxrAdminUserApiContext;
|
||||||
import com.rj.dto.hxr.HxrLbUserSelectResponse;
|
import com.rj.dto.hxr.HxrLbUserSelectResponse;
|
||||||
import com.rj.dto.hxr.HxrSimpleApiResponse;
|
import com.rj.dto.hxr.HxrSimpleApiResponse;
|
||||||
import com.rj.dto.hxr.HxrUserRow;
|
import com.rj.dto.hxr.HxrUserRow;
|
||||||
@@ -102,7 +103,7 @@ public class HxrAdminUserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页拉取用户列表,{@code data} 解析为 {@link }(与 lb_user 字段对应)。
|
* 分页拉取用户列表(使用 {@code hxr.admin} 配置文件,兼容旧调用)。
|
||||||
*
|
*
|
||||||
* @param page 页码,从 1 开始
|
* @param page 页码,从 1 开始
|
||||||
*/
|
*/
|
||||||
@@ -112,10 +113,41 @@ public class HxrAdminUserService {
|
|||||||
log.warn("hxr.admin 未配置 cookie 或 phpsid,跳过 user/select");
|
log.warn("hxr.admin 未配置 cookie 或 phpsid,跳过 user/select");
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
HxrAdminUserApiContext ctx = new HxrAdminUserApiContext(
|
||||||
|
stripQuery(properties.getUserSelectUrl()),
|
||||||
|
USER_SELECT_PAGE_SIZE,
|
||||||
|
cookieHeader,
|
||||||
|
"https://hxrdhoutai.hxrdsm.cn/app/admin/user/index");
|
||||||
|
return fetchUserSelectPage(page, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
String uri = UriComponentsBuilder.fromUriString(properties.getUserSelectUrl())
|
/**
|
||||||
.replaceQueryParam("page", Math.max(1, page))
|
* 分页拉取用户列表(使用租户 {@code lb_third_integration_config} 解析出的运行时配置)。
|
||||||
.replaceQueryParam("limit", USER_SELECT_PAGE_SIZE)
|
*
|
||||||
|
* @param page 页码,从 1 开始
|
||||||
|
*/
|
||||||
|
public Optional<HxrLbUserSelectResponse> fetchUserSelectPage(int page, HxrAdminUserApiContext ctx)
|
||||||
|
throws Exception {
|
||||||
|
if (ctx == null) {
|
||||||
|
log.warn("用户 API 配置为空,跳过 user/select");
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
String cookieHeader = ctx.cookieHeader();
|
||||||
|
if (cookieHeader == null || cookieHeader.isBlank()) {
|
||||||
|
log.warn("未配置 cookie 或 phpsid,跳过 user/select");
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
String userSelectBaseUrl = ctx.userSelectBaseUrl();
|
||||||
|
if (userSelectBaseUrl == null || userSelectBaseUrl.isBlank()) {
|
||||||
|
log.warn("未配置 userSelectBaseUrl,跳过 user/select");
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
int pageLimit = ctx.pageLimit() > 0 ? ctx.pageLimit() : USER_SELECT_PAGE_SIZE;
|
||||||
|
int safePage = Math.max(1, page);
|
||||||
|
String uri = UriComponentsBuilder.fromUriString(userSelectBaseUrl)
|
||||||
|
.replaceQueryParam("page", safePage)
|
||||||
|
.replaceQueryParam("limit", pageLimit)
|
||||||
.replaceQueryParam("mobile", "")
|
.replaceQueryParam("mobile", "")
|
||||||
.replaceQueryParam("id", "")
|
.replaceQueryParam("id", "")
|
||||||
.replaceQueryParam("pid", "")
|
.replaceQueryParam("pid", "")
|
||||||
@@ -123,6 +155,12 @@ public class HxrAdminUserService {
|
|||||||
.encode()
|
.encode()
|
||||||
.toUriString();
|
.toUriString();
|
||||||
|
|
||||||
|
String referer = ctx.referer();
|
||||||
|
if (referer == null || referer.isBlank()) {
|
||||||
|
log.warn("未配置 referer ,跳过 user/select");
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
HttpClient client = HttpClient.newBuilder()
|
HttpClient client = HttpClient.newBuilder()
|
||||||
.connectTimeout(java.time.Duration.ofSeconds(35))
|
.connectTimeout(java.time.Duration.ofSeconds(35))
|
||||||
.followRedirects(HttpClient.Redirect.NORMAL)
|
.followRedirects(HttpClient.Redirect.NORMAL)
|
||||||
@@ -135,7 +173,7 @@ public class HxrAdminUserService {
|
|||||||
.header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")
|
.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("Cookie", cookieHeader)
|
||||||
.header("Priority", "u=1, i")
|
.header("Priority", "u=1, i")
|
||||||
.header("Referer", "https://hxrdhoutai.hxrdsm.cn/app/admin/user/index")
|
.header("Referer", referer)
|
||||||
.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")
|
.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()
|
.GET()
|
||||||
.build();
|
.build();
|
||||||
@@ -302,6 +340,14 @@ public class HxrAdminUserService {
|
|||||||
return form.toString();
|
return form.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String stripQuery(String url) {
|
||||||
|
if (url == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
int q = url.indexOf('?');
|
||||||
|
return q >= 0 ? url.substring(0, q) : url;
|
||||||
|
}
|
||||||
|
|
||||||
private static String abbreviate(String s, int maxLen) {
|
private static String abbreviate(String s, int maxLen) {
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
return "";
|
return "";
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package com.rj.service;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import com.rj.dto.LbThirdIntegrationCredentialUpdateRequest;
|
import com.rj.dto.LbThirdIntegrationCredentialUpdateRequest;
|
||||||
|
import com.rj.dto.hxr.HxrAdminOrderApiContext;
|
||||||
|
import com.rj.dto.hxr.HxrAdminUserApiContext;
|
||||||
import com.rj.dto.hxr.HxrGoodsApiContext;
|
import com.rj.dto.hxr.HxrGoodsApiContext;
|
||||||
import com.rj.entity.LbThirdIntegrationConfig;
|
import com.rj.entity.LbThirdIntegrationConfig;
|
||||||
|
|
||||||
@@ -42,4 +44,14 @@ public interface ILbThirdIntegrationConfigService extends IService<LbThirdIntegr
|
|||||||
* 按租户 id 解析货品 API 运行时配置(含解密凭证);{@code tokenOverride} 非空时优先于库中 token。
|
* 按租户 id 解析货品 API 运行时配置(含解密凭证);{@code tokenOverride} 非空时优先于库中 token。
|
||||||
*/
|
*/
|
||||||
Optional<HxrGoodsApiContext> resolveGoodsApiContext(String tenantId, String tokenOverride);
|
Optional<HxrGoodsApiContext> resolveGoodsApiContext(String tenantId, String tokenOverride);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按租户 id 解析后台用户 API 运行时配置(含 cookie/phpsid、URL、Referer)。
|
||||||
|
*/
|
||||||
|
Optional<HxrAdminUserApiContext> resolveAdminUserApiContext(String tenantId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按租户 id 解析后台订单 API 运行时配置(含 cookie/phpsid、URL、Referer)。
|
||||||
|
*/
|
||||||
|
Optional<HxrAdminOrderApiContext> resolveAdminOrderApiContext(String tenantId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.rj.service.impl;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.rj.dto.hxr.HxrAdminOrderApiContext;
|
||||||
import com.rj.dto.hxr.HxrOrderRow;
|
import com.rj.dto.hxr.HxrOrderRow;
|
||||||
import com.rj.dto.hxr.HxrOrderSelectResponse;
|
import com.rj.dto.hxr.HxrOrderSelectResponse;
|
||||||
import com.rj.entity.LbDepartmentUser;
|
import com.rj.entity.LbDepartmentUser;
|
||||||
@@ -35,9 +36,6 @@ import java.util.stream.Collectors;
|
|||||||
@Service
|
@Service
|
||||||
public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrderRow> implements ILbOrderRowService {
|
public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrderRow> implements ILbOrderRowService {
|
||||||
|
|
||||||
/** 与 hxr.admin.order-select-url 中 {@code limit} 一致,用于判断是否还有下一页 */
|
|
||||||
private static final int HXR_ORDER_PAGE_SIZE = 90;
|
|
||||||
|
|
||||||
/** 从第三方同步的订单明细默认 data_type */
|
/** 从第三方同步的订单明细默认 data_type */
|
||||||
private static final String SYNC_DATA_TYPE_DETAIL = "detail_data";
|
private static final String SYNC_DATA_TYPE_DETAIL = "detail_data";
|
||||||
|
|
||||||
@@ -59,6 +57,9 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
|
|||||||
@Autowired
|
@Autowired
|
||||||
private HxrAdminOrderSelectService hxrAdminOrderSelectService;
|
private HxrAdminOrderSelectService hxrAdminOrderSelectService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ILbThirdIntegrationConfigService lbThirdIntegrationConfigService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ILbDepartmentUserService lbDepartmentUserService;
|
private ILbDepartmentUserService lbDepartmentUserService;
|
||||||
|
|
||||||
@@ -290,6 +291,18 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
|
|||||||
|
|
||||||
|
|
||||||
String tid = tenantId.trim();
|
String tid = tenantId.trim();
|
||||||
|
Optional<HxrAdminOrderApiContext> apiContextOpt =
|
||||||
|
lbThirdIntegrationConfigService.resolveAdminOrderApiContext(tid);
|
||||||
|
if (apiContextOpt.isEmpty()) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message",
|
||||||
|
"未找到该租户的第三方集成配置,或配置未启用、URL/凭证不完整(请检查 lb_third_integration_config)");
|
||||||
|
result.put("synced", 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
HxrAdminOrderApiContext apiContext = apiContextOpt.get();
|
||||||
|
int orderPageLimit = apiContext.pageLimit() > 0 ? apiContext.pageLimit() : 90;
|
||||||
|
|
||||||
String previousTenantId = TenantContextHolder.getTenantId();
|
String previousTenantId = TenantContextHolder.getTenantId();
|
||||||
TenantContextHolder.setTenantId(tid);
|
TenantContextHolder.setTenantId(tid);
|
||||||
try {
|
try {
|
||||||
@@ -298,11 +311,12 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
|
|||||||
int totalSynced = 0;
|
int totalSynced = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
Optional<HxrOrderSelectResponse> opt =
|
Optional<HxrOrderSelectResponse> opt =
|
||||||
fetchHxrOrderPage(buyTimeStart, buyTimeEnd, isResell, hxrOrderStatus, page);
|
fetchHxrOrderPage(buyTimeStart, buyTimeEnd, isResell, hxrOrderStatus, page, apiContext);
|
||||||
if (opt.isEmpty()) {
|
if (opt.isEmpty()) {
|
||||||
if (page == 1) {
|
if (page == 1) {
|
||||||
result.put("success", false);
|
result.put("success", false);
|
||||||
result.put("message", "未拉取到订单(请检查 hxr.admin cookie/phpsid、网络或后台返回)");
|
result.put("message",
|
||||||
|
"未拉取到订单(请检查 lb_third_integration_config 中 cookie/phpsid、URL 或网络)");
|
||||||
result.put("synced", 0);
|
result.put("synced", 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -346,7 +360,7 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
|
|||||||
}
|
}
|
||||||
totalSynced += upserted;
|
totalSynced += upserted;
|
||||||
|
|
||||||
if (rows.size() < HXR_ORDER_PAGE_SIZE ) {
|
if (rows.size() < orderPageLimit) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
page++;
|
page++;
|
||||||
@@ -389,17 +403,21 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
|
|||||||
String buyTimeEnd,
|
String buyTimeEnd,
|
||||||
Integer isResell,
|
Integer isResell,
|
||||||
Integer hxrOrderStatus,
|
Integer hxrOrderStatus,
|
||||||
int page)
|
int page,
|
||||||
|
HxrAdminOrderApiContext apiContext)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
if (hxrOrderStatus != null) {
|
if (hxrOrderStatus != null) {
|
||||||
if (hxrOrderStatus == 0) {
|
if (hxrOrderStatus == 0) {
|
||||||
return hxrAdminOrderSelectService.fetchUnpaidOrderSelect(buyTimeStart, buyTimeEnd, page);
|
return hxrAdminOrderSelectService.fetchUnpaidOrderSelect(
|
||||||
|
buyTimeStart, buyTimeEnd, page, apiContext);
|
||||||
}
|
}
|
||||||
if (hxrOrderStatus == 1) {
|
if (hxrOrderStatus == 1) {
|
||||||
return hxrAdminOrderSelectService.fetchPaidOrderSelect(buyTimeStart, buyTimeEnd, page);
|
return hxrAdminOrderSelectService.fetchPaidOrderSelect(
|
||||||
|
buyTimeStart, buyTimeEnd, page, apiContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hxrAdminOrderSelectService.fetchOrderSelect(buyTimeStart, buyTimeEnd, isResell, page);
|
return hxrAdminOrderSelectService.fetchOrderSelect(
|
||||||
|
buyTimeStart, buyTimeEnd, isResell, page, apiContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.rj.common.LbThirdIntegrationConstants;
|
import com.rj.common.LbThirdIntegrationConstants;
|
||||||
import com.rj.common.PasswordUtil;
|
|
||||||
import com.rj.dto.LbThirdIntegrationCredentialUpdateRequest;
|
import com.rj.dto.LbThirdIntegrationCredentialUpdateRequest;
|
||||||
|
import com.rj.dto.hxr.HxrAdminOrderApiContext;
|
||||||
|
import com.rj.dto.hxr.HxrAdminUserApiContext;
|
||||||
import com.rj.dto.hxr.HxrGoodsApiContext;
|
import com.rj.dto.hxr.HxrGoodsApiContext;
|
||||||
import com.rj.entity.LbThirdIntegrationConfig;
|
import com.rj.entity.LbThirdIntegrationConfig;
|
||||||
import com.rj.mapper.LbThirdIntegrationConfigMapper;
|
import com.rj.mapper.LbThirdIntegrationConfigMapper;
|
||||||
@@ -15,7 +16,6 @@ import com.rj.util.LbThirdIntegrationConfigUtil;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -57,10 +57,7 @@ public class LbThirdIntegrationConfigServiceImpl
|
|||||||
entity.setCreateTime(now);
|
entity.setCreateTime(now);
|
||||||
entity.setUpdateTime(now);
|
entity.setUpdateTime(now);
|
||||||
|
|
||||||
boolean credentialUpdated = applyCredentialEncryption(entity, null);
|
if (entity.getCredentialVersion() == null) {
|
||||||
if (credentialUpdated && entity.getCredentialVersion() == null) {
|
|
||||||
entity.setCredentialVersion(1);
|
|
||||||
} else if (entity.getCredentialVersion() == null) {
|
|
||||||
entity.setCredentialVersion(1);
|
entity.setCredentialVersion(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +105,7 @@ public class LbThirdIntegrationConfigServiceImpl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean credentialUpdated = applyCredentialEncryption(entity, existing);
|
boolean credentialUpdated = applyCredentials(entity, existing);
|
||||||
if (credentialUpdated) {
|
if (credentialUpdated) {
|
||||||
int version = existing.getCredentialVersion() == null ? 1 : existing.getCredentialVersion();
|
int version = existing.getCredentialVersion() == null ? 1 : existing.getCredentialVersion();
|
||||||
entity.setCredentialVersion(version + 1);
|
entity.setCredentialVersion(version + 1);
|
||||||
@@ -324,8 +321,8 @@ public class LbThirdIntegrationConfigServiceImpl
|
|||||||
|
|
||||||
String token = StringUtils.hasText(tokenOverride)
|
String token = StringUtils.hasText(tokenOverride)
|
||||||
? tokenOverride.trim()
|
? tokenOverride.trim()
|
||||||
: decryptFromBytes(config.getGoodsApiTokenCipher());
|
: config.getGoodsApiToken();
|
||||||
String appStr = decryptFromBytes(config.getGoodsApiAppStrCipher());
|
String appStr = config.getGoodsApiAppStr();
|
||||||
if (!StringUtils.hasText(token) || !StringUtils.hasText(appStr)) {
|
if (!StringUtils.hasText(token) || !StringUtils.hasText(appStr)) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
@@ -343,6 +340,64 @@ public class LbThirdIntegrationConfigServiceImpl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<HxrAdminUserApiContext> resolveAdminUserApiContext(String tenantId) {
|
||||||
|
if (!StringUtils.hasText(tenantId)) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
LbThirdIntegrationConfig config = getByTenantIdOrNull(tenantId.trim());
|
||||||
|
if (config == null) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
if (config.getEnabled() == null || config.getEnabled() != 1) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
String cookieHeader = LbThirdIntegrationConfigUtil.resolveCookieHeader(config);
|
||||||
|
if (!StringUtils.hasText(cookieHeader)) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Optional.of(new HxrAdminUserApiContext(
|
||||||
|
LbThirdIntegrationConfigUtil.resolveUserSelectBaseUrl(config),
|
||||||
|
LbThirdIntegrationConfigUtil.resolveUserPageLimit(config),
|
||||||
|
cookieHeader.trim(),
|
||||||
|
LbThirdIntegrationConfigUtil.resolveUserReferer(config)));
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<HxrAdminOrderApiContext> resolveAdminOrderApiContext(String tenantId) {
|
||||||
|
if (!StringUtils.hasText(tenantId)) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
LbThirdIntegrationConfig config = getByTenantIdOrNull(tenantId.trim());
|
||||||
|
if (config == null) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
if (config.getEnabled() == null || config.getEnabled() != 1) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
String cookieHeader = LbThirdIntegrationConfigUtil.resolveCookieHeader(config);
|
||||||
|
if (!StringUtils.hasText(cookieHeader)) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Optional.of(new HxrAdminOrderApiContext(
|
||||||
|
LbThirdIntegrationConfigUtil.resolveOrderSelectBaseUrl(config),
|
||||||
|
LbThirdIntegrationConfigUtil.resolveOrderPageLimit(config),
|
||||||
|
cookieHeader.trim(),
|
||||||
|
LbThirdIntegrationConfigUtil.resolveOrderReferer(config)));
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private LbThirdIntegrationConfig getByTenantIdOrNull(String tenantId) {
|
private LbThirdIntegrationConfig getByTenantIdOrNull(String tenantId) {
|
||||||
return this.getOne(new LambdaQueryWrapper<LbThirdIntegrationConfig>()
|
return this.getOne(new LambdaQueryWrapper<LbThirdIntegrationConfig>()
|
||||||
.eq(LbThirdIntegrationConfig::getTenantId, tenantId)
|
.eq(LbThirdIntegrationConfig::getTenantId, tenantId)
|
||||||
@@ -359,7 +414,7 @@ public class LbThirdIntegrationConfigServiceImpl
|
|||||||
|| Boolean.TRUE.equals(request.getClearGoodsApiToken())
|
|| Boolean.TRUE.equals(request.getClearGoodsApiToken())
|
||||||
|| Boolean.TRUE.equals(request.getClearGoodsApiAppStr());
|
|| Boolean.TRUE.equals(request.getClearGoodsApiAppStr());
|
||||||
if (!hasUpdate && !hasClear) {
|
if (!hasUpdate && !hasClear) {
|
||||||
return "请至少提供一项凭证明文,或指定一项 clear* 清除操作";
|
return "请至少提供一项凭证,或指定一项 clear* 清除操作";
|
||||||
}
|
}
|
||||||
if (Boolean.TRUE.equals(request.getClearCookie()) && StringUtils.hasText(request.getCookie())) {
|
if (Boolean.TRUE.equals(request.getClearCookie()) && StringUtils.hasText(request.getCookie())) {
|
||||||
return "clearCookie 与 cookie 不能同时传";
|
return "clearCookie 与 cookie 不能同时传";
|
||||||
@@ -380,27 +435,27 @@ public class LbThirdIntegrationConfigServiceImpl
|
|||||||
LambdaUpdateWrapper<LbThirdIntegrationConfig> uw,
|
LambdaUpdateWrapper<LbThirdIntegrationConfig> uw,
|
||||||
LbThirdIntegrationCredentialUpdateRequest request) {
|
LbThirdIntegrationCredentialUpdateRequest request) {
|
||||||
if (Boolean.TRUE.equals(request.getClearCookie())) {
|
if (Boolean.TRUE.equals(request.getClearCookie())) {
|
||||||
uw.set(LbThirdIntegrationConfig::getCookieCipher, null);
|
uw.set(LbThirdIntegrationConfig::getCookie, null);
|
||||||
} else if (StringUtils.hasText(request.getCookie())) {
|
} else if (StringUtils.hasText(request.getCookie())) {
|
||||||
uw.set(LbThirdIntegrationConfig::getCookieCipher, encryptToBytes(request.getCookie()));
|
uw.set(LbThirdIntegrationConfig::getCookie, request.getCookie().trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Boolean.TRUE.equals(request.getClearPhpsid())) {
|
if (Boolean.TRUE.equals(request.getClearPhpsid())) {
|
||||||
uw.set(LbThirdIntegrationConfig::getPhpsidCipher, null);
|
uw.set(LbThirdIntegrationConfig::getPhpsid, null);
|
||||||
} else if (StringUtils.hasText(request.getPhpsid())) {
|
} else if (StringUtils.hasText(request.getPhpsid())) {
|
||||||
uw.set(LbThirdIntegrationConfig::getPhpsidCipher, encryptToBytes(request.getPhpsid()));
|
uw.set(LbThirdIntegrationConfig::getPhpsid, request.getPhpsid().trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Boolean.TRUE.equals(request.getClearGoodsApiToken())) {
|
if (Boolean.TRUE.equals(request.getClearGoodsApiToken())) {
|
||||||
uw.set(LbThirdIntegrationConfig::getGoodsApiTokenCipher, null);
|
uw.set(LbThirdIntegrationConfig::getGoodsApiToken, null);
|
||||||
} else if (StringUtils.hasText(request.getGoodsApiToken())) {
|
} else if (StringUtils.hasText(request.getGoodsApiToken())) {
|
||||||
uw.set(LbThirdIntegrationConfig::getGoodsApiTokenCipher, encryptToBytes(request.getGoodsApiToken()));
|
uw.set(LbThirdIntegrationConfig::getGoodsApiToken, request.getGoodsApiToken().trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Boolean.TRUE.equals(request.getClearGoodsApiAppStr())) {
|
if (Boolean.TRUE.equals(request.getClearGoodsApiAppStr())) {
|
||||||
uw.set(LbThirdIntegrationConfig::getGoodsApiAppStrCipher, null);
|
uw.set(LbThirdIntegrationConfig::getGoodsApiAppStr, null);
|
||||||
} else if (StringUtils.hasText(request.getGoodsApiAppStr())) {
|
} else if (StringUtils.hasText(request.getGoodsApiAppStr())) {
|
||||||
uw.set(LbThirdIntegrationConfig::getGoodsApiAppStrCipher, encryptToBytes(request.getGoodsApiAppStr()));
|
uw.set(LbThirdIntegrationConfig::getGoodsApiAppStr, request.getGoodsApiAppStr().trim());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,20 +465,20 @@ public class LbThirdIntegrationConfigServiceImpl
|
|||||||
data.put("tenantId", config.getTenantId());
|
data.put("tenantId", config.getTenantId());
|
||||||
data.put("providerCode", config.getProviderCode());
|
data.put("providerCode", config.getProviderCode());
|
||||||
data.put("authType", config.getAuthType());
|
data.put("authType", config.getAuthType());
|
||||||
data.put("cookieConfigured", hasCipher(config.getCookieCipher()));
|
data.put("cookieConfigured", isConfigured(config.getCookie()));
|
||||||
data.put("phpsidConfigured", hasCipher(config.getPhpsidCipher()));
|
data.put("phpsidConfigured", isConfigured(config.getPhpsid()));
|
||||||
data.put("goodsApiTokenConfigured", hasCipher(config.getGoodsApiTokenCipher()));
|
data.put("goodsApiTokenConfigured", isConfigured(config.getGoodsApiToken()));
|
||||||
data.put("goodsApiAppStrConfigured", hasCipher(config.getGoodsApiAppStrCipher()));
|
data.put("goodsApiAppStrConfigured", isConfigured(config.getGoodsApiAppStr()));
|
||||||
data.put("credentialVersion", config.getCredentialVersion());
|
data.put("credentialVersion", config.getCredentialVersion());
|
||||||
data.put("credentialExpireTime", config.getCredentialExpireTime());
|
data.put("credentialExpireTime", config.getCredentialExpireTime());
|
||||||
data.put("lastVerifiedTime", config.getLastVerifiedTime());
|
data.put("lastVerifiedTime", config.getLastVerifiedTime());
|
||||||
data.put("lastVerifiedOk", config.getLastVerifiedOk());
|
data.put("lastVerifiedOk", config.getLastVerifiedOk());
|
||||||
data.put("updateTime", config.getUpdateTime());
|
data.put("updateTime", config.getUpdateTime());
|
||||||
if (includePlaintext) {
|
if (includePlaintext) {
|
||||||
data.put("cookie", decryptFromBytes(config.getCookieCipher()));
|
data.put("cookie", config.getCookie());
|
||||||
data.put("phpsid", decryptFromBytes(config.getPhpsidCipher()));
|
data.put("phpsid", config.getPhpsid());
|
||||||
data.put("goodsApiToken", decryptFromBytes(config.getGoodsApiTokenCipher()));
|
data.put("goodsApiToken", config.getGoodsApiToken());
|
||||||
data.put("goodsApiAppStr", decryptFromBytes(config.getGoodsApiAppStrCipher()));
|
data.put("goodsApiAppStr", config.getGoodsApiAppStr());
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@@ -496,85 +551,61 @@ public class LbThirdIntegrationConfigServiceImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将明文凭证加密为 VARBINARY;未传明文则保留已有密文(更新场景)。
|
* 更新场景下保留未传凭证字段的已有值。
|
||||||
*
|
*
|
||||||
* @return 是否有任一凭证字段被更新
|
* @return 是否有任一凭证字段被更新
|
||||||
*/
|
*/
|
||||||
private boolean applyCredentialEncryption(LbThirdIntegrationConfig entity, LbThirdIntegrationConfig existing) {
|
private boolean applyCredentials(LbThirdIntegrationConfig entity, LbThirdIntegrationConfig existing) {
|
||||||
boolean updated = false;
|
boolean updated = false;
|
||||||
|
|
||||||
if (StringUtils.hasText(entity.getCookiePlain())) {
|
if (StringUtils.hasText(entity.getCookie())) {
|
||||||
entity.setCookieCipher(encryptToBytes(entity.getCookiePlain()));
|
entity.setCookie(entity.getCookie().trim());
|
||||||
updated = true;
|
updated = true;
|
||||||
} else if (existing != null) {
|
} else if (existing != null) {
|
||||||
entity.setCookieCipher(existing.getCookieCipher());
|
entity.setCookie(existing.getCookie());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.hasText(entity.getPhpsidPlain())) {
|
if (StringUtils.hasText(entity.getPhpsid())) {
|
||||||
entity.setPhpsidCipher(encryptToBytes(entity.getPhpsidPlain()));
|
entity.setPhpsid(entity.getPhpsid().trim());
|
||||||
updated = true;
|
updated = true;
|
||||||
} else if (existing != null) {
|
} else if (existing != null) {
|
||||||
entity.setPhpsidCipher(existing.getPhpsidCipher());
|
entity.setPhpsid(existing.getPhpsid());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.hasText(entity.getGoodsApiTokenPlain())) {
|
if (StringUtils.hasText(entity.getGoodsApiToken())) {
|
||||||
entity.setGoodsApiTokenCipher(encryptToBytes(entity.getGoodsApiTokenPlain()));
|
entity.setGoodsApiToken(entity.getGoodsApiToken().trim());
|
||||||
updated = true;
|
updated = true;
|
||||||
} else if (existing != null) {
|
} else if (existing != null) {
|
||||||
entity.setGoodsApiTokenCipher(existing.getGoodsApiTokenCipher());
|
entity.setGoodsApiToken(existing.getGoodsApiToken());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.hasText(entity.getGoodsApiAppStrPlain())) {
|
if (StringUtils.hasText(entity.getGoodsApiAppStr())) {
|
||||||
entity.setGoodsApiAppStrCipher(encryptToBytes(entity.getGoodsApiAppStrPlain()));
|
entity.setGoodsApiAppStr(entity.getGoodsApiAppStr().trim());
|
||||||
updated = true;
|
updated = true;
|
||||||
} else if (existing != null) {
|
} else if (existing != null) {
|
||||||
entity.setGoodsApiAppStrCipher(existing.getGoodsApiAppStrCipher());
|
entity.setGoodsApiAppStr(existing.getGoodsApiAppStr());
|
||||||
}
|
}
|
||||||
|
|
||||||
entity.setCookiePlain(null);
|
|
||||||
entity.setPhpsidPlain(null);
|
|
||||||
entity.setGoodsApiTokenPlain(null);
|
|
||||||
entity.setGoodsApiAppStrPlain(null);
|
|
||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] encryptToBytes(String plainText) {
|
|
||||||
String encrypted = PasswordUtil.encryptReversibleWithDefaultSalt(plainText);
|
|
||||||
return encrypted.getBytes(StandardCharsets.UTF_8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 供业务层读取凭证明文(内部使用)
|
|
||||||
*/
|
|
||||||
public static String decryptFromBytes(byte[] cipherBytes) {
|
|
||||||
if (cipherBytes == null || cipherBytes.length == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String stored = new String(cipherBytes, StandardCharsets.UTF_8);
|
|
||||||
return PasswordUtil.decryptReversibleWithDefaultSalt(stored);
|
|
||||||
}
|
|
||||||
|
|
||||||
private LbThirdIntegrationConfig maskForResponse(LbThirdIntegrationConfig entity) {
|
private LbThirdIntegrationConfig maskForResponse(LbThirdIntegrationConfig entity) {
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
entity.setCookieConfigured(hasCipher(entity.getCookieCipher()));
|
entity.setCookieConfigured(isConfigured(entity.getCookie()));
|
||||||
entity.setPhpsidConfigured(hasCipher(entity.getPhpsidCipher()));
|
entity.setPhpsidConfigured(isConfigured(entity.getPhpsid()));
|
||||||
entity.setGoodsApiTokenConfigured(hasCipher(entity.getGoodsApiTokenCipher()));
|
entity.setGoodsApiTokenConfigured(isConfigured(entity.getGoodsApiToken()));
|
||||||
entity.setGoodsApiAppStrConfigured(hasCipher(entity.getGoodsApiAppStrCipher()));
|
entity.setGoodsApiAppStrConfigured(isConfigured(entity.getGoodsApiAppStr()));
|
||||||
|
|
||||||
entity.setCookieCipher(null);
|
entity.setCookie(null);
|
||||||
entity.setPhpsidCipher(null);
|
entity.setPhpsid(null);
|
||||||
entity.setGoodsApiTokenCipher(null);
|
entity.setGoodsApiToken(null);
|
||||||
entity.setGoodsApiAppStrCipher(null);
|
entity.setGoodsApiAppStr(null);
|
||||||
entity.setCookiePlain(null);
|
|
||||||
entity.setPhpsidPlain(null);
|
|
||||||
entity.setGoodsApiTokenPlain(null);
|
|
||||||
entity.setGoodsApiAppStrPlain(null);
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasCipher(byte[] cipher) {
|
private static boolean isConfigured(String value) {
|
||||||
return cipher != null && cipher.length > 0;
|
return StringUtils.hasText(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ package com.rj.service.impl;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.rj.dto.hxr.HxrAdminUserApiContext;
|
||||||
import com.rj.dto.hxr.HxrLbUserSelectResponse;
|
import com.rj.dto.hxr.HxrLbUserSelectResponse;
|
||||||
import com.rj.entity.LbUser;
|
import com.rj.entity.LbUser;
|
||||||
import com.rj.mapper.LbUserMapper;
|
import com.rj.mapper.LbUserMapper;
|
||||||
import com.rj.service.HxrAdminUserService;
|
import com.rj.service.HxrAdminUserService;
|
||||||
|
import com.rj.service.ILbThirdIntegrationConfigService;
|
||||||
import com.rj.service.ILbUserService;
|
import com.rj.service.ILbUserService;
|
||||||
import com.rj.tenant.TenantContextHolder;
|
import com.rj.tenant.TenantContextHolder;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -34,6 +36,9 @@ public class LbUserServiceImpl extends ServiceImpl<LbUserMapper, LbUser> impleme
|
|||||||
@Autowired
|
@Autowired
|
||||||
private HxrAdminUserService hxrAdminUserService;
|
private HxrAdminUserService hxrAdminUserService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ILbThirdIntegrationConfigService lbThirdIntegrationConfigService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> add(LbUser entity) {
|
public Map<String, Object> add(LbUser entity) {
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
@@ -313,6 +318,20 @@ public class LbUserServiceImpl extends ServiceImpl<LbUserMapper, LbUser> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
String tid = tenantId.trim();
|
String tid = tenantId.trim();
|
||||||
|
Optional<HxrAdminUserApiContext> apiContextOpt =
|
||||||
|
lbThirdIntegrationConfigService.resolveAdminUserApiContext(tid);
|
||||||
|
if (apiContextOpt.isEmpty()) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message",
|
||||||
|
"未找到该租户的第三方集成配置,或配置未启用、URL/凭证不完整(请检查 lb_third_integration_config)");
|
||||||
|
result.put("synced", 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
HxrAdminUserApiContext apiContext = apiContextOpt.get();
|
||||||
|
int userPageLimit = apiContext.pageLimit() > 0
|
||||||
|
? apiContext.pageLimit()
|
||||||
|
: HxrAdminUserService.USER_SELECT_PAGE_SIZE;
|
||||||
|
|
||||||
String previousTenantId = TenantContextHolder.getTenantId();
|
String previousTenantId = TenantContextHolder.getTenantId();
|
||||||
TenantContextHolder.setTenantId(tid);
|
TenantContextHolder.setTenantId(tid);
|
||||||
try {
|
try {
|
||||||
@@ -320,11 +339,13 @@ public class LbUserServiceImpl extends ServiceImpl<LbUserMapper, LbUser> impleme
|
|||||||
int page = 1;
|
int page = 1;
|
||||||
int totalSynced = 0;
|
int totalSynced = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
Optional<HxrLbUserSelectResponse> opt = hxrAdminUserService.fetchUserSelectPage(page);
|
Optional<HxrLbUserSelectResponse> opt =
|
||||||
|
hxrAdminUserService.fetchUserSelectPage(page, apiContext);
|
||||||
if (opt.isEmpty()) {
|
if (opt.isEmpty()) {
|
||||||
if (page == 1) {
|
if (page == 1) {
|
||||||
result.put("success", false);
|
result.put("success", false);
|
||||||
result.put("message", "未拉取到用户(请检查 hxr.admin cookie/phpsid、网络或后台返回)");
|
result.put("message",
|
||||||
|
"未拉取到用户(请检查 lb_third_integration_config 中 cookie/phpsid、URL 或网络)");
|
||||||
result.put("synced", 0);
|
result.put("synced", 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -370,7 +391,7 @@ public class LbUserServiceImpl extends ServiceImpl<LbUserMapper, LbUser> impleme
|
|||||||
}
|
}
|
||||||
totalSynced += upserted;
|
totalSynced += upserted;
|
||||||
|
|
||||||
if (rows.size() < HxrAdminUserService.USER_SELECT_PAGE_SIZE) {
|
if (rows.size() < userPageLimit) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
page++;
|
page++;
|
||||||
|
|||||||
@@ -47,6 +47,87 @@ public final class LbThirdIntegrationConfigUtil {
|
|||||||
return limit;
|
return limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String resolveUserSelectBaseUrl(LbThirdIntegrationConfig config) {
|
||||||
|
String base = trimTrailingSlash(requireText(config.getAdminBaseUrl(), "adminBaseUrl"));
|
||||||
|
String path = config.getUserSelectPath();
|
||||||
|
if (!StringUtils.hasText(path)) {
|
||||||
|
path = LbThirdIntegrationConstants.DEFAULT_USER_SELECT_PATH;
|
||||||
|
}
|
||||||
|
path = path.trim();
|
||||||
|
if (!path.startsWith("/")) {
|
||||||
|
path = "/" + path;
|
||||||
|
}
|
||||||
|
return base + path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String resolveUserReferer(LbThirdIntegrationConfig config) {
|
||||||
|
if (StringUtils.hasText(config.getUserReferer())) {
|
||||||
|
return config.getUserReferer().trim();
|
||||||
|
}
|
||||||
|
return trimTrailingSlash(requireText(config.getAdminBaseUrl(), "adminBaseUrl"))
|
||||||
|
+ "/app/admin/user/index";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int resolveUserPageLimit(LbThirdIntegrationConfig config) {
|
||||||
|
Integer limit = config.getUserPageLimit();
|
||||||
|
if (limit == null || limit < 1) {
|
||||||
|
return LbThirdIntegrationConstants.DEFAULT_USER_PAGE_LIMIT;
|
||||||
|
}
|
||||||
|
return limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String resolveOrderSelectBaseUrl(LbThirdIntegrationConfig config) {
|
||||||
|
String base = trimTrailingSlash(requireText(config.getAdminBaseUrl(), "adminBaseUrl"));
|
||||||
|
String path = config.getOrderSelectPath();
|
||||||
|
if (!StringUtils.hasText(path)) {
|
||||||
|
path = LbThirdIntegrationConstants.DEFAULT_ORDER_SELECT_PATH;
|
||||||
|
}
|
||||||
|
path = path.trim();
|
||||||
|
if (!path.startsWith("/")) {
|
||||||
|
path = "/" + path;
|
||||||
|
}
|
||||||
|
return base + path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String resolveOrderReferer(LbThirdIntegrationConfig config) {
|
||||||
|
if (StringUtils.hasText(config.getOrderReferer())) {
|
||||||
|
return config.getOrderReferer().trim();
|
||||||
|
}
|
||||||
|
return trimTrailingSlash(requireText(config.getAdminBaseUrl(), "adminBaseUrl"))
|
||||||
|
+ "/app/admin/order/index";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int resolveOrderPageLimit(LbThirdIntegrationConfig config) {
|
||||||
|
Integer limit = config.getOrderPageLimit();
|
||||||
|
if (limit == null || limit < 1) {
|
||||||
|
return LbThirdIntegrationConstants.DEFAULT_ORDER_PAGE_LIMIT;
|
||||||
|
}
|
||||||
|
return limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组装 Cookie 请求头:优先完整 cookie,否则 {@code PHPSID=} + phpsid。
|
||||||
|
*/
|
||||||
|
public static String resolveCookieHeader(LbThirdIntegrationConfig config) {
|
||||||
|
String c = firstNonBlank(config.getCookie());
|
||||||
|
if (c != null) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
String id = firstNonBlank(config.getPhpsid());
|
||||||
|
if (id != null) {
|
||||||
|
return "PHPSID=" + id;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String firstNonBlank(String s) {
|
||||||
|
if (s == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String t = s.trim();
|
||||||
|
return t.isEmpty() ? null : t;
|
||||||
|
}
|
||||||
|
|
||||||
private static String requireText(String value, String fieldName) {
|
private static String requireText(String value, String fieldName) {
|
||||||
if (!StringUtils.hasText(value)) {
|
if (!StringUtils.hasText(value)) {
|
||||||
throw new IllegalStateException(fieldName + " 未配置");
|
throw new IllegalStateException(fieldName + " 未配置");
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ CREATE TABLE `lb_third_integration_config` (
|
|||||||
`goods_api_referer` VARCHAR(256) DEFAULT NULL COMMENT '货品 Referer;空则 web_base_url/',
|
`goods_api_referer` VARCHAR(256) DEFAULT NULL COMMENT '货品 Referer;空则 web_base_url/',
|
||||||
|
|
||||||
`auth_type` VARCHAR(32) NOT NULL DEFAULT 'COOKIE_PHPSID' COMMENT 'Admin 鉴权类型',
|
`auth_type` VARCHAR(32) NOT NULL DEFAULT 'COOKIE_PHPSID' COMMENT 'Admin 鉴权类型',
|
||||||
`cookie_cipher` VARBINARY(1024) DEFAULT NULL COMMENT '完整 Cookie 密文(优先使用)',
|
`cookie` VARCHAR(1024) DEFAULT NULL COMMENT '完整 Cookie 明文(优先使用)',
|
||||||
`phpsid_cipher` VARBINARY(512) DEFAULT NULL COMMENT 'PHPSID 值密文',
|
`phpsid` VARCHAR(512) DEFAULT NULL COMMENT 'PHPSID 值明文',
|
||||||
`goods_api_token_cipher` VARBINARY(512) DEFAULT NULL COMMENT '货品/抢购 token 密文',
|
`goods_api_token` VARCHAR(512) DEFAULT NULL COMMENT '货品/抢购 token 明文',
|
||||||
`goods_api_app_str_cipher` VARBINARY(512) DEFAULT NULL COMMENT '签名密钥 appStr 密文',
|
`goods_api_app_str` VARCHAR(512) DEFAULT NULL COMMENT '签名密钥 appStr 明文',
|
||||||
`credential_version` INT NOT NULL DEFAULT 1 COMMENT '凭证版本号,轮换时递增',
|
`credential_version` INT NOT NULL DEFAULT 1 COMMENT '凭证版本号,轮换时递增',
|
||||||
`credential_expire_time` DATETIME DEFAULT NULL COMMENT '凭证预计过期时间',
|
`credential_expire_time` DATETIME DEFAULT NULL COMMENT '凭证预计过期时间',
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user