自动回复

This commit is contained in:
shikong 2024-12-08 02:04:20 +08:00
parent bb55f4030f
commit e8a7435a42
Signed by: Shikong
GPG Key ID: BD85FF18B373C341
5 changed files with 144 additions and 3 deletions

View File

@ -5,16 +5,19 @@ import cn.skcks.docking.wx.common.json.JsonResponse;
import cn.skcks.docking.wx.common.page.PageWrapper;
import cn.skcks.docking.wx.orm.entity.MpApp;
import cn.skcks.docking.wx.services.mp.service.MpAppService;
import cn.skcks.docking.wx.services.mp.vo.verify.SignatureVo;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
@Tag(name = "微信公众号")
@ -41,4 +44,10 @@ public class MpAppController {
public JsonResponse<PageWrapper<MpApp>> getMpAppListPage(@RequestParam Integer pageNo, @RequestParam Integer pageSize) {
return JsonResponse.success(mpAppService.getMpAppPageList(pageNo,pageSize));
}
@RequestMapping("/{appId}")
public void verify(HttpServletRequest request, HttpServletResponse response,
@PathVariable String appId, @ParameterObject SignatureVo signatureVo) throws Exception {
mpAppService.service(request, response, appId, signatureVo);
}
}

View File

@ -1,14 +1,31 @@
package cn.skcks.docking.wx.services.mp.service;
import cn.hutool.core.date.DateUtil;
import cn.skcks.docking.wx.common.page.PageWrapper;
import cn.skcks.docking.wx.orm.entity.MpApp;
import cn.skcks.docking.wx.orm.mapper.MpAppMapper;
import cn.skcks.docking.wx.services.mp.vo.verify.SignatureVo;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ForkJoinPool;
@Slf4j
@Service
@ -16,6 +33,96 @@ import java.util.List;
public class MpAppService {
private final MpAppMapper mpAppMapper;
private final Map<String, WxMpService> serviceMap = new ConcurrentHashMap<>();
@PostConstruct
private void init(){
LambdaQueryChainWrapper<MpApp> queryWrapper = new LambdaQueryChainWrapper<>(mpAppMapper);
queryWrapper.ne(MpApp::getEnable, false);
List<MpApp> mpApps = queryWrapper.list();
new ForkJoinPool(Runtime.getRuntime().availableProcessors()).execute(() -> {
mpApps.parallelStream().forEach(mpApp -> {
WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl();
config.setAppId(mpApp.getAppId());
config.setSecret(mpApp.getAppSecret());
config.setToken(mpApp.getToken());
config.setAesKey(mpApp.getEncodingAesKey());
WxMpService service = new WxMpServiceImpl();
service.setWxMpConfigStorage(config);
serviceMap.put(mpApp.getAppId(), service);
});
});
}
public void service(HttpServletRequest request, HttpServletResponse response, String appId, SignatureVo signatureVo) throws IOException {
response.setContentType("text/html;charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK);
WxMpService wxMpService = serviceMap.get(appId);
if(ObjectUtils.anyNull(appId, signatureVo, wxMpService)){
response.getWriter().println("非法请求");
return;
}
if(!wxMpService.checkSignature(signatureVo.getTimestamp(), signatureVo.getNonce(), signatureVo.getSignature())){
response.getWriter().println("非法请求");
return;
}
// 签名验证请求
String echostr = request.getParameter("echostr");
if(StringUtils.isNotBlank(echostr)){
response.getWriter().println(echostr);
return;
}
String encryptType = StringUtils.isBlank(request.getParameter("encrypt_type")) ?
"raw" :
request.getParameter("encrypt_type");
if ("raw".equals(encryptType)) {
// 明文传输的消息
WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(request.getInputStream());
// WxMpXmlOutMessage outMessage = wxMpMessageRouter.route(inMessage);
// if(outMessage == null) {
// //为null说明路由配置有问题需要注意
// response.getWriter().write("");
// }
// response.getWriter().write(outMessage.toXml());
log.debug("\n[↓] 接收消息: \n{}", inMessage);
WxMpXmlOutMessage outMessage = WxMpXmlOutMessage.TEXT()
.toUser(inMessage.getFromUser())
.fromUser(inMessage.getToUser())
.content(DateUtil.now())
.build();
log.debug("\n[↑] 响应消息: \n{}", outMessage);
response.getWriter().write(outMessage.toXml());
return;
}
// if ("aes".equals(encryptType)) {
// // 是aes加密的消息
// String msgSignature = request.getParameter("msg_signature");
// WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(request.getInputStream(), wxMpConfigStorage, timestamp, nonce, msgSignature);
// WxMpXmlOutMessage outMessage = wxMpMessageRouter.route(inMessage);
// if(outMessage == null) {
// //为null说明路由配置有问题需要注意
// response.getWriter().write("");
// }
// response.getWriter().write(outMessage.toEncryptedXml(wxMpConfigStorage));
// return;
// }
response.getWriter().println("不可识别的加密类型");
// return;
}
/**
* 获取所有公众号列表

View File

@ -0,0 +1,15 @@
package cn.skcks.docking.wx.services.mp.vo.verify;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(title="签名验证 Vo")
public class SignatureVo {
@Schema(description = "时间戳")
private String timestamp;
@Schema(description = "随机数")
private String nonce;
@Schema(description = "签名")
private String signature;
}

View File

@ -4,3 +4,8 @@ spring:
server:
port: 18881
logging:
level:
root: info
cn.skcks.docking.wx: debug

View File

@ -10,3 +10,8 @@ spring:
deserialization:
# 忽略没有的字段
fail_on_unknown_properties: false
logging:
level:
root: info
cn.skcks.docking.wx: debug