微信通知功能

This commit is contained in:
13405411873 2025-04-28 15:02:09 +08:00
parent 975050e5d6
commit 68cd9bc6cc
14 changed files with 331 additions and 11 deletions

View File

@ -17,6 +17,12 @@
<dependencies>
<!--微信支付SDK-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>

View File

@ -55,4 +55,8 @@ public class WxMsgApi {
}
}

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.base.domain.BaseCity;
import com.ruoyi.base.service.IBaseCityService;
import com.ruoyi.base.vo.BaseCityVO;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
@ -48,6 +49,7 @@ public class BaseCityController extends BaseController {
* @date 15:11 2025/4/2
**/
@GetMapping("/treeCity")
@Anonymous
public AjaxResult treeCity() {
List<BaseCityVO> list = baseCityService.treeCity();
return success(list);

View File

@ -133,14 +133,9 @@ public class BusiNoticeController extends BaseController
@Log(title = "通告", businessType = BusinessType.INSERT)
@PostMapping("saveOrUpdate")
public AjaxResult saveOrUpdate(@RequestBody BusiNotice busiNotice)
{
public AjaxResult saveOrUpdate(@RequestBody BusiNotice busiNotice) throws Exception {
JSONObject res = new JSONObject();
try{
res.put("noticeId", busiNoticeService.saveOrUpdateVo(busiNotice));
} catch (Exception e){
return error(e.getMessage());
}
res.put("noticeId", busiNoticeService.saveOrUpdateVo(busiNotice));
return success(res);
}

View File

@ -1,5 +1,6 @@
package com.ruoyi.busi.controller;
import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.busi.domain.BusiSubscribe;
@ -14,6 +15,8 @@ import com.ruoyi.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
/**
* 订阅Controller
*
@ -60,6 +63,16 @@ public class BusiSubscribeController extends BaseController {
SubscribeDataObj subscribeDataObj = JSONObject.parseObject(busiSubscribe.getJsonObj(), SubscribeDataObj.class);
busiSubscribe.setNewNotice(subscribeDataObj.getNewNotice()?"1":"0");
busiSubscribe.setForkNotice(subscribeDataObj.getForkNotice()?"1":"0");
busiSubscribe.setBloggerTypeCode(String.join(",", subscribeDataObj.getBloggerTypeCode()));
busiSubscribe.setPlatformCode(String.join(",", subscribeDataObj.getPlatformCode()));
busiSubscribe.setSettleTypeCode(subscribeDataObj.getSettleTypeCode());
busiSubscribe.setKeywordsList(String.join(",", subscribeDataObj.getKeywordsList()));
busiSubscribe.setFansLimit(subscribeDataObj.getFansLimit()?"1":"0");
busiSubscribe.setFeeLimit(subscribeDataObj.getFeeLimit()?"1":"0");
busiSubscribe.setFansUp(subscribeDataObj.getFansUp());
busiSubscribe.setFansDown(subscribeDataObj.getFansDown());
busiSubscribe.setFeeUp(subscribeDataObj.getFeeUp());
busiSubscribe.setFeeDown(subscribeDataObj.getFeeDown());
busiSubscribeService.saveOrUpdate(busiSubscribe);
return success();
}

View File

@ -7,6 +7,8 @@ import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import com.ruoyi.common.core.domain.DlBaseEntity;
import java.util.List;
/**
* 请填写功能名称对象 dl_busi_subscribe
*
@ -37,4 +39,25 @@ public class BusiSubscribe extends DlBaseEntity
//订阅通告主新通告0否 1是
private String forkNotice;
//领域 博主类型
private String bloggerTypeCode;
//平台
private String platformCode;
//结算方式类型
private String settleTypeCode;
//关键词
private String keywordsList;
//粉丝数量是否限制
private String fansLimit;
//粉丝数量上限
private Integer fansUp;
//粉丝数量下限
private Integer fansDown;
//费用是否限制
private String feeLimit;
//费用上限
private Double feeDown;
//费用下限
private Double feeUp;
}

View File

@ -1,9 +1,13 @@
package com.ruoyi.busi.mapper;
import java.util.List;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.busi.domain.BusiSubscribe;
import com.ruoyi.busi.vo.SubScribeQuery;
import com.ruoyi.busi.vo.SubscribeDataObj;
import org.apache.ibatis.annotations.Param;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@ -17,4 +21,5 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BusiSubscribeMapper extends BaseMapper<BusiSubscribe>
{
List<JSONObject> getOkUser(SubScribeQuery subscribeDataObj);
}

View File

@ -1,10 +1,14 @@
package com.ruoyi.busi.service;
import java.util.List;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.busi.domain.BusiSubscribe;
import com.ruoyi.busi.vo.SubScribeQuery;
import com.ruoyi.busi.vo.SubscribeDataObj;
/**
* 订阅Service接口
@ -14,4 +18,6 @@ import com.ruoyi.busi.domain.BusiSubscribe;
*/
public interface IBusiSubscribeService extends IService<BusiSubscribe>
{
List<JSONObject> getOkUser(SubScribeQuery subscribeDataObj);
}

View File

@ -1,10 +1,14 @@
package com.ruoyi.busi.service.impl;
import java.math.BigDecimal;
import java.util.*;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.base.domain.BaseCategory;
@ -18,7 +22,9 @@ import com.ruoyi.busi.service.IBusiNoticeFormService;
import com.ruoyi.busi.service.IBusiSubscribeService;
import com.ruoyi.busi.service.IBusiUserLoveService;
import com.ruoyi.busi.vo.BusiNoticeVo;
import com.ruoyi.busi.vo.SubScribeQuery;
import com.ruoyi.busi.vo.SubscribeDataObj;
import com.ruoyi.common.config.WxAppConfig;
import com.ruoyi.common.core.domain.DlBaseEntity;
import java.util.stream.Collectors;
@ -36,11 +42,13 @@ import com.ruoyi.member.domain.MemberApply;
import com.ruoyi.member.domain.MemberPoints;
import com.ruoyi.member.domain.MemberUser;
import com.ruoyi.member.service.*;
import com.ruoyi.payConfig.WechatPayConfig;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysDictTypeService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.busi.mapper.BusiNoticeMapper;
@ -87,8 +95,14 @@ public class BusiNoticeServiceImpl extends ServiceImpl<BusiNoticeMapper,BusiNoti
private IMemberCouponService memberCouponService;
@Autowired
private IMemberPointsService memberPointsService;
@Resource
private WechatPayConfig wechatPayConfig;
@Autowired
private ISysConfigService configService;
private WxAppConfig wxAppConfig;
@Autowired
private ThreadPoolTaskExecutor executor;
@Override
public IPage<BusiNoticeVo> queryListPage(BusiNoticeQuery query, Page<BusiNotice> page) {
@ -123,6 +137,7 @@ public class BusiNoticeServiceImpl extends ServiceImpl<BusiNoticeMapper,BusiNoti
if (v1>=0.7&&v2>=0.7){
//title detail 相似度大于70% 待审核
data.setApprovalStatus("0");
data.setApprovalTime(null);
data.setSimilarityIds(Optional.ofNullable(data.getSimilarityIds()).orElse("")+busiNotice.getId()+",");
}
}
@ -130,6 +145,8 @@ public class BusiNoticeServiceImpl extends ServiceImpl<BusiNoticeMapper,BusiNoti
//删除结尾的最后一个逗号
data.setSimilarityIds(data.getSimilarityIds().substring(0, data.getSimilarityIds().length() - 1));
}
this.save(data);
if(data.getApprovalStatus().equals("1")){
//如果审核通过
//从配置表中获取积分
@ -138,9 +155,8 @@ public class BusiNoticeServiceImpl extends ServiceImpl<BusiNoticeMapper,BusiNoti
memberPoints.setType("1");
memberPoints.setFromCode("fbgg");
memberPointsService.savePoints(memberPoints);
}
this.save(data);
try {
cardService.dealMemberRights2(data.getUserId(),null,"add_notice",1);
}catch (Exception e){
@ -163,6 +179,12 @@ public class BusiNoticeServiceImpl extends ServiceImpl<BusiNoticeMapper,BusiNoti
}
}
if(data.getApprovalStatus().equals("1")){
//进行模版消息通知
sendNoticeMsg(data);
}
}
@ -326,6 +348,10 @@ public class BusiNoticeServiceImpl extends ServiceImpl<BusiNoticeMapper,BusiNoti
busiNotice.setApprovalTime(new Date());
busiNotice.setApprovalRemark(query.getApprovalRemark());
this.updateById(busiNotice);
if(busiNotice.getApprovalStatus().equals("1")){
//进行模版消息通知
sendNoticeMsg(busiNotice);
}
}
/**
@ -656,4 +682,158 @@ public class BusiNoticeServiceImpl extends ServiceImpl<BusiNoticeMapper,BusiNoti
}
/**
* 获取token
* @return
*/
public String getAccessToken(String APPLET_APPID,String APPLET_SECRET) {
String tokenUrl="https://api.weixin.qq.com/cgi-bin/token?appid="+APPLET_APPID+"&secret="+APPLET_SECRET+"&grant_type=client_credential";
String responseStr= HttpUtil.get(tokenUrl);
JSONObject object = JSON.parseObject(responseStr);
String access_Token = object.getString("access_token");
System.out.println("appid"+APPLET_APPID+"secret"+APPLET_SECRET);
System.out.println("获取到的token信息"+object.toJSONString());
return access_Token;
}
/**
* 推送
* @param content
* @return
*/
public String push(Map<String, String> content) {
/**小程序appid*/
String APPLET_APPID=wxAppConfig.getAppId();
/**公众号秘钥*/
String OFFICIAL_ACCOUNT_SECRET=wechatPayConfig.getWxAppSecret();
/**公众号appid*/
String OFFICIAL_ACCOUNT_APPID=wechatPayConfig.getAppId();
/**公众号模板id*/
String OFFICIAL_ACCOUNT_TEMPLATE_ID="h646Xn1xNc70npuUI7C3bvrL0DxZQgf7wM0qKRqep5c";
//获取需要推送的用户openid
String openid= content.get("openid");
//获取用户token
String token = getAccessToken(OFFICIAL_ACCOUNT_APPID,OFFICIAL_ACCOUNT_SECRET);
String resultStatus = "0";//0:失败1成功
try {
//小程序统一消息推送
String path = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + token;
//封装参数
JSONObject jsonData = new JSONObject();
//小程序用户的openid
jsonData.put("touser", openid);
//公众号模板ID
jsonData.put("template_id", OFFICIAL_ACCOUNT_TEMPLATE_ID);
//公众号模板消息所要跳转的小程序小程序的必须与公众号具有绑定关系
JSONObject miniprogram = new JSONObject();
//小程序APPID
miniprogram.put("appid",APPLET_APPID);
//跳转到小程序的页面路径
miniprogram.put("pagepath","pages/notice/detail?id="+content.get("noticeId"));
jsonData.put("miniprogram", miniprogram);
//公众号消息数据封装
JSONObject data = new JSONObject();
//此处的参数key,需要对照模板中的key来设置
data.put("thing15", getValue(content.get("noticeTitle")));
data.put("thing2", getValue(content.get("platformName")));//联系方式
data.put("thing19", getValue(content.get("tgzName")));//时间
data.put("time78", getValue(content.get("startTime")));
data.put("time38", getValue(content.get("endTime")));
jsonData.put("data", data);
System.out.println("请求参数:"+jsonData);
String s = HttpUtil.post(path, jsonData.toJSONString());
System.out.println("返回结果:"+s);
resultStatus="1";
} catch (Exception e) {
log.error("微信公众号发送消息失败!"+e.getMessage());
resultStatus="0";
}
return resultStatus;
}
/**
* 获取data
* @param value
* @return
*/
private JSONObject getValue(String value) {
// TODO Auto-generated method stub
JSONObject json = new JSONObject();
json.put("value", value);
return json;
}
public void sendNoticeMsg(BusiNotice notice){
//开始线程
ThreadUtil.execute(()->{
if(null!=notice){
//推送分两个1符合订阅设置的 2符合关注的
SubScribeQuery subScribeQuery =new SubScribeQuery();
subScribeQuery.setBloggerTypeCode(StringUtils.isNotEmpty(notice.getBloggerTypes())?notice.getBloggerTypes().split(","):new String[]{});
subScribeQuery.setPlatformCode(notice.getPlatformCode());
//结算方式
subScribeQuery.setSettleTypeCode(notice.getIsPlatformFree().toString());
subScribeQuery.setFansDown(notice.getFansDown());
subScribeQuery.setFansUp(notice.getFansUp()==null?999999999:notice.getFansUp());
subScribeQuery.setFeeDown(notice.getFeeDown());
subScribeQuery.setFeeUp(notice.getFeeUp()==null?new BigDecimal(999999999):notice.getFeeUp());
subScribeQuery.setLoveUserId(notice.getUserId().toString());
List<JSONObject> okUser = subscribeService.getOkUser(subScribeQuery);
//过滤重复wxOpenId
List<String> wxOpenIdList = new ArrayList<>();
for (JSONObject jsonObject : okUser) {
//判断关键词是否满足
boolean flag = true;
if (jsonObject.getString("allOk").equals("0")&&jsonObject.containsKey("keywordsList")&& StringUtils.isNotEmpty(jsonObject.getString("keywordsList"))){
String[] split = jsonObject.getString("keywordsList").split(",");
flag = false;
for (String s : split) {
//判断关键词是否满足
if (notice.getTitle().contains(s)) {
//满足关键词
flag = true;
break;
}
}
}
if (flag){
if (!wxOpenIdList.contains(jsonObject.getString("wxOpenId"))){
wxOpenIdList.add(jsonObject.getString("wxOpenId"));
//推送消息
Map<String, String> content =new HashMap<>();
content.put("openid",jsonObject.getString("wxOpenId"));
String noticeTitle = notice.getTitle();
if (noticeTitle.length() > 20) {
noticeTitle = noticeTitle.substring(0, 19);
}
content.put("noticeTitle", noticeTitle);
content.put("platformName",baseCategoryService.selectByCode(notice.getPlatformCode()).get(0).getTitle());
SysUser sysUser = userService.selectUserById(notice.getUserId());
content.put("tgzName",sysUser.getNickName());
content.put("startTime",DateUtil.format(notice.getApprovalTime(),"yyyy年MM月dd日 HH:mm"));
content.put("endTime",DateUtil.format(notice.getEndDate(),"yyyy年MM月dd日 HH:mm"));
push(content);
}
}
}
}
});
}
}

View File

@ -1,6 +1,10 @@
package com.ruoyi.busi.service.impl;
import java.util.List;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.busi.vo.SubScribeQuery;
import com.ruoyi.busi.vo.SubscribeDataObj;
import com.ruoyi.common.utils.DateUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -24,4 +28,8 @@ public class BusiSubscribeServiceImpl extends ServiceImpl<BusiSubscribeMapper,Bu
private BusiSubscribeMapper busiSubscribeMapper;
@Override
public List<JSONObject> getOkUser(SubScribeQuery subscribeDataObj) {
return busiSubscribeMapper.getOkUser(subscribeDataObj);
}
}

View File

@ -47,4 +47,6 @@ public class NoticeUtils {
});
return String.join(" ",rtnList);
}
}

View File

@ -0,0 +1,30 @@
package com.ruoyi.busi.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
public class SubScribeQuery {
//领域 博主类型
private String[] bloggerTypeCode;
//平台
private String platformCode;
//结算方式类型
private String settleTypeCode;
//标题
private String title;
private String content;
//粉丝数量上限
private Long fansUp;
//粉丝数量下限
private Long fansDown;
//费用上限
private BigDecimal feeDown;
//费用下限
private BigDecimal feeUp;
private String loveUserId;
}

View File

@ -17,5 +17,48 @@
<sql id="selectBusiSubscribeVo">
select id, json_obj, create_time, update_time, creator, updater, del_flag from dl_busi_subscribe
</sql>
<select id="getOkUser" resultType="com.alibaba.fastjson2.JSONObject"
parameterType="com.ruoyi.busi.vo.SubscribeDataObj">
SELECT
distinct su.wx_open_id as wxOpenId,
sub.keywords_list as keywordsList,
'0' as allOk
FROM
dl_busi_subscribe sub
inner join sys_user su on sub.user_id = su.user_id and su.wx_open_id is not null
where sub.new_notice = '1' and sub.del_flag ='0'
-- 领域
and (sub.blogger_type_code = '-1'
<if test="bloggerTypeCode != null and bloggerTypeCode.length>0">
<foreach item="item" index="index" collection="bloggerTypeCode"
open="(" separator="or" close=")">
sub.blogger_type_code like concat('%',#{item},'%')
</foreach>
</if>
)
-- 平台
and (sub.platform_code = '-1' or sub.platform_code like concat('%',#{platformCode},'%'))
-- 结算方式
and (sub.settle_type_code = '-1' or sub.settle_type_code like concat('%',#{settleTypeCode},'%'))
-- 粉丝限制
and (sub.fans_limit = '0' or sub.fans_limit is null
or (sub.fans_limit = '1' and sub.fans_up <![CDATA[<= ]]> #{fansUp} and sub.fans_down <![CDATA[>= ]]> #{fansDown}))
-- 收费限制
and (sub.fee_limit = '0' or sub.fee_limit is null
or (sub.fee_limit = '1' and sub.fee_up <![CDATA[<= ]]> #{feeUp} and sub.fee_down <![CDATA[>= ]]> #{feeDown}))
union
SELECT
distinct su.wx_open_id as wxOpenId,
'' as keywordsList,
'1' as allOk
FROM
dl_busi_subscribe sub
inner join sys_user su on sub.user_id = su.user_id and su.wx_open_id is not null
inner join dl_busi_user_love love on love.user_id = sub.user_id and love.love_user_id = #{loveUserId}
where sub.new_notice = '1' and sub.del_flag ='0' and sub.fork_notice = '1'
</mapper>
</select>
</mapper>

View File

@ -39,9 +39,12 @@ public class ThreadPoolConfig
executor.setKeepAliveSeconds(keepAliveSeconds);
// 线程池对拒绝任务(无线程可用)的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize(); // 初始化
return executor;
}
/**
* 执行周期性或定时任务
*/