From f5c77d68f54a3654006c560cad7b011010012299 Mon Sep 17 00:00:00 2001 From: ronger Date: Mon, 16 Mar 2020 21:17:58 +0800 Subject: [PATCH 01/19] =?UTF-8?q?:sparkles:=20=E5=BE=AE=E4=BF=A1=E5=85=AC?= =?UTF-8?q?=E4=BC=97=E5=8F=B7=E6=9C=8D=E5=8A=A1=E9=9B=86=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 + .../wx/mp/builder/AbstractBuilder.java | 17 ++ .../vertical/wx/mp/builder/ImageBuilder.java | 24 +++ .../vertical/wx/mp/builder/TextBuilder.java | 22 ++ .../wx/mp/config/WxMpConfiguration.java | 111 +++++++++++ .../vertical/wx/mp/config/WxMpProperties.java | 46 +++++ .../wx/mp/controller/WxMenuController.java | 188 ++++++++++++++++++ .../wx/mp/controller/WxPortalController.java | 116 +++++++++++ .../mp/controller/WxRedirectController.java | 42 ++++ .../vertical/wx/mp/error/ErrorController.java | 29 +++ .../wx/mp/error/ErrorPageConfiguration.java | 27 +++ .../wx/mp/handler/AbstractHandler.java | 12 ++ .../wx/mp/handler/KfSessionHandler.java | 25 +++ .../wx/mp/handler/LocationHandler.java | 44 ++++ .../vertical/wx/mp/handler/LogHandler.java | 25 +++ .../vertical/wx/mp/handler/MenuHandler.java | 35 ++++ .../vertical/wx/mp/handler/MsgHandler.java | 52 +++++ .../vertical/wx/mp/handler/NullHandler.java | 24 +++ .../vertical/wx/mp/handler/ScanHandler.java | 25 +++ .../mp/handler/StoreCheckNotifyHandler.java | 27 +++ .../wx/mp/handler/SubscribeHandler.java | 71 +++++++ .../wx/mp/handler/UnsubscribeHandler.java | 27 +++ .../rymcu/vertical/wx/mp/utils/JsonUtils.java | 9 + 23 files changed, 1003 insertions(+) create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/builder/AbstractBuilder.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/builder/ImageBuilder.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/builder/TextBuilder.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/config/WxMpConfiguration.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/config/WxMpProperties.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/controller/WxMenuController.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/controller/WxPortalController.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/controller/WxRedirectController.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/error/ErrorController.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/error/ErrorPageConfiguration.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/handler/AbstractHandler.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/handler/KfSessionHandler.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/handler/LocationHandler.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/handler/LogHandler.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/handler/MenuHandler.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/handler/MsgHandler.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/handler/NullHandler.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/handler/ScanHandler.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/handler/StoreCheckNotifyHandler.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/handler/SubscribeHandler.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/handler/UnsubscribeHandler.java create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/utils/JsonUtils.java diff --git a/pom.xml b/pom.xml index 27c3657..c8b3a9c 100644 --- a/pom.xml +++ b/pom.xml @@ -169,6 +169,11 @@ jodd-http 5.0.13 + + com.github.binarywang + weixin-java-mp + 3.7.0 + diff --git a/src/main/java/com/rymcu/vertical/wx/mp/builder/AbstractBuilder.java b/src/main/java/com/rymcu/vertical/wx/mp/builder/AbstractBuilder.java new file mode 100644 index 0000000..57207d4 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/builder/AbstractBuilder.java @@ -0,0 +1,17 @@ +package com.rymcu.vertical.wx.mp.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 org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +public abstract class AbstractBuilder { + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + public abstract WxMpXmlOutMessage build(String content, + WxMpXmlMessage wxMessage, WxMpService service); +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/builder/ImageBuilder.java b/src/main/java/com/rymcu/vertical/wx/mp/builder/ImageBuilder.java new file mode 100644 index 0000000..922b3bb --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/builder/ImageBuilder.java @@ -0,0 +1,24 @@ +package com.rymcu.vertical.wx.mp.builder; + +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +public class ImageBuilder extends AbstractBuilder { + + @Override + public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, + WxMpService service) { + + WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId(content) + .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) + .build(); + + return m; + } + +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/builder/TextBuilder.java b/src/main/java/com/rymcu/vertical/wx/mp/builder/TextBuilder.java new file mode 100644 index 0000000..83f0ea9 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/builder/TextBuilder.java @@ -0,0 +1,22 @@ +package com.rymcu.vertical.wx.mp.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 Binary Wang(https://github.com/binarywang) + */ +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; + } + +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/config/WxMpConfiguration.java b/src/main/java/com/rymcu/vertical/wx/mp/config/WxMpConfiguration.java new file mode 100644 index 0000000..94c1402 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/config/WxMpConfiguration.java @@ -0,0 +1,111 @@ +package com.rymcu.vertical.wx.mp.config; + +import com.rymcu.vertical.wx.mp.handler.*; +import lombok.AllArgsConstructor; +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.impl.WxMpDefaultConfigImpl; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.List; +import java.util.stream.Collectors; + +import static me.chanjar.weixin.common.api.WxConsts.EventType; +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; +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 Binary Wang(https://github.com/binarywang) + */ +@AllArgsConstructor +@Configuration +@EnableConfigurationProperties(WxMpProperties.class) +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; + private final WxMpProperties properties; + + @Bean + public WxMpService wxMpService() { + // 代码里 getConfigs()处报错的同学,请注意仔细阅读项目说明,你的IDE需要引入lombok插件!!!! + final List configs = this.properties.getConfigs(); + if (configs == null) { + throw new RuntimeException("大哥,拜托先看下项目首页的说明(readme文件),添加下相关配置,注意别配错了!"); + } + + WxMpService service = new WxMpServiceImpl(); + service.setMultiConfigStorages(configs + .stream().map(a -> { + WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl(); + configStorage.setAppId(a.getAppId()); + configStorage.setSecret(a.getSecret()); + configStorage.setToken(a.getToken()); + configStorage.setAesKey(a.getAesKey()); + return configStorage; + }).collect(Collectors.toMap(WxMpDefaultConfigImpl::getAppId, a -> a, (o, n) -> o))); + return service; + } + + @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(EventType.CLICK).handler(this.menuHandler).end(); + + // 点击菜单连接事件 + newRouter.rule().async(false).msgType(EVENT).event(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(EventType.LOCATION).handler(this.locationHandler).end(); + + // 接收地理位置消息 + newRouter.rule().async(false).msgType(XmlMsgType.LOCATION).handler(this.locationHandler).end(); + + // 扫码事件 + newRouter.rule().async(false).msgType(EVENT).event(EventType.SCAN).handler(this.scanHandler).end(); + + // 默认 + newRouter.rule().async(false).handler(this.msgHandler).end(); + + return newRouter; + } + +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/config/WxMpProperties.java b/src/main/java/com/rymcu/vertical/wx/mp/config/WxMpProperties.java new file mode 100644 index 0000000..de1ee9d --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/config/WxMpProperties.java @@ -0,0 +1,46 @@ +package com.rymcu.vertical.wx.mp.config; + +import com.rymcu.vertical.wx.mp.utils.JsonUtils; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.List; + +/** + * wechat mp properties + * + * @author Binary Wang(https://github.com/binarywang) + */ +@Data +@ConfigurationProperties(prefix = "wx.mp") +public class WxMpProperties { + private List configs; + + @Data + public static class MpConfig { + /** + * 设置微信公众号的appid + */ + private String appId; + + /** + * 设置微信公众号的app secret + */ + private String secret; + + /** + * 设置微信公众号的token + */ + private String token; + + /** + * 设置微信公众号的EncodingAESKey + */ + private String aesKey; + } + + @Override + public String toString() { + return JsonUtils.toJson(this); + } +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/controller/WxMenuController.java b/src/main/java/com/rymcu/vertical/wx/mp/controller/WxMenuController.java new file mode 100644 index 0000000..03c2372 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/controller/WxMenuController.java @@ -0,0 +1,188 @@ +package com.rymcu.vertical.wx.mp.controller; + +import lombok.AllArgsConstructor; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.bean.menu.WxMenu; +import me.chanjar.weixin.common.bean.menu.WxMenuButton; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult; +import me.chanjar.weixin.mp.bean.menu.WxMpMenu; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.net.MalformedURLException; +import java.net.URL; + +import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@AllArgsConstructor +@RestController +@RequestMapping("/wx/menu/{appid}") +public class WxMenuController { + private final WxMpService wxService; + + /** + *
+     * 自定义菜单创建接口
+     * 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013&token=&lang=zh_CN
+     * 如果要创建个性化菜单,请设置matchrule属性
+     * 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN
+     * 
+ * + * @return 如果是个性化菜单,则返回menuid,否则返回null + */ + @PostMapping("/create") + public String menuCreate(@PathVariable String appid, @RequestBody WxMenu menu) throws WxErrorException { + return this.wxService.switchoverTo(appid).getMenuService().menuCreate(menu); + } + + @GetMapping("/create") + public String menuCreateSample(@PathVariable String appid) throws WxErrorException, MalformedURLException { + WxMenu menu = new WxMenu(); + WxMenuButton button1 = new WxMenuButton(); + button1.setType(MenuButtonType.CLICK); + button1.setName("今日歌曲"); + button1.setKey("V1001_TODAY_MUSIC"); + +// WxMenuButton button2 = new WxMenuButton(); +// button2.setType(WxConsts.BUTTON_MINIPROGRAM); +// button2.setName("小程序"); +// button2.setAppId("wx286b93c14bbf93aa"); +// button2.setPagePath("pages/lunar/index.html"); +// button2.setUrl("http://mp.weixin.qq.com"); + + WxMenuButton button3 = new WxMenuButton(); + button3.setName("菜单"); + + menu.getButtons().add(button1); +// menu.getButtons().add(button2); + menu.getButtons().add(button3); + + WxMenuButton button31 = new WxMenuButton(); + button31.setType(MenuButtonType.VIEW); + button31.setName("搜索"); + button31.setUrl("http://www.soso.com/"); + + WxMenuButton button32 = new WxMenuButton(); + button32.setType(MenuButtonType.VIEW); + button32.setName("视频"); + button32.setUrl("http://v.qq.com/"); + + WxMenuButton button33 = new WxMenuButton(); + button33.setType(MenuButtonType.CLICK); + button33.setName("赞一下我们"); + button33.setKey("V1001_GOOD"); + + WxMenuButton button34 = new WxMenuButton(); + button34.setType(MenuButtonType.VIEW); + button34.setName("获取用户信息"); + + ServletRequestAttributes servletRequestAttributes = + (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (servletRequestAttributes != null) { + HttpServletRequest request = servletRequestAttributes.getRequest(); + URL requestURL = new URL(request.getRequestURL().toString()); + String url = this.wxService.switchoverTo(appid).oauth2buildAuthorizationUrl( + String.format("%s://%s/wx/redirect/%s/greet", requestURL.getProtocol(), requestURL.getHost(), appid), + WxConsts.OAuth2Scope.SNSAPI_USERINFO, null); + button34.setUrl(url); + } + + button3.getSubButtons().add(button31); + button3.getSubButtons().add(button32); + button3.getSubButtons().add(button33); + button3.getSubButtons().add(button34); + + this.wxService.switchover(appid); + return this.wxService.getMenuService().menuCreate(menu); + } + + /** + *
+     * 自定义菜单创建接口
+     * 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013&token=&lang=zh_CN
+     * 如果要创建个性化菜单,请设置matchrule属性
+     * 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN
+     * 
+ * + * @return 如果是个性化菜单,则返回menuid,否则返回null + */ + @PostMapping("/createByJson") + public String menuCreate(@PathVariable String appid, @RequestBody String json) throws WxErrorException { + return this.wxService.switchoverTo(appid).getMenuService().menuCreate(json); + } + + /** + *
+     * 自定义菜单删除接口
+     * 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141015&token=&lang=zh_CN
+     * 
+ */ + @GetMapping("/delete") + public void menuDelete(@PathVariable String appid) throws WxErrorException { + this.wxService.switchoverTo(appid).getMenuService().menuDelete(); + } + + /** + *
+     * 删除个性化菜单接口
+     * 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN
+     * 
+ * + * @param menuId 个性化菜单的menuid + */ + @GetMapping("/delete/{menuId}") + public void menuDelete(@PathVariable String appid, @PathVariable String menuId) throws WxErrorException { + this.wxService.switchoverTo(appid).getMenuService().menuDelete(menuId); + } + + /** + *
+     * 自定义菜单查询接口
+     * 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141014&token=&lang=zh_CN
+     * 
+ */ + @GetMapping("/get") + public WxMpMenu menuGet(@PathVariable String appid) throws WxErrorException { + return this.wxService.switchoverTo(appid).getMenuService().menuGet(); + } + + /** + *
+     * 测试个性化菜单匹配结果
+     * 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html
+     * 
+ * + * @param userid 可以是粉丝的OpenID,也可以是粉丝的微信号。 + */ + @GetMapping("/menuTryMatch/{userid}") + public WxMenu menuTryMatch(@PathVariable String appid, @PathVariable String userid) throws WxErrorException { + return this.wxService.switchoverTo(appid).getMenuService().menuTryMatch(userid); + } + + /** + *
+     * 获取自定义菜单配置接口
+     * 本接口将会提供公众号当前使用的自定义菜单的配置,如果公众号是通过API调用设置的菜单,则返回菜单的开发配置,而如果公众号是在公众平台官网通过网站功能发布菜单,则本接口返回运营者设置的菜单配置。
+     * 请注意:
+     * 1、第三方平台开发者可以通过本接口,在旗下公众号将业务授权给你后,立即通过本接口检测公众号的自定义菜单配置,并通过接口再次给公众号设置好自动回复规则,以提升公众号运营者的业务体验。
+     * 2、本接口与自定义菜单查询接口的不同之处在于,本接口无论公众号的接口是如何设置的,都能查询到接口,而自定义菜单查询接口则仅能查询到使用API设置的菜单配置。
+     * 3、认证/未认证的服务号/订阅号,以及接口测试号,均拥有该接口权限。
+     * 4、从第三方平台的公众号登录授权机制上来说,该接口从属于消息与菜单权限集。
+     * 5、本接口中返回的图片/语音/视频为临时素材(临时素材每次获取都不同,3天内有效,通过素材管理-获取临时素材接口来获取这些素材),本接口返回的图文消息为永久素材素材(通过素材管理-获取永久素材接口来获取这些素材)。
+     *  接口调用请求说明:
+     * http请求方式: GET(请使用https协议)
+     * https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=ACCESS_TOKEN
+     * 
+ */ + @GetMapping("/getSelfMenuInfo") + public WxMpGetSelfMenuInfoResult getSelfMenuInfo(@PathVariable String appid) throws WxErrorException { + return this.wxService.switchoverTo(appid).getMenuService().getSelfMenuInfo(); + } +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/controller/WxPortalController.java b/src/main/java/com/rymcu/vertical/wx/mp/controller/WxPortalController.java new file mode 100644 index 0000000..524549a --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/controller/WxPortalController.java @@ -0,0 +1,116 @@ +package com.rymcu.vertical.wx.mp.controller; + +import lombok.AllArgsConstructor; +import lombok.extern.log4j.Log4j; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.mp.api.WxMpMessageRouter; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("/wx/portal/{appid}") +public class WxPortalController { + private final WxMpService wxService; + 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; + } + +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/controller/WxRedirectController.java b/src/main/java/com/rymcu/vertical/wx/mp/controller/WxRedirectController.java new file mode 100644 index 0000000..35bf6b4 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/controller/WxRedirectController.java @@ -0,0 +1,42 @@ +package com.rymcu.vertical.wx.mp.controller; + +import lombok.AllArgsConstructor; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; +import me.chanjar.weixin.mp.bean.result.WxMpUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import javax.xml.ws.Action; + +/** + * @author Edward + */ +@AllArgsConstructor +@Controller +@RequestMapping("/wx/redirect/{appid}") +public class WxRedirectController { + private final WxMpService wxService; + + @RequestMapping("/greet") + public String greetUser(@PathVariable String appid, @RequestParam String code, ModelMap map) { + if (!this.wxService.switchover(appid)) { + throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid)); + } + + try { + WxMpOAuth2AccessToken accessToken = wxService.oauth2getAccessToken(code); + WxMpUser user = wxService.oauth2getUserInfo(accessToken, null); + map.put("user", user); + } catch (WxErrorException e) { + e.printStackTrace(); + } + + return "greet_user"; + } +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/error/ErrorController.java b/src/main/java/com/rymcu/vertical/wx/mp/error/ErrorController.java new file mode 100644 index 0000000..03b8bad --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/error/ErrorController.java @@ -0,0 +1,29 @@ +package com.rymcu.vertical.wx.mp.error; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + *
+ * 出错页面控制器
+ * Created by Binary Wang on 2018/8/25.
+ * 
+ * + * @author Binary Wang + */ +@Controller +@RequestMapping("/error") +public class ErrorController { + + @GetMapping(value = "/404") + public String error404() { + return "error"; + } + + @GetMapping(value = "/500") + public String error500() { + return "error"; + } + +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/error/ErrorPageConfiguration.java b/src/main/java/com/rymcu/vertical/wx/mp/error/ErrorPageConfiguration.java new file mode 100644 index 0000000..2502a00 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/error/ErrorPageConfiguration.java @@ -0,0 +1,27 @@ +package com.rymcu.vertical.wx.mp.error; + +import org.springframework.boot.web.server.ErrorPage; +import org.springframework.boot.web.server.ErrorPageRegistrar; +import org.springframework.boot.web.server.ErrorPageRegistry; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; + +/** + *
+ * 配置错误状态与对应访问路径
+ * Created by Binary Wang on 2018/8/25.
+ * 
+ * + * @author Binary Wang + */ +@Component +public class ErrorPageConfiguration implements ErrorPageRegistrar { + @Override + public void registerErrorPages(ErrorPageRegistry errorPageRegistry) { + errorPageRegistry.addErrorPages( + new ErrorPage(HttpStatus.NOT_FOUND, "/error/404"), + new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500") + ); + } + +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/handler/AbstractHandler.java b/src/main/java/com/rymcu/vertical/wx/mp/handler/AbstractHandler.java new file mode 100644 index 0000000..2149b1c --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/handler/AbstractHandler.java @@ -0,0 +1,12 @@ +package com.rymcu.vertical.wx.mp.handler; + +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +public abstract class AbstractHandler implements WxMpMessageHandler { + protected Logger logger = LoggerFactory.getLogger(getClass()); +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/handler/KfSessionHandler.java b/src/main/java/com/rymcu/vertical/wx/mp/handler/KfSessionHandler.java new file mode 100644 index 0000000..0423997 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/handler/KfSessionHandler.java @@ -0,0 +1,25 @@ +package com.rymcu.vertical.wx.mp.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 Binary Wang(https://github.com/binarywang) + */ +@Component +public class KfSessionHandler extends AbstractHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + //TODO 对会话做处理 + return null; + } + +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/handler/LocationHandler.java b/src/main/java/com/rymcu/vertical/wx/mp/handler/LocationHandler.java new file mode 100644 index 0000000..fd0330f --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/handler/LocationHandler.java @@ -0,0 +1,44 @@ +package com.rymcu.vertical.wx.mp.handler; + +import com.rymcu.vertical.wx.mp.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 Binary Wang(https://github.com/binarywang) + */ +@Component +public class LocationHandler extends AbstractHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map 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(), String.valueOf(wxMessage.getPrecision())); + + //TODO 可以将用户地理位置信息保存到本地数据库,以便以后使用 + + return null; + } + +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/handler/LogHandler.java b/src/main/java/com/rymcu/vertical/wx/mp/handler/LogHandler.java new file mode 100644 index 0000000..f405a19 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/handler/LogHandler.java @@ -0,0 +1,25 @@ +package com.rymcu.vertical.wx.mp.handler; + +import com.rymcu.vertical.wx.mp.utils.JsonUtils; +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 Binary Wang(https://github.com/binarywang) + */ +@Component +public class LogHandler extends AbstractHandler { + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + this.logger.info("\n接收到请求消息,内容:{}", JsonUtils.toJson(wxMessage)); + return null; + } + +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/handler/MenuHandler.java b/src/main/java/com/rymcu/vertical/wx/mp/handler/MenuHandler.java new file mode 100644 index 0000000..e100914 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/handler/MenuHandler.java @@ -0,0 +1,35 @@ +package com.rymcu.vertical.wx.mp.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; + +import static me.chanjar.weixin.common.api.WxConsts.EventType; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class MenuHandler extends AbstractHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService weixinService, + WxSessionManager sessionManager) { + String msg = String.format("type:%s, event:%s, key:%s", + wxMessage.getMsgType(), wxMessage.getEvent(), + wxMessage.getEventKey()); + if (EventType.VIEW.equals(wxMessage.getEvent())) { + return null; + } + + return WxMpXmlOutMessage.TEXT().content(msg) + .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) + .build(); + } + +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/handler/MsgHandler.java b/src/main/java/com/rymcu/vertical/wx/mp/handler/MsgHandler.java new file mode 100644 index 0000000..74cde99 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/handler/MsgHandler.java @@ -0,0 +1,52 @@ +package com.rymcu.vertical.wx.mp.handler; + +import com.rymcu.vertical.wx.mp.builder.TextBuilder; +import com.rymcu.vertical.wx.mp.utils.JsonUtils; +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.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import java.util.Map; + +import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class MsgHandler extends AbstractHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService weixinService, + WxSessionManager sessionManager) { + + if (!wxMessage.getMsgType().equals(XmlMsgType.EVENT)) { + //TODO 可以选择将消息保存到本地 + } + + //当用户输入关键词如“你好”,“客服”等,并且有客服在线时,把消息转发给在线客服 + try { + if (StringUtils.startsWithAny(wxMessage.getContent(), "你好", "客服") + && weixinService.getKefuService().kfOnlineList() + .getKfOnlineList().size() > 0) { + return WxMpXmlOutMessage.TRANSFER_CUSTOMER_SERVICE() + .fromUser(wxMessage.getToUser()) + .toUser(wxMessage.getFromUser()).build(); + } + } catch (WxErrorException e) { + e.printStackTrace(); + } + + //TODO 组装回复消息 + String content = "收到信息内容:" + JsonUtils.toJson(wxMessage); + + return new TextBuilder().build(content, wxMessage, weixinService); + + } + +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/handler/NullHandler.java b/src/main/java/com/rymcu/vertical/wx/mp/handler/NullHandler.java new file mode 100644 index 0000000..23bbdad --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/handler/NullHandler.java @@ -0,0 +1,24 @@ +package com.rymcu.vertical.wx.mp.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 Binary Wang(https://github.com/binarywang) + */ +@Component +public class NullHandler extends AbstractHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + return null; + } + +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/handler/ScanHandler.java b/src/main/java/com/rymcu/vertical/wx/mp/handler/ScanHandler.java new file mode 100644 index 0000000..99bc85b --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/handler/ScanHandler.java @@ -0,0 +1,25 @@ +package com.rymcu.vertical.wx.mp.handler; + +import java.util.Map; + +import org.springframework.stereotype.Component; + +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; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class ScanHandler extends AbstractHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMpXmlMessage, Map map, + WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException { + // 扫码事件处理 + return null; + } +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/handler/StoreCheckNotifyHandler.java b/src/main/java/com/rymcu/vertical/wx/mp/handler/StoreCheckNotifyHandler.java new file mode 100644 index 0000000..d036ea7 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/handler/StoreCheckNotifyHandler.java @@ -0,0 +1,27 @@ +package com.rymcu.vertical.wx.mp.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 Binary Wang(https://github.com/binarywang) + */ +@Component +public class StoreCheckNotifyHandler extends AbstractHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + // TODO 处理门店审核事件 + return null; + } + +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/handler/SubscribeHandler.java b/src/main/java/com/rymcu/vertical/wx/mp/handler/SubscribeHandler.java new file mode 100644 index 0000000..d4fac61 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/handler/SubscribeHandler.java @@ -0,0 +1,71 @@ +package com.rymcu.vertical.wx.mp.handler; + +import java.util.Map; + +import com.rymcu.vertical.wx.mp.builder.TextBuilder; +import org.springframework.stereotype.Component; + +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.result.WxMpUser; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class SubscribeHandler extends AbstractHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService weixinService, + WxSessionManager sessionManager) throws WxErrorException { + + this.logger.info("新关注用户 OPENID: " + wxMessage.getFromUser()); + + // 获取微信用户基本信息 + try { + WxMpUser userWxInfo = weixinService.getUserService() + .userInfo(wxMessage.getFromUser(), null); + if (userWxInfo != null) { + // TODO 可以添加关注用户到本地数据库 + } + } catch (WxErrorException e) { + if (e.getError().getErrorCode() == 48001) { + this.logger.info("该公众号没有获取用户信息权限!"); + } + } + + + WxMpXmlOutMessage responseResult = null; + try { + responseResult = this.handleSpecial(wxMessage); + } catch (Exception e) { + this.logger.error(e.getMessage(), e); + } + + if (responseResult != null) { + return responseResult; + } + + try { + return new TextBuilder().build("感谢关注", wxMessage, weixinService); + } catch (Exception e) { + this.logger.error(e.getMessage(), e); + } + + return null; + } + + /** + * 处理特殊请求,比如如果是扫码进来的,可以做相应处理 + */ + private WxMpXmlOutMessage handleSpecial(WxMpXmlMessage wxMessage) + throws Exception { + //TODO + return null; + } + +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/handler/UnsubscribeHandler.java b/src/main/java/com/rymcu/vertical/wx/mp/handler/UnsubscribeHandler.java new file mode 100644 index 0000000..49cfa3d --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/handler/UnsubscribeHandler.java @@ -0,0 +1,27 @@ +package com.rymcu.vertical.wx.mp.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 Binary Wang(https://github.com/binarywang) + */ +@Component +public class UnsubscribeHandler extends AbstractHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + String openId = wxMessage.getFromUser(); + this.logger.info("取消关注用户 OPENID: " + openId); + // TODO 可以更新本地数据库为取消关注状态 + return null; + } + +} diff --git a/src/main/java/com/rymcu/vertical/wx/mp/utils/JsonUtils.java b/src/main/java/com/rymcu/vertical/wx/mp/utils/JsonUtils.java new file mode 100644 index 0000000..bda28aa --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/utils/JsonUtils.java @@ -0,0 +1,9 @@ +package com.rymcu.vertical.wx.mp.utils; + +import com.alibaba.fastjson.JSONObject; + +public class JsonUtils { + public static String toJson(Object obj) { + return JSONObject.toJSONString(obj); + } +} From 94a4d38a93c040b178e8ff98b393ae421c27bb85 Mon Sep 17 00:00:00 2001 From: x ronger Date: Mon, 16 Mar 2020 21:50:14 +0800 Subject: [PATCH 02/19] :art: --- .../{dynProps4Files => props}/DynProps4FilesService.java | 2 +- .../vertical/core/service/redis/impl/RedisServiceImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/main/java/com/rymcu/vertical/core/service/{dynProps4Files => props}/DynProps4FilesService.java (99%) diff --git a/src/main/java/com/rymcu/vertical/core/service/dynProps4Files/DynProps4FilesService.java b/src/main/java/com/rymcu/vertical/core/service/props/DynProps4FilesService.java similarity index 99% rename from src/main/java/com/rymcu/vertical/core/service/dynProps4Files/DynProps4FilesService.java rename to src/main/java/com/rymcu/vertical/core/service/props/DynProps4FilesService.java index a34e634..c9b3349 100644 --- a/src/main/java/com/rymcu/vertical/core/service/dynProps4Files/DynProps4FilesService.java +++ b/src/main/java/com/rymcu/vertical/core/service/props/DynProps4FilesService.java @@ -1,4 +1,4 @@ -package com.rymcu.vertical.core.service.dynProps4Files; +package com.rymcu.vertical.core.service.props; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; diff --git a/src/main/java/com/rymcu/vertical/core/service/redis/impl/RedisServiceImpl.java b/src/main/java/com/rymcu/vertical/core/service/redis/impl/RedisServiceImpl.java index a2a2858..caff003 100644 --- a/src/main/java/com/rymcu/vertical/core/service/redis/impl/RedisServiceImpl.java +++ b/src/main/java/com/rymcu/vertical/core/service/redis/impl/RedisServiceImpl.java @@ -3,7 +3,7 @@ package com.rymcu.vertical.core.service.redis.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; import com.fasterxml.jackson.databind.JavaType; -import com.rymcu.vertical.core.service.dynProps4Files.DynProps4FilesService; +import com.rymcu.vertical.core.service.props.DynProps4FilesService; import com.rymcu.vertical.core.service.redis.RedisResult; import com.rymcu.vertical.core.service.redis.RedisService; import org.apache.commons.io.IOUtils; From f663f41270954fee2af7d1fd5e8f32fc39ac345e Mon Sep 17 00:00:00 2001 From: x ronger Date: Mon, 16 Mar 2020 22:29:45 +0800 Subject: [PATCH 03/19] =?UTF-8?q?:sparkles:=20=E5=BE=AE=E4=BF=A1=E5=85=AC?= =?UTF-8?q?=E4=BC=97=E5=8F=B7=E6=9C=8D=E5=8A=A1=E9=9B=86=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/rymcu/vertical/config/ShiroConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/rymcu/vertical/config/ShiroConfig.java b/src/main/java/com/rymcu/vertical/config/ShiroConfig.java index 9fda51a..25b48ce 100644 --- a/src/main/java/com/rymcu/vertical/config/ShiroConfig.java +++ b/src/main/java/com/rymcu/vertical/config/ShiroConfig.java @@ -55,6 +55,7 @@ public class ShiroConfig implements EnvironmentAware { filterChainDefinitionMap.put("/api/**", "anon"); filterChainDefinitionMap.put("/ws/**", "anon"); + filterChainDefinitionMap.put("/wx/**", "anon"); filterChainDefinitionMap.put("/**", "auth"); //配置shiro默认登录界面地址,前后端分离中登录界面跳转应由前端路由控制,后台仅返回json数据 shiroFilterFactoryBean.setLoginUrl("/login"); From a461492eba80377621657286a70dc2bf15a82654 Mon Sep 17 00:00:00 2001 From: x ronger Date: Mon, 16 Mar 2020 23:39:25 +0800 Subject: [PATCH 04/19] :art: --- .../wx/mp/controller/WxMenuController.java | 38 +++++++++---------- .../wx/mp/controller/WxPortalController.java | 14 +++---- .../mp/controller/WxRedirectController.java | 8 ++-- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/rymcu/vertical/wx/mp/controller/WxMenuController.java b/src/main/java/com/rymcu/vertical/wx/mp/controller/WxMenuController.java index 03c2372..40ad886 100644 --- a/src/main/java/com/rymcu/vertical/wx/mp/controller/WxMenuController.java +++ b/src/main/java/com/rymcu/vertical/wx/mp/controller/WxMenuController.java @@ -23,7 +23,7 @@ import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType; */ @AllArgsConstructor @RestController -@RequestMapping("/wx/menu/{appid}") +@RequestMapping("/wx/menu/{appId}") public class WxMenuController { private final WxMpService wxService; @@ -38,12 +38,12 @@ public class WxMenuController { * @return 如果是个性化菜单,则返回menuid,否则返回null */ @PostMapping("/create") - public String menuCreate(@PathVariable String appid, @RequestBody WxMenu menu) throws WxErrorException { - return this.wxService.switchoverTo(appid).getMenuService().menuCreate(menu); + public String menuCreate(@PathVariable String appId, @RequestBody WxMenu menu) throws WxErrorException { + return this.wxService.switchoverTo(appId).getMenuService().menuCreate(menu); } @GetMapping("/create") - public String menuCreateSample(@PathVariable String appid) throws WxErrorException, MalformedURLException { + public String menuCreateSample(@PathVariable String appId) throws WxErrorException, MalformedURLException { WxMenu menu = new WxMenu(); WxMenuButton button1 = new WxMenuButton(); button1.setType(MenuButtonType.CLICK); @@ -88,8 +88,8 @@ public class WxMenuController { if (servletRequestAttributes != null) { HttpServletRequest request = servletRequestAttributes.getRequest(); URL requestURL = new URL(request.getRequestURL().toString()); - String url = this.wxService.switchoverTo(appid).oauth2buildAuthorizationUrl( - String.format("%s://%s/wx/redirect/%s/greet", requestURL.getProtocol(), requestURL.getHost(), appid), + String url = this.wxService.switchoverTo(appId).oauth2buildAuthorizationUrl( + String.format("%s://%s/wx/redirect/%s/greet", requestURL.getProtocol(), requestURL.getHost(), appId), WxConsts.OAuth2Scope.SNSAPI_USERINFO, null); button34.setUrl(url); } @@ -99,7 +99,7 @@ public class WxMenuController { button3.getSubButtons().add(button33); button3.getSubButtons().add(button34); - this.wxService.switchover(appid); + this.wxService.switchover(appId); return this.wxService.getMenuService().menuCreate(menu); } @@ -114,8 +114,8 @@ public class WxMenuController { * @return 如果是个性化菜单,则返回menuid,否则返回null */ @PostMapping("/createByJson") - public String menuCreate(@PathVariable String appid, @RequestBody String json) throws WxErrorException { - return this.wxService.switchoverTo(appid).getMenuService().menuCreate(json); + public String menuCreate(@PathVariable String appId, @RequestBody String json) throws WxErrorException { + return this.wxService.switchoverTo(appId).getMenuService().menuCreate(json); } /** @@ -125,8 +125,8 @@ public class WxMenuController { * */ @GetMapping("/delete") - public void menuDelete(@PathVariable String appid) throws WxErrorException { - this.wxService.switchoverTo(appid).getMenuService().menuDelete(); + public void menuDelete(@PathVariable String appId) throws WxErrorException { + this.wxService.switchoverTo(appId).getMenuService().menuDelete(); } /** @@ -138,8 +138,8 @@ public class WxMenuController { * @param menuId 个性化菜单的menuid */ @GetMapping("/delete/{menuId}") - public void menuDelete(@PathVariable String appid, @PathVariable String menuId) throws WxErrorException { - this.wxService.switchoverTo(appid).getMenuService().menuDelete(menuId); + public void menuDelete(@PathVariable String appId, @PathVariable String menuId) throws WxErrorException { + this.wxService.switchoverTo(appId).getMenuService().menuDelete(menuId); } /** @@ -149,8 +149,8 @@ public class WxMenuController { * */ @GetMapping("/get") - public WxMpMenu menuGet(@PathVariable String appid) throws WxErrorException { - return this.wxService.switchoverTo(appid).getMenuService().menuGet(); + public WxMpMenu menuGet(@PathVariable String appId) throws WxErrorException { + return this.wxService.switchoverTo(appId).getMenuService().menuGet(); } /** @@ -162,8 +162,8 @@ public class WxMenuController { * @param userid 可以是粉丝的OpenID,也可以是粉丝的微信号。 */ @GetMapping("/menuTryMatch/{userid}") - public WxMenu menuTryMatch(@PathVariable String appid, @PathVariable String userid) throws WxErrorException { - return this.wxService.switchoverTo(appid).getMenuService().menuTryMatch(userid); + public WxMenu menuTryMatch(@PathVariable String appId, @PathVariable String userid) throws WxErrorException { + return this.wxService.switchoverTo(appId).getMenuService().menuTryMatch(userid); } /** @@ -182,7 +182,7 @@ public class WxMenuController { * */ @GetMapping("/getSelfMenuInfo") - public WxMpGetSelfMenuInfoResult getSelfMenuInfo(@PathVariable String appid) throws WxErrorException { - return this.wxService.switchoverTo(appid).getMenuService().getSelfMenuInfo(); + public WxMpGetSelfMenuInfoResult getSelfMenuInfo(@PathVariable String appId) throws WxErrorException { + return this.wxService.switchoverTo(appId).getMenuService().getSelfMenuInfo(); } } diff --git a/src/main/java/com/rymcu/vertical/wx/mp/controller/WxPortalController.java b/src/main/java/com/rymcu/vertical/wx/mp/controller/WxPortalController.java index 524549a..2462c67 100644 --- a/src/main/java/com/rymcu/vertical/wx/mp/controller/WxPortalController.java +++ b/src/main/java/com/rymcu/vertical/wx/mp/controller/WxPortalController.java @@ -26,13 +26,13 @@ import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; @Slf4j @AllArgsConstructor @RestController -@RequestMapping("/wx/portal/{appid}") +@RequestMapping("/wx/portal/{appId}") public class WxPortalController { private final WxMpService wxService; private final WxMpMessageRouter messageRouter; @GetMapping(produces = "text/plain;charset=utf-8") - public String authGet(@PathVariable String appid, + 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, @@ -44,8 +44,8 @@ public class WxPortalController { throw new IllegalArgumentException("请求参数非法,请核实!"); } - if (!this.wxService.switchover(appid)) { - throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid)); + if (!this.wxService.switchover(appId)) { + throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appId)); } if (wxService.checkSignature(timestamp, nonce, signature)) { @@ -56,7 +56,7 @@ public class WxPortalController { } @PostMapping(produces = "application/xml; charset=UTF-8") - public String post(@PathVariable String appid, + public String post(@PathVariable String appId, @RequestBody String requestBody, @RequestParam("signature") String signature, @RequestParam("timestamp") String timestamp, @@ -68,8 +68,8 @@ public class WxPortalController { + " 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 (!this.wxService.switchover(appId)) { + throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appId)); } if (!wxService.checkSignature(timestamp, nonce, signature)) { diff --git a/src/main/java/com/rymcu/vertical/wx/mp/controller/WxRedirectController.java b/src/main/java/com/rymcu/vertical/wx/mp/controller/WxRedirectController.java index 35bf6b4..39c785f 100644 --- a/src/main/java/com/rymcu/vertical/wx/mp/controller/WxRedirectController.java +++ b/src/main/java/com/rymcu/vertical/wx/mp/controller/WxRedirectController.java @@ -19,14 +19,14 @@ import javax.xml.ws.Action; */ @AllArgsConstructor @Controller -@RequestMapping("/wx/redirect/{appid}") +@RequestMapping("/wx/redirect/{appId}") public class WxRedirectController { private final WxMpService wxService; @RequestMapping("/greet") - public String greetUser(@PathVariable String appid, @RequestParam String code, ModelMap map) { - if (!this.wxService.switchover(appid)) { - throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid)); + public String greetUser(@PathVariable String appId, @RequestParam String code, ModelMap map) { + if (!this.wxService.switchover(appId)) { + throw new IllegalArgumentException(String.format("未找到对应appId=[%s]的配置,请核实!", appId)); } try { From 637c66135c278c7d76293b5c571fa51b749ee683 Mon Sep 17 00:00:00 2001 From: ronger Date: Tue, 17 Mar 2020 17:32:38 +0800 Subject: [PATCH 05/19] =?UTF-8?q?:heavy=5Fplus=5Fsign:=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=BE=AE=E4=BF=A1=E6=9C=8D=E5=8A=A1=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pom.xml b/pom.xml index c8b3a9c..5e02b24 100644 --- a/pom.xml +++ b/pom.xml @@ -174,6 +174,16 @@ weixin-java-mp 3.7.0 + + com.github.binarywang + weixin-java-miniapp + 3.7.0 + + + com.github.binarywang + weixin-java-open + 3.7.0 + From e28e21942809ce7a3675a0094bcca2c6c3bf9521 Mon Sep 17 00:00:00 2001 From: ronger Date: Tue, 17 Mar 2020 17:33:35 +0800 Subject: [PATCH 06/19] =?UTF-8?q?:sparkles:=20=E5=BE=AE=E4=BF=A1=E5=BC=80?= =?UTF-8?q?=E6=94=BE=E5=B9=B3=E5=8F=B0=E6=9C=8D=E5=8A=A1=E9=9B=86=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wx/mp/controller/WxoAuthController.java | 68 +++++++++++ .../wx/open/config/WxOpenProperties.java | 42 +++++++ .../controller/WxOpenNotifyController.java | 110 ++++++++++++++++++ .../wx/open/handler/WxOpenServiceHandler.java | 74 ++++++++++++ 4 files changed, 294 insertions(+) create mode 100644 src/main/java/com/rymcu/vertical/wx/mp/controller/WxoAuthController.java create mode 100644 src/main/java/com/rymcu/vertical/wx/open/config/WxOpenProperties.java create mode 100644 src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenNotifyController.java create mode 100644 src/main/java/com/rymcu/vertical/wx/open/handler/WxOpenServiceHandler.java diff --git a/src/main/java/com/rymcu/vertical/wx/mp/controller/WxoAuthController.java b/src/main/java/com/rymcu/vertical/wx/mp/controller/WxoAuthController.java new file mode 100644 index 0000000..7e77d71 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/mp/controller/WxoAuthController.java @@ -0,0 +1,68 @@ +package com.rymcu.vertical.wx.mp.controller; + +import com.rymcu.vertical.util.ContextHolderUtils; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.bean.WxJsapiSignature; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.http.URIUtil; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; +import me.chanjar.weixin.mp.bean.result.WxMpUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +/** + * @author ronger + */ +@Controller +@RequestMapping("/wx/oauth/{appId}") +public class WxoAuthController { + + @Resource + private WxMpService wxMpService; + + @Value("${resource.domain}") + private String domain; + + @GetMapping + public String wxAuth(@PathVariable String appId, @RequestParam(name = "redirectUrl") String redirectUrl) { + wxMpService.switchoverTo(appId); + if ("wxa49093339a5a822b".equals(appId)) { + domain = "http://oae.nat300.top/vertical"; + } else { + domain += "/vertical-console"; + } + StringBuilder accessTokenUrl = new StringBuilder(domain).append("/wx/oauth/" + appId + "/getAccessToken?redirectUrl=").append(URIUtil.encodeURIComponent(domain + redirectUrl)); + String oauth2Url = wxMpService.oauth2buildAuthorizationUrl(accessTokenUrl.toString(), WxConsts.OAuth2Scope.SNSAPI_BASE, null); + return "redirect:" + oauth2Url; + } + + @GetMapping("getAccessToken") + public String getAccessToken(@PathVariable String appId, @RequestParam(name = "code") String code, @RequestParam(name = "redirectUrl") String redirectUrl) throws Exception { + wxMpService.switchoverTo(appId); + WxMpOAuth2AccessToken oAuth2AccessToken = wxMpService.oauth2getAccessToken(code); + boolean valid = wxMpService.oauth2validateAccessToken(oAuth2AccessToken); + if (!valid) { + throw new Exception("无权限"); + } + + WxMpUser wxMpUser =wxMpService.getUserService().userInfo(oAuth2AccessToken.getOpenId()); + ContextHolderUtils.getSession2().setAttribute("wxUser", wxMpUser); + return "redirect:" + redirectUrl; + } + + @GetMapping("validJs") + @ResponseBody + public WxJsapiSignature validJs(String url) throws WxErrorException { + return wxMpService.createJsapiSignature(url); + } + + @GetMapping("t") + public String reOauth() { + return "wx/oauth"; + } +} diff --git a/src/main/java/com/rymcu/vertical/wx/open/config/WxOpenProperties.java b/src/main/java/com/rymcu/vertical/wx/open/config/WxOpenProperties.java new file mode 100644 index 0000000..4fcce5d --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/open/config/WxOpenProperties.java @@ -0,0 +1,42 @@ +package com.rymcu.vertical.wx.open.config; + +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.springframework.boot.context.properties.ConfigurationProperties; + + +/** + * @author 007 + */ +@Getter +@Setter +@ConfigurationProperties(prefix = "wx.open") +public class WxOpenProperties { + /** + * 设置微信三方平台的appid + */ + private String componentAppId; + + /** + * 设置微信三方平台的app secret + */ + private String componentSecret; + + /** + * 设置微信三方平台的token + */ + private String componentToken; + + /** + * 设置微信三方平台的EncodingAESKey + */ + private String componentAesKey; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, + ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git a/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenNotifyController.java b/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenNotifyController.java new file mode 100644 index 0000000..3b2e3fe --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenNotifyController.java @@ -0,0 +1,110 @@ +package com.rymcu.vertical.wx.open.controller; + +import com.rymcu.vertical.wx.open.handler.WxOpenServiceHandler; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + * @author 007 + */ +@RestController +@RequestMapping("/notify") +public class WxOpenNotifyController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + @Autowired + protected WxOpenServiceHandler wxOpenService; + + @RequestMapping("/receive_ticket") + public Object receiveTicket(@RequestBody(required = false) String requestBody, @RequestParam("timestamp") String timestamp, + @RequestParam("nonce") String nonce, @RequestParam("signature") String signature, + @RequestParam(name = "encrypt_type", required = false) String encType, + @RequestParam(name = "msg_signature", required = false) String msgSignature) { + this.logger.info( + "\n接收微信请求:[signature=[{}], encType=[{}], msgSignature=[{}]," + + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", + signature, encType, msgSignature, timestamp, nonce, requestBody); + + if (!StringUtils.equalsIgnoreCase("aes", encType) + || !wxOpenService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) { + throw new IllegalArgumentException("非法请求,可能属于伪造的请求!"); + } + + // aes加密的消息 + WxOpenXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedXml(requestBody, + wxOpenService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature); + this.logger.debug("\n消息解密后内容为:\n{} ", inMessage.toString()); + try { + String out = wxOpenService.getWxOpenComponentService().route(inMessage); + this.logger.debug("\n组装回复信息:{}", out); + } catch (WxErrorException e) { + this.logger.error("receive_ticket", e); + } + + + return "success"; + } + + @RequestMapping("{appId}/callback") + public Object callback(@RequestBody(required = false) String requestBody, + @PathVariable("appId") String appId, + @RequestParam("signature") String signature, + @RequestParam("timestamp") String timestamp, + @RequestParam("nonce") String nonce, + @RequestParam("openid") String openid, + @RequestParam("encrypt_type") String encType, + @RequestParam("msg_signature") String msgSignature) { + this.logger.info( + "\n接收微信请求:[appId=[{}], openid=[{}], signature=[{}], encType=[{}], msgSignature=[{}]," + + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", + appId, openid, signature, encType, msgSignature, timestamp, nonce, requestBody); + if (!StringUtils.equalsIgnoreCase("aes", encType) + || !wxOpenService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) { + throw new IllegalArgumentException("非法请求,可能属于伪造的请求!"); + } + + String out = ""; + // aes加密的消息 + WxMpXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedMpXml(requestBody, + wxOpenService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature); + this.logger.debug("\n消息解密后内容为:\n{} ", inMessage.toString()); + // 全网发布测试用例 + if (StringUtils.equalsAnyIgnoreCase(appId)) { + try { + if (StringUtils.equals(inMessage.getMsgType(), "text")) { + if (StringUtils.equals(inMessage.getContent(), "TESTCOMPONENT_MSG_TYPE_TEXT")) { + out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml( + WxMpXmlOutMessage.TEXT().content("TESTCOMPONENT_MSG_TYPE_TEXT_callback") + .fromUser(inMessage.getToUser()) + .toUser(inMessage.getFromUser()) + .build(), + wxOpenService.getWxOpenConfigStorage() + ); + } else if (StringUtils.startsWith(inMessage.getContent(), "QUERY_AUTH_CODE:")) { + String msg = inMessage.getContent().replace("QUERY_AUTH_CODE:", "") + "_from_api"; + WxMpKefuMessage kefuMessage = WxMpKefuMessage.TEXT().content(msg).toUser(inMessage.getFromUser()).build(); + wxOpenService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getKefuService().sendKefuMessage(kefuMessage); + } + } else if (StringUtils.equals(inMessage.getMsgType(), "event")) { + WxMpKefuMessage kefuMessage = WxMpKefuMessage.TEXT().content(inMessage.getEvent() + "from_callback").toUser(inMessage.getFromUser()).build(); + wxOpenService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getKefuService().sendKefuMessage(kefuMessage); + } + } catch (WxErrorException e) { + logger.error("callback", e); + } + }else{ + WxMpXmlOutMessage outMessage = wxOpenService.getWxOpenMessageRouter().route(inMessage, appId); + if(outMessage != null){ + out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml(outMessage, wxOpenService.getWxOpenConfigStorage()); + } + } + return out; + } +} diff --git a/src/main/java/com/rymcu/vertical/wx/open/handler/WxOpenServiceHandler.java b/src/main/java/com/rymcu/vertical/wx/open/handler/WxOpenServiceHandler.java new file mode 100644 index 0000000..e361568 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/open/handler/WxOpenServiceHandler.java @@ -0,0 +1,74 @@ +package com.rymcu.vertical.wx.open.handler; + +import com.rymcu.vertical.core.service.props.DynProps4FilesService; +import com.rymcu.vertical.wx.open.config.WxOpenProperties; +import me.chanjar.weixin.open.api.impl.WxOpenInRedisConfigStorage; +import me.chanjar.weixin.open.api.impl.WxOpenMessageRouter; +import me.chanjar.weixin.open.api.impl.WxOpenServiceImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Service; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; + +/** + * @author ronger + */ +@Service +public class WxOpenServiceHandler extends WxOpenServiceImpl { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + + @Resource + private WxOpenProperties wxOpenProperties; + @Resource + private WxOpenMessageRouter wxOpenMessageRouter; + @Resource + private DynProps4FilesService dynProps4Files; + @Resource + private Environment env; + private static JedisPool pool; + + @PostConstruct + public void init() { + WxOpenInRedisConfigStorage inRedisConfigStorage = new WxOpenInRedisConfigStorage(getJedisPool()); + inRedisConfigStorage.setComponentAppId(wxOpenProperties.getComponentAppId()); + inRedisConfigStorage.setComponentAppSecret(wxOpenProperties.getComponentSecret()); + inRedisConfigStorage.setComponentToken(wxOpenProperties.getComponentToken()); + inRedisConfigStorage.setComponentAesKey(wxOpenProperties.getComponentAesKey()); + setWxOpenConfigStorage(inRedisConfigStorage); + wxOpenMessageRouter = new WxOpenMessageRouter(this); + wxOpenMessageRouter.rule().handler((wxMpXmlMessage, map, wxMpService, wxSessionManager) -> { + logger.info("\n接收到 {} 公众号请求消息,内容:{}", wxMpService.getWxMpConfigStorage().getAppId(), wxMpXmlMessage); + return null; + }).next(); + } + + private JedisPool getJedisPool() { + if (pool == null) { + synchronized (WxOpenServiceHandler.class) { + if (pool == null) { + JedisPoolConfig config = new JedisPoolConfig(); + config.setMaxIdle(dynProps4Files.getInt("REDIS_MAX_IDLE", JedisPoolConfig.DEFAULT_MAX_IDLE)); + config.setMaxTotal(dynProps4Files.getInt("REDIS_MAX_TOTAL", JedisPoolConfig.DEFAULT_MAX_TOTAL)); + config.setMaxWaitMillis(dynProps4Files.getLong("REDIS_MAX_WAIT", JedisPoolConfig.DEFAULT_MAX_WAIT_MILLIS)); + config.setTestOnBorrow(true); + pool = new JedisPool(config, env.getProperty("spring.redis.host"), + dynProps4Files.getInt("REDIS_PORT", 6379), dynProps4Files.getInt( + "REDIS_MAX_WAIT", 1000), dynProps4Files.getProperty("REDIS_PASSWORD", env.getProperty("spring.redis.password"))); + } + } + } + return pool; + } + + public WxOpenMessageRouter getWxOpenMessageRouter() { + return wxOpenMessageRouter; + } +} From a18d3847d849b7b92acacded65a85f9cbc806ee4 Mon Sep 17 00:00:00 2001 From: ronger Date: Thu, 19 Mar 2020 17:47:10 +0800 Subject: [PATCH 07/19] =?UTF-8?q?:sparkles:=20=E5=BE=AE=E4=BF=A1=E5=BC=80?= =?UTF-8?q?=E6=94=BE=E5=B9=B3=E5=8F=B0=E6=9C=8D=E5=8A=A1=E9=9B=86=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 ++ .../open/controller/WxOpenApiController.java | 76 +++++++++++++++++++ .../controller/WxOpenNotifyController.java | 4 +- .../wx/open/handler/WxOpenServiceHandler.java | 29 +++---- 4 files changed, 95 insertions(+), 20 deletions(-) create mode 100644 src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenApiController.java diff --git a/pom.xml b/pom.xml index 5e02b24..6f5f2f0 100644 --- a/pom.xml +++ b/pom.xml @@ -24,6 +24,11 @@ org.springframework.boot spring-boot-starter-data-redis + + redis.clients + jedis + 2.9.3 + org.springframework.boot spring-boot-starter-mail @@ -123,6 +128,7 @@ commons-codec commons-codec + 1.14 io.jsonwebtoken diff --git a/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenApiController.java b/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenApiController.java new file mode 100644 index 0000000..ed14ee3 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenApiController.java @@ -0,0 +1,76 @@ +package com.rymcu.vertical.wx.open.controller; + +import com.rymcu.vertical.wx.open.handler.WxOpenServiceHandler; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerInfoResult; +import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author 007 + */ +@Controller +@RequestMapping("/wx/open/auth") +public class WxOpenApiController { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + @Resource + private WxOpenServiceHandler wxOpenServiceHandler; + + @GetMapping("/goto_auth_url_show") + @ResponseBody + public String gotoPreAuthUrlShow(){ + return "go"; + } + + @GetMapping("/goto_auth_url") + public void gotoPreAuthUrl(HttpServletRequest request, HttpServletResponse response){ + String host = request.getHeader("host"); + String url = "http://"+host+"/vertical-console/wx/open/auth/jump"; + try { + url = wxOpenServiceHandler.getWxOpenComponentService().getPreAuthUrl(url); + // 添加来源,解决302跳转来源丢失的问题 + response.addHeader("Referer", "http://"+host); + response.sendRedirect(url); + } catch (WxErrorException | IOException e) { + logger.error("gotoPreAuthUrl", e); + throw new RuntimeException(e); + } + } + + @GetMapping("/jump") + @ResponseBody + public WxOpenQueryAuthResult jump(@RequestParam("auth_code") String authorizationCode){ + try { + WxOpenQueryAuthResult queryAuthResult = wxOpenServiceHandler.getWxOpenComponentService().getQueryAuth(authorizationCode); + logger.info("getQueryAuth", queryAuthResult); + return queryAuthResult; + } catch (WxErrorException e) { + logger.error("gotoPreAuthUrl", e); + throw new RuntimeException(e); + } + } + + @GetMapping("/get_auth_info") + @ResponseBody + public WxOpenAuthorizerInfoResult getAuthInfo(@RequestParam String appId){ + try { + return wxOpenServiceHandler.getWxOpenComponentService().getAuthorizerInfo(appId); + } catch (WxErrorException e) { + logger.error("getAuthInfo", e); + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenNotifyController.java b/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenNotifyController.java index 3b2e3fe..1b23a91 100644 --- a/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenNotifyController.java +++ b/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenNotifyController.java @@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.*; * @author 007 */ @RestController -@RequestMapping("/notify") +@RequestMapping("/wx/notify") public class WxOpenNotifyController { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired @@ -52,7 +52,7 @@ public class WxOpenNotifyController { return "success"; } - @RequestMapping("{appId}/callback") + @RequestMapping("/{appId}/callback") public Object callback(@RequestBody(required = false) String requestBody, @PathVariable("appId") String appId, @RequestParam("signature") String signature, diff --git a/src/main/java/com/rymcu/vertical/wx/open/handler/WxOpenServiceHandler.java b/src/main/java/com/rymcu/vertical/wx/open/handler/WxOpenServiceHandler.java index e361568..f038c2b 100644 --- a/src/main/java/com/rymcu/vertical/wx/open/handler/WxOpenServiceHandler.java +++ b/src/main/java/com/rymcu/vertical/wx/open/handler/WxOpenServiceHandler.java @@ -1,17 +1,15 @@ package com.rymcu.vertical.wx.open.handler; -import com.rymcu.vertical.core.service.props.DynProps4FilesService; +import com.rymcu.vertical.config.RedisProperties; import com.rymcu.vertical.wx.open.config.WxOpenProperties; import me.chanjar.weixin.open.api.impl.WxOpenInRedisConfigStorage; import me.chanjar.weixin.open.api.impl.WxOpenMessageRouter; import me.chanjar.weixin.open.api.impl.WxOpenServiceImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.core.env.Environment; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.stereotype.Service; -import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; -import redis.clients.jedis.JedisPoolConfig; import javax.annotation.PostConstruct; import javax.annotation.Resource; @@ -20,20 +18,17 @@ import javax.annotation.Resource; * @author ronger */ @Service +@EnableConfigurationProperties({WxOpenProperties.class, RedisProperties.class}) public class WxOpenServiceHandler extends WxOpenServiceImpl { private Logger logger = LoggerFactory.getLogger(getClass()); - @Resource private WxOpenProperties wxOpenProperties; @Resource - private WxOpenMessageRouter wxOpenMessageRouter; - @Resource - private DynProps4FilesService dynProps4Files; - @Resource - private Environment env; + private RedisProperties redisProperties; private static JedisPool pool; + private WxOpenMessageRouter wxOpenMessageRouter; @PostConstruct public void init() { @@ -54,14 +49,12 @@ public class WxOpenServiceHandler extends WxOpenServiceImpl { if (pool == null) { synchronized (WxOpenServiceHandler.class) { if (pool == null) { - JedisPoolConfig config = new JedisPoolConfig(); - config.setMaxIdle(dynProps4Files.getInt("REDIS_MAX_IDLE", JedisPoolConfig.DEFAULT_MAX_IDLE)); - config.setMaxTotal(dynProps4Files.getInt("REDIS_MAX_TOTAL", JedisPoolConfig.DEFAULT_MAX_TOTAL)); - config.setMaxWaitMillis(dynProps4Files.getLong("REDIS_MAX_WAIT", JedisPoolConfig.DEFAULT_MAX_WAIT_MILLIS)); - config.setTestOnBorrow(true); - pool = new JedisPool(config, env.getProperty("spring.redis.host"), - dynProps4Files.getInt("REDIS_PORT", 6379), dynProps4Files.getInt( - "REDIS_MAX_WAIT", 1000), dynProps4Files.getProperty("REDIS_PASSWORD", env.getProperty("spring.redis.password"))); + pool = new JedisPool(redisProperties, redisProperties.getHost(), + redisProperties.getPort(), redisProperties.getConnectionTimeout(), + redisProperties.getSoTimeout(), redisProperties.getPassword(), + redisProperties.getDatabase(), redisProperties.getClientName(), + redisProperties.isSsl(), redisProperties.getSslSocketFactory(), + redisProperties.getSslParameters(), redisProperties.getHostnameVerifier()); } } } From 4736f383ce392451bf7e7f24d5114f8952502e74 Mon Sep 17 00:00:00 2001 From: ronger Date: Fri, 20 Mar 2020 15:02:53 +0800 Subject: [PATCH 08/19] =?UTF-8?q?:sparkles:=20=E5=BE=AE=E4=BF=A1=E5=BC=80?= =?UTF-8?q?=E6=94=BE=E5=B9=B3=E5=8F=B0=E6=9C=8D=E5=8A=A1=E9=9B=86=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 10 -- .../vertical/config/RedisProperties.java | 124 ++++++++++++++++++ .../open/controller/WxOpenApiController.java | 2 + .../controller/WxOpenNotifyController.java | 16 ++- 4 files changed, 138 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/rymcu/vertical/config/RedisProperties.java diff --git a/pom.xml b/pom.xml index 6f5f2f0..bd2ce30 100644 --- a/pom.xml +++ b/pom.xml @@ -175,16 +175,6 @@ jodd-http 5.0.13 - - com.github.binarywang - weixin-java-mp - 3.7.0 - - - com.github.binarywang - weixin-java-miniapp - 3.7.0 - com.github.binarywang weixin-java-open diff --git a/src/main/java/com/rymcu/vertical/config/RedisProperties.java b/src/main/java/com/rymcu/vertical/config/RedisProperties.java new file mode 100644 index 0000000..02ae5d2 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/config/RedisProperties.java @@ -0,0 +1,124 @@ +package com.rymcu.vertical.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import redis.clients.jedis.JedisPoolConfig; +import redis.clients.jedis.Protocol; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocketFactory; + +/** + * @author 007 + */ +@ConfigurationProperties(prefix = "spring.redis") +public class RedisProperties extends JedisPoolConfig { + private String host = Protocol.DEFAULT_HOST; + private int port = Protocol.DEFAULT_PORT; + private String password; + private int database = 1; + private int connectionTimeout = Protocol.DEFAULT_TIMEOUT; + private int soTimeout = Protocol.DEFAULT_TIMEOUT; + private String clientName; + private boolean ssl; + private SSLSocketFactory sslSocketFactory; + private SSLParameters sslParameters; + private HostnameVerifier hostnameVerifier; + + public boolean isSsl() { + return ssl; + } + + public void setSsl(boolean ssl) { + this.ssl = ssl; + } + + public SSLSocketFactory getSslSocketFactory() { + return sslSocketFactory; + } + + public void setSslSocketFactory(SSLSocketFactory sslSocketFactory) { + this.sslSocketFactory = sslSocketFactory; + } + + public SSLParameters getSslParameters() { + return sslParameters; + } + + public void setSslParameters(SSLParameters sslParameters) { + this.sslParameters = sslParameters; + } + + public HostnameVerifier getHostnameVerifier() { + return hostnameVerifier; + } + + public void setHostnameVerifier(HostnameVerifier hostnameVerifier) { + this.hostnameVerifier = hostnameVerifier; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + if (host == null || "".equals(host)) { + host = Protocol.DEFAULT_HOST; + } + this.host = host; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + if ("".equals(password)) { + password = null; + } + this.password = password; + } + + public int getDatabase() { + return database; + } + + public void setDatabase(int database) { + this.database = database; + } + + public String getClientName() { + return clientName; + } + + public void setClientName(String clientName) { + if ("".equals(clientName)) { + clientName = null; + } + this.clientName = clientName; + } + + public int getConnectionTimeout() { + return connectionTimeout; + } + + public void setConnectionTimeout(int connectionTimeout) { + this.connectionTimeout = connectionTimeout; + } + + public int getSoTimeout() { + return soTimeout; + } + + public void setSoTimeout(int soTimeout) { + this.soTimeout = soTimeout; + } +} diff --git a/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenApiController.java b/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenApiController.java index ed14ee3..3473a02 100644 --- a/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenApiController.java +++ b/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenApiController.java @@ -37,6 +37,8 @@ public class WxOpenApiController { @GetMapping("/goto_auth_url") public void gotoPreAuthUrl(HttpServletRequest request, HttpServletResponse response){ + System.out.println("===================================Host:"); + System.out.println(request.getHeader("host")); String host = request.getHeader("host"); String url = "http://"+host+"/vertical-console/wx/open/auth/jump"; try { diff --git a/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenNotifyController.java b/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenNotifyController.java index 1b23a91..d7b2784 100644 --- a/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenNotifyController.java +++ b/src/main/java/com/rymcu/vertical/wx/open/controller/WxOpenNotifyController.java @@ -1,6 +1,7 @@ package com.rymcu.vertical.wx.open.controller; import com.rymcu.vertical.wx.open.handler.WxOpenServiceHandler; +import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; @@ -22,6 +23,13 @@ public class WxOpenNotifyController { @Autowired protected WxOpenServiceHandler wxOpenService; + /**全网发布官方测试小程序 AppId*/ + private final static String testMiniProgramAppId = "wxd101a85aa106f53e"; + /**全网发布官方测试公众号 AppId*/ + private final static String testMpAppId = "wx570bc396a51b8ff8"; + private final static String TESTCOMPONENT_MSG_TYPE_TEXT = "TESTCOMPONENT_MSG_TYPE_TEXT"; + private final static String TESTCOMPONENT_MSG_TYPE_TEXT_callback = "TESTCOMPONENT_MSG_TYPE_TEXT_callback"; + @RequestMapping("/receive_ticket") public Object receiveTicket(@RequestBody(required = false) String requestBody, @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce, @RequestParam("signature") String signature, @@ -76,12 +84,12 @@ public class WxOpenNotifyController { wxOpenService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature); this.logger.debug("\n消息解密后内容为:\n{} ", inMessage.toString()); // 全网发布测试用例 - if (StringUtils.equalsAnyIgnoreCase(appId)) { + if (StringUtils.equalsAnyIgnoreCase(appId, testMiniProgramAppId, testMpAppId)) { try { - if (StringUtils.equals(inMessage.getMsgType(), "text")) { - if (StringUtils.equals(inMessage.getContent(), "TESTCOMPONENT_MSG_TYPE_TEXT")) { + if (StringUtils.equals(inMessage.getMsgType(), WxConsts.XmlMsgType.TEXT)) { + if (StringUtils.equals(inMessage.getContent(), TESTCOMPONENT_MSG_TYPE_TEXT)) { out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml( - WxMpXmlOutMessage.TEXT().content("TESTCOMPONENT_MSG_TYPE_TEXT_callback") + WxMpXmlOutMessage.TEXT().content(TESTCOMPONENT_MSG_TYPE_TEXT_callback) .fromUser(inMessage.getToUser()) .toUser(inMessage.getFromUser()) .build(), From 33d7856bd5367363b4c14f5bfc5bec0e51c4ee5b Mon Sep 17 00:00:00 2001 From: x ronger Date: Tue, 24 Mar 2020 01:05:03 +0800 Subject: [PATCH 09/19] =?UTF-8?q?:art:=20=E4=B8=93=E9=A2=98=E9=A1=B5?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/rymcu/vertical/service/ArticleService.java | 4 ++-- .../vertical/service/impl/ArticleServiceImpl.java | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/rymcu/vertical/service/ArticleService.java b/src/main/java/com/rymcu/vertical/service/ArticleService.java index 541bf57..30325a3 100644 --- a/src/main/java/com/rymcu/vertical/service/ArticleService.java +++ b/src/main/java/com/rymcu/vertical/service/ArticleService.java @@ -26,10 +26,10 @@ public interface ArticleService extends Service
{ /** * 查询文章详情信息 * @param id - * @param i + * @param type * @return * */ - ArticleDTO findArticleDTOById(Integer id, int i); + ArticleDTO findArticleDTOById(Integer id, Integer type); /** * 查询主题下文章列表 diff --git a/src/main/java/com/rymcu/vertical/service/impl/ArticleServiceImpl.java b/src/main/java/com/rymcu/vertical/service/impl/ArticleServiceImpl.java index f451556..802c65a 100644 --- a/src/main/java/com/rymcu/vertical/service/impl/ArticleServiceImpl.java +++ b/src/main/java/com/rymcu/vertical/service/impl/ArticleServiceImpl.java @@ -66,7 +66,7 @@ public class ArticleServiceImpl extends AbstractService
implements Arti } @Override - public ArticleDTO findArticleDTOById(Integer id, int type) { + public ArticleDTO findArticleDTOById(Integer id, Integer type) { ArticleDTO articleDTO = articleMapper.selectArticleDTOById(id,type); if (articleDTO == null) { return null; @@ -78,6 +78,9 @@ public class ArticleServiceImpl extends AbstractService
implements Arti @Override public List findArticlesByTopicUri(String name) { List articleDTOS = articleMapper.selectArticlesByTopicUri(name); + articleDTOS.forEach(articleDTO -> { + genArticle(articleDTO,0); + }); return articleDTOS; } @@ -266,16 +269,14 @@ public class ArticleServiceImpl extends AbstractService
implements Arti article.setTimeAgo(Utils.getTimeAgo(article.getUpdatedTime())); List tags = articleMapper.selectTags(article.getIdArticle()); article.setTags(tags); - if(type == 1){ - ArticleContent articleContent = articleMapper.selectArticleContent(article.getIdArticle()); + ArticleContent articleContent = articleMapper.selectArticleContent(article.getIdArticle()); + if (type == 1){ article.setArticleContent(articleContent.getArticleContentHtml()); - } else if(type == 2){ - ArticleContent articleContent = articleMapper.selectArticleContent(article.getIdArticle()); + } else if (type == 2) { article.setArticleContent(articleContent.getArticleContent()); } if(StringUtils.isBlank(article.getArticlePreviewContent())){ - ArticleContent articleContent = articleMapper.selectArticleContent(article.getIdArticle()); Integer length = articleContent.getArticleContentHtml().length(); if(length > MAX_PREVIEW){ length = 200; From 4cd5f99898813b90dcc9efda01f918892f077181 Mon Sep 17 00:00:00 2001 From: x ronger Date: Tue, 24 Mar 2020 01:07:05 +0800 Subject: [PATCH 10/19] =?UTF-8?q?:art:=20=E6=88=91=E7=9A=84=E8=8D=89?= =?UTF-8?q?=E7=A8=BF=E5=8A=9F=E8=83=BD=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rymcu/vertical/web/api/article/ArticleController.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/rymcu/vertical/web/api/article/ArticleController.java b/src/main/java/com/rymcu/vertical/web/api/article/ArticleController.java index 8fa3f41..13aab2c 100644 --- a/src/main/java/com/rymcu/vertical/web/api/article/ArticleController.java +++ b/src/main/java/com/rymcu/vertical/web/api/article/ArticleController.java @@ -31,11 +31,9 @@ public class ArticleController { @Resource private CommentService commentService; - - @GetMapping("/detail/{id}") - public GlobalResult> detail(@PathVariable Integer id){ - ArticleDTO articleDTO = articleService.findArticleDTOById(id,2); + public GlobalResult> detail(@PathVariable Integer id, @RequestParam(defaultValue = "2") Integer type){ + ArticleDTO articleDTO = articleService.findArticleDTOById(id,type); Map map = new HashMap<>(1); map.put("article", articleDTO); return GlobalResultGenerator.genSuccessResult(map); From 98d3ee1ce81650500c15efffa29fffa4d4badee6 Mon Sep 17 00:00:00 2001 From: ronger Date: Fri, 27 Mar 2020 15:57:33 +0800 Subject: [PATCH 11/19] =?UTF-8?q?:sparkles:=20=E5=8F=91=E5=B8=83=E6=96=87?= =?UTF-8?q?=E7=AB=A0=E7=95=8C=E9=9D=A2=E5=8A=A0=E8=BD=BD=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/rymcu/vertical/dto/LabelModel.java | 17 +++ .../com/rymcu/vertical/mapper/TagMapper.java | 8 + .../rymcu/vertical/service/TagService.java | 8 + .../vertical/service/impl/TagServiceImpl.java | 15 ++ .../com/rymcu/vertical/util/CacheUtils.java | 139 ++++++++++++++++++ .../vertical/web/api/tag/TagController.java | 11 ++ src/main/java/mapper/TagMapper.xml | 7 + 7 files changed, 205 insertions(+) create mode 100644 src/main/java/com/rymcu/vertical/dto/LabelModel.java create mode 100644 src/main/java/com/rymcu/vertical/util/CacheUtils.java diff --git a/src/main/java/com/rymcu/vertical/dto/LabelModel.java b/src/main/java/com/rymcu/vertical/dto/LabelModel.java new file mode 100644 index 0000000..ed70e92 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/dto/LabelModel.java @@ -0,0 +1,17 @@ +package com.rymcu.vertical.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author ronger + */ +@Data +public class LabelModel implements Serializable { + + private String label; + + private String value; + +} diff --git a/src/main/java/com/rymcu/vertical/mapper/TagMapper.java b/src/main/java/com/rymcu/vertical/mapper/TagMapper.java index dcd8d30..ed4fbe2 100644 --- a/src/main/java/com/rymcu/vertical/mapper/TagMapper.java +++ b/src/main/java/com/rymcu/vertical/mapper/TagMapper.java @@ -1,9 +1,12 @@ package com.rymcu.vertical.mapper; import com.rymcu.vertical.core.mapper.Mapper; +import com.rymcu.vertical.dto.LabelModel; import com.rymcu.vertical.entity.Tag; import org.apache.ibatis.annotations.Param; +import java.util.List; + public interface TagMapper extends Mapper { Integer insertTagArticle(@Param("idTag") Integer idTag, @Param("idArticle") Integer idArticle); @@ -16,4 +19,9 @@ public interface TagMapper extends Mapper { Integer deleteUnusedTag(); Integer update(@Param("idTag") Integer idTag, @Param("tagUri") String tagUri, @Param("tagIconPath") String tagIconPath, @Param("tagStatus") String tagStatus, @Param("tagDescription") String tagDescription, @Param("tagReservation") String tagReservation); + + /** + * @return + */ + List selectTagLabels(); } diff --git a/src/main/java/com/rymcu/vertical/service/TagService.java b/src/main/java/com/rymcu/vertical/service/TagService.java index 7c0f4c4..6664bbb 100644 --- a/src/main/java/com/rymcu/vertical/service/TagService.java +++ b/src/main/java/com/rymcu/vertical/service/TagService.java @@ -1,11 +1,13 @@ package com.rymcu.vertical.service; import com.rymcu.vertical.core.service.Service; +import com.rymcu.vertical.dto.LabelModel; import com.rymcu.vertical.entity.Article; import com.rymcu.vertical.entity.Tag; import com.rymcu.vertical.web.api.exception.BaseApiException; import java.io.UnsupportedEncodingException; +import java.util.List; import java.util.Map; /** @@ -34,4 +36,10 @@ public interface TagService extends Service { * @return */ Map saveTag(Tag tag); + + /** + * 获取标签列表 + * @return + */ + List findTagLabels(); } diff --git a/src/main/java/com/rymcu/vertical/service/impl/TagServiceImpl.java b/src/main/java/com/rymcu/vertical/service/impl/TagServiceImpl.java index d58eed3..16b25fd 100644 --- a/src/main/java/com/rymcu/vertical/service/impl/TagServiceImpl.java +++ b/src/main/java/com/rymcu/vertical/service/impl/TagServiceImpl.java @@ -1,13 +1,16 @@ package com.rymcu.vertical.service.impl; import com.rymcu.vertical.core.service.AbstractService; +import com.rymcu.vertical.core.service.redis.RedisService; import com.rymcu.vertical.dto.ArticleTagDTO; +import com.rymcu.vertical.dto.LabelModel; import com.rymcu.vertical.entity.Article; import com.rymcu.vertical.entity.Tag; import com.rymcu.vertical.entity.User; import com.rymcu.vertical.mapper.ArticleMapper; import com.rymcu.vertical.mapper.TagMapper; import com.rymcu.vertical.service.TagService; +import com.rymcu.vertical.util.CacheUtils; import com.rymcu.vertical.util.UserUtils; import com.rymcu.vertical.web.api.exception.BaseApiException; import org.apache.commons.lang.StringUtils; @@ -33,6 +36,8 @@ public class TagServiceImpl extends AbstractService implements TagService { private TagMapper tagMapper; @Resource private ArticleMapper articleMapper; + @Resource + private RedisService redisService; @Override @Transactional(rollbackFor = { UnsupportedEncodingException.class,BaseApiException.class }) @@ -139,4 +144,14 @@ public class TagServiceImpl extends AbstractService implements TagService { } return map; } + + @Override + public List findTagLabels() { + List list = (List) CacheUtils.get("tags"); + if (list == null) { + list = tagMapper.selectTagLabels(); + CacheUtils.put("tags", list); + } + return list; + } } diff --git a/src/main/java/com/rymcu/vertical/util/CacheUtils.java b/src/main/java/com/rymcu/vertical/util/CacheUtils.java new file mode 100644 index 0000000..c532cd7 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/util/CacheUtils.java @@ -0,0 +1,139 @@ +package com.rymcu.vertical.util; + +import org.apache.shiro.cache.Cache; +import org.apache.shiro.cache.CacheManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Iterator; +import java.util.Set; + +/** + * Cache工具类 + */ +public class CacheUtils { + + private static Logger logger = LoggerFactory.getLogger(CacheUtils.class); + private static CacheManager cacheManager = SpringContextHolder.getBean(CacheManager.class); + + private static final String SYS_CACHE = "system"; + + /** + * 获取SYS_CACHE缓存 + * @param key + * @return + */ + public static Object get(String key) { + return get(SYS_CACHE, key); + } + + /** + * 获取SYS_CACHE缓存 + * @param key + * @param defaultValue + * @return + */ + public static Object get(String key, Object defaultValue) { + Object value = get(key); + return value != null ? value : defaultValue; + } + + /** + * 写入SYS_CACHE缓存 + * @param key + * @return + */ + public static void put(String key, Object value) { + put(SYS_CACHE, key, value); + } + + /** + * 从SYS_CACHE缓存中移除 + * @param key + * @return + */ + public static void remove(String key) { + remove(SYS_CACHE, key); + } + + /** + * 获取缓存 + * @param cacheName + * @param key + * @return + */ + public static Object get(String cacheName, String key) { + return getCache(cacheName).get(getKey(key)); + } + + /** + * 获取缓存 + * @param cacheName + * @param key + * @param defaultValue + * @return + */ + public static Object get(String cacheName, String key, Object defaultValue) { + Object value = get(cacheName, getKey(key)); + return value != null ? value : defaultValue; + } + + /** + * 写入缓存 + * @param cacheName + * @param key + * @param value + */ + public static void put(String cacheName, String key, Object value) { + getCache(cacheName).put(getKey(key), value); + } + + /** + * 从缓存中移除 + * @param cacheName + * @param key + */ + public static void remove(String cacheName, String key) { + getCache(cacheName).remove(getKey(key)); + } + + /** + * 从缓存中移除所有 + * @param cacheName + */ + public static void removeAll(String cacheName) { + Cache cache = getCache(cacheName); + Set keys = cache.keys(); + for (Iterator it = keys.iterator(); it.hasNext();){ + cache.remove(it.next()); + } + logger.info("清理缓存: {} => {}", cacheName, keys); + } + + /** + * 获取缓存键名,多数据源下增加数据源名称前缀 + * @param key + * @return + */ + private static String getKey(String key){ +// String dsName = DataSourceHolder.getDataSourceName(); +// if (StringUtils.isNotBlank(dsName)){ +// return dsName + "_" + key; +// } + return key; + } + + /** + * 获得一个Cache,没有则显示日志。 + * @param cacheName + * @return + */ + private static Cache getCache(String cacheName){ + Cache cache = cacheManager.getCache(cacheName); + if (cache == null){ + throw new RuntimeException("当前系统中没有定义“"+cacheName+"”这个缓存。"); + } + return cache; + } + +} diff --git a/src/main/java/com/rymcu/vertical/web/api/tag/TagController.java b/src/main/java/com/rymcu/vertical/web/api/tag/TagController.java index 700bac3..406645d 100644 --- a/src/main/java/com/rymcu/vertical/web/api/tag/TagController.java +++ b/src/main/java/com/rymcu/vertical/web/api/tag/TagController.java @@ -5,7 +5,10 @@ import com.github.pagehelper.PageInfo; import com.rymcu.vertical.core.result.GlobalResult; import com.rymcu.vertical.core.result.GlobalResultGenerator; import com.rymcu.vertical.dto.ArticleDTO; +import com.rymcu.vertical.dto.LabelModel; +import com.rymcu.vertical.entity.Tag; import com.rymcu.vertical.service.ArticleService; +import com.rymcu.vertical.service.TagService; import com.rymcu.vertical.util.Utils; import org.springframework.web.bind.annotation.*; @@ -22,6 +25,8 @@ public class TagController { @Resource private ArticleService articleService; + @Resource + private TagService tagService; @GetMapping("/{name}") public GlobalResult articles(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "10") Integer rows, @PathVariable String name){ @@ -31,4 +36,10 @@ public class TagController { Map map = Utils.getArticlesGlobalResult(pageInfo); return GlobalResultGenerator.genSuccessResult(map); } + + @GetMapping("/tags") + public GlobalResult tags() { + List list = tagService.findTagLabels(); + return GlobalResultGenerator.genSuccessResult(list); + } } diff --git a/src/main/java/mapper/TagMapper.xml b/src/main/java/mapper/TagMapper.xml index 4f4d437..6425fc0 100644 --- a/src/main/java/mapper/TagMapper.xml +++ b/src/main/java/mapper/TagMapper.xml @@ -18,6 +18,10 @@ + + + + insert into vertical_tag_article (id_tag,id_article,created_time,updated_time) values (#{idTag},#{idArticle},sysdate(),sysdate()) @@ -36,4 +40,7 @@ + \ No newline at end of file From 218b4a06a7fd97d2b0046ee43177397fe4cb62fe Mon Sep 17 00:00:00 2001 From: ronger Date: Fri, 27 Mar 2020 16:15:58 +0800 Subject: [PATCH 12/19] =?UTF-8?q?:bug:=20=E9=82=AE=E4=BB=B6=E5=8F=91?= =?UTF-8?q?=E9=80=81=E5=A4=B1=E8=B4=A5=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/rymcu/vertical/service/impl/JavaMailServiceImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/rymcu/vertical/service/impl/JavaMailServiceImpl.java b/src/main/java/com/rymcu/vertical/service/impl/JavaMailServiceImpl.java index c930885..7c3bc57 100644 --- a/src/main/java/com/rymcu/vertical/service/impl/JavaMailServiceImpl.java +++ b/src/main/java/com/rymcu/vertical/service/impl/JavaMailServiceImpl.java @@ -63,7 +63,8 @@ public class JavaMailServiceImpl implements JavaMailService { private Integer sendCode(String to, Integer type) throws MessagingException { Properties props = new Properties(); // 表示SMTP发送邮件,需要进行身份验证 - props.put("mail.smtp.auth", "true"); + props.put("mail.smtp.auth", true); + props.put("mail.smtp.ssl.enable", true); props.put("mail.smtp.host", SERVER_HOST); props.put("mail.smtp.port", SERVER_PORT); // 如果使用ssl,则去掉使用25端口的配置,进行如下配置, From b65bd06797e9cec8acdb59ab0f8761fc09915186 Mon Sep 17 00:00:00 2001 From: ronger Date: Fri, 27 Mar 2020 16:20:19 +0800 Subject: [PATCH 13/19] =?UTF-8?q?:art:=20=E4=BB=A3=E7=A0=81=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/rymcu/vertical/dto/UserDTO.java | 3 +++ .../rymcu/vertical/dto/UserRegisterInfoDTO.java | 17 +++++++++++++++++ .../web/api/common/CommonApiController.java | 13 +++++++------ 3 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/rymcu/vertical/dto/UserRegisterInfoDTO.java diff --git a/src/main/java/com/rymcu/vertical/dto/UserDTO.java b/src/main/java/com/rymcu/vertical/dto/UserDTO.java index d8b5b29..b3248bd 100644 --- a/src/main/java/com/rymcu/vertical/dto/UserDTO.java +++ b/src/main/java/com/rymcu/vertical/dto/UserDTO.java @@ -2,6 +2,9 @@ package com.rymcu.vertical.dto; import lombok.Data; +/** + * @author ronger + */ @Data public class UserDTO { diff --git a/src/main/java/com/rymcu/vertical/dto/UserRegisterInfoDTO.java b/src/main/java/com/rymcu/vertical/dto/UserRegisterInfoDTO.java new file mode 100644 index 0000000..740fa08 --- /dev/null +++ b/src/main/java/com/rymcu/vertical/dto/UserRegisterInfoDTO.java @@ -0,0 +1,17 @@ +package com.rymcu.vertical.dto; + +import lombok.Data; + +/** + * @author ronger + */ +@Data +public class UserRegisterInfoDTO { + + private String email; + + private String password; + + private String code; + +} diff --git a/src/main/java/com/rymcu/vertical/web/api/common/CommonApiController.java b/src/main/java/com/rymcu/vertical/web/api/common/CommonApiController.java index 789481e..b26ea25 100644 --- a/src/main/java/com/rymcu/vertical/web/api/common/CommonApiController.java +++ b/src/main/java/com/rymcu/vertical/web/api/common/CommonApiController.java @@ -9,6 +9,7 @@ import com.rymcu.vertical.core.service.log.annotation.VisitLogger; import com.rymcu.vertical.dto.ArticleDTO; import com.rymcu.vertical.dto.ForgetPasswordDTO; import com.rymcu.vertical.dto.TokenUser; +import com.rymcu.vertical.dto.UserRegisterInfoDTO; import com.rymcu.vertical.entity.User; import com.rymcu.vertical.service.ArticleService; import com.rymcu.vertical.service.JavaMailService; @@ -39,7 +40,7 @@ public class CommonApiController { private ArticleService articleService; @ApiOperation(value = "获取邮件验证码") - @PostMapping("/get-email-code") + @GetMapping("/get-email-code") public GlobalResult> getEmailCode(@RequestParam("email") String email) throws MessagingException { Map map = new HashMap<>(1); map.put("message",GlobalResultMessage.SEND_SUCCESS.getMessage()); @@ -56,7 +57,7 @@ public class CommonApiController { } @ApiOperation(value = "获取找回密码邮件") - @PostMapping("/get-forget-password-email") + @GetMapping("/get-forget-password-email") public GlobalResult> getForgetPasswordEmail(@RequestParam("email") String email) throws MessagingException { Map map = new HashMap<>(1); map.put("message",GlobalResultMessage.SEND_SUCCESS.getMessage()); @@ -73,14 +74,14 @@ public class CommonApiController { } @PostMapping("/register") - public GlobalResult register(@RequestParam("email") String email, @RequestParam("password") String password, @RequestParam("code") String code){ - Map map = userService.register(email,password,code); + public GlobalResult register(@RequestBody UserRegisterInfoDTO registerInfo){ + Map map = userService.register(registerInfo.getEmail(), registerInfo.getPassword(), registerInfo.getCode()); return GlobalResultGenerator.genSuccessResult(map); } @PostMapping("/login") - public GlobalResult login(@RequestParam("account") String account, @RequestParam("password") String password){ - Map map = userService.login(account,password); + public GlobalResult login(@RequestBody User user){ + Map map = userService.login(user.getAccount(), user.getPassword()); return GlobalResultGenerator.genSuccessResult(map); } From 005c7f0189387812cdaabce80a138ecb1dba1282 Mon Sep 17 00:00:00 2001 From: ronger Date: Fri, 27 Mar 2020 16:50:55 +0800 Subject: [PATCH 14/19] =?UTF-8?q?:art:=20=E7=94=A8=E6=88=B7=E4=B8=BB?= =?UTF-8?q?=E9=A1=B5=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/rymcu/vertical/dto/UserDTO.java | 2 ++ src/main/java/mapper/UserMapper.xml | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/rymcu/vertical/dto/UserDTO.java b/src/main/java/com/rymcu/vertical/dto/UserDTO.java index b3248bd..fa6c87f 100644 --- a/src/main/java/com/rymcu/vertical/dto/UserDTO.java +++ b/src/main/java/com/rymcu/vertical/dto/UserDTO.java @@ -17,4 +17,6 @@ public class UserDTO { private String avatarUrl; private String nickname; + + private String signature; } diff --git a/src/main/java/mapper/UserMapper.xml b/src/main/java/mapper/UserMapper.xml index ea2ab1a..398908e 100644 --- a/src/main/java/mapper/UserMapper.xml +++ b/src/main/java/mapper/UserMapper.xml @@ -39,6 +39,7 @@ + insert into vertical_user_role (id_user,id_role,created_time) values (#{idUser},#{idRole},sysdate()) @@ -67,7 +68,7 @@ select id, nickname, sex, avatar_type, avatar_url, email, phone, account, status, signature, last_login_time from vertical_user where account = #{account}