Compare commits
44 Commits
633c0919eb
...
87dd4cc3ba
| Author | SHA1 | Date | |
|---|---|---|---|
| 87dd4cc3ba | |||
| 5df01f5192 | |||
| 3b83d210dc | |||
| d70546f55e | |||
| c6102dd4b4 | |||
|
|
f374c335c4 | ||
| b171b1a81f | |||
| 0b5ec53187 | |||
| ec59490f3a | |||
| 7d434ff5c7 | |||
| ef48e4e51d | |||
| 5cb895ac19 | |||
| e125eed517 | |||
|
|
621bf2401d | ||
| bae1762dba | |||
|
|
22a5ae8f68 | ||
|
|
ae65bf1814 | ||
|
|
b1215acca5 | ||
|
|
a6dd4f4611 | ||
| 506e74747a | |||
| 72c9379e87 | |||
| 441ede37cf | |||
| b359b08713 | |||
| 821b83f7c6 | |||
| a8bcf991fe | |||
| 240d672211 | |||
|
|
302504b891 | ||
|
|
a76c3f75a4 | ||
| a05d8083bc | |||
| ed1b6b2ecf | |||
| 7c9c6d6a02 | |||
|
|
658c7f14b2 | ||
| 8635c42506 | |||
|
|
f318c18606 | ||
|
|
2be24abced | ||
|
|
ee6df9ad1c | ||
|
|
81e102ff41 | ||
| 2f4226b3c8 | |||
| 56ab4d0403 | |||
| 7af2f8f925 | |||
| 5938520ddf | |||
| f88612d115 | |||
| ebe2da9163 | |||
| 0dbda61bac |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -61,3 +61,4 @@ build/
|
||||
/cash-api/product-server/src/main/resources/application-zs.yml
|
||||
/cash-api/system-server/src/main/resources/application-zs.yml
|
||||
/cash-service/code-generator/src/main/java/com/czg/Main.java
|
||||
/cash-api/product-server/logs/
|
||||
|
||||
@@ -147,32 +147,4 @@ public class NotifyController {
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
String str = "<xml><ToUserName><![CDATA[gh_11fc27b7ef34]]></ToUserName><FromUserName><![CDATA[owWHW7Tzeh2gx3WmFsFSxBq2JUTk]]></FromUserName><CreateTime>1761095747</CreateTime><MsgType><![CDATA[event]]></MsgType><Event><![CDATA[subscribe]]></Event><EventKey><![CDATA[qrscene_275]]></EventKey><Ticket><![CDATA[gQGF8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyUTZDVHRTMXhmbUoxYUlYdk5GY2sAAgSsLvhoAwQAjScA]]></Ticket></xml>";
|
||||
// 2. 解析 XML 为 Map(便于获取字段)
|
||||
Map<String, String> messageMap = new HashMap<>();
|
||||
try {
|
||||
messageMap = parseXmlToMap(str);
|
||||
} catch (DocumentException e) {
|
||||
log.error("XML 解析失败,", e);
|
||||
}
|
||||
log.info("微信 POST 消息内容: {}", messageMap);
|
||||
//携带参数
|
||||
String eventKey = messageMap.get("EventKey");
|
||||
Long userId = null;
|
||||
if (eventKey != null && eventKey.startsWith("qrscene_")) {
|
||||
try {
|
||||
// 截取 "qrscene_" 前缀后的字符串(长度为 8),并转为 Long
|
||||
String numberStr = eventKey.substring("qrscene_".length());
|
||||
userId = Long.parseLong(numberStr);
|
||||
} catch (NumberFormatException e) {
|
||||
log.error("EventKey 后缀不是有效数字,eventKey: {}", eventKey, e);
|
||||
}
|
||||
}
|
||||
System.out.println("userId: " + userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
* @author GYJoker
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/test")
|
||||
@RequestMapping("/notify/test")
|
||||
public class TestController {
|
||||
@Resource
|
||||
private ShopUserFlowService shopUserFlowService;
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* 会员配置管理
|
||||
* @author ww
|
||||
*/
|
||||
|
||||
@RestController
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.czg.annotation.SaAdminCheckPermission;
|
||||
import com.czg.market.dto.MkPointsConfigDTO;
|
||||
import com.czg.market.dto.MkPointsUserDTO;
|
||||
import com.czg.market.entity.MkPointsConfig;
|
||||
import com.czg.market.entity.MkPointsUser;
|
||||
import com.czg.market.entity.MkPointsUserRecord;
|
||||
import com.czg.market.service.MkPointsConfigService;
|
||||
import com.czg.market.service.MkPointsUserRecordService;
|
||||
@@ -12,15 +13,16 @@ import com.czg.market.service.MkPointsUserService;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.utils.CzgStrUtils;
|
||||
import com.czg.validator.ValidatorUtil;
|
||||
import com.czg.validator.group.DefaultGroup;
|
||||
import com.czg.validator.group.InsertGroup;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 积分配置
|
||||
@@ -88,4 +90,23 @@ public class PointsConfigController {
|
||||
@RequestParam(required = false) Long id) {
|
||||
return CzgResult.success(userRecordService.pageByPointsUserId(page, size, id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户积分 包括配置信息
|
||||
* {
|
||||
* "pointsConfig": 配置信息,
|
||||
* "pointsUser": 用户积分信息
|
||||
* }
|
||||
*/
|
||||
@GetMapping("userPoints")
|
||||
public CzgResult<Map<String, Object>> userPoints(@RequestParam(required = false) Long shopUserId) {
|
||||
Long shopId = StpKit.USER.getShopId();
|
||||
Map<String, Object> result = new HashMap<>(2);
|
||||
MkPointsConfig pointsConfig = pointsConfigService.getById(shopId);
|
||||
MkPointsUser pointsUser = pointsUserService.getOne(QueryWrapper.create().eq(MkPointsUser::getShopId, shopId).eq(MkPointsUser::getShopUserId, shopUserId));
|
||||
result.put("pointsConfig", pointsConfig == null ? "" : pointsConfig);
|
||||
result.put("pointsUser", pointsUser == null ? "" : pointsUser);
|
||||
return CzgResult.success(result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -89,6 +89,14 @@ public class PpPackageController {
|
||||
return CzgResult.success(ppPackageService.getPackagePage(reqVo, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取套餐详情
|
||||
*/
|
||||
@GetMapping("/detail/{id}")
|
||||
public CzgResult<PpPackageVO> getPackageDetail(@PathVariable Long id, Long shopId) {
|
||||
return CzgResult.success(ppPackageService.getPackageDetail(id, shopId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取套餐推广开关
|
||||
* 0: 关闭 1: 开启
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.czg.controller.admin;
|
||||
|
||||
import com.czg.market.dto.MkShopRechargeDTO;
|
||||
import com.czg.market.entity.MkShopConsumeDiscountRecord;
|
||||
import com.czg.market.entity.MkShopRechargeFlow;
|
||||
import com.czg.market.service.MkRechargeFlowService;
|
||||
import com.czg.market.service.MkShopConsumeDiscountRecordService;
|
||||
@@ -30,12 +29,6 @@ public class ShopRechargeController {
|
||||
@Resource
|
||||
private MkShopConsumeDiscountRecordService shopConsumeDiscountRecordService;
|
||||
|
||||
@GetMapping("/test")
|
||||
public CzgResult<MkShopConsumeDiscountRecord> get(@RequestParam Long shopId) {
|
||||
// return CzgResult.success(shopConsumeDiscountRecordService.get(shopId));
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置信息获取
|
||||
* 权限标识: activate:list
|
||||
|
||||
@@ -60,10 +60,10 @@ public class UPointsController {
|
||||
Long shopId = StpKit.USER.getShopId();
|
||||
Map<String, Object> result = new HashMap<>(2);
|
||||
MkPointsConfig pointsConfig = pointsConfigService.getById(shopId);
|
||||
MkPointsUser pointsUser = pointsUserService.getOne(QueryWrapper.create().eq(MkPointsUser::getShopId, shopId).eq(MkPointsUser::getUserId, shopUserId));
|
||||
MkPointsUser pointsUser = pointsUserService.getOne(QueryWrapper.create().eq(MkPointsUser::getShopId, shopId).eq(MkPointsUser::getShopUserId, shopUserId));
|
||||
result.put("pointsConfig", pointsConfig == null ? "" : pointsConfig);
|
||||
result.put("pointsUser", pointsUser == null ? "" : pointsUser);
|
||||
return CzgResult.success();
|
||||
return CzgResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,8 +4,7 @@ import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.CzgPayUtils;
|
||||
import com.czg.account.entity.ShopUser;
|
||||
import com.czg.account.service.ShopUserService;
|
||||
import com.czg.constants.PayTypeConstants;
|
||||
import com.czg.entity.CzgBaseRespParams;
|
||||
import com.czg.market.entity.MkShopConsumeDiscountRecord;
|
||||
import com.czg.market.service.MkDistributionUserService;
|
||||
@@ -13,7 +12,6 @@ import com.czg.market.service.MkShopConsumeDiscountRecordService;
|
||||
import com.czg.market.service.OrderInfoService;
|
||||
import com.czg.order.entity.OrderInfo;
|
||||
import com.czg.order.entity.OrderPayment;
|
||||
import com.czg.constants.PayTypeConstants;
|
||||
import com.czg.order.service.OrderInfoCustomService;
|
||||
import com.czg.order.service.OrderPaymentService;
|
||||
import com.czg.service.market.service.impl.AppWxServiceImpl;
|
||||
@@ -39,10 +37,6 @@ import java.io.IOException;
|
||||
@RequestMapping("/notify")
|
||||
public class NotifyController {
|
||||
private static final String SUCCESS = "SUCCESS";
|
||||
|
||||
@Resource
|
||||
private ShopUserService shopUserService;
|
||||
|
||||
@Resource
|
||||
private OrderInfoCustomService orderInfoCustomService;
|
||||
@Resource
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.czg.market.service.GbWareService;
|
||||
import com.czg.order.dto.GbOrderQueryParam;
|
||||
import com.czg.order.service.GbOrderService;
|
||||
import com.czg.order.vo.GbOrderCountVO;
|
||||
import com.czg.order.vo.GbWareVO;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.utils.AssertUtil;
|
||||
@@ -87,4 +88,12 @@ public class GbWareController {
|
||||
AssertUtil.isNull(id, "操作失败,请选择商品");
|
||||
return CzgResult.success(wareService.deleteGbWare(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团商品详情
|
||||
*/
|
||||
@GetMapping("/ware/detail")
|
||||
public CzgResult<GbWareVO> getWareDetail(@RequestParam Long shopId, @RequestParam Long wareId) {
|
||||
return CzgResult.success(gbOrderService.getWareDetail(shopId, wareId, null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import cn.hutool.core.util.URLUtil;
|
||||
import com.czg.log.annotation.OperationLog;
|
||||
import com.czg.product.dto.ConsStockFlowDTO;
|
||||
import com.czg.product.dto.OcrDTO;
|
||||
import com.czg.product.entity.MkOcrService;
|
||||
import com.czg.product.param.ConsCheckStockParam;
|
||||
import com.czg.product.param.ConsInOutStockHeadParam;
|
||||
import com.czg.product.param.ConsReportDamageParam;
|
||||
@@ -37,6 +38,8 @@ public class ConsStockFlowController {
|
||||
|
||||
@Resource
|
||||
private ConsStockFlowService consStockFlowService;
|
||||
@Resource
|
||||
private MkOcrService ocrService;
|
||||
|
||||
/**
|
||||
* 入库单识别
|
||||
@@ -46,17 +49,18 @@ public class ConsStockFlowController {
|
||||
URI uri = new URI(ocrDTO.getUrl());
|
||||
URL url = uri.toURL();
|
||||
InputStream stream = URLUtil.getStream(url);
|
||||
return CzgResult.success(consStockFlowService.ocr(FileUtil.getName(ocrDTO.getUrl()), stream));
|
||||
return CzgResult.success(ocrService.ocr(FileUtil.getName(ocrDTO.getUrl()), stream, "cons"));
|
||||
}
|
||||
|
||||
/**
|
||||
* ocr识别结果
|
||||
*
|
||||
* @param id ocrId
|
||||
* @return 识别结果
|
||||
*/
|
||||
@GetMapping("/ocrResult")
|
||||
public CzgResult<ConsInOutStockHeadParam> ocrResult(@RequestParam Long id) {
|
||||
return CzgResult.success(consStockFlowService.ocrDetail(id));
|
||||
return CzgResult.success(ocrService.ocrDetail(id));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 商品管理 - 商品列表
|
||||
* 管理端/商品管理 - 商品列表
|
||||
*
|
||||
* @author Tankaikai tankaikai@aliyun.com
|
||||
* @since 1.0 2025-02-16
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.czg.controller.admin;
|
||||
|
||||
import com.czg.product.service.MkOcrCountStickService;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
/**
|
||||
* 拍照数签子
|
||||
* @author ww
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/admin/stick")
|
||||
public class StickCountController {
|
||||
|
||||
@Resource
|
||||
private MkOcrCountStickService stickCountService;
|
||||
|
||||
/**
|
||||
* 文件上传并返回点数统计结果
|
||||
*
|
||||
* @param file 上传的图片文件
|
||||
* @return 点数统计结果
|
||||
*/
|
||||
@PostMapping("/count")
|
||||
public CzgResult<Integer> uploadAndCount(MultipartFile file) throws IOException {
|
||||
AssertUtil.isNull(file, "上传文件不能为空");
|
||||
// 9. 返回成功结果
|
||||
return CzgResult.success(stickCountService.getCountStick(file.getBytes(), file.getOriginalFilename()));
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import com.czg.product.vo.ShopProductSkuInfoVo;
|
||||
import com.czg.product.vo.ShopProductVo;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.RedisService;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import com.czg.validator.ValidatorUtil;
|
||||
import com.czg.validator.group.DefaultGroup;
|
||||
@@ -24,7 +23,7 @@ import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 店铺商品
|
||||
* 用户端/店铺商品
|
||||
*
|
||||
* @author Tankaikai tankaikai@aliyun.com
|
||||
* @since 1.0 2025-02-16
|
||||
@@ -34,7 +33,6 @@ import java.util.Map;
|
||||
@RequestMapping("/user/product")
|
||||
public class UProductController {
|
||||
private final UProductService uProductService;
|
||||
private final RedisService redisService;
|
||||
|
||||
/**
|
||||
* 小程序点餐-热销商品列表
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.czg.service;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.product.dto.ProductDTO;
|
||||
import com.czg.product.service.ProductService;
|
||||
import com.czg.product.service.UProductService;
|
||||
import com.czg.product.vo.ShopGroupProductVo;
|
||||
import com.czg.product.vo.ShopProductVo;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yjjie
|
||||
* @date 2025/12/24 13:36
|
||||
*/
|
||||
@SpringBootTest
|
||||
public class ProductTest {
|
||||
|
||||
@Resource
|
||||
private ProductService productService;
|
||||
|
||||
@Resource
|
||||
private UProductService uProductService;
|
||||
|
||||
@Test
|
||||
public void testGetById() {
|
||||
// ProductDTO product = productService.getProductById(169L);
|
||||
// System.out.println(JSONObject.toJSONString( product));
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,8 @@ import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author GYJoker
|
||||
@@ -94,18 +96,19 @@ public class VersionController {
|
||||
@GetMapping(value = "/getCredentials")
|
||||
public CzgResult<Object> getCredentials() {
|
||||
try {
|
||||
Map<String, String> ossKeyMap = paramsService.getParamsByMap("ossKeySet", ParamCodeCst.OSS_KEY_SET);
|
||||
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
|
||||
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
|
||||
.setAccessKeyId(paramsService.getSysParamValue(ParamCodeCst.AliYun.ALI_OSS_ACCESS_KEY))
|
||||
.setAccessKeyId(ossKeyMap.get(ParamCodeCst.AliYun.ALI_OSS_ACCESS_KEY))
|
||||
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
|
||||
.setAccessKeySecret(paramsService.getSysParamValue(ParamCodeCst.AliYun.ALI_OSS_ACCESS_SECRET));
|
||||
.setAccessKeySecret(ossKeyMap.get(ParamCodeCst.AliYun.ALI_OSS_ACCESS_SECRET));
|
||||
|
||||
// Endpoint 请参考 https://api.aliyun.com/product/Sts
|
||||
config.endpoint = paramsService.getSysParamValue(ParamCodeCst.AliYun.ALI_OSS_ENDPOINT);
|
||||
config.endpoint = ossKeyMap.get(ParamCodeCst.AliYun.ALI_OSS_ENDPOINT);
|
||||
|
||||
com.aliyun.sts20150401.Client client = new com.aliyun.sts20150401.Client(config);
|
||||
com.aliyun.sts20150401.models.AssumeRoleRequest assumeRoleRequest = new com.aliyun.sts20150401.models.AssumeRoleRequest();
|
||||
assumeRoleRequest.setRoleArn(paramsService.getSysParamValue(ParamCodeCst.AliYun.ALI_OSS_ROLE_ARN));
|
||||
assumeRoleRequest.setRoleArn(ossKeyMap.get(ParamCodeCst.AliYun.ALI_OSS_ROLE_ARN));
|
||||
assumeRoleRequest.setRoleSessionName("test");
|
||||
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
|
||||
// 复制代码运行请自行打印 API 的返回值
|
||||
|
||||
@@ -26,6 +26,7 @@ public class FilteredNacosRegistry extends NacosRegistry {
|
||||
"removeByMap",
|
||||
"getByIdOpt",
|
||||
"getOneOpt",
|
||||
"getOneAs",
|
||||
"getObjOpt",
|
||||
"getObjAs",
|
||||
"getObjAsOpt",
|
||||
|
||||
@@ -86,7 +86,6 @@ public class CzgControllerAdvice {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 处理自定义异常
|
||||
*/
|
||||
@@ -164,9 +163,20 @@ public class CzgControllerAdvice {
|
||||
@ExceptionHandler(value = Exception.class)
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public CzgResult<Object> errorHandler(Exception ex) {
|
||||
// setErrorLog(ex);
|
||||
// 3. 处理未捕获的异常(系统异常,隐藏敏感信息)
|
||||
log.error("系统未处理异常", ex);
|
||||
Throwable rootCause = ex;
|
||||
while (rootCause.getCause() != null && !(rootCause instanceof CzgException)) {
|
||||
rootCause = rootCause.getCause();
|
||||
}
|
||||
|
||||
// 2. 如果根因是CzgException,直接抛出/返回该异常
|
||||
if (rootCause instanceof CzgException exception) {
|
||||
return CzgResult.failure(exception.getCode(), exception.getMsg());
|
||||
}else if (rootCause instanceof ValidateException exception) {
|
||||
return CzgResult.failure(exception.getStatus(), exception.getMessage());
|
||||
}
|
||||
|
||||
// 3. 非业务异常,按原有逻辑处理
|
||||
return CzgResult.failure(CzgRespCode.SYSTEM_ERROR.getCode(), "系统错误,请联系管理员");
|
||||
}
|
||||
|
||||
|
||||
@@ -133,6 +133,7 @@ public class RabbitPublisher {
|
||||
|
||||
/**
|
||||
* 订单商品状态消息
|
||||
* type bc 广播
|
||||
*/
|
||||
public void sendOrderDetailStatusMsg(String shopId, String type) {
|
||||
sendMsg(RabbitConstants.Queue.ORDER_DETAIL_STATUS_QUEUE, JSONObject.toJSONString(Map.of(
|
||||
|
||||
@@ -280,5 +280,9 @@ public class ShopInfoEditDTO {
|
||||
* 上菜时间 分钟
|
||||
*/
|
||||
private Integer serveTime;
|
||||
/**
|
||||
* 数签子
|
||||
*/
|
||||
private Integer isCountStick;
|
||||
|
||||
}
|
||||
|
||||
@@ -27,5 +27,6 @@ public class ShopUserDTO extends ShopUser {
|
||||
private String memberLevelName;
|
||||
private String nextMemberLevelName;
|
||||
private Long nextExperience;
|
||||
private Long pointBalance;
|
||||
private boolean isNew;
|
||||
}
|
||||
|
||||
@@ -127,6 +127,10 @@ public class ShopConfig implements Serializable {
|
||||
* 套餐推广 开关
|
||||
*/
|
||||
private Integer isPackagePromotion;
|
||||
/**
|
||||
* 数签子
|
||||
*/
|
||||
private Integer isCountStick;
|
||||
|
||||
|
||||
private String dingAppKey;
|
||||
|
||||
@@ -352,6 +352,11 @@ public class ShopInfo implements Serializable {
|
||||
private Integer serveTime;
|
||||
@Column(ignore = true)
|
||||
private Integer isGroupBuy;
|
||||
/**
|
||||
* 数签子
|
||||
*/
|
||||
@Column(ignore = true)
|
||||
private Integer isCountStick;
|
||||
|
||||
/**
|
||||
* 运营端余额
|
||||
|
||||
@@ -11,5 +11,5 @@ public class PointsShopListVO {
|
||||
private String logo;
|
||||
private String coverImg;
|
||||
private Long shopId;
|
||||
private Integer accountPoints;
|
||||
private Integer pointBalance;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.czg.constants;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 系统参数编码常量类
|
||||
*
|
||||
@@ -9,6 +11,65 @@ package com.czg.constants;
|
||||
*/
|
||||
public interface ParamCodeCst {
|
||||
|
||||
/**
|
||||
* 用户小程序参数
|
||||
*/
|
||||
Set<String> USER_MINI_KEY_SET = Set.of(Wechat.Mini.USER_WX_APP_ID, Wechat.Mini.USER_WX_SECRETE);
|
||||
|
||||
/**
|
||||
* 商家小程序参数
|
||||
*/
|
||||
Set<String> SHOP_MINI_KEY_SET = Set.of(Wechat.Mini.SHOP_WX_APP_ID, Wechat.Mini.SHOP_WX_SECRETE);
|
||||
|
||||
/**
|
||||
* 商家公众号参数 推送 库存不足等消息
|
||||
*/
|
||||
Set<String> SHOP_AC_KEY_SET = Set.of(Wechat.Ac.SHOP_WX_AC_APP_ID, Wechat.Ac.SHOP_WX_AC_SECRETE);
|
||||
/**
|
||||
* 用户公众号参数 推送商家模板消息
|
||||
*/
|
||||
Set<String> USER_AC_KEY_SET = Set.of(Wechat.Ac.USER_WX_AC_APP_ID, Wechat.Ac.USER_WX_AC_SECRETE);
|
||||
|
||||
/**
|
||||
* 微信支付参数KEY
|
||||
*/
|
||||
Set<String> PAY_KEY_SET = Set.of(
|
||||
Wechat.Pay.WX_PUB_KEY,
|
||||
Wechat.Pay.WX_API_CLIENT_KEY,
|
||||
Wechat.Pay.WX_API_CLIENT_CERT,
|
||||
Wechat.Pay.WX_MCH_ID,
|
||||
Wechat.Pay.WX_V3_KEY,
|
||||
System.NATIVE_NOTIFY_URL
|
||||
);
|
||||
|
||||
/**
|
||||
* 支付宝参数KEY
|
||||
*/
|
||||
Set<String> ALI_PAY_KEY_SET = Set.of(
|
||||
Alipay.Web.ALI_GATEWAY,
|
||||
Alipay.Mini.ALI_MINI_APP_ID,
|
||||
Alipay.Mini.ALI_MINI_PRIVATE_KEY,
|
||||
Alipay.Mini.ALI_MINI_PUBLIC_KEY,
|
||||
Alipay.Web.ALI_ACCOUNT_APP_ID,
|
||||
Alipay.Web.ALI_ACCOUNT_PRIVATE_KEY,
|
||||
Alipay.Web.ALI_ACCOUNT_PUBLIC_KEY
|
||||
);
|
||||
|
||||
/**
|
||||
* 阿里云OSS参数KEY
|
||||
*/
|
||||
Set<String> ALI_OSS_KEY_SET = Set.of(
|
||||
ParamCodeCst.AliYun.ALI_SMS_KEY,
|
||||
ParamCodeCst.AliYun.ALI_SMS_SECRET,
|
||||
ParamCodeCst.AliYun.ALI_SMS_TEMPLATE_CODE
|
||||
);
|
||||
|
||||
/**
|
||||
* 阿里云临时凭证
|
||||
*/
|
||||
Set<String> OSS_KEY_SET = Set.of(AliYun.ALI_OSS_ACCESS_KEY, AliYun.ALI_OSS_ACCESS_SECRET, AliYun.ALI_OSS_ENDPOINT, AliYun.ALI_OSS_ROLE_ARN);
|
||||
|
||||
|
||||
/**
|
||||
* 系统通用配置项
|
||||
* <p>存放跨业务模块的通用系统配置</p>
|
||||
|
||||
@@ -9,7 +9,7 @@ import com.czg.market.entity.MkConsumeCashback;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 服务层。
|
||||
* 服务层。
|
||||
*
|
||||
* @author zs
|
||||
* @since 2025-10-13
|
||||
@@ -21,11 +21,17 @@ public interface MkConsumeCashbackService extends IService<MkConsumeCashback> {
|
||||
|
||||
/**
|
||||
* 消费返现
|
||||
* @param shopId 店铺id
|
||||
* @param userId 用户id
|
||||
* @param amount 金额
|
||||
*
|
||||
* @param shopId 店铺id
|
||||
* @param userId 用户id
|
||||
* @param amount 金额
|
||||
* @param orderId 订单id
|
||||
* @param orderNo 订单号
|
||||
*/
|
||||
void cashback(Long shopId, Long userId, BigDecimal amount, Long orderId, String orderNo);
|
||||
|
||||
/**
|
||||
* 订单退款 删除返现
|
||||
*/
|
||||
void removeCashback(Long shopId, Long userId, Long orderId, String orderNo);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package com.czg.market.service;
|
||||
|
||||
import cn.hutool.core.exceptions.ValidateException;
|
||||
import com.czg.account.entity.UserInfo;
|
||||
import com.czg.constant.TableValueConstant;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.market.dto.MkDistributionUserDTO;
|
||||
import com.czg.market.dto.MkDistributionWithdrawFlowDTO;
|
||||
import com.czg.market.entity.MkDistributionConfig;
|
||||
@@ -57,7 +59,7 @@ public interface MkDistributionUserService extends IService<MkDistributionUser>
|
||||
/**
|
||||
* 分销员中心-绑定邀请人
|
||||
*/
|
||||
void bindInviteUser(MkDistributionUserDTO param);
|
||||
void bindInviteUser(MkDistributionUserDTO param) throws CzgException, ValidateException;
|
||||
|
||||
/**
|
||||
* 获取分销员分页列表
|
||||
@@ -85,6 +87,7 @@ public interface MkDistributionUserService extends IService<MkDistributionUser>
|
||||
* 更新分销员
|
||||
*/
|
||||
void updateDistributionUserById(MkDistributionUserDTO param);
|
||||
|
||||
/**
|
||||
* 重置分销员等级
|
||||
*/
|
||||
@@ -100,15 +103,14 @@ public interface MkDistributionUserService extends IService<MkDistributionUser>
|
||||
void deleteDistributionUser(Long id, Long shopId);
|
||||
|
||||
|
||||
|
||||
Boolean cashPayOrder(long adminId, MkDistributionPayDTO payParam);
|
||||
|
||||
/**
|
||||
* 分销员开通
|
||||
*
|
||||
* @param shopUserId 用户
|
||||
* @param amount 金额
|
||||
* @param shopId 店铺id
|
||||
* @param amount 金额
|
||||
* @param shopId 店铺id
|
||||
*/
|
||||
void open(Long shopUserId, BigDecimal amount, Long shopId, Long sourceId);
|
||||
|
||||
@@ -141,15 +143,16 @@ public interface MkDistributionUserService extends IService<MkDistributionUser>
|
||||
|
||||
/**
|
||||
* 微信转账回调
|
||||
*
|
||||
* @param outBillNo 转账单号
|
||||
* @param state ACCEPTED:单据已受理
|
||||
* PROCESSING:单据处理中,转账结果尚未明确,如一直处于此状态,建议检查账户余额是否足够
|
||||
* WAIT_USER_CONFIRM:待收款用户确认,可拉起微信收款确认页面进行收款确认
|
||||
* TRANSFERING:转账中,转账结果尚未明确,可拉起微信收款确认页面再次重试确认收款
|
||||
* SUCCESS: 转账成功
|
||||
* FAIL: 转账失败
|
||||
* CANCELING: 撤销中
|
||||
* CANCELLED: 已撤销
|
||||
* @param state ACCEPTED:单据已受理
|
||||
* PROCESSING:单据处理中,转账结果尚未明确,如一直处于此状态,建议检查账户余额是否足够
|
||||
* WAIT_USER_CONFIRM:待收款用户确认,可拉起微信收款确认页面进行收款确认
|
||||
* TRANSFERING:转账中,转账结果尚未明确,可拉起微信收款确认页面再次重试确认收款
|
||||
* SUCCESS: 转账成功
|
||||
* FAIL: 转账失败
|
||||
* CANCELING: 撤销中
|
||||
* CANCELLED: 已撤销
|
||||
*/
|
||||
void withdrawNotify(String outBillNo, String state, String failReason);
|
||||
|
||||
|
||||
@@ -17,4 +17,9 @@ public interface MkPointsConfigService extends IService<MkPointsConfig> {
|
||||
*
|
||||
*/
|
||||
void consumeAwardPoints(ShopUser shopUser, OrderInfo orderInfo);
|
||||
|
||||
/**
|
||||
* 订单退款成功,通过计算 给用户赠送积分
|
||||
*/
|
||||
void removeConsumeAwardPoints(Long shopId, Long userId, Long orderId, String orderNo);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package com.czg.market.service;
|
||||
|
||||
import com.czg.account.vo.PointsShopListVO;
|
||||
import com.czg.market.entity.MkPointsUserRecord;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.czg.market.entity.MkPointsUserRecord;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 会员积分变动记录 服务层。
|
||||
|
||||
@@ -29,9 +29,9 @@ public interface MkPointsUserService extends IService<MkPointsUser> {
|
||||
* 获取用户积分信息
|
||||
* 返回的数据ID可能为空 不影响修改用户积分 统一接口的处理
|
||||
*
|
||||
* @param shopId 店铺Id
|
||||
* @param shopId 店铺Id
|
||||
* @param shopUserId 店铺用户Id
|
||||
* @param userId 会员Id
|
||||
* @param userId 会员Id
|
||||
*/
|
||||
MkPointsUser getPointsUser(Long shopId, Long shopUserId, Long userId);
|
||||
|
||||
@@ -48,4 +48,9 @@ public interface MkPointsUserService extends IService<MkPointsUser> {
|
||||
*/
|
||||
Long alterPoints(Long userId, Long shopUserId, @NotNull Long shopId, @NotNull PointsConstant floatType,
|
||||
@NotNull Integer points, Long sourceId, @NotBlank String reason);
|
||||
|
||||
/**
|
||||
* 订单退款 赠送的积分 扣除
|
||||
*/
|
||||
void removePointByOrder(Long shopId, Long userId, Long orderId, String orderNo, String reason);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,12 @@ public interface MkShopConsumerCouponService extends IService<MkShopConsumerCoup
|
||||
*/
|
||||
void receiveConsumerCoupon(Long shopId, Long orderId, BigDecimal orderAmount, Long userId, Long shopUserId);
|
||||
|
||||
/**
|
||||
* 订单退款 移除消费赠券
|
||||
*
|
||||
*/
|
||||
void removeConsumerCoupon(Long shopId, Long userId, Long orderId);
|
||||
|
||||
MkShopConsumerCouponDTO getConsumerCouponById(Long id);
|
||||
|
||||
void addConsumerCoupon(MkShopConsumerCouponDTO param);
|
||||
|
||||
@@ -22,13 +22,19 @@ import java.util.List;
|
||||
public interface MkShopRechargeService extends IService<MkShopRecharge> {
|
||||
|
||||
MkShopRechargeVO detail(Long shopId);
|
||||
|
||||
MkShopRechargeVO detailApp(Long shopId);
|
||||
|
||||
Boolean edit(Long shopId, MkShopRechargeDTO shopRechargeDTO);
|
||||
|
||||
BigDecimal checkRecharge(Long mainShopId, @NotNull(message = "店铺不能为空") Long shopId, Long userId, Long rechargeDetailId, @DecimalMin("0.01") BigDecimal money);
|
||||
|
||||
void recharge(Long shopId, Long shopUserId, Long rechargeDetailId, BigDecimal amount, Long paymentId, String payType, ShopUserFlowBizEnum bizEnum);
|
||||
/**
|
||||
* 充值
|
||||
* @param isNoJoin 是否没有执行 加入会员的方法
|
||||
* 会员如果是条件开通 则 需要统计
|
||||
*/
|
||||
void recharge(Long shopId, Long shopUserId, Long rechargeDetailId, BigDecimal amount, Long paymentId, String payType, ShopUserFlowBizEnum bizEnum, boolean isNoJoin);
|
||||
|
||||
List<RechargeListVO> getList(long loginIdAsLong);
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.czg.market.entity.PpHelpRecord;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 套餐推广助力记录 服务层。
|
||||
*
|
||||
@@ -20,5 +22,7 @@ public interface PpHelpRecordService extends IService<PpHelpRecord> {
|
||||
|
||||
void removeHelpRecord(Long orderId);
|
||||
|
||||
void deleteByOrderIds(List<Long> orderIds);
|
||||
|
||||
Page<PpHelpRecordDTO> helpPage(PageQueryParam reqVo);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.czg.order.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 拼团参与 DTO
|
||||
*
|
||||
* @author ww
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class GroupJoinDTO extends LtPayOtherDTO{
|
||||
/**
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.czg.order.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 积分商品兑换信息
|
||||
*
|
||||
* @author ww
|
||||
*/
|
||||
@Data
|
||||
public class PointGoodsExchangeDTO extends LtPayOtherDTO{
|
||||
/**
|
||||
* 积分商品id
|
||||
*/
|
||||
@NotNull(message = "积分商品不能为空")
|
||||
private Long pointsGoodsId;
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package com.czg.order.service;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.czg.order.entity.OrderPayment;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 支付详情 服务层。
|
||||
*
|
||||
@@ -11,4 +13,5 @@ import com.czg.order.entity.OrderPayment;
|
||||
*/
|
||||
public interface OrderPaymentService extends IService<OrderPayment> {
|
||||
|
||||
BigDecimal countMemberInAmount(Long shopId, Long shopUserId);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package com.czg.product.dto;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.czg.product.vo.ProductGroupVo;
|
||||
import com.czg.validator.group.DefaultGroup;
|
||||
import com.czg.validator.group.InsertGroup;
|
||||
import com.czg.validator.group.UpdateGroup;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -235,6 +238,12 @@ public class ProductDTO implements Serializable {
|
||||
* 是否可售时间 1-是 0-否
|
||||
*/
|
||||
private Integer isSaleTime;
|
||||
/**
|
||||
* 相关推荐商品
|
||||
*/
|
||||
private List<RelatedProductDTO> relatedRecommendJson;
|
||||
@JsonIgnore
|
||||
private String relatedRecommend;
|
||||
|
||||
public Object getImages() {
|
||||
return JSON.parseArray(Convert.toStr(images, "[]"));
|
||||
@@ -250,4 +259,16 @@ public class ProductDTO implements Serializable {
|
||||
public Object getGroupSnap() {
|
||||
return JSON.parseArray(Convert.toStr(groupSnap, "[]"));
|
||||
}
|
||||
|
||||
public String getRelatedRecommendStr() {
|
||||
if (CollUtil.isNotEmpty(relatedRecommendJson)) {
|
||||
JSONArray array = new JSONArray();
|
||||
for (RelatedProductDTO relatedProductDTO : relatedRecommendJson) {
|
||||
array.add(relatedProductDTO.getId());
|
||||
}
|
||||
return array.toJSONString();
|
||||
}
|
||||
|
||||
return "[]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.czg.product.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 相关推荐 商品 DTO
|
||||
*
|
||||
* @author yjjie
|
||||
* @date 2025/12/24 13:34
|
||||
*/
|
||||
@Data
|
||||
public class RelatedProductDTO implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 商品 ID
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 商品名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 商品图片
|
||||
*/
|
||||
private String coverImg;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.czg.product.entity;
|
||||
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 数签子的外链渠道 实体类。
|
||||
*
|
||||
* @author ww
|
||||
* @since 2025-12-24
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table("mk_ocr_count_stick")
|
||||
public class MkOcrCountStick implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 渠道名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 标记
|
||||
*/
|
||||
private String mark;
|
||||
|
||||
/**
|
||||
* 地址
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 状态 0/1
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
private Integer sort;
|
||||
|
||||
private String token;
|
||||
private String account;
|
||||
private String pwd;
|
||||
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
package com.czg.product.entity;
|
||||
|
||||
import com.czg.product.param.ConsInOutStockHeadParam;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.czg.market.entity.MkOcr;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* ocr识别结果 服务层。
|
||||
*
|
||||
@@ -11,4 +14,7 @@ import com.czg.market.entity.MkOcr;
|
||||
*/
|
||||
public interface MkOcrService extends IService<MkOcr> {
|
||||
|
||||
ConsInOutStockHeadParam ocrDetail(Long id);
|
||||
|
||||
Integer ocr(String originalFilename, InputStream inputStream, String type);
|
||||
}
|
||||
|
||||
@@ -142,6 +142,10 @@ public class Product implements Serializable {
|
||||
* 退款是否退回库存
|
||||
*/
|
||||
private Integer isRefundStock;
|
||||
/**
|
||||
* 相关推荐
|
||||
*/
|
||||
private String relatedRecommend;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,6 @@ import com.czg.product.vo.ConsCheckStockRecordVo;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -25,7 +24,6 @@ public interface ConsStockFlowService extends IService<ConsStockFlow> {
|
||||
* 手动入库
|
||||
*
|
||||
* @param param 手动出库入参
|
||||
* @return
|
||||
*/
|
||||
ConsInOutStockHeadParam inStock(ConsInOutStockHeadParam param);
|
||||
|
||||
@@ -78,8 +76,4 @@ public interface ConsStockFlowService extends IService<ConsStockFlow> {
|
||||
* @param entity 库存变动记录实体
|
||||
*/
|
||||
void saveFlow(ConsStockFlow entity);
|
||||
|
||||
Integer ocr(String originalFilename, InputStream inputStream);
|
||||
|
||||
ConsInOutStockHeadParam ocrDetail(Long id);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.czg.product.service;
|
||||
|
||||
import com.czg.product.entity.MkOcrCountStick;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
|
||||
/**
|
||||
* 数签子的外链渠道 服务层。
|
||||
*
|
||||
* @author ww
|
||||
* @since 2025-12-24
|
||||
*/
|
||||
public interface MkOcrCountStickService extends IService<MkOcrCountStick> {
|
||||
|
||||
int getCountStick(byte[] stream, String fileName);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.czg.product.service;
|
||||
|
||||
import com.czg.product.dto.ProductDTO;
|
||||
import com.czg.product.dto.RelatedProductDTO;
|
||||
import com.czg.product.entity.Product;
|
||||
import com.czg.product.entity.ProductStockFlow;
|
||||
import com.czg.product.param.*;
|
||||
|
||||
@@ -3,12 +3,14 @@ package com.czg.product.vo;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品规格详情
|
||||
@@ -109,6 +111,12 @@ public class ShopProductInfoVo implements Serializable {
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
private LocalTime endTime;
|
||||
/**
|
||||
* 相关推荐商品
|
||||
*/
|
||||
private List<ShopProductVo> relatedRecommendJson;
|
||||
@JsonIgnore
|
||||
private String relatedRecommend;
|
||||
|
||||
public Object getImages() {
|
||||
return JSON.parseArray(Convert.toStr(images, "[]"));
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package com.czg.system.service;
|
||||
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.system.dto.SysParamsDTO;
|
||||
import com.czg.system.entity.SysParams;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 服务层。
|
||||
@@ -23,6 +26,7 @@ public interface SysParamsService extends IService<SysParams> {
|
||||
* @return 参数列表
|
||||
*/
|
||||
CzgResult<List<SysParamsDTO>> getParamsByType(Integer type);
|
||||
|
||||
/**
|
||||
* 新增参数
|
||||
*
|
||||
@@ -62,4 +66,13 @@ public interface SysParamsService extends IService<SysParams> {
|
||||
*/
|
||||
String getSysParamValue(String code);
|
||||
|
||||
|
||||
/**
|
||||
* 根据参数类型获取参数
|
||||
* dubbo 调用需要 显式抛出 异常类型
|
||||
*
|
||||
* @param type 参数类型
|
||||
* @param keyList 内容为 {@link com.czg.constants.ParamCodeCst}的Set集合
|
||||
*/
|
||||
Map<String, String> getParamsByMap(String type, Set<String> keyList) throws CzgException;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ public enum ShopUserFlowBizEnum {
|
||||
// 会员充值
|
||||
CASH_IN("cashIn", "会员充值"),
|
||||
CASHBACK("cashback", "消费返现"),
|
||||
CASHBACK_REFUND("cashback_refund", "消费返现扣减"),
|
||||
|
||||
FREE_IN("freeIn", "霸王餐充值"),
|
||||
// 重置奖励
|
||||
AWARD_IN("awardIn", "充值奖励"),
|
||||
|
||||
@@ -16,9 +16,6 @@ import com.czg.exception.CzgException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -35,9 +32,8 @@ public class AliOcrUtil {
|
||||
/**
|
||||
* <b>description</b> :
|
||||
* <p>使用凭据初始化账号Client</p>
|
||||
* @return Client
|
||||
*
|
||||
* @throws Exception
|
||||
* @return Client
|
||||
*/
|
||||
public static com.aliyun.bailian20231229.Client createClient() {
|
||||
|
||||
@@ -56,7 +52,6 @@ public class AliOcrUtil {
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static ApplyFileUploadLeaseResponseBody.ApplyFileUploadLeaseResponseBodyData applyFileUpload(byte[] bytes, String fileName) {
|
||||
|
||||
String md5 = DigestUtil.md5Hex(bytes);
|
||||
@@ -95,7 +90,7 @@ public class AliOcrUtil {
|
||||
.setCategoryId("default")
|
||||
.setCategoryType("SESSION_FILE");
|
||||
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
|
||||
java.util.Map<String, String> headers = new java.util.HashMap<>();
|
||||
java.util.Map<String, String> headers = new java.util.HashMap<>();
|
||||
try {
|
||||
// 复制代码运行请自行打印 API 的返回值
|
||||
AddFileResponse addFileResponse = client.addFileWithOptions("llm-9zg04s7wlbvi32tq", addFileRequest, headers, runtime);
|
||||
@@ -110,7 +105,7 @@ public class AliOcrUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean getFileStatus(String fileId) {
|
||||
public static boolean getFileStatus(String fileId) {
|
||||
com.aliyun.bailian20231229.Client client = createClient();
|
||||
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
|
||||
java.util.Map<String, String> headers = new java.util.HashMap<>();
|
||||
@@ -118,7 +113,7 @@ public class AliOcrUtil {
|
||||
// 复制代码运行请自行打印 API 的返回值
|
||||
DescribeFileResponse describeFileResponse = client.describeFileWithOptions("llm-9zg04s7wlbvi32tq", fileId, headers, runtime);
|
||||
|
||||
log.info("file status: {}", describeFileResponse.getBody());
|
||||
log.info("file status: {}", describeFileResponse.getStatusCode());
|
||||
return describeFileResponse.getBody().getData() != null && "FILE_IS_READY".equals(describeFileResponse.getBody().getData().getStatus());
|
||||
} catch (Exception error) {
|
||||
throw new RuntimeException(error);
|
||||
@@ -158,18 +153,18 @@ public class AliOcrUtil {
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static String appCall(byte[] bytes, String fileName) {
|
||||
String id = null;
|
||||
//地址 https://bailian.console.aliyun.com
|
||||
public static String appCall(byte[] bytes, String fileName, String detail) {
|
||||
String id;
|
||||
try {
|
||||
id = getSessionId(bytes, fileName);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
ApplicationParam param = ApplicationParam.builder()
|
||||
ApplicationParam param = ApplicationParam.builder()
|
||||
.apiKey("sk-2343af4413834ad1ab43b036e3a903de")
|
||||
.appId("cd612ac509a4499f8ac68a656532d4ae")
|
||||
.prompt("你是一名票据OCR结构化专家,请从我提供的票据图片中智能提取信息并只输出JSON,不得添加解释、不补充不存在内容、不得返回空字符串、字段缺失填null、字段不可省略、数字一律用字符串,使用以下固定JSON结构:{\"documentType\":\"\",\"orderNumber\":\"\",\"date\":\"\",\"customerName\":\"\",\"operator\":\"\",\"items\":[{\"conName\":\"\",\"spec\":\"\",\"unitName\":\"\",\"inOutNumber\":\"\",\"purchasePrice\":\"\",\"subTotal\":\"\"}],\"totalAmount\":\"\",\"remark\":\"\"}。字段映射规则:documentType对应单据类型/销售单/采购单/出货单;orderNumber对应单号/编号/No;date对应日期/开单日期;customerName对应客户名称/收货单位/供应商;operator对应业务员/经办人/制单人/操作员;items.conName对应品名/名称;items.spec对应规格/型号;items.unitName对应单位;items.inOutNumber对应数量;items.purchasePrice对应单价;items.subTotal对应金额/小计;totalAmount对应总金额/合计金额;remark对应备注。严禁生成图片中不存在的字段内容,看不清或未出现的字段必须为null,不允许推测或补全,不得生成多余字段;items只能根据识别到的行生成,不得虚构。必须能识别旋转、倾斜、模糊、撕裂、光照差异、列顺序混乱、无表格线等情况并尽量恢复信息。最终输出必须是纯JSON,不得包含任何非JSON字符。")
|
||||
.prompt(detail)
|
||||
.ragOptions(RagOptions.builder()
|
||||
.sessionFileIds(List.of(id))
|
||||
.build())
|
||||
@@ -187,11 +182,4 @@ public class AliOcrUtil {
|
||||
return result.getOutput().getText();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
}
|
||||
|
||||
static void main() throws Exception {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,9 +2,12 @@ package com.czg.utils;
|
||||
|
||||
import cn.hutool.core.lang.func.Func0;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.transaction.support.TransactionSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author zs
|
||||
*/
|
||||
@Slf4j
|
||||
public class FunUtils {
|
||||
/**
|
||||
@@ -38,4 +41,27 @@ public class FunUtils {
|
||||
log.error(errorMsg, args, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在事务提交后执行方法
|
||||
* 异步 执行
|
||||
*
|
||||
* @param func 方法
|
||||
*/
|
||||
public static void transactionSafeRun(Runnable func) {
|
||||
try {
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||
@Override
|
||||
public void afterCommit() {
|
||||
safeRunVoid(func, "");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
safeRunVoid(func, "");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("方法执行失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,15 @@ public class PageUtil {
|
||||
return new Page<>(pageNum, pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取空Page对象
|
||||
*/
|
||||
public <T> Page<T> emptyPage() {
|
||||
return Page.of(1,10,0) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 构造排序QueryWrapper
|
||||
* 从param体获取
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.czg.market.vo.MemberConfigVO;
|
||||
import com.czg.order.entity.OrderInfo;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.account.mapper.ShopUserMapper;
|
||||
import com.czg.system.service.SysParamsService;
|
||||
import com.czg.utils.PageUtil;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
@@ -35,7 +34,6 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -57,8 +55,6 @@ public class AShopUserServiceImpl implements AShopUserService {
|
||||
@Resource
|
||||
private UserInfoService userInfoService;
|
||||
@DubboReference
|
||||
private SysParamsService sysParamsService;
|
||||
@DubboReference
|
||||
private OrderInfoService orderInfoService;
|
||||
@DubboReference
|
||||
private MkShopCouponRecordService couponRecordService;
|
||||
@@ -66,8 +62,6 @@ public class AShopUserServiceImpl implements AShopUserService {
|
||||
private MemberLevelConfigService memberLevelConfigService;
|
||||
@DubboReference
|
||||
private TbMemberConfigService memberConfigService;
|
||||
// @DubboReference
|
||||
// private MkShopConsumeDiscountRecordService consumeDiscountService;
|
||||
|
||||
private ShopUser getUserInfo(Long shopUserId) {
|
||||
ShopUser shopUser = shopUserService.queryChain().eq(ShopUser::getId, shopUserId).one();
|
||||
@@ -94,12 +88,8 @@ public class AShopUserServiceImpl implements AShopUserService {
|
||||
public Page<ShopUserDTO> getPage(String key, Integer isVip, BigDecimal amount) {
|
||||
Long mainIdByShopId = shopInfoService.getMainIdByShopId(StpKit.USER.getShopId());
|
||||
PageHelper.startPage(PageUtil.buildPageHelp());
|
||||
PageInfo<ShopUserDTO> shopUserDTOPageInfo = new PageInfo<>(shopUserMapper.selectPageByKeyAndIsVip(mainIdByShopId, isVip, key, amount));
|
||||
// shopUserDTOPageInfo.getList().forEach(item -> {
|
||||
// item.setNew(consumeDiscountService.isNewUser(item, StpKit.USER.getShopId()));
|
||||
// setUserDiscount(item);
|
||||
// });
|
||||
return PageUtil.convert(shopUserDTOPageInfo);
|
||||
PageInfo<ShopUserDTO> shopUsers = new PageInfo<>(shopUserMapper.selectPageByKeyAndIsVip(mainIdByShopId, isVip, key, amount));
|
||||
return PageUtil.convert(shopUsers);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -177,16 +167,6 @@ public class AShopUserServiceImpl implements AShopUserService {
|
||||
return shopUserService.save(shopUser);
|
||||
}
|
||||
|
||||
private void setUserDiscount(ShopUserDTO shopUserDTO) {
|
||||
if (shopUserDTO.getMemberLevelId() != null) {
|
||||
MemberLevelConfig memberLevelConfig = memberLevelConfigService.getById(shopUserDTO.getMemberLevelId());
|
||||
shopUserDTO.setMemberLevelName(memberLevelConfig == null ? null : memberLevelConfig.getName());
|
||||
if (memberLevelConfig != null) {
|
||||
shopUserDTO.setDiscount(memberLevelConfig.getDiscount());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShopUser getDetail(Integer id, Integer userId) {
|
||||
Long mainId = shopInfoService.getMainIdByShopId(StpKit.USER.getShopId());
|
||||
|
||||
@@ -473,7 +473,7 @@ public class CallTableServiceImpl extends ServiceImpl<CallTableMapper, CallTable
|
||||
} else {
|
||||
List<CallTable> list = queryChain().eq(CallTable::getShopId, shopId).eq(CallTable::getState, 1).list();
|
||||
if (list.isEmpty()) {
|
||||
return new Page<>();
|
||||
return PageUtil.emptyPage();
|
||||
}
|
||||
tableIds = list.stream()
|
||||
.map(CallTable::getId)
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
package com.czg.service.account.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.czg.account.dto.ShopConfigDTO;
|
||||
import com.czg.account.entity.ShopConfig;
|
||||
import com.czg.account.entity.ShopInfo;
|
||||
import com.czg.account.service.ShopConfigService;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.RedisService;
|
||||
import com.czg.service.account.mapper.ShopConfigMapper;
|
||||
import com.czg.service.account.mapper.ShopInfoMapper;
|
||||
import com.czg.utils.PageUtil;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import jakarta.annotation.Resource;
|
||||
@@ -90,19 +87,10 @@ public class ShopConfigServiceImpl extends ServiceImpl<ShopConfigMapper, ShopCon
|
||||
});
|
||||
|
||||
if (isEnable == 0 && !onyUpValid) {
|
||||
|
||||
updateChain().or(or -> {
|
||||
or.eq(ShopConfig::getId, mainShopId);
|
||||
}).or(or -> {
|
||||
or.in(ShopConfig::getId, childShopIdList);
|
||||
}).set(property, 0).update();
|
||||
updateChain().in(ShopConfig::getId, childShopIdList).set(property, 0).update();
|
||||
}else {
|
||||
if ("all".equals(useShopType)) {
|
||||
updateChain().or(or -> {
|
||||
or.eq(ShopConfig::getId, mainShopId);
|
||||
}).or(or -> {
|
||||
or.in(ShopConfig::getId, childShopIdList);
|
||||
}).set(property, 1).update();
|
||||
updateChain().in(ShopConfig::getId, childShopIdList).set(property, 1).update();
|
||||
}else {
|
||||
if (shopIdList.isEmpty()) {
|
||||
updateChain().eq(ShopConfig::getId, mainShopId).set(property, 1).update();
|
||||
@@ -115,7 +103,6 @@ public class ShopConfigServiceImpl extends ServiceImpl<ShopConfigMapper, ShopCon
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extistList.forEach(item -> redisService.del("shopInfo::" + item));
|
||||
redisService.del("shopInfo::" + mainShopId);
|
||||
}
|
||||
|
||||
@@ -152,9 +152,6 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
|
||||
|
||||
// Step 2: 解析 apiInfo 并判断菜单是否已绑定
|
||||
for (BaseMenu menu : menuList) {
|
||||
if (menu.getMenuId() == 1L) {
|
||||
continue;
|
||||
}
|
||||
// 解析 apiInfo
|
||||
if (StrUtil.isNotBlank(menu.getApiInfo())) {
|
||||
List<MenuApiInfoItemDTO> itemDTOS = JSONArray.parseArray(menu.getApiInfo())
|
||||
@@ -180,9 +177,6 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
|
||||
|
||||
List<SysMenu> matchedMenus = sysMenuService.list(wrapper);
|
||||
for (SysMenu matched : matchedMenus) {
|
||||
if (matched.getMenuId() == 1L) {
|
||||
continue;
|
||||
}
|
||||
long count = sysRolesMenusService.count(new QueryWrapper()
|
||||
.eq("menu_id", matched.getMenuId())
|
||||
.eq("role_id", roleId)
|
||||
|
||||
@@ -6,7 +6,6 @@ import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.account.dto.auth.GetPhoneDTO;
|
||||
import com.czg.account.dto.auth.LoginTokenDTO;
|
||||
import com.czg.account.dto.auth.UserAuthorizationLoginDTO;
|
||||
import com.czg.account.dto.auth.WechatRawDataDTO;
|
||||
import com.czg.account.entity.UserInfo;
|
||||
import com.czg.account.service.UserAuthorizationService;
|
||||
import com.czg.account.service.UserInfoService;
|
||||
@@ -95,19 +94,13 @@ public class UserAuthorizationServiceImpl implements UserAuthorizationService {
|
||||
openId = wechatAuthUtil.getSessionKeyOrOpenId(userAuthorizationLoginDTO.getCode(), false);
|
||||
userInfo = userInfoService.queryChain().eq(UserInfo::getWechatOpenId, openId).one();
|
||||
userInfo = userInfo == null ? new UserInfo() : userInfo;
|
||||
if (StrUtil.isNotBlank(userAuthorizationLoginDTO.getRawData())) {
|
||||
WechatRawDataDTO wechatRawDataDTO = JSONObject.parseObject(userAuthorizationLoginDTO.getRawData(), WechatRawDataDTO.class);
|
||||
userInfo.setHeadImg(wechatRawDataDTO.getAvatarUrl());
|
||||
userInfo.setNickName(StrUtil.isNotBlank(wechatRawDataDTO.getNickName()) ? wechatRawDataDTO.getNickName() : "微信用户");
|
||||
} else {
|
||||
userInfo.setNickName("微信用户");
|
||||
}
|
||||
userInfo.setNickName(StrUtil.isNotBlank(userInfo.getNickName()) ? userInfo.getNickName() : "微信用户");
|
||||
userInfo.setWechatOpenId(openId);
|
||||
} else {
|
||||
openId = alipayUtil.getOpenId(userAuthorizationLoginDTO.getCode(), false);
|
||||
userInfo = userInfoService.queryChain().eq(UserInfo::getAlipayOpenId, openId).one();
|
||||
userInfo = userInfo == null ? new UserInfo() : userInfo;
|
||||
userInfo.setNickName("支付宝用户");
|
||||
userInfo.setNickName(StrUtil.isNotBlank(userInfo.getNickName()) ? userInfo.getNickName() : "支付宝用户");
|
||||
userInfo.setAlipayOpenId(openId);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.czg.account.dto.user.userinfo.UserInfoEditDTO;
|
||||
import com.czg.account.dto.user.userinfo.UserInfoPwdEditDTO;
|
||||
import com.czg.account.entity.ShopUser;
|
||||
import com.czg.account.entity.UserInfo;
|
||||
import com.czg.account.service.ShopInfoService;
|
||||
import com.czg.account.service.UserInfoService;
|
||||
import com.czg.config.RedisCst;
|
||||
import com.czg.exception.CzgException;
|
||||
@@ -38,6 +39,8 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> i
|
||||
@Resource
|
||||
private ShopUserMapper shopUserMapper;
|
||||
@Resource
|
||||
private ShopInfoService shopInfoService;
|
||||
@Resource
|
||||
private RedisService redisService;
|
||||
@Resource
|
||||
private AcAccountUtil acAccountUtil;
|
||||
@@ -62,9 +65,10 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> i
|
||||
UserInfo userInfo = getById(userId);
|
||||
BeanUtil.copyProperties(userInfoEditDTO, userInfo);
|
||||
if (updateById(userInfo)) {
|
||||
if (shopId != -1L) {
|
||||
if (shopId != 0L) {
|
||||
ShopUser shopUser = BeanUtil.copyProperties(userInfo, ShopUser.class);
|
||||
return shopUserMapper.updateByQuery(shopUser, new QueryWrapper().eq(ShopUser::getSourceShopId, shopId).eq(ShopUser::getUserId, userId)) > 0;
|
||||
Long mainIdByShopId = shopInfoService.getMainIdByShopId(shopId);
|
||||
return shopUserMapper.updateByQuery(shopUser, new QueryWrapper().eq(ShopUser::getMainShopId, mainIdByShopId).eq(ShopUser::getUserId, userId)) > 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 微信公众号
|
||||
@@ -90,8 +91,10 @@ public class AcAccountUtil {
|
||||
if (StrUtil.isNotEmpty(accessToken)) {
|
||||
return accessToken;
|
||||
}
|
||||
String acAppId = paramsService.getSysParamValue(ParamCodeCst.Wechat.Ac.USER_WX_AC_APP_ID);
|
||||
String acSecrete = paramsService.getSysParamValue(ParamCodeCst.Wechat.Ac.USER_WX_AC_SECRETE);
|
||||
Map<String, String> userAc = paramsService.getParamsByMap("user_ac_key_set", ParamCodeCst.USER_AC_KEY_SET);
|
||||
// 用户小程序参数
|
||||
String acAppId = userAc.get(ParamCodeCst.Wechat.Ac.USER_WX_AC_APP_ID);
|
||||
String acSecrete = userAc.get(ParamCodeCst.Wechat.Ac.USER_WX_AC_SECRETE);
|
||||
String resp = HttpUtil.get(StrUtil.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}", acAppId, acSecrete));
|
||||
JSONObject respInfo = JSONObject.parseObject(resp);
|
||||
if (!respInfo.containsKey("access_token")) {
|
||||
@@ -103,26 +106,4 @@ public class AcAccountUtil {
|
||||
redisService.set("wx:ac:AccessToken", accessToken, expiresIn - 10);
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// String resp = HttpUtil.get(StrUtil.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}", "wx1fb600d0f5ea6279", "b4c0534c9b5e6c84a7fe5c2078dff876"));
|
||||
// System.out.println(resp);
|
||||
// String accessToken = "97_HZVThQrtvOiCZGrr23ZHN0cVpHBJHc18RSFHU6dvkQDMAme4GsG0NU-Dax1HP5Wx-aGa1l35KaqiMVv61TCj0Qk8DK1LC6kQ8uKLDfgRYVJjX3QjcelmIjp4PCkERBeABAUHR";
|
||||
// JSONObject bodyJson = new JSONObject();
|
||||
// //二维码有效时间(秒),最大2592000,仅临时二维码需要
|
||||
// bodyJson.put("expire_seconds", "2592000");
|
||||
// //二维码类型:QR_SCENE(临时整型)/QR_STR_SCENE(临时字符串)/QR_LIMIT_SCENE(永久整型)/QR_LIMIT_STR_SCENE(永久字符串)
|
||||
// bodyJson.put("action_name", "QR_STR_SCENE");
|
||||
// JSONObject actionInfo = new JSONObject();
|
||||
// JSONObject scene = new JSONObject();
|
||||
// scene.put("scene_str", "43525423");
|
||||
// actionInfo.put("scene", scene);
|
||||
// bodyJson.put("action_info", actionInfo);
|
||||
// System.out.println(bodyJson);
|
||||
//创建临时二维码失败,发送参数: {"action_info":{"scene":{"scene_id":36449}},"action_name":"QR_SCENE","expire_seconds":"2592000"}, 响应内容: {"errcode":40052,"errmsg":"invalid action name rid: 68f5fa37-20fb3162-0f87b4f2"}
|
||||
//创建临时二维码失败,发送参数: {"action_info":{"scene":{"scene_id":36449}},"action_name":"QR_SCENE","expire_seconds":"2592000"}, 响应内容: {"errcode":40052,"errmsg":"invalid action name rid: 68f5f970-2a84749c-78e4d78f"}
|
||||
// String resps = HttpUtil.post(StrUtil.format("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={}", accessToken), JSONObject.toJSONString(bodyJson));
|
||||
// JSONObject respInfos = JSONObject.parseObject(resps);
|
||||
// System.out.println(respInfos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 支付宝通用SDK工具类
|
||||
*
|
||||
@@ -37,13 +40,15 @@ public class AlipayUtil {
|
||||
*/
|
||||
@SneakyThrows
|
||||
public AlipayClient createClient(boolean isAccount) {
|
||||
String serverUrl = sysParamsService.getSysParamValue(ParamCodeCst.Alipay.Web.ALI_GATEWAY);
|
||||
String appId = sysParamsService.getSysParamValue(ParamCodeCst.Alipay.Mini.ALI_MINI_APP_ID);
|
||||
String privateKey = sysParamsService.getSysParamValue(ParamCodeCst.Alipay.Mini.ALI_MINI_PRIVATE_KEY);
|
||||
String alipayPublicKey = sysParamsService.getSysParamValue(ParamCodeCst.Alipay.Mini.ALI_MINI_PUBLIC_KEY);
|
||||
String accountAppId = sysParamsService.getSysParamValue(ParamCodeCst.Alipay.Web.ALI_ACCOUNT_APP_ID);
|
||||
String accountPrivateKey = sysParamsService.getSysParamValue(ParamCodeCst.Alipay.Web.ALI_ACCOUNT_PRIVATE_KEY);
|
||||
String accountPublicKey = sysParamsService.getSysParamValue(ParamCodeCst.Alipay.Web.ALI_ACCOUNT_PUBLIC_KEY);
|
||||
Map<String, String> aliPayKeySet = sysParamsService.getParamsByMap("ali_pay_key_set", ParamCodeCst.ALI_PAY_KEY_SET);
|
||||
|
||||
String serverUrl = aliPayKeySet.get(ParamCodeCst.Alipay.Web.ALI_GATEWAY);
|
||||
String appId = aliPayKeySet.get(ParamCodeCst.Alipay.Mini.ALI_MINI_APP_ID);
|
||||
String privateKey = aliPayKeySet.get(ParamCodeCst.Alipay.Mini.ALI_MINI_PRIVATE_KEY);
|
||||
String alipayPublicKey = aliPayKeySet.get(ParamCodeCst.Alipay.Mini.ALI_MINI_PUBLIC_KEY);
|
||||
String accountAppId = aliPayKeySet.get(ParamCodeCst.Alipay.Web.ALI_ACCOUNT_APP_ID);
|
||||
String accountPrivateKey = aliPayKeySet.get(ParamCodeCst.Alipay.Web.ALI_ACCOUNT_PRIVATE_KEY);
|
||||
String accountPublicKey = aliPayKeySet.get(ParamCodeCst.Alipay.Web.ALI_ACCOUNT_PUBLIC_KEY);
|
||||
AlipayConfig alipayConfig = new AlipayConfig();
|
||||
//设置网关地址
|
||||
alipayConfig.setServerUrl(serverUrl);
|
||||
|
||||
@@ -56,8 +56,9 @@ public class WechatAuthUtil {
|
||||
}
|
||||
|
||||
public String getAccountOpenId(String code) {
|
||||
String accountAppId = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Ac.SHOP_WX_AC_APP_ID);
|
||||
String accountSecrete = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Ac.SHOP_WX_AC_SECRETE);
|
||||
Map<String, String> shopAc = sysParamsService.getParamsByMap("shop_ac_key_set", ParamCodeCst.SHOP_AC_KEY_SET);
|
||||
String accountAppId = shopAc.get(ParamCodeCst.Wechat.Ac.SHOP_WX_AC_APP_ID);
|
||||
String accountSecrete = shopAc.get(ParamCodeCst.Wechat.Ac.SHOP_WX_AC_SECRETE);
|
||||
String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?";
|
||||
Map<String, Object> requestUrlParam = new HashMap<>();
|
||||
// https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN
|
||||
@@ -78,8 +79,10 @@ public class WechatAuthUtil {
|
||||
|
||||
//获取小程序token
|
||||
private String getAccessToken() {
|
||||
String appId = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID);
|
||||
String secrete = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Mini.USER_WX_SECRETE);
|
||||
Map<String, String> userMini = sysParamsService.getParamsByMap("user_mini_key_set", ParamCodeCst.USER_MINI_KEY_SET);
|
||||
// 用户小程序参数
|
||||
String appId = userMini.get(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID);
|
||||
String secrete = userMini.get(ParamCodeCst.Wechat.Mini.USER_WX_SECRETE);
|
||||
String url = String.format("%s?grant_type=client_credential&appid=%s&secret=%s", TOKEN_URL, appId, secrete);
|
||||
String response = HttpUtil.get(url);
|
||||
com.alibaba.fastjson.JSONObject jsonResponse = com.alibaba.fastjson.JSONObject.parseObject(response);
|
||||
@@ -120,8 +123,11 @@ public class WechatAuthUtil {
|
||||
|
||||
|
||||
public JSONObject getSession(String code) {
|
||||
String appId = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID);
|
||||
String secrete = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Mini.USER_WX_SECRETE);
|
||||
Map<String, String> userMini = sysParamsService.getParamsByMap("user_mini_key_set", ParamCodeCst.USER_MINI_KEY_SET);
|
||||
// 用户小程序参数
|
||||
String appId = userMini.get(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID);
|
||||
String secrete = userMini.get(ParamCodeCst.Wechat.Mini.USER_WX_SECRETE);
|
||||
|
||||
String requestUrl = "https://api.weixin.qq.com/sns/jscode2session";
|
||||
Map<String, Object> requestUrlParam = new HashMap<>();
|
||||
// https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN
|
||||
|
||||
@@ -139,8 +139,9 @@ public class WechatMiniMsgUtil {
|
||||
}
|
||||
|
||||
public String getAccountOpenId(String code) {
|
||||
String accountAppId = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Ac.SHOP_WX_AC_APP_ID);
|
||||
String accountSecrete = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Ac.SHOP_WX_AC_SECRETE);
|
||||
Map<String, String> shopAc = sysParamsService.getParamsByMap("shop_ac_key_set", ParamCodeCst.SHOP_AC_KEY_SET);
|
||||
String accountAppId = shopAc.get(ParamCodeCst.Wechat.Ac.SHOP_WX_AC_APP_ID);
|
||||
String accountSecrete = shopAc.get(ParamCodeCst.Wechat.Ac.SHOP_WX_AC_SECRETE);
|
||||
String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?";
|
||||
Map<String, Object> requestUrlParam = new HashMap<>();
|
||||
// https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN
|
||||
@@ -165,8 +166,10 @@ public class WechatMiniMsgUtil {
|
||||
if (StrUtil.isNotEmpty(accessToken)) {
|
||||
return accessToken;
|
||||
}
|
||||
String appId = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Mini.SHOP_WX_APP_ID);
|
||||
String secrete = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Mini.SHOP_WX_SECRETE);
|
||||
// 商户小程序参数
|
||||
Map<String, String> shopMiniKeyMap = sysParamsService.getParamsByMap("shop_mini_key_set", ParamCodeCst.SHOP_MINI_KEY_SET);
|
||||
String appId = shopMiniKeyMap.get(ParamCodeCst.Wechat.Mini.SHOP_WX_APP_ID);
|
||||
String secrete = shopMiniKeyMap.get(ParamCodeCst.Wechat.Mini.SHOP_WX_SECRETE);
|
||||
|
||||
String url = String.format("%s?grant_type=client_credential&appid=%s&secret=%s", TOKEN_URL, appId, secrete);
|
||||
String response = HttpUtil.get(url);
|
||||
@@ -211,8 +214,10 @@ public class WechatMiniMsgUtil {
|
||||
|
||||
|
||||
public JSONObject getSession(String code) {
|
||||
String appId = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID);
|
||||
String secrete = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Mini.USER_WX_SECRETE);
|
||||
Map<String, String> userMini = sysParamsService.getParamsByMap("user_mini_key_set", ParamCodeCst.USER_MINI_KEY_SET);
|
||||
// 用户小程序参数
|
||||
String appId = userMini.get(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID);
|
||||
String secrete = userMini.get(ParamCodeCst.Wechat.Mini.USER_WX_SECRETE);
|
||||
String requestUrl = "https://api.weixin.qq.com/sns/jscode2session";
|
||||
Map<String, Object> requestUrlParam = new HashMap<>();
|
||||
// https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<mapper namespace="com.czg.service.account.mapper.ShopUserMapper">
|
||||
<update id="incrAccount">
|
||||
update tb_shop_user
|
||||
set amount = COALESCE(amount, 0) + #{money},
|
||||
set amount = amount + #{money},
|
||||
update_time = #{time}
|
||||
where id = #{id}
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
</select>
|
||||
|
||||
<select id="selectVipCard" resultType="com.czg.account.dto.shopuser.ShopUserVipCardDTO">
|
||||
select tb_shop_info.logo, tb_shop_info.shop_name shopName, tb_shop_user.amount, tb_shop_user.shop_id shopId
|
||||
select tb_shop_info.logo, tb_shop_info.shop_name shopName, tb_shop_user.amount, tb_shop_user.main_shop_id shopId
|
||||
from tb_shop_user
|
||||
left join tb_shop_info on tb_shop_user.main_shop_id = tb_shop_info.id
|
||||
${qwSql}
|
||||
@@ -72,41 +72,20 @@
|
||||
IFNULL(c.couponNum, 0) AS couponNum,
|
||||
IFNULL(d.orderNumber, 0) AS orderNumber,
|
||||
IFNULL(f.rechargeAmount, 0) AS rechargeAmount,
|
||||
c.name as memberLevelName,
|
||||
c.discount
|
||||
point.point_balance as pointBalance,
|
||||
c1.name as memberLevelName,
|
||||
c1.discount
|
||||
FROM tb_shop_user a
|
||||
LEFT JOIN tb_user_info b ON b.id = a.user_id
|
||||
LEFT JOIN tb_member_level_config c on c.id=a.member_level_id
|
||||
|
||||
LEFT JOIN tb_member_level_config c1 on c1.id=a.member_level_id
|
||||
LEFT JOIN mk_points_user point on point.shop_user_id = a.id
|
||||
-- 预计算优惠券数量
|
||||
LEFT JOIN (
|
||||
SELECT shop_user_id, COUNT(*) AS couponNum
|
||||
FROM mk_shop_coupon_record
|
||||
WHERE
|
||||
is_del = 0
|
||||
# AND status = 0
|
||||
# AND use_start_time < NOW()
|
||||
# AND use_end_time > NOW()
|
||||
GROUP BY shop_user_id
|
||||
) c ON c.shop_user_id = a.id
|
||||
|
||||
LEFT JOIN (SELECT shop_user_id, COUNT(*) AS couponNum FROM mk_shop_coupon_record WHERE is_del = 0 GROUP BY shop_user_id ) c ON c.shop_user_id = a.id
|
||||
-- 预计算订单数量
|
||||
LEFT JOIN (
|
||||
SELECT user_id, shop_id, COUNT(*) AS orderNumber
|
||||
FROM tb_order_info
|
||||
GROUP BY user_id, shop_id
|
||||
) d ON d.user_id = a.user_id AND d.shop_id = a.main_shop_id
|
||||
|
||||
LEFT JOIN (SELECT user_id, shop_id, COUNT(*) AS orderNumber FROM tb_order_info GROUP BY user_id, shop_id) d ON d.user_id = a.user_id AND d.shop_id = a.main_shop_id
|
||||
-- 预计算充值总金额
|
||||
LEFT JOIN (
|
||||
SELECT user_id, shop_id, SUM(amount) AS rechargeAmount
|
||||
FROM tb_shop_user_flow
|
||||
WHERE biz_code IN ('cashIn', 'wechatIn', 'alipayIn')
|
||||
GROUP BY user_id, shop_id
|
||||
) f ON f.user_id = a.user_id AND f.shop_id = a.main_shop_id
|
||||
|
||||
LEFT JOIN ( SELECT user_id, shop_id, SUM(amount) AS rechargeAmount
|
||||
FROM tb_shop_user_flow WHERE biz_code IN ('cashIn', 'wechatIn', 'alipayIn') GROUP BY user_id, shop_id ) f ON f.user_id = a.user_id AND f.shop_id = a.main_shop_id
|
||||
WHERE a.main_shop_id = #{shopId}
|
||||
|
||||
<if test="isVip != null">
|
||||
AND a.is_vip = #{isVip}
|
||||
</if>
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
package com.czg.service.market.service.impl;
|
||||
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.constants.ParamCodeCst;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.service.RedisService;
|
||||
import com.czg.system.service.SysParamsService;
|
||||
import com.ijpay.core.kit.RsaKit;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 微信支付service
|
||||
* @author Administrator
|
||||
@@ -28,24 +33,52 @@ public class AppWxServiceImpl extends BaseWx {
|
||||
config = new Config();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
@Override
|
||||
public String getAccessToken(boolean refresh) {
|
||||
init();
|
||||
Object token = redisService.get("wx:user:access_token");
|
||||
if (!refresh && token instanceof String) {
|
||||
return (String) token;
|
||||
}
|
||||
|
||||
String response = HttpUtil.get(WX_ACCESS_TOKEN_URL,
|
||||
Map.of("grant_type", "client_credential", "appid", config.appId, "secret", config.appSecret)
|
||||
);
|
||||
|
||||
log.info("获取access_token响应: {}", response);
|
||||
JSONObject jsonObject = JSONObject.parseObject(response);
|
||||
String accessToken = jsonObject.getString("access_token");
|
||||
if (accessToken == null) {
|
||||
throw new RuntimeException("获取access_token失败");
|
||||
}
|
||||
Long expiresIn = jsonObject.getLong("expires_in");
|
||||
if (expiresIn == null) {
|
||||
expiresIn = DEFAULT_EXPIRES_IN;
|
||||
}
|
||||
redisService.set("wx:user:access_token", accessToken, expiresIn - EXPIRES_OFFSET);
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() throws CzgException {
|
||||
// 用户小程序参数
|
||||
Map<String, String> userMiniKeyMap = paramsService.getParamsByMap("user_mini_key_set", ParamCodeCst.USER_MINI_KEY_SET);
|
||||
|
||||
// 微信支付参数
|
||||
Map<String, String> payKeyMap = paramsService.getParamsByMap("pay_key_set", ParamCodeCst.PAY_KEY_SET);
|
||||
|
||||
// 小程序id
|
||||
config.appId = paramsService.getSysParamValue(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID);
|
||||
log.info("小程序id:{}", config.appId);
|
||||
config.appId = userMiniKeyMap.get(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID);
|
||||
// 小程序secrete
|
||||
config.appSecret = paramsService.getSysParamValue(ParamCodeCst.Wechat.Mini.USER_WX_SECRETE);
|
||||
log.info("小程序secrete:{}", config.appSecret);
|
||||
config.appSecret = userMiniKeyMap.get(ParamCodeCst.Wechat.Mini.USER_WX_SECRETE);
|
||||
|
||||
config.certPath = "";
|
||||
// 微信支付公钥
|
||||
config.pubKey = paramsService.getSysParamValue(ParamCodeCst.Wechat.Pay.WX_PUB_KEY);
|
||||
log.info("微信支付公钥:{}", config.pubKey);
|
||||
config.pubKey = payKeyMap.get(ParamCodeCst.Wechat.Pay.WX_PUB_KEY);
|
||||
// api支付证书私钥
|
||||
config.apiCertKey = paramsService.getSysParamValue(ParamCodeCst.Wechat.Pay.WX_API_CLIENT_KEY);
|
||||
log.info("api支付证书私钥:{}", config.apiCertKey);
|
||||
config.apiCertKey = payKeyMap.get(ParamCodeCst.Wechat.Pay.WX_API_CLIENT_KEY);
|
||||
// api支付证书公钥
|
||||
config.apiCert = paramsService.getSysParamValue(ParamCodeCst.Wechat.Pay.WX_API_CLIENT_CERT);
|
||||
log.info("api支付证书公钥:{}", config.apiCert);
|
||||
config.apiCert = payKeyMap.get(ParamCodeCst.Wechat.Pay.WX_API_CLIENT_CERT);
|
||||
try {
|
||||
config.privateKey = RsaKit.loadPrivateKey(config.apiCertKey);
|
||||
} catch (Exception e) {
|
||||
@@ -56,18 +89,14 @@ public class AppWxServiceImpl extends BaseWx {
|
||||
// 平台证书编号
|
||||
config.platformCertNo = "";
|
||||
// 商户号
|
||||
config.mchId = paramsService.getSysParamValue(ParamCodeCst.Wechat.Pay.WX_MCH_ID);
|
||||
log.info("商户号:{}", config.mchId);
|
||||
config.mchId = payKeyMap.get(ParamCodeCst.Wechat.Pay.WX_MCH_ID);
|
||||
// v3密钥
|
||||
config.apiV3Key = paramsService.getSysParamValue(ParamCodeCst.Wechat.Pay.WX_V3_KEY);
|
||||
log.info("v3密钥:{}", config.apiV3Key);
|
||||
config.apiV3Key = payKeyMap.get(ParamCodeCst.Wechat.Pay.WX_V3_KEY);
|
||||
config.apiV2Key = "";
|
||||
// 回调地址
|
||||
config.notifyUrl = paramsService.getSysParamValue(ParamCodeCst.System.NATIVE_NOTIFY_URL) + "/wx/pay";
|
||||
log.info("回调地址:{}", config.notifyUrl);
|
||||
config.notifyUrl = payKeyMap.get(ParamCodeCst.System.NATIVE_NOTIFY_URL) + "/wx/pay";
|
||||
config.refundNotifyUrl = "";
|
||||
config.transferNotifyUrl = paramsService.getSysParamValue(ParamCodeCst.System.NATIVE_NOTIFY_URL) + "/wx/transfer";
|
||||
log.info("转账回调地址:{}", config.transferNotifyUrl);
|
||||
config.transferNotifyUrl = payKeyMap.get(ParamCodeCst.System.NATIVE_NOTIFY_URL) + "/wx/transfer";
|
||||
}
|
||||
|
||||
public BaseWx getAppService() {
|
||||
|
||||
@@ -5,6 +5,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.constants.ParamCodeCst;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.service.RedisService;
|
||||
import com.ijpay.core.IJPayHttpResponse;
|
||||
@@ -20,8 +21,7 @@ import com.ijpay.wxpay.enums.v3.BasePayApiEnum;
|
||||
import com.ijpay.wxpay.model.v3.*;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.Data;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -35,36 +35,49 @@ import java.security.cert.X509Certificate;
|
||||
import java.util.Base64;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 微信支付相关
|
||||
*
|
||||
* @author Administrator
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class BaseWx {
|
||||
public Config config;
|
||||
protected Config config;
|
||||
public RedisService redisService;
|
||||
public Logger log = LoggerFactory.getLogger(BaseWx.class);
|
||||
@Data
|
||||
public static class Config {
|
||||
public String appId;
|
||||
public String appSecret;
|
||||
public String certPath;
|
||||
public String pubKey;
|
||||
public String apiCertKey;
|
||||
public PrivateKey privateKey;
|
||||
public String apiCert;
|
||||
public String platformCertPath;
|
||||
public String platformCertNo;
|
||||
public String mchId;
|
||||
public String apiV3Key;
|
||||
public String apiV2Key;
|
||||
public String notifyUrl;
|
||||
public String refundNotifyUrl;
|
||||
public String transferNotifyUrl;
|
||||
}
|
||||
/**
|
||||
* 微信 AccessToken 接口地址
|
||||
*/
|
||||
protected static final String WX_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
|
||||
/**
|
||||
* AccessToken 默认过期时间(秒):微信官方默认7200秒
|
||||
*/
|
||||
protected static final Long DEFAULT_EXPIRES_IN = 7200L;
|
||||
/**
|
||||
* 缓存过期偏移量(秒):提前200秒过期,避免接口调用时刚好过期
|
||||
*/
|
||||
protected static final Long EXPIRES_OFFSET = 200L;
|
||||
|
||||
/**
|
||||
* 初始化配置信息
|
||||
*/
|
||||
protected abstract void init();
|
||||
|
||||
String getPhone(String code) {
|
||||
/**
|
||||
* 获取微信 AccessToken
|
||||
*
|
||||
* @param refresh 是否强制刷新(true=忽略缓存,重新获取;false=优先用缓存)
|
||||
* @return 有效的 AccessToken
|
||||
*/
|
||||
public abstract String getAccessToken(boolean refresh);
|
||||
|
||||
/**
|
||||
* 通过code 获取用户手机号
|
||||
*
|
||||
* @param code 微信code
|
||||
*/
|
||||
public String getPhone(String code) {
|
||||
String requestBody = JSONObject.toJSONString(Map.of("code", code));
|
||||
String response = HttpUtil.post("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + getAccessToken(false), requestBody);
|
||||
log.info("获取手机号响应: {}", response);
|
||||
@@ -79,129 +92,10 @@ public abstract class BaseWx {
|
||||
throw new RuntimeException("获取手机号失败");
|
||||
}
|
||||
|
||||
String getAccessToken(boolean refresh) {
|
||||
Object token = redisService.get("access_token");
|
||||
if (!refresh && token instanceof String) {
|
||||
return (String) token;
|
||||
}
|
||||
|
||||
String response = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/token",
|
||||
Map.of("grant_type", "client_credential", "appid", config.appId, "secret", config.appSecret)
|
||||
);
|
||||
|
||||
log.info("获取access_token响应: {}", response);
|
||||
JSONObject jsonObject = JSONObject.parseObject(response);
|
||||
String accessToken = jsonObject.getString("access_token");
|
||||
if (accessToken == null) {
|
||||
throw new RuntimeException("获取access_token失败");
|
||||
}
|
||||
Long expiresIn = jsonObject.getLong("expires_in");
|
||||
if (expiresIn == null) {
|
||||
expiresIn = 7200L;
|
||||
}
|
||||
redisService.set("access_token", accessToken, expiresIn - 200);
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用微信支付平台证书公钥加密敏感信息(OAEP)
|
||||
*/
|
||||
String encryptByPlatformCert(String content) {
|
||||
return PayKit.encryptData(content, config.pubKey);
|
||||
}
|
||||
|
||||
String getSerialNumberFromPem(String certContent) {
|
||||
try {
|
||||
// 去掉 PEM 头尾并清理空格换行
|
||||
String pem = certContent
|
||||
.replace("-----BEGIN CERTIFICATE-----", "")
|
||||
.replace("-----END CERTIFICATE-----", "")
|
||||
.replaceAll("\\s+", "");
|
||||
|
||||
// Base64 解码
|
||||
byte[] certBytes = Base64.getDecoder().decode(pem);
|
||||
|
||||
try (ByteArrayInputStream bis = new ByteArrayInputStream(certBytes)) {
|
||||
X509Certificate certificate = PayKit.getCertificate(bis);
|
||||
|
||||
if (certificate != null) {
|
||||
String serialNo = certificate.getSerialNumber()
|
||||
.toString(16)
|
||||
.toUpperCase(Locale.getDefault());
|
||||
|
||||
System.out.println("证书序列号:" + serialNo);
|
||||
|
||||
return serialNo;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("无效的证书", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getSerialNumber() {
|
||||
|
||||
try (var certStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(config.getCertPath())) {
|
||||
X509Certificate certificate = PayKit.getCertificate(certStream);
|
||||
if (certificate != null) {
|
||||
String serialNo = certificate.getSerialNumber().toString(16).toUpperCase(Locale.getDefault());
|
||||
boolean isValid = PayKit.checkCertificateIsValid(certificate, config.getMchId(), -2);
|
||||
log.info("证书是否可用 {} 证书有效期为 {}", isValid, certificate.getNotAfter());
|
||||
log.info("证书序列号: {}", serialNo);
|
||||
return serialNo;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("读取证书失败", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public JSONObject verifySignature(HttpServletRequest request) {
|
||||
try {
|
||||
log.info("开始校验签名并解密");
|
||||
String timestamp = request.getHeader("Wechatpay-Timestamp");
|
||||
String nonce = request.getHeader("Wechatpay-Nonce");
|
||||
String serialNo = request.getHeader("Wechatpay-Serial");
|
||||
String signature = request.getHeader("Wechatpay-Signature");
|
||||
String result = request.getReader().lines().reduce((a, b) -> a + b).orElse("");
|
||||
log.info("参数信息: timestamp: {}, nonce: {}, serialNo: {}, signature: {}, result: {}", timestamp, nonce, serialNo, signature, result);
|
||||
boolean b = WxPayKit.verifySignature(signature, result, nonce, timestamp, config.pubKey);
|
||||
if (!b) {
|
||||
throw new CzgException("验签失败");
|
||||
}
|
||||
JSONObject jsonObject = JSONObject.parseObject(result);
|
||||
JSONObject resource = jsonObject.getJSONObject("resource");
|
||||
String associatedData = resource.getString("associated_data");
|
||||
String ciphertext = resource.getString("ciphertext");
|
||||
String nonceStr = resource.getString("nonce");
|
||||
|
||||
String plainText = decryptToString(associatedData, nonceStr, ciphertext);
|
||||
log.info("充值支付通知明文 {}", plainText);
|
||||
return JSONObject.parseObject(plainText);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String decryptToString(String associatedData, String nonceStr, String ciphertext) {
|
||||
AesUtil aesUtil = new AesUtil(config.getApiV3Key().getBytes(StandardCharsets.UTF_8));
|
||||
try {
|
||||
return aesUtil.decryptToString(
|
||||
associatedData.getBytes(StandardCharsets.UTF_8),
|
||||
nonceStr.getBytes(StandardCharsets.UTF_8),
|
||||
ciphertext
|
||||
);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getOpenId(String code) {
|
||||
|
||||
public String getOpenId(String code) {
|
||||
init();
|
||||
String response = HttpUtil.get("https://api.weixin.qq.com/sns/jscode2session",
|
||||
Map.of("appid", config.getAppId() , "secret", config.getAppSecret(), "js_code", code, "grant_type", "authorization_code")
|
||||
Map.of("appid", config.getAppId(), "secret", config.getAppSecret(), "js_code", code, "grant_type", "authorization_code")
|
||||
);
|
||||
log.info("获取openId响应: {}", response);
|
||||
JSONObject jsonObject = JSONObject.parseObject(response);
|
||||
@@ -212,8 +106,8 @@ public abstract class BaseWx {
|
||||
throw new RuntimeException("获取openId失败");
|
||||
}
|
||||
|
||||
public Map<String, String> v3Pay(String openId, BigDecimal amount, String desc, String tradeNo, String type) {
|
||||
|
||||
public Map<String, String> v3Pay(String openId, BigDecimal amount, String desc, String tradeNo, String type) {
|
||||
init();
|
||||
if (desc == null) desc = "订单支付";
|
||||
UnifiedOrderModel model = new UnifiedOrderModel();
|
||||
model.setAppid(config.getAppId());
|
||||
@@ -254,8 +148,104 @@ public abstract class BaseWx {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用微信支付平台证书公钥加密敏感信息(OAEP)
|
||||
*/
|
||||
String encryptByPlatformCert(String content, String pubKey) {
|
||||
return PayKit.encryptData(content, pubKey);
|
||||
}
|
||||
|
||||
Map<String, String> v2Pay(String openId, BigDecimal amount, String desc, String tradeNo) {
|
||||
public JSONObject verifySignature(HttpServletRequest request) {
|
||||
try {
|
||||
init();
|
||||
log.info("开始校验签名并解密");
|
||||
String timestamp = request.getHeader("Wechatpay-Timestamp");
|
||||
String nonce = request.getHeader("Wechatpay-Nonce");
|
||||
String serialNo = request.getHeader("Wechatpay-Serial");
|
||||
String signature = request.getHeader("Wechatpay-Signature");
|
||||
String result = request.getReader().lines().reduce((a, b) -> a + b).orElse("");
|
||||
log.info("参数信息: timestamp: {}, nonce: {}, serialNo: {}, signature: {}, result: {}", timestamp, nonce, serialNo, signature, result);
|
||||
boolean b = WxPayKit.verifySignature(signature, result, nonce, timestamp, config.pubKey);
|
||||
if (!b) {
|
||||
throw new CzgException("验签失败");
|
||||
}
|
||||
JSONObject jsonObject = JSONObject.parseObject(result);
|
||||
JSONObject resource = jsonObject.getJSONObject("resource");
|
||||
String associatedData = resource.getString("associated_data");
|
||||
String ciphertext = resource.getString("ciphertext");
|
||||
String nonceStr = resource.getString("nonce");
|
||||
|
||||
String plainText = decryptToString(associatedData, nonceStr, ciphertext);
|
||||
log.info("充值支付通知明文 {}", plainText);
|
||||
return JSONObject.parseObject(plainText);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密
|
||||
*/
|
||||
public String decryptToString(String associatedData, String nonceStr, String ciphertext) {
|
||||
init();
|
||||
AesUtil aesUtil = new AesUtil(config.getApiV3Key().getBytes(StandardCharsets.UTF_8));
|
||||
try {
|
||||
return aesUtil.decryptToString(
|
||||
associatedData.getBytes(StandardCharsets.UTF_8),
|
||||
nonceStr.getBytes(StandardCharsets.UTF_8),
|
||||
ciphertext
|
||||
);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
String getSerialNumberFromPem(String certContent) {
|
||||
try {
|
||||
// 去掉 PEM 头尾并清理空格换行
|
||||
String pem = certContent
|
||||
.replace("-----BEGIN CERTIFICATE-----", "")
|
||||
.replace("-----END CERTIFICATE-----", "")
|
||||
.replaceAll("\\s+", "");
|
||||
|
||||
// Base64 解码
|
||||
byte[] certBytes = Base64.getDecoder().decode(pem);
|
||||
try (ByteArrayInputStream bis = new ByteArrayInputStream(certBytes)) {
|
||||
X509Certificate certificate = PayKit.getCertificate(bis);
|
||||
|
||||
if (certificate != null) {
|
||||
String serialNo = certificate.getSerialNumber()
|
||||
.toString(16)
|
||||
.toUpperCase(Locale.getDefault());
|
||||
return serialNo;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("无效的证书", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getSerialNumber(String certPath, String mchId) {
|
||||
|
||||
try (var certStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(certPath)) {
|
||||
X509Certificate certificate = PayKit.getCertificate(certStream);
|
||||
if (certificate != null) {
|
||||
String serialNo = certificate.getSerialNumber().toString(16).toUpperCase(Locale.getDefault());
|
||||
boolean isValid = PayKit.checkCertificateIsValid(certificate, mchId, -2);
|
||||
log.info("证书是否可用 {} 证书有效期为 {}", isValid, certificate.getNotAfter());
|
||||
log.info("证书序列号: {}", serialNo);
|
||||
return serialNo;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("读取证书失败", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Map<String, String> v2Pay(String openId, BigDecimal amount, String desc, String tradeNo) {
|
||||
|
||||
Map<String, String> payModel = com.ijpay.wxpay.model.UnifiedOrderModel.builder()
|
||||
.appid(config.appId)
|
||||
@@ -288,88 +278,11 @@ public abstract class BaseWx {
|
||||
return WxPayKit.prepayIdCreateSign(prepayId, config.appId, config.appSecret, SignType.MD5);
|
||||
}
|
||||
|
||||
|
||||
String refund(String tradeNo, String refundTradeNo, BigDecimal amount) {
|
||||
|
||||
int finalAmount = amount.multiply(new BigDecimal(100)).intValueExact();
|
||||
RefundModel model = new RefundModel();
|
||||
model.setOut_trade_no(tradeNo);
|
||||
model.setOut_refund_no(refundTradeNo);
|
||||
model.setAmount(new RefundAmount(finalAmount, "CNY", finalAmount));
|
||||
model.setNotify_url(config.refundNotifyUrl);
|
||||
|
||||
String info = JSONObject.toJSONString(model);
|
||||
log.info("统一退款参数: {}", info);
|
||||
IJPayHttpResponse response;
|
||||
try {
|
||||
response = WxPayApi.v3(
|
||||
RequestMethodEnum.POST,
|
||||
WxDomainEnum.CHINA.toString(),
|
||||
BasePayApiEnum.REFUND.toString(),
|
||||
config.mchId,
|
||||
getSerialNumber(),
|
||||
getSerialNumber(),
|
||||
config.apiCertKey,
|
||||
info
|
||||
);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
log.info("统一退款响应 {}", response);
|
||||
String body = response.getBody();
|
||||
JSONObject jsonObject = JSONObject.parseObject(body);
|
||||
if ("ABNORMAL".equals(jsonObject.getString("status")) || response.getStatus() != 200) {
|
||||
throw new CzgException("退款异常," + jsonObject.getString("message"));
|
||||
}
|
||||
return jsonObject.getString("refund_id");
|
||||
}
|
||||
|
||||
public String genCode(String path, String scene) {
|
||||
Map<String, Object> params = Map.of(
|
||||
"scene", scene,
|
||||
"page", path,
|
||||
"width", 430
|
||||
);
|
||||
var response = HttpRequest.post("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + getAccessToken(false))
|
||||
.body(JSONObject.toJSONString(params))
|
||||
.execute();
|
||||
|
||||
byte[] bodyBytes = response.bodyBytes();
|
||||
String str = new String(bodyBytes);
|
||||
if (str.contains("errmsg")) {
|
||||
JSONObject json = JSONObject.parseObject(str);
|
||||
throw new CzgException(json.getString("errmsg"));
|
||||
}
|
||||
return "data:image/png;base64," + Base64.getEncoder().encodeToString(bodyBytes);
|
||||
}
|
||||
public static X509Certificate loadCertificate(String certStr) throws Exception {
|
||||
// 去掉 PEM 头尾
|
||||
String pem = certStr
|
||||
.replace("-----BEGIN CERTIFICATE-----", "")
|
||||
.replace("-----END CERTIFICATE-----", "")
|
||||
.replaceAll("\\s+", "");
|
||||
|
||||
byte[] der = Base64.getDecoder().decode(pem);
|
||||
CertificateFactory factory = CertificateFactory.getInstance("X.509");
|
||||
return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(der));
|
||||
}
|
||||
|
||||
|
||||
public String rsaEncryptOAEP(String content) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, RsaKit.loadPublicKey(config.pubKey));
|
||||
byte[] dataByte = content.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] cipherData = cipher.doFinal(dataByte);
|
||||
return cn.hutool.core.codec.Base64.encode(cipherData);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public JSONObject transferBalance(String openId, String name, BigDecimal amount, String remarkTxt, String billNoTxt) {
|
||||
|
||||
/**
|
||||
* 提现
|
||||
*/
|
||||
public JSONObject transferBalance(String openId, String name, BigDecimal amount, String remarkTxt, String billNoTxt) {
|
||||
init();
|
||||
String remark = remarkTxt == null ? "佣金" : remarkTxt;
|
||||
String billNo = billNoTxt == null ? IdUtil.simpleUUID() : billNoTxt;
|
||||
Map<String, Object> params = new java.util.HashMap<>(Map.of(
|
||||
@@ -386,7 +299,7 @@ public abstract class BaseWx {
|
||||
}
|
||||
));
|
||||
if (amount.compareTo(BigDecimal.valueOf(0.3)) >= 0) {
|
||||
params.put("user_name", rsaEncryptOAEP(name));
|
||||
params.put("user_name", rsaEncryptOAEP(name, config.pubKey));
|
||||
}
|
||||
log.info("转账到零钱参数: {}", JSONObject.toJSONString(params));
|
||||
IJPayHttpResponse response = null;
|
||||
@@ -412,5 +325,102 @@ public abstract class BaseWx {
|
||||
return resp;
|
||||
}
|
||||
|
||||
String refund(String tradeNo, String refundTradeNo, BigDecimal amount) {
|
||||
init();
|
||||
int finalAmount = amount.multiply(new BigDecimal(100)).intValueExact();
|
||||
RefundModel model = new RefundModel();
|
||||
model.setOut_trade_no(tradeNo);
|
||||
model.setOut_refund_no(refundTradeNo);
|
||||
model.setAmount(new RefundAmount(finalAmount, "CNY", finalAmount));
|
||||
model.setNotify_url(config.refundNotifyUrl);
|
||||
|
||||
String info = JSONObject.toJSONString(model);
|
||||
log.info("统一退款参数: {}", info);
|
||||
IJPayHttpResponse response;
|
||||
try {
|
||||
response = WxPayApi.v3(
|
||||
RequestMethodEnum.POST,
|
||||
WxDomainEnum.CHINA.toString(),
|
||||
BasePayApiEnum.REFUND.toString(),
|
||||
config.mchId,
|
||||
getSerialNumber(config.getCertPath(), config.mchId),
|
||||
getSerialNumber(config.getCertPath(), config.mchId),
|
||||
config.apiCertKey,
|
||||
info
|
||||
);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
log.info("统一退款响应 {}", response);
|
||||
String body = response.getBody();
|
||||
JSONObject jsonObject = JSONObject.parseObject(body);
|
||||
if ("ABNORMAL".equals(jsonObject.getString("status")) || response.getStatus() != 200) {
|
||||
throw new CzgException("退款异常," + jsonObject.getString("message"));
|
||||
}
|
||||
return jsonObject.getString("refund_id");
|
||||
}
|
||||
|
||||
public String genCode(String path, String scene) {
|
||||
Map<String, Object> params = Map.of(
|
||||
"scene", scene,
|
||||
"page", path,
|
||||
"width", 430
|
||||
);
|
||||
var response = HttpRequest.post("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + getAccessToken(false))
|
||||
.body(JSONObject.toJSONString(params))
|
||||
.execute();
|
||||
|
||||
byte[] bodyBytes = response.bodyBytes();
|
||||
String str = new String(bodyBytes);
|
||||
if (str.contains("errmsg")) {
|
||||
JSONObject json = JSONObject.parseObject(str);
|
||||
throw new CzgException(json.getString("errmsg"));
|
||||
}
|
||||
return "data:image/png;base64," + Base64.getEncoder().encodeToString(bodyBytes);
|
||||
}
|
||||
|
||||
public static X509Certificate loadCertificate(String certStr) throws Exception {
|
||||
// 去掉 PEM 头尾
|
||||
String pem = certStr
|
||||
.replace("-----BEGIN CERTIFICATE-----", "")
|
||||
.replace("-----END CERTIFICATE-----", "")
|
||||
.replaceAll("\\s+", "");
|
||||
|
||||
byte[] der = Base64.getDecoder().decode(pem);
|
||||
CertificateFactory factory = CertificateFactory.getInstance("X.509");
|
||||
return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(der));
|
||||
}
|
||||
|
||||
|
||||
public String rsaEncryptOAEP(String content, String pubKey) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, RsaKit.loadPublicKey(pubKey));
|
||||
byte[] dataByte = content.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] cipherData = cipher.doFinal(dataByte);
|
||||
return cn.hutool.core.codec.Base64.encode(cipherData);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
protected static class Config {
|
||||
public String appId;
|
||||
public String appSecret;
|
||||
public String certPath;
|
||||
public String pubKey;
|
||||
public String apiCertKey;
|
||||
public PrivateKey privateKey;
|
||||
public String apiCert;
|
||||
public String platformCertPath;
|
||||
public String platformCertNo;
|
||||
public String mchId;
|
||||
public String apiV3Key;
|
||||
public String apiV2Key;
|
||||
public String notifyUrl;
|
||||
public String refundNotifyUrl;
|
||||
public String transferNotifyUrl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.czg.market.service.GbWareService;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.market.mapper.GbWareMapper;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import com.czg.utils.PageUtil;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
@@ -32,7 +33,7 @@ public class GbWareServiceImpl extends ServiceImpl<GbWareMapper, GbWare> impleme
|
||||
@Override
|
||||
public Page<GbWare> getGbWarePage(GbWareQueryParamDTO param, Long shopId, boolean isAdmin) {
|
||||
if (!isAdmin && !shopInfoService.checkSwitch(shopId, ShopSwitchTypeEnum.GROUP_BUY)) {
|
||||
return new Page<>();
|
||||
return PageUtil.emptyPage();
|
||||
}
|
||||
Long mainShopId = shopInfoService.getMainIdByShopId(shopId);
|
||||
QueryWrapper queryWrapper = new QueryWrapper();
|
||||
@@ -54,9 +55,7 @@ public class GbWareServiceImpl extends ServiceImpl<GbWareMapper, GbWare> impleme
|
||||
});
|
||||
Page<GbWare> page = page(Page.of(param.getPage(), param.getSize()), queryWrapper);
|
||||
if (!isAdmin) {
|
||||
page.getRecords().forEach(item -> {
|
||||
item.setShopId(shopId);
|
||||
});
|
||||
page.getRecords().forEach(item -> item.setShopId(shopId));
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ public class MkConsumeCashbackServiceImpl extends ServiceImpl<MkConsumeCashbackM
|
||||
shopUserService.updateMoney(new ShopUserMoneyEditDTO().setId(shopUser.getId()).setType(1)
|
||||
.setRelationId(mkConsumeCashbackRecord.getId()).setMoney(cashbackAmount).setBizEnum(ShopUserFlowBizEnum.CASHBACK)
|
||||
.setRemark(StrUtil.format("订单消费: {}, 返现: {}", amount, cashbackAmount)));
|
||||
log.info("订单返现 订单ID:{}, 店铺用户id: {}, 订单消费: {}, 返现: {}",orderId, shopUser.getId(), amount, cashbackAmount);
|
||||
log.info("订单返现 订单ID:{}, 店铺用户id: {}, 订单消费: {}, 返现: {}", orderId, shopUser.getId(), amount, cashbackAmount);
|
||||
|
||||
AcUserMsg msg = new AcUserMsg()
|
||||
.setUserId(userId)
|
||||
@@ -176,4 +176,45 @@ public class MkConsumeCashbackServiceImpl extends ServiceImpl<MkConsumeCashbackM
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void removeCashback(Long shopId, Long userId, Long orderId, String orderNo) {
|
||||
MkConsumeCashbackRecord record = consumeCashbackRecordService.getOne(query()
|
||||
.eq(MkConsumeCashbackRecord::getShopId, shopId)
|
||||
.eq(MkConsumeCashbackRecord::getUserId, userId)
|
||||
.eq(MkConsumeCashbackRecord::getOrderNo, orderNo)
|
||||
.eq(MkConsumeCashbackRecord::getOrderId, orderId));
|
||||
if (record == null) {
|
||||
return;
|
||||
}
|
||||
MkConsumeCashbackRecord mkConsumeCashbackRecord = new MkConsumeCashbackRecord()
|
||||
.setOrderNo(orderNo)
|
||||
.setOrderId(orderId)
|
||||
.setMainShopId(record.getMainShopId())
|
||||
.setShopId(shopId)
|
||||
.setAmount(BigDecimal.ZERO)
|
||||
.setCashbackAmount(record.getCashbackAmount().negate())
|
||||
.setUserId(userId)
|
||||
.setShopUserId(record.getShopUserId());
|
||||
consumeCashbackRecordService.save(mkConsumeCashbackRecord);
|
||||
shopUserService.updateMoney(new ShopUserMoneyEditDTO()
|
||||
.setId(record.getShopUserId())
|
||||
.setType(0)
|
||||
.setRelationId(mkConsumeCashbackRecord.getId())
|
||||
.setMoney(record.getCashbackAmount())
|
||||
.setBizEnum(ShopUserFlowBizEnum.CASHBACK_REFUND)
|
||||
.setRemark(StrUtil.format("订单退款,扣除返现: {}", record.getCashbackAmount())));
|
||||
log.info("订单退款扣除返现 订单ID:{}, 店铺用户id: {}, 扣除返现: {}", orderId, record.getShopUserId(), record.getCashbackAmount());
|
||||
|
||||
AcUserMsg msg = new AcUserMsg()
|
||||
.setUserId(userId)
|
||||
.setShopId(shopId)
|
||||
.setSourceId(orderId)
|
||||
.setSourceType("order")
|
||||
.setType("cash")
|
||||
.setTitle("订单退款,消费返现扣除")
|
||||
.setContent(StrUtil.format("返现扣除提醒: 订单退款扣除的{}元返现。订单编号:{}", record.getCashbackAmount(), orderNo));
|
||||
acUserMsgService.addUserMsg(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.czg.service.market.service.impl;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.exceptions.ValidateException;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.IdcardUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
@@ -234,7 +235,7 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
|
||||
|
||||
@Override
|
||||
@GlobalTransactional
|
||||
public void bindInviteUser(MkDistributionUserDTO param) {
|
||||
public void bindInviteUser(MkDistributionUserDTO param) throws CzgException, ValidateException {
|
||||
ShopUser shopUser = shopUserService.getById(param.getId());
|
||||
AssertUtil.isNull(shopUser, "店铺用户不存在");
|
||||
ShopUserInvite shopUserInvite = shopUserInviteService.getOneByShopIdAndShopUserId(param.getShopId(), shopUser.getId());
|
||||
@@ -611,7 +612,7 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
|
||||
if (count >= config.getRewardCount()) {
|
||||
log.info("分销员{}已达到奖励次数上限, 次数: {}", currentDistributionUser.getId(), config.getRewardCount());
|
||||
return;
|
||||
}else {
|
||||
} else {
|
||||
log.info("分销员奖励次数: {}", count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,4 +65,9 @@ public class MkPointsConfigServiceImpl extends ServiceImpl<MkPointsConfigMapper,
|
||||
mkPointsUserService.alterPoints(null, shopUser.getId(), orderInfo.getShopId(), PointsConstant.ADD,
|
||||
awardPoints.intValue(), orderInfo.getId(), StrUtil.format("消费¥{}送{}积分", payAmount, awardPoints.intValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeConsumeAwardPoints(Long shopId, Long userId, Long orderId, String orderNo) {
|
||||
mkPointsUserService.removePointByOrder(shopId, userId, orderId, orderNo, "订单退款扣除赠送积分");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -43,7 +42,7 @@ public class MkPointsGoodsServiceImpl extends ServiceImpl<MkPointsGoodsMapper, M
|
||||
public Page<MkPointsGoods> getPointsGoodsPage(BaseQueryParam param, Long shopId) {
|
||||
boolean exists = mkPointsConfigService.exists(query().eq(MkPointsConfig::getShopId, shopId).eq(MkPointsConfig::getEnablePointsMall, 1));
|
||||
if (!exists) {
|
||||
return new Page<>();
|
||||
return PageUtil.emptyPage();
|
||||
}
|
||||
Page<MkPointsGoods> page = page(Page.of(param.getPage(), param.getSize()),
|
||||
query()
|
||||
|
||||
@@ -31,11 +31,11 @@ public class MkPointsUserRecordServiceImpl extends ServiceImpl<MkPointsUserRecor
|
||||
@Override
|
||||
public Page<MkPointsUserRecord> pageByPointsUserId(Integer page, Integer size, Long mkPointsUserId) {
|
||||
if (mkPointsUserId == null) {
|
||||
return new Page<>();
|
||||
return PageUtil.emptyPage();
|
||||
}
|
||||
ShopInfo shopInfo = shopInfoService.getById(StpKit.USER.getShopId());
|
||||
if (shopInfo == null) {
|
||||
return new Page<>();
|
||||
return PageUtil.emptyPage();
|
||||
}
|
||||
Page<MkPointsUserRecord> pages = page(Page.of(page, size),
|
||||
query().eq(MkPointsUserRecord::getMkPointsUserId, mkPointsUserId).orderBy(MkPointsUserRecord::getCreateTime, false));
|
||||
@@ -46,7 +46,7 @@ public class MkPointsUserRecordServiceImpl extends ServiceImpl<MkPointsUserRecor
|
||||
@Override
|
||||
public Page<MkPointsUserRecord> getPointsUserRecord(Integer page, Integer size, Long mkPointsUserId) {
|
||||
if (mkPointsUserId == null) {
|
||||
return new Page<>();
|
||||
return PageUtil.emptyPage();
|
||||
}
|
||||
PageHelper.startPage(page, size);
|
||||
List<MkPointsUserRecord> record = mapper.getPointsUserRecord(mkPointsUserId);
|
||||
|
||||
@@ -17,11 +17,13 @@ import com.czg.market.service.MkPointsUserRecordService;
|
||||
import com.czg.market.service.MkPointsUserService;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.market.mapper.MkPointsUserMapper;
|
||||
import com.czg.utils.PageUtil;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -50,7 +52,7 @@ public class MkPointsUserServiceImpl extends ServiceImpl<MkPointsUserMapper, MkP
|
||||
if (StrUtil.isNotBlank(phone)) {
|
||||
ShopUser one = shopUserService.getOne(query().eq(ShopUser::getPhone, phone).eq(ShopUser::getMainShopId, mainIdByShopId));
|
||||
if (one == null) {
|
||||
return new Page<>();
|
||||
return PageUtil.emptyPage();
|
||||
}
|
||||
shopUserId = one.getId();
|
||||
}
|
||||
@@ -70,7 +72,7 @@ public class MkPointsUserServiceImpl extends ServiceImpl<MkPointsUserMapper, MkP
|
||||
|
||||
@Override
|
||||
public List<PointsShopListVO> pointsShopList(Long userId, String shopName) {
|
||||
return listAs(query().select(MkPointsUser::getId, MkPointsUser::getShopId).select(ShopInfo::getShopName, ShopInfo::getLogo, ShopInfo::getCoverImg)
|
||||
return listAs(query().select(MkPointsUser::getId, MkPointsUser::getShopId, MkPointsUser::getPointBalance).select(ShopInfo::getShopName, ShopInfo::getLogo, ShopInfo::getCoverImg)
|
||||
.eq(MkPointsUser::getUserId, userId).leftJoin(ShopInfo.class).on(MkPointsUser::getShopId, ShopInfo::getId),
|
||||
PointsShopListVO.class);
|
||||
}
|
||||
@@ -130,9 +132,6 @@ public class MkPointsUserServiceImpl extends ServiceImpl<MkPointsUserMapper, MkP
|
||||
break;
|
||||
case SUB:
|
||||
pointsUser.setPointBalance(pointsUser.getPointBalance() - points);
|
||||
if (pointsUser.getPointBalance() < 0) {
|
||||
throw new CzgException("积分操作失败,积分不足");
|
||||
}
|
||||
points = -points;
|
||||
break;
|
||||
default:
|
||||
@@ -169,4 +168,49 @@ public class MkPointsUserServiceImpl extends ServiceImpl<MkPointsUserMapper, MkP
|
||||
acUserMsgService.addUserMsg(msg);
|
||||
return record.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void removePointByOrder(Long shopId, Long userId, Long orderId, String orderNo, String reason) {
|
||||
MkPointsUser pointsUser = getPointsUser(shopId, null, userId);
|
||||
MkPointsUserRecord one = pointsUserRecordService.getOne(query()
|
||||
.eq(MkPointsUserRecord::getMkPointsUserId, pointsUser.getId())
|
||||
.eq(MkPointsUserRecord::getShopId, shopId)
|
||||
.eq(MkPointsUserRecord::getSourceId, orderId.toString())
|
||||
.eq(MkPointsUserRecord::getFloatType, PointsConstant.ADD.getValue())
|
||||
.orderBy(MkPointsUserRecord::getId, true)
|
||||
);
|
||||
if (one == null) {
|
||||
return;
|
||||
}
|
||||
Long floatPoints = Math.abs(one.getFloatPoints());
|
||||
pointsUser.setPointBalance(pointsUser.getPointBalance() - floatPoints);
|
||||
saveOrUpdate(pointsUser);
|
||||
|
||||
MkPointsUserRecord record = MkPointsUserRecord.builder()
|
||||
.mkPointsUserId(pointsUser.getId())
|
||||
.shopId(pointsUser.getShopId())
|
||||
.shopUserId(pointsUser.getShopUserId())
|
||||
.floatType(PointsConstant.SUB.getValue())
|
||||
.floatPoints(floatPoints)
|
||||
.balancePoints(pointsUser.getPointBalance())
|
||||
.sourceId(orderId.toString())
|
||||
.content(reason)
|
||||
.build();
|
||||
boolean save = pointsUserRecordService.save(record);
|
||||
if (!save) {
|
||||
throw new CzgException("积分操作失败,积分记录保存失败");
|
||||
}
|
||||
|
||||
AcUserMsg msg = new AcUserMsg()
|
||||
.setUserId(pointsUser.getUserId())
|
||||
.setShopId(shopId)
|
||||
.setSourceId(orderId)
|
||||
.setSourceType("order")
|
||||
.setType("points")
|
||||
.setReadStatus(0)
|
||||
.setTitle("积分扣除")
|
||||
.setContent(StrUtil.format("订单退款积分扣除提醒:{} 积分已扣除,订单号:{}!", floatPoints, orderNo));
|
||||
acUserMsgService.addUserMsg(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,13 +106,14 @@ public class MkShopConsumeDiscountRecordServiceImpl extends ServiceImpl<MkShopCo
|
||||
.eq(MkShopConsumeDiscountRecord::getIsUse, 1)
|
||||
.eq(MkShopConsumeDiscountRecord::getShopUserId, shopUser.getId()));
|
||||
boolean exists = orderInfoService.exists(new QueryWrapper().eq(OrderInfo::getUserId, shopUser.getUserId())
|
||||
.eq(OrderInfo::getShopId, shopUser.getSourceShopId()).eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode()));
|
||||
.eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode()));
|
||||
return !exists && discountRecord == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MkShopConsumeDiscountRecord getDiscount(Long shopId, Long userId, Long orderId) {
|
||||
ShopUser shopUser = shopUserService.getOne(new QueryWrapper().eq(ShopUser::getUserId, userId).eq(ShopUser::getSourceShopId, shopId));
|
||||
ShopUser shopUser = shopUserService.getUserInfo(shopId, userId);
|
||||
AssertUtil.isTrue(shopUser == null, "用户不存在");
|
||||
boolean newUser = isNewUser(shopUser, shopId);
|
||||
if (!newUser) {
|
||||
// throw new CzgException("新客立减仅新用户可用");
|
||||
|
||||
@@ -110,6 +110,17 @@ public class MkShopConsumerCouponServiceImpl extends ServiceImpl<MkShopConsumerC
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeConsumerCoupon(Long shopId, Long userId, Long orderId) {
|
||||
recordService.remove(query()
|
||||
.eq(MkShopCouponRecord::getShopId, shopId)
|
||||
.eq(MkShopCouponRecord::getUserId, userId)
|
||||
.eq(MkShopCouponRecord::getSourceFlowId, orderId)
|
||||
.eq(MkShopCouponRecord::getSource, "消费赠券")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MkShopConsumerCouponDTO getConsumerCouponById(Long id) {
|
||||
AssertUtil.isNull(id, "ID不能为空");
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.czg.market.enums.PointsConstant;
|
||||
import com.czg.market.service.*;
|
||||
import com.czg.market.vo.*;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import com.czg.utils.FunUtils;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import com.czg.market.entity.MkShopRecharge;
|
||||
@@ -45,6 +46,8 @@ public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper,
|
||||
@Resource
|
||||
private MkShopRechargeDetailService shopRechargeDetailService;
|
||||
@Resource
|
||||
private TbMemberConfigService memberConfigService;
|
||||
@Resource
|
||||
private ShopCouponService shopCouponService;
|
||||
@DubboReference
|
||||
private ShopUserService shopUserService;
|
||||
@@ -159,7 +162,8 @@ public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recharge(Long shopId, Long shopUserId, Long rechargeDetailId, BigDecimal amount, Long paymentId, String payType, ShopUserFlowBizEnum bizEnum) {
|
||||
public void recharge(Long shopId, Long shopUserId, Long rechargeDetailId, BigDecimal amount, Long paymentId,
|
||||
String payType, ShopUserFlowBizEnum bizEnum, boolean isNoJoin) {
|
||||
log.info("充值回调, 用户id: {}, 金额: {}, rechargeDetailId: {}", shopUserId, amount, rechargeDetailId);
|
||||
ShopUser shopUser = shopUserService.getById(shopUserId);
|
||||
ShopUserMoneyEditDTO shopUserMoneyEditDTO = new ShopUserMoneyEditDTO()
|
||||
@@ -168,7 +172,6 @@ public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper,
|
||||
.setBizEnum(bizEnum)
|
||||
.setRelationId(paymentId);
|
||||
|
||||
|
||||
// 标准充值
|
||||
if (rechargeDetailId != null) {
|
||||
MkShopRechargeDetail rechargeDetail = shopRechargeDetailService.getById(rechargeDetailId);
|
||||
@@ -195,10 +198,10 @@ public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper,
|
||||
return;
|
||||
}
|
||||
// try {
|
||||
shopCouponRecordService.grant(shopId, new MkRewardCouponDTO().setCouponId(item.getId())
|
||||
.setNum(item.getNum())
|
||||
.setUserId(shopUser.getUserId())
|
||||
.setShopId(shopId), "充值赠券");
|
||||
shopCouponRecordService.grant(shopId, new MkRewardCouponDTO().setCouponId(item.getId())
|
||||
.setNum(item.getNum())
|
||||
.setUserId(shopUser.getUserId())
|
||||
.setShopId(shopId), "充值赠券");
|
||||
// } catch (Exception e) {
|
||||
// log.warn("发放优惠券失败", e);
|
||||
// }
|
||||
@@ -209,7 +212,9 @@ public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper,
|
||||
shopUserMoneyEditDTO.setMoney(amount);
|
||||
}
|
||||
shopUserService.updateMoney(shopUserMoneyEditDTO);
|
||||
|
||||
if (isNoJoin) {
|
||||
FunUtils.transactionSafeRun(() -> memberConfigService.joinMemberByCondition(shopId, shopUser.getUserId(), shopUser));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,6 +15,8 @@ import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 套餐推广助力记录 服务层实现。
|
||||
*
|
||||
@@ -55,6 +57,11 @@ public class PpHelpRecordServiceImpl extends ServiceImpl<PpHelpRecordMapper, PpH
|
||||
remove(QueryWrapper.create().eq(PpHelpRecord::getOrderId, orderId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteByOrderIds(List<Long> orderIds) {
|
||||
remove(QueryWrapper.create().in(PpHelpRecord::getOrderId, orderIds));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<PpHelpRecordDTO> helpPage(PageQueryParam reqVo) {
|
||||
QueryWrapper wrapper = QueryWrapper.create().eq(PpHelpRecord::getOrderId, reqVo.getRecordId());
|
||||
|
||||
@@ -12,16 +12,20 @@ import com.czg.constants.SystemConstants;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.market.entity.PpPackage;
|
||||
import com.czg.market.entity.PpPackageOrder;
|
||||
import com.czg.market.service.PpHelpRecordService;
|
||||
import com.czg.market.service.PpPackageService;
|
||||
import com.czg.market.vo.PpPackagePageReqVo;
|
||||
import com.czg.market.vo.PpPackageVO;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.market.mapper.PpPackageMapper;
|
||||
import com.czg.service.market.mapper.PpPackageOrderMapper;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import com.czg.utils.PageUtil;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.core.update.UpdateChain;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
@@ -31,6 +35,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 套餐推广套餐 服务层实现。
|
||||
@@ -48,6 +53,12 @@ public class PpPackageServiceImpl extends ServiceImpl<PpPackageMapper, PpPackage
|
||||
@DubboReference
|
||||
private ShopConfigService shopConfigService;
|
||||
|
||||
@Resource
|
||||
private PpHelpRecordService ppHelpRecordService;
|
||||
|
||||
@Resource
|
||||
private PpPackageOrderMapper ppPackageOrderMapper;
|
||||
|
||||
@Override
|
||||
public Integer getPackagePromotionSwitch(Long shopId) {
|
||||
Integer isPackagePromotion = shopConfigService.getById(shopId).getIsPackagePromotion();
|
||||
@@ -158,7 +169,7 @@ public class PpPackageServiceImpl extends ServiceImpl<PpPackageMapper, PpPackage
|
||||
Integer promotionSwitch = getPackagePromotionSwitch(shopId);
|
||||
if (!isAdmin && SystemConstants.OneZero.ZERO == promotionSwitch) {
|
||||
log.info("没有开启套餐推广");
|
||||
return new Page<>();
|
||||
return PageUtil.emptyPage();
|
||||
}
|
||||
|
||||
Long mainShopId = shopInfoService.getMainIdByShopId(shopId);
|
||||
@@ -254,6 +265,18 @@ public class PpPackageServiceImpl extends ServiceImpl<PpPackageMapper, PpPackage
|
||||
}
|
||||
|
||||
public void cancelProgressingPackageOrder(Long shopId, Long packageId) {
|
||||
// 查询订单 id 集合,删除助力记录
|
||||
QueryWrapper wrapper = QueryWrapper.create();
|
||||
if (packageId != null && packageId > 0L) {
|
||||
wrapper.eq(PpPackageOrder::getPackageId, packageId);
|
||||
}
|
||||
wrapper.eq(PpPackageOrder::getShopId, shopId)
|
||||
.in(PpPackageOrder::getStatus, PpPackageConstants.OrderStatus.PROCESSING, PpPackageConstants.OrderStatus.TIMEOUT);
|
||||
List<PpPackageOrder> orderList = ppPackageOrderMapper.selectListByQuery(wrapper);
|
||||
if (orderList != null && !orderList.isEmpty()) {
|
||||
ppHelpRecordService.deleteByOrderIds(orderList.stream().map(PpPackageOrder::getId).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
UpdateChain<PpPackageOrder> update = UpdateChain.of(PpPackageOrder.class)
|
||||
.set(PpPackageOrder::getStatus, PpPackageConstants.OrderStatus.CANCEL)
|
||||
.set(PpPackageOrder::getCancelTime, LocalDateTime.now())
|
||||
@@ -262,7 +285,7 @@ public class PpPackageServiceImpl extends ServiceImpl<PpPackageMapper, PpPackage
|
||||
update.eq(PpPackageOrder::getPackageId, packageId);
|
||||
}
|
||||
update.eq(PpPackageOrder::getShopId, shopId)
|
||||
.eq(PpPackageOrder::getStatus, PpPackageConstants.OrderStatus.PROCESSING)
|
||||
.in(PpPackageOrder::getStatus, PpPackageConstants.OrderStatus.PROCESSING, PpPackageConstants.OrderStatus.TIMEOUT)
|
||||
.update();
|
||||
}
|
||||
|
||||
|
||||
@@ -310,7 +310,7 @@ public class ShopCouponServiceImpl extends ServiceImpl<ShopCouponMapper, ShopCou
|
||||
}
|
||||
return PageUtil.convert(new PageInfo<>(coupons));
|
||||
}
|
||||
return new Page<>();
|
||||
return PageUtil.emptyPage();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -11,7 +11,6 @@ import com.czg.account.entity.ShopUser;
|
||||
import com.czg.account.service.ShopConfigService;
|
||||
import com.czg.account.service.ShopInfoService;
|
||||
import com.czg.account.service.ShopUserService;
|
||||
import com.czg.account.service.UserInfoService;
|
||||
import com.czg.constant.TableValueConstant;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.market.dto.MemberConfigDTO;
|
||||
@@ -25,7 +24,6 @@ import com.czg.market.enums.PointsConstant;
|
||||
import com.czg.market.service.*;
|
||||
import com.czg.market.vo.*;
|
||||
import com.czg.order.entity.OrderInfo;
|
||||
import com.czg.order.entity.OrderPayment;
|
||||
import com.czg.order.service.OrderPaymentService;
|
||||
import com.czg.service.market.enums.OrderStatusEnums;
|
||||
import com.czg.service.market.mapper.TbMemberConfigMapper;
|
||||
@@ -59,8 +57,6 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
|
||||
@Resource
|
||||
private MemberLevelConfigService levelConfigService;
|
||||
@DubboReference
|
||||
private UserInfoService userInfoService;
|
||||
@DubboReference
|
||||
private ShopUserService shopUserService;
|
||||
@Resource
|
||||
private OrderInfoService orderInfoService;
|
||||
@@ -121,21 +117,21 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
|
||||
conditionMap.put("BIND_PHONE", StrUtil.isNotBlank(shopUserInfo.getPhone()));
|
||||
break;
|
||||
case "ORDER":
|
||||
conditionMap.put("ORDER", orderInfoService.count(new QueryWrapper().eq(OrderInfo::getShopId, shopUserInfo.getSourceShopId()).eq(OrderInfo::getUserId, shopUserInfo.getUserId())
|
||||
.notIn(OrderInfo::getStatus, OrderStatusEnums.UNPAID.getCode(), OrderStatusEnums.CANCELLED.getCode())) >= Integer.parseInt(item.getValue()));
|
||||
conditionMap.put("ORDER", orderInfoService.count(query().eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getUserId, shopUserInfo.getUserId())
|
||||
.eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode())) >= Integer.parseInt(item.getValue()));
|
||||
|
||||
break;
|
||||
case "COST_AMOUNT":
|
||||
conditionMap.put("COST_AMOUNT", orderInfoService.list(new QueryWrapper().eq(OrderInfo::getShopId, shopUserInfo.getSourceShopId()).eq(OrderInfo::getUserId, shopUserInfo.getUserId())
|
||||
.notIn(OrderInfo::getStatus, OrderStatusEnums.UNPAID.getCode(), OrderStatusEnums.CANCELLED.getCode()))
|
||||
.stream().map(OrderInfo::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(new BigDecimal(item.getValue())) >= 0);
|
||||
|
||||
conditionMap.put("COST_AMOUNT", orderInfoService.getOneAs(query()
|
||||
.select("IFNULL(sum(pay_amount), 0) as total_amount ")
|
||||
.eq(OrderInfo::getShopId, shopId)
|
||||
.eq(OrderInfo::getUserId, shopUserInfo.getUserId())
|
||||
.eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode()), BigDecimal.class)
|
||||
.compareTo(new BigDecimal(item.getValue())) >= 0);
|
||||
break;
|
||||
case "RECHARGE_AMOUNT":
|
||||
conditionMap.put("RECHARGE_AMOUNT", paymentService.list(new QueryWrapper().eq(OrderPayment::getShopId, shopUserInfo.getSourceShopId())
|
||||
.eq(OrderPayment::getSourceId, shopUserInfo.getId()).isNotNull(OrderPayment::getTradeNumber))
|
||||
.stream().map(OrderPayment::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(new BigDecimal(item.getValue())) >= 0);
|
||||
|
||||
conditionMap.put("RECHARGE_AMOUNT", paymentService.countMemberInAmount(shopId, shopUserInfo.getId())
|
||||
.compareTo(new BigDecimal(item.getValue())) >= 0);
|
||||
break;
|
||||
default:
|
||||
throw new CzgException("会员开通条件类型错误");
|
||||
@@ -199,7 +195,10 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
|
||||
memberConfig.setMemberPriceShopIdList(JSONObject.toJSONString(memberDTO.getMemberPriceShopIdList()));
|
||||
}
|
||||
|
||||
shopConfigService.editStatusByShopIdList(memberConfig.getShopId(), memberConfig.getIsOpen().intValue() == 1 && memberConfig.getIsMemberPrice() == 1 ? 1 : 0, false, "is_member_price",
|
||||
shopConfigService.editStatusByShopIdList(memberConfig.getShopId(),
|
||||
memberConfig.getIsOpen().intValue() == 1 && memberConfig.getIsMemberPrice() == 1 ? 1 : 0,
|
||||
false,
|
||||
"is_member_price",
|
||||
"ALL".equals(memberConfig.getMemberPriceShopType()) ? "all" : "part",
|
||||
StrUtil.isNotBlank(memberConfig.getMemberPriceShopIdList()) ? JSONArray.parseArray(memberConfig.getMemberPriceShopIdList()).toList(Long.class) : new ArrayList<>());
|
||||
|
||||
@@ -304,6 +303,7 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
|
||||
return false;
|
||||
}
|
||||
ShopUser upShopUser = new ShopUser();
|
||||
upShopUser.setId(shopUser.getId());
|
||||
if (shopUser.getExperience() == null) {
|
||||
upShopUser.setExperience(0L);
|
||||
}
|
||||
@@ -337,13 +337,11 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
|
||||
}
|
||||
|
||||
if (levelVO.getCycleRewardCouponList() != null && !levelVO.getCycleRewardCouponList().isEmpty()) {
|
||||
levelVO.getCycleRewardCouponList().forEach(item -> {
|
||||
shopCouponRecordService.grant(shopUser.getMainShopId(), new MkRewardCouponDTO().setCouponId(item.getCoupon().getId())
|
||||
.setNum(item.getNum())
|
||||
.setUserId(shopUser.getUserId())
|
||||
.setShopId(shopUser.getMainShopId()), "购买会员赠券");
|
||||
|
||||
});
|
||||
levelVO.getCycleRewardCouponList().forEach(item ->
|
||||
shopCouponRecordService.grant(shopUser.getMainShopId(), new MkRewardCouponDTO().setCouponId(item.getCoupon().getId())
|
||||
.setNum(item.getNum())
|
||||
.setUserId(shopUser.getUserId())
|
||||
.setShopId(shopUser.getMainShopId()), "购买会员赠券"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,16 +379,17 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean joinMemberByCondition(Long shopId, Long userId, ShopUser shopUser) {
|
||||
MemberConfigVO memberConfigVO = detail(shopId);
|
||||
if (!memberConfigVO.getIsOpen().equals(1L)) {
|
||||
log.info("超级会员未开启, 店铺id: {}", shopId);
|
||||
return false;
|
||||
}
|
||||
if (shopUser == null) {
|
||||
log.warn("用户不存在, 店铺id: {}, 用户id: {}", shopId, userId);
|
||||
return false;
|
||||
}
|
||||
if (shopUser.getStartTime() != null && shopUser.getEndTime() != null && DateUtil.isIn(DateUtil.date(), DateUtil.date(shopUser.getStartTime()), DateUtil.date(shopUser.getEndTime()))) {
|
||||
if (shopUser.getIsVip() == 1 && shopUser.getStartTime() != null && shopUser.getEndTime() != null &&
|
||||
DateUtil.isIn(DateUtil.date(), DateUtil.date(shopUser.getStartTime()), DateUtil.date(shopUser.getEndTime()))) {
|
||||
return false;
|
||||
}
|
||||
MemberConfigVO memberConfigVO = detail(shopId);
|
||||
if (!memberConfigVO.getIsOpen().equals(1L)) {
|
||||
log.info("超级会员未开启, 店铺id: {}", shopId);
|
||||
return false;
|
||||
}
|
||||
MemberLevelConfig levelConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId).orderBy(MemberLevelConfig::getExperienceValue, true).limit(1));
|
||||
@@ -411,16 +410,14 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
|
||||
boolean canOpen = switch (item.getCode()) {
|
||||
case "BIND_PHONE" -> StrUtil.isNotBlank(shopUser.getPhone());
|
||||
case "ORDER" ->
|
||||
orderInfoService.count(new QueryWrapper().eq(OrderInfo::getShopId, shopUser.getSourceShopId()).eq(OrderInfo::getUserId, shopUser.getUserId())
|
||||
.notIn(OrderInfo::getStatus, OrderStatusEnums.UNPAID.getCode(), OrderStatusEnums.CANCELLED.getCode())) >= Integer.parseInt(item.getValue());
|
||||
orderInfoService.count(query().eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getUserId, shopUser.getUserId())
|
||||
.eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode())) >= Integer.parseInt(item.getValue());
|
||||
case "COST_AMOUNT" ->
|
||||
orderInfoService.list(new QueryWrapper().eq(OrderInfo::getShopId, shopUser.getSourceShopId()).eq(OrderInfo::getUserId, shopUser.getUserId())
|
||||
.notIn(OrderInfo::getStatus, OrderStatusEnums.UNPAID.getCode(), OrderStatusEnums.CANCELLED.getCode()))
|
||||
.stream().map(OrderInfo::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(new BigDecimal(item.getValue())) >= 0;
|
||||
case "RECHARGE_AMOUNT" ->
|
||||
paymentService.list(new QueryWrapper().eq(OrderPayment::getShopId, shopUser.getSourceShopId())
|
||||
.eq(OrderPayment::getSourceId, shopUser.getId()).isNotNull(OrderPayment::getTradeNumber))
|
||||
.stream().map(OrderPayment::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(new BigDecimal(item.getValue())) >= 0;
|
||||
orderInfoService.getOneAs(query().select("IFNULL(sum(pay_amount), 0) as total_amount").eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getUserId, shopUser.getUserId())
|
||||
.eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode()), BigDecimal.class)
|
||||
.compareTo(new BigDecimal(item.getValue())) >= 0;
|
||||
case "RECHARGE_AMOUNT" -> paymentService.countMemberInAmount(shopId, shopUser.getId())
|
||||
.compareTo(new BigDecimal(item.getValue())) >= 0;
|
||||
default -> throw new CzgException("会员开通条件类型错误");
|
||||
};
|
||||
if (!canOpen) {
|
||||
@@ -431,10 +428,12 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
|
||||
ShopUser upShopUser = new ShopUser();
|
||||
upShopUser.setId(shopUser.getId());
|
||||
upShopUser.setMemberLevelId(levelConfig.getId());
|
||||
upShopUser.setStartTime(DateUtil.date().toLocalDateTime());
|
||||
|
||||
upShopUser.setEndTime(shopUser.getStartTime().plusDays(20000));
|
||||
upShopUser.setStartTime(LocalDateTime.now());
|
||||
upShopUser.setEndTime(upShopUser.getStartTime().plusDays(20000));
|
||||
upShopUser.setIsVip(1);
|
||||
if (shopUser.getJoinTime() != null) {
|
||||
upShopUser.setJoinTime(LocalDateTime.now());
|
||||
}
|
||||
upShopUser.setOpenType("CONDITION");
|
||||
return shopUserService.updateById(upShopUser);
|
||||
}
|
||||
@@ -557,20 +556,27 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
|
||||
@Override
|
||||
@Transactional
|
||||
public MemberDetailVO getUserDetail(Long userId, Long shopId) {
|
||||
Long mainIdByShopId = shopInfoService.getMainIdByShopId(shopId);
|
||||
ShopInfo shopInfo = shopInfoService.getById(shopId);
|
||||
Long mainIdByShopId = shopInfo.getMainId() == null ? shopId : shopInfo.getMainId();
|
||||
ShopUser shopUser = shopUserService.getOne(new QueryWrapper().eq(ShopUser::getUserId, userId).eq(ShopUser::getMainShopId, mainIdByShopId));
|
||||
MemberLevelVO levelVO = null;
|
||||
if (shopUser.getMemberLevelId() != null) {
|
||||
levelVO = levelConfigService.detail(shopUser.getMemberLevelId());
|
||||
}
|
||||
TbMemberConfig memberConfig = getOne(new QueryWrapper().eq(TbMemberConfig::getShopId, shopId));
|
||||
if ("CONDITION".equals(memberConfig.getOpenType())) {
|
||||
joinMemberByCondition(shopId, userId, shopUser);
|
||||
MemberConfigVO memberConfig = detail(shopId);
|
||||
long nextLevelExperience = 0;
|
||||
if (memberConfig != null && memberConfig.getIsOpen() == 1) {
|
||||
if ("CONDITION".equals(memberConfig.getOpenType())) {
|
||||
joinMemberByCondition(shopId, userId, shopUser);
|
||||
}
|
||||
MemberLevelConfig nextLevel = levelConfigService.getOne(new QueryWrapper()
|
||||
.eq(MemberLevelConfig::getShopId, mainIdByShopId)
|
||||
.ge(MemberLevelConfig::getExperienceValue, shopUser.getExperience())
|
||||
.ne(MemberLevelConfig::getId, shopUser.getMemberLevelId()).orderBy(MemberLevelConfig::getExperienceValue, true));
|
||||
if (nextLevel != null) {
|
||||
nextLevelExperience = nextLevel.getExperienceValue() - shopUser.getExperience();
|
||||
}
|
||||
}
|
||||
|
||||
ShopInfo shopInfo = shopInfoService.getById(shopUser.getSourceShopId());
|
||||
MemberLevelConfig nextLevel = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId).ge(MemberLevelConfig::getExperienceValue, shopUser.getExperience())
|
||||
.ne(MemberLevelConfig::getId, shopUser.getMemberLevelId()).orderBy(MemberLevelConfig::getExperienceValue, true));
|
||||
return new MemberDetailVO()
|
||||
.setMemberCircleName(shopUser.getMemberCircleName())
|
||||
.setMemberCircleReward(shopUser.getMemberCircleReward())
|
||||
@@ -579,6 +585,6 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
|
||||
.setMemberLevel(levelVO)
|
||||
.setExperience(shopUser.getExperience())
|
||||
.setEndTime(shopUser.getEndTime())
|
||||
.setNextExperienceValue(nextLevel == null ? 0 : nextLevel.getExperienceValue() - shopUser.getExperience());
|
||||
.setNextExperienceValue(nextLevelExperience);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
package com.czg.service.market.service.impl;
|
||||
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.constants.ParamCodeCst;
|
||||
import com.czg.service.RedisService;
|
||||
import com.czg.system.service.SysParamsService;
|
||||
import com.ijpay.core.kit.RsaKit;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* 微信支付service
|
||||
*
|
||||
* @author Administrator
|
||||
*/
|
||||
@Component
|
||||
@@ -24,27 +27,59 @@ public class WxServiceImpl extends BaseWx {
|
||||
@DubboReference
|
||||
private SysParamsService paramsService;
|
||||
|
||||
private final Set<String> shopMiniKeys = Set.of(ParamCodeCst.Wechat.Mini.SHOP_WX_APP_ID, ParamCodeCst.Wechat.Mini.SHOP_WX_SECRETE);
|
||||
|
||||
|
||||
public WxServiceImpl(@Autowired RedisService redisService) {
|
||||
this.redisService = redisService;
|
||||
config = new Config();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
@Override
|
||||
public String getAccessToken(boolean refresh) {
|
||||
init();
|
||||
Object token = redisService.get("wx:shop:access_token");
|
||||
if (!refresh && token instanceof String) {
|
||||
return (String) token;
|
||||
}
|
||||
|
||||
String response = HttpUtil.get(WX_ACCESS_TOKEN_URL,
|
||||
Map.of("grant_type", "client_credential", "appid", config.appId, "secret", config.appSecret)
|
||||
);
|
||||
|
||||
log.info("获取access_token响应: {}", response);
|
||||
JSONObject jsonObject = JSONObject.parseObject(response);
|
||||
String accessToken = jsonObject.getString("access_token");
|
||||
if (accessToken == null) {
|
||||
throw new RuntimeException("获取access_token失败");
|
||||
}
|
||||
Long expiresIn = jsonObject.getLong("expires_in");
|
||||
if (expiresIn == null) {
|
||||
expiresIn = DEFAULT_EXPIRES_IN;
|
||||
}
|
||||
redisService.set("wx:shop:access_token", accessToken, expiresIn - EXPIRES_OFFSET);
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
// 商户小程序参数
|
||||
Map<String, String> shopMiniKeyMap = paramsService.getParamsByMap("shop_mini_key_set", ParamCodeCst.SHOP_MINI_KEY_SET);
|
||||
|
||||
// 小程序id
|
||||
config.appId = paramsService.getSysParamValue(ParamCodeCst.Wechat.Mini.SHOP_WX_APP_ID);
|
||||
config.appId = shopMiniKeyMap.get(ParamCodeCst.Wechat.Mini.SHOP_WX_APP_ID);
|
||||
// 小程序secrete
|
||||
config.appSecret = paramsService.getSysParamValue(ParamCodeCst.Wechat.Mini.SHOP_WX_SECRETE);
|
||||
|
||||
config.appSecret = shopMiniKeyMap.get(ParamCodeCst.Wechat.Mini.SHOP_WX_SECRETE);
|
||||
|
||||
// 微信支付参数
|
||||
Map<String, String> payKeyMap = paramsService.getParamsByMap("pay_key_set", ParamCodeCst.PAY_KEY_SET);
|
||||
config.certPath = "";
|
||||
// 微信支付公钥
|
||||
config.pubKey = paramsService.getSysParamValue(ParamCodeCst.Wechat.Pay.WX_PUB_KEY);
|
||||
config.pubKey = payKeyMap.get(ParamCodeCst.Wechat.Pay.WX_PUB_KEY);
|
||||
// api支付证书私钥
|
||||
config.apiCertKey = paramsService.getSysParamValue(ParamCodeCst.Wechat.Pay.WX_API_CLIENT_KEY);
|
||||
config.apiCertKey = payKeyMap.get(ParamCodeCst.Wechat.Pay.WX_API_CLIENT_KEY);
|
||||
// api支付证书公钥
|
||||
config.apiCert = paramsService.getSysParamValue(ParamCodeCst.Wechat.Pay.WX_API_CLIENT_CERT);
|
||||
config.apiCert = payKeyMap.get(ParamCodeCst.Wechat.Pay.WX_API_CLIENT_CERT);
|
||||
try {
|
||||
config.privateKey = RsaKit.loadPrivateKey(config.apiCertKey);
|
||||
} catch (Exception e) {
|
||||
@@ -55,14 +90,14 @@ public class WxServiceImpl extends BaseWx {
|
||||
// 平台证书编号
|
||||
config.platformCertNo = "";
|
||||
// 商户号
|
||||
config.mchId = paramsService.getSysParamValue(ParamCodeCst.Wechat.Pay.WX_MCH_ID);
|
||||
config.mchId = payKeyMap.get(ParamCodeCst.Wechat.Pay.WX_MCH_ID);
|
||||
// v3密钥
|
||||
config.apiV3Key = paramsService.getSysParamValue(ParamCodeCst.Wechat.Pay.WX_V3_KEY);
|
||||
config.apiV3Key = payKeyMap.get(ParamCodeCst.Wechat.Pay.WX_V3_KEY);
|
||||
config.apiV2Key = "";
|
||||
// 回调地址
|
||||
config.notifyUrl = paramsService.getSysParamValue(ParamCodeCst.System.NATIVE_NOTIFY_URL) + "/wx/pay";
|
||||
config.notifyUrl = payKeyMap.get(ParamCodeCst.System.NATIVE_NOTIFY_URL) + "/wx/pay";
|
||||
config.refundNotifyUrl = "";
|
||||
config.transferNotifyUrl = paramsService.getSysParamValue(ParamCodeCst.System.NATIVE_NOTIFY_URL) + "/wx/transfer";
|
||||
config.transferNotifyUrl = payKeyMap.get(ParamCodeCst.System.NATIVE_NOTIFY_URL) + "/wx/transfer";
|
||||
}
|
||||
|
||||
public BaseWx getAppService() {
|
||||
|
||||
@@ -15,13 +15,16 @@
|
||||
left join tb_shop_info s on o.shop_id = s.id
|
||||
left join pp_package p on o.package_id = p.id
|
||||
left join tb_user_info u on o.user_id = u.id
|
||||
where 1=1
|
||||
<if test="shopId != null">
|
||||
and o.shop_id = #{shopId}
|
||||
</if>
|
||||
<if test="userId != null">
|
||||
and o.user_id = #{userId} and o.status != 'ing'
|
||||
</if>
|
||||
where o.shop_id = #{shopId}
|
||||
<choose>
|
||||
<!-- userId为空时:拼接 and o.status != 'ing' -->
|
||||
<when test="userId == null or userId == ''">
|
||||
and o.status != 'ing'
|
||||
</when>
|
||||
<otherwise>
|
||||
and o.user_id = #{userId}
|
||||
</otherwise>
|
||||
</choose>
|
||||
<if test="param.orderNo != null">
|
||||
and o.order_no = #{param.orderNo}
|
||||
</if>
|
||||
|
||||
@@ -151,7 +151,9 @@ public class GbOrderServiceImpl extends ServiceImpl<GbOrderMapper, GbOrder> impl
|
||||
q.eq(GbOrderDetail::getStatus, "待成团").or(GbOrderDetail::getStatus).eq("退款中");
|
||||
});
|
||||
queryWrapper1.eq(GbOrderDetail::getGroupOrderNo, ing.getGroupOrderNo());
|
||||
queryWrapper1.eq(GbOrderDetail::getUserId, userId);
|
||||
if (userId != null) {
|
||||
queryWrapper1.eq(GbOrderDetail::getUserId, userId);
|
||||
}
|
||||
boolean exists = detailService.exists(queryWrapper1);
|
||||
if (exists) {
|
||||
continue;
|
||||
|
||||
@@ -162,7 +162,7 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
|
||||
.like(OrderDetail::getProductName, productName);
|
||||
like = orderDetailService.listAs(queryWrapper, Long.class);
|
||||
if (CollUtil.isEmpty(like)) {
|
||||
return new Page<>();
|
||||
return PageUtil.emptyPage();
|
||||
}
|
||||
}
|
||||
QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
|
||||
@@ -1060,8 +1060,7 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
|
||||
distributionUserService.costUpgradeLevelBefore(orderInfo.getUserId(), orderInfo.getShopId());
|
||||
// 分销奖励
|
||||
distributionUserService.distribute(orderInfo.getId(), orderInfo.getOrderNo(), payment.getAmount(), orderInfo.getUserId(), orderInfo.getShopId(), "order");
|
||||
}
|
||||
else if (PayTypeConstants.SourceType.MEMBER_IN.equals(payment.getSourceType()) || PayTypeConstants.SourceType.FREE.equals(payment.getSourceType())) {
|
||||
} else if (PayTypeConstants.SourceType.MEMBER_IN.equals(payment.getSourceType()) || PayTypeConstants.SourceType.FREE.equals(payment.getSourceType())) {
|
||||
boolean isFree = PayTypeConstants.SourceType.FREE.equals(payment.getSourceType());
|
||||
ShopUser shopUser = shopUserService.getById(payment.getSourceId());
|
||||
OrderInfo orderInfo = null;
|
||||
@@ -1089,99 +1088,41 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
|
||||
.setRelationId(orderInfo.getId())
|
||||
.setMoney(BigDecimal.valueOf(czgCallBackDto.getAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN));
|
||||
shopUserService.updateMoney(shopUserMoneyEditDTO);
|
||||
OrderInfo orderInfo1 = new OrderInfo();
|
||||
orderInfo1.setId(orderInfo.getId());
|
||||
orderInfo1.setIsFreeDine(1);
|
||||
orderInfo1.setStatus(OrderStatusEnums.DONE.getCode());
|
||||
orderInfo1.setPayAmount(BigDecimal.ZERO);
|
||||
orderInfo1.setPaidTime(LocalDateTime.now());
|
||||
orderInfo1.setPayType(PayEnums.FREE_PAY.getValue());
|
||||
orderInfoService.updateById(orderInfo1);
|
||||
orderDetailService.updateOrderDetailStatus(orderInfo.getId(), OrderStatusEnums.DONE.getCode());
|
||||
redisService.del(RedisCst.classKeyExpired.EXPIRED_ORDER + orderInfo.getId());
|
||||
upOrderInfo(orderInfo, BigDecimal.ZERO,
|
||||
LocalDateTime.now(), null, PayEnums.FREE_PAY);
|
||||
}
|
||||
} else {
|
||||
shopRechargeService.recharge(payment.getShopId(), payment.getSourceId(), payment.getRelatedId(),
|
||||
BigDecimal.valueOf(czgCallBackDto.getAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN), payment.getId(), payment.getSourceType(), bizEnum);
|
||||
//充值并支付 ↓
|
||||
orderInfo = orderInfoService.getOne(new QueryWrapper()
|
||||
.eq(OrderInfo::getPayOrderId, payment.getId())
|
||||
.eq(OrderInfo::getPayType, PayEnums.VIP_PAY.getValue()));
|
||||
if (orderInfo != null) {
|
||||
OrderInfo upOrderInfo = new OrderInfo()
|
||||
.setId(orderInfo.getId())
|
||||
.setPayType(PayEnums.VIP_PAY.getValue())
|
||||
.setPaidTime(LocalDateTime.now())
|
||||
.setPayAmount(orderInfo.getOrderAmount())
|
||||
.setStatus(OrderStatusEnums.DONE.getCode());
|
||||
orderInfoService.updateById(upOrderInfo);
|
||||
orderDetailService.updateOrderDetailStatus(orderInfo.getId(), OrderStatusEnums.DONE.getCode());
|
||||
ShopUserMoneyEditDTO shopUserMoneyEditDTO = new ShopUserMoneyEditDTO()
|
||||
.setId(shopUser.getId())
|
||||
.setType(0)
|
||||
.setBizEnum(ShopUserFlowBizEnum.ORDER_PAY)
|
||||
.setRelationId(orderInfo.getId())
|
||||
.setMoney(orderInfo.getOrderAmount());
|
||||
|
||||
shopUserService.updateMoney(shopUserMoneyEditDTO);
|
||||
redisService.del(RedisCst.classKeyExpired.EXPIRED_ORDER + orderInfo.getId());
|
||||
|
||||
// 发放成长值
|
||||
shopUser = shopUserService.getById(shopUser);
|
||||
//充值
|
||||
memberConfigService.deliver(shopUser,
|
||||
TableValueConstant.MemberExpFlow.Type.RECHARGE,
|
||||
BigDecimal.valueOf(czgCallBackDto.getAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN), null, orderInfo.getId());
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
OrderInfo finalOrderInfo = orderInfo;
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||
@Override
|
||||
public void afterCommit() {
|
||||
// 事务成功提交后执行消息发送
|
||||
String printParam = finalOrderInfo.getId() + "_" + (!"after-pay".equals(finalOrderInfo.getPayMode()) ? 1 : 0) + "_1";
|
||||
rabbitPublisher.sendOrderPrintMsg(printParam, finalOrderInfo.getIsPrint() == 1);
|
||||
// log.info("订单{}事务提交后,发送打印消息", orderId);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 非事务环境下直接发送(兼容无事务场景)
|
||||
String printParam = orderInfo.getId() + "_" + (!"after-pay".equals(orderInfo.getPayMode()) ? 1 : 0) + "_1";
|
||||
rabbitPublisher.sendOrderPrintMsg(printParam, orderInfo.getIsPrint() == 1);
|
||||
// log.info("非事务环境下,直接发送订单{}打印消息", orderId);
|
||||
}
|
||||
upOrderInfo(orderInfo, orderInfo.getOrderAmount(),
|
||||
LocalDateTime.now(), null, PayEnums.VIP_PAY);
|
||||
}
|
||||
shopRechargeService.recharge(payment.getShopId(), payment.getSourceId(), payment.getRelatedId(),
|
||||
BigDecimal.valueOf(czgCallBackDto.getAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN),
|
||||
payment.getId(), payment.getSourceType(), bizEnum, orderInfo == null);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 分销奖励
|
||||
// if (shopUser != null) {
|
||||
// distributionUserService.distribute(payment.getId(), payment.getOrderNo(), payment.getAmount(), shopUser.getUserId(), payment.getShopId(), "recharge");
|
||||
// }
|
||||
// if (orderInfo != null) {
|
||||
// distributionUserService.distribute(payment.getId(), payment.getOrderNo(), payment.getAmount(), orderInfo.getUserId(), payment.getShopId(), "recharge");
|
||||
// }
|
||||
}
|
||||
else if (PayTypeConstants.SourceType.MEMBER_PAY.equals(payment.getSourceType())) {
|
||||
} else if (PayTypeConstants.SourceType.MEMBER_PAY.equals(payment.getSourceType())) {
|
||||
//购买会员
|
||||
ShopUser shopUser = shopUserService.getById(payment.getSourceId());
|
||||
memberConfigService.joinMember(payment.getShopId(), shopUser.getUserId(), payment.getRelatedId());
|
||||
// 充值赠送积分
|
||||
// memberConfigService.deliver(shopUser.getMainShopId(), shopUser.getUserId(), TableValueConstant.MemberExpFlow.Type.COST, payment.getAmount(), null, payment.getId());
|
||||
|
||||
// 分销员开通
|
||||
}
|
||||
else if (PayTypeConstants.SourceType.DISTRIBUTION.equals(payment.getSourceType())) {
|
||||
} else if (PayTypeConstants.SourceType.DISTRIBUTION.equals(payment.getSourceType())) {
|
||||
distributionUserService.open(payment.getSourceId(), payment.getAmount(), payment.getShopId(), payment.getId());
|
||||
}
|
||||
else if (PayTypeConstants.SourceType.POINT.equals(payment.getSourceType())) {
|
||||
} else if (PayTypeConstants.SourceType.POINT.equals(payment.getSourceType())) {
|
||||
goodPayService.payCallBack(payment.getSourceId(), payment.getId());
|
||||
}
|
||||
else if (PayTypeConstants.SourceType.WARE.equals(payment.getSourceType())) {
|
||||
} else if (PayTypeConstants.SourceType.WARE.equals(payment.getSourceType())) {
|
||||
gbOrderService.payCallBack(payment.getSourceId(), payment.getId());
|
||||
}
|
||||
else if (PayTypeConstants.SourceType.PP.equals(payment.getSourceType())) {
|
||||
} else if (PayTypeConstants.SourceType.PP.equals(payment.getSourceType())) {
|
||||
ppPackageOrderService.paySuccess(payment.getSourceId(), payment.getId());
|
||||
}
|
||||
}
|
||||
@@ -1306,14 +1247,14 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
|
||||
shopUserUseInfo(orderInfo, shopUser);
|
||||
// 后续 赠送等功能 挂账支付不赠送
|
||||
if (!orderInfo.getPayType().equals(PayEnums.CREDIT_PAY.getValue())) {
|
||||
FunUtils.safeRunVoid(() -> consumerCouponService.receiveConsumerCoupon(shopUser.getSourceShopId(), orderInfo.getId(),
|
||||
orderInfo.getPayAmount(), shopUser.getUserId(), shopUser.getId()), "订单{}消费赠券失败", orderInfo.getId());
|
||||
FunUtils.safeRunVoid(() -> pointsConfigService.consumeAwardPoints(shopUser, orderInfo), "订单{}赠送积分失败", orderInfo.getId());
|
||||
|
||||
FunUtils.safeRunVoid(() -> consumeCashbackService.cashback(orderInfo.getShopId(), shopUser.getUserId(),
|
||||
orderInfo.getPayAmount(), orderInfo.getId(), orderInfo.getOrderNo()), "订单{}消费返现失败", orderInfo.getId());
|
||||
|
||||
if (!orderInfo.getPayType().equals(PayEnums.FREE_PAY.getValue())) {
|
||||
FunUtils.safeRunVoid(() -> consumerCouponService.receiveConsumerCoupon(shopUser.getSourceShopId(), orderInfo.getId(),
|
||||
orderInfo.getPayAmount(), shopUser.getUserId(), shopUser.getId()), "订单{}消费赠券失败", orderInfo.getId());
|
||||
FunUtils.safeRunVoid(() -> pointsConfigService.consumeAwardPoints(shopUser, orderInfo), "订单{}赠送积分失败", orderInfo.getId());
|
||||
|
||||
FunUtils.safeRunVoid(() -> consumeCashbackService.cashback(orderInfo.getShopId(), shopUser.getUserId(),
|
||||
orderInfo.getPayAmount(), orderInfo.getId(), orderInfo.getOrderNo()), "订单{}消费返现失败", orderInfo.getId());
|
||||
}
|
||||
FunUtils.safeRunVoid(() -> {
|
||||
if (shopUser.getIsVip().equals(0)) {
|
||||
// 消费累计成为会员的情况
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package com.czg.service.order.service.impl;
|
||||
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import com.czg.constants.PayTypeConstants;
|
||||
import com.czg.order.entity.OrderPayment;
|
||||
import com.czg.order.service.OrderPaymentService;
|
||||
import com.czg.service.order.mapper.OrderPaymentMapper;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 支付详情 服务层实现。
|
||||
@@ -14,6 +17,15 @@ import org.springframework.stereotype.Service;
|
||||
* @since 2025-02-15
|
||||
*/
|
||||
@DubboService
|
||||
public class OrderPaymentServiceImpl extends ServiceImpl<OrderPaymentMapper, OrderPayment> implements OrderPaymentService{
|
||||
public class OrderPaymentServiceImpl extends ServiceImpl<OrderPaymentMapper, OrderPayment> implements OrderPaymentService {
|
||||
|
||||
@Override
|
||||
public BigDecimal countMemberInAmount(Long shopId, Long shopUserId) {
|
||||
return getOneAs(QueryWrapper.create().select("sum(amount)")
|
||||
.eq(OrderPayment::getShopId, 143)
|
||||
.eq(OrderPayment::getSourceType, PayTypeConstants.SourceType.MEMBER_IN)
|
||||
.eq(OrderPayment::getPayType, PayTypeConstants.PayType.PAY)
|
||||
.eq(OrderPayment::getSourceId, 127452)
|
||||
.eq(OrderPayment::getPayStatus, PayTypeConstants.PayStatus.SUCCESS), BigDecimal.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.czg.market.dto.MemberOrderDTO;
|
||||
import com.czg.market.entity.MemberOrder;
|
||||
import com.czg.market.entity.MkShopCouponRecord;
|
||||
import com.czg.market.entity.MkShopRechargeDetail;
|
||||
import com.czg.market.enums.PointsConstant;
|
||||
import com.czg.market.service.*;
|
||||
import com.czg.market.vo.MkShopRechargeVO;
|
||||
import com.czg.order.dto.CheckOrderPay;
|
||||
@@ -51,12 +52,14 @@ import com.czg.service.order.service.PayService;
|
||||
import com.czg.system.service.SysParamsService;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import com.czg.utils.CzgRandomUtils;
|
||||
import com.czg.utils.FunUtils;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -116,9 +119,15 @@ public class PayServiceImpl implements PayService {
|
||||
@Resource
|
||||
private MkShopRechargeDetailService shopRechargeDetailService;
|
||||
@Resource
|
||||
private TbMemberConfigService memberConfigService;
|
||||
@Resource
|
||||
private MkDistributionUserService distributionUserService;
|
||||
@Resource
|
||||
private MkShopConsumerCouponService consumerCouponService;
|
||||
@Resource
|
||||
private MkPointsUserService mkPointsUserService;
|
||||
@Resource
|
||||
private MkConsumeCashbackService consumeCashbackService;
|
||||
@Resource
|
||||
private MkPointsConfigService pointsConfigService;
|
||||
|
||||
private final BigDecimal MONEY_RATE = new BigDecimal("100");
|
||||
|
||||
@@ -152,7 +161,6 @@ public class PayServiceImpl implements PayService {
|
||||
throw new CzgException("该店铺未启用霸王餐");
|
||||
}
|
||||
CheckOrderPay checkOrderPay = payParam.getCheckOrderPay();
|
||||
// CheckOrderPay checkOrderPay = BeanUtil.copyProperties(payParam, CheckOrderPay.class);
|
||||
OrderInfo orderInfo = orderInfoCustomService.checkOrderPay(checkOrderPay.setFreeDine(true).setWithCoupon(freeConfig.getWithCoupon()).setWithPoints(freeConfig.getWithPoints()));
|
||||
payParam.setAmount(orderInfo.getOrderAmount().multiply(BigDecimal.valueOf(freeConfig.getRechargeTimes())));
|
||||
return true;
|
||||
@@ -245,14 +253,9 @@ public class PayServiceImpl implements PayService {
|
||||
orderInfo.setRemark(payParam.getCheckOrderPay().getRemark());
|
||||
}
|
||||
|
||||
// log.info("发放经验值");
|
||||
// memberConfigService.deliver(shopUser, TableValueConstant.MemberExpFlow.Type.COST, orderInfo.getOrderAmount(), null, orderInfo.getId());
|
||||
|
||||
Long flowId = shopUserService.updateMoney(shopUserMoneyEditDTO);
|
||||
orderInfoCustomService.upOrderInfo(orderInfo, orderInfo.getOrderAmount(),
|
||||
LocalDateTime.now(), flowId, PayEnums.VIP_PAY);
|
||||
|
||||
|
||||
return CzgResult.success();
|
||||
}
|
||||
|
||||
@@ -261,9 +264,6 @@ public class PayServiceImpl implements PayService {
|
||||
OrderInfo orderInfo = checkPay(payParam.getCheckOrderPay());
|
||||
ShopInfo shopInfo = shopInfoService.getById(payParam.getShopId());
|
||||
AssertUtil.isNull(shopInfo, "店铺不存在");
|
||||
// if (!shopInfo.getIsAccountPay().equals(1)) {
|
||||
// return CzgResult.failure("支付失败,店铺暂未开启会员余额支付。");
|
||||
// }
|
||||
AssertUtil.isNull(payParam.getShopUserId(), "请选择付款人后重试");
|
||||
ShopUser shopUser = shopUserService.getById(payParam.getShopUserId());
|
||||
AssertUtil.isNull(shopUser, "支付失败 该店铺用户不存在");
|
||||
@@ -427,15 +427,16 @@ public class PayServiceImpl implements PayService {
|
||||
return CzgResult.failure("支付密码错误");
|
||||
}
|
||||
}
|
||||
if (shopUser.getIsVip().equals(0)) {
|
||||
//更新会员
|
||||
ShopUser updateInfo = new ShopUser();
|
||||
updateInfo.setIsVip(1);
|
||||
updateInfo.setJoinTime(LocalDateTime.now());
|
||||
updateInfo.setId(payParam.getShopUserId());
|
||||
shopUserService.updateById(updateInfo);
|
||||
}
|
||||
shopRechargeService.recharge(shopUser.getMainShopId(), shopUser.getId(), payParam.getRechargeDetailId(), payParam.getAmount(), null, "cash", ShopUserFlowBizEnum.CASH_IN);
|
||||
// if (shopUser.getIsVip().equals(0)) {
|
||||
// //更新会员
|
||||
// ShopUser updateInfo = new ShopUser();
|
||||
// updateInfo.setIsVip(1);
|
||||
// updateInfo.setJoinTime(LocalDateTime.now());
|
||||
// updateInfo.setId(payParam.getShopUserId());
|
||||
// shopUserService.updateById(updateInfo);
|
||||
// }
|
||||
shopRechargeService.recharge(shopUser.getMainShopId(), shopUser.getId(), payParam.getRechargeDetailId(),
|
||||
payParam.getAmount(), null, "cash", ShopUserFlowBizEnum.CASH_IN, true);
|
||||
return CzgResult.success();
|
||||
}
|
||||
|
||||
@@ -687,6 +688,10 @@ public class PayServiceImpl implements PayService {
|
||||
if (orderInfo.getStatus().equals(OrderStatusEnums.CANCELLED.getCode())) {
|
||||
throw new CzgException("订单已过期不可退单");
|
||||
}
|
||||
boolean isFirstRefund = true;
|
||||
if (orderInfo.getRefundAmount().compareTo(BigDecimal.ZERO) != 0) {
|
||||
isFirstRefund = false;
|
||||
}
|
||||
ShopInfo shopInfo = shopInfoService.getById(orderInfo.getShopId());
|
||||
Map<String, BigDecimal> returnProMap = new HashMap<>();
|
||||
boolean isPay = true;
|
||||
@@ -755,7 +760,6 @@ public class PayServiceImpl implements PayService {
|
||||
}
|
||||
} else {
|
||||
orderInfo.setStatus(OrderStatusEnums.REFUND.getCode());
|
||||
// ssss
|
||||
List<OrderDetail> orderDetails = orderDetailService.queryChain()
|
||||
.select(OrderDetail::getId, OrderDetail::getProductId, OrderDetail::getNum, OrderDetail::getReturnNum, OrderDetail::getPackAmount, OrderDetail::getReturnNum)
|
||||
.eq(OrderDetail::getOrderId, orderInfo.getId())
|
||||
@@ -812,16 +816,42 @@ public class PayServiceImpl implements PayService {
|
||||
}
|
||||
orderInfo.setRefundRemark(orderInfo.getRefundRemark() + param.getRefundReason());
|
||||
orderInfoService.updateById(orderInfo);
|
||||
//退款后续
|
||||
//退款返还库存
|
||||
if (!returnProMap.isEmpty()) {
|
||||
rabbitPublisher.sendOrderRefundMsg(JSONObject.toJSONString(Map.of("orderId", orderInfo.getId(), "returnProMap", returnProMap)));
|
||||
}
|
||||
|
||||
// 退款分销还原
|
||||
distributionUserService.refund(orderInfo.getId(), orderInfo.getOrderNo());
|
||||
refundOrderAfter(orderInfo.getId(), orderInfo.getShopId(), orderInfo.getUserId(), orderInfo.getOrderNo(),
|
||||
orderInfo.getPointsNum(), isFirstRefund, orderInfo.getStatus().equals(OrderStatusEnums.REFUND.getCode()));
|
||||
return CzgResult.success();
|
||||
}
|
||||
|
||||
//触发订单退款时 后续处理
|
||||
@Async
|
||||
public void refundOrderAfter(@NonNull Long orderId, @NonNull Long shopId, Long userId, String orderNo,
|
||||
Integer pointsNum, boolean isFirstRefund, boolean isAllRefund) {
|
||||
if (isFirstRefund) {
|
||||
// 退款分销还原
|
||||
FunUtils.safeRunVoid(() -> distributionUserService.refund(orderId, orderNo),
|
||||
"订单id:{} 退款,分销处理失败", orderId);
|
||||
if (userId == null) {
|
||||
return;
|
||||
}
|
||||
FunUtils.safeRunVoid(() -> consumerCouponService.removeConsumerCoupon(shopId, userId, orderId),
|
||||
"订单id:{} 退款,消费赠券回撤处理失败", orderId);
|
||||
FunUtils.safeRunVoid(() -> consumeCashbackService.removeCashback(shopId, userId, orderId, orderNo),
|
||||
"订单id:{} 退款,消费返现扣除处理失败", orderId);
|
||||
FunUtils.safeRunVoid(() -> pointsConfigService.removeConsumeAwardPoints(shopId, userId, orderId, orderNo),
|
||||
"订单id:{} 退款,赠送积分扣除失败", orderId);
|
||||
}
|
||||
if (isAllRefund && userId != null && pointsNum != null && pointsNum > 0) {
|
||||
FunUtils.safeRunVoid(() -> mkPointsUserService.alterPoints(userId, null, shopId, PointsConstant.ADD,
|
||||
pointsNum, orderId, StrUtil.format("订单退款返还{}积分", pointsNum)),
|
||||
"订单id:{} 退款,赠送积分扣除失败", orderId);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void refundOrder(@NonNull Long shopId, @NonNull Long orderId, @NonNull Long payOrderId, @NonNull String refPayOrderNo,
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.czg.service.product.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.czg.product.entity.MkOcrCountStick;
|
||||
|
||||
/**
|
||||
* 数签子的外链渠道 映射层。
|
||||
*
|
||||
* @author ww
|
||||
* @since 2025-12-24
|
||||
*/
|
||||
public interface MkOcrCountStickMapper extends BaseMapper<MkOcrCountStick> {
|
||||
|
||||
}
|
||||
@@ -32,7 +32,7 @@ public interface ProductMapper extends BaseMapper<Product> {
|
||||
|
||||
List<ShopProductVo> selectHotsProductList(@Param("shopId") Long shopId);
|
||||
|
||||
List<ShopProductVo> selectGroupProductList(@Param("shopId") Long shopId);
|
||||
List<ShopProductVo> selectGroupProductList(@Param("shopId") Long shopId, @Param("idList") List<Long> idList);
|
||||
|
||||
ShopProductInfoVo selectOneProductInfo(@Param("id") Long id, @Param("shopId") Long shopId);
|
||||
|
||||
|
||||
@@ -1,370 +1,279 @@
|
||||
package com.czg.service.product.service.impl;
|
||||
package com.czg.service.product.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.bean.copier.CopyOptions;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.digest.DigestUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.market.entity.MkOcr;
|
||||
import com.czg.product.entity.MkOcrService;
|
||||
import com.czg.product.dto.ConsStockFlowDTO;
|
||||
import com.czg.product.dto.SaleOrderDTO;
|
||||
import com.czg.product.entity.ConsInfo;
|
||||
import com.czg.product.entity.ConsStockFlow;
|
||||
import com.czg.product.enums.InOutItemEnum;
|
||||
import com.czg.product.enums.InOutTypeEnum;
|
||||
import com.czg.product.param.*;
|
||||
import com.czg.product.service.ConsStockFlowService;
|
||||
import com.czg.product.vo.ConsCheckStockRecordVo;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.product.mapper.ConsInfoMapper;
|
||||
import com.czg.service.product.mapper.ConsStockFlowMapper;
|
||||
import com.czg.service.product.mapper.ProductMapper;
|
||||
import com.czg.service.product.util.WxAccountUtil;
|
||||
import com.czg.utils.AliOcrUtil;
|
||||
import com.czg.utils.PageUtil;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.bean.copier.CopyOptions;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.product.dto.ConsStockFlowDTO;
|
||||
import com.czg.product.entity.ConsInfo;
|
||||
import com.czg.product.entity.ConsStockFlow;
|
||||
import com.czg.product.enums.InOutItemEnum;
|
||||
import com.czg.product.enums.InOutTypeEnum;
|
||||
import com.czg.product.param.*;
|
||||
import com.czg.product.service.ConsStockFlowService;
|
||||
import com.czg.product.vo.ConsCheckStockRecordVo;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.product.mapper.ConsInfoMapper;
|
||||
import com.czg.service.product.mapper.ConsStockFlowMapper;
|
||||
import com.czg.service.product.mapper.ProductMapper;
|
||||
import com.czg.service.product.util.WxAccountUtil;
|
||||
import com.czg.utils.PageUtil;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 耗材库存变动记录
|
||||
*
|
||||
* @author Tankaikai tankaikai@aliyun.com
|
||||
* @since 1.0 2025-02-21
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ConsStockFlowServiceImpl extends ServiceImpl<ConsStockFlowMapper, ConsStockFlow> implements ConsStockFlowService {
|
||||
/**
|
||||
* 耗材库存变动记录
|
||||
*
|
||||
* @author Tankaikai tankaikai@aliyun.com
|
||||
* @since 1.0 2025-02-21
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ConsStockFlowServiceImpl extends ServiceImpl<ConsStockFlowMapper, ConsStockFlow> implements ConsStockFlowService {
|
||||
|
||||
private final ConsInfoMapper consInfoMapper;
|
||||
private final ProductMapper productMapper;
|
||||
@Resource
|
||||
private WxAccountUtil wxAccountUtil;
|
||||
@Resource
|
||||
private MkOcrService ocrService;
|
||||
private final ConsInfoMapper consInfoMapper;
|
||||
private final ProductMapper productMapper;
|
||||
@Resource
|
||||
private WxAccountUtil wxAccountUtil;
|
||||
|
||||
private QueryWrapper buildQueryWrapper(ConsStockFlowDTO param) {
|
||||
QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
|
||||
private QueryWrapper buildQueryWrapper(ConsStockFlowDTO param) {
|
||||
QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
|
||||
/*if (StrUtil.isNotEmpty(param.getName())) {
|
||||
queryWrapper.like(ConsStockFlow::getName, param.getName());
|
||||
}*/
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
queryWrapper.eq(ConsStockFlow::getShopId, shopId);
|
||||
queryWrapper.orderBy(ConsStockFlow::getId, false);
|
||||
return queryWrapper;
|
||||
}
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
queryWrapper.eq(ConsStockFlow::getShopId, shopId);
|
||||
queryWrapper.orderBy(ConsStockFlow::getId, false);
|
||||
return queryWrapper;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ConsInOutStockHeadParam inStock(ConsInOutStockHeadParam param) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
||||
String createUserName = StpKit.USER.getAccount();
|
||||
ConsStockFlow head = BeanUtil.copyProperties(param, ConsStockFlow.class);
|
||||
List<ConsStockFlow> entityList = BeanUtil.copyToList(param.getBodyList(), ConsStockFlow.class);
|
||||
List<ConsStockFlow> insertList = new ArrayList<>();
|
||||
List<ConsInfo> updateStockList = new ArrayList<>();
|
||||
for (ConsInOutStockBodyParam entity : param.getBodyList()) {
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ConsInOutStockHeadParam inStock(ConsInOutStockHeadParam param) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
||||
String createUserName = StpKit.USER.getAccount();
|
||||
ConsStockFlow head = BeanUtil.copyProperties(param, ConsStockFlow.class);
|
||||
List<ConsStockFlow> entityList = BeanUtil.copyToList(param.getBodyList(), ConsStockFlow.class);
|
||||
List<ConsStockFlow> insertList = new ArrayList<>();
|
||||
List<ConsInfo> updateStockList = new ArrayList<>();
|
||||
for (ConsInOutStockBodyParam entity : param.getBodyList()) {
|
||||
|
||||
ConsStockFlow consStockFlow = BeanUtil.copyProperties(entity, ConsStockFlow.class);
|
||||
BeanUtil.copyProperties(head, entity, CopyOptions.create().ignoreNullValue());
|
||||
consStockFlow.setShopId(shopId);
|
||||
consStockFlow.setInOutType(InOutTypeEnum.IN.value());
|
||||
consStockFlow.setInOutItem(InOutItemEnum.MANUAL_IN.value());
|
||||
consStockFlow.setCreateUserId(createUserId);
|
||||
consStockFlow.setCreateUserName(createUserName);
|
||||
consStockFlow.setVendorId(param.getVendorId());
|
||||
String conId = entity.getConId();
|
||||
ConsInfo consInfo;
|
||||
if (StrUtil.isBlank(entity.getConId())) {
|
||||
consInfo = consInfoMapper.selectOneByQuery(new QueryWrapper().like(ConsInfo::getConName, entity.getConName())
|
||||
.eq(ConsInfo::getShopId, shopId).limit(1));
|
||||
if (consInfo == null) {
|
||||
entity.setFailReason("耗材不存在");
|
||||
}else if (!consInfo.getConUnit().equals(entity.getUnitName())) {
|
||||
entity.setFailReason("耗材单位不匹配");
|
||||
consInfo = null;
|
||||
}
|
||||
|
||||
entity.setConId(consInfo == null ? null : consInfo.getId().toString());
|
||||
consStockFlow.setConId(consInfo == null ? null : consInfo.getId());
|
||||
}else {
|
||||
consInfo = consInfoMapper.selectOneById(conId);
|
||||
}
|
||||
ConsStockFlow consStockFlow = BeanUtil.copyProperties(entity, ConsStockFlow.class);
|
||||
BeanUtil.copyProperties(head, entity, CopyOptions.create().ignoreNullValue());
|
||||
consStockFlow.setShopId(shopId);
|
||||
consStockFlow.setInOutType(InOutTypeEnum.IN.value());
|
||||
consStockFlow.setInOutItem(InOutItemEnum.MANUAL_IN.value());
|
||||
consStockFlow.setCreateUserId(createUserId);
|
||||
consStockFlow.setCreateUserName(createUserName);
|
||||
consStockFlow.setVendorId(param.getVendorId());
|
||||
String conId = entity.getConId();
|
||||
ConsInfo consInfo;
|
||||
if (StrUtil.isBlank(entity.getConId())) {
|
||||
consInfo = consInfoMapper.selectOneByQuery(new QueryWrapper().like(ConsInfo::getConName, entity.getConName())
|
||||
.eq(ConsInfo::getShopId, shopId).limit(1));
|
||||
if (consInfo == null) {
|
||||
continue;
|
||||
entity.setFailReason("耗材不存在");
|
||||
} else if (!consInfo.getConUnit().equals(entity.getUnitName())) {
|
||||
entity.setFailReason("耗材单位不匹配");
|
||||
consInfo = null;
|
||||
}
|
||||
consStockFlow.setBeforeNumber(consInfo.getStockNumber());
|
||||
consStockFlow.setAfterNumber(NumberUtil.add(consStockFlow.getBeforeNumber(), entity.getInOutNumber()));
|
||||
insertList.add(consStockFlow);
|
||||
consInfo.setStockNumber(consStockFlow.getAfterNumber());
|
||||
updateStockList.add(consInfo);
|
||||
}
|
||||
if (!insertList.isEmpty()) {
|
||||
mapper.insertBatchSelective(insertList, 50);
|
||||
}
|
||||
for (ConsInfo consInfo : updateStockList) {
|
||||
consInfoMapper.update(consInfo);
|
||||
}
|
||||
|
||||
return param;
|
||||
entity.setConId(consInfo == null ? null : consInfo.getId().toString());
|
||||
consStockFlow.setConId(consInfo == null ? null : consInfo.getId());
|
||||
} else {
|
||||
consInfo = consInfoMapper.selectOneById(conId);
|
||||
}
|
||||
if (consInfo == null) {
|
||||
continue;
|
||||
}
|
||||
consStockFlow.setBeforeNumber(consInfo.getStockNumber());
|
||||
consStockFlow.setAfterNumber(NumberUtil.add(consStockFlow.getBeforeNumber(), entity.getInOutNumber()));
|
||||
insertList.add(consStockFlow);
|
||||
consInfo.setStockNumber(consStockFlow.getAfterNumber());
|
||||
updateStockList.add(consInfo);
|
||||
}
|
||||
if (!insertList.isEmpty()) {
|
||||
mapper.insertBatchSelective(insertList, 50);
|
||||
}
|
||||
for (ConsInfo consInfo : updateStockList) {
|
||||
consInfoMapper.update(consInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void outStock(ConsInOutStockHeadParam param) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
||||
String createUserName = StpKit.USER.getAccount();
|
||||
ConsStockFlow head = BeanUtil.copyProperties(param, ConsStockFlow.class);
|
||||
List<ConsStockFlow> entityList = BeanUtil.copyToList(param.getBodyList(), ConsStockFlow.class);
|
||||
List<ConsStockFlow> insertList = new ArrayList<>();
|
||||
List<ConsInfo> updateStockList = new ArrayList<>();
|
||||
for (ConsStockFlow entity : entityList) {
|
||||
BeanUtil.copyProperties(head, entity, CopyOptions.create().ignoreNullValue());
|
||||
entity.setInOutNumber(NumberUtil.sub(BigDecimal.ZERO, entity.getInOutNumber()));
|
||||
entity.setShopId(shopId);
|
||||
entity.setInOutType(InOutTypeEnum.OUT.value());
|
||||
entity.setInOutItem(InOutItemEnum.MANUAL_OUT.value());
|
||||
entity.setCreateUserId(createUserId);
|
||||
entity.setCreateUserName(createUserName);
|
||||
Long conId = entity.getConId();
|
||||
ConsInfo consInfo = consInfoMapper.selectOneById(conId);
|
||||
if (consInfo == null) {
|
||||
throw new CzgException(StrUtil.format("耗材{}不存在", entity.getConName()));
|
||||
}
|
||||
entity.setBeforeNumber(consInfo.getStockNumber());
|
||||
entity.setAfterNumber(NumberUtil.add(entity.getBeforeNumber(), entity.getInOutNumber()));
|
||||
insertList.add(entity);
|
||||
consInfo.setStockNumber(entity.getAfterNumber());
|
||||
updateStockList.add(consInfo);
|
||||
}
|
||||
mapper.insertBatchSelective(insertList, 50);
|
||||
for (ConsInfo consInfo : updateStockList) {
|
||||
consInfoMapper.update(consInfo);
|
||||
}
|
||||
}
|
||||
return param;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void checkStock(ConsCheckStockParam param) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
||||
String createUserName = StpKit.USER.getAccount();
|
||||
ConsStockFlow entity = new ConsStockFlow();
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void outStock(ConsInOutStockHeadParam param) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
||||
String createUserName = StpKit.USER.getAccount();
|
||||
ConsStockFlow head = BeanUtil.copyProperties(param, ConsStockFlow.class);
|
||||
List<ConsStockFlow> entityList = BeanUtil.copyToList(param.getBodyList(), ConsStockFlow.class);
|
||||
List<ConsStockFlow> insertList = new ArrayList<>();
|
||||
List<ConsInfo> updateStockList = new ArrayList<>();
|
||||
for (ConsStockFlow entity : entityList) {
|
||||
BeanUtil.copyProperties(head, entity, CopyOptions.create().ignoreNullValue());
|
||||
entity.setInOutNumber(NumberUtil.sub(BigDecimal.ZERO, entity.getInOutNumber()));
|
||||
entity.setShopId(shopId);
|
||||
entity.setInOutType(InOutTypeEnum.OUT.value());
|
||||
entity.setInOutItem(InOutItemEnum.MANUAL_OUT.value());
|
||||
entity.setCreateUserId(createUserId);
|
||||
entity.setCreateUserName(createUserName);
|
||||
entity.setShopId(shopId);
|
||||
entity.setConId(param.getConId());
|
||||
entity.setConName(param.getConName());
|
||||
entity.setPurchasePrice(param.getPrice());
|
||||
ConsInfo consInfo = consInfoMapper.selectOneById(param.getConId());
|
||||
Long conId = entity.getConId();
|
||||
ConsInfo consInfo = consInfoMapper.selectOneById(conId);
|
||||
if (consInfo == null) {
|
||||
throw new CzgException(StrUtil.format("耗材{}不存在", entity.getConName()));
|
||||
}
|
||||
BigDecimal winLossNumber = NumberUtil.sub(param.getActualNumber(), param.getStockNumber());
|
||||
if (!NumberUtil.equals(winLossNumber, param.getWinLossNumber())) {
|
||||
throw new CzgException(StrUtil.format("耗材{}库存在发生变动,请刷新后重试", entity.getConName()));
|
||||
}
|
||||
entity.setBeforeNumber(consInfo.getStockNumber());
|
||||
entity.setInOutNumber(winLossNumber);
|
||||
entity.setAfterNumber(NumberUtil.add(entity.getBeforeNumber(), entity.getInOutNumber()));
|
||||
if (NumberUtil.isLess(winLossNumber, BigDecimal.ZERO)) {
|
||||
entity.setInOutType(InOutTypeEnum.OUT.value());
|
||||
entity.setInOutItem(InOutItemEnum.LOSS_OUT.value());
|
||||
} else {
|
||||
entity.setInOutType(InOutTypeEnum.IN.value());
|
||||
entity.setInOutItem(InOutItemEnum.WIN_IN.value());
|
||||
}
|
||||
entity.setSubTotal(NumberUtil.mul(winLossNumber, param.getPrice()));
|
||||
entity.setRemark(param.getRemark());
|
||||
saveFlow(entity);
|
||||
insertList.add(entity);
|
||||
consInfo.setStockNumber(entity.getAfterNumber());
|
||||
updateStockList.add(consInfo);
|
||||
}
|
||||
mapper.insertBatchSelective(insertList, 50);
|
||||
for (ConsInfo consInfo : updateStockList) {
|
||||
consInfoMapper.update(consInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ConsCheckStockRecordVo> getCheckStockRecordPage(Long conId) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
return super.pageAs(PageUtil.buildPage(), query().eq(ConsStockFlow::getShopId, shopId).eq(ConsStockFlow::getConId, conId).orderBy(ConsStockFlow::getId, false), ConsCheckStockRecordVo.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConsCheckStockRecordVo> getCheckStockRecordList(Long conId) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
return super.mapper.selectListByQueryAs(query().eq(ConsStockFlow::getShopId, shopId).eq(ConsStockFlow::getConId, conId).orderBy(ConsStockFlow::getId, false), ConsCheckStockRecordVo.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportDamage(ConsReportDamageParam param) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
||||
String createUserName = StpKit.USER.getAccount();
|
||||
ConsInfo consInfo = consInfoMapper.selectOneById(param.getConId());
|
||||
if (consInfo == null) {
|
||||
throw new CzgException("耗材不存在");
|
||||
}
|
||||
ConsStockFlow entity = new ConsStockFlow();
|
||||
entity.setCreateUserId(createUserId);
|
||||
entity.setCreateUserName(createUserName);
|
||||
entity.setShopId(shopId);
|
||||
entity.setConId(param.getConId());
|
||||
entity.setConName(consInfo.getConName());
|
||||
entity.setPurchasePrice(consInfo.getPrice());
|
||||
BigDecimal balance = NumberUtil.sub(consInfo.getStockNumber(), param.getNumber());
|
||||
if (NumberUtil.isLess(balance, BigDecimal.ZERO)) {
|
||||
throw new CzgException(StrUtil.format("耗材{}报损数量不能大于当前库存{}", entity.getConName(), consInfo.getStockNumber()));
|
||||
}
|
||||
entity.setBeforeNumber(consInfo.getStockNumber());
|
||||
entity.setInOutNumber(NumberUtil.sub(BigDecimal.ZERO, param.getNumber()));
|
||||
entity.setAfterNumber(balance);
|
||||
entity.setInOutType(InOutTypeEnum.OUT.value());
|
||||
entity.setInOutItem(InOutItemEnum.DAMAGE_OUT.value());
|
||||
entity.setSubTotal(NumberUtil.mul(param.getNumber(), consInfo.getPrice()));
|
||||
entity.setImgUrls(JSON.toJSONString(param.getImgUrls()));
|
||||
saveFlow(entity);
|
||||
consInfo.setStockNumber(entity.getAfterNumber());
|
||||
consInfoMapper.update(consInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ConsStockFlowDTO> findConsStockFlowPage(ConsStockFlowParam param) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
PageHelper.startPage(PageUtil.buildPageHelp());
|
||||
return PageUtil.convert(new PageInfo<>(mapper.findConsStockFlowPage(shopId, param.getInOutType(), param.getInOutItem(), param.getConId())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveFlow(ConsStockFlow entity) {
|
||||
super.save(entity);
|
||||
Long shopId = entity.getShopId();
|
||||
BigDecimal afterNumber = entity.getAfterNumber();
|
||||
ConsInfo consInfo = consInfoMapper.selectOneById(entity.getConId());
|
||||
String shopName = "";
|
||||
try {
|
||||
shopName = StpKit.USER.getShopName();
|
||||
} catch (Exception e) {
|
||||
log.error("获取店铺名称失败");
|
||||
}
|
||||
if (StrUtil.isEmpty(shopName)) {
|
||||
shopName = productMapper.getShopName(shopId);
|
||||
}
|
||||
BigDecimal conWarning = consInfo.getConWarning();
|
||||
// 库存小于警告值,发送消息提醒
|
||||
if (NumberUtil.isLess(afterNumber, conWarning)) {
|
||||
List<String> openIdList = consInfoMapper.findOpenIdList(shopId, "con");
|
||||
if (CollUtil.isEmpty(openIdList)) {
|
||||
return;
|
||||
}
|
||||
String conName = StrUtil.format("{}数量<预警值{}", consInfo.getConName(), conWarning);
|
||||
String finalShopName = shopName;
|
||||
ThreadUtil.execAsync(() -> {
|
||||
openIdList.parallelStream().forEach(openId -> {
|
||||
wxAccountUtil.sendStockMsg(finalShopName, conName, afterNumber, openId);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer ocr(String originalFilename, InputStream inputStream) {
|
||||
Long shopId = StpKit.USER.getShopId();
|
||||
byte[] readAllBytes = null;
|
||||
try {
|
||||
readAllBytes = inputStream.readAllBytes();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String md5 = DigestUtil.md5Hex(readAllBytes);
|
||||
MkOcr ocr = ocrService.getOne(new QueryWrapper().eq(MkOcr::getShopId, shopId).eq(MkOcr::getMd5, md5));
|
||||
if (ocr != null) {
|
||||
return ocr.getId();
|
||||
}
|
||||
MkOcr mkOcr = new MkOcr();
|
||||
mkOcr.setShopId(shopId);
|
||||
mkOcr.setMd5(md5);
|
||||
ocrService.save(mkOcr);
|
||||
byte[] finalReadAllBytes1 = readAllBytes;
|
||||
ThreadUtil.execAsync(() -> {
|
||||
try {
|
||||
String infoStr = AliOcrUtil.appCall(finalReadAllBytes1, originalFilename);
|
||||
SaleOrderDTO saleOrderDTO = JSONObject.parseObject(infoStr, SaleOrderDTO.class);
|
||||
|
||||
ArrayList<ConsInOutStockBodyParam> bodyList = new ArrayList<>();
|
||||
Set<String> nameList = saleOrderDTO.getItems().stream().map(SaleOrderDTO.Item::getConName).collect(Collectors.toSet());
|
||||
Map<String, ConsInfo> consInfoMap = new HashMap<>();
|
||||
if (!nameList.isEmpty()) {
|
||||
consInfoMap = consInfoMapper.selectListByQuery(new QueryWrapper().in(ConsInfo::getConName, nameList).eq(ConsInfo::getShopId, shopId))
|
||||
.stream().collect(Collectors.toMap(ConsInfo::getConName, consInfo -> consInfo));
|
||||
}
|
||||
ArrayList<SaleOrderDTO.Item> unInCons = new ArrayList<>();
|
||||
for (SaleOrderDTO.Item item : saleOrderDTO.getItems()) {
|
||||
ConsInOutStockBodyParam bodyParam = new ConsInOutStockBodyParam()
|
||||
.setConName(item.getConName())
|
||||
.setPurchasePrice(new BigDecimal(item.getPurchasePrice()))
|
||||
.setUnitName(item.getUnitName())
|
||||
.setSubTotal(new BigDecimal(item.getSubTotal()))
|
||||
.setInOutNumber(new BigDecimal(item.getInOutNumber()));
|
||||
ConsInfo consInfo = consInfoMap.get(item.getConName());
|
||||
if (consInfo != null) {
|
||||
unInCons.add(item);
|
||||
bodyParam.setConId(consInfo.getId().toString());
|
||||
}
|
||||
bodyList.add(bodyParam);
|
||||
}
|
||||
|
||||
ConsInOutStockHeadParam headParam = new ConsInOutStockHeadParam();
|
||||
headParam.setBatchNo(saleOrderDTO.getOrderNumber())
|
||||
.setInOutDate(LocalDate.parse(saleOrderDTO.getDate()))
|
||||
.setAmountPayable(new BigDecimal(saleOrderDTO.getTotalAmount()))
|
||||
.setBodyList(bodyList)
|
||||
.setUnInCons(unInCons)
|
||||
.setOcrSaleOrder(saleOrderDTO);
|
||||
|
||||
|
||||
mkOcr.setStatus("SUCCESS");
|
||||
mkOcr.setResp(JSON.toJSONString(headParam));
|
||||
}catch (Exception e) {
|
||||
mkOcr.setErr(e.getMessage());
|
||||
mkOcr.setStatus("FAILED");
|
||||
log.error("ocr失败:", e);
|
||||
}finally {
|
||||
ocrService.updateById(mkOcr);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return mkOcr.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConsInOutStockHeadParam ocrDetail(Long id) {
|
||||
MkOcr mkOcr = ocrService.getOne(new QueryWrapper().eq(MkOcr::getShopId, StpKit.USER.getShopId()).eq(MkOcr::getId, id));
|
||||
if (StrUtil.isNotBlank(mkOcr.getResp())) {
|
||||
return JSONObject.parseObject(mkOcr.getResp(), ConsInOutStockHeadParam.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void checkStock(ConsCheckStockParam param) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
||||
String createUserName = StpKit.USER.getAccount();
|
||||
ConsStockFlow entity = new ConsStockFlow();
|
||||
entity.setCreateUserId(createUserId);
|
||||
entity.setCreateUserName(createUserName);
|
||||
entity.setShopId(shopId);
|
||||
entity.setConId(param.getConId());
|
||||
entity.setConName(param.getConName());
|
||||
entity.setPurchasePrice(param.getPrice());
|
||||
ConsInfo consInfo = consInfoMapper.selectOneById(param.getConId());
|
||||
if (consInfo == null) {
|
||||
throw new CzgException(StrUtil.format("耗材{}不存在", entity.getConName()));
|
||||
}
|
||||
BigDecimal winLossNumber = NumberUtil.sub(param.getActualNumber(), param.getStockNumber());
|
||||
if (!NumberUtil.equals(winLossNumber, param.getWinLossNumber())) {
|
||||
throw new CzgException(StrUtil.format("耗材{}库存在发生变动,请刷新后重试", entity.getConName()));
|
||||
}
|
||||
entity.setBeforeNumber(consInfo.getStockNumber());
|
||||
entity.setInOutNumber(winLossNumber);
|
||||
entity.setAfterNumber(NumberUtil.add(entity.getBeforeNumber(), entity.getInOutNumber()));
|
||||
if (NumberUtil.isLess(winLossNumber, BigDecimal.ZERO)) {
|
||||
entity.setInOutType(InOutTypeEnum.OUT.value());
|
||||
entity.setInOutItem(InOutItemEnum.LOSS_OUT.value());
|
||||
} else {
|
||||
entity.setInOutType(InOutTypeEnum.IN.value());
|
||||
entity.setInOutItem(InOutItemEnum.WIN_IN.value());
|
||||
}
|
||||
entity.setSubTotal(NumberUtil.mul(winLossNumber, param.getPrice()));
|
||||
entity.setRemark(param.getRemark());
|
||||
saveFlow(entity);
|
||||
consInfo.setStockNumber(entity.getAfterNumber());
|
||||
consInfoMapper.update(consInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ConsCheckStockRecordVo> getCheckStockRecordPage(Long conId) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
return super.pageAs(PageUtil.buildPage(), query().eq(ConsStockFlow::getShopId, shopId).eq(ConsStockFlow::getConId, conId).orderBy(ConsStockFlow::getId, false), ConsCheckStockRecordVo.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConsCheckStockRecordVo> getCheckStockRecordList(Long conId) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
return super.mapper.selectListByQueryAs(query().eq(ConsStockFlow::getShopId, shopId).eq(ConsStockFlow::getConId, conId).orderBy(ConsStockFlow::getId, false), ConsCheckStockRecordVo.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportDamage(ConsReportDamageParam param) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
||||
String createUserName = StpKit.USER.getAccount();
|
||||
ConsInfo consInfo = consInfoMapper.selectOneById(param.getConId());
|
||||
if (consInfo == null) {
|
||||
throw new CzgException("耗材不存在");
|
||||
}
|
||||
ConsStockFlow entity = new ConsStockFlow();
|
||||
entity.setCreateUserId(createUserId);
|
||||
entity.setCreateUserName(createUserName);
|
||||
entity.setShopId(shopId);
|
||||
entity.setConId(param.getConId());
|
||||
entity.setConName(consInfo.getConName());
|
||||
entity.setPurchasePrice(consInfo.getPrice());
|
||||
BigDecimal balance = NumberUtil.sub(consInfo.getStockNumber(), param.getNumber());
|
||||
if (NumberUtil.isLess(balance, BigDecimal.ZERO)) {
|
||||
throw new CzgException(StrUtil.format("耗材{}报损数量不能大于当前库存{}", entity.getConName(), consInfo.getStockNumber()));
|
||||
}
|
||||
entity.setBeforeNumber(consInfo.getStockNumber());
|
||||
entity.setInOutNumber(NumberUtil.sub(BigDecimal.ZERO, param.getNumber()));
|
||||
entity.setAfterNumber(balance);
|
||||
entity.setInOutType(InOutTypeEnum.OUT.value());
|
||||
entity.setInOutItem(InOutItemEnum.DAMAGE_OUT.value());
|
||||
entity.setSubTotal(NumberUtil.mul(param.getNumber(), consInfo.getPrice()));
|
||||
entity.setImgUrls(JSON.toJSONString(param.getImgUrls()));
|
||||
saveFlow(entity);
|
||||
consInfo.setStockNumber(entity.getAfterNumber());
|
||||
consInfoMapper.update(consInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ConsStockFlowDTO> findConsStockFlowPage(ConsStockFlowParam param) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
PageHelper.startPage(PageUtil.buildPageHelp());
|
||||
return PageUtil.convert(new PageInfo<>(mapper.findConsStockFlowPage(shopId, param.getInOutType(), param.getInOutItem(), param.getConId())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveFlow(ConsStockFlow entity) {
|
||||
super.save(entity);
|
||||
Long shopId = entity.getShopId();
|
||||
BigDecimal afterNumber = entity.getAfterNumber();
|
||||
ConsInfo consInfo = consInfoMapper.selectOneById(entity.getConId());
|
||||
String shopName = "";
|
||||
try {
|
||||
shopName = StpKit.USER.getShopName();
|
||||
} catch (Exception e) {
|
||||
log.error("获取店铺名称失败");
|
||||
}
|
||||
if (StrUtil.isEmpty(shopName)) {
|
||||
shopName = productMapper.getShopName(shopId);
|
||||
}
|
||||
BigDecimal conWarning = consInfo.getConWarning();
|
||||
// 库存小于警告值,发送消息提醒
|
||||
if (NumberUtil.isLess(afterNumber, conWarning)) {
|
||||
List<String> openIdList = consInfoMapper.findOpenIdList(shopId, "con");
|
||||
if (CollUtil.isEmpty(openIdList)) {
|
||||
return;
|
||||
}
|
||||
String conName = StrUtil.format("{}数量<预警值{}", consInfo.getConName(), conWarning);
|
||||
String finalShopName = shopName;
|
||||
ThreadUtil.execAsync(() -> {
|
||||
openIdList.parallelStream().forEach(openId -> {
|
||||
wxAccountUtil.sendStockMsg(finalShopName, conName, afterNumber, openId);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.czg.service.product.service.impl;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.czg.constants.SystemConstants;
|
||||
import com.czg.product.entity.MkOcrCountStick;
|
||||
import com.czg.product.service.MkOcrCountStickService;
|
||||
import com.czg.service.RedisService;
|
||||
import com.czg.service.product.mapper.MkOcrCountStickMapper;
|
||||
import com.czg.service.product.util.AISmartCountUtils;
|
||||
import com.czg.service.product.util.MuSmartCountUtils;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 数签子的外链渠道 服务层实现。
|
||||
*
|
||||
* @author ww
|
||||
* @since 2025-12-24
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MkOcrCountStickServiceImpl extends ServiceImpl<MkOcrCountStickMapper, MkOcrCountStick> implements MkOcrCountStickService {
|
||||
|
||||
@Resource
|
||||
private RedisService redisService;
|
||||
|
||||
@Override
|
||||
public int getCountStick(byte[] fileByte, String fileName) {
|
||||
List<MkOcrCountStick> list = list(query().eq(MkOcrCountStick::getStatus, SystemConstants.OneZero.ONE).orderBy(MkOcrCountStick::getSort, true));
|
||||
for (MkOcrCountStick mkOcrCountStick : list) {
|
||||
if ("znds".equals(mkOcrCountStick.getMark())) {
|
||||
try {
|
||||
String tickCount = AISmartCountUtils.getTickCount(mkOcrCountStick.getToken(), fileByte, fileName);
|
||||
if (StrUtil.isNotBlank(tickCount)) {
|
||||
return Integer.parseInt(tickCount);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
mkOcrCountStick.setStatus(SystemConstants.OneZero.ZERO);
|
||||
log.error("智能点数失败", e);
|
||||
updateById(mkOcrCountStick);
|
||||
}
|
||||
} else if ("ygmh".equals(mkOcrCountStick.getMark())) {
|
||||
try {
|
||||
String token = getToken(mkOcrCountStick.getAccount(), mkOcrCountStick.getPwd());
|
||||
return MuSmartCountUtils.detectBambooStick(Base64.encode(fileByte), token);
|
||||
} catch (Exception e) {
|
||||
mkOcrCountStick.setStatus(SystemConstants.OneZero.ZERO);
|
||||
log.error("智能点数失败", e);
|
||||
updateById(mkOcrCountStick);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 一个木涵 获取token
|
||||
private String getToken(String username, String password) {
|
||||
Object token = redisService.get("ocr:ygmh:token");
|
||||
if (token != null) {
|
||||
return token.toString();
|
||||
}
|
||||
String muToken = MuSmartCountUtils.login(username, password);
|
||||
//时间为3个月减去60秒
|
||||
redisService.set("ocr:ygmh:token", muToken, 7775940);
|
||||
return muToken;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,148 @@
|
||||
package com.czg.service.product.service.impl;
|
||||
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.digest.DigestUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.product.dto.SaleOrderDTO;
|
||||
import com.czg.product.entity.ConsInfo;
|
||||
import com.czg.product.param.ConsInOutStockBodyParam;
|
||||
import com.czg.product.param.ConsInOutStockHeadParam;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.product.mapper.ConsInfoMapper;
|
||||
import com.czg.service.product.mapper.MkOcrMapper;
|
||||
import com.czg.utils.AliOcrUtil;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import com.czg.market.entity.MkOcr;
|
||||
import com.czg.product.entity.MkOcrService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* ocr识别结果 服务层实现。
|
||||
*
|
||||
* @author zs
|
||||
* @since 2025-11-26
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MkOcrServiceImpl extends ServiceImpl<MkOcrMapper, MkOcr> implements MkOcrService{
|
||||
public class MkOcrServiceImpl extends ServiceImpl<MkOcrMapper, MkOcr> implements MkOcrService {
|
||||
|
||||
@Resource
|
||||
private ConsInfoMapper consInfoMapper;
|
||||
|
||||
String consOcrDetail = "你是一名票据OCR结构化专家,请从我提供的票据图片中智能提取信息并只输出JSON,不得添加解释、不补充不存在内容、不得返回空字符串、字段缺失填null、字段不可省略、数字一律用字符串," +
|
||||
"使用以下固定JSON结构:{\"documentType\":\"\",\"orderNumber\":\"\",\"date\":\"\",\"customerName\":\"\",\"operator\":\"\"," +
|
||||
"\"items\":[{\"conName\":\"\",\"spec\":\"\",\"unitName\":\"\",\"inOutNumber\":\"\",\"purchasePrice\":\"\",\"subTotal\":\"\"}]," +
|
||||
"\"totalAmount\":\"\",\"remark\":\"\"}。字段映射规则:documentType对应单据类型/销售单/采购单/出货单;orderNumber对应单号/编号/No;" +
|
||||
"date对应日期/开单日期;customerName对应客户名称/收货单位/供应商;operator对应业务员/经办人/制单人/操作员;items.conName对应品名/名称;" +
|
||||
"items.spec对应规格/型号;items.unitName对应单位;items.inOutNumber对应数量;items.purchasePrice对应单价;items.subTotal对应金额/小计;" +
|
||||
"totalAmount对应总金额/合计金额;remark对应备注。严禁生成图片中不存在的字段内容,看不清或未出现的字段必须为null,不允许推测或补全,不得生成多余字段;" +
|
||||
"items只能根据识别到的行生成,不得虚构。必须能识别旋转、倾斜、模糊、撕裂、光照差异、列顺序混乱、无表格线等情况并尽量恢复信息。" +
|
||||
"最终输出必须是纯JSON,不得包含任何非JSON字符。";
|
||||
|
||||
@Override
|
||||
public ConsInOutStockHeadParam ocrDetail(Long id) {
|
||||
MkOcr mkOcr = getOne(new QueryWrapper().eq(MkOcr::getShopId, StpKit.USER.getShopId()).eq(MkOcr::getId, id));
|
||||
if (StrUtil.isNotBlank(mkOcr.getResp())) {
|
||||
return JSONObject.parseObject(mkOcr.getResp(), ConsInOutStockHeadParam.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer ocr(String originalFilename, InputStream inputStream, String type) {
|
||||
Long shopId = StpKit.USER.getShopId();
|
||||
byte[] readAllBytes = null;
|
||||
try {
|
||||
readAllBytes = inputStream.readAllBytes();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String md5 = DigestUtil.md5Hex(readAllBytes);
|
||||
MkOcr ocr = getOne(new QueryWrapper().eq(MkOcr::getShopId, shopId).eq(MkOcr::getMd5, md5));
|
||||
if (ocr != null) {
|
||||
return ocr.getId();
|
||||
}
|
||||
MkOcr mkOcr = new MkOcr();
|
||||
mkOcr.setShopId(shopId);
|
||||
mkOcr.setMd5(md5);
|
||||
save(mkOcr);
|
||||
byte[] finalReadAllBytes1 = readAllBytes;
|
||||
ThreadUtil.execAsync(() -> {
|
||||
try {
|
||||
if ("cons".equals(type)) {
|
||||
mkOcr.setResp(ocrCons(finalReadAllBytes1, originalFilename, shopId));
|
||||
} else {
|
||||
|
||||
}
|
||||
mkOcr.setStatus("SUCCESS");
|
||||
} catch (Exception e) {
|
||||
mkOcr.setErr(e.getMessage());
|
||||
mkOcr.setStatus("FAILED");
|
||||
log.error("ocr失败:", e);
|
||||
} finally {
|
||||
updateById(mkOcr);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return mkOcr.getId();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 识别 入库单
|
||||
*/
|
||||
private String ocrCons(byte[] finalReadAllBytes1, String originalFilename, Long shopId) {
|
||||
String infoStr = AliOcrUtil.appCall(finalReadAllBytes1, originalFilename, consOcrDetail);
|
||||
SaleOrderDTO saleOrderDTO = JSONObject.parseObject(infoStr, SaleOrderDTO.class);
|
||||
|
||||
ArrayList<ConsInOutStockBodyParam> bodyList = new ArrayList<>();
|
||||
Set<String> nameList = saleOrderDTO.getItems().stream().map(SaleOrderDTO.Item::getConName).collect(Collectors.toSet());
|
||||
Map<String, ConsInfo> consInfoMap = new HashMap<>();
|
||||
if (!nameList.isEmpty()) {
|
||||
consInfoMap = consInfoMapper.selectListByQuery(new QueryWrapper().in(ConsInfo::getConName, nameList).eq(ConsInfo::getShopId, shopId))
|
||||
.stream().collect(Collectors.toMap(ConsInfo::getConName, consInfo -> consInfo));
|
||||
}
|
||||
ArrayList<SaleOrderDTO.Item> unInCons = new ArrayList<>();
|
||||
for (SaleOrderDTO.Item item : saleOrderDTO.getItems()) {
|
||||
ConsInOutStockBodyParam bodyParam = new ConsInOutStockBodyParam()
|
||||
.setConName(item.getConName())
|
||||
.setPurchasePrice(new BigDecimal(item.getPurchasePrice()))
|
||||
.setUnitName(item.getUnitName())
|
||||
.setSubTotal(new BigDecimal(item.getSubTotal()))
|
||||
.setInOutNumber(new BigDecimal(item.getInOutNumber()));
|
||||
ConsInfo consInfo = consInfoMap.get(item.getConName());
|
||||
if (consInfo != null) {
|
||||
unInCons.add(item);
|
||||
bodyParam.setConId(consInfo.getId().toString());
|
||||
}
|
||||
bodyList.add(bodyParam);
|
||||
}
|
||||
|
||||
ConsInOutStockHeadParam headParam = new ConsInOutStockHeadParam();
|
||||
headParam.setBatchNo(saleOrderDTO.getOrderNumber())
|
||||
.setInOutDate(LocalDate.parse(saleOrderDTO.getDate()))
|
||||
.setAmountPayable(new BigDecimal(saleOrderDTO.getTotalAmount()))
|
||||
.setBodyList(bodyList)
|
||||
.setUnInCons(unInCons)
|
||||
.setOcrSaleOrder(saleOrderDTO);
|
||||
return JSON.toJSONString(headParam);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -6,14 +6,12 @@ import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONWriter;
|
||||
import com.czg.constant.CacheConstant;
|
||||
import com.czg.constants.SystemConstants;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.product.dto.ProdConsRelationDTO;
|
||||
import com.czg.product.dto.ProdSkuDTO;
|
||||
import com.czg.product.dto.ProductDTO;
|
||||
import com.czg.product.dto.ShopProdCategoryDTO;
|
||||
import com.czg.product.dto.*;
|
||||
import com.czg.product.entity.*;
|
||||
import com.czg.product.enums.*;
|
||||
import com.czg.product.param.*;
|
||||
@@ -310,6 +308,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
|
||||
dto.setSkuList(skuList);
|
||||
List<ProdConsRelationDTO> consList = prodConsRelationMapper.selectListByProdId(dto.getId());
|
||||
dto.setConsList(consList);
|
||||
dto.setRelatedRecommendJson(getRelateProductList(dto.getRelatedRecommend()));
|
||||
return dto;
|
||||
}
|
||||
|
||||
@@ -336,6 +335,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
|
||||
}
|
||||
entity.setIsDel(SystemConstants.OneZero.ZERO);
|
||||
entity.setShopId(shopId);
|
||||
entity.setRelatedRecommend(dto.getRelatedRecommendStr());
|
||||
super.save(entity);
|
||||
dto.setId(entity.getId());
|
||||
// 清除商品分类列表缓存
|
||||
@@ -404,6 +404,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
|
||||
if (!ProductTypeEnum.SKU.value().equals(entity.getType())) {
|
||||
UpdateChain.of(Product.class).set(Product::getSpecId, null).eq(Product::getId, dto.getId()).update();
|
||||
}
|
||||
entity.setRelatedRecommend(dto.getRelatedRecommendStr());
|
||||
super.updateById(entity);
|
||||
// 清除商品分类列表缓存
|
||||
clearProductCache(old.getCategoryId());
|
||||
@@ -788,4 +789,16 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
|
||||
String key = StrUtil.format(CacheConstant.SHOP_PRODUCT_STOCK, shopId, productId);
|
||||
redisService.set(key, stockNumber);
|
||||
}
|
||||
|
||||
private List<RelatedProductDTO> getRelateProductList(String relatedProduct) {
|
||||
if (StrUtil.isNotBlank(relatedProduct) && !"[]".equals(relatedProduct)) {
|
||||
List<Long> idList = JSONArray.parseArray(relatedProduct, Long.class);
|
||||
|
||||
QueryWrapper wrapper = QueryWrapper.create().select(Product::getId, Product::getName, Product::getCoverImg).eq(Product::getIsDel, SystemConstants.OneZero.ZERO)
|
||||
.in(Product::getId, idList);
|
||||
return super.listAs(wrapper, RelatedProductDTO.class);
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.czg.constant.CacheConstant;
|
||||
import com.czg.constants.SystemConstants;
|
||||
import com.czg.exception.CzgException;
|
||||
@@ -78,7 +79,7 @@ public class UProductServiceImpl extends ServiceImpl<ProductMapper, Product> imp
|
||||
query().select(ProdGroup::getId, ProdGroup::getName, ProdGroup::getSortMode, ProdGroup::getUseTime, ProdGroup::getSaleStartTime, ProdGroup::getSaleEndTime)
|
||||
.eq(ProdGroup::getShopId, shopId).eq(ProdGroup::getStatus,SystemConstants.OneZero.ONE)
|
||||
.orderBy(ProdGroup::getSort, true), ShopGroupProductVo.class);
|
||||
List<ShopProductVo> productAllList = productMapper.selectGroupProductList(shopId);
|
||||
List<ShopProductVo> productAllList = productMapper.selectGroupProductList(shopId, null);
|
||||
productAllList.forEach(item -> {
|
||||
List<ProdSkuDTO> skuList = prodSkuMapper.selectListByQueryAs(query()
|
||||
.eq(ProdSku::getProductId, item.getId())
|
||||
@@ -130,6 +131,21 @@ public class UProductServiceImpl extends ServiceImpl<ProductMapper, Product> imp
|
||||
if (data == null) {
|
||||
throw new CzgException("商品不可售");
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(data.getRelatedRecommend()) || "[]".equals(data.getRelatedRecommend())) {
|
||||
data.setRelatedRecommendJson(new ArrayList<>());
|
||||
} else {
|
||||
List<ShopProductVo> productAllList = productMapper.selectGroupProductList(shopId, JSONArray.parseArray(data.getRelatedRecommend(), Long.class));
|
||||
productAllList.forEach(item -> {
|
||||
List<ProdSkuDTO> skuList = prodSkuMapper.selectListByQueryAs(query()
|
||||
.eq(ProdSku::getProductId, item.getId())
|
||||
.eq(ProdSku::getIsGrounding, SystemConstants.OneZero.ONE)
|
||||
.eq(ProdSku::getIsDel, SystemConstants.OneZero.ZERO), ProdSkuDTO.class);
|
||||
item.setSkuList(skuList);
|
||||
});
|
||||
data.setRelatedRecommendJson(productAllList);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.czg.service.product.util;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.czg.exception.CzgException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
/**
|
||||
* 智能点数上传工具类
|
||||
* @author ww
|
||||
*/
|
||||
@Slf4j
|
||||
public class AISmartCountUtils {
|
||||
// 基础配置
|
||||
private static final String BASE_URL = "https://api.aismartcount.com/api/v1";
|
||||
private static final int TIMEOUT = 30000;
|
||||
|
||||
/**
|
||||
* 示例:完整调用流程
|
||||
*/
|
||||
public static String getTickCount(String token, byte[] file, String fileName) throws Exception {
|
||||
String uploadResponse = uploadImage(token, file, fileName);
|
||||
return countImageDots(token, uploadResponse);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传图片接口
|
||||
* 完全使用你提供的header(String, String)方法设置请求头
|
||||
*
|
||||
* @param imageData 图片数据(InputStream / byte[] / File)
|
||||
* @return 上传响应结果
|
||||
* @throws Exception 上传异常
|
||||
*/
|
||||
private static String uploadImage(String token, Object imageData, String fileName) {
|
||||
|
||||
// 1. 构建请求URL
|
||||
String uploadUrl = BASE_URL + "/upload/image";
|
||||
|
||||
// 2. 构建POST请求并设置基础参数
|
||||
HttpRequest postRequest = HttpUtil.createPost(uploadUrl)
|
||||
.header("authorization", token)
|
||||
.timeout(TIMEOUT);
|
||||
|
||||
// 3. 根据数据类型设置文件上传参数
|
||||
if (imageData instanceof File files) {
|
||||
postRequest.form("file", files);
|
||||
} else if (imageData instanceof InputStream input) {
|
||||
postRequest.form("file", input, fileName);
|
||||
} else if (imageData instanceof byte[] bytes) {
|
||||
postRequest.form("file", bytes, fileName);
|
||||
} else {
|
||||
throw new IllegalArgumentException("不支持的图片数据类型:" + (imageData == null ? "null" : imageData.getClass().getName()));
|
||||
}
|
||||
String body = postRequest.execute().body();
|
||||
// 解析上传响应并校验状态码
|
||||
JSONObject uploadResult = JSONUtil.parseObj(body);
|
||||
|
||||
// 1. 校验响应码(核心)
|
||||
int code = uploadResult.getInt("code", -1);
|
||||
if (code != 200) {
|
||||
log.error("智能点数 图片上传失败 {}", uploadResult);
|
||||
throw new CzgException("图片上传失败");
|
||||
}
|
||||
JSONObject dataObj = uploadResult.getJSONObject("data");
|
||||
if (dataObj == null) {
|
||||
log.error("智能点数 图片上传响应中未找到data字段 {}", uploadResult);
|
||||
throw new CzgException("图片上传失败");
|
||||
}
|
||||
String imgUrl = dataObj.getStr("url");
|
||||
if (StrUtil.isBlank(imgUrl)) {
|
||||
log.error("智能点数 图片上传成功,但未返回图片URL {}", uploadResult);
|
||||
throw new CzgException("图片上传成功,但未返回图片URL");
|
||||
}
|
||||
return imgUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计图片点数接口
|
||||
* 手动拼接URL参数,使用header方法设置授权头
|
||||
*
|
||||
* @param imgUrl 图片URL
|
||||
* @return 统计响应结果
|
||||
* @throws Exception 请求异常
|
||||
*/
|
||||
private static String countImageDots(String token, String imgUrl) throws Exception {
|
||||
String countUrl = BASE_URL + "/count/count-image-dots" +
|
||||
"?img_url=" + encodeParam(imgUrl) +
|
||||
"&type=stick&secure=true&upload_source=pc";
|
||||
|
||||
// 2. 构建请求(仅使用你提供的方法)
|
||||
String countResponse = HttpUtil.createPost(countUrl)
|
||||
.header("authorization", token)
|
||||
.timeout(TIMEOUT)
|
||||
.execute()
|
||||
.body();
|
||||
JSONObject countResult = JSONUtil.parseObj(countResponse);
|
||||
int countCode = countResult.getInt("code", -1);
|
||||
if (countCode != 200) {
|
||||
log.error("智能点数 点数统计失败,未知错误 {}", countResult);
|
||||
throw new CzgException("点数统计失败,未知错误");
|
||||
}
|
||||
// 3. 执行请求并返回结果
|
||||
return countResult.getStr("total_count");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通用URL参数编码
|
||||
*
|
||||
* @param param 要编码的参数
|
||||
* @return 编码后的字符串
|
||||
*/
|
||||
private static String encodeParam(String param) {
|
||||
if (StrUtil.isBlank(param)) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
return URLEncoder.encode(param, StandardCharsets.UTF_8);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("URL参数编码失败: " + param, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package com.czg.service.product.util;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.czg.exception.CzgException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
/**
|
||||
* 一个木涵
|
||||
*
|
||||
* @author: ww
|
||||
*/
|
||||
@Slf4j
|
||||
public class MuSmartCountUtils {
|
||||
// 基础配置
|
||||
private static final String LOGIN_URL = "https://uapi.woobx.cn/user/login";
|
||||
private static final String DETECT_URL = "https://uapi.woobx.cn/app/object-det/bamboo-stick";
|
||||
// 请求超时时间(毫秒)
|
||||
private static final int TIMEOUT = 10000;
|
||||
|
||||
/**
|
||||
* 登录接口 - 获取认证Token(线程安全)
|
||||
*
|
||||
* @return 认证Token
|
||||
*/
|
||||
public static String login(String username, String password) {
|
||||
// 构建登录请求
|
||||
HttpResponse response = HttpRequest.post(LOGIN_URL)
|
||||
.form("username", username)
|
||||
.form("password", password)
|
||||
.timeout(TIMEOUT)
|
||||
.execute();
|
||||
// 校验响应状态
|
||||
if (!response.isOk()) {
|
||||
log.error("登录失败,响应码:{},数据:{}", response.getStatus(), response.body());
|
||||
throw new CzgException("登录失败");
|
||||
}
|
||||
|
||||
// 解析响应结果
|
||||
String responseStr = response.body();
|
||||
JSONObject result = JSON.parseObject(responseStr);
|
||||
if (200 != result.getIntValue("code")) {
|
||||
log.error("登录失败,响应码:{},数据:{}", response.getStatus(), result);
|
||||
throw new CzgException("登录失败");
|
||||
}
|
||||
|
||||
// 提取并缓存Token
|
||||
String token = result.getJSONObject("data").getString("authToken");
|
||||
if (StrUtil.isBlank(token)) {
|
||||
log.error("登录失败,响应码:{},数据:{}", response.getStatus(), result);
|
||||
throw new CzgException("登录失败");
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* 竹签识别核心方法(自动处理Token过期重试)
|
||||
*
|
||||
* @param imageBase64 图片Base64编码字符串
|
||||
* @return 识别结果JSON对象
|
||||
* @throws Exception 识别异常
|
||||
*/
|
||||
public static int detectBambooStick(String imageBase64, String token) throws Exception {
|
||||
// 参数校验
|
||||
if (StrUtil.isBlank(imageBase64)) {
|
||||
throw new CzgException("图片Base64编码不能为空");
|
||||
}
|
||||
// 第一次调用识别接口
|
||||
JSONObject detectResult = doDetectRequest(imageBase64, token);
|
||||
return MuSmartCountUtils.countBambooStick(detectResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行竹签识别请求(核心请求逻辑)
|
||||
*
|
||||
* @param imageBase64 图片Base64编码
|
||||
* @param token 认证Token
|
||||
* @return 识别结果
|
||||
*/
|
||||
private static JSONObject doDetectRequest(String imageBase64, String token){
|
||||
// 构建识别请求
|
||||
HttpResponse response = HttpRequest.post(DETECT_URL)
|
||||
.header("authorization", "Bearer " + token)
|
||||
.form("image", imageBase64)
|
||||
.form("base64", "true")
|
||||
.timeout(TIMEOUT)
|
||||
.execute();
|
||||
|
||||
// 校验响应状态
|
||||
if (!response.isOk()) {
|
||||
throw new RuntimeException("识别请求失败,响应码:" + response.getStatus());
|
||||
}
|
||||
|
||||
// 解析响应结果
|
||||
String responseStr = response.body();
|
||||
return JSON.parseObject(responseStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析识别结果,统计竹签数量(自定义分数阈值)
|
||||
*
|
||||
* @param detectResult 识别结果JSON
|
||||
* @return 竹签数量
|
||||
*/
|
||||
private static int countBambooStick(JSONObject detectResult) {
|
||||
// 参数校验
|
||||
if (detectResult == null || 200 != detectResult.getIntValue("code")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
JSONArray dataArray = detectResult.getJSONArray("data");
|
||||
if (dataArray == null || dataArray.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
return dataArray.size();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.czg.service.product.mapper.MkOcrCountStickMapper">
|
||||
|
||||
</mapper>
|
||||
@@ -95,7 +95,8 @@
|
||||
t1.pack_fee,
|
||||
ifnull(t4.sales_volume, 0) as sales_volume,
|
||||
t1.shop_id,
|
||||
t1.is_stock
|
||||
t1.is_stock,
|
||||
t1.related_recommend
|
||||
from tb_product t1
|
||||
left join (select x.product_id,
|
||||
x.id as sku_id,
|
||||
@@ -147,6 +148,12 @@
|
||||
and t2.sale_price is not null
|
||||
and t1.shop_id = #{shopId}
|
||||
</where>
|
||||
<if test="idList != null">
|
||||
and t1.id in
|
||||
<foreach item="item" collection="idList" separator="," open="(" close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
order by t1.sort desc,t1.id desc
|
||||
</select>
|
||||
<select id="selectOneProductInfo" resultType="com.czg.product.vo.ShopProductInfoVo">
|
||||
|
||||
@@ -12,6 +12,9 @@ import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 验证码工具类
|
||||
*
|
||||
@@ -23,38 +26,24 @@ public class SmsServiceImpl implements SmsService {
|
||||
@Resource
|
||||
private SysParamsService sysParamsService;
|
||||
|
||||
/**
|
||||
* 阿里云key
|
||||
*/
|
||||
private String key;
|
||||
/**
|
||||
* 阿里云secret
|
||||
*/
|
||||
private String secret;
|
||||
/**
|
||||
* 短信模板id
|
||||
*/
|
||||
private String templateCode;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
key = sysParamsService.getSysParamValue(ParamCodeCst.AliYun.ALI_SMS_KEY);
|
||||
secret = sysParamsService.getSysParamValue(ParamCodeCst.AliYun.ALI_SMS_SECRET);
|
||||
templateCode = sysParamsService.getSysParamValue(ParamCodeCst.AliYun.ALI_SMS_TEMPLATE_CODE);
|
||||
log.info("短信工具类初始化完毕,key: {}, secret: {}, templateCode: {}", key, secret, templateCode);
|
||||
}
|
||||
|
||||
public Client createClient() throws Exception {
|
||||
public Client init() throws Exception {
|
||||
Config config = new Config();
|
||||
config.accessKeyId = key;
|
||||
config.accessKeySecret = secret;
|
||||
Map<String, String> aliOssKeys = sysParamsService.getParamsByMap("ali_oss_key_set", ParamCodeCst.ALI_OSS_KEY_SET);
|
||||
config.accessKeyId = aliOssKeys.get(ParamCodeCst.AliYun.ALI_SMS_KEY);
|
||||
config.accessKeySecret = aliOssKeys.get(ParamCodeCst.AliYun.ALI_SMS_SECRET);
|
||||
templateCode = aliOssKeys.get(ParamCodeCst.AliYun.ALI_SMS_TEMPLATE_CODE);
|
||||
return new Client(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendCode(String phone, String checkCode) {
|
||||
try {
|
||||
Client client = createClient();
|
||||
Client client = init();
|
||||
// 1.发送短信
|
||||
com.aliyun.dysmsapi20170525.models.SendSmsRequest sendSmsRequest = new com.aliyun.dysmsapi20170525.models.SendSmsRequest()
|
||||
.setSignName("陕西超掌柜科技")
|
||||
@@ -67,7 +56,7 @@ public class SmsServiceImpl implements SmsService {
|
||||
if (sendSmsResponse.getStatusCode() != 200) {
|
||||
throw new CzgException("短信发送失败");
|
||||
}
|
||||
}catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
log.info("发送短信失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.czg.service.system.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.system.mapper.SysParamsMapper;
|
||||
@@ -11,11 +13,11 @@ import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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 org.springframework.cache.annotation.Caching;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 服务层实现。
|
||||
@@ -25,7 +27,6 @@ import java.util.List;
|
||||
*/
|
||||
@Slf4j
|
||||
@DubboService
|
||||
@CacheConfig(cacheNames = "params")
|
||||
public class SysParamsServiceImpl extends ServiceImpl<SysParamsMapper, SysParams> implements SysParamsService {
|
||||
|
||||
@Override
|
||||
@@ -62,7 +63,10 @@ public class SysParamsServiceImpl extends ServiceImpl<SysParamsMapper, SysParams
|
||||
}
|
||||
|
||||
@Override
|
||||
@CacheEvict(key = "#paramsDTO.paramCode")
|
||||
@Caching(evict = {
|
||||
@CacheEvict(cacheNames = "params:entity", allEntries = true),
|
||||
@CacheEvict(cacheNames = "params", key = "#paramsDTO.paramCode")
|
||||
})
|
||||
public CzgResult<String> updateParams(SysParamsDTO paramsDTO) {
|
||||
// 查询 paramCode 是否存在
|
||||
SysParams sysParams = getOne(new QueryWrapper().eq(SysParams::getParamCode, paramsDTO.getParamCode())
|
||||
@@ -90,7 +94,10 @@ public class SysParamsServiceImpl extends ServiceImpl<SysParamsMapper, SysParams
|
||||
}
|
||||
|
||||
@Override
|
||||
@CacheEvict(key = "#code")
|
||||
@Caching(evict = {
|
||||
@CacheEvict(cacheNames = "params:entity", allEntries = true),
|
||||
@CacheEvict(cacheNames = "params", key = "#code")
|
||||
})
|
||||
public CzgResult<Boolean> deleteParams(String code) {
|
||||
SysParams sysParams = getById(code);
|
||||
if (sysParams == null) {
|
||||
@@ -130,4 +137,18 @@ public class SysParamsServiceImpl extends ServiceImpl<SysParamsMapper, SysParams
|
||||
}
|
||||
return sysParam.getParamValue();
|
||||
}
|
||||
|
||||
@Cacheable(cacheNames = "params:entity", key = "#type")
|
||||
@Override
|
||||
public Map<String, String> getParamsByMap(String type, Set<String> keyList) throws CzgException {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
for (String key : keyList) {
|
||||
SysParams sysParam = getSysParam(key);
|
||||
if (sysParam == null || StrUtil.isBlank(sysParam.getParamValue())) {
|
||||
throw new CzgException("sysParam的类型" + type + " 的 " + key + "参数不存在");
|
||||
}
|
||||
map.put(key, sysParam.getParamValue());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user