From a21f6803f9ce4e0531f98d581e2a7cfaa0b046c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=94=B0=E8=89=BA=E9=B9=8F?= <18382071280@163.com>
Date: Wed, 23 Aug 2023 16:40:17 +0800
Subject: [PATCH] =?UTF-8?q?fix(*)=20=E9=A6=96=E6=AC=A1=E6=8F=90=E4=BA=A4WX?=
=?UTF-8?q?Engine=E9=A1=B9=E7=9B=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 2 +
WXEngine/pom.xml | 177 ++++++++++++++++++
.../cloud/wxengine/WXEngineApplcation.java | 37 ++++
.../config/DataSourceConfiguration.java | 34 ++++
.../config/RedisRepositoryConfig.java | 30 +++
.../cloud/wxengine/config/WxMpConfig.java | 79 ++++++++
.../controller/WeiXinAPIController.java | 113 +++++++++++
.../cloud/wxengine/mapper/WxMpMapper.java | 19 ++
.../cloud/wxengine/mapper/WxMpTempMapper.java | 16 ++
.../cn/crtech/cloud/wxengine/pojo/WxMp.java | 53 ++++++
.../crtech/cloud/wxengine/pojo/WxMpTemp.java | 41 ++++
.../wxengine/serveice/AbstractBuilder.java | 15 ++
.../cloud/wxengine/serveice/BaseService.java | 50 +++++
.../wxengine/serveice/WxMpAccessService.java | 113 +++++++++++
.../cloud/wxengine/serveice/WxMpService.java | 49 +++++
.../wxengine/serveice/WxMpTempService.java | 49 +++++
.../wxengine/serveice/WxMpTextBuilder.java | 23 +++
.../cloud/wxengine/utils/CodeUtils.java | 22 +++
.../src/main/resources/application-dev.yml | 37 ++++
.../src/main/resources/application-prod.yml | 40 ++++
WXEngine/src/main/resources/bootstrap-dev.yml | 13 ++
.../src/main/resources/bootstrap-prod.yml | 13 ++
WXEngine/src/main/resources/bootstrap.yml | 5 +
WXEngine/src/main/resources/logback.xml | 56 ++++++
.../src/main/resources/mapper/WxMpMapper.xml | 92 +++++++++
.../main/resources/mapper/WxMpTempMapper.xml | 43 +++++
26 files changed, 1221 insertions(+)
create mode 100644 WXEngine/pom.xml
create mode 100644 WXEngine/src/main/java/cn/crtech/cloud/wxengine/WXEngineApplcation.java
create mode 100644 WXEngine/src/main/java/cn/crtech/cloud/wxengine/config/DataSourceConfiguration.java
create mode 100644 WXEngine/src/main/java/cn/crtech/cloud/wxengine/config/RedisRepositoryConfig.java
create mode 100644 WXEngine/src/main/java/cn/crtech/cloud/wxengine/config/WxMpConfig.java
create mode 100644 WXEngine/src/main/java/cn/crtech/cloud/wxengine/controller/WeiXinAPIController.java
create mode 100644 WXEngine/src/main/java/cn/crtech/cloud/wxengine/mapper/WxMpMapper.java
create mode 100644 WXEngine/src/main/java/cn/crtech/cloud/wxengine/mapper/WxMpTempMapper.java
create mode 100644 WXEngine/src/main/java/cn/crtech/cloud/wxengine/pojo/WxMp.java
create mode 100644 WXEngine/src/main/java/cn/crtech/cloud/wxengine/pojo/WxMpTemp.java
create mode 100644 WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/AbstractBuilder.java
create mode 100644 WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/BaseService.java
create mode 100644 WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/WxMpAccessService.java
create mode 100644 WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/WxMpService.java
create mode 100644 WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/WxMpTempService.java
create mode 100644 WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/WxMpTextBuilder.java
create mode 100644 WXEngine/src/main/java/cn/crtech/cloud/wxengine/utils/CodeUtils.java
create mode 100644 WXEngine/src/main/resources/application-dev.yml
create mode 100644 WXEngine/src/main/resources/application-prod.yml
create mode 100644 WXEngine/src/main/resources/bootstrap-dev.yml
create mode 100644 WXEngine/src/main/resources/bootstrap-prod.yml
create mode 100644 WXEngine/src/main/resources/bootstrap.yml
create mode 100644 WXEngine/src/main/resources/logback.xml
create mode 100644 WXEngine/src/main/resources/mapper/WxMpMapper.xml
create mode 100644 WXEngine/src/main/resources/mapper/WxMpTempMapper.xml
diff --git a/.gitignore b/.gitignore
index 1b5050f..f41242f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,5 @@
/Gateway/src/main/resources/application-test.yml
/ResourceManager/src/main/resources/application-test.yml
/ResourceManager/src/main/resources/bootstrap-test.yml
+/WXEngine/src/main/resources/bootstrap-test.yml
+/WXEngine/src/main/resources/application-test.yml
diff --git a/WXEngine/pom.xml b/WXEngine/pom.xml
new file mode 100644
index 0000000..bfb73af
--- /dev/null
+++ b/WXEngine/pom.xml
@@ -0,0 +1,177 @@
+
+
+ 4.0.0
+
+ cn.crtech.cloud.wxengine
+ WXEngine
+ 1.0.1
+
+
+
+ cn.crtech.cloud.dependencies
+ Dependencies
+ 1.0.1
+
+
+
+
+
+ 8
+ 8
+ 1.8
+ UTF-8
+
+ 1.0.1
+ 1.14.3
+ 6.4.0.jre8
+ 4.3.0
+ 4.2.0
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+
+
+
+
+
+ junit
+ junit
+ test
+
+
+
+ org.springframework.boot
+ spring-boot-test
+
+
+
+ org.springframework
+ spring-test
+
+
+
+ org.apache.commons
+ commons-lang3
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-loadbalancer
+
+
+
+ redis.clients
+ jedis
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+ cn.crtech.cloud.common
+ Common
+ ${common.version}
+
+
+
+ org.jsoup
+ jsoup
+ ${jsoup.version}
+
+
+
+ com.microsoft.sqlserver
+ mssql-jdbc
+ ${mssql.version}
+ runtime
+
+
+
+
+ com.github.binarywang
+ weixin-java-mp
+ ${wx.mp.version}
+
+
+ com.google.guava
+ guava
+
+
+ commons-io
+ commons-io
+
+
+
+
+
+
+ com.github.binarywang
+ weixin-java-miniapp
+ ${normal.wx.version}
+
+
+
+
+ com.github.binarywang
+ weixin-java-cp
+ ${normal.wx.version}
+
+
+
+
+ com.github.binarywang
+ weixin-java-pay
+ ${normal.wx.version}
+
+
+
+
+ com.github.binarywang
+ weixin-java-open
+ ${normal.wx.version}
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+ -Dfile.encoding=UTF-8
+
+
+
+
+
diff --git a/WXEngine/src/main/java/cn/crtech/cloud/wxengine/WXEngineApplcation.java b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/WXEngineApplcation.java
new file mode 100644
index 0000000..7cda8e0
--- /dev/null
+++ b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/WXEngineApplcation.java
@@ -0,0 +1,37 @@
+package cn.crtech.cloud.wxengine;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+//微服务启动时使用 begin
+
+@EnableDiscoveryClient
+@SpringBootApplication
+@EnableTransactionManagement
+@MapperScan("cn.crtech.cloud.wxengine.mapper")
+public class WXEngineApplcation {
+ public static void main(String[] args) {
+ SpringApplication.run(WXEngineApplcation.class, args);
+ }
+}
+
+//微服务启动时使用 end
+
+//使用launcher启动时使用 begin
+//launcher.NacosConfig @Component需要放开
+//
+//@SpringBootApplication
+//@MapperScan("cn.crtech.cloud.resmanager.mapper")
+//public class ResmanagerApplcation extends SpringBootServletInitializer {
+// @Override
+// protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+// return application.sources(ResmanagerApplcation.class);
+// }
+//}
+
+//使用launcher启动时使用 end
+
+
diff --git a/WXEngine/src/main/java/cn/crtech/cloud/wxengine/config/DataSourceConfiguration.java b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/config/DataSourceConfiguration.java
new file mode 100644
index 0000000..05cd519
--- /dev/null
+++ b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/config/DataSourceConfiguration.java
@@ -0,0 +1,34 @@
+package cn.crtech.cloud.wxengine.config;
+
+import cn.crtech.cloud.common.utils.EncryptUtil;
+import com.alibaba.druid.pool.DruidDataSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+import java.util.Objects;
+
+@Configuration
+public class DataSourceConfiguration {
+ @Autowired
+ private DataSourceProperties properties;
+
+ @Bean
+ public DataSource dataSource() throws Exception {
+ DruidDataSource dataSource = new DruidDataSource();
+ dataSource.setDbType("mysql");
+ dataSource.setUrl(properties.getUrl());
+ dataSource.setUsername(new String(Objects.requireNonNull(EncryptUtil.decrypt(EncryptUtil.parseHexStr2Byte(properties.getUsername()), "THIS SHALL NOT BE SEEN."))));
+ dataSource.setPassword(new String(Objects.requireNonNull(EncryptUtil.decrypt(EncryptUtil.parseHexStr2Byte(properties.getPassword()), "THIS SHALL NOT BE SEEN."))));
+ dataSource.setInitialSize(5);
+ dataSource.setMinIdle(1);
+ dataSource.setMinEvictableIdleTimeMillis(10000L);
+ dataSource.setMaxActive(100);
+ dataSource.setMaxWait(60000L);
+ dataSource.setValidationQuery("SELECT 'x'");
+ dataSource.setFilters("stat, wall");
+ return dataSource;
+ }
+}
diff --git a/WXEngine/src/main/java/cn/crtech/cloud/wxengine/config/RedisRepositoryConfig.java b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/config/RedisRepositoryConfig.java
new file mode 100644
index 0000000..3a156ae
--- /dev/null
+++ b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/config/RedisRepositoryConfig.java
@@ -0,0 +1,30 @@
+package cn.crtech.cloud.wxengine.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * Redis相关配置
+ */
+@Configuration
+@EnableRedisRepositories
+public class RedisRepositoryConfig {
+ @Bean
+ public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
+ RedisTemplate redisTemplate = new RedisTemplate<>();
+ redisTemplate.setConnectionFactory(connectionFactory);
+ StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
+ redisTemplate.setKeySerializer(stringRedisSerializer);
+ redisTemplate.setHashKeySerializer(stringRedisSerializer);
+ Jackson2JsonRedisSerializer> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
+ redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
+ redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
+ redisTemplate.afterPropertiesSet();
+ return redisTemplate;
+ }
+}
diff --git a/WXEngine/src/main/java/cn/crtech/cloud/wxengine/config/WxMpConfig.java b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/config/WxMpConfig.java
new file mode 100644
index 0000000..d5b8c4a
--- /dev/null
+++ b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/config/WxMpConfig.java
@@ -0,0 +1,79 @@
+package cn.crtech.cloud.wxengine.config;
+
+import cn.crtech.cloud.wxengine.mapper.WxMpMapper;
+import cn.crtech.cloud.wxengine.pojo.WxMp;
+import cn.crtech.cloud.wxengine.pojo.WxMpTemp;
+import cn.hutool.core.collection.CollectionUtil;
+import lombok.Data;
+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.config.impl.WxMpDefaultConfigImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.PostConstruct;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Data
+@Slf4j
+@Configuration
+public class WxMpConfig {
+ @Autowired
+ private WxMpMapper wxMpMapper;
+
+ private Map wxMpMap;
+
+ private Map wxMpServiceList;
+
+ @PostConstruct
+ public void initWxConfig() {
+ this.initWxMp();
+ }
+
+ public void initWxMp() {
+ wxMpServiceList = new HashMap<>();
+ wxMpMap = new HashMap<>();
+ List list = wxMpMapper.getWxMpByList(1);
+ if (!CollectionUtil.isEmpty(list)) {
+ list.forEach(item -> {
+ WxMpService wxMpService = new WxMpServiceImpl();
+ WxMpDefaultConfigImpl wxMpConfigStorage = new WxMpDefaultConfigImpl();
+ wxMpConfigStorage.setAppId(item.getAppId());
+ wxMpConfigStorage.setSecret(item.getAppSecret());
+ wxMpConfigStorage.setToken(item.getAppToken());
+ wxMpConfigStorage.setAesKey(item.getAppAeskey());
+ wxMpService.setWxMpConfigStorage(wxMpConfigStorage);
+ wxMpServiceList.put(item.getAppId(), wxMpService);
+ item.getWxMpTempMap().putAll(item.getWxMpTemps().stream().collect(Collectors.toMap(WxMpTemp::getTypeCode, WxMpTemp -> WxMpTemp)));
+ wxMpMap.put(item.getAppId(), item);
+ });
+ log.info("公众号配置缓存成功!");
+ } else {
+ log.error("公众号配置数据为空,系统缓存失败!");
+ }
+ }
+
+ /**
+ * 获取对应公众号的配置信息
+ *
+ * @param appId
+ * @return
+ */
+ public WxMp getWxMp(String appId) {
+ return wxMpMap.get(appId);
+ }
+
+ /**
+ * 获取对应公众号的wxMpService
+ *
+ * @param appId
+ * @return
+ */
+ public WxMpService getWxMpService(String appId) {
+ return wxMpServiceList.get(appId);
+ }
+}
diff --git a/WXEngine/src/main/java/cn/crtech/cloud/wxengine/controller/WeiXinAPIController.java b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/controller/WeiXinAPIController.java
new file mode 100644
index 0000000..e559ad1
--- /dev/null
+++ b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/controller/WeiXinAPIController.java
@@ -0,0 +1,113 @@
+package cn.crtech.cloud.wxengine.controller;
+
+import cn.crtech.cloud.wxengine.config.WxMpConfig;
+import cn.crtech.cloud.wxengine.pojo.WxMp;
+import cn.crtech.cloud.wxengine.serveice.WxMpAccessService;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Date;
+
+@RestController
+@RequestMapping("/api")
+@Slf4j
+public class WeiXinAPIController {
+ @Autowired
+ private WxMpAccessService wxMpAccessService;
+
+ @Autowired
+ private WxMpConfig wxMpConfig;
+
+ /**
+ * 公众号消息接入
+ *
+ * @param signature 消息签名
+ * @param timestamp 时间戳
+ * @param nonce 随机字符串
+ * @param echostr 加密内容
+ * @return
+ */
+ @GetMapping("/message/{appId}")
+ @ResponseBody
+ public String message(@PathVariable("appId") String appId,
+ @RequestParam("signature") String signature,
+ @RequestParam("timestamp") String timestamp,
+ @RequestParam("nonce") String nonce,
+ @RequestParam("echostr") String echostr) {
+ WxMp wxMp = wxMpConfig.getWxMp(appId);
+ if (wxMp == null) {
+ log.error("系统没有此公众号({})配置", appId);
+ return "公众号配置信息异常";
+ }
+
+ if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
+ throw new IllegalArgumentException("请求参数非法,请核实!");
+ }
+ WxMpService wxMpService = wxMpConfig.getWxMpService(appId);
+ if (wxMpService == null) {
+ log.error("公众号配置信息异常");
+ return "公众号配置信息异常!";
+ }
+
+ if (wxMpService.checkSignature(timestamp, nonce, signature)) {
+ return echostr;
+ }
+
+ log.error("验证失败");
+ log.info("\n微信公众号消息服务中心接收消息: \nsignature:[{}] \ntimestamp:[{}] \nnonce:[{}] \nechostr:[{}]",
+ signature, timestamp, nonce, echostr);
+ return "";
+ }
+
+ /**
+ * 公众号消息处理
+ *
+ * @param requestBody 消息内容
+ * @param signature 消息签名
+ * @param timestamp 时间戳
+ * @param nonce 随机字符串
+ * @param openid 发送方openid
+ * @param encType 加密方式
+ * @param msgSignature 消息加密串
+ * @return
+ */
+ @PostMapping("/message/{appId}")
+ @ResponseBody
+ public String message(@RequestBody 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) {
+ WxMp wxMp = wxMpConfig.getWxMp(appId);
+ if (wxMp == null) {
+ log.error("系统没有此公众号({})配置", appId);
+ return "公众号配置信息异常";
+ }
+
+ Date start = new Date();
+ WxMpService wxMpService = wxMpConfig.getWxMpService(appId);
+ if (wxMpService == null) {
+ log.error("公众号配置信息异常");
+ return "公众号配置信息异常!";
+ }
+
+ if (encType == null) {
+ WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
+ log.info("花费时间 ==> {}", new Date().getTime() - start.getTime());
+ return wxMpAccessService.dealCenter(appId, wxMpService, inMessage);
+ } else if ("aes".equalsIgnoreCase(encType)) {
+ WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxMpService.getWxMpConfigStorage(),
+ timestamp, nonce, msgSignature);
+ log.info("花费时间 ==> {}", new Date().getTime() - start.getTime());
+ return wxMpAccessService.dealCenter(appId, wxMpService, inMessage);
+ }
+ return "";
+ }
+}
diff --git a/WXEngine/src/main/java/cn/crtech/cloud/wxengine/mapper/WxMpMapper.java b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/mapper/WxMpMapper.java
new file mode 100644
index 0000000..fec51c7
--- /dev/null
+++ b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/mapper/WxMpMapper.java
@@ -0,0 +1,19 @@
+package cn.crtech.cloud.wxengine.mapper;
+
+import cn.crtech.cloud.wxengine.pojo.WxMp;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+import tk.mybatis.mapper.common.Mapper;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by rxy on 2023-03-02 10:48:14
+ */
+@Repository
+public interface WxMpMapper extends Mapper {
+ List listWxMpByPage(Map params);
+
+ List getWxMpByList(@Param("status") int status);
+}
diff --git a/WXEngine/src/main/java/cn/crtech/cloud/wxengine/mapper/WxMpTempMapper.java b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/mapper/WxMpTempMapper.java
new file mode 100644
index 0000000..e6a75a5
--- /dev/null
+++ b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/mapper/WxMpTempMapper.java
@@ -0,0 +1,16 @@
+package cn.crtech.cloud.wxengine.mapper;
+
+import cn.crtech.cloud.wxengine.pojo.WxMpTemp;
+import org.springframework.stereotype.Repository;
+import tk.mybatis.mapper.common.Mapper;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by rxy on 2023-03-02 10:49:03
+ */
+@Repository
+public interface WxMpTempMapper extends Mapper {
+ List listWxMpTempByPage(Map params);
+}
diff --git a/WXEngine/src/main/java/cn/crtech/cloud/wxengine/pojo/WxMp.java b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/pojo/WxMp.java
new file mode 100644
index 0000000..57d189b
--- /dev/null
+++ b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/pojo/WxMp.java
@@ -0,0 +1,53 @@
+package cn.crtech.cloud.wxengine.pojo;
+
+import cn.crtech.cloud.common.annotation.DataExportAnnotation;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * Created by rxy on 2023-03-02 10:48:14
+ */
+@Data
+@Table(name = "cr_wx_mp")
+@DataExportAnnotation("微信公众号配置")
+public class WxMp implements Serializable {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @DataExportAnnotation("")
+ private Integer id;
+ @Column(name = "gzh_name")
+ @DataExportAnnotation("公众号名称")
+ private String gzhName;
+ @Column(name = "app_id")
+ @DataExportAnnotation("应用id")
+ private String appId;
+ @Column(name = "app_secret")
+ @DataExportAnnotation("公众号授权秘钥")
+ private String appSecret;
+ @Column(name = "app_token")
+ @DataExportAnnotation("公众号授权解码token")
+ private String appToken;
+ @Column(name = "app_aeskey")
+ @DataExportAnnotation("公众号授权解码key")
+ private String appAeskey;
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @Column(name = "created")
+ @DataExportAnnotation("创建时间")
+ private Date created;
+ @Column(name = "status")
+ @DataExportAnnotation("状态 0删除 1停用 2启用 ")
+ private Integer status;
+ @Column(name = "concat")
+ @DataExportAnnotation("服务器是否接通 0未接入 1接入成功")
+ private Integer concat;
+
+ @Transient
+ private List wxMpTemps = new ArrayList<>();
+
+ @Transient
+ private Map wxMpTempMap = new HashMap<>();
+}
diff --git a/WXEngine/src/main/java/cn/crtech/cloud/wxengine/pojo/WxMpTemp.java b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/pojo/WxMpTemp.java
new file mode 100644
index 0000000..fbe38af
--- /dev/null
+++ b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/pojo/WxMpTemp.java
@@ -0,0 +1,41 @@
+package cn.crtech.cloud.wxengine.pojo;
+
+import java.util.Date;
+import java.math.BigDecimal;
+import cn.crtech.cloud.common.annotation.DataExportAnnotation;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import java.io.Serializable;
+import lombok.*;
+import javax.persistence.*;
+
+/**
+ * Created by rxy on 2023-03-02 10:49:03
+ */
+@Data
+@Table(name = "cr_wx_mp_temp")
+@DataExportAnnotation("微信公众号模板配置")
+public class WxMpTemp implements Serializable {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @DataExportAnnotation("主键")
+ private Integer id;
+ @Column(name = "wx_mp_id")
+ @DataExportAnnotation("微信公众号id")
+ private Integer wxMpId;
+ @Column(name = "mp_temp")
+ @DataExportAnnotation("模板id")
+ private String mpTemp;
+ @Column(name = "temp_url")
+ @DataExportAnnotation("模板url")
+ private String tempUrl;
+ @Column(name = "type_code")
+ @DataExportAnnotation("类型id 关联字典")
+ private String typeCode;
+ @Column(name = "status")
+ @DataExportAnnotation("0 禁用 1启用")
+ private Integer status;
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @Column(name = "created")
+ @DataExportAnnotation("创建时间")
+ private Date created;
+}
diff --git a/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/AbstractBuilder.java b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/AbstractBuilder.java
new file mode 100644
index 0000000..312ea8c
--- /dev/null
+++ b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/AbstractBuilder.java
@@ -0,0 +1,15 @@
+package cn.crtech.cloud.wxengine.serveice;
+
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+
+/**
+ * desc
+ *
+ * @Author: TYP
+ * @Date: 2022-06-10 10:46
+ */
+public abstract class AbstractBuilder {
+ public abstract WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, WxMpService service);
+}
diff --git a/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/BaseService.java b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/BaseService.java
new file mode 100644
index 0000000..e2a04a3
--- /dev/null
+++ b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/BaseService.java
@@ -0,0 +1,50 @@
+package cn.crtech.cloud.wxengine.serveice;
+
+import cn.crtech.cloud.common.dto.Result;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+import tk.mybatis.mapper.common.Mapper;
+
+import java.util.Map;
+
+public abstract class BaseService {
+ public abstract Mapper getMapper();
+
+ @Transactional(propagation = Propagation.REQUIRED)
+ public Result add(T obj) {
+ getMapper().insert(obj);
+ return Result.success(obj, "操作成功!");
+ }
+
+ @Transactional(propagation = Propagation.REQUIRED)
+ public Result update(T obj) {
+ getMapper().updateByPrimaryKeySelective(obj);
+ return Result.success(obj, "操作成功!");
+ }
+
+ @Transactional(propagation = Propagation.REQUIRED)
+ public Result deleteById(int id) {
+ getMapper().deleteByPrimaryKey(id);
+ return Result.success(id, "操作成功!");
+ }
+
+ @Transactional(propagation = Propagation.REQUIRED)
+ public Result delete(T obj) {
+ getMapper().delete(obj);
+ return Result.success(obj, "操作成功!");
+ }
+
+
+ public T getById(int id) {
+ return (T) getMapper().selectByPrimaryKey(id);
+ }
+
+ public T getById(String id) {
+ return (T) getMapper().selectByPrimaryKey(id);
+ }
+
+ public abstract Result listByPage(Map params);
+
+ public abstract Result listByParams(Map params);
+
+}
diff --git a/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/WxMpAccessService.java b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/WxMpAccessService.java
new file mode 100644
index 0000000..78e44f3
--- /dev/null
+++ b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/WxMpAccessService.java
@@ -0,0 +1,113 @@
+package cn.crtech.cloud.wxengine.serveice;
+
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.mp.api.WxMpService;
+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 org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Map;
+
+/**
+ * 微信公众号事件处理 实现层
+ */
+
+@Slf4j
+@Service
+public class WxMpAccessService {
+ /**
+ * 消息/事件处理中心
+ *
+ * @param wxMpService
+ * @param inMessage
+ * @return
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public String dealCenter(String appId, WxMpService wxMpService, WxMpXmlMessage inMessage) {
+ if (!StringUtils.isEmpty(inMessage.getEvent())) {
+ return this.eventCenter(appId, wxMpService, inMessage, inMessage.getEvent());
+ } else {
+ // todo 消息处理
+ String msgType = inMessage.getMsgType();
+ // msgType = text 主动推送
+ WxMpXmlOutMessage build = new WxMpTextBuilder().build("123456", inMessage, wxMpService);
+ System.out.println("回复消息 ==> \n" + build.toXml());
+ return build.toXml();
+ }
+ }
+
+ /**
+ * 事件处理中心
+ *
+ * @param wxMpService
+ * @param inMessage
+ * @param eventName
+ * @return
+ */
+ private String eventCenter(String appId, WxMpService wxMpService, WxMpXmlMessage inMessage, String eventName) {
+ String reply = "";
+ String wxOpenId = inMessage.getFromUser();
+
+ switch (eventName) {
+ case "subscribe":
+ String content = "超然静配欢迎您的关注!";
+ reply = new WxMpTextBuilder().build(content, inMessage, wxMpService).toXml();
+ break;
+ case "unsubscribe":
+
+ break;
+ case "SCAN":
+ log.info("公众号({})用户({})扫码事件接收", appId, wxOpenId);
+ break;
+ case "CLICK":
+ reply = eventKeyCenter(appId, wxMpService, inMessage, inMessage.getEventKey());
+ break;
+ default:
+ reply = "";
+ }
+ return reply;
+ }
+
+ private String eventKeyCenter(String appId, WxMpService wxMpService, WxMpXmlMessage inMessage, String eventKey) {
+ String reply = "";
+ switch (eventKey) {
+ case "click_get_kf_url":
+ // todo 测试用 售前客服 待其他关系库完善后再进行处理
+ break;
+ case "click_get_kf_url_back":
+ // 售后客服
+ break;
+ default:
+ break;
+ }
+ return reply;
+ }
+
+ /**
+ * 主动发送消息接口
+ *
+ * @param sendMsg 发送内容 包括content以及消息接收方
+ * @param wxMpService 对应的发送服务
+ * @return
+ */
+ public Boolean sendMsg(Map sendMsg, WxMpService wxMpService) {
+ String content = sendMsg.get("content").toString();
+ String toUser = sendMsg.get("toUser").toString();
+
+ WxMpKefuMessage wxMpKefuMessage = new WxMpKefuMessage();
+ wxMpKefuMessage.setContent(content);
+ wxMpKefuMessage.setToUser(toUser);
+ wxMpKefuMessage.setMsgType("text");
+
+ try {
+ return wxMpService.getKefuService().sendKefuMessage(wxMpKefuMessage);
+ } catch (WxErrorException e) {
+ log.error("主动发送消息失败 , 原因 ==> {}", e.getMessage());
+ return false;
+ }
+ }
+}
diff --git a/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/WxMpService.java b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/WxMpService.java
new file mode 100644
index 0000000..cb3add3
--- /dev/null
+++ b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/WxMpService.java
@@ -0,0 +1,49 @@
+package cn.crtech.cloud.wxengine.serveice;
+
+import cn.crtech.cloud.common.dto.Result;
+import cn.crtech.cloud.wxengine.mapper.WxMpMapper;
+import cn.crtech.cloud.wxengine.pojo.WxMp;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import tk.mybatis.mapper.common.Mapper;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by rxy on 2023-03-02 10:48:14
+ */
+@Service
+@Transactional(readOnly = true)
+public class WxMpService extends BaseService {
+ @Autowired
+ WxMpMapper wxMpMapper;
+
+ @Override
+ public Mapper getMapper() {
+ return wxMpMapper;
+ }
+
+ @Override
+ public Result listByPage(Map params) {
+ List data;
+ if(params != null){
+ PageHelper.startPage( params );
+ data = wxMpMapper.listWxMpByPage(params);
+ }else{
+ data = new ArrayList<>();
+ }
+ PageInfo page = new PageInfo( data );
+ return Result.success(page);
+ }
+
+ @Override
+ public Result listByParams(Map params) {
+ return null;
+ }
+
+}
diff --git a/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/WxMpTempService.java b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/WxMpTempService.java
new file mode 100644
index 0000000..8b9de8f
--- /dev/null
+++ b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/WxMpTempService.java
@@ -0,0 +1,49 @@
+package cn.crtech.cloud.wxengine.serveice;
+
+import cn.crtech.cloud.common.dto.Result;
+import cn.crtech.cloud.wxengine.mapper.WxMpTempMapper;
+import cn.crtech.cloud.wxengine.pojo.WxMpTemp;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import tk.mybatis.mapper.common.Mapper;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by rxy on 2023-03-02 10:49:03
+ */
+@Service
+@Transactional(readOnly = true)
+public class WxMpTempService extends BaseService {
+ @Autowired
+ WxMpTempMapper wxMpTempMapper;
+
+ @Override
+ public Mapper getMapper() {
+ return wxMpTempMapper;
+ }
+
+ @Override
+ public Result listByPage(Map params) {
+ List data;
+ if (params != null) {
+ PageHelper.startPage(params);
+ data = wxMpTempMapper.listWxMpTempByPage(params);
+ } else {
+ data = new ArrayList<>();
+ }
+ PageInfo page = new PageInfo(data);
+ return Result.success(page);
+ }
+
+ @Override
+ public Result listByParams(Map params) {
+ return null;
+ }
+
+}
diff --git a/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/WxMpTextBuilder.java b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/WxMpTextBuilder.java
new file mode 100644
index 0000000..69e10bd
--- /dev/null
+++ b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/serveice/WxMpTextBuilder.java
@@ -0,0 +1,23 @@
+package cn.crtech.cloud.wxengine.serveice;
+
+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: TYP
+ * @Date: 2022-06-10 10:47
+ */
+public class WxMpTextBuilder extends AbstractBuilder {
+ @Override
+ public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
+ WxMpService service) {
+ WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content(content)
+ .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
+ .build();
+ return m;
+ }
+}
diff --git a/WXEngine/src/main/java/cn/crtech/cloud/wxengine/utils/CodeUtils.java b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/utils/CodeUtils.java
new file mode 100644
index 0000000..3612736
--- /dev/null
+++ b/WXEngine/src/main/java/cn/crtech/cloud/wxengine/utils/CodeUtils.java
@@ -0,0 +1,22 @@
+package cn.crtech.cloud.wxengine.utils;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class CodeUtils {
+ private static byte[] lock = new byte[0];
+
+ private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssss");
+
+ // 位数,默认是8位
+ private final static long w = 5;
+
+ public static String createID(String Prefix) {
+ long r = 0;
+ synchronized (lock) {
+ r = (long) ((Math.random() + 1) * w);
+ }
+
+ return Prefix + sdf.format(new Date()) + String.valueOf(r).substring(1);
+ }
+}
diff --git a/WXEngine/src/main/resources/application-dev.yml b/WXEngine/src/main/resources/application-dev.yml
new file mode 100644
index 0000000..ef6b747
--- /dev/null
+++ b/WXEngine/src/main/resources/application-dev.yml
@@ -0,0 +1,37 @@
+server:
+ port: 2001
+ servlet:
+ encoding:
+ charset: utf-8
+ enabled: true
+ force: true
+spring:
+ servlet:
+ multipart:
+ max-file-size: 50MB
+ max-request-size: 50MB
+ jackson:
+ date-format: yyyy-MM-dd HH:mm:ss
+ time-zone: GMT+8
+ redis:
+ database: 0
+ port: 6379
+ host: localhost
+ password:
+mybatis:
+ mapper-locations: classpath*:/mapper/*Mapper.xml
+ type-aliases-package: cn.crtech.cloud.common.pojo.general,cn.crtech.cloud.common.dto.general
+ #配置驼峰下划线
+ configuration:
+ map-underscore-to-camel-case: true
+logging:
+ config: classpath:logback.xml
+ file:
+ path: logs/crtech-service-wxengine.log
+ level:
+ cn.crtech.cloud.customer: debug
+weixin:
+ appid: wxc74a3f37e8bdfbed # 设置微信公众号的appid
+ secret: bd58cb0e336efbed8faf907931d2d974 # 设置微信公众号的app corpSecret
+ token: Crtech # 设置微信公众号的token
+ aes-token: yHEUfbxwnmKcjRnMQBWekDo9QvGfHCkC0IRrlbNpg5H # 设置微信公众号的EncodingAESKey
diff --git a/WXEngine/src/main/resources/application-prod.yml b/WXEngine/src/main/resources/application-prod.yml
new file mode 100644
index 0000000..e438c1e
--- /dev/null
+++ b/WXEngine/src/main/resources/application-prod.yml
@@ -0,0 +1,40 @@
+server:
+ port: 8087
+ servlet:
+ encoding:
+ charset: utf-8
+ enabled: true
+ force: true
+spring:
+ servlet:
+ multipart:
+ max-file-size: 50MB
+ max-request-size: 50MB
+ jackson:
+ date-format: yyyy-MM-dd HH:mm:ss
+ time-zone: GMT+8
+ redis:
+ database: 0
+ port: 6397
+ host: chaoran.crtech.cn
+ password:
+mybatis:
+ mapper-locations: classpath*:/mapper/*Mapper.xml
+ type-aliases-package: cn.crtech.cloud.common.pojo.customer,cn.crtech.cloud.common.dto.customer
+ #配置驼峰下划线
+ configuration:
+ map-underscore-to-camel-case: true
+logging:
+ config: classpath:logback.xml
+ file:
+ path: logs/crtech-service-customer.log
+ level:
+ cn.crtech.cloud.customer: debug
+wx:
+ mp:
+ domain: http://crcloud.crtech.cn/client
+LingKaiSMS:
+ CorpID: CRTECH00002
+ Pwd: crtech
+ domain: https://mb345.com/ws/BatchSend2.aspx
+
diff --git a/WXEngine/src/main/resources/bootstrap-dev.yml b/WXEngine/src/main/resources/bootstrap-dev.yml
new file mode 100644
index 0000000..4e1725c
--- /dev/null
+++ b/WXEngine/src/main/resources/bootstrap-dev.yml
@@ -0,0 +1,13 @@
+spring:
+ application:
+ name: crtech-cloud-wxengine # 项目名称尽量用小写
+ cloud:
+ nacos:
+ discovery:
+ server-addr: localhost:8848
+ datasource:
+ url: jdbc:mysql://chaoran.crtech.cn:9803/cr_cloud_general_dev?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
+ username: 406EB1CDA013F64723B971DBD68B8511
+ password: 086B2FA5626018DE67E865D13134D67B9BC1AEBE46D471A439DECA0725908C65
+
+
diff --git a/WXEngine/src/main/resources/bootstrap-prod.yml b/WXEngine/src/main/resources/bootstrap-prod.yml
new file mode 100644
index 0000000..d34e188
--- /dev/null
+++ b/WXEngine/src/main/resources/bootstrap-prod.yml
@@ -0,0 +1,13 @@
+spring:
+ application:
+ name: crtech-cloud-wxengine # 项目名称尽量用小写
+ cloud:
+ nacos:
+ discovery:
+ server-addr: http://chaoran.crtech.cn:28848
+ datasource:
+ url: jdbc:mysql://chaoran.crtech.cn:9803/cr_cloud_customer?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true&allowMultiQueries=true
+ username: 406EB1CDA013F64723B971DBD68B8511
+ password: 086B2FA5626018DE67E865D13134D67B9BC1AEBE46D471A439DECA0725908C65
+
+
diff --git a/WXEngine/src/main/resources/bootstrap.yml b/WXEngine/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..76d483d
--- /dev/null
+++ b/WXEngine/src/main/resources/bootstrap.yml
@@ -0,0 +1,5 @@
+spring:
+ profiles:
+ active: dev
+
+
diff --git a/WXEngine/src/main/resources/logback.xml b/WXEngine/src/main/resources/logback.xml
new file mode 100644
index 0000000..9cde327
--- /dev/null
+++ b/WXEngine/src/main/resources/logback.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+ logs/crtech-service-wxengine.%d{yyyy-MM-dd}.log
+
+
+
+
+ %d{yyyy-MM-dd_HH:mm:ss} %logger{18} -%msg%n
+
+
+
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+ 0
+ 1000
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WXEngine/src/main/resources/mapper/WxMpMapper.xml b/WXEngine/src/main/resources/mapper/WxMpMapper.xml
new file mode 100644
index 0000000..1eef0dc
--- /dev/null
+++ b/WXEngine/src/main/resources/mapper/WxMpMapper.xml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a.id,a.gzh_name,a.app_id,a.app_secret,a.app_token,a.app_aeskey,a.created,a.status
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WXEngine/src/main/resources/mapper/WxMpTempMapper.xml b/WXEngine/src/main/resources/mapper/WxMpTempMapper.xml
new file mode 100644
index 0000000..200bf14
--- /dev/null
+++ b/WXEngine/src/main/resources/mapper/WxMpTempMapper.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a.id,a.wx_mp_id,a.mp_temp,a.type_code,a.status,a.created
+
+
+
+