Merge branch 'test' into prod
# Conflicts: # cash-api/account-server/src/main/java/com/czg/controller/admin/AuthorizationController.java # cash-api/order-server/src/main/java/com/czg/controller/DistributionPayController.java # cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderInfoCustomServiceImpl.java # cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PayServiceImpl.java
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package com.czg.service.account.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.czg.account.entity.QuickMenu;
|
||||
|
||||
/**
|
||||
* 悬浮窗配置 映射层。
|
||||
*
|
||||
* @author ww
|
||||
* @since 2025-12-29
|
||||
*/
|
||||
public interface QuickMenuMapper extends BaseMapper<QuickMenu> {
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.czg.service.account.mapper;
|
||||
|
||||
import com.czg.account.entity.ShopMerchant;
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
|
||||
/**
|
||||
* 第三方商户进件 映射层。
|
||||
*
|
||||
* @author Administrator
|
||||
* @since 2025-02-11
|
||||
*/
|
||||
public interface ShopMerchantMapper extends BaseMapper<ShopMerchant> {
|
||||
|
||||
}
|
||||
@@ -14,9 +14,9 @@ import com.czg.config.RedisCst;
|
||||
import com.czg.constants.ParamCodeCst;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.service.RedisService;
|
||||
import com.czg.service.account.mapper.CallQueueMapper;
|
||||
import com.czg.service.account.mapper.CallTableMapper;
|
||||
import com.czg.service.account.util.FunUtil;
|
||||
import com.czg.service.account.util.WechatMiniMsgUtil;
|
||||
import com.czg.system.dto.SysParamsDTO;
|
||||
import com.czg.system.service.SysParamsService;
|
||||
@@ -29,6 +29,7 @@ import jakarta.annotation.Resource;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.*;
|
||||
@@ -41,7 +42,7 @@ import java.util.stream.Collectors;
|
||||
* @author zs
|
||||
* @since 2025-02-21
|
||||
*/
|
||||
@DubboService
|
||||
@Service
|
||||
public class CallTableServiceImpl extends ServiceImpl<CallTableMapper, CallTable> implements CallTableService {
|
||||
@DubboReference
|
||||
private SysParamsService sysParamsService;
|
||||
@@ -51,10 +52,10 @@ public class CallTableServiceImpl extends ServiceImpl<CallTableMapper, CallTable
|
||||
@Resource
|
||||
private ShopUserService shopUserService;
|
||||
@Resource
|
||||
private FunUtil funUtil;
|
||||
@Resource
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
@Resource
|
||||
private RedisService redisService;
|
||||
@Resource
|
||||
private ShopInfoService shopInfoService;
|
||||
@Resource
|
||||
private CallConfigService callConfigService;
|
||||
@@ -228,13 +229,13 @@ public class CallTableServiceImpl extends ServiceImpl<CallTableMapper, CallTable
|
||||
}
|
||||
|
||||
private String getCallNumber(Long shopId, CallTable callTable) {
|
||||
return funUtil.runFunAndCheckKey(() -> {
|
||||
return redisService.runFunAndCheckKey(() -> {
|
||||
String callNumKey = RedisCst.getTableCallNumKey(shopId, callTable.getId());
|
||||
String value = stringRedisTemplate.opsForValue().get(callNumKey);
|
||||
AtomicReference<String> newVal = new AtomicReference<>("");
|
||||
// 初始化
|
||||
if (StrUtil.isBlank(value)) {
|
||||
Boolean setFlag = FunUtil.runFunAndRetry(() -> stringRedisTemplate.opsForValue().setIfAbsent(callNumKey, callTable.getStart().toString()), flag -> !flag,
|
||||
Boolean setFlag = RedisService.runFunAndRetry(() -> stringRedisTemplate.opsForValue().setIfAbsent(callNumKey, callTable.getStart().toString()), flag -> !flag,
|
||||
_ -> newVal.set(stringRedisTemplate.opsForValue().get(callNumKey)));
|
||||
|
||||
if (setFlag) {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.czg.service.account.service.impl;
|
||||
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import com.czg.account.entity.QuickMenu;
|
||||
import com.czg.account.service.QuickMenuService;
|
||||
import com.czg.service.account.mapper.QuickMenuMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 悬浮窗配置 服务层实现。
|
||||
*
|
||||
* @author ww
|
||||
* @since 2025-12-29
|
||||
*/
|
||||
@Service
|
||||
public class QuickMenuServiceImpl extends ServiceImpl<QuickMenuMapper, QuickMenu> implements QuickMenuService{
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package com.czg.service.account.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.czg.account.dto.merchant.ShopMerchantEditDTO;
|
||||
import com.czg.account.entity.ShopMerchant;
|
||||
import com.czg.account.service.ShopMerchantService;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.account.mapper.ShopMerchantMapper;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 第三方商户进件 服务层实现。
|
||||
*
|
||||
* @author Administrator
|
||||
* @since 2025-02-11
|
||||
*/
|
||||
@CacheConfig(cacheNames = "shop:merchant")
|
||||
@DubboService
|
||||
public class ShopMerchantServiceImpl extends ServiceImpl<ShopMerchantMapper, ShopMerchant> implements ShopMerchantService {
|
||||
|
||||
@Override
|
||||
public ShopMerchant detail(Integer shopId) {
|
||||
ShopMerchant one = queryChain().eq(ShopMerchant::getShopId, shopId).one();
|
||||
return one == null ? new ShopMerchant() : one;
|
||||
}
|
||||
|
||||
@CacheEvict(key = "#shopMerchantEditDTO.shopId")
|
||||
@Override
|
||||
public Boolean edit(ShopMerchantEditDTO shopMerchantEditDTO) {
|
||||
ShopMerchant shopMerchant = queryChain().eq(ShopMerchant::getShopId, shopMerchantEditDTO.getShopId()).one();
|
||||
if (shopMerchant == null) {
|
||||
shopMerchant = new ShopMerchant();
|
||||
shopMerchant.setShopId(shopMerchantEditDTO.getShopId());
|
||||
BeanUtil.copyProperties(shopMerchantEditDTO, shopMerchant);
|
||||
return save(shopMerchant);
|
||||
}
|
||||
BeanUtil.copyProperties(shopMerchantEditDTO, shopMerchant);
|
||||
return updateById(shopMerchant);
|
||||
}
|
||||
|
||||
@Cacheable(key = "#id")
|
||||
@Override
|
||||
public ShopMerchant getById(Serializable id) {
|
||||
ShopMerchant shopMerchant = getMapper().selectOneById(id);
|
||||
AssertUtil.isNull(shopMerchant, "暂未开通支付");
|
||||
return shopMerchant;
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import com.czg.market.vo.InviteUserVO;
|
||||
import com.czg.market.vo.MemberConfigVO;
|
||||
import com.czg.order.entity.OrderInfo;
|
||||
import com.czg.service.account.mapper.ShopUserMapper;
|
||||
import com.czg.service.account.util.FunUtil;
|
||||
import com.czg.utils.FunUtils;
|
||||
import com.czg.utils.PageUtil;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
package com.czg.service.account.util;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @author Administrator
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class FunUtil {
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
public static int retryCount = 5;
|
||||
|
||||
/**
|
||||
* 执行任务并保证锁唯一
|
||||
* @param supplier 业务逻辑
|
||||
* @param lockKey Redis锁的Key
|
||||
* @return 业务逻辑返回值
|
||||
*/
|
||||
public <T> T runFunAndCheckKey(Supplier<T> supplier, String lockKey) {
|
||||
String lockValue = String.valueOf(System.nanoTime() + Thread.currentThread().threadId());
|
||||
try {
|
||||
// 尝试获取锁,超时时间 5 秒,防止死锁
|
||||
boolean lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 5, TimeUnit.SECONDS));
|
||||
int count = 0;
|
||||
// 初始等待 10ms
|
||||
int retryDelay = 10;
|
||||
|
||||
while (!lock) {
|
||||
// 最多重试 10 次,大约 10 秒
|
||||
if (count++ > 50) {
|
||||
throw new RuntimeException("系统繁忙, 稍后再试");
|
||||
}
|
||||
Thread.sleep(retryDelay);
|
||||
// 指数退避,最大等待 200ms
|
||||
retryDelay = Math.min(retryDelay * 2, 200);
|
||||
lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 5, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
// 执行任务
|
||||
return supplier.get();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException("线程被中断", e);
|
||||
} catch (Exception e) {
|
||||
log.error("执行出错:{}", e.getMessage(), e);
|
||||
throw e;
|
||||
} finally {
|
||||
// 释放锁(使用 Lua 脚本确保原子性)
|
||||
unlock(lockKey, lockValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 Lua 脚本确保释放锁的原子性
|
||||
* @param lockKey 锁的 Key
|
||||
* @param lockValue 当前线程的锁值
|
||||
*/
|
||||
private void unlock(String lockKey, String lockValue) {
|
||||
String luaScript =
|
||||
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
|
||||
"return redis.call('del', KEYS[1]) " +
|
||||
"else return 0 end";
|
||||
redisTemplate.execute(new DefaultRedisScript<>(luaScript, Long.class),
|
||||
Collections.singletonList(lockKey), lockValue);
|
||||
}
|
||||
|
||||
public static <T, R> R runFunAndRetry(
|
||||
Supplier<R> function,
|
||||
Function<R, Boolean> check, Consumer<R> errFun) {
|
||||
log.info("工具类开始执行函数");
|
||||
R result = function.get();
|
||||
boolean flag = check.apply(result);
|
||||
|
||||
log.info("执行结果: {}", result);
|
||||
|
||||
while (flag && retryCount-- > 0) {
|
||||
log.info("执行函数失败, 剩余尝试次数{}", retryCount);
|
||||
result = function.get();
|
||||
log.info("执行结果: {}", result);
|
||||
flag = check.apply(result);
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
errFun.accept(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,6 @@
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.czg.service.account.mapper.ShopMerchantMapper">
|
||||
<mapper namespace="com.czg.service.account.mapper.QuickMenuMapper">
|
||||
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user