🔥 删除微信相关文件
This commit is contained in:
parent
659c1b7166
commit
605862adbd
5
pom.xml
5
pom.xml
@ -175,11 +175,6 @@
|
||||
<artifactId>jodd-http</artifactId>
|
||||
<version>5.0.13</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-open</artifactId>
|
||||
<version>3.7.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -1,17 +0,0 @@
|
||||
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);
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
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<WxMpProperties.MpConfig> 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;
|
||||
}
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
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<MpConfig> 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);
|
||||
}
|
||||
}
|
@ -1,188 +0,0 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 自定义菜单创建接口
|
||||
* 详情请见: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
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 自定义菜单创建接口
|
||||
* 详情请见: 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
|
||||
* </pre>
|
||||
*
|
||||
* @return 如果是个性化菜单,则返回menuid,否则返回null
|
||||
*/
|
||||
@PostMapping("/createByJson")
|
||||
public String menuCreate(@PathVariable String appId, @RequestBody String json) throws WxErrorException {
|
||||
return this.wxService.switchoverTo(appId).getMenuService().menuCreate(json);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 自定义菜单删除接口
|
||||
* 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141015&token=&lang=zh_CN
|
||||
* </pre>
|
||||
*/
|
||||
@GetMapping("/delete")
|
||||
public void menuDelete(@PathVariable String appId) throws WxErrorException {
|
||||
this.wxService.switchoverTo(appId).getMenuService().menuDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 删除个性化菜单接口
|
||||
* 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN
|
||||
* </pre>
|
||||
*
|
||||
* @param menuId 个性化菜单的menuid
|
||||
*/
|
||||
@GetMapping("/delete/{menuId}")
|
||||
public void menuDelete(@PathVariable String appId, @PathVariable String menuId) throws WxErrorException {
|
||||
this.wxService.switchoverTo(appId).getMenuService().menuDelete(menuId);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 自定义菜单查询接口
|
||||
* 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141014&token=&lang=zh_CN
|
||||
* </pre>
|
||||
*/
|
||||
@GetMapping("/get")
|
||||
public WxMpMenu menuGet(@PathVariable String appId) throws WxErrorException {
|
||||
return this.wxService.switchoverTo(appId).getMenuService().menuGet();
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 测试个性化菜单匹配结果
|
||||
* 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 获取自定义菜单配置接口
|
||||
* 本接口将会提供公众号当前使用的自定义菜单的配置,如果公众号是通过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
|
||||
* </pre>
|
||||
*/
|
||||
@GetMapping("/getSelfMenuInfo")
|
||||
public WxMpGetSelfMenuInfoResult getSelfMenuInfo(@PathVariable String appId) throws WxErrorException {
|
||||
return this.wxService.switchoverTo(appId).getMenuService().getSelfMenuInfo();
|
||||
}
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
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";
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
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";
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 出错页面控制器
|
||||
* Created by Binary Wang on 2018/8/25.
|
||||
* </pre>
|
||||
*
|
||||
* @author <a href="https://github.com/binarywang">Binary Wang</a>
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/error")
|
||||
public class ErrorController {
|
||||
|
||||
@GetMapping(value = "/404")
|
||||
public String error404() {
|
||||
return "error";
|
||||
}
|
||||
|
||||
@GetMapping(value = "/500")
|
||||
public String error500() {
|
||||
return "error";
|
||||
}
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 配置错误状态与对应访问路径
|
||||
* Created by Binary Wang on 2018/8/25.
|
||||
* </pre>
|
||||
*
|
||||
* @author <a href="https://github.com/binarywang">Binary Wang</a>
|
||||
*/
|
||||
@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")
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
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());
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
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<String, Object> context, WxMpService wxMpService,
|
||||
WxSessionManager sessionManager) {
|
||||
//TODO 对会话做处理
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
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<String, Object> context, WxMpService wxMpService,
|
||||
WxSessionManager sessionManager) {
|
||||
if (wxMessage.getMsgType().equals(XmlMsgType.LOCATION)) {
|
||||
//TODO 接收处理用户发送的地理位置消息
|
||||
try {
|
||||
String content = "感谢反馈,您的的地理位置已收到!";
|
||||
return new TextBuilder().build(content, wxMessage, null);
|
||||
} catch (Exception e) {
|
||||
this.logger.error("位置消息接收处理失败", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//上报地理位置事件
|
||||
this.logger.info("上报地理位置,纬度 : {},经度 : {},精度 : {}",
|
||||
wxMessage.getLatitude(), wxMessage.getLongitude(), String.valueOf(wxMessage.getPrecision()));
|
||||
|
||||
//TODO 可以将用户地理位置信息保存到本地数据库,以便以后使用
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
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<String, Object> context, WxMpService wxMpService,
|
||||
WxSessionManager sessionManager) {
|
||||
this.logger.info("\n接收到请求消息,内容:{}", JsonUtils.toJson(wxMessage));
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
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<String, Object> 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();
|
||||
}
|
||||
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
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<String, Object> 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);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
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<String, Object> context, WxMpService wxMpService,
|
||||
WxSessionManager sessionManager) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
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<String, Object> map,
|
||||
WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException {
|
||||
// 扫码事件处理
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
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<String, Object> context, WxMpService wxMpService,
|
||||
WxSessionManager sessionManager) {
|
||||
// TODO 处理门店审核事件
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
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<String, Object> 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;
|
||||
}
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
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<String, Object> context, WxMpService wxMpService,
|
||||
WxSessionManager sessionManager) {
|
||||
String openId = wxMessage.getFromUser();
|
||||
this.logger.info("取消关注用户 OPENID: " + openId);
|
||||
// TODO 可以更新本地数据库为取消关注状态
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
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 <a href="https://github.com/007gzs">007</a>
|
||||
*/
|
||||
@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);
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
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 <a href="https://github.com/007gzs">007</a>
|
||||
*/
|
||||
@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 "<a href='goto_auth_url'>go</a>";
|
||||
}
|
||||
|
||||
@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 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,118 +0,0 @@
|
||||
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;
|
||||
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 <a href="https://github.com/007gzs">007</a>
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/wx/notify")
|
||||
public class WxOpenNotifyController {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
@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,
|
||||
@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, testMiniProgramAppId, testMpAppId)) {
|
||||
try {
|
||||
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)
|
||||
.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;
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package com.rymcu.vertical.wx.open.handler;
|
||||
|
||||
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.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.stereotype.Service;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
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 RedisProperties redisProperties;
|
||||
private static JedisPool pool;
|
||||
private WxOpenMessageRouter wxOpenMessageRouter;
|
||||
|
||||
@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) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
return pool;
|
||||
}
|
||||
|
||||
public WxOpenMessageRouter getWxOpenMessageRouter() {
|
||||
return wxOpenMessageRouter;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user