已超出当天可抢订单数 ,停止抢单
This commit is contained in:
@@ -11,6 +11,7 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
@@ -68,6 +69,18 @@ public class LbFanManagement implements Serializable {
|
||||
@Schema(description = "登录 token")
|
||||
private String token;
|
||||
|
||||
@TableField("coupon")
|
||||
@Schema(description = "优惠券金额")
|
||||
private BigDecimal coupon;
|
||||
|
||||
@TableField("self_bonus")
|
||||
@Schema(description = "自购奖金")
|
||||
private BigDecimal selfBonus;
|
||||
|
||||
@TableField("share_bonus")
|
||||
@Schema(description = "分享奖金")
|
||||
private BigDecimal shareBonus;
|
||||
|
||||
@TableField("created_at")
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
|
||||
@@ -37,6 +37,9 @@ public class HxrAdminBuyService {
|
||||
/** 与 hxrd 前端 DevTools 一致,使用 {@code Token} 而非小写 {@code token}。 */
|
||||
private static final String HEADER_TOKEN = "Token";
|
||||
|
||||
/** 外部系统返回此文案时表示该账号当日可抢订单数已满,应停止继续抢购。 */
|
||||
public static final String MSG_DAILY_LIMIT_EXCEEDED = "已超出当天可抢订单数";
|
||||
|
||||
private static final ObjectMapper JSON = new ObjectMapper()
|
||||
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
|
||||
|
||||
@@ -148,6 +151,10 @@ public class HxrAdminBuyService {
|
||||
log.warn("hxr /api/order/buy 鉴权失败常见原因:Token 与浏览器不一致或已过期、goodsApiAppStr 错误;"
|
||||
+ "请在 rush-buy 请求体传入浏览器 DevTools 中 Token 头的值,并核对 lb_third_integration_config.goods_api_token / goods_api_app_str");
|
||||
}
|
||||
if (MSG_DAILY_LIMIT_EXCEEDED.equals(msg)) {
|
||||
log.warn("hxr /api/order/buy 当日可抢订单数已满,停止该账号继续抢购 id={} sellerId={} tokenPrefix={}",
|
||||
goodsId, sellerId, abbreviate(resolvedToken, 8));
|
||||
}
|
||||
}
|
||||
return new BuyApiResult(code == 0, code, msg);
|
||||
}
|
||||
@@ -169,6 +176,11 @@ public class HxrAdminBuyService {
|
||||
public static BuyApiResult failure(int code, String msg) {
|
||||
return new BuyApiResult(false, code, msg);
|
||||
}
|
||||
|
||||
/** {@code code=1} 且 msg 为「已超出当天可抢订单数」时,调用方应停止该账号后续抢购。 */
|
||||
public boolean dailyLimitExceeded() {
|
||||
return apiCode == 1 && MSG_DAILY_LIMIT_EXCEEDED.equals(apiMsg);
|
||||
}
|
||||
}
|
||||
|
||||
private static String randomNoncestr() {
|
||||
|
||||
@@ -59,7 +59,7 @@ public class HxrAdminUserLoginService {
|
||||
String noncestr = randomNoncestr();
|
||||
|
||||
Map<String, Object> body = new LinkedHashMap<>();
|
||||
body.put("mobile", mobile.trim());
|
||||
body.put("account", mobile.trim());
|
||||
body.put("password", password.trim());
|
||||
String bodyJson = JSON.writeValueAsString(body);
|
||||
|
||||
@@ -76,7 +76,7 @@ public class HxrAdminUserLoginService {
|
||||
String appStr = ctx.appStr();
|
||||
if (StringUtils.hasText(appStr)) {
|
||||
Map<String, Object> signParams = new LinkedHashMap<>();
|
||||
signParams.put("mobile", mobile.trim());
|
||||
signParams.put("account", mobile.trim());
|
||||
signParams.put("password", password.trim());
|
||||
signParams.put("timestamp", timestamp);
|
||||
signParams.put("noncestr", noncestr);
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.rj.dto.LbThirdIntegrationCredentialUpdateRequest;
|
||||
import com.rj.dto.hxr.HxrAdminOrderApiContext;
|
||||
import com.rj.dto.hxr.HxrAdminUserApiContext;
|
||||
import com.rj.dto.hxr.HxrFansApiContext;
|
||||
import com.rj.dto.hxr.HxrGoodsApiContext;
|
||||
import com.rj.dto.hxr.HxrUserLoginApiContext;
|
||||
import com.rj.entity.LbThirdIntegrationConfig;
|
||||
@@ -60,4 +61,10 @@ public interface ILbThirdIntegrationConfigService extends IService<LbThirdIntegr
|
||||
* 按租户 id 解析用户登录 API 运行时配置(login_api_path、Origin、Referer、appStr)。
|
||||
*/
|
||||
Optional<HxrUserLoginApiContext> resolveUserLoginApiContext(String tenantId);
|
||||
|
||||
/**
|
||||
* 按租户 id 解析粉丝列表 API 运行时配置(fans_api_path、fans_page_limit、Origin、Referer、appStr);
|
||||
* {@code token} 为登录用户 token,必填。
|
||||
*/
|
||||
Optional<HxrFansApiContext> resolveFansApiContext(String tenantId, String token);
|
||||
}
|
||||
|
||||
@@ -4,9 +4,13 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.rj.dto.LbFanSimulateLoginRequest;
|
||||
import com.rj.dto.hxr.HxrFansApiContext;
|
||||
import com.rj.dto.hxr.HxrLbFansPageData;
|
||||
import com.rj.dto.hxr.HxrLbFansSelectResponse;
|
||||
import com.rj.dto.hxr.HxrUserLoginApiContext;
|
||||
import com.rj.entity.LbFanManagement;
|
||||
import com.rj.mapper.LbFanManagementMapper;
|
||||
import com.rj.service.HxrAdminFansService;
|
||||
import com.rj.service.HxrAdminUserLoginService;
|
||||
import com.rj.service.ILbFanManagementService;
|
||||
import com.rj.service.ILbThirdIntegrationConfigService;
|
||||
@@ -16,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
@@ -40,6 +45,9 @@ public class LbFanManagementServiceImpl
|
||||
@Autowired
|
||||
private HxrAdminUserLoginService hxrAdminUserLoginService;
|
||||
|
||||
@Autowired
|
||||
private HxrAdminFansService hxrAdminFansService;
|
||||
|
||||
private static final String DEFAULT_SIMULATE_LOGIN_PASSWORD = "123456";
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER =
|
||||
@@ -67,6 +75,15 @@ public class LbFanManagementServiceImpl
|
||||
if (entity.getShareNum() == null) {
|
||||
entity.setShareNum(0);
|
||||
}
|
||||
if (entity.getCoupon() == null) {
|
||||
entity.setCoupon(BigDecimal.ZERO);
|
||||
}
|
||||
if (entity.getSelfBonus() == null) {
|
||||
entity.setSelfBonus(BigDecimal.ZERO);
|
||||
}
|
||||
if (entity.getShareBonus() == null) {
|
||||
entity.setShareBonus(BigDecimal.ZERO);
|
||||
}
|
||||
if (entity.getCreatedAt() == null) {
|
||||
entity.setCreatedAt(LocalDateTime.now());
|
||||
}
|
||||
@@ -288,6 +305,18 @@ public class LbFanManagementServiceImpl
|
||||
item.put("parsed", loginResult.parsed());
|
||||
if (loginResult.success()) {
|
||||
successCount++;
|
||||
Map<String, Object> userinfo = extractUserinfo(loginResult.parsed());
|
||||
if (userinfo != null) {
|
||||
Map<String, Object> saveResult =
|
||||
saveFanFromLoginUserinfo(userinfo, tenantId);
|
||||
item.putAll(saveResult);
|
||||
if (Boolean.TRUE.equals(saveResult.get("saved"))) {
|
||||
item.putAll(fetchAndSaveFansFromThirdParty(userinfo, tenantId));
|
||||
}
|
||||
} else {
|
||||
item.put("saved", false);
|
||||
item.put("saveMsg", "响应中无 data.userinfo");
|
||||
}
|
||||
} else {
|
||||
failCount++;
|
||||
}
|
||||
@@ -408,4 +437,350 @@ public class LbFanManagementServiceImpl
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Map<String, Object> extractUserinfo(Object parsed) {
|
||||
if (!(parsed instanceof Map<?, ?> root)) {
|
||||
return null;
|
||||
}
|
||||
Object dataObj = root.get("data");
|
||||
if (!(dataObj instanceof Map<?, ?> data)) {
|
||||
return null;
|
||||
}
|
||||
Object userinfoObj = data.get("userinfo");
|
||||
if (!(userinfoObj instanceof Map<?, ?>)) {
|
||||
return null;
|
||||
}
|
||||
return (Map<String, Object>) userinfoObj;
|
||||
}
|
||||
|
||||
private Map<String, Object> saveFanFromLoginUserinfo(Map<String, Object> userinfo, String tenantId) {
|
||||
Map<String, Object> saveResult = new LinkedHashMap<>();
|
||||
Long fanId = parseLong(userinfo.get("id"));
|
||||
if (fanId == null) {
|
||||
saveResult.put("saved", false);
|
||||
saveResult.put("saveMsg", "userinfo.id 为空");
|
||||
return saveResult;
|
||||
}
|
||||
|
||||
LbFanManagement entity = new LbFanManagement();
|
||||
entity.setTenantId(tenantId);
|
||||
entity.setId(fanId);
|
||||
entity.setIdTenantId(buildIdTenantId(fanId, tenantId));
|
||||
entity.setAvatar(parseString(userinfo.get("avatar")));
|
||||
entity.setNickname(parseString(userinfo.get("nickname")));
|
||||
entity.setMobile(parseString(userinfo.get("mobile")));
|
||||
entity.setToken(parseString(userinfo.get("token")));
|
||||
entity.setCoupon(parseDecimal(userinfo.get("coupon")));
|
||||
entity.setSelfBonus(parseDecimal(userinfo.get("self_bonus")));
|
||||
entity.setShareBonus(parseDecimal(userinfo.get("share_bonus")));
|
||||
trimStringFields(entity);
|
||||
|
||||
LbFanManagement existing = this.getById(entity.getIdTenantId());
|
||||
if (existing != null) {
|
||||
entity.setCreatedAt(existing.getCreatedAt());
|
||||
entity.setShareNum(existing.getShareNum());
|
||||
entity.setPName(existing.getPName());
|
||||
entity.setPid(existing.getPid());
|
||||
entity.setPPhone(existing.getPPhone());
|
||||
if (entity.getCoupon() == null) {
|
||||
entity.setCoupon(existing.getCoupon());
|
||||
}
|
||||
if (entity.getSelfBonus() == null) {
|
||||
entity.setSelfBonus(existing.getSelfBonus());
|
||||
}
|
||||
if (entity.getShareBonus() == null) {
|
||||
entity.setShareBonus(existing.getShareBonus());
|
||||
}
|
||||
boolean ok = this.updateById(entity);
|
||||
saveResult.put("saved", ok);
|
||||
saveResult.put("saveMsg", ok ? "已更新" : "更新失败");
|
||||
if (ok) {
|
||||
saveResult.put("fan", this.getById(entity.getIdTenantId()));
|
||||
}
|
||||
return saveResult;
|
||||
}
|
||||
|
||||
if (entity.getShareNum() == null) {
|
||||
entity.setShareNum(0);
|
||||
}
|
||||
if (entity.getCoupon() == null) {
|
||||
entity.setCoupon(BigDecimal.ZERO);
|
||||
}
|
||||
if (entity.getSelfBonus() == null) {
|
||||
entity.setSelfBonus(BigDecimal.ZERO);
|
||||
}
|
||||
if (entity.getShareBonus() == null) {
|
||||
entity.setShareBonus(BigDecimal.ZERO);
|
||||
}
|
||||
entity.setCreatedAt(LocalDateTime.now());
|
||||
try {
|
||||
boolean ok = this.save(entity);
|
||||
saveResult.put("saved", ok);
|
||||
saveResult.put("saveMsg", ok ? "已新增" : "新增失败");
|
||||
if (ok) {
|
||||
saveResult.put("fan", entity);
|
||||
}
|
||||
} catch (DuplicateKeyException e) {
|
||||
log.warn("粉丝模拟登录入库重复键, idTenantId={}", entity.getIdTenantId());
|
||||
saveResult.put("saved", false);
|
||||
saveResult.put("saveMsg", "唯一ID已存在:" + entity.getIdTenantId());
|
||||
}
|
||||
return saveResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录用户保存成功后,分页调用第三方粉丝列表 API 并入库。
|
||||
*/
|
||||
private Map<String, Object> fetchAndSaveFansFromThirdParty(Map<String, Object> parentUserinfo,
|
||||
String tenantId) {
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
String token = parseString(parentUserinfo.get("token"));
|
||||
if (token == null) {
|
||||
result.put("fansFetchSuccess", false);
|
||||
result.put("fansFetchMsg", "userinfo.token 为空,无法拉取粉丝");
|
||||
result.put("fansSaved", 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
Optional<HxrFansApiContext> ctxOpt =
|
||||
lbThirdIntegrationConfigService.resolveFansApiContext(tenantId, token);
|
||||
if (ctxOpt.isEmpty()) {
|
||||
result.put("fansFetchSuccess", false);
|
||||
result.put("fansFetchMsg",
|
||||
"未找到粉丝 API 配置,或配置未启用、URL/凭证不完整(请检查 lb_third_integration_config)");
|
||||
result.put("fansSaved", 0);
|
||||
return result;
|
||||
}
|
||||
HxrFansApiContext ctx = ctxOpt.get();
|
||||
|
||||
Long parentId = parseLong(parentUserinfo.get("id"));
|
||||
String parentName = parseString(parentUserinfo.get("nickname"));
|
||||
String parentPhone = parseString(parentUserinfo.get("mobile"));
|
||||
|
||||
int page = 1;
|
||||
int totalSaved = 0;
|
||||
int totalFetched = 0;
|
||||
HxrLbFansPageData firstPageData = null;
|
||||
try {
|
||||
while (true) {
|
||||
Optional<HxrLbFansSelectResponse> opt =
|
||||
hxrAdminFansService.fetchFansPage(page, ctx);
|
||||
if (opt.isEmpty()) {
|
||||
if (page == 1) {
|
||||
result.put("fansFetchSuccess", false);
|
||||
result.put("fansFetchMsg",
|
||||
"未拉取到粉丝(请检查 lb_third_integration_config 中 token、appStr、URL 或网络)");
|
||||
result.put("fansSaved", 0);
|
||||
result.put("fansApiUrl", ctx.fansApiBaseUrl());
|
||||
return result;
|
||||
}
|
||||
result.put("fansFetchSuccess", false);
|
||||
result.put("fansFetchMsg", "第 " + page + " 页拉取失败,已成功保存前 "
|
||||
+ (page - 1) + " 页共 " + totalSaved + " 条粉丝");
|
||||
result.put("fansSaved", totalSaved);
|
||||
result.put("fansFetched", totalFetched);
|
||||
if (firstPageData != null) {
|
||||
result.put("lastPage", firstPageData.lastPage());
|
||||
}
|
||||
result.put("fansPages", page - 1);
|
||||
result.put("fansApiUrl", ctx.fansApiBaseUrl());
|
||||
return result;
|
||||
}
|
||||
|
||||
HxrLbFansSelectResponse body = opt.get();
|
||||
HxrLbFansPageData pageData = body.data();
|
||||
if (firstPageData == null && pageData != null) {
|
||||
firstPageData = pageData;
|
||||
}
|
||||
List<Map<String, Object>> rows = pageData != null ? pageData.list() : null;
|
||||
if (rows == null || rows.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
totalFetched += rows.size();
|
||||
|
||||
for (Map<String, Object> row : rows) {
|
||||
Map<String, Object> rowSave = saveFanFromShareRow(
|
||||
row, tenantId, parentId, parentName, parentPhone);
|
||||
if (Boolean.TRUE.equals(rowSave.get("saved"))) {
|
||||
totalSaved++;
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasMore = pageData != null && pageData.hasmore();
|
||||
int lastPage = pageData != null ? pageData.lastPage() : page;
|
||||
if (!hasMore || page >= lastPage) {
|
||||
break;
|
||||
}
|
||||
page++;
|
||||
}
|
||||
|
||||
result.put("fansFetchSuccess", true);
|
||||
result.put("fansFetchMsg", totalSaved == 0 ? "接口成功,无粉丝数据" : "粉丝拉取完成");
|
||||
result.put("fansSaved", totalSaved);
|
||||
result.put("fansFetched", totalFetched);
|
||||
result.put("lastPage", firstPageData != null ? firstPageData.lastPage() : page);
|
||||
result.put("fansPages", page);
|
||||
result.put("fansApiUrl", ctx.fansApiBaseUrl());
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.warn("拉取粉丝异常 tenantId={} parentId={}", tenantId, parentId, e);
|
||||
result.put("fansFetchSuccess", false);
|
||||
result.put("fansFetchMsg", "拉取粉丝异常:" + e.getMessage());
|
||||
result.put("fansSaved", totalSaved);
|
||||
result.put("fansFetched", totalFetched);
|
||||
if (firstPageData != null) {
|
||||
result.put("lastPage", firstPageData.lastPage());
|
||||
}
|
||||
result.put("fansPages", page > 1 ? page - 1 : 0);
|
||||
result.put("fansApiUrl", ctx.fansApiBaseUrl());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> saveFanFromShareRow(Map<String, Object> row,
|
||||
String tenantId,
|
||||
Long parentId,
|
||||
String parentName,
|
||||
String parentPhone) {
|
||||
Map<String, Object> saveResult = new LinkedHashMap<>();
|
||||
Long fanId = parseLong(row.get("id"));
|
||||
if (fanId == null) {
|
||||
saveResult.put("saved", false);
|
||||
saveResult.put("saveMsg", "粉丝 id 为空");
|
||||
return saveResult;
|
||||
}
|
||||
|
||||
LbFanManagement entity = new LbFanManagement();
|
||||
entity.setTenantId(tenantId);
|
||||
entity.setId(fanId);
|
||||
entity.setIdTenantId(buildIdTenantId(fanId, tenantId));
|
||||
entity.setAvatar(parseString(row.get("avatar")));
|
||||
entity.setNickname(parseString(row.get("nickname")));
|
||||
entity.setMobile(parseString(row.get("mobile")));
|
||||
entity.setPid(parentId);
|
||||
entity.setPName(parentName);
|
||||
entity.setPPhone(parentPhone);
|
||||
entity.setCoupon(parseDecimal(row.get("coupon")));
|
||||
entity.setSelfBonus(parseDecimal(row.get("self_bonus")));
|
||||
entity.setShareBonus(parseDecimal(row.get("share_bonus")));
|
||||
Integer shareNum = parseInteger(row.get("share_num"));
|
||||
if (shareNum != null) {
|
||||
entity.setShareNum(shareNum);
|
||||
}
|
||||
trimStringFields(entity);
|
||||
|
||||
LbFanManagement existing = this.getById(entity.getIdTenantId());
|
||||
if (existing != null) {
|
||||
entity.setCreatedAt(existing.getCreatedAt());
|
||||
if (entity.getShareNum() == null) {
|
||||
entity.setShareNum(existing.getShareNum());
|
||||
}
|
||||
if (entity.getCoupon() == null) {
|
||||
entity.setCoupon(existing.getCoupon());
|
||||
}
|
||||
if (entity.getSelfBonus() == null) {
|
||||
entity.setSelfBonus(existing.getSelfBonus());
|
||||
}
|
||||
if (entity.getShareBonus() == null) {
|
||||
entity.setShareBonus(existing.getShareBonus());
|
||||
}
|
||||
if (entity.getToken() == null) {
|
||||
entity.setToken(existing.getToken());
|
||||
}
|
||||
boolean ok = this.updateById(entity);
|
||||
saveResult.put("saved", ok);
|
||||
saveResult.put("saveMsg", ok ? "已更新" : "更新失败");
|
||||
return saveResult;
|
||||
}
|
||||
|
||||
if (entity.getShareNum() == null) {
|
||||
entity.setShareNum(0);
|
||||
}
|
||||
if (entity.getCoupon() == null) {
|
||||
entity.setCoupon(BigDecimal.ZERO);
|
||||
}
|
||||
if (entity.getSelfBonus() == null) {
|
||||
entity.setSelfBonus(BigDecimal.ZERO);
|
||||
}
|
||||
if (entity.getShareBonus() == null) {
|
||||
entity.setShareBonus(BigDecimal.ZERO);
|
||||
}
|
||||
entity.setCreatedAt(LocalDateTime.now());
|
||||
try {
|
||||
boolean ok = this.save(entity);
|
||||
saveResult.put("saved", ok);
|
||||
saveResult.put("saveMsg", ok ? "已新增" : "新增失败");
|
||||
} catch (DuplicateKeyException e) {
|
||||
log.warn("粉丝拉取入库重复键, idTenantId={}", entity.getIdTenantId());
|
||||
saveResult.put("saved", false);
|
||||
saveResult.put("saveMsg", "唯一ID已存在:" + entity.getIdTenantId());
|
||||
}
|
||||
return saveResult;
|
||||
}
|
||||
|
||||
private static Integer parseInteger(Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
if (value instanceof Number number) {
|
||||
return number.intValue();
|
||||
}
|
||||
String text = value.toString().trim();
|
||||
if (text.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(text);
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Long parseLong(Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
if (value instanceof Number number) {
|
||||
return number.longValue();
|
||||
}
|
||||
String text = value.toString().trim();
|
||||
if (text.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return Long.parseLong(text);
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String parseString(Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String text = value.toString().trim();
|
||||
return text.isEmpty() ? null : text;
|
||||
}
|
||||
|
||||
private static BigDecimal parseDecimal(Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
if (value instanceof BigDecimal decimal) {
|
||||
return decimal;
|
||||
}
|
||||
if (value instanceof Number number) {
|
||||
return BigDecimal.valueOf(number.doubleValue());
|
||||
}
|
||||
String text = value.toString().trim();
|
||||
if (text.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return new BigDecimal(text);
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import java.util.Optional;
|
||||
@RequiredArgsConstructor
|
||||
public class LbGoodsServiceImpl extends ServiceImpl<LbGoodsMapper, LbGoods> implements ILbGoodsService {
|
||||
|
||||
private static final BigDecimal RUSH_BUY_MIN_TOTAL_MONEY = new BigDecimal("26000");
|
||||
private static final BigDecimal RUSH_BUY_MIN_TOTAL_MONEY = new BigDecimal("25000");
|
||||
|
||||
private static final DateTimeFormatter DATETIME_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@@ -569,6 +569,7 @@ public class LbGoodsServiceImpl extends ServiceImpl<LbGoodsMapper, LbGoods> impl
|
||||
int attemptCount = 0;
|
||||
boolean stoppedByMax = false;
|
||||
boolean stoppedByMaxAttempts = false;
|
||||
boolean stoppedByDailyLimit = false;
|
||||
|
||||
for (LbGoods goods : goodsList) {
|
||||
if (successCount >= maxBuyCount) {
|
||||
@@ -605,19 +606,35 @@ public class LbGoodsServiceImpl extends ServiceImpl<LbGoodsMapper, LbGoods> impl
|
||||
successCount++;
|
||||
} else {
|
||||
failCount++;
|
||||
if (buyResult.dailyLimitExceeded()) {
|
||||
stoppedByDailyLimit = true;
|
||||
if (accountTag.isEmpty()) {
|
||||
log.info("当日可抢订单数已满,停止继续抢购");
|
||||
} else {
|
||||
log.info("{} 当日可抢订单数已满,停止继续抢购", accountTag);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.put("success", successCount > 0);
|
||||
result.put("message", successCount > 0
|
||||
? "抢购完成,成功 " + successCount + " 笔,失败 " + failCount + " 笔"
|
||||
: "抢购未成功");
|
||||
if (stoppedByDailyLimit) {
|
||||
result.put("message", successCount > 0
|
||||
? "当日可抢订单数已满,已停止抢购;成功 " + successCount + " 笔,失败 " + failCount + " 笔"
|
||||
: HxrAdminBuyService.MSG_DAILY_LIMIT_EXCEEDED);
|
||||
} else {
|
||||
result.put("message", successCount > 0
|
||||
? "抢购完成,成功 " + successCount + " 笔,失败 " + failCount + " 笔"
|
||||
: "抢购未成功");
|
||||
}
|
||||
result.put("successCount", successCount);
|
||||
result.put("failCount", failCount);
|
||||
result.put("attemptCount", attemptCount);
|
||||
result.put("maxAttempts", maxAttempts);
|
||||
result.put("stoppedByMax", stoppedByMax);
|
||||
result.put("stoppedByMaxAttempts", stoppedByMaxAttempts);
|
||||
result.put("stoppedByDailyLimit", stoppedByDailyLimit);
|
||||
result.put("details", details);
|
||||
if (accountTag.isEmpty()) {
|
||||
log.info("抢购结束,success={},message={}", successCount > 0, result.get("message"));
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.rj.common.LbThirdIntegrationConstants;
|
||||
import com.rj.dto.LbThirdIntegrationCredentialUpdateRequest;
|
||||
import com.rj.dto.hxr.HxrAdminOrderApiContext;
|
||||
import com.rj.dto.hxr.HxrAdminUserApiContext;
|
||||
import com.rj.dto.hxr.HxrFansApiContext;
|
||||
import com.rj.dto.hxr.HxrGoodsApiContext;
|
||||
import com.rj.dto.hxr.HxrUserLoginApiContext;
|
||||
import com.rj.entity.LbThirdIntegrationConfig;
|
||||
@@ -397,6 +398,37 @@ public class LbThirdIntegrationConfigServiceImpl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<HxrFansApiContext> resolveFansApiContext(String tenantId, String token) {
|
||||
if (!StringUtils.hasText(tenantId) || !StringUtils.hasText(token)) {
|
||||
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 appStr = config.getGoodsApiAppStr();
|
||||
if (!StringUtils.hasText(appStr)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
try {
|
||||
return Optional.of(new HxrFansApiContext(
|
||||
LbThirdIntegrationConfigUtil.resolveFansApiBaseUrl(config),
|
||||
LbThirdIntegrationConfigUtil.resolveFansPageLimit(config),
|
||||
LbThirdIntegrationConfigUtil.resolveGoodsApiOrigin(config),
|
||||
LbThirdIntegrationConfigUtil.resolveGoodsApiReferer(config),
|
||||
token.trim(),
|
||||
appStr.trim()));
|
||||
} catch (IllegalStateException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<HxrAdminOrderApiContext> resolveAdminOrderApiContext(String tenantId) {
|
||||
if (!StringUtils.hasText(tenantId)) {
|
||||
|
||||
@@ -13,6 +13,9 @@ CREATE TABLE `lb_fan_management` (
|
||||
`pid` BIGINT NULL DEFAULT NULL COMMENT '父ID',
|
||||
`p_phone` VARCHAR(32) NULL DEFAULT NULL COMMENT '父手机号',
|
||||
`token` VARCHAR(512) NULL DEFAULT NULL COMMENT '登录 token',
|
||||
`coupon` DECIMAL(12,3) NOT NULL DEFAULT 0.000 COMMENT '优惠券金额',
|
||||
`self_bonus` DECIMAL(12,3) NOT NULL DEFAULT 0.000 COMMENT '自购奖金',
|
||||
`share_bonus` DECIMAL(12,3) NOT NULL DEFAULT 0.000 COMMENT '分享奖金',
|
||||
`created_at` DATETIME NULL DEFAULT NULL COMMENT '创建时间',
|
||||
`share_num` INT NOT NULL DEFAULT 0 COMMENT '分享次数',
|
||||
PRIMARY KEY (`id_tenant_id`) USING BTREE,
|
||||
|
||||
Reference in New Issue
Block a user