diff --git a/eladmin-common/src/main/java/cn/ysk/cashier/utils/FileUtil.java b/eladmin-common/src/main/java/cn/ysk/cashier/utils/FileUtil.java index 36c88ff1..ae33d9f2 100644 --- a/eladmin-common/src/main/java/cn/ysk/cashier/utils/FileUtil.java +++ b/eladmin-common/src/main/java/cn/ysk/cashier/utils/FileUtil.java @@ -17,14 +17,19 @@ package cn.ysk.cashier.utils; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.poi.excel.BigExcelWriter; import cn.hutool.poi.excel.ExcelUtil; +import cn.hutool.poi.excel.ExcelWriter; import cn.ysk.cashier.exception.BadRequestException; +import org.apache.poi.ss.usermodel.*; import org.apache.poi.util.IOUtils; import org.apache.poi.xssf.streaming.SXSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFSheet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.multipart.MultipartFile; + import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -154,7 +159,7 @@ public class FileUtil extends cn.hutool.core.io.FileUtil { /** * inputStream 转 File */ - static File inputStreamToFile(InputStream ins, String name){ + static File inputStreamToFile(InputStream ins, String name) { File file = new File(SYS_TEM_DIR + name); if (file.exists()) { return file; @@ -215,7 +220,7 @@ public class FileUtil extends cn.hutool.core.io.FileUtil { BigExcelWriter writer = ExcelUtil.getBigWriter(file); // 一次性写出内容,使用默认样式,强制输出标题 writer.write(list, true); - SXSSFSheet sheet = (SXSSFSheet)writer.getSheet(); + SXSSFSheet sheet = (SXSSFSheet) writer.getSheet(); //上面需要强转SXSSFSheet 不然没有trackAllColumnsForAutoSizing方法 sheet.trackAllColumnsForAutoSizing(); //列宽自适应 @@ -232,29 +237,71 @@ public class FileUtil extends cn.hutool.core.io.FileUtil { IoUtil.close(out); } + /** + * 输入标题到excel + * + * @param writer excel对象 + * @param column 当前列位置 + * @param cellValue 标题内容 + * @param requiredFlag 是否标红 + */ + private static void writeCell(ExcelWriter writer, int column, int row, String cellValue, boolean requiredFlag) { + // 根据x,y轴设置单元格内容 + if (StrUtil.isNotBlank(cellValue)) { + writer.writeCellValue(column, row, cellValue); + } + Font font = writer.createFont(); + font.setColor(Font.COLOR_RED); + if (requiredFlag) { + // 根据x,y轴获取当前单元格样式 + CellStyle cellStyle = writer.createCellStyle(column, row); + // 内容水平居中 + cellStyle.setAlignment(HorizontalAlignment.CENTER); + // 内容垂直居中 + cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); + // 设置边框 + cellStyle.setBorderBottom(BorderStyle.THIN); + cellStyle.setBorderLeft(BorderStyle.THIN); + cellStyle.setBorderRight(BorderStyle.THIN); + // 字体颜色标红 +// cellStyle.setFont(font); + cellStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex()); + cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + } + } + public static void downloadExcelAndMerge(List> list, int colSize, HttpServletResponse response, ArrayList mergeRowIndex) throws IOException { String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx"; File file = new File(tempPath); - BigExcelWriter writer = ExcelUtil.getBigWriter(file); - - // 合并单元格后的标题行,使用默认标题样式. + ExcelWriter writer = ExcelUtil.getWriter(file); for (int i = 0; i < mergeRowIndex.size(); i++) { - System.out.println(i); + + int start = i == 0 ? 1 : mergeRowIndex.get(i - 1) + 1; for (int i1 = 0; i1 < colSize; i1++) { - writer.merge(i == 0 ? 0 : mergeRowIndex.get(i - 1) + 1, mergeRowIndex.get(i), i1, i1, "", true); + + if (start != mergeRowIndex.get(i)) { + writer.merge(i == 0 ? 1 : mergeRowIndex.get(i - 1) + 1, mergeRowIndex.get(i), i1, i1, "", true); + } } } + // 一次性写出内容,使用默认样式,强制输出标题 writer.write(list, true); - SXSSFSheet sheet = (SXSSFSheet)writer.getSheet(); + + XSSFSheet sheet = (XSSFSheet) writer.getSheet(); + // 设置列宽 + for (int i = 0; i < colSize + 2; i++) { + sheet.setColumnWidth(i, 4000); // 200个字符宽度 + } //上面需要强转SXSSFSheet 不然没有trackAllColumnsForAutoSizing方法 - sheet.trackAllColumnsForAutoSizing(); +// sheet.trackAllColumnsForAutoSizing(); //列宽自适应 - writer.autoSizeColumnAll(); +// writer.autoSizeColumnAll(); //response为HttpServletResponse对象 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"); //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码 response.setHeader("Content-Disposition", "attachment;filename=file.xlsx"); + // 将写入的Excel作为文件流写出到response ServletOutputStream out = response.getOutputStream(); // 终止后删除临时文件 file.deleteOnExit(); @@ -295,7 +342,7 @@ public class FileUtil extends cn.hutool.core.io.FileUtil { public static boolean check(File file1, File file2) { String img1Md5 = getMd5(file1); String img2Md5 = getMd5(file2); - if(img1Md5 != null){ + if (img1Md5 != null) { return img1Md5.equals(img2Md5); } return false; diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/controller/product/StockController.java b/eladmin-system/src/main/java/cn/ysk/cashier/controller/product/StockController.java index 8326bb57..a41c8e77 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/controller/product/StockController.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/controller/product/StockController.java @@ -1,15 +1,11 @@ package cn.ysk.cashier.controller.product; import cn.hutool.core.util.StrUtil; -import cn.ysk.cashier.annotation.AnonymousAccess; import cn.ysk.cashier.annotation.Log; -import cn.ysk.cashier.annotation.rest.AnonymousPostMapping; import cn.ysk.cashier.dto.product.StockQueryDto; import cn.ysk.cashier.exception.BadRequestException; import cn.ysk.cashier.service.product.StockService; import cn.ysk.cashier.utils.BeanUtil; -import cn.ysk.cashier.utils.SecurityUtils; -import cn.ysk.cashier.vo.StockPageImpl; import cn.ysk.cashier.vo.StockUpdateValueVO; import cn.ysk.cashier.vo.StockUpdateWarnLineVO; import cn.ysk.cashier.vo.StockV2Vo; @@ -18,15 +14,12 @@ import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; import java.io.IOException; import java.util.Map; diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/entity/TbShopOpenId.java b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/entity/TbShopOpenId.java new file mode 100644 index 00000000..72c687f3 --- /dev/null +++ b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/entity/TbShopOpenId.java @@ -0,0 +1,59 @@ +package cn.ysk.cashier.mybatis.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; +import javax.persistence.Column; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 商家openid信息表 + * @TableName tb_shop_open_id + */ +@Table(name="tb_shop_open_id") +@Data +@EqualsAndHashCode +public class TbShopOpenId implements Serializable { + /** + * + */ + @Id + private Integer id; + + /** + * 店铺id + */ + private Integer shopId; + + /** + * 已经订阅消息的商家微信号 + */ + private String openId; + + /** + * + */ + private Integer status; + + /** + * + */ + private LocalDateTime createTime; + + /** + * + */ + private LocalDateTime updateTime; + + /** + * 类型 -1 任意消息 0库存预警 + */ + private Integer type; + + private static final long serialVersionUID = 1L; + + +} diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/mapper/TbShopOpenIdMapper.java b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/mapper/TbShopOpenIdMapper.java new file mode 100644 index 00000000..3e088ed0 --- /dev/null +++ b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/mapper/TbShopOpenIdMapper.java @@ -0,0 +1,18 @@ +package cn.ysk.cashier.mybatis.mapper; + +import cn.ysk.cashier.mybatis.entity.TbShopOpenId; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author Administrator +* @description 针对表【tb_shop_open_id(商家openid信息表)】的数据库操作Mapper +* @createDate 2024-08-02 10:00:27 +* @Entity cn.ysk.cashier.mybatis.entity.TbShopOpenId +*/ +public interface TbShopOpenIdMapper extends BaseMapper { + +} + + + + diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/TbShopOpenIdService.java b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/TbShopOpenIdService.java new file mode 100644 index 00000000..554107d5 --- /dev/null +++ b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/TbShopOpenIdService.java @@ -0,0 +1,13 @@ +package cn.ysk.cashier.mybatis.service; + +import cn.ysk.cashier.mybatis.entity.TbShopOpenId; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author Administrator +* @description 针对表【tb_shop_open_id(商家openid信息表)】的数据库操作Service +* @createDate 2024-08-02 10:00:27 +*/ +public interface TbShopOpenIdService extends IService { + +} diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/impl/TbShopOpenIdServiceImpl.java b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/impl/TbShopOpenIdServiceImpl.java new file mode 100644 index 00000000..bf99c448 --- /dev/null +++ b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/impl/TbShopOpenIdServiceImpl.java @@ -0,0 +1,22 @@ +package cn.ysk.cashier.mybatis.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import cn.ysk.cashier.mybatis.entity.TbShopOpenId; +import cn.ysk.cashier.mybatis.service.TbShopOpenIdService; +import cn.ysk.cashier.mybatis.mapper.TbShopOpenIdMapper; +import org.springframework.stereotype.Service; + +/** +* @author Administrator +* @description 针对表【tb_shop_open_id(商家openid信息表)】的数据库操作Service实现 +* @createDate 2024-08-02 10:00:27 +*/ +@Service +public class TbShopOpenIdServiceImpl extends ServiceImpl + implements TbShopOpenIdService{ + +} + + + + diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/repository/product/TbProductRepository.java b/eladmin-system/src/main/java/cn/ysk/cashier/repository/product/TbProductRepository.java index 01e2ae64..86bc5ffc 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/repository/product/TbProductRepository.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/repository/product/TbProductRepository.java @@ -62,4 +62,6 @@ public interface TbProductRepository extends JpaRepository, @Query("select product from TbProduct product where product.shopId=:shopId") List selectByShopId(String shopId); + @Query(value = "select b.* from tb_product_sku as a left join tb_product as b on a.product_id=b.id where a.id=:skuId", nativeQuery = true) + TbProduct selectBySkuId(@Param("skuId") Integer skuId); } diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/SummaryServiceImpl.java b/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/SummaryServiceImpl.java index d7b4ff6f..15c158ca 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/SummaryServiceImpl.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/SummaryServiceImpl.java @@ -467,7 +467,7 @@ public class SummaryServiceImpl implements SummaryService { }); } - FileUtil.downloadExcelAndMerge(list, 12, response, mergeRowIndex); + FileUtil.downloadExcelAndMerge(list, 10, response, mergeRowIndex); } @Override diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/productimpl/StockServiceImpl.java b/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/productimpl/StockServiceImpl.java index 25363231..4511db70 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/productimpl/StockServiceImpl.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/productimpl/StockServiceImpl.java @@ -17,10 +17,7 @@ import cn.ysk.cashier.repository.shop.TbShopUnitRepository; import cn.ysk.cashier.service.TbProductStockOperateService; import cn.ysk.cashier.service.product.StockService; import cn.ysk.cashier.service.product.TbProductService; -import cn.ysk.cashier.utils.CacheKey; -import cn.ysk.cashier.utils.FileUtil; -import cn.ysk.cashier.utils.RedisUtils; -import cn.ysk.cashier.utils.StringUtils; +import cn.ysk.cashier.utils.*; import cn.ysk.cashier.vo.StockUpdateValueVO; import cn.ysk.cashier.vo.StockUpdateWarnLineVO; import cn.ysk.cashier.vo.StockV2Vo; @@ -62,6 +59,7 @@ public class StockServiceImpl implements StockService { private final TbShopUnitRepository shopUnitRepository; private final TbProductStockDetailRepository tbProductStockDetailRepository; private final TbProductRepository tbProductRepository; + private final WxMsgUtils wxMsgUtils; @PersistenceContext private EntityManager em; @@ -349,6 +347,15 @@ public class StockServiceImpl implements StockService { Query nativeQuery = em.createNativeQuery(String.valueOf(sqlQuery)); nativeQuery.executeUpdate(); + + TbProduct product = tbProductRepository.selectBySkuId(Integer.valueOf(updateValueVO.getTargetId())); + TbProductSku tbProductSku = tbProductSkuRepository.findById(Integer.valueOf(updateValueVO.getTargetId())).orElse(null); + // 推送微信操作消息 + if (product != null && tbProductSku != null) { + wxMsgUtils.aboardOperationMsg(("0".equals(updateValueVO.getUpdateValue()) ? "关闭sku售罄: " : "开启sku售罄: ") + product.getName() + "/"+ tbProductSku.getSpecSnap()); + }else { + log.warn("推送微信操作消息失败,未查询到商品信息,skuId: {}", updateValueVO.getTargetId()); + } return; case "stock": sqlQuery.append(" set is_stock = ").append(updateValueVO.getUpdateValue()); @@ -358,6 +365,13 @@ public class StockServiceImpl implements StockService { break; case "pauseSale": sqlQuery.append(" set is_pause_sale = ").append(updateValueVO.getUpdateValue()); + TbProduct product1 = tbProductRepository.selectBySkuId(Integer.valueOf(updateValueVO.getTargetId())); + // 推送微信操作消息 + if (product1 != null) { + wxMsgUtils.aboardOperationMsg(("0".equals(updateValueVO.getUpdateValue()) ? "关闭售罄: " : "开启售罄: ") + product1.getName()); + }else { + log.warn("推送微信操作消息失败,未查询到商品信息,skuId: {}", updateValueVO.getTargetId()); + } break; default: throw new BadRequestException("无效更新类型"); @@ -393,7 +407,10 @@ public class StockServiceImpl implements StockService { if (tbProductSku == null) { throw new BadRequestException("商品不存在,skuId: " + skuId); } + TbProduct product = tbProductRepository.selectByShopIdAndId(Integer.parseInt(tbProductSku.getProductId()), String.valueOf(shopId)); + // 推送微信操作消息 + wxMsgUtils.aboardOperationMsg((isGrounding ? "上架商品: " : "下架商品: ") + product.getName()); // 共享库存下架所有sku if (product.getIsDistribute().equals(1)) { tbProductSkuRepository.updateGroundingByProId(product.getId().toString(), isGrounding ? 1 : 0); diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/productimpl/TbProductGroupServiceImpl.java b/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/productimpl/TbProductGroupServiceImpl.java index 89bbc6cc..bb84510a 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/productimpl/TbProductGroupServiceImpl.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/productimpl/TbProductGroupServiceImpl.java @@ -46,6 +46,7 @@ public class TbProductGroupServiceImpl implements TbProductGroupService { private final TbProductGroupRepository tbProductGroupRepository; private final TbProductGroupMapper tbProductGroupMapper; private final TbProductRepository tbProductRepository; + private final WxMsgUtils wxMsgUtils; @Resource private OnlineUserService onlineUserService; @@ -104,6 +105,9 @@ public class TbProductGroupServiceImpl implements TbProductGroupService { ValidationUtil.isNull( tbProductGroup.getId(),"TbProductGroup","id",resources.getId()); tbProductGroup.copy(resources); tbProductGroupRepository.save(tbProductGroup); + + // 推送微信操作消息 + wxMsgUtils.aboardOperationMsg((resources.getIsShow() == 0 ? "关闭分组: " : "开启分组: ") + tbProductGroup.getName()); } @Transactional(rollbackFor = Exception.class) @@ -224,4 +228,4 @@ public class TbProductGroupServiceImpl implements TbProductGroupService { -} \ No newline at end of file +} diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/productimpl/TbProductStocktakinServiceImpl.java b/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/productimpl/TbProductStocktakinServiceImpl.java index 2f953ab9..ed5c51ce 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/productimpl/TbProductStocktakinServiceImpl.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/productimpl/TbProductStocktakinServiceImpl.java @@ -160,6 +160,7 @@ public class TbProductStocktakinServiceImpl implements TbProductStocktakinServic round = (int) Math.floor( productSku.getStockNumber()); + productStockDetail.setSpecSnap(productSku.getSpecSnap()); productStockDetail.setSubType(productStocktakinDTO.getStocktakinNum() > productSku.getStockNumber() ? 1 : -1); stockOperate.setType(productStocktakinDTO.getStocktakinNum() > productSku.getStockNumber() ? "盘点入库" : "盘点出库"); diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/utils/WxAccountUtil.java b/eladmin-system/src/main/java/cn/ysk/cashier/utils/WxAccountUtil.java new file mode 100644 index 00000000..409d60ed --- /dev/null +++ b/eladmin-system/src/main/java/cn/ysk/cashier/utils/WxAccountUtil.java @@ -0,0 +1,126 @@ +package cn.ysk.cashier.utils; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpUtil; +import cn.ysk.cashier.mybatis.entity.TbShopOpenId; +import com.alibaba.fastjson.JSONObject; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@Data +@Slf4j +@Component +public class WxAccountUtil { + @Value("${wx.ysk.appId}") + private String appId = "wx212769170d2c6b2a"; + @Value("${wx.ysk.secrete}") + private String secrete = "8492a7e8d55bbb1b57f5c8276ea1add0"; + @Value("${wx.ysk.operationMsgTmpId}") + private String operationMsgTmpId ; + + static LinkedHashMap linkedHashMap=new LinkedHashMap<>(); + + static { + + linkedHashMap.put("40001","获取 access_token 时 AppSecret 错误,或者 access_token 无效。请开发者认真比对 AppSecret 的正确性,或查看是否正在为恰当的公众号调用接口"); + linkedHashMap.put("40003","不合法的 OpenID ,请开发者确认 OpenID (该用户)是否已关注公众号,或是否是其他公众号的 OpenID"); + linkedHashMap.put("40014","不合法的 access_token ,请开发者认真比对 access_token 的有效性(如是否过期),或查看是否正在为恰当的公众号调用接口"); + linkedHashMap.put("40037","不合法的 template_id"); + linkedHashMap.put("43101","用户未订阅消息"); + linkedHashMap.put("43107","订阅消息能力封禁"); + linkedHashMap.put("43108","并发下发消息给同一个粉丝"); + linkedHashMap.put("45168","命中敏感词"); + linkedHashMap.put("47003","参数错误"); + + } + + public static void main(String[] args) { +// sendStockWarnMsg("13213", "31123", "234", "ojC-S6n2DDlpj52iVMoiLL0Ry4HI"); + } + + public String getRadarQrCode(Integer shopId) { + HashMap req = new HashMap<>(); + req.put("expire_seconds", 300); + req.put("action_name", "QR_STR_SCENE"); + HashMap actionInfo = new HashMap<>(); + HashMap scene = new HashMap<>(); + scene.put("scene_str", "msg" + shopId); + actionInfo.put("scene", scene); + req.put("action_info", actionInfo); + log.info("开始获取公众号二维码, 请求数据: {}", req); + String resp = HttpUtil.post("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + getAccessToken(), JSONObject.toJSONString(req)); + JSONObject respInfo = JSONObject.parseObject(resp); + log.warn("获取微信公众号二维码结束,响应: {}", resp); + if (!respInfo.containsKey("url")) { + log.warn("获取微信公众号二维码失败,响应: {}", resp); + throw new RuntimeException(resp); + } + return respInfo.getString("url"); + } + + + public String getAccessToken() { + String resp = HttpUtil.get(StrUtil.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}", appId, secrete)); + JSONObject respInfo = JSONObject.parseObject(resp); + if (!respInfo.containsKey("access_token")) { + log.warn("公众号获取token失败, 响应内容: {}", resp); + throw new RuntimeException(resp); + } + return respInfo.getString("access_token"); + } + + public JSONObject sendTemplateMsg(String templateId, String toUserOpenId, Map data) { + log.info("开始发送微信模板消息, 接收用户openId: {}, 消息数据: {}", toUserOpenId, data); + String accessToken = getAccessToken(); + + JSONObject object1=new JSONObject(); + + object1.put("template_id", templateId); + object1.put("touser", toUserOpenId); + object1.put("data",data); + + String response= HttpRequest.post("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=".concat(accessToken)).body(object1.toString()).execute().body(); + log.info("微信模板消息发送成功,响应内容:{}",response); + JSONObject resObj=JSONObject.parseObject(response); + if(ObjectUtil.isNotEmpty(resObj)&&ObjectUtil.isNotNull(resObj)&&"0".equals(resObj.get("errcode")+"")){ + return resObj; + } + + throw new RuntimeException(linkedHashMap.getOrDefault(resObj.get("errcode") + "", "未知错误")); + } + + @Async + public void sendOperationMsg(List openIds, String userName, String operationDesc) { + openIds.forEach(item -> { + Map data = new HashMap() {{ + put("thing19", new HashMap(){{ + put("value", userName); + }}); + put("thing8", new HashMap(){{ + put("value", operationDesc); + }}); + put("time21", new HashMap(){{ + put("value", DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss")); + }}); + }}; + log.info("开始发送敏感操作消息, 接收用户openId: {}, 操作用户: {}, 操作描述: {}", item.getOpenId(), userName, operationDesc); + try { + sendTemplateMsg(operationMsgTmpId, item.getOpenId(), data); + }catch (Exception e) { + log.error("发送失败, openId: {}, 响应: {}", item.getOpenId(), e.getMessage()); + } + }); + + } +} diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/utils/WxMsgUtils.java b/eladmin-system/src/main/java/cn/ysk/cashier/utils/WxMsgUtils.java new file mode 100644 index 00000000..79d74135 --- /dev/null +++ b/eladmin-system/src/main/java/cn/ysk/cashier/utils/WxMsgUtils.java @@ -0,0 +1,58 @@ +package cn.ysk.cashier.utils; + +import cn.ysk.cashier.mybatis.entity.TbShopOpenId; +import cn.ysk.cashier.mybatis.service.TbShopOpenIdService; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +@Component +@Slf4j +public class WxMsgUtils { + + private final TbShopOpenIdService tbShopOpenIdService; + + private final RedisUtils redisUtils; + + private final WxAccountUtil wxAccountUtil; + + public WxMsgUtils(TbShopOpenIdService tbShopOpenIdService, RedisUtils redisUtils, WxAccountUtil wxAccountUtil) { + this.tbShopOpenIdService = tbShopOpenIdService; + this.redisUtils = redisUtils; + this.wxAccountUtil = wxAccountUtil; + } + + public void aboardOperationMsg(String operationDesc) { + HttpServletRequest request = RequestHolder.getHttpServletRequest(); + + Object o = redisUtils.get("online-token-"+getToken(request)); + JSONObject jsonObject; + Integer shopId; + String nickName; + if (o != null) { + String jsonString = JSON.toJSONString(o); + jsonObject = JSONObject.parseObject(jsonString); + shopId = (Integer) jsonObject.get("shopId"); + nickName = jsonObject.get("nickName") == null ? "" : jsonObject.get("nickName").toString(); + List openIds = tbShopOpenIdService.lambdaQuery().eq(TbShopOpenId::getShopId, shopId).list(); + log.info("即将开始推送敏感操作消息, 接收推送openId列表: {}", openIds); + String finalNickName = nickName; + wxAccountUtil.sendOperationMsg(openIds, finalNickName, operationDesc); + }else { + log.warn("发送敏感操作预警失败,未获取到登录信息"); + } + } + + public String getToken(HttpServletRequest request) { + final String requestHeader = request.getHeader("Authorization"); + if (requestHeader != null && requestHeader.startsWith("Bearer")) { + return requestHeader.substring(7); + } + return null; + } +} diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/vo/TbOrderSaleVO.java b/eladmin-system/src/main/java/cn/ysk/cashier/vo/TbOrderSaleVO.java new file mode 100644 index 00000000..667e3ebe --- /dev/null +++ b/eladmin-system/src/main/java/cn/ysk/cashier/vo/TbOrderSaleVO.java @@ -0,0 +1,17 @@ +package cn.ysk.cashier.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class TbOrderSaleVO { + private String orderNo; + private Integer num; + private BigDecimal price; + private String status; +} diff --git a/eladmin-system/src/main/resources/config/application.yml b/eladmin-system/src/main/resources/config/application.yml index 79bfa777..752a7fc8 100644 --- a/eladmin-system/src/main/resources/config/application.yml +++ b/eladmin-system/src/main/resources/config/application.yml @@ -78,3 +78,9 @@ aliyun: oss: bucketname: cashier-oss endpoint: oss-cn-beijing.aliyuncs.com + +wx: + ysk: + appId: wx212769170d2c6b2a + secrete: 8492a7e8d55bbb1b57f5c8276ea1add0 + operationMsgTmpId: wFdoUG-dUT7bDRHq8bMJD9CF5TjyH9x_uJQgQByZqHg diff --git a/eladmin-system/src/main/resources/mapper/TbShopOpenIdMapper.xml b/eladmin-system/src/main/resources/mapper/TbShopOpenIdMapper.xml new file mode 100644 index 00000000..131b90c7 --- /dev/null +++ b/eladmin-system/src/main/resources/mapper/TbShopOpenIdMapper.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + id,shop_id,open_id, + status,create_time,update_time, + type + +