yshop1.9.1,WxJava升级到3.6,微信公众号服务配置重构,修复后台配置公众号API端必须要重启才能生效的问题
This commit is contained in:
@ -1 +1 @@
|
|||||||
nohup java -jar yshop-api-1.8.jar --spring.profiles.active=prod &
|
nohup java -jar yshop-api-1.9.jar --spring.profiles.active=prod &
|
@ -1,4 +1,4 @@
|
|||||||
PID=$(ps -ef | grep yshop-api-1.8.jar | grep -v grep | awk '{ print $2 }')
|
PID=$(ps -ef | grep yshop-api-1.9.jar | grep -v grep | awk '{ print $2 }')
|
||||||
if [ -z "$PID" ];then
|
if [ -z "$PID" ];then
|
||||||
echo Application is already stopped
|
echo Application is already stopped
|
||||||
else
|
else
|
||||||
|
@ -1425,8 +1425,8 @@ public class YxStoreOrderServiceImpl extends BaseServiceImpl<YxStoreOrderMapper,
|
|||||||
|
|
||||||
|
|
||||||
//使用MQ延时消息
|
//使用MQ延时消息
|
||||||
mqProducer.sendMsg("yshop-topic",storeOrder.getId().toString());
|
//mqProducer.sendMsg("yshop-topic",storeOrder.getId().toString());
|
||||||
log.info("投递延时订单id: [{}]:", storeOrder.getId());
|
//log.info("投递延时订单id: [{}]:", storeOrder.getId());
|
||||||
|
|
||||||
return storeOrder;
|
return storeOrder;
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import co.yixiang.modules.user.entity.YxWechatUser;
|
|||||||
import co.yixiang.modules.user.service.YxUserService;
|
import co.yixiang.modules.user.service.YxUserService;
|
||||||
import co.yixiang.modules.user.service.YxWechatUserService;
|
import co.yixiang.modules.user.service.YxWechatUserService;
|
||||||
import co.yixiang.modules.user.web.vo.YxUserQueryVo;
|
import co.yixiang.modules.user.web.vo.YxUserQueryVo;
|
||||||
|
import co.yixiang.mp.config.WxMpConfiguration;
|
||||||
import co.yixiang.utils.OrderUtil;
|
import co.yixiang.utils.OrderUtil;
|
||||||
import co.yixiang.utils.RedisUtil;
|
import co.yixiang.utils.RedisUtil;
|
||||||
import co.yixiang.utils.RedisUtils;
|
import co.yixiang.utils.RedisUtils;
|
||||||
@ -85,7 +86,6 @@ public class AuthController {
|
|||||||
private final AuthenticationManagerBuilder authenticationManagerBuilder;
|
private final AuthenticationManagerBuilder authenticationManagerBuilder;
|
||||||
private final YxUserService userService;
|
private final YxUserService userService;
|
||||||
private final PasswordEncoder passwordEncoder;
|
private final PasswordEncoder passwordEncoder;
|
||||||
private final WxMpService wxService;
|
|
||||||
private final YxWechatUserService wechatUserService;
|
private final YxWechatUserService wechatUserService;
|
||||||
private final WxMaService wxMaService;
|
private final WxMaService wxMaService;
|
||||||
private final NotifyService notifyService;
|
private final NotifyService notifyService;
|
||||||
@ -95,7 +95,7 @@ public class AuthController {
|
|||||||
OnlineUserService onlineUserService, TokenProvider tokenProvider,
|
OnlineUserService onlineUserService, TokenProvider tokenProvider,
|
||||||
AuthenticationManagerBuilder authenticationManagerBuilder,
|
AuthenticationManagerBuilder authenticationManagerBuilder,
|
||||||
YxUserService userService, PasswordEncoder passwordEncoder,
|
YxUserService userService, PasswordEncoder passwordEncoder,
|
||||||
WxMpService wxService, YxWechatUserService wechatUserService,
|
YxWechatUserService wechatUserService,
|
||||||
WxMaService wxMaService,NotifyService notifyService) {
|
WxMaService wxMaService,NotifyService notifyService) {
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
this.redisUtils = redisUtils;
|
this.redisUtils = redisUtils;
|
||||||
@ -105,7 +105,6 @@ public class AuthController {
|
|||||||
this.authenticationManagerBuilder = authenticationManagerBuilder;
|
this.authenticationManagerBuilder = authenticationManagerBuilder;
|
||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
this.passwordEncoder = passwordEncoder;
|
this.passwordEncoder = passwordEncoder;
|
||||||
this.wxService = wxService;
|
|
||||||
this.wechatUserService = wechatUserService;
|
this.wechatUserService = wechatUserService;
|
||||||
this.wxMaService = wxMaService;
|
this.wxMaService = wxMaService;
|
||||||
this.notifyService = notifyService;
|
this.notifyService = notifyService;
|
||||||
@ -154,6 +153,11 @@ public class AuthController {
|
|||||||
HttpServletRequest request) {
|
HttpServletRequest request) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
String appId = RedisUtil.get("wechat_appid");
|
||||||
|
if(StrUtil.isBlank(appId)) {
|
||||||
|
return ApiResult.fail("请配置公众号");
|
||||||
|
}
|
||||||
|
WxMpService wxService = WxMpConfiguration.getWxMpService(appId);
|
||||||
WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxService.oauth2getAccessToken(code);
|
WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxService.oauth2getAccessToken(code);
|
||||||
WxMpUser wxMpUser = wxService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);
|
WxMpUser wxMpUser = wxService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);
|
||||||
String openid = wxMpUser.getOpenId();
|
String openid = wxMpUser.getOpenId();
|
||||||
|
@ -1,43 +1,29 @@
|
|||||||
package co.yixiang.modules.wechat.web.controller;
|
package co.yixiang.modules.wechat.web.controller;
|
||||||
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import co.yixiang.annotation.AnonymousAccess;
|
import co.yixiang.annotation.AnonymousAccess;
|
||||||
import co.yixiang.common.api.ApiCode;
|
|
||||||
import co.yixiang.common.api.ApiResult;
|
import co.yixiang.common.api.ApiResult;
|
||||||
import co.yixiang.common.web.controller.BaseController;
|
import co.yixiang.common.web.controller.BaseController;
|
||||||
import co.yixiang.modules.order.entity.YxStoreOrder;
|
import co.yixiang.modules.order.entity.YxStoreOrder;
|
||||||
import co.yixiang.modules.order.service.YxStoreOrderService;
|
import co.yixiang.modules.order.service.YxStoreOrderService;
|
||||||
import co.yixiang.modules.order.web.vo.YxStoreOrderQueryVo;
|
import co.yixiang.modules.order.web.vo.YxStoreOrderQueryVo;
|
||||||
import co.yixiang.modules.shop.service.YxSystemConfigService;
|
import co.yixiang.modules.shop.service.YxSystemConfigService;
|
||||||
import co.yixiang.modules.user.entity.YxUser;
|
import co.yixiang.mp.config.WxMpConfiguration;
|
||||||
import co.yixiang.modules.user.entity.YxWechatUser;
|
import co.yixiang.utils.RedisUtil;
|
||||||
import co.yixiang.modules.user.service.YxUserService;
|
|
||||||
import co.yixiang.modules.user.service.YxWechatUserService;
|
|
||||||
import co.yixiang.modules.user.web.vo.YxUserQueryVo;
|
|
||||||
import co.yixiang.utils.EncryptUtils;
|
|
||||||
import co.yixiang.utils.OrderUtil;
|
|
||||||
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
|
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
|
||||||
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
|
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
|
||||||
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
|
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
|
||||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||||
import com.github.binarywang.wxpay.service.WxPayService;
|
import com.github.binarywang.wxpay.service.WxPayService;
|
||||||
import com.vdurmont.emoji.EmojiParser;
|
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import me.chanjar.weixin.common.error.WxErrorException;
|
import me.chanjar.weixin.common.error.WxErrorException;
|
||||||
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
|
|
||||||
import me.chanjar.weixin.mp.api.WxMpService;
|
import me.chanjar.weixin.mp.api.WxMpService;
|
||||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||||
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.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
@ -45,7 +31,6 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -60,12 +45,8 @@ import java.util.Map;
|
|||||||
@Api(value = "微信模块", tags = "微信模块", description = "微信模块")
|
@Api(value = "微信模块", tags = "微信模块", description = "微信模块")
|
||||||
public class WechatController extends BaseController {
|
public class WechatController extends BaseController {
|
||||||
|
|
||||||
private final WxMpService wxService;
|
|
||||||
private final YxWechatUserService wechatUserService;
|
|
||||||
private final YxUserService userService;
|
|
||||||
private final WxPayService wxPayService;
|
private final WxPayService wxPayService;
|
||||||
private final YxStoreOrderService orderService;
|
private final YxStoreOrderService orderService;
|
||||||
private final WxMpMessageRouter messageRouter;
|
|
||||||
private final YxSystemConfigService systemConfigService;
|
private final YxSystemConfigService systemConfigService;
|
||||||
|
|
||||||
|
|
||||||
@ -92,6 +73,9 @@ public class WechatController extends BaseController {
|
|||||||
@GetMapping("/wechat/config")
|
@GetMapping("/wechat/config")
|
||||||
@ApiOperation(value = "jssdk配置",notes = "jssdk配置")
|
@ApiOperation(value = "jssdk配置",notes = "jssdk配置")
|
||||||
public ApiResult<Object> jsConfig(@RequestParam(value = "url") String url) throws WxErrorException {
|
public ApiResult<Object> jsConfig(@RequestParam(value = "url") String url) throws WxErrorException {
|
||||||
|
String appId = RedisUtil.get("wechat_appid");
|
||||||
|
if(StrUtil.isBlank(appId)) return ApiResult.fail("请配置公众号");
|
||||||
|
WxMpService wxService = WxMpConfiguration.getWxMpService(appId);
|
||||||
return ApiResult.ok(wxService.createJsapiSignature(url));
|
return ApiResult.ok(wxService.createJsapiSignature(url));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,6 +149,9 @@ public class WechatController extends BaseController {
|
|||||||
@RequestParam(name = "nonce", required = false) String nonce,
|
@RequestParam(name = "nonce", required = false) String nonce,
|
||||||
@RequestParam(name = "echostr", required = false) String echostr){
|
@RequestParam(name = "echostr", required = false) String echostr){
|
||||||
|
|
||||||
|
String appId = RedisUtil.get("wechat_appid");
|
||||||
|
if(StrUtil.isBlank(appId)) return "请配置公众号";
|
||||||
|
WxMpService wxService = WxMpConfiguration.getWxMpService(appId);
|
||||||
if (wxService.checkSignature(timestamp, nonce, signature)) {
|
if (wxService.checkSignature(timestamp, nonce, signature)) {
|
||||||
return echostr;
|
return echostr;
|
||||||
}
|
}
|
||||||
@ -186,6 +173,12 @@ public class WechatController extends BaseController {
|
|||||||
HttpServletRequest request,
|
HttpServletRequest request,
|
||||||
HttpServletResponse response) throws IOException {
|
HttpServletResponse response) throws IOException {
|
||||||
|
|
||||||
|
String appId = RedisUtil.get("wechat_appid");
|
||||||
|
if(StrUtil.isBlank(appId)) {
|
||||||
|
log.error("请配置公众号!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
WxMpService wxService = WxMpConfiguration.getWxMpService(appId);
|
||||||
|
|
||||||
if (!wxService.checkSignature(timestamp, nonce, signature)) {
|
if (!wxService.checkSignature(timestamp, nonce, signature)) {
|
||||||
throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
|
throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
|
||||||
@ -195,14 +188,14 @@ public class WechatController extends BaseController {
|
|||||||
if (encType == null) {
|
if (encType == null) {
|
||||||
// 明文传输的消息
|
// 明文传输的消息
|
||||||
WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
|
WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
|
||||||
WxMpXmlOutMessage outMessage = this.route(inMessage);
|
WxMpXmlOutMessage outMessage = this.route(inMessage,appId);
|
||||||
if(outMessage == null) return;
|
if(outMessage == null) return;
|
||||||
out = outMessage.toXml();;
|
out = outMessage.toXml();;
|
||||||
} else if ("aes".equalsIgnoreCase(encType)) {
|
} else if ("aes".equalsIgnoreCase(encType)) {
|
||||||
// aes加密的消息
|
// aes加密的消息
|
||||||
WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxService.getWxMpConfigStorage(),
|
WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxService.getWxMpConfigStorage(),
|
||||||
timestamp, nonce, msgSignature);
|
timestamp, nonce, msgSignature);
|
||||||
WxMpXmlOutMessage outMessage = this.route(inMessage);
|
WxMpXmlOutMessage outMessage = this.route(inMessage,appId);
|
||||||
if(outMessage == null) return;
|
if(outMessage == null) return;
|
||||||
|
|
||||||
out = outMessage.toEncryptedXml(wxService.getWxMpConfigStorage());
|
out = outMessage.toEncryptedXml(wxService.getWxMpConfigStorage());
|
||||||
@ -214,9 +207,9 @@ public class WechatController extends BaseController {
|
|||||||
writer.close();
|
writer.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private WxMpXmlOutMessage route(WxMpXmlMessage message) {
|
private WxMpXmlOutMessage route(WxMpXmlMessage message,String appId) {
|
||||||
try {
|
try {
|
||||||
return this.messageRouter.route(message);
|
return WxMpConfiguration.getWxMpMessageRouter(appId).route(message);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("路由消息时出现异常!", e);
|
log.error("路由消息时出现异常!", e);
|
||||||
}
|
}
|
||||||
|
@ -12,21 +12,25 @@
|
|||||||
<artifactId>yshop-mp</artifactId>
|
<artifactId>yshop-mp</artifactId>
|
||||||
<name>微信模块</name>
|
<name>微信模块</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<weixin-java.version>3.6.0</weixin-java.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.binarywang</groupId>
|
<groupId>com.github.binarywang</groupId>
|
||||||
<artifactId>weixin-java-mp</artifactId>
|
<artifactId>weixin-java-mp</artifactId>
|
||||||
<version>3.5.0</version>
|
<version>${weixin-java.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.binarywang</groupId>
|
<groupId>com.github.binarywang</groupId>
|
||||||
<artifactId>wx-java-pay-spring-boot-starter</artifactId>
|
<artifactId>wx-java-pay-spring-boot-starter</artifactId>
|
||||||
<version>3.5.0</version>
|
<version>${weixin-java.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.binarywang</groupId>
|
<groupId>com.github.binarywang</groupId>
|
||||||
<artifactId>wx-java-miniapp-spring-boot-starter</artifactId>
|
<artifactId>wx-java-miniapp-spring-boot-starter</artifactId>
|
||||||
<version>3.5.0</version>
|
<version>${weixin-java.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>co.yixiang</groupId>
|
<groupId>co.yixiang</groupId>
|
||||||
|
@ -1,141 +1,154 @@
|
|||||||
package co.yixiang.mp.config;
|
package co.yixiang.mp.config;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import co.yixiang.mp.handler.*;
|
import co.yixiang.mp.handler.*;
|
||||||
import co.yixiang.utils.RedisUtil;
|
import com.google.common.collect.Maps;
|
||||||
import lombok.AllArgsConstructor;
|
import me.chanjar.weixin.common.api.WxConsts;
|
||||||
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
|
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
|
||||||
import me.chanjar.weixin.mp.api.WxMpService;
|
import me.chanjar.weixin.mp.api.WxMpService;
|
||||||
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
|
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
|
||||||
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
|
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
|
||||||
import org.apache.poi.util.StringUtil;
|
import me.chanjar.weixin.mp.constant.WxMpEventConstants;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.Map;
|
||||||
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;
|
||||||
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.MenuButtonType.CLICK;
|
|
||||||
import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType.VIEW;
|
|
||||||
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType;
|
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 hupeng
|
||||||
|
* @date 2020/01/20
|
||||||
*/
|
*/
|
||||||
@AllArgsConstructor
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableConfigurationProperties(WxMpProperties.class)
|
|
||||||
public class WxMpConfiguration {
|
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;
|
|
||||||
private final RedisHandler redisHandler;
|
|
||||||
|
|
||||||
@Bean
|
private static Map<String, WxMpService> mpServices = Maps.newHashMap();
|
||||||
public WxMpService wxMpService() {
|
private static Map<String, WxMpMessageRouter> routers = Maps.newHashMap();
|
||||||
|
|
||||||
final List<WxMpProperties.MpConfig> configs = new ArrayList<>();
|
private static LogHandler logHandler;
|
||||||
WxMpProperties.MpConfig mpConfig = new WxMpProperties.MpConfig();
|
private static NullHandler nullHandler;
|
||||||
String appId = redisHandler.getVal("wechat_appid");
|
private static KfSessionHandler kfSessionHandler;
|
||||||
String secret = redisHandler.getVal("wechat_appsecret");
|
private static StoreCheckNotifyHandler storeCheckNotifyHandler;
|
||||||
String token = redisHandler.getVal("wechat_token");
|
private static LocationHandler locationHandler;
|
||||||
String aesKey = redisHandler.getVal("wechat_encodingaeskey");
|
private static MenuHandler menuHandler;
|
||||||
|
private static MsgHandler msgHandler;
|
||||||
|
private static UnsubscribeHandler unsubscribeHandler;
|
||||||
|
private static SubscribeHandler subscribeHandler;
|
||||||
|
private static ScanHandler scanHandler;
|
||||||
|
private static RedisHandler redisHandler;
|
||||||
|
|
||||||
|
public WxMpConfiguration(LogHandler logHandler,NullHandler nullHandler,KfSessionHandler kfSessionHandler,
|
||||||
if(StrUtil.isNotBlank(appId) && StrUtil.isNotBlank(secret)
|
StoreCheckNotifyHandler storeCheckNotifyHandler,LocationHandler locationHandler,
|
||||||
&& StrUtil.isNotBlank(token) && StrUtil.isNotBlank(aesKey)) {
|
MenuHandler menuHandler,MsgHandler msgHandler,UnsubscribeHandler unsubscribeHandler,
|
||||||
mpConfig.setAppId(appId);
|
SubscribeHandler subscribeHandler,ScanHandler scanHandler,
|
||||||
mpConfig.setSecret(secret);
|
RedisHandler redisHandler){
|
||||||
mpConfig.setToken(token);
|
this.logHandler = logHandler;
|
||||||
mpConfig.setAesKey(aesKey);
|
this.nullHandler = nullHandler;
|
||||||
System.out.println(mpConfig);
|
this.kfSessionHandler = kfSessionHandler;
|
||||||
|
this.storeCheckNotifyHandler = storeCheckNotifyHandler;
|
||||||
configs.add(mpConfig);
|
this.locationHandler = locationHandler;
|
||||||
}else{
|
this.menuHandler = menuHandler;
|
||||||
mpConfig.setAppId("111111");
|
this.msgHandler = msgHandler;
|
||||||
mpConfig.setSecret("111111");
|
this.unsubscribeHandler = unsubscribeHandler;
|
||||||
mpConfig.setToken("111111");
|
this.subscribeHandler = subscribeHandler;
|
||||||
mpConfig.setAesKey("111111");
|
this.scanHandler = scanHandler;
|
||||||
|
this.redisHandler = redisHandler;
|
||||||
configs.add(mpConfig);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//System.out.println("configs:"+configs);
|
|
||||||
|
|
||||||
if (configs.isEmpty()) {
|
/**
|
||||||
throw new RuntimeException("请先配置!");
|
* 获取WxMpService
|
||||||
}
|
* @return
|
||||||
|
*/
|
||||||
|
public static WxMpService getWxMpService(String appId) {
|
||||||
|
|
||||||
WxMpService service = new WxMpServiceImpl();
|
WxMpService wxMpService = mpServices.get(appId);
|
||||||
service.setMultiConfigStorages(configs
|
if(wxMpService == null) {
|
||||||
.stream().map(a -> {
|
|
||||||
WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
|
WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
|
||||||
configStorage.setAppId(a.getAppId());
|
configStorage.setAppId(redisHandler.getVal("wechat_appid"));
|
||||||
configStorage.setSecret(a.getSecret());
|
configStorage.setSecret(redisHandler.getVal("wechat_appsecret"));
|
||||||
configStorage.setToken(a.getToken());
|
configStorage.setToken(redisHandler.getVal("wechat_token"));
|
||||||
configStorage.setAesKey(a.getAesKey());
|
configStorage.setAesKey(redisHandler.getVal("wechat_encodingaeskey"));
|
||||||
return configStorage;
|
wxMpService = new WxMpServiceImpl();
|
||||||
}).collect(Collectors.toMap(WxMpDefaultConfigImpl::getAppId, a -> a, (o, n) -> o)));
|
wxMpService.setWxMpConfigStorage(configStorage);
|
||||||
return service;
|
mpServices.put(appId, wxMpService);
|
||||||
|
routers.put(appId, newRouter(wxMpService));
|
||||||
|
}
|
||||||
|
return wxMpService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
/**
|
||||||
public WxMpMessageRouter messageRouter(WxMpService wxMpService) {
|
* 移除WxMpService
|
||||||
|
* @param appId
|
||||||
|
*/
|
||||||
|
public static void removeWxMpService(String appId){
|
||||||
|
mpServices.remove(appId);
|
||||||
|
routers.remove(appId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取WxMpMessageRouter
|
||||||
|
* @param appId
|
||||||
|
*/
|
||||||
|
public static WxMpMessageRouter getWxMpMessageRouter(String appId) {
|
||||||
|
WxMpMessageRouter wxMpMessageRouter = routers.get(appId);
|
||||||
|
return wxMpMessageRouter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WxMpMessageRouter newRouter(WxMpService wxMpService) {
|
||||||
final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);
|
final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);
|
||||||
|
|
||||||
// 记录所有事件的日志 (异步执行)
|
// 记录所有事件的日志 (异步执行)
|
||||||
//newRouter.rule().handler(this.logHandler).next();
|
newRouter.rule().handler(logHandler).next();
|
||||||
|
|
||||||
// 接收客服会话管理事件
|
// 接收客服会话管理事件
|
||||||
// newRouter.rule().async(false).msgType(EVENT).event(KF_CREATE_SESSION)
|
newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
|
||||||
// .handler(this.kfSessionHandler).end();
|
.event(WxMpEventConstants.CustomerService.KF_CREATE_SESSION)
|
||||||
// newRouter.rule().async(false).msgType(EVENT).event(KF_CLOSE_SESSION)
|
.handler(kfSessionHandler).end();
|
||||||
// .handler(this.kfSessionHandler).end();
|
newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
|
||||||
// newRouter.rule().async(false).msgType(EVENT).event(KF_SWITCH_SESSION)
|
.event(WxMpEventConstants.CustomerService.KF_CLOSE_SESSION)
|
||||||
// .handler(this.kfSessionHandler).end();
|
.handler(kfSessionHandler)
|
||||||
|
.end();
|
||||||
|
newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
|
||||||
|
.event(WxMpEventConstants.CustomerService.KF_SWITCH_SESSION)
|
||||||
|
.handler(kfSessionHandler).end();
|
||||||
|
|
||||||
// 门店审核事件
|
// 门店审核事件
|
||||||
//newRouter.rule().async(false).msgType(EVENT).event(POI_CHECK_NOTIFY).handler(this.storeCheckNotifyHandler).end();
|
newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
|
||||||
|
.event(WxMpEventConstants.POI_CHECK_NOTIFY)
|
||||||
|
.handler(storeCheckNotifyHandler).end();
|
||||||
|
|
||||||
// 自定义菜单事件
|
// 自定义菜单事件
|
||||||
newRouter.rule().async(false).msgType(EVENT).event(CLICK).handler(this.menuHandler).end();
|
newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
|
||||||
|
.event(WxConsts.MenuButtonType.CLICK).handler(menuHandler).end();
|
||||||
|
|
||||||
// 点击菜单连接事件
|
// 点击菜单连接事件
|
||||||
newRouter.rule().async(false).msgType(EVENT).event(VIEW).handler(this.nullHandler).end();
|
newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
|
||||||
|
.event(WxConsts.MenuButtonType.VIEW).handler(menuHandler).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).msgType(XmlMsgType.EVENT)
|
||||||
|
.event(EventType.SCANCODE_WAITMSG).handler(menuHandler).end();
|
||||||
|
|
||||||
|
// 关注事件
|
||||||
|
newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
|
||||||
|
.event(EventType.SUBSCRIBE).handler(subscribeHandler)
|
||||||
|
.end();
|
||||||
|
|
||||||
|
// 取消关注事件
|
||||||
|
newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
|
||||||
|
.event(EventType.UNSUBSCRIBE)
|
||||||
|
.handler(unsubscribeHandler).end();
|
||||||
|
|
||||||
|
// 上报地理位置事件
|
||||||
|
newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
|
||||||
|
.event(EventType.LOCATION).handler(locationHandler)
|
||||||
|
.end();
|
||||||
|
|
||||||
|
|
||||||
// 默认
|
// 默认
|
||||||
newRouter.rule().async(false).handler(this.msgHandler).end();
|
newRouter.rule().async(false).handler(msgHandler).end();
|
||||||
|
|
||||||
return newRouter;
|
return newRouter;
|
||||||
}
|
}
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
package co.yixiang.mp.config;
|
|
||||||
|
|
||||||
import co.yixiang.mp.utils.JsonUtils;
|
|
||||||
import lombok.Data;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* wechat mp properties
|
|
||||||
*/
|
|
||||||
@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,186 +0,0 @@
|
|||||||
package co.yixiang.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;
|
|
||||||
|
|
||||||
|
|
||||||
@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,105 +0,0 @@
|
|||||||
package co.yixiang.mp.controller;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
|
|
||||||
import me.chanjar.weixin.mp.api.WxMpService;
|
|
||||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
|
||||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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,37 +0,0 @@
|
|||||||
package co.yixiang.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.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;
|
|
||||||
|
|
||||||
|
|
||||||
@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";
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,9 +3,11 @@ package co.yixiang.mp.controller;
|
|||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import co.yixiang.exception.BadRequestException;
|
import co.yixiang.exception.BadRequestException;
|
||||||
|
import co.yixiang.mp.config.WxMpConfiguration;
|
||||||
import co.yixiang.mp.domain.YxCache;
|
import co.yixiang.mp.domain.YxCache;
|
||||||
import co.yixiang.mp.service.YxCacheService;
|
import co.yixiang.mp.service.YxCacheService;
|
||||||
import co.yixiang.utils.OrderUtil;
|
import co.yixiang.utils.OrderUtil;
|
||||||
|
import co.yixiang.utils.RedisUtil;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
@ -31,8 +33,6 @@ public class YxCacheController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private YxCacheService yxCacheService;
|
private YxCacheService yxCacheService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private WxMpService wxService;
|
|
||||||
|
|
||||||
|
|
||||||
@ApiOperation(value = "查询菜单")
|
@ApiOperation(value = "查询菜单")
|
||||||
@ -53,6 +53,12 @@ public class YxCacheController {
|
|||||||
YxCache yxCache = new YxCache();
|
YxCache yxCache = new YxCache();
|
||||||
Boolean isExist = yxCacheService.isExist("wechat_menus");
|
Boolean isExist = yxCacheService.isExist("wechat_menus");
|
||||||
WxMenu menu = JSONObject.parseObject(jsonStr,WxMenu.class);
|
WxMenu menu = JSONObject.parseObject(jsonStr,WxMenu.class);
|
||||||
|
|
||||||
|
String appId = RedisUtil.get("wechat_appid");
|
||||||
|
if(StrUtil.isBlank(appId)) {
|
||||||
|
throw new BadRequestException("请配置公众号");
|
||||||
|
}
|
||||||
|
WxMpService wxService = WxMpConfiguration.getWxMpService(appId);
|
||||||
if(isExist){
|
if(isExist){
|
||||||
yxCache.setKey("wechat_menus");
|
yxCache.setKey("wechat_menus");
|
||||||
yxCache.setResult(jsonButton);
|
yxCache.setResult(jsonButton);
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package co.yixiang.mp.service.impl;
|
package co.yixiang.mp.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import co.yixiang.mp.config.WxMpConfiguration;
|
||||||
import co.yixiang.mp.service.WxMpTemplateMessageService;
|
import co.yixiang.mp.service.WxMpTemplateMessageService;
|
||||||
|
import co.yixiang.utils.RedisUtil;
|
||||||
import me.chanjar.weixin.common.error.WxErrorException;
|
import me.chanjar.weixin.common.error.WxErrorException;
|
||||||
import me.chanjar.weixin.mp.api.WxMpService;
|
import me.chanjar.weixin.mp.api.WxMpService;
|
||||||
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
|
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
|
||||||
@ -13,9 +16,6 @@ import java.util.Map;
|
|||||||
@Component
|
@Component
|
||||||
public class WxMpTemplateMessageServiceImpl implements WxMpTemplateMessageService {
|
public class WxMpTemplateMessageServiceImpl implements WxMpTemplateMessageService {
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private WxMpService wxMpService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String sendWxMpTemplateMessage(String openId, String templateId, String url, Map<String,String> map){
|
public String sendWxMpTemplateMessage(String openId, String templateId, String url, Map<String,String> map){
|
||||||
WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
|
WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
|
||||||
@ -25,8 +25,13 @@ public class WxMpTemplateMessageServiceImpl implements WxMpTemplateMessageServic
|
|||||||
.build();
|
.build();
|
||||||
map.forEach( (k,v)-> { templateMessage.addData(new WxMpTemplateData(k, v, "#000000"));} );
|
map.forEach( (k,v)-> { templateMessage.addData(new WxMpTemplateData(k, v, "#000000"));} );
|
||||||
String msgId = null;
|
String msgId = null;
|
||||||
|
String appId = RedisUtil.get("wechat_appid");
|
||||||
|
if(StrUtil.isBlank(appId)) {
|
||||||
|
return "请配置公众号";
|
||||||
|
}
|
||||||
|
WxMpService wxService = WxMpConfiguration.getWxMpService(appId);
|
||||||
try {
|
try {
|
||||||
msgId = wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
|
msgId = wxService.getTemplateMsgService().sendTemplateMsg(templateMessage);
|
||||||
} catch (WxErrorException e) {
|
} catch (WxErrorException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,12 @@ package co.yixiang.mp.service.impl;
|
|||||||
|
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.util.ReUtil;
|
import cn.hutool.core.util.ReUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.http.HttpUtil;
|
import cn.hutool.http.HttpUtil;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import co.yixiang.exception.BadRequestException;
|
||||||
import co.yixiang.exception.ErrorRequestException;
|
import co.yixiang.exception.ErrorRequestException;
|
||||||
|
import co.yixiang.mp.config.WxMpConfiguration;
|
||||||
import co.yixiang.mp.domain.YxArticle;
|
import co.yixiang.mp.domain.YxArticle;
|
||||||
import co.yixiang.mp.repository.YxArticleRepository;
|
import co.yixiang.mp.repository.YxArticleRepository;
|
||||||
import co.yixiang.mp.service.YxArticleService;
|
import co.yixiang.mp.service.YxArticleService;
|
||||||
@ -13,10 +16,7 @@ import co.yixiang.mp.service.dto.YxArticleDTO;
|
|||||||
import co.yixiang.mp.service.dto.YxArticleQueryCriteria;
|
import co.yixiang.mp.service.dto.YxArticleQueryCriteria;
|
||||||
import co.yixiang.mp.service.mapper.YxArticleMapper;
|
import co.yixiang.mp.service.mapper.YxArticleMapper;
|
||||||
import co.yixiang.mp.utils.URLUtils;
|
import co.yixiang.mp.utils.URLUtils;
|
||||||
import co.yixiang.utils.OrderUtil;
|
import co.yixiang.utils.*;
|
||||||
import co.yixiang.utils.PageUtil;
|
|
||||||
import co.yixiang.utils.QueryHelp;
|
|
||||||
import co.yixiang.utils.ValidationUtil;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import me.chanjar.weixin.common.api.WxConsts;
|
import me.chanjar.weixin.common.api.WxConsts;
|
||||||
import me.chanjar.weixin.common.error.WxErrorException;
|
import me.chanjar.weixin.common.error.WxErrorException;
|
||||||
@ -56,8 +56,6 @@ public class YxArticleServiceImpl implements YxArticleService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private YxArticleMapper yxArticleMapper;
|
private YxArticleMapper yxArticleMapper;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private WxMpService wxMpService;
|
|
||||||
|
|
||||||
@Value("${file.path}")
|
@Value("${file.path}")
|
||||||
private String uploadDirStr;
|
private String uploadDirStr;
|
||||||
@ -107,6 +105,12 @@ public class YxArticleServiceImpl implements YxArticleService {
|
|||||||
@Override
|
@Override
|
||||||
public void uploadNews(YxArticleDTO wxNewsArticleItem) throws Exception {
|
public void uploadNews(YxArticleDTO wxNewsArticleItem) throws Exception {
|
||||||
|
|
||||||
|
String appId = RedisUtil.get("wechat_appid");
|
||||||
|
if(StrUtil.isBlank(appId)) {
|
||||||
|
throw new BadRequestException("请配置公众号");
|
||||||
|
}
|
||||||
|
WxMpService wxMpService = WxMpConfiguration.getWxMpService(appId);
|
||||||
|
|
||||||
WxMpMaterialNews wxMpMaterialNews = new WxMpMaterialNews();
|
WxMpMaterialNews wxMpMaterialNews = new WxMpMaterialNews();
|
||||||
|
|
||||||
|
|
||||||
@ -118,7 +122,6 @@ public class YxArticleServiceImpl implements YxArticleService {
|
|||||||
|
|
||||||
article.setAuthor( wxNewsArticleItem.getAuthor() );
|
article.setAuthor( wxNewsArticleItem.getAuthor() );
|
||||||
|
|
||||||
System.out.println(wxNewsArticleItem.getContent());
|
|
||||||
|
|
||||||
//处理content
|
//处理content
|
||||||
String content = processContent(wxMpService, wxNewsArticleItem.getContent());
|
String content = processContent(wxMpService, wxNewsArticleItem.getContent());
|
||||||
|
@ -7,6 +7,7 @@ import co.yixiang.exception.BadRequestException;
|
|||||||
import co.yixiang.modules.wechat.domain.YxSystemConfig;
|
import co.yixiang.modules.wechat.domain.YxSystemConfig;
|
||||||
import co.yixiang.modules.wechat.service.YxSystemConfigService;
|
import co.yixiang.modules.wechat.service.YxSystemConfigService;
|
||||||
import co.yixiang.modules.wechat.service.dto.YxSystemConfigQueryCriteria;
|
import co.yixiang.modules.wechat.service.dto.YxSystemConfigQueryCriteria;
|
||||||
|
import co.yixiang.mp.config.WxMpConfiguration;
|
||||||
import co.yixiang.utils.RedisUtil;
|
import co.yixiang.utils.RedisUtil;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
@ -52,6 +53,10 @@ public class YxSystemConfigController {
|
|||||||
YxSystemConfig yxSystemConfigModel = new YxSystemConfig();
|
YxSystemConfig yxSystemConfigModel = new YxSystemConfig();
|
||||||
yxSystemConfigModel.setMenuName(key);
|
yxSystemConfigModel.setMenuName(key);
|
||||||
yxSystemConfigModel.setValue(value.toString());
|
yxSystemConfigModel.setValue(value.toString());
|
||||||
|
//重新配置微信相关
|
||||||
|
if(key.equals("wechat_appid")){
|
||||||
|
WxMpConfiguration.removeWxMpService(key);
|
||||||
|
}
|
||||||
RedisUtil.set(key,value.toString(),0);
|
RedisUtil.set(key,value.toString(),0);
|
||||||
if(ObjectUtil.isNull(yxSystemConfig)){
|
if(ObjectUtil.isNull(yxSystemConfig)){
|
||||||
yxSystemConfigService.create(yxSystemConfigModel);
|
yxSystemConfigService.create(yxSystemConfigModel);
|
||||||
|
Reference in New Issue
Block a user