fix(*) 首次提交WXEngine项目

This commit is contained in:
2023-08-23 16:40:17 +08:00
parent 4d8f27a991
commit a21f6803f9
26 changed files with 1221 additions and 0 deletions

177
WXEngine/pom.xml Normal file
View File

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.crtech.cloud.wxengine</groupId>
<artifactId>WXEngine</artifactId>
<version>1.0.1</version>
<!-- 父工程 -->
<parent>
<groupId>cn.crtech.cloud.dependencies</groupId>
<artifactId>Dependencies</artifactId>
<version>1.0.1</version>
<relativePath/>
</parent>
<!-- 依赖的版本锁定 -->
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<common.version>1.0.1</common.version>
<jsoup.version>1.14.3</jsoup.version>
<mssql.version>6.4.0.jre8</mssql.version>
<wx.mp.version>4.3.0</wx.mp.version>
<normal.wx.version>4.2.0</normal.wx.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- nacos 客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!--feign依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.crtech.cloud.common</groupId>
<artifactId>Common</artifactId>
<version>${common.version}</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>${mssql.version}</version>
<scope>runtime</scope>
</dependency>
<!-- 微信公众号API -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>${wx.mp.version}</version>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
<exclusion>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 微信小程序weixin-java-miniapp -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
<version>${normal.wx.version}</version>
</dependency>
<!-- 企业号/企业微信weixin-java-cp -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-cp</artifactId>
<version>${normal.wx.version}</version>
</dependency>
<!-- 微信支付weixin-java-pay -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>${normal.wx.version}</version>
</dependency>
<!-- 微信开放平台weixin-java-open -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-open</artifactId>
<version>${normal.wx.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<jvmArguments>-Dfile.encoding=UTF-8</jvmArguments>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -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

View File

@ -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;
}
}

View File

@ -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<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> 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;
}
}

View File

@ -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<String, WxMp> wxMpMap;
private Map<String, WxMpService> wxMpServiceList;
@PostConstruct
public void initWxConfig() {
this.initWxMp();
}
public void initWxMp() {
wxMpServiceList = new HashMap<>();
wxMpMap = new HashMap<>();
List<WxMp> 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);
}
}

View File

@ -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 "";
}
}

View File

@ -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<WxMp> {
List<WxMp> listWxMpByPage(Map<String, Object> params);
List<WxMp> getWxMpByList(@Param("status") int status);
}

View File

@ -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<WxMpTemp> {
List<WxMpTemp> listWxMpTempByPage(Map<String, Object> params);
}

View File

@ -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<WxMpTemp> wxMpTemps = new ArrayList<>();
@Transient
private Map<String, WxMpTemp> wxMpTempMap = new HashMap<>();
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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<T> {
public abstract Mapper<T> 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<String, Object> params);
public abstract Result listByParams(Map<String, Object> params);
}

View File

@ -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<String, Object> 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;
}
}
}

View File

@ -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<WxMp> {
@Autowired
WxMpMapper wxMpMapper;
@Override
public Mapper<WxMp> getMapper() {
return wxMpMapper;
}
@Override
public Result listByPage(Map<String, Object> params) {
List<WxMp> 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<String, Object> params) {
return null;
}
}

View File

@ -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<WxMpTemp> {
@Autowired
WxMpTempMapper wxMpTempMapper;
@Override
public Mapper<WxMpTemp> getMapper() {
return wxMpTempMapper;
}
@Override
public Result listByPage(Map<String, Object> params) {
List<WxMpTemp> 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<String, Object> params) {
return null;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,5 @@
spring:
profiles:
active: dev

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/crtech-service-wxengine.%d{yyyy-MM-dd}.log
</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd_HH:mm:ss} %logger{18} -%msg%n
</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>1000</queueSize>
<appender-ref ref="FILE"/>
</appender>
<logger name="org" level="info" additivity="false">
<appender-ref ref="FILE"></appender-ref>
<appender-ref ref="STDOUT"></appender-ref>
</logger>
<logger name="com" level="info" additivity="false">
<appender-ref ref="FILE"></appender-ref>
<appender-ref ref="STDOUT"></appender-ref>
</logger>
<logger name="net" level="info" additivity="false">
<appender-ref ref="FILE"></appender-ref>
<appender-ref ref="STDOUT"></appender-ref>
</logger>
<logger name="com.netflix" level="debug" additivity="false">
<appender-ref ref="STDOUT"></appender-ref>
<appender-ref ref="FILE"></appender-ref>
</logger>
<logger name="cn.crtech.cloud.wxengine" level="debug" additivity="false">
<appender-ref ref="STDOUT"></appender-ref>
<appender-ref ref="FILE"></appender-ref>
</logger>
<root level="INFO">
<appender-ref ref="ASYNC"/>
</root>
</configuration>

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Created by rxy on 2023-03-02 10:48:14-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.crtech.cloud.wxengine.mapper.WxMpMapper">
<resultMap id="BaseResultMap" type="cn.crtech.cloud.wxengine.pojo.WxMp">
<id column="id" jdbcType="INTEGER" property="id"/>
<result column="gzh_name" jdbcType="VARCHAR" property="gzhName"/>
<result column="app_id" jdbcType="VARCHAR" property="appId"/>
<result column="app_secret" jdbcType="VARCHAR" property="appSecret"/>
<result column="app_token" jdbcType="VARCHAR" property="appToken"/>
<result column="app_aeskey" jdbcType="VARCHAR" property="appAeskey"/>
<result column="created" jdbcType="TIMESTAMP" property="created"/>
<result column="status" jdbcType="INTEGER" property="status"/>
</resultMap>
<sql id="basic_list">
a.id,a.gzh_name,a.app_id,a.app_secret,a.app_token,a.app_aeskey,a.created,a.status
</sql>
<select id="listWxMpByPage" resultMap="BaseResultMap" parameterType="map">
SELECT
<include refid="basic_list"/>
FROM cr_wx_mp a
<where>
<if test="id!=null and id!='' ">
and a.id=#{id}
</if>
<if test="gzhName!=null and gzhName!='' ">
and a.gzh_name LIKE CONCAT('%', #{gzhName}, '%')
</if>
<if test="appId!=null and appId!='' ">
and a.app_id=#{appId}
</if>
<if test="appSecret!=null and appSecret!='' ">
and a.app_secret LIKE CONCAT('%', #{appSecret}, '%')
</if>
<if test="appToken!=null and appToken!='' ">
and a.app_token LIKE CONCAT('%', #{appToken}, '%')
</if>
<if test="appAeskey!=null and appAeskey!='' ">
and a.app_aeskey LIKE CONCAT('%', #{appAeskey}, '%')
</if>
<if test="created!=null and created!='' ">
and a.created LIKE CONCAT('%', #{created}, '%')
</if>
<if test="status!=null and status!='' ">
and a.status LIKE CONCAT('%', #{status}, '%')
</if>
<if test="concat!=null and concat!='' ">
and a.concat LIKE CONCAT('%', #{concat}, '%')
</if>
</where>
</select>
<resultMap id="getWxMpResultMap" type="cn.crtech.cloud.wxengine.pojo.WxMp">
<id column="id" jdbcType="INTEGER" property="id"/>
<result column="gzh_name" jdbcType="VARCHAR" property="gzhName"/>
<result column="app_id" jdbcType="VARCHAR" property="appId"/>
<result column="app_secret" jdbcType="VARCHAR" property="appSecret"/>
<result column="app_token" jdbcType="VARCHAR" property="appToken"/>
<result column="app_aeskey" jdbcType="VARCHAR" property="appAeskey"/>
<result column="created" jdbcType="TIMESTAMP" property="created"/>
<result column="status" jdbcType="INTEGER" property="status"/>
<collection property="wxMpTemps" column="id" ofType="cn.crtech.cloud.common.pojo.mns.WxMpTemp"
select="getWxMpTempByWxMpId">
<result column="wx_mp_id" jdbcType="INTEGER" property="wxMpId"/>
<result column="mp_temp" jdbcType="VARCHAR" property="mpTemp"/>
<result column="temp_url" jdbcType="VARCHAR" property="tempUrl"/>
<result column="type_code" jdbcType="VARCHAR" property="typeCode"/>
</collection>
</resultMap>
<select id="getWxMpByList" resultMap="getWxMpResultMap" parameterType="java.lang.Integer">
SELECT
<include refid="basic_list"/>
FROM cr_wx_mp a
where
a.status = #{status}
</select>
<select id="getWxMpTempByWxMpId" resultType="cn.crtech.cloud.wxengine.pojo.WxMpTemp">
SELECT a.id,
a.wx_mp_id,
a.mp_temp,
a.type_code,
a.status,
a.created
FROM cr_wx_mp_temp a
where a.wx_mp_id = #{wxMpId}
</select>
</mapper>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Created by rxy on 2023-03-02 10:49:03-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.crtech.cloud.wxengine.mapper.WxMpTempMapper">
<resultMap id="BaseResultMap" type="cn.crtech.cloud.wxengine.pojo.WxMpTemp">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="wx_mp_id" jdbcType="INTEGER" property="wxMpId" />
<result column="mp_temp" jdbcType="VARCHAR" property="mpTemp" />
<result column="type_code" jdbcType="VARCHAR" property="typeCode" />
<result column="status" jdbcType="INTEGER" property="status" />
<result column="created" jdbcType="TIMESTAMP" property="created" />
</resultMap>
<sql id="basic_list">
a.id,a.wx_mp_id,a.mp_temp,a.type_code,a.status,a.created
</sql>
<select id="listWxMpTempByPage" resultMap="BaseResultMap" parameterType="map">
SELECT
<include refid="basic_list"/>
FROM cr_wx_mp_temp a
<where>
<if test="id!=null and id!='' ">
and a.id=#{id}
</if>
<if test="wxMpId!=null and wxMpId!='' ">
and a.wx_mp_id=#{wxMpId}
</if>
<if test="mpTemp!=null and mpTemp!='' ">
and a.mp_temp LIKE CONCAT('%', #{mpTemp}, '%')
</if>
<if test="typeId!=null and typeId!='' ">
and a.type_id=#{typeId}
</if>
<if test="status!=null and status!='' ">
and a.status LIKE CONCAT('%', #{status}, '%')
</if>
<if test="created!=null and created!='' ">
and a.created LIKE CONCAT('%', #{created}, '%')
</if>
</where>
</select>
</mapper>