微信网页登录

This commit is contained in:
starrySky
2024-04-09 10:17:49 +08:00
parent b2f6921ef1
commit e8b6c8e0aa
128 changed files with 2861 additions and 4243 deletions

View File

@@ -1,13 +0,0 @@
package com.starry.admin.modules.weichat.builder;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
/**
* @author admin
*/
public abstract class AbstractBuilder {
public abstract WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, WxMpService service);
}

View File

@@ -1,21 +0,0 @@
package com.starry.admin.modules.weichat.builder;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
/**
* @author admin
*/
public class ImageBuilder extends AbstractBuilder {
@Override
public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
WxMpService service) {
return WxMpXmlOutMessage.IMAGE().mediaId(content)
.fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
.build();
}
}

View File

@@ -1,22 +0,0 @@
package com.starry.admin.modules.weichat.builder;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage;
/**
* @author admin
*/
public class TextBuilder extends AbstractBuilder {
@Override
public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
WxMpService service) {
WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content(content)
.fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
.build();
return m;
}
}

View File

@@ -1,24 +0,0 @@
package com.starry.admin.modules.weichat.config;
/**
* @author admin
*/
public interface CommonConstants {
/**
* 是
*/
String YES = "1";
/**
* 否
*/
String NO = "0";
/**
* 树形父类ID
*/
String PARENT_ID = "0";
/**
* 编码
*/
String UTF8 = "UTF-8";
}

View File

@@ -1,36 +0,0 @@
package com.starry.admin.modules.weichat.config;
import com.starry.admin.modules.weichat.interceptor.ThirdSessionInterceptor;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* web配置
*
* @author admin
*/
@Configuration
@AllArgsConstructor
public class WebConfig implements WebMvcConfigurer {
/**
* 拦截器
*
* @param registry InterceptorRegistry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
/*
进入ThirdSession拦截器
*/
registry.addInterceptor(new ThirdSessionInterceptor())
// 拦截/api/**接口
.addPathPatterns("/weixin/api/**")
// 放行接口
.excludePathPatterns("/weixin/api/ma/wxuser/login",
"/weixin/api/ma/orderinfo/notify-order", "/weixin/api/ma/orderinfo/notify-logisticsr",
"/weixin/api/ma/orderinfo/notify-refunds");
}
}

View File

@@ -1,111 +0,0 @@
// package com.starry.admin.modules.weichat.config;
//
//
// import cn.hutool.core.util.StrUtil;
// import com.starry.admin.modules.weichat.entity.CustomWxMpProperties;
// import com.starry.admin.modules.weichat.handler.*;
// import com.starry.admin.modules.weichat.utils.WxMpPropertiesUtils;
// import lombok.AllArgsConstructor;
// import me.chanjar.weixin.common.api.WxConsts;
// import me.chanjar.weixin.mp.api.WxMpMessageRouter;
// import me.chanjar.weixin.mp.api.WxMpService;
// import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
// import me.chanjar.weixin.mp.config.WxMpConfigStorage;
// import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
// import org.springframework.context.annotation.Bean;
// import org.springframework.context.annotation.Configuration;
//
// import java.util.HashMap;
// import java.util.Map;
//
// import static me.chanjar.weixin.common.api.WxConsts.EventType.SUBSCRIBE;
// import static me.chanjar.weixin.common.api.WxConsts.EventType.UNSUBSCRIBE;
// import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType.EVENT;
// import static me.chanjar.weixin.mp.constant.WxMpEventConstants.CustomerService.*;
// import static me.chanjar.weixin.mp.constant.WxMpEventConstants.POI_CHECK_NOTIFY;
//
///**
// * wechat mp configuration
// *
// * @author admin
// */
//@AllArgsConstructor
//@Configuration
// public class WxMpConfiguration {
// private final LogHandler logHandler;
// private final NullHandler nullHandler;
// private final KfSessionHandler kfSessionHandler;
// private final StoreCheckNotifyHandler storeCheckNotifyHandler;
// private final LocationHandler locationHandler;
// private final MenuHandler menuHandler;
// private final MsgHandler msgHandler;
// private final UnsubscribeHandler unsubscribeHandler;
// private final SubscribeHandler subscribeHandler;
// private final ScanHandler scanHandler;
//
// @Bean
// public WxMpService wxMpService() {
// CustomWxMpProperties customWxMpProperties = WxMpPropertiesUtils.getWeiChatProperties();
// if (StrUtil.isBlankIfStr(customWxMpProperties.getAppid()) || StrUtil.isBlankIfStr(customWxMpProperties.getAppid()) || StrUtil.isBlankIfStr(customWxMpProperties.getAppid()) || StrUtil.isBlankIfStr(customWxMpProperties.getAppid())) {
// throw new RuntimeException("微信配置文件出错");
// }
// return getWxMpService(customWxMpProperties);
// }
//
// private static WxMpService getWxMpService(CustomWxMpProperties customWxMpProperties) {
// Map<String, WxMpConfigStorage> multiConfigStorages = new HashMap<>();
// WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
// configStorage.setAppId(customWxMpProperties.getAppid());
// configStorage.setSecret(customWxMpProperties.getSecret());
// configStorage.setToken(customWxMpProperties.getToken());
// configStorage.setAesKey(customWxMpProperties.getAesKey());
//
//
// WxMpService mpService = new WxMpServiceImpl();
// mpService.setMultiConfigStorages(multiConfigStorages);
// return mpService;
// }
//
// @Bean
// public WxMpMessageRouter messageRouter(WxMpService wxMpService) {
// final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);
//
// // 记录所有事件的日志 (异步执行)
// newRouter.rule().handler(this.logHandler).next();
//
// // 接收客服会话管理事件
// newRouter.rule().async(false).msgType(EVENT).event(KF_CREATE_SESSION).handler(this.kfSessionHandler).end();
// newRouter.rule().async(false).msgType(EVENT).event(KF_CLOSE_SESSION).handler(this.kfSessionHandler).end();
// newRouter.rule().async(false).msgType(EVENT).event(KF_SWITCH_SESSION).handler(this.kfSessionHandler).end();
//
// // 门店审核事件
// newRouter.rule().async(false).msgType(EVENT).event(POI_CHECK_NOTIFY).handler(this.storeCheckNotifyHandler).end();
//
// // 自定义菜单事件
// newRouter.rule().async(false).msgType(EVENT).event(WxConsts.EventType.CLICK).handler(this.menuHandler).end();
//
// // 点击菜单连接事件
// newRouter.rule().async(false).msgType(EVENT).event(WxConsts.EventType.VIEW).handler(this.nullHandler).end();
//
// // 关注事件
// newRouter.rule().async(false).msgType(EVENT).event(SUBSCRIBE).handler(this.subscribeHandler).end();
//
// // 取消关注事件
// newRouter.rule().async(false).msgType(EVENT).event(UNSUBSCRIBE).handler(this.unsubscribeHandler).end();
//
// // 上报地理位置事件
// newRouter.rule().async(false).msgType(EVENT).event(WxConsts.EventType.LOCATION).handler(this.locationHandler).end();
//
// // 接收地理位置消息
// newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION).handler(this.locationHandler).end();
//
// // 扫码事件
// newRouter.rule().async(false).msgType(EVENT).event(WxConsts.EventType.SCAN).handler(this.scanHandler).end();
//
// // 默认
// newRouter.rule().async(false).handler(this.msgHandler).end();
//
// return newRouter;
// }
//
//}

View File

@@ -23,7 +23,7 @@ public interface ConfigConstant {
String SUBSCRIBE_TYPE_WEBLIEN = "2";
/**
* 应用类型 1:小程序
* 应用类型 1:微信
*/
String WX_APP_TYPE_1 = "1";
/**

View File

@@ -2,7 +2,7 @@ package com.starry.admin.modules.weichat.constant;
/**
* 全局返回码
* 小程序用6开头例60001
* 微信用6开头例60001
*
* @author admin
* 2019年7月25日

File diff suppressed because one or more lines are too long

View File

@@ -1,132 +0,0 @@
package com.starry.admin.modules.weichat.controller;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.modules.weichat.constant.ConfigConstant;
import com.starry.admin.modules.weichat.entity.WxAutoReply;
import com.starry.admin.modules.weichat.service.WxAutoReplyService;
import com.starry.common.result.R;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* 消息自动回复
*
* @author admin
* @since 2019-04-18 15:40:39
*/
@RestController
@AllArgsConstructor
@RequestMapping("/wxautoreply")
public class WxAutoReplyController {
@Resource
WxAutoReplyService wxAutoReplyService;
/**
* 分页查询
*
* @param page 分页对象
* @param wxAutoReply 消息自动回复
* @return
*/
@GetMapping("/page")
@PreAuthorize("@customSs.hasPermission('wxmp:wxautoreply:index')")
public R getWxAutoReplyPage(Page page, WxAutoReply wxAutoReply) {
return R.ok(wxAutoReplyService.page(page, Wrappers.query(wxAutoReply)));
}
/**
* 通过id查询消息自动回复
*
* @param id id
* @return R
*/
@GetMapping("/{id}")
@PreAuthorize("@customSs.hasPermission('wxmp:wxautoreply:get')")
public R getById(@PathVariable("id") String id) {
return R.ok(wxAutoReplyService.getById(id));
}
/**
* 新增消息自动回复
*
* @param wxAutoReply 消息自动回复
* @return R
*/
@PostMapping
@PreAuthorize("@customSs.hasPermission('wxmp:wxautoreply:add')")
public R save(@RequestBody WxAutoReply wxAutoReply) {
this.jude(wxAutoReply);
return R.ok(wxAutoReplyService.save(wxAutoReply));
}
/**
* 修改消息自动回复
*
* @param wxAutoReply 消息自动回复
* @return R
*/
@PutMapping
@PreAuthorize("@customSs.hasPermission('wxmp:wxautoreply:edit')")
public R updateById(@RequestBody WxAutoReply wxAutoReply) {
this.jude(wxAutoReply);
return R.ok(wxAutoReplyService.updateById(wxAutoReply));
}
/**
* 通过id删除消息自动回复
*
* @param id id
* @return R
*/
@DeleteMapping("/{id}")
@PreAuthorize("@customSs.hasPermission('wxmp:wxautoreply:del')")
public R removeById(@PathVariable String id) {
return R.ok(wxAutoReplyService.removeById(id));
}
/**
* //校验参数
*
* @param wxAutoReply
*/
public void jude(WxAutoReply wxAutoReply) {
if (ConfigConstant.WX_AUTO_REPLY_TYPE_2.equals(wxAutoReply.getType())) {
Wrapper<WxAutoReply> queryWrapper = Wrappers.<WxAutoReply>lambdaQuery()
.eq(WxAutoReply::getReqType, wxAutoReply.getReqType());
List<WxAutoReply> list = wxAutoReplyService.list(queryWrapper);
if (StringUtils.isNotBlank(wxAutoReply.getId())) {
if (list != null && list.size() == 1) {
if (!list.get(0).getId().equals(wxAutoReply.getId())) {
throw new RuntimeException("请求消息类型重复");
}
}
if (list != null && list.size() > 1) {
throw new RuntimeException("请求消息类型重复");
}
}
}
if (ConfigConstant.WX_AUTO_REPLY_TYPE_3.equals(wxAutoReply.getType())) {
Wrapper<WxAutoReply> queryWrapper = Wrappers.<WxAutoReply>lambdaQuery()
.eq(WxAutoReply::getReqKey, wxAutoReply.getReqKey())
.eq(WxAutoReply::getRepType, wxAutoReply.getRepMate());
List<WxAutoReply> list = wxAutoReplyService.list(queryWrapper);
if (list != null && list.size() == 1) {
if (!list.get(0).getId().equals(wxAutoReply.getId())) {
throw new RuntimeException("关键词重复");
}
}
if (list != null && list.size() > 1) {
throw new RuntimeException("关键词重复");
}
}
}
}

View File

@@ -1,129 +0,0 @@
package com.starry.admin.modules.weichat.controller;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.common.result.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpDraftService;
import me.chanjar.weixin.mp.api.WxMpFreePublishService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.draft.WxMpAddDraft;
import me.chanjar.weixin.mp.bean.draft.WxMpDraftArticles;
import me.chanjar.weixin.mp.bean.draft.WxMpUpdateDraft;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* 微信草稿箱
*
* @author admin
* @since 2022-03-10 21:26:35
*/
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/wxdraft")
@Api(value = "wxdraft", tags = "微信草稿箱")
public class WxDraftController {
@Resource
WxMpService wxService;
/**
* 新增图文消息
*
* @param data
* @return
*/
@ApiOperation(value = "新增草稿箱")
@PostMapping
@PreAuthorize("@customSs.hasPermission('wxmp:wxdraft:add')")
public R add(@RequestBody JSONObject data) throws Exception {
JSONArray jSONArray = data.getJSONArray("articles");
List<WxMpDraftArticles> articles = jSONArray.toList(WxMpDraftArticles.class);
WxMpAddDraft wxMpAddDraft = new WxMpAddDraft();
wxMpAddDraft.setArticles(articles);
WxMpDraftService wxMpDraftService = wxService.getDraftService();
String rs = wxMpDraftService.addDraft(wxMpAddDraft);
return R.ok(rs);
}
/**
* 修改微信草稿箱
*
* @param data
* @return
*/
@ApiOperation(value = "修改微信草稿箱")
@PutMapping
@PreAuthorize("@customSs.hasPermission('wxmp:wxdraft:edit')")
public R edit(@RequestBody JSONObject data) throws Exception {
String mediaId = data.getStr("mediaId");
JSONArray jSONArray = data.getJSONArray("articles");
List<WxMpDraftArticles> articles = jSONArray.toList(WxMpDraftArticles.class);
WxMpDraftService wxMpDraftService = wxService.getDraftService();
WxMpUpdateDraft wxMpUpdateDraft = new WxMpUpdateDraft();
wxMpUpdateDraft.setMediaId(mediaId);
int index = 0;
for (WxMpDraftArticles article : articles) {
wxMpUpdateDraft.setIndex(index);
wxMpUpdateDraft.setArticles(article);
wxMpDraftService.updateDraft(wxMpUpdateDraft);
index++;
}
return R.ok();
}
/**
* 通过id删除微信草稿箱
*
* @param
* @return R
*/
@ApiOperation(value = "通过id删除微信草稿箱")
@DeleteMapping
@PreAuthorize("@customSs.hasPermission('wxmp:wxdraft:del')")
public R del(String id) throws Exception {
WxMpDraftService wxMpDraftService = wxService.getDraftService();
return R.ok(wxMpDraftService.delDraft(id));
}
/**
* 分页查询
*
* @param page 分页对象
* @param
* @return
*/
@ApiOperation(value = "分页查询")
@GetMapping("/page")
@PreAuthorize("@customSs.hasPermission('wxmp:wxdraft:index')")
public R getPage(Page page) throws Exception {
WxMpDraftService wxMpDraftService = wxService.getDraftService();
int count = (int) page.getSize();
int offset = (int) page.getCurrent() * count - count;
return R.ok(wxMpDraftService.listDraft(offset, count));
}
/**
* 发布草稿箱
*
* @param id
* @return
*/
@ApiOperation(value = "发布草稿箱")
@PostMapping("/publish/{id}")
@PreAuthorize("@customSs.hasPermission('wxmp:wxdraft:publish')")
public R publish(@PathVariable String id) throws Exception {
WxMpFreePublishService wxMpFreePublishService = wxService.getFreePublishService();
wxMpFreePublishService.submit(id);
return R.ok();
}
}

View File

@@ -1,66 +0,0 @@
package com.starry.admin.modules.weichat.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.common.result.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpFreePublishService;
import me.chanjar.weixin.mp.api.WxMpService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 微信发布
*
* @author admin
* @since 2022-03-10 21:26:35
*/
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/freepublish")
@Api(value = "freepublish", tags = "微信发布")
public class WxFreePublishController {
@Resource
WxMpService wxService;
/**
* 删除发布
*
* @param
* @return R
*/
@ApiOperation(value = "删除发布")
@DeleteMapping
@PreAuthorize("@customSs.hasPermission('wxmp:wxfreepublish:del')")
public R del(String id) throws Exception {
WxMpFreePublishService wxMpFreePublishService = wxService.getFreePublishService();
return R.ok(wxMpFreePublishService.deletePushAllArticle(id));
}
/**
* 获取成功发布列表
*
* @param page 获取成功发布列表
* @param
* @return
*/
@ApiOperation(value = "获取成功发布列表")
@GetMapping("/page")
@PreAuthorize("@customSs.hasPermission('wxmp:wxfreepublish:index')")
public R getPage(Page page) throws Exception {
WxMpFreePublishService wxMpFreePublishService = wxService.getFreePublishService();
int count = (int) page.getSize();
int offset = (int) page.getCurrent() * count - count;
return R.ok(wxMpFreePublishService.getPublicationRecords(offset, count));
}
}

View File

@@ -1,246 +0,0 @@
package com.starry.admin.modules.weichat.controller;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.modules.weichat.entity.ImageManager;
import com.starry.admin.modules.weichat.utils.FileUtils;
import com.starry.common.result.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpMaterialService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult;
import me.chanjar.weixin.mp.bean.material.WxMpMaterial;
import me.chanjar.weixin.mp.bean.material.WxMpMaterialFileBatchGetResult;
import me.chanjar.weixin.mp.bean.material.WxMpMaterialUploadResult;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 微信素材
*
* @author admin
* @since 2019-03-23 21:26:35
*/
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/wxmaterial")
public class WxMaterialController {
@Resource
WxMpService wxService;
/**
* 上传非图文微信素材
*
* @param mulFile
* @param mediaType
* @return
*/
@PostMapping("/materialFileUpload")
// @PreAuthorize("@customSs.hasPermission('wxmp:wxmaterial:add')")
public R materialFileUpload(@RequestParam("file") MultipartFile mulFile,
@RequestParam("title") String title,
@RequestParam("introduction") String introduction,
@RequestParam("mediaType") String mediaType) {
try {
WxMpMaterial material = new WxMpMaterial();
material.setName(mulFile.getOriginalFilename());
if (WxConsts.MediaFileType.VIDEO.equals(mediaType)) {
material.setVideoTitle(title);
material.setVideoIntroduction(introduction);
}
File file = FileUtils.multipartFileToFile(mulFile);
material.setFile(file);
WxMpMaterialService wxMpMaterialService = wxService.getMaterialService();
WxMpMaterialUploadResult wxMpMaterialUploadResult = wxMpMaterialService.materialFileUpload(mediaType, material);
WxMpMaterialFileBatchGetResult.WxMaterialFileBatchGetNewsItem wxMpMaterialFileBatchGetResult = new WxMpMaterialFileBatchGetResult.WxMaterialFileBatchGetNewsItem();
wxMpMaterialFileBatchGetResult.setName(file.getName());
wxMpMaterialFileBatchGetResult.setMediaId(wxMpMaterialUploadResult.getMediaId());
wxMpMaterialFileBatchGetResult.setUrl(wxMpMaterialUploadResult.getUrl());
return R.ok(wxMpMaterialFileBatchGetResult);
} catch (WxErrorException e) {
log.error("上传非图文微信素材失败" + e);
return R.error(e.getMessage());
} catch (Exception e) {
log.error("上传失败", e);
return R.error(e.getLocalizedMessage());
}
}
/**
* 上传图文消息内的图片获取URL
*
* @param mulFile
* @return
*/
@PostMapping("/newsImgUpload")
// @PreAuthorize("@customSs.hasPermission('wxmp:wxmaterial:add')")
public String newsImgUpload(@RequestParam("file") MultipartFile mulFile) throws Exception {
File file = FileUtils.multipartFileToFile(mulFile);
WxMpMaterialService wxMpMaterialService = wxService.getMaterialService();
WxMediaImgUploadResult wxMediaImgUploadResult = wxMpMaterialService.mediaImgUpload(file);
Map<Object, Object> responseData = new HashMap<>();
responseData.put("link", wxMediaImgUploadResult.getUrl());
return JSONUtil.toJsonStr(responseData);
}
/**
* 通过id删除微信素材
*
* @param
* @return R
*/
@DeleteMapping
@PreAuthorize("@customSs.hasPermission('wxmp:wxmaterial:del')")
public R materialDel(String id) {
WxMpMaterialService wxMpMaterialService = wxService.getMaterialService();
try {
return R.ok(wxMpMaterialService.materialDelete(id));
} catch (WxErrorException e) {
log.error("删除微信素材失败", e);
return R.error(e.getMessage());
}
}
/**
* 分页查询
*
* @param page 分页对象
* @param type
* @return
*/
@GetMapping("/page")
@PreAuthorize("@customSs.hasPermission('wxmp:wxmaterial:index')")
public R getWxMaterialPage(Page page, String type) {
try {
WxMpMaterialService wxMpMaterialService = wxService.getMaterialService();
int count = (int) page.getSize();
int offset = (int) page.getCurrent() * count - count;
if (WxConsts.MaterialType.NEWS.equals(type)) {
return R.ok(wxMpMaterialService.materialNewsBatchGet(offset, count));
} else {
return R.ok(wxMpMaterialService.materialFileBatchGet(type, offset, count));
}
} catch (WxErrorException e) {
log.error("查询素材失败", e);
return R.error(e.getMessage());
}
}
/**
* 分页查询2
*
* @param type
* @return
*/
@GetMapping("/page-manager")
// @PreAuthorize("@customSs.hasPermission('wxmp:wxmaterial:index')")
public String getWxMaterialPageManager(Integer count, Integer offset, String type) throws WxErrorException {
List<ImageManager> listImageManager = new ArrayList<>();
WxMpMaterialService wxMpMaterialService = wxService.getMaterialService();
List<WxMpMaterialFileBatchGetResult.WxMaterialFileBatchGetNewsItem> list = wxMpMaterialService.materialFileBatchGet(type, offset, count).getItems();
list.forEach(wxMaterialFileBatchGetNewsItem -> {
ImageManager imageManager = new ImageManager();
imageManager.setName(wxMaterialFileBatchGetNewsItem.getMediaId());
imageManager.setUrl(wxMaterialFileBatchGetNewsItem.getUrl());
imageManager.setThumb(wxMaterialFileBatchGetNewsItem.getUrl());
listImageManager.add(imageManager);
});
return JSONUtil.toJsonStr(listImageManager);
}
/**
* 获取微信视频素材
*
* @param
* @return R
*/
@GetMapping("/materialVideo")
@PreAuthorize("@customSs.hasPermission('wxmp:wxmaterial:get')")
public R getMaterialVideo(String mediaId) {
WxMpMaterialService wxMpMaterialService = wxService.getMaterialService();
try {
return R.ok(wxMpMaterialService.materialVideoInfo(mediaId));
} catch (WxErrorException e) {
log.error("获取微信视频素材失败", e);
return R.error(e.getMessage());
}
}
/**
* 获取微信素材直接文件
*
* @param
* @return R
*/
@GetMapping("/materialOther")
@PreAuthorize("@customSs.hasPermission('wxmp:wxmaterial:get')")
public ResponseEntity<byte[]> getMaterialOther(String mediaId, String fileName) throws Exception {
try {
WxMpMaterialService wxMpMaterialService = wxService.getMaterialService();
// 获取文件
InputStream is = wxMpMaterialService.materialImageOrVoiceDownload(mediaId);
byte[] body = new byte[is.available()];
is.read(body);
HttpHeaders headers = new HttpHeaders();
// 设置文件类型
headers.add("Content-Disposition", "attchement;filename=" + URLEncoder.encode(fileName, "UTF-8"));
headers.add("Content-Type", "application/octet-stream");
HttpStatus statusCode = HttpStatus.OK;
// 返回数据
return new ResponseEntity<>(body, headers, statusCode);
} catch (WxErrorException e) {
log.error("获取微信素材直接文件失败", e);
return null;
}
}
/**
* 获取微信临时素材直接文件
*
* @param
* @return R
*/
@GetMapping("/tempMaterialOther")
@PreAuthorize("@customSs.hasPermission('wxmp:wxmsg:index')")
public ResponseEntity<byte[]> getTempMaterialOther(String mediaId, String fileName) throws Exception {
WxMpMaterialService wxMpMaterialService = wxService.getMaterialService();
try (InputStream is = Files.newInputStream(wxMpMaterialService.mediaDownload(mediaId).toPath())) {
byte[] body = new byte[is.available()];
is.read(body);
HttpHeaders headers = new HttpHeaders();
// 设置文件类型
headers.add("Content-Disposition", "attchement;filename=" + URLEncoder.encode(fileName, "UTF-8"));
headers.add("Content-Type", "application/octet-stream");
HttpStatus statusCode = HttpStatus.OK;
// 返回数据
return new ResponseEntity<>(body, headers, statusCode);
} catch (WxErrorException e) {
log.error("获取微信素材直接文件失败", e);
return null;
}
}
}

View File

@@ -1,63 +0,0 @@
package com.starry.admin.modules.weichat.controller;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.starry.admin.modules.weichat.service.WxMenuService;
import com.starry.common.result.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* 自定义菜单
*
* @author admin
* @since 2019-03-27 16:52:10
*/
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/wxmenu")
public class WxMenuController {
@Resource
WxMenuService wxMenuService;
/**
* 通过appId查询自定义菜单
*
* @return R
*/
@GetMapping("/list")
@PreAuthorize("@customSs.hasPermission('wxmp:wxmenu:get')")
public R getWxMenuButton() {
return R.ok(wxMenuService.getWxMenuButton());
}
/**
* 保存并发布菜单
*
* @param
* @return R
*/
@PostMapping("/release")
@PreAuthorize("@customSs.hasPermission('wxmp:wxmenu:add')")
public R saveAndRelease(@RequestBody String data) {
JSONObject jSONObject = JSONUtil.parseObj(data);
String strWxMenu = jSONObject.getStr("strWxMenu");
String appId = jSONObject.getStr("appId");
try {
wxMenuService.saveAndRelease(strWxMenu);
return R.ok();
} catch (WxErrorException e) {
log.error("发布自定义菜单失败appID:" + appId + ":" + e.getMessage());
return R.error(e.getMessage());
}
}
}

View File

@@ -1,29 +0,0 @@
package com.starry.admin.modules.weichat.controller;
import com.starry.admin.modules.weichat.service.WxMpApi;
import com.starry.common.result.R;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author: huchuansai
* @Date: 2024/3/27 10:39 PM
* @Description:
*/
@RestController
@RequestMapping("/wx/test")
@RequiredArgsConstructor
public class WxMpTestController {
private final WxMpApi wxMpApi;
@GetMapping("/getToken")
public R getToken(String appId, String secret) {
return R.ok(wxMpApi.getAccessToken(appId, secret, true));
}
}

View File

@@ -1,209 +0,0 @@
package com.starry.admin.modules.weichat.controller;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.modules.weichat.config.CommonConstants;
import com.starry.admin.modules.weichat.constant.ConfigConstant;
import com.starry.admin.modules.weichat.entity.WxMsg;
import com.starry.admin.modules.weichat.entity.WxMsgVO;
import com.starry.admin.modules.weichat.entity.WxUser;
import com.starry.admin.modules.weichat.service.WxMsgService;
import com.starry.admin.modules.weichat.service.WxUserService;
import com.starry.common.result.R;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpKefuService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* 微信消息
*
* @author admin
* @since 2019-05-28 16:12:10
*/
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/wxmsg")
@Api(value = "wxmsg", tags = "wxmsg管理")
public class WxMsgController {
@Resource
WxMsgService wxMsgService;
@Resource
WxUserService wxUserService;
@Resource
WxMpService wxService;
/**
* 分页查询
*
* @param page 分页对象
* @param wxMsgVO 微信消息
* @return
*/
@GetMapping("/page")
@PreAuthorize("@customSs.hasPermission('wxmp:wxmsg:index')")
public R getWxMsgPage(Page<WxMsg> page, WxMsgVO wxMsgVO) {
if (StringUtils.isNotBlank(wxMsgVO.getNotInRepType())) {
return R.ok(wxMsgService.listWxMsgMapGroup(page, wxMsgVO));
}
// 标记为已读
if (StringUtils.isNotBlank(wxMsgVO.getWxUserId())) {
WxMsg wxMsg = new WxMsg();
wxMsg.setReadFlag(CommonConstants.YES);
Wrapper<WxMsg> queryWrapper = Wrappers.<WxMsg>lambdaQuery().eq(WxMsg::getWxUserId, wxMsgVO.getWxUserId()).eq(WxMsg::getReadFlag, CommonConstants.NO);
wxMsgService.update(wxMsg, queryWrapper);
}
return R.ok(wxMsgService.page(page, Wrappers.query(wxMsgVO)));
}
/**
* 通过id查询微信消息
*
* @param id id
* @return R
*/
@GetMapping("/{id}")
@PreAuthorize("@customSs.hasPermission('wxmp:wxmsg:get')")
public R getById(@PathVariable("id") String id) {
return R.ok(wxMsgService.getById(id));
}
/**
* 新增微信消息
*
* @param wxMsg 微信消息
* @return R
*/
@PostMapping
@PreAuthorize("@customSs.hasPermission('wxmp:wxmsg:add')")
public R save(@RequestBody WxMsg wxMsg) {
try {
WxUser wxUser = wxUserService.getById(wxMsg.getWxUserId());
// 入库
wxMsg.setNickName(wxUser.getNickName());
wxMsg.setHeadimgUrl(wxUser.getHeadimgUrl());
wxMsg.setCreateTime(LocalDateTime.now());
wxMsg.setType(ConfigConstant.WX_MSG_TYPE_2);
WxMpKefuMessage wxMpKefuMessage = null;
if (WxConsts.KefuMsgType.TEXT.equals(wxMsg.getRepType())) {
wxMsg.setRepContent(wxMsg.getRepContent());
wxMpKefuMessage = WxMpKefuMessage.TEXT().build();
wxMpKefuMessage.setContent(wxMsg.getRepContent());
}
if (WxConsts.KefuMsgType.IMAGE.equals(wxMsg.getRepType())) {// 图片
wxMsg.setRepName(wxMsg.getRepName());
wxMsg.setRepUrl(wxMsg.getRepUrl());
wxMsg.setRepMediaId(wxMsg.getRepMediaId());
wxMpKefuMessage = WxMpKefuMessage.IMAGE().build();
wxMpKefuMessage.setMediaId(wxMsg.getRepMediaId());
}
if (WxConsts.KefuMsgType.VOICE.equals(wxMsg.getRepType())) {
wxMsg.setRepName(wxMsg.getRepName());
wxMsg.setRepUrl(wxMsg.getRepUrl());
wxMsg.setRepMediaId(wxMsg.getRepMediaId());
wxMpKefuMessage = WxMpKefuMessage.VOICE().build();
wxMpKefuMessage.setMediaId(wxMsg.getRepMediaId());
}
if (WxConsts.KefuMsgType.VIDEO.equals(wxMsg.getRepType())) {
wxMsg.setRepName(wxMsg.getRepName());
wxMsg.setRepDesc(wxMsg.getRepDesc());
wxMsg.setRepUrl(wxMsg.getRepUrl());
wxMsg.setRepMediaId(wxMsg.getRepMediaId());
wxMpKefuMessage = WxMpKefuMessage.VIDEO().build();
wxMpKefuMessage.setMediaId(wxMsg.getRepMediaId());
wxMpKefuMessage.setTitle(wxMsg.getRepName());
wxMpKefuMessage.setDescription(wxMsg.getRepDesc());
}
if (WxConsts.KefuMsgType.MUSIC.equals(wxMsg.getRepType())) {
wxMsg.setRepName(wxMsg.getRepName());
wxMsg.setRepDesc(wxMsg.getRepDesc());
wxMsg.setRepUrl(wxMsg.getRepUrl());
wxMsg.setRepHqUrl(wxMsg.getRepHqUrl());
wxMpKefuMessage = WxMpKefuMessage.MUSIC().build();
wxMpKefuMessage.setTitle(wxMsg.getRepName());
wxMpKefuMessage.setDescription(wxMsg.getRepDesc());
wxMpKefuMessage.setMusicUrl(wxMsg.getRepUrl());
wxMpKefuMessage.setHqMusicUrl(wxMsg.getRepHqUrl());
wxMpKefuMessage.setThumbMediaId(wxMsg.getRepThumbMediaId());
}
if (WxConsts.KefuMsgType.NEWS.equals(wxMsg.getRepType())) {
List<WxMpKefuMessage.WxArticle> list = new ArrayList<>();
JSONArray jSONArray = wxMsg.getContent().getJSONArray("articles");
WxMpKefuMessage.WxArticle t;
for (Object object : jSONArray) {
JSONObject jSONObject = JSONUtil.parseObj(JSONUtil.toJsonStr(object));
t = new WxMpKefuMessage.WxArticle();
t.setTitle(jSONObject.getStr("title"));
t.setDescription(jSONObject.getStr("digest"));
t.setPicUrl(jSONObject.getStr("thumbUrl"));
t.setUrl(jSONObject.getStr("url"));
list.add(t);
}
wxMsg.setRepName(wxMsg.getRepName());
wxMsg.setRepDesc(wxMsg.getRepDesc());
wxMsg.setRepUrl(wxMsg.getRepUrl());
wxMsg.setRepMediaId(wxMsg.getRepMediaId());
wxMsg.setContent(wxMsg.getContent());
wxMpKefuMessage = WxMpKefuMessage.NEWS().build();
wxMpKefuMessage.setArticles(list);
}
if (wxMpKefuMessage != null) {
WxMpKefuService wxMpKefuService = wxService.getKefuService();
wxMpKefuMessage.setToUser(wxUser.getOpenId());
wxMpKefuService.sendKefuMessage(wxMpKefuMessage);
wxMsgService.save(wxMsg);
return R.ok(wxMsg);
} else {
return R.error("非法消息类型");
}
} catch (WxErrorException e) {
log.error("新增微信消息失败" + e.getMessage());
return R.error(e.getMessage());
}
}
/**
* 修改微信消息
*
* @param wxMsg 微信消息
* @return R
*/
@PutMapping
@PreAuthorize("@customSs.hasPermission('wxmp:wxmsg:edit')")
public R updateById(@RequestBody WxMsg wxMsg) {
return R.ok(wxMsgService.updateById(wxMsg));
}
/**
* 通过id删除微信消息
*
* @param id id
* @return R
*/
@DeleteMapping("/{id}")
@PreAuthorize("@customSs.hasPermission('wxmp:wxmsg:del')")
public R removeById(@PathVariable String id) {
return R.ok(wxMsgService.removeById(id));
}
}

View File

@@ -0,0 +1,132 @@
package com.starry.admin.modules.weichat.controller;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.starry.admin.common.aspect.ClerkUserLogin;
import com.starry.admin.common.aspect.CustomUserLogin;
import com.starry.admin.common.conf.ThreadLocalRequestDetail;
import com.starry.admin.modules.clear.module.entity.PlayClerkUserInfoEntity;
import com.starry.admin.modules.clear.service.IPlayClerkUserInfoService;
import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity;
import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService;
import com.starry.admin.modules.weichat.entity.WxUserLoginVo;
import com.starry.admin.modules.weichat.entity.WxUserQueryAddressVo;
import com.starry.admin.modules.weichat.service.WxOauthService;
import com.starry.admin.modules.weichat.service.WxTokenService;
import com.starry.common.result.R;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Date;
import static com.starry.common.constant.Constants.*;
/**
* 微信用户
*
* @author admin
* @since 2019-03-25 15:39:39
*/
@Slf4j
@RestController
@RequestMapping("/wx/oauth2")
public class WxOauthController {
@Resource
private WxMpService wxMpService;
@Resource
private IPlayCustomUserInfoService customUserInfoService;
@Resource
private IPlayClerkUserInfoService clerkUserInfoService;
@Resource
private WxTokenService tokenService;
@Resource
private WxOauthService wxOauthService;
@GetMapping("/getClerkLoginAddress")
public R getClerkLoginAddress(@RequestBody WxUserQueryAddressVo vo) {
// 默认回调地址
String defaultAddress = "http://july.hucs.top/api/wx/oauth2/clerkLoginCallback";
if (!StrUtil.isBlankIfStr(vo.getUrl())) {
defaultAddress = vo.getUrl();
}
String url = wxMpService.getOAuth2Service().buildAuthorizationUrl(defaultAddress, "snsapi_userinfo", "STATE");
return R.ok(url);
}
@GetMapping("/clerkLoginCallback")
public void clerkLoginCallback(@RequestParam("code") String code) {
}
@GetMapping("/clark/login")
public R clerkLogin(@Valid @RequestBody WxUserLoginVo vo) {
String userId = wxOauthService.clarkUserLogin(vo.getCode());
PlayClerkUserInfoEntity entity = clerkUserInfoService.selectPlayClerkUserInfoById(userId);
JSONObject jsonObject = JSONObject.from(entity);
String tokenForMiniUser = tokenService.createMiniUserToken(entity.getId());
jsonObject.put("tokenValue", TOKEN_PREFIX + tokenForMiniUser);
jsonObject.put("tokenName", CLERK_USER_LOGIN_TOKEN);
jsonObject.put("accountRole", "user");
jsonObject.put("loginDate", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
return R.ok(jsonObject);
}
@ClerkUserLogin
@GetMapping("/clark/logout")
public R clerkLogout() {
wxOauthService.clarkUserLogout(ThreadLocalRequestDetail.getClerkUserInfo());
return R.ok("登出成功");
}
@GetMapping("/getCustomLoginAddress")
public R getCustomLoginAddress(@RequestBody WxUserQueryAddressVo vo) {
// 默认回调地址
String defaultAddress = "http://july.hucs.top/api/wx/oauth2/customLoginCallback";
if (!StrUtil.isBlankIfStr(vo.getUrl())) {
defaultAddress = vo.getUrl();
}
String url = wxMpService.getOAuth2Service().buildAuthorizationUrl(defaultAddress, "snsapi_userinfo", "STATE");
return R.ok(url);
}
@GetMapping("/customLoginCallback")
public void customLoginCallback(@RequestParam("code") String code) {
}
@GetMapping("/custom/login")
public R customLogin(@Valid @RequestBody WxUserLoginVo vo) {
String userId = wxOauthService.customUserLogin(vo.getCode());
PlayCustomUserInfoEntity entity = customUserInfoService.selectPlayCustomUserInfoById(userId);
JSONObject jsonObject = JSONObject.from(entity);
String tokenForMiniUser = tokenService.createMiniUserToken(entity.getId());
jsonObject.put("tokenValue", TOKEN_PREFIX + tokenForMiniUser);
jsonObject.put("tokenName", CUSTOM_USER_LOGIN_TOKEN);
jsonObject.put("accountRole", "user");
jsonObject.put("loginDate", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
return R.ok(jsonObject);
}
@GetMapping("/custom/logout")
@CustomUserLogin
public R customLogout(@Valid @RequestBody WxUserLoginVo vo) {
wxOauthService.customUserLogout(ThreadLocalRequestDetail.getCustomUserInfo());
return R.ok("登出成功");
}
}

View File

@@ -1,110 +0,0 @@
package com.starry.admin.modules.weichat.controller;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* @author admin
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/weixin/portal/{appid}")
public class WxPortalController {
@Resource
private final WxMpService wxService;
//@Resource
// private final WxMpMessageRouter messageRouter;
@GetMapping(produces = "text/plain;charset=utf-8")
public String authGet(@PathVariable String appid,
@RequestParam(name = "signature", required = false) String signature,
@RequestParam(name = "timestamp", required = false) String timestamp,
@RequestParam(name = "nonce", required = false) String nonce,
@RequestParam(name = "echostr", required = false) String echostr) {
log.info("\n接收到来自微信服务器的认证消息[{}, {}, {}, {}]", signature,
timestamp, nonce, echostr);
if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
throw new IllegalArgumentException("请求参数非法,请核实!");
}
if (!this.wxService.switchover(appid)) {
throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
}
if (wxService.checkSignature(timestamp, nonce, signature)) {
return echostr;
}
return "非法请求";
}
@PostMapping(produces = "application/xml; charset=UTF-8")
public String post(@PathVariable String appid,
@RequestBody String requestBody,
@RequestParam("signature") String signature,
@RequestParam("timestamp") String timestamp,
@RequestParam("nonce") String nonce,
@RequestParam("openid") String openid,
@RequestParam(name = "encrypt_type", required = false) String encType,
@RequestParam(name = "msg_signature", required = false) String msgSignature) {
log.info("\n接收微信请求[openid=[{}], [signature=[{}], encType=[{}], msgSignature=[{}],"
+ " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
openid, signature, encType, msgSignature, timestamp, nonce, requestBody);
if (!this.wxService.switchover(appid)) {
throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
}
if (!wxService.checkSignature(timestamp, nonce, signature)) {
throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
}
String out = null;
if (encType == null) {
// 明文传输的消息
WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
WxMpXmlOutMessage outMessage = this.route(inMessage);
if (outMessage == null) {
return "";
}
out = outMessage.toXml();
} else if ("aes".equalsIgnoreCase(encType)) {
// aes加密的消息
WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxService.getWxMpConfigStorage(),
timestamp, nonce, msgSignature);
log.debug("\n消息解密后内容为\n{} ", inMessage.toString());
WxMpXmlOutMessage outMessage = this.route(inMessage);
if (outMessage == null) {
return "";
}
out = outMessage.toEncryptedXml(wxService.getWxMpConfigStorage());
}
log.debug("\n组装回复信息{}", out);
return out;
}
private WxMpXmlOutMessage route(WxMpXmlMessage message) {
// try {
// return this.messageRouter.route(message);
//} catch (Exception e) {
// log.error("路由消息时出现异常!", e);
//}
return null;
}
}

View File

@@ -1,108 +0,0 @@
package com.starry.admin.modules.weichat.controller;
import com.starry.common.result.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpDataCubeService;
import me.chanjar.weixin.mp.api.WxMpService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
/**
* 微信账号配置
*
* @author admin
* @since 2019-03-23 21:26:35
*/
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/wxsummary")
public class WxSummaryController {
@Resource
WxMpService wxService;
/**
* 获取用户增减数据
*
* @param appId
* @param startDate
* @param endDate
* @return
*/
@GetMapping("/usersummary")
// @PreAuthorize("@customSs.hasPermission('wxmp:wxsummary:index')")
public R getUsersummary(String appId, String startDate, String endDate) {
try {
WxMpDataCubeService wxMpDataCubeService = wxService.getDataCubeService();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return R.ok(wxMpDataCubeService.getUserSummary(sdf.parse(startDate), sdf.parse(endDate)));
} catch (WxErrorException e) {
log.error("获取用户增减数据失败", e);
return R.error(e.getMessage());
} catch (Exception e) {
log.error("获取用户增减数据失败", e);
return R.error("获取用户增减数据失败");
}
}
/**
* 获取累计用户数据
*
* @param appId
* @param startDate
* @param endDate
* @return
*/
@GetMapping("/usercumulate")
// @PreAuthorize("@customSs.hasPermission('wxmp:wxsummary:index')")
public R getUserCumulate(String appId, String startDate, String endDate) {
try {
WxMpDataCubeService wxMpDataCubeService = wxService.getDataCubeService();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return R.ok(wxMpDataCubeService.getUserCumulate(sdf.parse(startDate), sdf.parse(endDate)));
} catch (WxErrorException e) {
log.error("获取累计用户数据失败", e);
return R.error(e.getMessage());
} catch (Exception e) {
log.error("获取用户增减数据失败", e);
return R.error("获取用户增减数据失败");
}
}
/**
* 获取接口分析数据
*
* @param appId
* @param startDate
* @param endDate
* @return
*/
@GetMapping("/interfacesummary")
// @PreAuthorize("@customSs.hasPermission('wxmp:wxsummary:index')")
public R getInterfaceSummary(String appId, String startDate, String endDate) {
try {
WxMpDataCubeService wxMpDataCubeService = wxService.getDataCubeService();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return R.ok(wxMpDataCubeService.getInterfaceSummary(sdf.parse(startDate), sdf.parse(endDate)));
} catch (WxErrorException e) {
log.error("获取接口分析数据失败", e);
return R.error(e.getMessage());
} catch (Exception e) {
log.error("获取接口分析数据失败", e);
return R.error("获取接口分析数据失败");
}
}
}

View File

@@ -1,174 +0,0 @@
package com.starry.admin.modules.weichat.controller;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.modules.weichat.entity.WxUser;
import com.starry.admin.modules.weichat.service.WxUserService;
import com.starry.common.result.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* 微信用户
*
* @author admin
* @since 2019-03-25 15:39:39
*/
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/wxuser")
public class WxUserController {
@Resource
WxUserService wxUserService;
/**
* 分页查询
*
* @param page 分页对象
* @param wxUser 微信用户
* @return
*/
@GetMapping("/page")
@PreAuthorize("@customSs.hasPermission('wxmp:wxuser:index')")
public R getWxUserPage(Page page, WxUser wxUser, String tagId) {
Wrapper<WxUser> queryWrapper;
if (StringUtils.isNotBlank(tagId)) {
queryWrapper = Wrappers.lambdaQuery(wxUser)
.and(wrapper -> wrapper
.eq(WxUser::getTagidList, "[" + tagId + "]")
.or()
.like(WxUser::getTagidList, "," + tagId + ",")
.or()
.likeRight(WxUser::getTagidList, "[" + tagId + ",")
.or()
.likeLeft(WxUser::getTagidList, "," + tagId + "]"));
} else if (StrUtil.isNotBlank(wxUser.getNickName())) {
String nickName = wxUser.getNickName();
wxUser.setNickName(null);
queryWrapper = Wrappers.lambdaQuery(wxUser)
.like(WxUser::getNickName, nickName);
} else {
queryWrapper = Wrappers.lambdaQuery(wxUser);
}
return R.ok(wxUserService.page(page, queryWrapper));
}
/**
* 通过id查询微信用户
*
* @param id id
* @return R
*/
@GetMapping("/{id}")
@PreAuthorize("@customSs.hasPermission('wxmp:wxuser:get')")
public R getById(@PathVariable("id") String id) {
return R.ok(wxUserService.getById(id));
}
/**
* 新增微信用户
*
* @param wxUser 微信用户
* @return R
*/
@PostMapping
@PreAuthorize("@customSs.hasPermission('wxmp:wxuser:add')")
public R save(@RequestBody WxUser wxUser) {
return R.ok(wxUserService.save(wxUser));
}
/**
* 修改微信用户
*
* @param wxUser 微信用户
* @return R
*/
@PutMapping
@PreAuthorize("@customSs.hasPermission('wxmp:wxuser:edit')")
public R updateById(@RequestBody WxUser wxUser) {
return R.ok(wxUserService.updateById(wxUser));
}
/**
* 通过id删除微信用户
*
* @param id id
* @return R
*/
@DeleteMapping("/{id}")
@PreAuthorize("@customSs.hasPermission('wxmp:wxuser:del')")
public R removeById(@PathVariable String id) {
return R.ok(wxUserService.removeById(id));
}
@PostMapping("/synchron")
@PreAuthorize("@customSs.hasPermission('wxmp:wxuser:synchro')")
public R synchron() {
try {
wxUserService.synchroWxUser();
return R.ok();
} catch (WxErrorException e) {
log.error("同步微信用户失败", e);
return R.error(e.getMessage());
}
}
/**
* 修改微信用户备注
*
* @param wxUser
* @return
*/
@PutMapping("/remark")
@PreAuthorize("@customSs.hasPermission('wxmp:wxuser:edit:remark')")
public R remark(@RequestBody WxUser wxUser) {
try {
return R.ok(wxUserService.updateRemark(wxUser));
} catch (WxErrorException e) {
log.error("修改微信用户备注失败", e);
return R.error(e.getMessage());
}
}
/**
* 打标签
*
* @param data
* @return
*/
@PutMapping("/tagid-list")
@PreAuthorize("@customSs.hasPermission('wxmp:wxuser:tagging')")
public R tagidList(@RequestBody JSONObject data) {
try {
String appId = data.getStr("appId");
String taggingType = data.getStr("taggingType");
JSONArray tagIdsArray = data.getJSONArray("tagIds");
JSONArray openIdsArray = data.getJSONArray("openIds");
String[] openIds = openIdsArray.toArray(new String[0]);
for (Object tagId : tagIdsArray) {
wxUserService.tagging(taggingType, Long.valueOf(String.valueOf(tagId)), openIds);
}
return R.ok();
} catch (WxErrorException e) {
log.error("修改微信用户备注失败", e);
return R.error(e.getMessage());
}
}
}

View File

@@ -1,159 +0,0 @@
package com.starry.admin.modules.weichat.controller;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.starry.admin.modules.weichat.entity.WxUser;
import com.starry.admin.modules.weichat.entity.WxUserTagsDict;
import com.starry.admin.modules.weichat.service.WxUserService;
import com.starry.common.result.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxMpUserTagService;
import me.chanjar.weixin.mp.bean.tag.WxUserTag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* 微信用户标签
*
* @author admin
* @since 2019-03-25 15:39:39
*/
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/wxusertags")
public class WxUserTagsController {
@Resource
WxMpService wxService;
@Resource
WxUserService wxUserService;
/**
* 获取微信用户标签
*
* @return
*/
@PreAuthorize("@customSs.hasPermission('wxmp:wxusertags:list')")
@GetMapping("/list")
public R getWxUserList(String appId) {
WxMpUserTagService wxMpUserTagService = wxService.getUserTagService();
try {
List<WxUserTag> listWxUserTag = wxMpUserTagService.tagGet();
return R.ok(listWxUserTag);
} catch (WxErrorException e) {
log.error("获取微信用户标签失败", e);
return R.error(e.getMessage());
}
}
/**
* 获取微信用户标签字典
*
* @param appId
* @return
*/
@PreAuthorize("@customSs.hasPermission('wxmp:wxusertags:list')")
@GetMapping("/dict")
public R getWxUserTagsDict(String appId) {
WxMpUserTagService wxMpUserTagService = wxService.getUserTagService();
try {
List<WxUserTag> listWxUserTag = wxMpUserTagService.tagGet();
List<WxUserTagsDict> listWxUserTagsDict = new ArrayList<>();
WxUserTagsDict wxUserTagsDict;
for (WxUserTag wxUserTag : listWxUserTag) {
wxUserTagsDict = new WxUserTagsDict();
wxUserTagsDict.setName(wxUserTag.getName());
wxUserTagsDict.setValue(wxUserTag.getId());
listWxUserTagsDict.add(wxUserTagsDict);
}
return R.ok(listWxUserTagsDict);
} catch (WxErrorException e) {
log.error("获取微信用户标签字典失败", e);
return R.error(e.getMessage());
}
}
/**
* 新增微信用户标签
*
* @return
*/
@PreAuthorize("@customSs.hasPermission('wxmp:wxusertags:add')")
@PostMapping
public R save(@RequestBody JSONObject data) {
String appId = data.getStr("appId");
String name = data.getStr("name");
WxMpUserTagService wxMpUserTagService = wxService.getUserTagService();
try {
return R.ok(wxMpUserTagService.tagCreate(name));
} catch (WxErrorException e) {
log.error("新增微信用户标签失败", e);
return R.error(e.getMessage());
}
}
/**
* 修改微信用户标签
*
* @return
*/
@PreAuthorize("@customSs.hasPermission('wxmp:wxusertags:edit')")
@PutMapping
public R updateById(@RequestBody JSONObject data) {
String appId = data.getStr("appId");
Long id = data.getLong("id");
String name = data.getStr("name");
WxMpUserTagService wxMpUserTagService = wxService.getUserTagService();
try {
return R.ok(wxMpUserTagService.tagUpdate(id, name));
} catch (WxErrorException e) {
log.error("修改微信用户标签失败", e);
return R.error(e.getMessage());
}
}
/**
* 删除微信用户标签
*
* @param id
* @param appId
* @return
*/
@PreAuthorize("@customSs.hasPermission('wxmp:wxusertags:del')")
@DeleteMapping
public R removeById(Long id, String appId) {
int count = (int) wxUserService.count(Wrappers.<WxUser>lambdaQuery()
.and(wrapper -> wrapper
.eq(WxUser::getTagidList, "[" + id + "]")
.or()
.like(WxUser::getTagidList, "," + id + ",")
.or()
.likeRight(WxUser::getTagidList, "[" + id + ",")
.or()
.likeLeft(WxUser::getTagidList, "," + id + "]")));
if (count > 0) {
return R.error("该标签下有用户存在,无法删除");
}
WxMpUserTagService wxMpUserTagService = wxService.getUserTagService();
try {
return R.ok(wxMpUserTagService.tagDelete(id));
} catch (WxErrorException e) {
log.error("删除微信用户标签失败", e);
return R.error(e.getMessage());
}
}
}

View File

@@ -1,32 +0,0 @@
package com.starry.admin.modules.weichat.entity;
import lombok.Data;
/**
* @author admin
*/
@Data
public class CustomWxMpProperties {
/**
* 微信APPID
*/
public String appid = "wx917f3f747c7dc5dd";
/**
* 微信公众号的app secret
*/
public String secret = "85012dec2ba8bdc9d0174dd800ef1dec";
/**
* 微信公众号的token
*/
public String token = "AkzAW8yqUhOWAFN550";
/**
* 微信公众号的EncodingAESKey
*/
public String aesKey = "tsoM88UUQ5uEHJ29xgNiaHHaoswZapS5ijWpaN6hUZF";
}

View File

@@ -1,22 +0,0 @@
package com.starry.admin.modules.weichat.entity;
import lombok.Data;
import java.io.Serializable;
/**
* imageManager
*
* @author admin
* @since 2019-03-23 21:26:35
*/
@Data
public class ImageManager implements Serializable {
private static final long serialVersionUID = 1L;
private String url;
private String thumb;
private String tag;
private String name;
private Integer id;
}

View File

@@ -1,40 +0,0 @@
package com.starry.admin.modules.weichat.entity;
import cn.hutool.json.JSONUtil;
import lombok.Data;
import me.chanjar.weixin.common.bean.menu.WxMenuRule;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 自定义菜单模型
*
* @author admin
*/
@Data
public class Menu implements Serializable {
private static final long serialVersionUID = -7083914585539687746L;
private List<MenuButton> button = new ArrayList<>();
private WxMenuRule matchrule;
/**
* 反序列化
*/
public static Menu fromJson(String json) {
return JSONUtil.parseObj(json).toBean(Menu.class);
}
public String toJson() {
return JSONUtil.toJsonStr(this);
}
@Override
public String toString() {
return this.toJson();
}
}

View File

@@ -1,68 +0,0 @@
package com.starry.admin.modules.weichat.entity;
import cn.hutool.json.JSONObject;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 自定义菜单模型
*
* @author admin
*/
@Data
public class MenuButton implements Serializable {
private String type;
private String name;
private String key;
private String url;
private String media_id;
private String appid;
private String pagepath;
private List<MenuButton> sub_button = new ArrayList<>();
/**
* content内容
*/
private JSONObject content;
private String repContent;
/**
* 消息类型
*/
private String repType;
/**
* 消息名
*/
private String repName;
/**
* 视频和音乐的描述
*/
private String repDesc;
/**
* 视频和音乐的描述
*/
private String repUrl;
/**
* 高质量链接
*/
private String repHqUrl;
/**
* 缩略图的媒体id
*/
private String repThumbMediaId;
/**
* 缩略图url
*/
private String repThumbUrl;
private String article_id;
}

View File

@@ -0,0 +1,69 @@
package com.starry.admin.modules.weichat.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.starry.common.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 微信用户对象 play_wx_user_info
*
* @author admin
* @since 2024-04-07
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("play_wx_user_info")
public class PlayWxUserInfoEntity extends BaseEntity<PlayWxUserInfoEntity> {
/**
* UUID
*/
private String id;
/**
* 租户ID
*/
private String tenantId;
/**
* 用户的标识,对当前公众号唯一
*/
private String openid;
/**
* 用户的标识,对当前公众号唯一
*/
private String unionid;
/**
* 昵称
*/
private String nickname;
/**
* 性别值为1时是男性值为2时是女性值为0时是未知
*/
private Integer sex;
/**
* 所在城市
*/
private String city;
/**
* 所在国家
*/
private String country;
/**
* 所在省份
*/
private String province;
/**
* 所在省份
*/
private String avatar;
}

View File

@@ -1,28 +0,0 @@
package com.starry.admin.modules.weichat.entity;
import lombok.Data;
import java.io.Serializable;
/**
* @author admin
*/
@Data
public class ThirdSession implements Serializable {
/**
* 微信用户ID
*/
private String wxUserId;
/**
* 配置项ID
*/
private String appId;
/**
* 微信sessionKey
*/
private String sessionKey;
/**
* 用户标识
*/
private String openId;
}

View File

@@ -1,119 +0,0 @@
package com.starry.admin.modules.weichat.entity;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.starry.common.config.typehandler.JsonTypeHandler;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.ibatis.type.JdbcType;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
/**
* 消息自动回复
*
* @author admin
* @since 2019-04-18 15:40:39
*/
@Data
@TableName("wx_auto_reply")
@EqualsAndHashCode(callSuper = true)
public class WxAutoReply extends Model<WxAutoReply> {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
* 创建者
*/
private String createId;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新者
*/
private String updateId;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 备注
*/
private String remark;
/**
* 逻辑删除标记0显示1隐藏
*/
private String delFlag;
/**
* 类型1、关注时回复2、消息回复3、关键词回复
*/
@NotNull(message = "类型不能为空")
private String type;
/**
* 关键词
*/
private String reqKey;
/**
* 请求消息类型text文本image图片voice语音video视频shortvideo小视频location地理位置
*/
private String reqType;
/**
* 回复消息类型text文本image图片voice语音video视频music音乐news图文
*/
@NotNull(message = "回复消息类型不能为空")
private String repType;
/**
* 回复类型文本匹配类型1、全匹配2、半匹配
*/
private String repMate;
/**
* 回复类型文本保存文字
*/
private String repContent;
/**
* 回复的素材名、视频和音乐的标题
*/
private String repName;
/**
* 回复类型imge、voice、news、video的mediaID或音乐缩略图的媒体id
*/
private String repMediaId;
/**
* 视频和音乐的描述
*/
private String repDesc;
/**
* 链接
*/
private String repUrl;
/**
* 高质量链接
*/
private String repHqUrl;
/**
* 缩略图的媒体id
*/
private String repThumbMediaId;
/**
* 缩略图url
*/
private String repThumbUrl;
/**
* 图文消息的内容
*/
@TableField(typeHandler = JsonTypeHandler.class, jdbcType = JdbcType.VARCHAR)
private JSONObject content;
}

View File

@@ -1,117 +0,0 @@
package com.starry.admin.modules.weichat.entity;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.starry.common.config.typehandler.JsonTypeHandler;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.ibatis.type.JdbcType;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
/**
* 自定义菜单
*
* @author admin
* @since 2019-03-27 16:52:10
*/
@Data
@TableName("wx_menu")
@EqualsAndHashCode(callSuper = true)
public class WxMenu extends Model<WxMenu> {
private static final long serialVersionUID = 1L;
/**
* 菜单IDclick、scancode_push、scancode_waitmsg、pic_sysphoto、pic_photo_or_album、pic_weixin、location_select保存key
*/
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
* 父菜单ID
*/
private String parentId;
/**
* 排序值
*/
private Integer sort;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 逻辑删除标记0显示1隐藏
*/
private String delFlag;
/**
* 菜单类型click、view、miniprogram、scancode_push、scancode_waitmsg、pic_sysphoto、pic_photo_or_album、pic_weixin、location_select、media_id、view_limited等
*/
@NotNull(message = "菜单类型不能为空")
private String type;
/**
* 菜单名
*/
@NotNull(message = "菜单名不能为空")
private String name;
/**
* View保存链接到url
*/
private String url;
/**
* Img、voice、News保存mediaID
*/
private String repMediaId;
/**
* 回复消息类型text文本image图片voice语音video视频music音乐news图文
*/
private String repType;
/**
* 素材名、视频和音乐的标题
*/
private String repName;
/**
* Text:保存文字
*/
private String repContent;
/**
* 小程序的appid
*/
private String maAppId;
/**
* 小程序的页面路径
*/
private String maPagePath;
/**
* 视频和音乐的描述
*/
private String repDesc;
/**
* 视频和音乐的描述
*/
private String repUrl;
/**
* 高质量链接
*/
private String repHqUrl;
/**
* 缩略图的媒体id
*/
private String repThumbMediaId;
/**
* 缩略图url
*/
private String repThumbUrl;
/**
* 图文消息的内容
*/
@TableField(typeHandler = JsonTypeHandler.class, jdbcType = JdbcType.VARCHAR)
private JSONObject content;
}

View File

@@ -1,145 +0,0 @@
package com.starry.admin.modules.weichat.entity;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.starry.common.config.typehandler.JsonTypeHandler;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.ibatis.type.JdbcType;
import java.time.LocalDateTime;
/**
* 微信消息
*
* @author admin
* @since 2019-05-28 16:12:10
*/
@Data
@TableName("wx_msg")
@EqualsAndHashCode(callSuper = true)
@ApiModel(description = "微信消息")
public class WxMsg extends Model<WxMsg> {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
* 创建者
*/
private String createId;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新者
*/
private String updateId;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 备注
*/
private String remark;
/**
* 逻辑删除标记0显示1隐藏
*/
private String delFlag;
/**
* 公众号名称
*/
private String appName;
/**
* 公众号logo
*/
private String appLogo;
/**
* 微信用户ID
*/
private String wxUserId;
/**
* 昵称
*/
private String nickName;
/**
* 头像
*/
private String headimgUrl;
/**
* 消息分类1、用户发给公众号2、公众号发给用户
*/
private String type;
/**
* 消息类型text文本image图片voice语音video视频shortvideo小视频location地理位置music音乐news图文event推送事件
*/
private String repType;
/**
* 事件类型subscribe关注unsubscribe取关CLICK、VIEW菜单事件
*/
private String repEvent;
/**
* 回复类型文本保存文字
*/
private String repContent;
/**
* 回复类型imge、voice、news、video的mediaID或音乐缩略图的媒体id
*/
private String repMediaId;
/**
* 回复的素材名、视频和音乐的标题
*/
private String repName;
/**
* 视频和音乐的描述
*/
private String repDesc;
/**
* 链接
*/
private String repUrl;
/**
* 高质量链接
*/
private String repHqUrl;
/**
* 图文消息的内容
*/
@TableField(typeHandler = JsonTypeHandler.class, jdbcType = JdbcType.VARCHAR)
private JSONObject content;
/**
* 缩略图的媒体id
*/
private String repThumbMediaId;
/**
* 缩略图url
*/
private String repThumbUrl;
/**
* 地理位置维度
*/
private Double repLocationX;
/**
* 地理位置经度
*/
private Double repLocationY;
/**
* 地图缩放大小
*/
private Double repScale;
/**
* 已读标记01
*/
private String readFlag;
}

View File

@@ -1,27 +0,0 @@
package com.starry.admin.modules.weichat.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 微信消息
*
* @author admin
* @since 2019-05-28 16:12:10
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class WxMsgVO extends WxMsg {
private static final long serialVersionUID = 1L;
/**
* 数量
*/
private Integer countMsg;
/**
* repType not in筛选
*/
private String notInRepType;
}

View File

@@ -1,20 +0,0 @@
package com.starry.admin.modules.weichat.entity;
import lombok.Data;
/**
* 微信开发数据
*
* @author admin
*/
@Data
public class WxOpenDataDTO {
private String appId;
private String userId;
private String encryptedData;
private String errMsg;
private String iv;
private String rawData;
private String signature;
private String sessionKey;
}

View File

@@ -1,153 +0,0 @@
package com.starry.admin.modules.weichat.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.starry.common.config.typehandler.ArrayLongTypeHandler;
import com.starry.common.sensitive.Sensitive;
import com.starry.common.sensitive.SensitiveTypeEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.ibatis.type.JdbcType;
import java.time.LocalDateTime;
/**
* 微信用户
*
* @author admin
* @since 2019-03-25 15:39:39
*/
@Data
@TableName("wx_user")
@EqualsAndHashCode(callSuper = true)
public class WxUser extends Model<WxUser> {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
* 创建者
*/
private String createId;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新者
*/
private String updateId;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 备注信息
*/
private String remark;
/**
* 逻辑删除标记0显示1隐藏
*/
private String delFlag;
/**
* 应用类型(1:小程序2:公众号)
*/
private String appType;
/**
* 是否订阅012网页授权用户
*/
private String subscribe;
/**
* 返回用户关注的渠道来源ADD_SCENE_SEARCH 公众号搜索ADD_SCENE_ACCOUNT_MIGRATION 公众号迁移ADD_SCENE_PROFILE_CARD 名片分享ADD_SCENE_QR_CODE 扫描二维码ADD_SCENEPROFILE LINK 图文页内名称点击ADD_SCENE_PROFILE_ITEM 图文页右上角菜单ADD_SCENE_PAID 支付后关注ADD_SCENE_OTHERS 其他
*/
private String subscribeScene;
/**
* 关注时间
*/
private LocalDateTime subscribeTime;
/**
* 关注次数
*/
private Integer subscribeNum;
/**
* 取消关注时间
*/
private LocalDateTime cancelSubscribeTime;
/**
* 用户标识
*/
private String openId;
/**
* 昵称
*/
private String nickName;
/**
* 性别120未知
*/
private String sex;
/**
* 所在城市
*/
private String city;
/**
* 所在国家
*/
private String country;
/**
* 所在省份
*/
private String province;
/**
* 手机号码
*/
@Sensitive(type = SensitiveTypeEnum.MOBILE_PHONE)
private String phone;
/**
* 用户语言
*/
private String language;
/**
* 头像
*/
private String headimgUrl;
/**
* union_id
*/
private String unionId;
/**
* 用户组
*/
private String groupId;
/**
* 标签列表
*/
@TableField(typeHandler = ArrayLongTypeHandler.class, jdbcType = JdbcType.VARCHAR)
private Long[] tagidList;
/**
* 二维码扫码场景
*/
private String qrSceneStr;
/**
* 地理位置纬度
*/
private Double latitude;
/**
* 地理位置经度
*/
private Double longitude;
/**
* 地理位置精度
*/
@TableField(value = "`precision`")
private Double precision;
/**
* 会话密钥
*/
private String sessionKey;
}

View File

@@ -0,0 +1,13 @@
package com.starry.admin.modules.weichat.entity;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class WxUserLoginVo {
@NotBlank(message = "code不能为空")
private String code;
}

View File

@@ -6,7 +6,8 @@ import lombok.Data;
* @author admin
*/
@Data
public class WxUserTagsDict {
private String name;
private Long value;
public class WxUserQueryAddressVo {
private String url;
}

View File

@@ -1,12 +0,0 @@
package com.starry.admin.modules.weichat.handler;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author admin
*/
public abstract class AbstractHandler implements WxMpMessageHandler {
protected Logger logger = LoggerFactory.getLogger(getClass());
}

View File

@@ -1,25 +0,0 @@
package com.starry.admin.modules.weichat.handler;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author admin
*/
@Component
public class KfSessionHandler extends AbstractHandler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) {
// TODO 对会话做处理
return null;
}
}

View File

@@ -1,44 +0,0 @@
package com.starry.admin.modules.weichat.handler;
import com.starry.admin.modules.weichat.builder.TextBuilder;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.stereotype.Component;
import java.util.Map;
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType;
/**
* @author admin
*/
@Component
public class LocationHandler extends AbstractHandler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) {
if (wxMessage.getMsgType().equals(XmlMsgType.LOCATION)) {
// TODO 接收处理用户发送的地理位置消息
try {
String content = "感谢反馈,您的的地理位置已收到!";
return new TextBuilder().build(content, wxMessage, null);
} catch (Exception e) {
this.logger.error("位置消息接收处理失败", e);
return null;
}
}
// 上报地理位置事件
this.logger.info("上报地理位置,纬度 : {},经度 : {},精度 : {}",
wxMessage.getLatitude(), wxMessage.getLongitude(), wxMessage.getPrecision());
// TODO 可以将用户地理位置信息保存到本地数据库,以便以后使用
return null;
}
}

View File

@@ -1,39 +0,0 @@
package com.starry.admin.modules.weichat.handler;
import cn.hutool.core.util.StrUtil;
import com.starry.admin.modules.weichat.utils.JsonUtils;
import com.starry.common.utils.HttpUtils;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author admin
*/
@Component
public class LogHandler extends AbstractHandler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) {
this.logger.info("\n接收到请求消息内容{}", JsonUtils.toJson(wxMessage));
// 以下为测试代码,自行删除不影响系统功能
if (wxMessage.getMsgType().equals(WxConsts.XmlMsgType.EVENT)) {
if (wxMessage.getEvent().equals(WxConsts.EventType.SUBSCRIBE) ||
wxMessage.getEvent().equals(WxConsts.EventType.SCAN)) {
if (wxMessage.getEventKey().contains("jl-wiki")) {
String openId = wxMessage.getFromUser();
String sceneStr = StrUtil.split(wxMessage.getEventKey(), ":").get(1);
String rs = HttpUtils.sendPost("http://127.0.0.1:8083/joolun-open/user", StrUtil.format("openId={}&sceneStr={}", openId, sceneStr));
}
}
}
return null;
}
}

View File

@@ -1,172 +0,0 @@
package com.starry.admin.modules.weichat.handler;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.starry.admin.modules.weichat.config.CommonConstants;
import com.starry.admin.modules.weichat.constant.ConfigConstant;
import com.starry.admin.modules.weichat.entity.WxMenu;
import com.starry.admin.modules.weichat.entity.WxMsg;
import com.starry.admin.modules.weichat.entity.WxUser;
import com.starry.admin.modules.weichat.mapper.WxMenuMapper;
import com.starry.admin.modules.weichat.mapper.WxMsgMapper;
import com.starry.admin.modules.weichat.mapper.WxUserMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutNewsMessage;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.builder.outxml.*;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author admin
*/
@Slf4j
@Component
@AllArgsConstructor
public class MenuHandler extends AbstractHandler {
private final WxMenuMapper wxMenuMapper;
private final WxUserMapper wxUserMapper;
private final WxMsgMapper wxMsgMapper;
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
Map<String, Object> context, WxMpService weixinService,
WxSessionManager sessionManager) throws WxErrorException {
// 消息记录
WxMenu wxMenu;
if (WxConsts.EventType.CLICK.equals(wxMessage.getEvent())
|| WxConsts.EventType.SCANCODE_WAITMSG.equals(wxMessage.getEvent())) {
wxMenu = wxMenuMapper.selectById(wxMessage.getEventKey());
if (wxMenu == null) {// 菜单过期
return new TextBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).content("非常抱歉,该菜单已删除!").build();
}
} else {
wxMenu = new WxMenu();
}
WxUser wxUser = wxUserMapper.selectOne(Wrappers.<WxUser>lambdaQuery()
.eq(WxUser::getOpenId, wxMessage.getFromUser()));
if (wxUser == null) {// 库中无此用户
WxMpUser userWxInfo = weixinService.getUserService()
.userInfo(wxMessage.getFromUser(), null);
wxUser = new WxUser();
wxUser.setSubscribeNum(1);
SubscribeHandler.setWxUserValue(wxUser, userWxInfo);
wxUserMapper.insert(wxUser);
}
// 组装菜单回复消息
return getWxMpXmlOutMessage(wxMessage, wxMenu, wxUser);
}
/**
* 组装菜单回复消息
*
* @param wxMessage
* @param wxMenu
* @return
*/
public WxMpXmlOutMessage getWxMpXmlOutMessage(WxMpXmlMessage wxMessage, WxMenu wxMenu, WxUser wxUser) {
WxMpXmlOutMessage wxMpXmlOutMessage = null;
// 记录接收消息
WxMsg wxMsg = new WxMsg();
// wxMsg.setTenantId(wxApp.getTenantId());
wxMsg.setWxUserId(wxUser.getId());
wxMsg.setNickName(wxUser.getNickName());
wxMsg.setHeadimgUrl(wxUser.getHeadimgUrl());
wxMsg.setType(ConfigConstant.WX_MSG_TYPE_1);
wxMsg.setRepEvent(wxMessage.getEvent());
wxMsg.setRepType(wxMessage.getMsgType());
wxMsg.setRepName(wxMenu.getName());
if (WxConsts.EventType.VIEW.equals(wxMessage.getEvent())) {
wxMsg.setRepUrl(wxMessage.getEventKey());
}
if (WxConsts.EventType.SCANCODE_WAITMSG.equals(wxMessage.getEvent())) {
wxMsg.setRepContent(wxMessage.getScanCodeInfo().getScanResult());
}
wxMsg.setReadFlag(CommonConstants.NO);
LocalDateTime now = LocalDateTime.now();
wxMsg.setCreateTime(now);
wxMsgMapper.insert(wxMsg);
if (WxConsts.MenuButtonType.CLICK.equals(wxMenu.getType())
|| WxConsts.MenuButtonType.SCANCODE_WAITMSG.equals(wxMenu.getType())) {
// 记录回复消息
wxMsg = new WxMsg();
wxMsg.setWxUserId(wxUser.getId());
wxMsg.setNickName(wxUser.getNickName());
wxMsg.setHeadimgUrl(wxUser.getHeadimgUrl());
wxMsg.setCreateTime(now.plusSeconds(1));
wxMsg.setType(ConfigConstant.WX_MSG_TYPE_2);
wxMsg.setRepType(wxMenu.getRepType());
if (WxConsts.KefuMsgType.TEXT.equals(wxMenu.getRepType())) {
wxMsg.setRepContent(wxMenu.getRepContent());
wxMpXmlOutMessage = new TextBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).content(wxMenu.getRepContent()).build();
}
if (WxConsts.KefuMsgType.IMAGE.equals(wxMenu.getRepType())) {
wxMsg.setRepName(wxMenu.getRepName());
wxMsg.setRepUrl(wxMenu.getRepUrl());
wxMsg.setRepMediaId(wxMenu.getRepMediaId());
wxMpXmlOutMessage = new ImageBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).mediaId(wxMenu.getRepMediaId()).build();
}
if (WxConsts.KefuMsgType.VOICE.equals(wxMenu.getRepType())) {
wxMsg.setRepName(wxMenu.getRepName());
wxMsg.setRepUrl(wxMenu.getRepUrl());
wxMsg.setRepMediaId(wxMenu.getRepMediaId());
wxMpXmlOutMessage = new VoiceBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).mediaId(wxMenu.getRepMediaId()).build();
}
if (WxConsts.KefuMsgType.VIDEO.equals(wxMenu.getRepType())) {
wxMsg.setRepName(wxMenu.getRepName());
wxMsg.setRepDesc(wxMenu.getRepDesc());
wxMsg.setRepUrl(wxMenu.getRepUrl());
wxMsg.setRepMediaId(wxMenu.getRepMediaId());
wxMpXmlOutMessage = new VideoBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).mediaId(wxMenu.getRepMediaId())
.title(wxMenu.getRepName()).description(wxMenu.getRepDesc()).build();
}
if (WxConsts.KefuMsgType.MUSIC.equals(wxMenu.getRepType())) {
wxMsg.setRepName(wxMenu.getRepName());
wxMsg.setRepDesc(wxMenu.getRepDesc());
wxMsg.setRepUrl(wxMenu.getRepUrl());
wxMsg.setRepHqUrl(wxMenu.getRepHqUrl());
wxMsg.setRepThumbMediaId(wxMenu.getRepThumbMediaId());
wxMsg.setRepThumbUrl(wxMenu.getRepThumbUrl());
wxMpXmlOutMessage = new MusicBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
.thumbMediaId(wxMenu.getRepThumbMediaId())
.title(wxMenu.getRepName()).description(wxMenu.getRepDesc())
.musicUrl(wxMenu.getRepUrl()).hqMusicUrl(wxMenu.getRepHqUrl()).build();
}
if (WxConsts.KefuMsgType.NEWS.equals(wxMenu.getRepType())) {
List<WxMpXmlOutNewsMessage.Item> list = new ArrayList<>();
List<JSONObject> listJSONObject = JSONUtil.toList(wxMenu.getContent().getJSONArray("articles"), JSONObject.class);
WxMpXmlOutNewsMessage.Item t;
for (JSONObject jSONObject : listJSONObject) {
t = new WxMpXmlOutNewsMessage.Item();
t.setTitle(jSONObject.getStr("title"));
t.setDescription(jSONObject.getStr("digest"));
t.setPicUrl(jSONObject.getStr("thumbUrl"));
t.setUrl(jSONObject.getStr("url"));
list.add(t);
}
wxMsg.setRepName(wxMenu.getRepName());
wxMsg.setRepDesc(wxMenu.getRepDesc());
wxMsg.setRepUrl(wxMenu.getRepUrl());
wxMsg.setRepMediaId(wxMenu.getRepMediaId());
wxMsg.setContent(wxMenu.getContent());
wxMpXmlOutMessage = new NewsBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).articles(list).build();
}
wxMsgMapper.insert(wxMsg);
}
return wxMpXmlOutMessage;
}
}

View File

@@ -1,194 +0,0 @@
package com.starry.admin.modules.weichat.handler;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.starry.admin.modules.weichat.config.CommonConstants;
import com.starry.admin.modules.weichat.constant.ConfigConstant;
import com.starry.admin.modules.weichat.constant.WebSocketConstant;
import com.starry.admin.modules.weichat.entity.WxAutoReply;
import com.starry.admin.modules.weichat.entity.WxMsg;
import com.starry.admin.modules.weichat.entity.WxUser;
import com.starry.admin.modules.weichat.mapper.WxUserMapper;
import com.starry.admin.modules.weichat.service.WxAutoReplyService;
import com.starry.admin.modules.weichat.service.WxMsgService;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutNewsMessage;
import me.chanjar.weixin.mp.builder.outxml.*;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType;
/**
* @author admin
*/
@Component
@AllArgsConstructor
public class MsgHandler extends AbstractHandler {
private final WxAutoReplyService wxAutoReplyService;
private final WxUserMapper wxUserMapper;
private final WxMsgService wxMsgService;
/**
* 组装回复消息,并记录消息
*
* @param wxMessage
* @param listWxAutoReply
* @return
*/
public static WxMpXmlOutMessage getWxMpXmlOutMessage(WxMpXmlMessage wxMessage, List<WxAutoReply> listWxAutoReply, WxUser wxUser, WxMsgService wxMsgService) {
WxMpXmlOutMessage wxMpXmlOutMessage = null;
// 记录接收消息
WxMsg wxMsg = new WxMsg();
wxMsg.setWxUserId(wxUser.getId());
wxMsg.setNickName(wxUser.getNickName());
wxMsg.setHeadimgUrl(wxUser.getHeadimgUrl());
wxMsg.setType(ConfigConstant.WX_MSG_TYPE_1);
wxMsg.setRepEvent(wxMessage.getEvent());
wxMsg.setRepType(wxMessage.getMsgType());
wxMsg.setRepMediaId(wxMessage.getMediaId());
if (XmlMsgType.TEXT.equals(wxMessage.getMsgType())) {
wxMsg.setRepContent(wxMessage.getContent());
}
if (XmlMsgType.VOICE.equals(wxMessage.getMsgType())) {
wxMsg.setRepName(wxMessage.getMediaId() + "." + wxMessage.getFormat());
wxMsg.setRepContent(wxMessage.getRecognition());
}
if (XmlMsgType.IMAGE.equals(wxMessage.getMsgType())) {
wxMsg.setRepUrl(wxMessage.getPicUrl());
}
if (XmlMsgType.LINK.equals(wxMessage.getMsgType())) {
wxMsg.setRepName(wxMessage.getTitle());
wxMsg.setRepDesc(wxMessage.getDescription());
wxMsg.setRepUrl(wxMessage.getUrl());
}
if (WxConsts.MediaFileType.FILE.equals(wxMessage.getMsgType())) {
wxMsg.setRepName(wxMessage.getTitle());
wxMsg.setRepDesc(wxMessage.getDescription());
}
if (XmlMsgType.VIDEO.equals(wxMessage.getMsgType())) {
wxMsg.setRepThumbMediaId(wxMessage.getThumbMediaId());
}
if (XmlMsgType.LOCATION.equals(wxMessage.getMsgType())) {
wxMsg.setRepLocationX(wxMessage.getLocationX());
wxMsg.setRepLocationY(wxMessage.getLocationY());
wxMsg.setRepScale(wxMessage.getScale());
wxMsg.setRepContent(wxMessage.getLabel());
}
wxMsg.setReadFlag(CommonConstants.NO);
LocalDateTime now = LocalDateTime.now();
wxMsg.setCreateTime(now);
wxMsgService.save(wxMsg);
// 推送websocket
String destination = WebSocketConstant.USER_DESTINATION_PREFIX + WebSocketConstant.WX_MSG + wxMsg.getWxUserId();
if (listWxAutoReply != null && !listWxAutoReply.isEmpty()) {
WxAutoReply wxAutoReply = listWxAutoReply.get(0);
// 记录回复消息
wxMsg = new WxMsg();
wxMsg.setWxUserId(wxUser.getId());
wxMsg.setNickName(wxUser.getNickName());
wxMsg.setHeadimgUrl(wxUser.getHeadimgUrl());
wxMsg.setCreateTime(now.plusSeconds(1));
wxMsg.setType(ConfigConstant.WX_MSG_TYPE_2);
wxMsg.setRepType(wxAutoReply.getRepType());
if (WxConsts.KefuMsgType.TEXT.equals(wxAutoReply.getRepType())) {// 文本
wxMsg.setRepContent(wxAutoReply.getRepContent());
wxMpXmlOutMessage = new TextBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).content(wxAutoReply.getRepContent()).build();
}
if (WxConsts.KefuMsgType.IMAGE.equals(wxAutoReply.getRepType())) {// 图片
wxMsg.setRepName(wxAutoReply.getRepName());
wxMsg.setRepUrl(wxAutoReply.getRepUrl());
wxMsg.setRepMediaId(wxAutoReply.getRepMediaId());
wxMpXmlOutMessage = new ImageBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).mediaId(wxAutoReply.getRepMediaId()).build();
}
if (WxConsts.KefuMsgType.VOICE.equals(wxAutoReply.getRepType())) {
wxMsg.setRepName(wxAutoReply.getRepName());
wxMsg.setRepUrl(wxAutoReply.getRepUrl());
wxMsg.setRepMediaId(wxAutoReply.getRepMediaId());
wxMpXmlOutMessage = new VoiceBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).mediaId(wxAutoReply.getRepMediaId()).build();
}
if (WxConsts.KefuMsgType.VIDEO.equals(wxAutoReply.getRepType())) {
wxMsg.setRepName(wxAutoReply.getRepName());
wxMsg.setRepDesc(wxAutoReply.getRepDesc());
wxMsg.setRepUrl(wxAutoReply.getRepUrl());
wxMsg.setRepMediaId(wxAutoReply.getRepMediaId());
wxMpXmlOutMessage = new VideoBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).mediaId(wxAutoReply.getRepMediaId()).title(wxAutoReply.getRepName()).description(wxAutoReply.getRepDesc()).build();
}
if (WxConsts.KefuMsgType.MUSIC.equals(wxAutoReply.getRepType())) {
wxMsg.setRepName(wxAutoReply.getRepName());
wxMsg.setRepDesc(wxAutoReply.getRepDesc());
wxMsg.setRepUrl(wxAutoReply.getRepUrl());
wxMsg.setRepHqUrl(wxAutoReply.getRepHqUrl());
wxMsg.setRepThumbMediaId(wxAutoReply.getRepThumbMediaId());
wxMsg.setRepThumbUrl(wxAutoReply.getRepThumbUrl());
wxMpXmlOutMessage = new MusicBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).thumbMediaId(wxAutoReply.getRepThumbMediaId()).title(wxAutoReply.getRepName()).description(wxAutoReply.getRepDesc()).musicUrl(wxAutoReply.getRepUrl()).hqMusicUrl(wxAutoReply.getRepHqUrl()).build();
}
if (WxConsts.KefuMsgType.NEWS.equals(wxAutoReply.getRepType())) {
List<WxMpXmlOutNewsMessage.Item> list = new ArrayList<>();
List<JSONObject> listJSONObject = wxAutoReply.getContent().getJSONArray("articles").toList(JSONObject.class);
WxMpXmlOutNewsMessage.Item t;
for (JSONObject jSONObject : listJSONObject) {
t = new WxMpXmlOutNewsMessage.Item();
t.setTitle(jSONObject.getStr("title"));
t.setDescription(jSONObject.getStr("digest"));
t.setPicUrl(jSONObject.getStr("thumbUrl"));
t.setUrl(jSONObject.getStr("url"));
list.add(t);
}
wxMsg.setRepName(wxAutoReply.getRepName());
wxMsg.setRepDesc(wxAutoReply.getRepDesc());
wxMsg.setRepUrl(wxAutoReply.getRepUrl());
wxMsg.setRepMediaId(wxAutoReply.getRepMediaId());
wxMsg.setContent(wxAutoReply.getContent());
wxMpXmlOutMessage = new NewsBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).articles(list).build();
}
wxMsgService.save(wxMsg);
}
return wxMpXmlOutMessage;
}
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) {
// 组装回复消息
if (!wxMessage.getMsgType().equals(XmlMsgType.EVENT)) {
WxMpXmlOutMessage rs;
// TODO 可以选择将消息保存到本地
WxUser wxUser = wxUserMapper.selectOne(Wrappers.<WxUser>lambdaQuery().eq(WxUser::getOpenId, wxMessage.getFromUser()));
if (WxConsts.KefuMsgType.TEXT.equals(wxMessage.getMsgType())) {// 1、先处理是否有文本关键字回复
// 先全匹配
List<WxAutoReply> listWxAutoReply = wxAutoReplyService.list(Wrappers.<WxAutoReply>query().lambda().eq(WxAutoReply::getType, ConfigConstant.WX_AUTO_REPLY_TYPE_3).eq(WxAutoReply::getRepMate, ConfigConstant.WX_REP_MATE_1).eq(WxAutoReply::getReqKey, wxMessage.getContent()));
if (listWxAutoReply != null && !listWxAutoReply.isEmpty()) {
rs = this.getWxMpXmlOutMessage(wxMessage, listWxAutoReply, wxUser, wxMsgService);
if (rs != null) {
return rs;
}
}
// 再半匹配
listWxAutoReply = wxAutoReplyService.list(Wrappers.<WxAutoReply>query().lambda().eq(WxAutoReply::getType, ConfigConstant.WX_AUTO_REPLY_TYPE_3).eq(WxAutoReply::getRepMate, ConfigConstant.WX_REP_MATE_2).like(WxAutoReply::getReqKey, wxMessage.getContent()));
if (listWxAutoReply != null && !listWxAutoReply.isEmpty()) {
rs = this.getWxMpXmlOutMessage(wxMessage, listWxAutoReply, wxUser, wxMsgService);
if (rs != null) {
return rs;
}
}
}
// 2、再处理消息回复
List<WxAutoReply> listWxAutoReply = wxAutoReplyService.list(Wrappers.<WxAutoReply>query().lambda().eq(WxAutoReply::getType, ConfigConstant.WX_AUTO_REPLY_TYPE_2).eq(WxAutoReply::getReqType, wxMessage.getMsgType()));
rs = this.getWxMpXmlOutMessage(wxMessage, listWxAutoReply, wxUser, wxMsgService);
return rs;
}
return null;
}
}

View File

@@ -1,24 +0,0 @@
package com.starry.admin.modules.weichat.handler;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author admin
*/
@Component
public class NullHandler extends AbstractHandler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) {
return null;
}
}

View File

@@ -1,24 +0,0 @@
package com.starry.admin.modules.weichat.handler;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author admin
*/
@Component
public class ScanHandler extends AbstractHandler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMpXmlMessage, Map<String, Object> map,
WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException {
// 扫码事件处理
return null;
}
}

View File

@@ -1,27 +0,0 @@
package com.starry.admin.modules.weichat.handler;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* 门店审核事件处理
*
* @author admin
*/
@Component
public class StoreCheckNotifyHandler extends AbstractHandler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) {
// TODO 处理门店审核事件
return null;
}
}

View File

@@ -1,84 +0,0 @@
package com.starry.admin.modules.weichat.handler;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.starry.admin.modules.weichat.constant.ConfigConstant;
import com.starry.admin.modules.weichat.entity.WxAutoReply;
import com.starry.admin.modules.weichat.entity.WxUser;
import com.starry.admin.modules.weichat.mapper.WxUserMapper;
import com.starry.admin.modules.weichat.service.WxAutoReplyService;
import com.starry.admin.modules.weichat.service.WxMsgService;
import com.starry.admin.modules.weichat.utils.LocalDateTimeUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
/**
* @author admin
*/
@Slf4j
@Component
@AllArgsConstructor
public class SubscribeHandler extends AbstractHandler {
private final WxAutoReplyService wxAutoReplyService;
private final WxUserMapper wxUserMapper;
private final WxMsgService wxMsgService;
public static void setWxUserValue(WxUser wxUser, WxMpUser userWxInfo) {
wxUser.setAppType(ConfigConstant.WX_APP_TYPE_2);
wxUser.setSubscribe(ConfigConstant.SUBSCRIBE_TYPE_YES);
wxUser.setSubscribeScene(userWxInfo.getSubscribeScene());
if (null != userWxInfo.getSubscribeTime()) {
wxUser.setSubscribeTime(LocalDateTimeUtils.timestamToDatetime(userWxInfo.getSubscribeTime() * 1000));
}
wxUser.setOpenId(userWxInfo.getOpenId());
wxUser.setLanguage(userWxInfo.getLanguage());
wxUser.setRemark(userWxInfo.getRemark());
wxUser.setUnionId(userWxInfo.getUnionId());
wxUser.setGroupId(JSONUtil.toJsonStr(userWxInfo.getGroupId()));
wxUser.setTagidList(userWxInfo.getTagIds());
wxUser.setQrSceneStr(userWxInfo.getQrSceneStr());
}
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService weixinService, WxSessionManager sessionManager) {
log.info("新关注用户 OPENID: " + wxMessage.getFromUser());
// 获取微信用户基本信息
try {
WxMpUser userWxInfo = weixinService.getUserService().userInfo(wxMessage.getFromUser(), null);
if (userWxInfo != null) {
// TODO 添加关注用户到本地数据库
WxUser wxUser = wxUserMapper.selectOne(Wrappers.<WxUser>lambdaQuery().eq(WxUser::getOpenId, userWxInfo.getOpenId()));
if (wxUser == null) {
// 第一次关注
wxUser = new WxUser();
wxUser.setSubscribeNum(1);
setWxUserValue(wxUser, userWxInfo);
// wxUser.setTenantId(wxApp.getTenantId());
wxUserMapper.insert(wxUser);
} else {
// 曾经关注过
wxUser.setSubscribeNum(wxUser.getSubscribeNum() + 1);
setWxUserValue(wxUser, userWxInfo);
// wxUser.setTenantId(wxApp.getTenantId());
wxUserMapper.updateById(wxUser);
}
// 发送关注消息
List<WxAutoReply> listWxAutoReply = wxAutoReplyService.list(Wrappers.<WxAutoReply>query().lambda().eq(WxAutoReply::getType, ConfigConstant.WX_AUTO_REPLY_TYPE_1));
return MsgHandler.getWxMpXmlOutMessage(wxMessage, listWxAutoReply, wxUser, wxMsgService);
}
} catch (Exception e) {
log.error("用户关注出错:" + e.getMessage());
}
return null;
}
}

View File

@@ -1,48 +0,0 @@
package com.starry.admin.modules.weichat.handler;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.starry.admin.modules.weichat.constant.ConfigConstant;
import com.starry.admin.modules.weichat.entity.WxUser;
import com.starry.admin.modules.weichat.mapper.WxUserMapper;
import com.starry.admin.modules.weichat.service.WxMsgService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.Map;
/**
* @author admin
*/
@Slf4j
@Component
@AllArgsConstructor
public class UnsubscribeHandler extends AbstractHandler {
private final WxMsgService wxMsgService;
private final WxUserMapper wxUserMapper;
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) {
String openId = wxMessage.getFromUser();
log.info("取消关注用户 OPENID: " + openId);
WxUser wxUser = wxUserMapper.selectOne(Wrappers.<WxUser>lambdaQuery()
.eq(WxUser::getOpenId, openId));
if (wxUser != null) {
wxUser.setSubscribe(ConfigConstant.SUBSCRIBE_TYPE_NO);
wxUser.setCancelSubscribeTime(LocalDateTime.now());
wxUserMapper.updateById(wxUser);
// 消息记录
MsgHandler.getWxMpXmlOutMessage(wxMessage, null, wxUser, wxMsgService);
}
return null;
}
}

View File

@@ -1,72 +0,0 @@
package com.starry.admin.modules.weichat.interceptor;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.starry.admin.modules.weichat.config.CommonConstants;
import com.starry.admin.modules.weichat.constant.ConfigConstant;
import com.starry.admin.modules.weichat.constant.MyReturnCode;
import com.starry.admin.modules.weichat.constant.WxMaConstants;
import com.starry.admin.modules.weichat.entity.ThirdSession;
import com.starry.admin.modules.weichat.utils.ThirdSessionHolder;
import com.starry.common.result.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* ThirdSession拦截器校验每个请求的ThirdSession
*
* @author admin
*/
@Slf4j
@Component
public class ThirdSessionInterceptor implements HandlerInterceptor {
@Resource
RedisTemplate<String, Object> redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 获取header中的thirdSession
String thirdSessionHeader = request.getHeader(ConfigConstant.HEADER_THIRDSESSION);
if (StrUtil.isNotBlank(thirdSessionHeader)) {
// 获取缓存中的ThirdSession
String key = WxMaConstants.THIRD_SESSION_BEGIN + ":" + thirdSessionHeader;
Object thirdSessionObj = redisTemplate.opsForValue().get(key);
if (thirdSessionObj == null) {
// session过期
R r = R.error(MyReturnCode.ERR_60001.getCode(), MyReturnCode.ERR_60001.getMsg());
this.writerPrint(response, r);
return Boolean.FALSE;
} else {
String thirdSessionStr = String.valueOf(thirdSessionObj);
ThirdSession thirdSession = JSONUtil.toBean(thirdSessionStr, ThirdSession.class);
// 设置thirdSession
ThirdSessionHolder.setThirdSession(thirdSession);
}
} else {
R r = R.error(MyReturnCode.ERR_60002.getCode(), MyReturnCode.ERR_60002.getMsg());
this.writerPrint(response, r);
return Boolean.FALSE;
}
return Boolean.TRUE;
}
private void writerPrint(HttpServletResponse response, R r) throws IOException {
// 返回超时错误码,触发小程序重新登录
response.setCharacterEncoding(CommonConstants.UTF8);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
PrintWriter writer = response.getWriter();
writer.print(JSONUtil.parseObj(r));
writer.close();
}
}

View File

@@ -0,0 +1,16 @@
package com.starry.admin.modules.weichat.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.starry.admin.modules.weichat.entity.PlayWxUserInfoEntity;
/**
* 微信用户Mapper接口
*
* @author admin
* @since 2024-04-07
*/
public interface PlayWxUserInfoMapper extends BaseMapper<PlayWxUserInfoEntity> {
}

View File

@@ -1,15 +0,0 @@
package com.starry.admin.modules.weichat.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.starry.admin.modules.weichat.entity.WxAutoReply;
/**
* 消息自动回复
*
* @author admin
* @since 2019-04-18 15:40:39
*/
public interface WxAutoReplyMapper extends BaseMapper<WxAutoReply> {
}

View File

@@ -1,14 +0,0 @@
package com.starry.admin.modules.weichat.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.starry.admin.modules.weichat.entity.WxMenu;
/**
* 自定义菜单
*
* @author admin
* @since 2019-03-27 16:52:10
*/
public interface WxMenuMapper extends BaseMapper<WxMenu> {
}

View File

@@ -1,27 +0,0 @@
package com.starry.admin.modules.weichat.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.modules.weichat.entity.WxMsg;
import com.starry.admin.modules.weichat.entity.WxMsgVO;
import org.apache.ibatis.annotations.Param;
/**
* 微信消息
*
* @author admin
* @since 2019-05-28 16:12:10
*/
public interface WxMsgMapper extends BaseMapper<WxMsg> {
/**
* 获取分组后的消息列表
*
* @param page
* @param wxMsgVO
* @return
*/
IPage listWxMsgMapGroup(Page<WxMsg> page, @Param("query") WxMsgVO wxMsgVO);
}

View File

@@ -1,14 +0,0 @@
package com.starry.admin.modules.weichat.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.starry.admin.modules.weichat.entity.WxUser;
/**
* 微信用户
*
* @author admin
* @since 2019-03-25 15:39:39
*/
public interface WxUserMapper extends BaseMapper<WxUser> {
}

View File

@@ -0,0 +1,152 @@
package com.starry.admin.modules.weichat.service;
import io.jsonwebtoken.Claims;
/**
* 通用常量信息
*
* @author ruoyi
*/
public class Constants
{
/**
* UTF-8 字符集
*/
public static final String UTF8 = "UTF-8";
/**
* GBK 字符集
*/
public static final String GBK = "GBK";
/**
* www主域
*/
public static final String WWW = "www.";
/**
* http请求
*/
public static final String HTTP = "http://";
/**
* https请求
*/
public static final String HTTPS = "https://";
/**
* 通用成功标识
*/
public static final String SUCCESS = "0";
/**
* 通用失败标识
*/
public static final String FAIL = "1";
/**
* 登录成功
*/
public static final String LOGIN_SUCCESS = "Success";
/**
* 注销
*/
public static final String LOGOUT = "Logout";
public static final String CHANGE_PHONE = "CHANGE_PHONE";
/**
* 注册
*/
public static final String REGISTER = "Register";
/**
* 登录失败
*/
public static final String LOGIN_FAIL = "Error";
/**
* 验证码有效期(分钟)
*/
public static final Integer CAPTCHA_EXPIRATION = 2;
/**
* 令牌
*/
public static final String TOKEN = "token";
/**
* 令牌前缀
*/
public static final String TOKEN_PREFIX = "Bearer ";
public static final String MINI_USER_LOGIN_TOKEN = "usertoken";
public static final String MINI_COSER_LOGIN_TOKEN = "cosertoken";
/**
* 令牌前缀
*/
public static final String LOGIN_USER_KEY = "login_user_key";
public static final String LOGIN_USER_KEY_MINI = "login_user_key_mini";
public static final String LOGIN_USER_KEY_COSER = "login_user_key_coser";
/**
* 用户ID
*/
public static final String JWT_USERID = "userid";
/**
* 用户名称
*/
public static final String JWT_USERNAME = Claims.SUBJECT;
/**
* 用户头像
*/
public static final String JWT_AVATAR = "avatar";
/**
* 创建时间
*/
public static final String JWT_CREATED = "created";
/**
* 用户权限
*/
public static final String JWT_AUTHORITIES = "authorities";
/**
* 资源映射路径 前缀
*/
public static final String RESOURCE_PREFIX = "/profile";
public static final String MINI_USER_DE_AVATAR = "https://live-cloud-cvoon.oss-cn-hangzhou.aliyuncs.com/cdn/img/1881712023451_.pic.jpg";
public static final String MINI_COSER_DE_AVATAR = "https://live-cloud-cvoon.oss-cn-hangzhou.aliyuncs.com/cdn/img/1891712023452_.pic.jpg";
/**
* RMI 远程方法调用
*/
public static final String LOOKUP_RMI = "rmi:";
/**
* LDAP 远程方法调用
*/
public static final String LOOKUP_LDAP = "ldap:";
/**
* LDAPS 远程方法调用
*/
public static final String LOOKUP_LDAPS = "ldaps:";
/**
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
*/
public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" };
/**
* 定时任务违规的字符
*/
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config" };
}

View File

@@ -1,14 +0,0 @@
package com.starry.admin.modules.weichat.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.modules.weichat.entity.WxAutoReply;
/**
* 消息自动回复
*
* @author admin
* @since 2019-04-18 15:40:39
*/
public interface WxAutoReplyService extends IService<WxAutoReply> {
}

View File

@@ -1,28 +0,0 @@
package com.starry.admin.modules.weichat.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.modules.weichat.entity.WxMenu;
import me.chanjar.weixin.common.error.WxErrorException;
/**
* 自定义菜单
*
* @author admin
* @since 2019-03-27 16:52:10
*/
public interface WxMenuService extends IService<WxMenu> {
/***
* 获取WxApp下的菜单
* @return
*/
String getWxMenuButton();
/**
* 保存并发布菜单
*
* @param
*/
void saveAndRelease(String strWxMenu) throws WxErrorException;
}

View File

@@ -1,109 +0,0 @@
package com.starry.admin.modules.weichat.service;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.starry.admin.common.exception.CustomException;
import com.starry.admin.modules.platform.entity.SysTenantEntity;
import com.starry.admin.modules.platform.service.ISysTenantService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.config.impl.WxMpMapConfigImpl;
import org.springframework.stereotype.Service;
import java.util.Objects;
/**
* @Author: huchuansai
* @Date: 2024/3/27 10:27 PM
* @Description:
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class WxMpApi {
private final WxMpService mpService;
private final ISysTenantService sysTenantService;
public String getAccessToken(String appId, boolean forceUpdate) {
SysTenantEntity tenant = sysTenantService.getOne(Wrappers.lambdaQuery(SysTenantEntity.class).eq(SysTenantEntity::getAppId, appId));
if (Objects.isNull(tenant)) {
throw new CustomException("该APPID未查询到相关租户");
}
if (StringUtils.isEmpty(tenant.getSecret())) {
throw new CustomException("公众号秘钥不能为空");
}
return getAccessToken(appId, tenant.getSecret(), forceUpdate);
}
public String getAccessToken(String appId, String secret, boolean forceUpdate) {
WxMpService wxMpService = this.proxyWxMpService(appId, secret);
try {
return wxMpService.getAccessToken(forceUpdate);
} catch (WxErrorException e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
private WxMpService proxyWxMpService(String appId, String secret) {
WxMpMapConfigImpl config = new WxMpMapConfigImpl();
config.setAppId(appId);
config.setSecret(secret);
config.setUseStableAccessToken(true);
mpService.addConfigStorage(appId, config);
return mpService.switchoverTo(appId);
}
public String getOauth2Url(String url) {
if (StringUtils.isEmpty(url)) {
throw new RuntimeException("oauth url不能为空");
}
return mpService.getOAuth2Service().buildAuthorizationUrl(url, "snsapi_userinfo", "mystate");
}
// public String oauth2Callback(String code, String appId) {
// if (StringUtils.isEmpty(code)) {
// throw new RuntimeException("授权码不能为空");
// }
// synchronized (code.intern()) {
// String openId;
// String key = "mpOauth2code:" + code;
// Object cacheObject = redisCache.getCacheObject(key);
// WxOAuth2UserInfo userInfo = null;
// if (Objects.nonNull(cacheObject)) {
// openId = cacheObject.toString();
// } else {
// // 通过code换取accessToken
// WxOAuth2AccessToken accessTokenResult;
// try {
// accessTokenResult = mpService.getOAuth2Service().getAccessToken(code);
// userInfo = mpService.getOAuth2Service().getUserInfo(accessTokenResult, null);
// } catch (WxErrorException e) {
// throw new RuntimeException(e);
// }
// openId = accessTokenResult.getOpenId();
// }
// // 返回token 和 userInfo
// SysUser user = userMapper.selectOne(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getOpenid, openId).eq(SysUser::getDelFlag, "0"));
// if (Objects.isNull(user)) {
// user = new SysUser();
// user.setOpenid(openId);
// user.setUserName("mp" + RandomUtil.randomString(6));
// user.setNickName(userInfo.getNickname());
// user.setAvartar(userInfo.getHeadImgUrl());
// user.setAvartar(userInfo.getSex());
// user.setPassword(SecurityUtils.encryptPassword("123456"));
// userMapper.insert(user);
// }
// // 制作token
// LoginUser loginUser = new LoginUser(user.getUserId(), user.getDeptId(), user, new LinkedHashSet<>());
// String token = tokenService.createToken(loginUser);
// redisCache.setCacheObject(key, openId, 1, TimeUnit.HOURS);
// return Constants.TOKEN_PREFIX + token;
// }
//}
}

View File

@@ -1,25 +0,0 @@
package com.starry.admin.modules.weichat.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.modules.weichat.entity.WxMsg;
import com.starry.admin.modules.weichat.entity.WxMsgVO;
/**
* 微信消息
*
* @author admin
* @since 2019-05-28 16:12:10
*/
public interface WxMsgService extends IService<WxMsg> {
/**
* 获取分组后的消息列表
*
* @param page
* @param wxMsgVO
* @return
*/
IPage<WxMsg> listWxMsgMapGroup(Page<WxMsg> page, WxMsgVO wxMsgVO);
}

View File

@@ -0,0 +1,143 @@
package com.starry.admin.modules.weichat.service;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.starry.admin.common.exception.CustomException;
import com.starry.admin.modules.clear.module.entity.PlayClerkUserInfoEntity;
import com.starry.admin.modules.clear.service.IPlayClerkUserInfoService;
import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity;
import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService;
import com.starry.common.utils.ConvertUtil;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Slf4j
@Service
public class WxOauthService {
@Resource
private WxMpService wxMpService;
@Resource
private IPlayCustomUserInfoService customUserInfoService;
@Resource
private IPlayClerkUserInfoService clerkUserInfoService;
@Resource
private WxTokenService tokenService;
public String clarkUserLogin(String code) {
WxOAuth2AccessToken token = getWxOAuth2AccessToken(code);
String openId = getOpenId(token);
WxOAuth2UserInfo userInfo = new WxOAuth2UserInfo();
PlayClerkUserInfoEntity item = clerkUserInfoService.selectByOpenid(openId);
if (item == null) {
PlayClerkUserInfoEntity entity = ConvertUtil.entityToVo(userInfo, PlayClerkUserInfoEntity.class);
entity.setAvatar(userInfo.getHeadImgUrl());
entity.setId(IdUtil.fastSimpleUUID());
clerkUserInfoService.create(entity);
return entity.getId();
} else {
item.setAvatar(userInfo.getHeadImgUrl());
clerkUserInfoService.update(item);
return item.getId();
}
}
public void clarkUserLogout(PlayClerkUserInfoEntity entity) {
entity.setToken("empty");
clerkUserInfoService.update(entity);
}
public void customUserLogout(PlayCustomUserInfoEntity entity) {
entity.setToken("empty");
customUserInfoService.update(entity);
}
public String customUserLogin(String code) {
WxOAuth2AccessToken token = getWxOAuth2AccessToken(code);
String openId = getOpenId(token);
WxOAuth2UserInfo userInfo = getWxOAuth2UserInfo(token);
PlayCustomUserInfoEntity entity = new PlayCustomUserInfoEntity();
ConvertUtil.entityToVo(userInfo, PlayClerkUserInfoEntity.class);
entity.setAvatar(userInfo.getHeadImgUrl());
PlayCustomUserInfoEntity item = customUserInfoService.selectByOpenid(openId);
entity.setId(item != null ? item.getId() : IdUtil.fastSimpleUUID());
customUserInfoService.saveOrUpdate(entity);
return entity.getId();
}
/**
* 获取微信授权Token
*
* @param code code
* @return WxOAuth2AccessToken
* @author admin
* @since 2024/4/8 14:47
**/
public WxOAuth2AccessToken getWxOAuth2AccessToken(String code) {
if (StrUtil.isBlankIfStr(code)) {
throw new CustomException("不能为空");
}
synchronized (code.intern()) {
try {
return wxMpService.getOAuth2Service().getAccessToken(code);
} catch (WxErrorException e) {
throw new RuntimeException(e);
}
}
}
/**
* 获取微信用户ID
*
* @param token code
* @return WxOAuth2AccessToken
* @author admin
* @since 2024/4/8 14:47
**/
public String getOpenId(WxOAuth2AccessToken token) {
if (token == null) {
throw new CustomException("获取微信授权异常WxOAuth2AccessToken不能为空");
}
String openId = token.getOpenId();
if (StrUtil.isBlankIfStr(openId)) {
throw new CustomException("获取微信授权异常openId不能为空");
}
return openId;
}
/**
* 获取微信用户ID
*
* @param token WxOAuth2AccessToken
* @return WxOAuth2UserInfo
* @author admin
* @since 2024/4/8 14:47
**/
public WxOAuth2UserInfo getWxOAuth2UserInfo(WxOAuth2AccessToken token) {
if (token == null) {
throw new CustomException("获取微信授权异常WxOAuth2AccessToken不能为空");
}
try {
return wxMpService.getOAuth2Service().getUserInfo(token, null);
} catch (WxErrorException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,226 @@
package com.starry.admin.modules.weichat.service;
import cn.hutool.core.date.DateUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* token验证处理
*
* @author ruoyi
*/
@Slf4j
@Service
public class WxTokenService {
// 令牌自定义标识
@Value("${token.header}")
private String header;
// 令牌秘钥
@Value("${token.secret}")
private String secret;
// 令牌有效期默认30分钟
@Value("${token.expireTime}")
private int expireTime;
protected static final long MILLIS_SECOND = 1000;
protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
//
// @Autowired
// private RedisCache redisCache;
// /**
// * 获取用户身份信息
// *
// * @return 用户信息
// */
// public LoginUser getLoginUser(HttpServletRequest request) {
// // 获取请求携带的令牌
// String token = getToken(request);
// if (StringUtils.isNotEmpty(token)) {
// try {
// Claims claims = parseToken(token);
// // 解析对应的权限以及用户信息
// String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
// String userKey = getTokenKey(uuid);
// LoginUser user = redisCache.getCacheObject(userKey);
// return user;
// } catch (Exception e) {
// }
// }
// return null;
// }
//
//
// /**
// * 设置用户身份信息
// */
// public void setLoginUser(LoginUser loginUser) {
// if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) {
// refreshToken(loginUser);
// }
// }
//
// /**
// * 删除用户身份信息
// */
// public void delLoginUser(String token) {
// if (StringUtils.isNotEmpty(token)) {
// String userKey = getTokenKey(token);
// redisCache.deleteObject(userKey);
// }
// }
//
// /**
// * 创建令牌
// *
// * @param loginUser 用户信息
// * @return 令牌
// */
// public String createToken(LoginUser loginUser) {
// String token = IdUtils.fastUUID();
// loginUser.setToken(token);
// setUserAgent(loginUser);
// refreshToken(loginUser);
//
// Map<String, Object> claims = new HashMap<>();
// claims.put(Constants.LOGIN_USER_KEY, token);
// return createToken(claims);
// }
// 小程序端-委托人
public String createMiniUserToken(String miniUserId) {
if (Objects.isNull(miniUserId)) {
throw new RuntimeException("用户id不能为空");
}
Map<String, Object> claims = new HashMap<>();
claims.put(Constants.LOGIN_USER_KEY_MINI, miniUserId);
return Jwts.builder().setClaims(claims).setExpiration(DateUtil.offsetMinute(new Date(), expireTime)).signWith(SignatureAlgorithm.HS512, secret).compact();
}
// 小程序端-委托人
public String getMiniUserIdByToken(String token) {
if (StringUtils.isEmpty(token)) {
throw new RuntimeException("token不能为空");
}
Claims claims = parseToken(token);
return claims.get(Constants.LOGIN_USER_KEY_MINI).toString();
}
//
// // 小程序端-coser
// public String createMiniCoserToken(Long miniCoserId) {
// if (Objects.isNull(miniCoserId)) {
// throw new RuntimeException("用户id不能为空");
// }
// Map<String, Object> claims = new HashMap<>();
// claims.put(Constants.LOGIN_USER_KEY_COSER, miniCoserId);
// return Jwts.builder().setClaims(claims).setExpiration(DateUtil.offsetMinute(new Date(), expireTime)).signWith(SignatureAlgorithm.HS512, secret).compact();
// }
//
// // 小程序端-coser
// public Long getMiniCoserIdByToken(String token) {
// if (StringUtils.isEmpty(token)) {
// throw new RuntimeException("token不能为空");
// }
// Claims claims = parseToken(token);
// String userId = claims.get(Constants.LOGIN_USER_KEY_COSER).toString();
// return Long.parseLong(userId);
// }
//
//
// /**
// * 验证令牌有效期相差不足20分钟自动刷新缓存
// *
// * @param loginUser
// * @return 令牌
// */
// public void verifyToken(LoginUser loginUser) {
// long expireTime = loginUser.getExpireTime();
// long currentTime = System.currentTimeMillis();
// if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
// refreshToken(loginUser);
// }
// }
//
// /**
// * 刷新令牌有效期
// *
// * @param loginUser 登录信息
// */
// public void refreshToken(LoginUser loginUser) {
// loginUser.setLoginTime(System.currentTimeMillis());
// loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
// // 根据uuid将loginUser缓存
// String userKey = getTokenKey(loginUser.getToken());
// redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
// }
//
//
// /**
// * 设置用户代理信息
// *
// * @param loginUser 登录信息
// */
// public void setUserAgent(LoginUser loginUser) {
// UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
// String ip = IpUtils.getIpAddr();
// loginUser.setIpaddr(ip);
// loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
// loginUser.setBrowser(userAgent.getBrowser().getName());
// loginUser.setOs(userAgent.getOperatingSystem().getName());
// }
//
// /**
// * 从数据声明生成令牌
// *
// * @param claims 数据声明
// * @return 令牌
// */
// private String createToken(Map<String, Object> claims) {
// String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact();
// return token;
// }
//
/**
* 从令牌中获取数据声明
*
* @param token 令牌
* @return 数据声明
*/
private Claims parseToken(String token) {
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
}
//
// /**
// * 获取请求token
// *
// * @param request
// * @return token
// */
// private String getToken(HttpServletRequest request) {
// String token = request.getHeader(header);
// if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) {
// token = token.replace(Constants.TOKEN_PREFIX, "");
// }
// return token;
// }
//
// private String getTokenKey(String uuid) {
// return CacheConstants.LOGIN_TOKEN_KEY + uuid;
// }
}

View File

@@ -1,46 +0,0 @@
package com.starry.admin.modules.weichat.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.modules.weichat.entity.WxUser;
import me.chanjar.weixin.common.error.WxErrorException;
/**
* 微信用户
*
* @author admin
* @since 2019-03-25 15:39:39
*/
public interface WxUserService extends IService<WxUser> {
/**
* 同步微信用户
*/
void synchroWxUser() throws WxErrorException;
/**
* 修改用户备注
*
* @param entity
* @return
*/
boolean updateRemark(WxUser entity) throws WxErrorException;
/**
* 认识标签
*
* @param taggingType
* @param tagId
* @param openIds
* @throws WxErrorException
*/
void tagging(String taggingType, Long tagId, String[] openIds) throws WxErrorException;
/**
* 根据openId获取用户
*
* @param openId
* @return
*/
WxUser getByOpenId(String openId);
}

View File

@@ -1,18 +0,0 @@
package com.starry.admin.modules.weichat.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.starry.admin.modules.weichat.entity.WxAutoReply;
import com.starry.admin.modules.weichat.mapper.WxAutoReplyMapper;
import com.starry.admin.modules.weichat.service.WxAutoReplyService;
import org.springframework.stereotype.Service;
/**
* 消息自动回复
*
* @author admin
* @since 2019-04-18 15:40:39
*/
@Service
public class WxAutoReplyServiceImpl extends ServiceImpl<WxAutoReplyMapper, WxAutoReply> implements WxAutoReplyService {
}

View File

@@ -1,163 +0,0 @@
package com.starry.admin.modules.weichat.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.starry.admin.modules.weichat.config.CommonConstants;
import com.starry.admin.modules.weichat.entity.Menu;
import com.starry.admin.modules.weichat.entity.MenuButton;
import com.starry.admin.modules.weichat.entity.WxMenu;
import com.starry.admin.modules.weichat.mapper.WxMenuMapper;
import com.starry.admin.modules.weichat.service.WxMenuService;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
/**
* 自定义菜单
*
* @author admin
* @since 2019-03-27 16:52:10
*/
@Service
@AllArgsConstructor
public class WxMenuServiceImpl extends ServiceImpl<WxMenuMapper, WxMenu> implements WxMenuService {
private final WxMpService wxService;
/***
* 获取WxApp下的菜单树结构
* @return
*/
@Override
public String getWxMenuButton() {
// 查出一级菜单
List<WxMenu> listWxMenu = baseMapper.selectList(Wrappers
.<WxMenu>query().lambda()
.eq(WxMenu::getParentId, CommonConstants.PARENT_ID).orderByAsc(WxMenu::getSort));
Menu menu = new Menu();
List<MenuButton> listMenuButton = new ArrayList<>();
MenuButton menuButton;
List<MenuButton> subButtons;
MenuButton subButton;
if (listWxMenu != null && !listWxMenu.isEmpty()) {
for (WxMenu wxMenu : listWxMenu) {
menuButton = new MenuButton();
menuButton.setName(wxMenu.getName());
String type = wxMenu.getType();
if (StringUtils.isNotBlank(type)) {// 无二级菜单
menuButton.setType(type);
setButtonValue(menuButton, wxMenu);
} else {// 有二级菜单
// 查出二级菜单
List<WxMenu> listWxMenu1 = baseMapper.selectList(Wrappers
.<WxMenu>query().lambda()
.eq(WxMenu::getParentId, wxMenu.getId()).orderByAsc(WxMenu::getSort));
subButtons = new ArrayList<>();
for (WxMenu wxMenu1 : listWxMenu1) {
subButton = new MenuButton();
String type1 = wxMenu1.getType();
subButton.setName(wxMenu1.getName());
subButton.setType(type1);
setButtonValue(subButton, wxMenu1);
subButtons.add(subButton);
}
menuButton.setSub_button(subButtons);
}
listMenuButton.add(menuButton);
}
}
menu.setButton(listMenuButton);
return menu.toString();
}
void setButtonValue(MenuButton menuButton, WxMenu wxMenu) {
menuButton.setKey(wxMenu.getId());
menuButton.setUrl(wxMenu.getUrl());
menuButton.setContent(wxMenu.getContent());
menuButton.setRepContent(wxMenu.getRepContent());
menuButton.setMedia_id(wxMenu.getRepMediaId());
menuButton.setRepType(wxMenu.getRepType());
menuButton.setRepName(wxMenu.getRepName());
menuButton.setAppid(wxMenu.getMaAppId());
menuButton.setPagepath(wxMenu.getMaPagePath());
menuButton.setUrl(wxMenu.getUrl());
menuButton.setRepUrl(wxMenu.getRepUrl());
menuButton.setRepHqUrl(wxMenu.getRepHqUrl());
menuButton.setRepDesc(wxMenu.getRepDesc());
menuButton.setRepThumbMediaId(wxMenu.getRepThumbMediaId());
menuButton.setRepThumbUrl(wxMenu.getRepThumbUrl());
}
/**
* 保存并发布菜单
*
* @param
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void saveAndRelease(String strWxMenu) throws WxErrorException {
Menu menu = Menu.fromJson(strWxMenu);
List<MenuButton> buttons = menu.getButton();
// 先删除
baseMapper.delete(Wrappers
.<WxMenu>query().lambda());
WxMenu wxMenu = null;
WxMenu wxMenu1 = null;
int sort1 = 1;
int sort2 = 1;
// 入库
for (MenuButton menuButton : buttons) {
wxMenu = new WxMenu();
setWxMenuValue(wxMenu, menuButton);
wxMenu.setSort(sort1);
wxMenu.setParentId(CommonConstants.PARENT_ID);
baseMapper.insert(wxMenu);
menuButton.setKey(wxMenu.getId());
sort1++;
for (MenuButton menuButton1 : menuButton.getSub_button()) {
wxMenu1 = new WxMenu();
setWxMenuValue(wxMenu1, menuButton1);
wxMenu1.setSort(sort2);
wxMenu1.setParentId(wxMenu.getId());
baseMapper.insert(wxMenu1);
menuButton1.setKey(wxMenu1.getId());
sort2++;
}
}
// 创建菜单
wxService.getMenuService().menuCreate(menu.toString());
}
void setWxMenuValue(WxMenu wxMenu, MenuButton menuButton) {
wxMenu.setId(menuButton.getKey());
wxMenu.setType(menuButton.getType());
wxMenu.setName(menuButton.getName());
wxMenu.setUrl(menuButton.getUrl());
wxMenu.setRepMediaId(menuButton.getMedia_id());
wxMenu.setRepType(menuButton.getRepType());
wxMenu.setRepName(menuButton.getRepName());
wxMenu.setMaAppId(menuButton.getAppid());
wxMenu.setMaPagePath(menuButton.getPagepath());
wxMenu.setRepContent(menuButton.getRepContent());
wxMenu.setContent(menuButton.getContent());
wxMenu.setRepUrl(menuButton.getRepUrl());
wxMenu.setRepHqUrl(menuButton.getRepHqUrl());
wxMenu.setRepDesc(menuButton.getRepDesc());
wxMenu.setRepThumbMediaId(menuButton.getRepThumbMediaId());
wxMenu.setRepThumbUrl(menuButton.getRepThumbUrl());
menuButton.setRepUrl(null);
menuButton.setRepDesc(null);
menuButton.setRepHqUrl(null);
menuButton.setContent(null);
menuButton.setRepContent(null);
menuButton.setRepType(null);
menuButton.setRepName(null);
menuButton.setRepThumbMediaId(null);
menuButton.setRepThumbUrl(null);
}
}

View File

@@ -1,37 +0,0 @@
package com.starry.admin.modules.weichat.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.starry.admin.modules.weichat.entity.WxMsg;
import com.starry.admin.modules.weichat.entity.WxMsgVO;
import com.starry.admin.modules.weichat.mapper.WxMsgMapper;
import com.starry.admin.modules.weichat.service.WxMsgService;
import org.springframework.stereotype.Service;
/**
* 微信消息
*
* @author admin
* @since 2019-05-28 16:12:10
*/
@Service
public class WxMsgServiceImpl extends ServiceImpl<WxMsgMapper, WxMsg> implements WxMsgService {
@Override
public IPage listWxMsgMapGroup(Page<WxMsg> page, WxMsgVO vo) {
// LambdaQueryWrapper<WxMsg> queryWrapper = new LambdaQueryWrapper<>();
// if (StrUtil.isBlankIfStr(vo.getType())) {
// queryWrapper.eq(WxMsg::getType, vo.getType());
// }
// if (StrUtil.isBlankIfStr(vo.getReadFlag())) {
// queryWrapper.eq(WxMsg::getReadFlag, vo.getReadFlag());
// }
// if (StrUtil.isBlankIfStr(vo.getRepType())) {
// queryWrapper.eq(WxMsg::getRepType, vo.getRepType());
// }
return baseMapper.listWxMsgMapGroup(page, vo);
}
}

View File

@@ -1,174 +0,0 @@
package com.starry.admin.modules.weichat.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.starry.admin.modules.weichat.constant.ConfigConstant;
import com.starry.admin.modules.weichat.entity.WxUser;
import com.starry.admin.modules.weichat.handler.SubscribeHandler;
import com.starry.admin.modules.weichat.mapper.WxUserMapper;
import com.starry.admin.modules.weichat.service.WxUserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxMpUserService;
import me.chanjar.weixin.mp.api.WxMpUserTagService;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 微信用户
*
* @author admin
* @since 2019-03-25 15:39:39
*/
@Slf4j
@Service
@AllArgsConstructor
public class WxUserServiceImpl extends ServiceImpl<WxUserMapper, WxUser> implements WxUserService {
private final WxMpService wxService;
private final RedisTemplate redisTemplate;
@Override
@Transactional(rollbackFor = Exception.class)
public boolean updateRemark(WxUser entity) throws WxErrorException {
String id = entity.getId();
String remark = entity.getRemark();
String openId = entity.getOpenId();
entity = new WxUser();
entity.setId(id);
entity.setRemark(remark);
super.updateById(entity);
WxMpUserService wxMpUserService = wxService.getUserService();
wxMpUserService.userUpdateRemark(openId, remark);
return true;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void tagging(String taggingType, Long tagId, String[] openIds) throws WxErrorException {
WxMpUserTagService wxMpUserTagService = wxService.getUserTagService();
WxUser wxUser;
if ("tagging".equals(taggingType)) {
for (String openId : openIds) {
wxUser = baseMapper.selectOne(Wrappers.<WxUser>lambdaQuery()
.eq(WxUser::getOpenId, openId));
Long[] tagidList = wxUser.getTagidList();
List<Long> list = Arrays.asList(tagidList);
list = new ArrayList<>(list);
if (!list.contains(tagId)) {
list.add(tagId);
tagidList = list.toArray(new Long[list.size()]);
wxUser.setTagidList(tagidList);
this.updateById(wxUser);
}
}
wxMpUserTagService.batchTagging(tagId, openIds);
}
if ("unTagging".equals(taggingType)) {
for (String openId : openIds) {
wxUser = baseMapper.selectOne(Wrappers.<WxUser>lambdaQuery()
.eq(WxUser::getOpenId, openId));
Long[] tagidList = wxUser.getTagidList();
List<Long> list = Arrays.asList(tagidList);
list = new ArrayList<>(list);
if (list.contains(tagId)) {
list.remove(tagId);
tagidList = list.toArray(new Long[list.size()]);
wxUser.setTagidList(tagidList);
this.updateById(wxUser);
}
}
wxMpUserTagService.batchUntagging(tagId, openIds);
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void synchroWxUser() throws WxErrorException {
// 先将已关注的用户取关
WxUser wxUser = new WxUser();
wxUser.setSubscribe(ConfigConstant.SUBSCRIBE_TYPE_NO);
this.baseMapper.update(wxUser, Wrappers.<WxUser>lambdaQuery()
.eq(WxUser::getSubscribe, ConfigConstant.SUBSCRIBE_TYPE_YES));
WxMpUserService wxMpUserService = wxService.getUserService();
this.recursionGet(wxMpUserService, null);
}
/**
* 递归获取
*
* @param nextOpenid
*/
void recursionGet(WxMpUserService wxMpUserService, String nextOpenid) throws WxErrorException {
WxMpUserList userList = wxMpUserService.userList(nextOpenid);
List<WxUser> listWxUser = new ArrayList<>();
List<WxMpUser> listWxMpUser = getWxMpUserList(wxMpUserService, userList.getOpenids());
listWxMpUser.forEach(wxMpUser -> {
WxUser wxUser = baseMapper.selectOne(Wrappers.<WxUser>lambdaQuery()
.eq(WxUser::getOpenId, wxMpUser.getOpenId()));
if (wxUser == null) {// 用户未存在
wxUser = new WxUser();
wxUser.setSubscribeNum(1);
}
SubscribeHandler.setWxUserValue(wxUser, wxMpUser);
listWxUser.add(wxUser);
});
this.saveOrUpdateBatch(listWxUser);
if (userList.getCount() >= 10000) {
this.recursionGet(wxMpUserService, userList.getNextOpenid());
}
}
/**
* 分批次获取微信粉丝信息 每批100条
*
* @param wxMpUserService
* @param openidsList
* @return
* @throws WxErrorException
* @author
*/
private List<WxMpUser> getWxMpUserList(WxMpUserService wxMpUserService, List<String> openidsList) throws WxErrorException {
// 粉丝openid数量
int count = openidsList.size();
if (count <= 0) {
return new ArrayList<>();
}
List<WxMpUser> list = new ArrayList<>();
List<WxMpUser> followersInfoList;
int a = count % 100 > 0 ? count / 100 + 1 : count / 100;
for (int i = 0; i < a; i++) {
if (i + 1 < a) {
log.debug("i:{},from:{},to:{}", i, i * 100, (i + 1) * 100);
followersInfoList = wxMpUserService.userInfoList(openidsList.subList(i * 100, ((i + 1) * 100)));
if (null != followersInfoList && !followersInfoList.isEmpty()) {
list.addAll(followersInfoList);
}
} else {
log.debug("i:{},from:{},to:{}", i, i * 100, count - i * 100);
followersInfoList = wxMpUserService.userInfoList(openidsList.subList(i * 100, count));
if (null != followersInfoList && !followersInfoList.isEmpty()) {
list.addAll(followersInfoList);
}
}
}
log.debug("本批次获取微信粉丝数:{}", list.size());
return list;
}
@Override
public WxUser getByOpenId(String openId) {
return this.baseMapper.selectOne(Wrappers.<WxUser>lambdaQuery()
.eq(WxUser::getOpenId, openId));
}
}

View File

@@ -1,67 +0,0 @@
package com.starry.admin.modules.weichat.utils;
import cn.hutool.core.lang.UUID;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
/**
* file工具
*
* @author admin
*/
public class FileUtils {
/**
* 将MultipartFile转为File
*
* @param mulFile
* @return
*/
public static File multipartFileToFile(MultipartFile mulFile) throws IOException {
InputStream ins = mulFile.getInputStream();
String fileName = mulFile.getOriginalFilename();
String prefix = getFileNameNoEx(fileName) + UUID.fastUUID();
String suffix = "." + getExtensionName(fileName);
File toFile = File.createTempFile(prefix, suffix);
OutputStream os = Files.newOutputStream(toFile.toPath());
int bytesRead;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
return toFile;
}
/**
* 获取文件扩展名
*/
public static String getExtensionName(String filename) {
if ((filename != null) && (!filename.isEmpty())) {
int dot = filename.lastIndexOf('.');
if ((dot > -1) && (dot < (filename.length() - 1))) {
return filename.substring(dot + 1);
}
}
return filename;
}
/**
* 获取不带扩展名的文件名
*/
public static String getFileNameNoEx(String filename) {
if ((filename != null) && (!filename.isEmpty())) {
int dot = filename.lastIndexOf('.');
if (dot > -1) {
return filename.substring(0, dot);
}
}
return filename;
}
}

View File

@@ -1,16 +0,0 @@
package com.starry.admin.modules.weichat.utils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
/**
* @author admin
*/
public class JsonUtils {
public static String toJson(Object obj) {
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.create();
return gson.toJson(obj);
}
}

View File

@@ -1,93 +0,0 @@
package com.starry.admin.modules.weichat.utils;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
/**
* LocalDateTime时间工具
*
* @author admin
*/
public class LocalDateTimeUtils {
public static final String YYYY = "yyyy";
public static final String YYYYMM = "yyyyMM";
public static final String YYYYMMDD = "yyyyMMdd";
public static final String YYYYMMDDHH = "yyyyMMddHH";
public static final String YYYYMMDDHHMM = "yyyyMMddHHmm";
public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
public static final String YYYY_MM = "yyyy-MM";
public static final String YYYY_MM_DD = "yyyy-MM-dd";
public static final String YYYY_MM_DD_HH = "yyyy-MM-dd HH";
public static final String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
private static final String BASE_TIME_FORMAT = "[yyyyMMddHHmmss][yyyyMMddHHmm][yyyyMMddHH][yyyyMMdd][yyyyMM][yyyy][[-][/][.]MM][[-][/][.]dd][ ][HH][[:][.]mm][[:][.]ss][[:][.]SSS]";
/**
* 【推荐】解析常用时间字符串,支持,并不局限于以下形式:
* [yyyy][yyyy-MM][yyyy-MM-dd][yyyy-MM-dd HH][yyyy-MM-dd HH:mm][yyyy-MM-dd HH:mm:ss][yyyy-MM-dd HH:mm:ss:SSS]
* [yyyy][yyyy/MM][yyyy/MM/dd][yyyy/MM/dd HH][yyyy/MM/dd HH:mm][yyyy/MM/dd HH:mm:ss][yyyy/MM/dd HH:mm:ss:SSS]
* [yyyy][yyyy.MM][yyyy.MM.dd][yyyy.MM.dd HH][yyyy.MM.dd HH.mm][yyyy.MM.dd HH.mm.ss][yyyy.MM.dd HH.mm.ss.SSS]
* [yyyy][yyyyMM][yyyyMMdd][yyyyMMddHH][yyyyMMddHHmm][yyyyMMddHHmmss]
* [MM-dd]
* 不支持yyyyMMddHHmmssSSS因为本身DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")就不支持这个形式
*
* @param timeString
* @return
*/
public static LocalDateTime parse(String timeString) {
return LocalDateTime.parse(timeString, getDateTimeFormatterByPattern(BASE_TIME_FORMAT));
}
/**
* 根据传进来的pattern返回LocalDateTime自动补齐
*
* @param timeString
* @param pattern
* @return
*/
public static LocalDateTime parseByPattern(String timeString, String pattern) {
return LocalDateTime.parse(timeString, getDateTimeFormatterByPattern(pattern));
}
private static DateTimeFormatter getDateTimeFormatterByPattern(String pattern) {
return new DateTimeFormatterBuilder()
.appendPattern(pattern)
.parseDefaulting(ChronoField.YEAR_OF_ERA, LocalDateTime.now().getYear())
.parseDefaulting(ChronoField.MONTH_OF_YEAR, LocalDateTime.now().getMonthValue())
.parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
.parseDefaulting(ChronoField.NANO_OF_SECOND, 0)
.toFormatter();
}
/**
* 将timestamp转为LocalDateTime
*
* @param timestamp
* @return
*/
public static LocalDateTime timestamToDatetime(long timestamp) {
Instant instant = Instant.ofEpochMilli(timestamp);
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
}
/**
* 将LocalDataTime转为timestamp
*
* @param ldt
* @return
*/
public static long datatimeToTimestamp(LocalDateTime ldt) {
ZoneId zone = ZoneId.systemDefault();
return ldt.atZone(zone).toInstant().toEpochMilli();
}
}

View File

@@ -1,46 +0,0 @@
package com.starry.admin.modules.weichat.utils;
import com.alibaba.ttl.TransmittableThreadLocal;
import com.starry.admin.modules.weichat.entity.ThirdSession;
import lombok.experimental.UtilityClass;
/**
* @author thirdSession工具类
*/
@UtilityClass
public class ThirdSessionHolder {
private final ThreadLocal<ThirdSession> THREAD_LOCAL_THIRD_SESSION = new TransmittableThreadLocal<>();
/**
* 获取TTL中的thirdSession
*
* @return
*/
public ThirdSession getThirdSession() {
return THREAD_LOCAL_THIRD_SESSION.get();
}
/**
* TTL 设置thirdSession
*
* @param thirdSession
*/
public void setThirdSession(ThirdSession thirdSession) {
THREAD_LOCAL_THIRD_SESSION.set(thirdSession);
}
public void clear() {
THREAD_LOCAL_THIRD_SESSION.remove();
}
/**
* 获取用户商城ID
*
* @return
*/
public String getWxUserId() {
return THREAD_LOCAL_THIRD_SESSION.get().getWxUserId();
}
}

View File

@@ -1,48 +0,0 @@
package com.starry.admin.modules.weichat.utils;
import cn.hutool.core.util.StrUtil;
import com.starry.admin.modules.platform.entity.SysTenantEntity;
import com.starry.admin.modules.platform.service.ISysTenantService;
import com.starry.admin.modules.weichat.entity.CustomWxMpProperties;
import com.starry.common.context.CustomSecurityContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
public class WxMpPropertiesUtils {
private static ISysTenantService tenantService;
public static CustomWxMpProperties getWeiChatProperties() {
CustomWxMpProperties properties = new CustomWxMpProperties();
String tenantId = CustomSecurityContextHolder.getTenantId();
if (StrUtil.isBlankIfStr(tenantId)) {
tenantId = "9999";
}
if (tenantService == null) {
properties.setAppid("9999");
properties.setAesKey("9999");
properties.setToken("9999");
properties.setSecret("9999");
return properties;
}
SysTenantEntity entity = tenantService.getById(tenantId);
if (entity != null) {
properties.setAppid(entity.getAppId());
properties.setAesKey(entity.getAesKey());
properties.setToken(entity.getToken());
properties.setSecret(entity.getSecret());
} else {
properties.setAppid("9999");
properties.setAesKey("9999");
properties.setToken("9999");
properties.setSecret("9999");
}
return properties;
}
@Autowired
public void setTenantService(ISysTenantService tenantService) {
WxMpPropertiesUtils.tenantService = tenantService;
}
}