From 468b2212697f7d7c1c1691d1866aab3e2e2574cf Mon Sep 17 00:00:00 2001 From: tianyongbao Date: Wed, 8 Jan 2025 15:22:23 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=BE=AE=E4=BF=A1=E5=85=AC=E4=BC=97?= =?UTF-8?q?=E5=8F=B7=E5=BE=AE=E6=9C=8D=E5=8A=A1=E6=B7=BB=E5=8A=A0=E5=8F=8A?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-common/ruoyi-common-core/pom.xml | 12 + .../common/core/sensitive/Sensitive.java | 28 ++ .../core/sensitive/SensitiveSerialize.java | 68 +++++ .../core/sensitive/SensitiveTypeEnum.java | 32 +++ .../typehandler/ArrayLongTypeHandler.java | 48 ++++ .../typehandler/ArrayStringTypeHandler.java | 48 ++++ .../core/typehandler/JsonTypeHandler.java | 50 ++++ .../common/core/utils/SensitiveUtils.java | 153 ++++++++++ .../common/core/utils/http/HttpHelper.java | 57 ++++ .../common/core/utils/http/HttpUtils.java | 267 ++++++++++++++++++ ruoyi-modules/intc-weixin/README.md | 1 + ruoyi-modules/intc-weixin/pom.xml | 214 ++++++++++++++ .../java/com/ruoyi/IntcWeixinApplication.java | 25 ++ .../ruoyi/config/ActuatorSecurityConfig.java | 44 +++ .../ruoyi/weixin/builder/AbstractBuilder.java | 40 +++ .../ruoyi/weixin/builder/ImageBuilder.java | 47 +++ .../com/ruoyi/weixin/builder/TextBuilder.java | 45 +++ .../ruoyi/weixin/config/CommonConstants.java | 47 +++ .../com/ruoyi/weixin/config/WebConfig.java | 34 +++ .../weixin/config/WxMaConfiguration.java | 148 ++++++++++ .../ruoyi/weixin/config/WxMaProperties.java | 80 ++++++ .../weixin/config/WxMpConfiguration.java | 132 +++++++++ .../ruoyi/weixin/config/WxMpProperties.java | 69 +++++ .../weixin/config/WxPayConfiguration.java | 51 ++++ .../ruoyi/weixin/constant/ConfigConstant.java | 106 +++++++ .../ruoyi/weixin/constant/MyReturnCode.java | 75 +++++ .../weixin/constant/WebSocketConstant.java | 34 +++ .../ruoyi/weixin/constant/WxMaConstants.java | 39 +++ .../ruoyi/weixin/constant/WxReturnCode.java | 259 +++++++++++++++++ .../weixin/controller/WeChatController.java | 58 ++++ .../controller/WxAutoReplyController.java | 148 ++++++++++ .../weixin/controller/WxDraftController.java | 141 +++++++++ .../controller/WxFreePublishController.java | 81 ++++++ .../controller/WxMaterialController.java | 266 +++++++++++++++++ .../weixin/controller/WxMenuController.java | 84 ++++++ .../weixin/controller/WxMsgController.java | 222 +++++++++++++++ .../weixin/controller/WxPortalController.java | 128 +++++++++ .../controller/WxSummaryController.java | 127 +++++++++ .../weixin/controller/WxUserController.java | 195 +++++++++++++ .../controller/WxUserTagsController.java | 174 ++++++++++++ .../com/ruoyi/weixin/entity/ImageManager.java | 42 +++ .../com/ruoyi/weixin/entity/LoginMaDTO.java | 8 + .../java/com/ruoyi/weixin/entity/Menu.java | 63 +++++ .../com/ruoyi/weixin/entity/MenuButton.java | 91 ++++++ .../com/ruoyi/weixin/entity/ThirdSession.java | 48 ++++ .../com/ruoyi/weixin/entity/WxAutoReply.java | 143 ++++++++++ .../java/com/ruoyi/weixin/entity/WxMenu.java | 142 ++++++++++ .../java/com/ruoyi/weixin/entity/WxMsg.java | 166 +++++++++++ .../java/com/ruoyi/weixin/entity/WxMsgVO.java | 48 ++++ .../ruoyi/weixin/entity/WxOpenDataDTO.java | 18 ++ .../java/com/ruoyi/weixin/entity/WxUser.java | 175 ++++++++++++ .../ruoyi/weixin/entity/WxUserTagsDict.java | 32 +++ .../ruoyi/weixin/handler/AbstractHandler.java | 35 +++ .../weixin/handler/KfSessionHandler.java | 48 ++++ .../ruoyi/weixin/handler/LocationHandler.java | 68 +++++ .../com/ruoyi/weixin/handler/LogHandler.java | 62 ++++ .../com/ruoyi/weixin/handler/MenuHandler.java | 194 +++++++++++++ .../com/ruoyi/weixin/handler/MsgHandler.java | 234 +++++++++++++++ .../com/ruoyi/weixin/handler/NullHandler.java | 47 +++ .../com/ruoyi/weixin/handler/ScanHandler.java | 47 +++ .../handler/StoreCheckNotifyHandler.java | 50 ++++ .../weixin/handler/SubscribeHandler.java | 110 ++++++++ .../weixin/handler/UnsubscribeHandler.java | 71 +++++ .../interceptor/ThirdSessionInterceptor.java | 70 +++++ .../weixin/mapper/WxAutoReplyMapper.java | 37 +++ .../com/ruoyi/weixin/mapper/WxMenuMapper.java | 37 +++ .../com/ruoyi/weixin/mapper/WxMsgMapper.java | 50 ++++ .../com/ruoyi/weixin/mapper/WxUserMapper.java | 37 +++ .../weixin/service/WxAutoReplyService.java | 37 +++ .../ruoyi/weixin/service/WxMenuService.java | 52 ++++ .../ruoyi/weixin/service/WxMsgService.java | 49 ++++ .../ruoyi/weixin/service/WxUserService.java | 81 ++++++ .../service/impl/WxAutoReplyServiceImpl.java | 41 +++ .../service/impl/WxMenuServiceImpl.java | 183 ++++++++++++ .../weixin/service/impl/WxMsgServiceImpl.java | 50 ++++ .../service/impl/WxUserServiceImpl.java | 264 +++++++++++++++++ .../com/ruoyi/weixin/utils/CheckUtil.java | 28 ++ .../com/ruoyi/weixin/utils/FileUtils.java | 85 ++++++ .../com/ruoyi/weixin/utils/JsonUtils.java | 39 +++ .../weixin/utils/LocalDateTimeUtils.java | 115 ++++++++ .../java/com/ruoyi/weixin/utils/SHA1.java | 35 +++ .../weixin/utils/ThirdSessionHolder.java | 48 ++++ .../java/com/ruoyi/weixin/utils/WxMaUtil.java | 23 ++ .../intc-weixin/src/main/resources/banner.txt | 24 ++ .../src/main/resources/bootstrap.yml | 41 +++ .../src/main/resources/logback.xml | 74 +++++ .../mapper/weixin/WxAutoReplyMapper.xml | 33 +++ .../resources/mapper/weixin/WxMenuMapper.xml | 33 +++ .../resources/mapper/weixin/WxMsgMapper.xml | 73 +++++ .../resources/mapper/weixin/WxUserMapper.xml | 42 +++ ruoyi-modules/pom.xml | 1 + 91 files changed, 7501 insertions(+) create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/sensitive/Sensitive.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/sensitive/SensitiveSerialize.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/sensitive/SensitiveTypeEnum.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/typehandler/ArrayLongTypeHandler.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/typehandler/ArrayStringTypeHandler.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/typehandler/JsonTypeHandler.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SensitiveUtils.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/http/HttpHelper.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/http/HttpUtils.java create mode 100644 ruoyi-modules/intc-weixin/README.md create mode 100644 ruoyi-modules/intc-weixin/pom.xml create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/IntcWeixinApplication.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/config/ActuatorSecurityConfig.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/builder/AbstractBuilder.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/builder/ImageBuilder.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/builder/TextBuilder.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/CommonConstants.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WebConfig.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxMaConfiguration.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxMaProperties.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxMpConfiguration.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxMpProperties.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxPayConfiguration.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/ConfigConstant.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/MyReturnCode.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/WebSocketConstant.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/WxMaConstants.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/WxReturnCode.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WeChatController.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxAutoReplyController.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxDraftController.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxFreePublishController.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxMaterialController.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxMenuController.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxMsgController.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxPortalController.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxSummaryController.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxUserController.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxUserTagsController.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/ImageManager.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/LoginMaDTO.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/Menu.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/MenuButton.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/ThirdSession.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxAutoReply.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxMenu.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxMsg.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxMsgVO.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxOpenDataDTO.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxUser.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxUserTagsDict.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/AbstractHandler.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/KfSessionHandler.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/LocationHandler.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/LogHandler.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/MenuHandler.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/MsgHandler.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/NullHandler.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/ScanHandler.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/StoreCheckNotifyHandler.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/SubscribeHandler.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/UnsubscribeHandler.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/interceptor/ThirdSessionInterceptor.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/mapper/WxAutoReplyMapper.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/mapper/WxMenuMapper.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/mapper/WxMsgMapper.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/mapper/WxUserMapper.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/WxAutoReplyService.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/WxMenuService.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/WxMsgService.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/WxUserService.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/impl/WxAutoReplyServiceImpl.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/impl/WxMenuServiceImpl.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/impl/WxMsgServiceImpl.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/impl/WxUserServiceImpl.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/CheckUtil.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/FileUtils.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/JsonUtils.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/LocalDateTimeUtils.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/SHA1.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/ThirdSessionHolder.java create mode 100644 ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/WxMaUtil.java create mode 100644 ruoyi-modules/intc-weixin/src/main/resources/banner.txt create mode 100644 ruoyi-modules/intc-weixin/src/main/resources/bootstrap.yml create mode 100644 ruoyi-modules/intc-weixin/src/main/resources/logback.xml create mode 100644 ruoyi-modules/intc-weixin/src/main/resources/mapper/weixin/WxAutoReplyMapper.xml create mode 100644 ruoyi-modules/intc-weixin/src/main/resources/mapper/weixin/WxMenuMapper.xml create mode 100644 ruoyi-modules/intc-weixin/src/main/resources/mapper/weixin/WxMsgMapper.xml create mode 100644 ruoyi-modules/intc-weixin/src/main/resources/mapper/weixin/WxUserMapper.xml diff --git a/ruoyi-common/ruoyi-common-core/pom.xml b/ruoyi-common/ruoyi-common-core/pom.xml index 8c59a54..9fed7c0 100644 --- a/ruoyi-common/ruoyi-common-core/pom.xml +++ b/ruoyi-common/ruoyi-common-core/pom.xml @@ -133,6 +133,18 @@ core 3.4.1 + + + cn.hutool + hutool-all + 5.1.0 + + + + com.baomidou + mybatis-plus-extension + 3.5.5 + diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/sensitive/Sensitive.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/sensitive/Sensitive.java new file mode 100644 index 0000000..b23b89f --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/sensitive/Sensitive.java @@ -0,0 +1,28 @@ +package com.ruoyi.common.core.sensitive; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 脱敏注解 + * + * @author JooLun + * @Author: https://www.cnblogs.com/xiluonanfeng/p/10183926.html + **/ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@JacksonAnnotationsInside +@JsonSerialize(using = SensitiveSerialize.class) +public @interface Sensitive { + + /** + * 脱敏数据类型 + */ + SensitiveTypeEnum type(); + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/sensitive/SensitiveSerialize.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/sensitive/SensitiveSerialize.java new file mode 100644 index 0000000..08109d6 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/sensitive/SensitiveSerialize.java @@ -0,0 +1,68 @@ +package com.ruoyi.common.core.sensitive; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.ContextualSerializer; +import com.ruoyi.common.core.utils.SensitiveUtils; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +import java.io.IOException; +import java.util.Objects; + +/** + * @author JooLun + * @Author: https://www.cnblogs.com/xiluonanfeng/p/10183926.html + * 脱敏序列化 + */ +@NoArgsConstructor +@AllArgsConstructor +public class SensitiveSerialize extends JsonSerializer implements ContextualSerializer { + + private SensitiveTypeEnum type; + + @Override + public void serialize(final String originStr, final JsonGenerator jsonGenerator, + final SerializerProvider serializerProvider) throws IOException { + switch (type) { + case CHINESE_NAME: + jsonGenerator.writeString(SensitiveUtils.chineseName(originStr)); + break; + case MOBILE_PHONE: + jsonGenerator.writeString(SensitiveUtils.mobilePhone(originStr)); + break; + case EMAIL: + jsonGenerator.writeString(SensitiveUtils.email(originStr)); + break; + case PASSWORD: + jsonGenerator.writeString(SensitiveUtils.password(originStr)); + break; + case KEY: + jsonGenerator.writeString(SensitiveUtils.key(originStr)); + break; + default: + throw new IllegalArgumentException("未定义的敏感信息枚举类" + type); + } + } + + @Override + public JsonSerializer createContextual(final SerializerProvider serializerProvider, final BeanProperty beanProperty) throws JsonMappingException { + if (beanProperty != null) { + if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) { + Sensitive sensitive = beanProperty.getAnnotation(Sensitive.class); + if (sensitive == null) { + sensitive = beanProperty.getContextAnnotation(Sensitive.class); + } + if (sensitive != null) { + return new SensitiveSerialize(sensitive.type()); + } + } + return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty); + } + return serializerProvider.findNullValueSerializer(null); + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/sensitive/SensitiveTypeEnum.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/sensitive/SensitiveTypeEnum.java new file mode 100644 index 0000000..284b7ec --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/sensitive/SensitiveTypeEnum.java @@ -0,0 +1,32 @@ +package com.ruoyi.common.core.sensitive; + +/** + * 敏感信息枚举类 + * + * @author JooLun + * @Author: https://www.cnblogs.com/xiluonanfeng/p/10183926.html + **/ +public enum SensitiveTypeEnum { + + /** + * 用户名, 李*天, 张* + */ + CHINESE_NAME, + /** + * 手机号, 185****1653 + */ + MOBILE_PHONE, + /** + * 电子邮件, r*****o@qq.com + */ + EMAIL, + /** + * 密码, ****** + */ + PASSWORD, + /** + * 密钥, 最后三位其他都是*** + */ + KEY + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/typehandler/ArrayLongTypeHandler.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/typehandler/ArrayLongTypeHandler.java new file mode 100644 index 0000000..6002fcb --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/typehandler/ArrayLongTypeHandler.java @@ -0,0 +1,48 @@ +package com.ruoyi.common.core.typehandler; + +import cn.hutool.json.JSONUtil; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * 存储到数据库, 将LONG数组转换成字符串; + * 从数据库获取数据, 将字符串转为LONG数组. + */ +@MappedTypes({Long[].class}) +@MappedJdbcTypes({JdbcType.VARCHAR}) +public class ArrayLongTypeHandler extends BaseTypeHandler { + + private static Long[] l = new Long[]{}; + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, + Long[] parameter, JdbcType jdbcType) throws SQLException { + ps.setString(i, JSONUtil.toJsonStr(parameter)); + } + + @Override + public Long[] getNullableResult(ResultSet rs, String columnName) + throws SQLException { + return JSONUtil.parseArray(rs.getString(columnName)).toArray(l); + } + + @Override + public Long[] getNullableResult(ResultSet rs, int columnIndex) + throws SQLException { + return JSONUtil.parseArray(rs.getString(columnIndex)).toArray(l); + } + + @Override + public Long[] getNullableResult(CallableStatement cs, int columnIndex) + throws SQLException { + return JSONUtil.parseArray(cs.getString(columnIndex)).toArray(l); + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/typehandler/ArrayStringTypeHandler.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/typehandler/ArrayStringTypeHandler.java new file mode 100644 index 0000000..6dab677 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/typehandler/ArrayStringTypeHandler.java @@ -0,0 +1,48 @@ +package com.ruoyi.common.core.typehandler; + +import cn.hutool.json.JSONUtil; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * 存储到数据库, 将String数组转换成字符串; + * 从数据库获取数据, 将字符串转为LONG数组. + */ +@MappedTypes({String[].class}) +@MappedJdbcTypes({JdbcType.VARCHAR}) +public class ArrayStringTypeHandler extends BaseTypeHandler { + + private static String[] l = new String[]{}; + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, + String[] parameter, JdbcType jdbcType) throws SQLException { + ps.setString(i, JSONUtil.toJsonStr(parameter)); + } + + @Override + public String[] getNullableResult(ResultSet rs, String columnName) + throws SQLException { + return JSONUtil.parseArray(rs.getString(columnName)).toArray(l); + } + + @Override + public String[] getNullableResult(ResultSet rs, int columnIndex) + throws SQLException { + return JSONUtil.parseArray(rs.getString(columnIndex)).toArray(l); + } + + @Override + public String[] getNullableResult(CallableStatement cs, int columnIndex) + throws SQLException { + return JSONUtil.parseArray(cs.getString(columnIndex)).toArray(l); + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/typehandler/JsonTypeHandler.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/typehandler/JsonTypeHandler.java new file mode 100644 index 0000000..b013bed --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/typehandler/JsonTypeHandler.java @@ -0,0 +1,50 @@ +package com.ruoyi.common.core.typehandler; + +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * 存储到数据库, 将JSON对象转换成字符串; + * 从数据库获取数据, 将字符串转为JSON对象. + */ +@MappedTypes({JSONObject.class}) +@MappedJdbcTypes({JdbcType.VARCHAR}) +public class JsonTypeHandler extends BaseTypeHandler { + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, JSONObject parameter, + JdbcType jdbcType) throws SQLException { + + ps.setString(i, JSONUtil.toJsonStr(parameter)); + } + + @Override + public JSONObject getNullableResult(ResultSet rs, String columnName) + throws SQLException { + + return JSONUtil.parseObj(rs.getString(columnName)).toBean(JSONObject.class); + } + + @Override + public JSONObject getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + + return JSONUtil.parseObj(rs.getString(columnIndex)).toBean(JSONObject.class); + } + + @Override + public JSONObject getNullableResult(CallableStatement cs, int columnIndex) + throws SQLException { + + return JSONUtil.parseObj(cs.getString(columnIndex)).toBean(JSONObject.class); + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SensitiveUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SensitiveUtils.java new file mode 100644 index 0000000..0412156 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SensitiveUtils.java @@ -0,0 +1,153 @@ +package com.ruoyi.common.core.utils; + +import cn.hutool.core.util.StrUtil; + +/** + * 数据脱敏工具类 + * + * @Author: JooLun + * @Author: https://www.cnblogs.com/xiluonanfeng/p/10183926.html + * @Date: 2021/7/19 16:21 + */ +public class SensitiveUtils { + + /** + * 默认填充字符 + */ + public static final String DEFAULT_PAD_STR = "*"; + + /** + * 数据脱敏 + * + */ + public static String process(String data) { + return process(data, 2, 1, DEFAULT_PAD_STR); + } + + /** + * 数据脱敏 + * + */ + public static String process(String data, Integer leftLen, Integer rightLen) { + return process(data, leftLen, rightLen, DEFAULT_PAD_STR); + } + + /** + * 对字符串进行脱敏操作 + * @param originStr 原始字符串 + * @param prefixNoMaskLen 左侧需要保留几位明文字段 + * @param suffixNoMaskLen 右侧需要保留几位明文字段 + * @param maskStr 用于遮罩的字符串, 如'*' + * @return 脱敏后结果 + */ + public static String process(String originStr, int prefixNoMaskLen, int suffixNoMaskLen, String maskStr) { + if (originStr == null) { + return null; + } + + StringBuilder sb = new StringBuilder(); + for (int i = 0, n = originStr.length(); i < n; i++) { + if (i < prefixNoMaskLen) { + sb.append(originStr.charAt(i)); + continue; + } + if (i > (n - suffixNoMaskLen - 1)) { + sb.append(originStr.charAt(i)); + continue; + } + sb.append(maskStr); + } + return sb.toString(); + } + + /** + * 中文姓名只显示最后一个汉字 + * @param fullName 姓名 + * @return + */ + public static String chineseName(String fullName) { + if (fullName == null) { + return null; + } + return process(fullName, 0, 1, DEFAULT_PAD_STR); + } + + /** + * 手机号码前三位,后四位,如186****2356 + * @param num 手机号码 + * @return + */ + public static String mobilePhone(String num) { + return process(num, 0, 4, DEFAULT_PAD_STR); + } + + /** + * 地址只显示到地区 + * @param address 地址 + * @return + */ + public static String address(String address) { + return process(address, 6, 0, DEFAULT_PAD_STR); + } + + /** + * 电子邮箱 仅显示第一个字母,@后面的地址显示,比如:r**@qq.com + * @param email 电子邮箱 + * @return + */ + public static String email(String email) { + if (email == null) { + return null; + } + int index = StrUtil.indexOf(email, '@'); + if (index <= 1) { + return email; + } + String preEmail = process(email.substring(0, index), 1, 0, DEFAULT_PAD_STR); + return preEmail + email.substring(index); + + } + + /** + * 密码的全部字符,如:****** + * @param password 密码 + * @return + */ + public static String password(String password) { + if (password == null) { + return null; + } + return "******"; + } + + /** + * 密钥除了最后三位,全部,比如:***klo + * @param key 密钥 + * @return 结果 + */ + public static String key(String key) { + if (key == null) { + return null; + } + int viewLength = 6; + StringBuilder tmpKey = new StringBuilder(process(key, 0, 3, DEFAULT_PAD_STR)); + if (tmpKey.length() > viewLength) { + return tmpKey.substring(tmpKey.length() - viewLength); + } + else if (tmpKey.length() < viewLength) { + int buffLength = viewLength - tmpKey.length(); + for (int i = 0; i < buffLength; i++) { + tmpKey.insert(0, DEFAULT_PAD_STR); + } + return tmpKey.toString(); + } + else { + return tmpKey.toString(); + } + } + + public static void main(String[] args) { + String s = mobilePhone("18653653621"); + System.out.println(s); + } +} \ No newline at end of file diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/http/HttpHelper.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/http/HttpHelper.java new file mode 100644 index 0000000..17532db --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/http/HttpHelper.java @@ -0,0 +1,57 @@ +package com.ruoyi.common.core.utils.http; + + +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletRequest; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +/** + * 通用http工具封装 + * + * @author ruoyi + */ +public class HttpHelper +{ + private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class); + + public static String getBodyString(ServletRequest request) + { + StringBuilder sb = new StringBuilder(); + BufferedReader reader = null; + try (InputStream inputStream = request.getInputStream()) + { + reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); + String line = ""; + while ((line = reader.readLine()) != null) + { + sb.append(line); + } + } + catch (IOException e) + { + LOGGER.warn("getBodyString出现问题!"); + } + finally + { + if (reader != null) + { + try + { + reader.close(); + } + catch (IOException e) + { + LOGGER.error(ExceptionUtils.getMessage(e)); + } + } + } + return sb.toString(); + } +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/http/HttpUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/http/HttpUtils.java new file mode 100644 index 0000000..b43e18f --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/http/HttpUtils.java @@ -0,0 +1,267 @@ +package com.ruoyi.common.core.utils.http; + + +import com.ruoyi.common.core.constant.Constants; +import com.ruoyi.common.core.utils.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.*; +import java.io.*; +import java.net.ConnectException; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.StandardCharsets; +import java.security.cert.X509Certificate; + +/** + * 通用http发送方法 + * + * @author ruoyi + */ +public class HttpUtils +{ + private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url 发送请求的 URL + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url) + { + return sendGet(url, StringUtils.EMPTY); + } + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param) + { + return sendGet(url, param, Constants.UTF8); + } + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @param contentType 编码类型 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param, String contentType) + { + StringBuilder result = new StringBuilder(); + BufferedReader in = null; + try + { + String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url; + log.info("sendGet - {}", urlNameString); + URL realUrl = new URL(urlNameString); + URLConnection connection = realUrl.openConnection(); + connection.setRequestProperty("accept", "*/*"); + connection.setRequestProperty("connection", "Keep-Alive"); + connection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"); + connection.connect(); + in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); + String line; + while ((line = in.readLine()) != null) + { + result.append(line); + } + log.info("recv - {}", result); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e); + } + finally + { + try + { + if (in != null) + { + in.close(); + } + } + catch (Exception ex) + { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + /** + * 向指定 URL 发送POST方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendPost(String url, String param) + { + PrintWriter out = null; + BufferedReader in = null; + StringBuilder result = new StringBuilder(); + try + { + log.info("sendPost - {}", url); + URL realUrl = new URL(url); + URLConnection conn = realUrl.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + out = new PrintWriter(conn.getOutputStream()); + out.print(param); + out.flush(); + in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); + String line; + while ((line = in.readLine()) != null) + { + result.append(line); + } + log.info("recv - {}", result); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e); + } + finally + { + try + { + if (out != null) + { + out.close(); + } + if (in != null) + { + in.close(); + } + } + catch (IOException ex) + { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + public static String sendSSLPost(String url, String param) + { + StringBuilder result = new StringBuilder(); + String urlNameString = url + "?" + param; + try + { + log.info("sendSSLPost - {}", urlNameString); + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom()); + URL console = new URL(urlNameString); + HttpsURLConnection conn = (HttpsURLConnection) console.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + + conn.setSSLSocketFactory(sc.getSocketFactory()); + conn.setHostnameVerifier(new TrustAnyHostnameVerifier()); + conn.connect(); + InputStream is = conn.getInputStream(); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String ret = ""; + while ((ret = br.readLine()) != null) + { + if (ret != null && !"".equals(ret.trim())) + { + result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8)); + } + } + log.info("recv - {}", result); + conn.disconnect(); + br.close(); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e); + } + return result.toString(); + } + + private static class TrustAnyTrustManager implements X509TrustManager + { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) + { + } + + @Override + public X509Certificate[] getAcceptedIssuers() + { + return new X509Certificate[] {}; + } + } + + private static class TrustAnyHostnameVerifier implements HostnameVerifier + { + @Override + public boolean verify(String hostname, SSLSession session) + { + return true; + } + } +} \ No newline at end of file diff --git a/ruoyi-modules/intc-weixin/README.md b/ruoyi-modules/intc-weixin/README.md new file mode 100644 index 0000000..d76f839 --- /dev/null +++ b/ruoyi-modules/intc-weixin/README.md @@ -0,0 +1 @@ +特定业务模块 \ No newline at end of file diff --git a/ruoyi-modules/intc-weixin/pom.xml b/ruoyi-modules/intc-weixin/pom.xml new file mode 100644 index 0000000..f6d2720 --- /dev/null +++ b/ruoyi-modules/intc-weixin/pom.xml @@ -0,0 +1,214 @@ + + + + com.ruoyi + ruoyi-modules + 3.6.3 + + 4.0.0 + + intc-weixin + + + intc-weixin 微信公众号 + + + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + io.micrometer + micrometer-registry-prometheus + + + + + + io.springfox + springfox-swagger-ui + ${swagger.fox.version} + + + + + + + + + + + com.ruoyi + ruoyi-common-datasource + 3.6.3 + + + + + com.ruoyi + ruoyi-common-datascope + 3.6.3 + + + + org.postgresql + postgresql + 42.2.22 + + + + org.projectlombok + lombok + + + + + + com.ruoyi + ruoyi-common-log + + + + + com.ruoyi + ruoyi-common-swagger + + + ws.schild + jave-core + 2.4.6 + + + ws.schild + jave-native-win64 + 2.4.6 + + + ws.schild + jave-native-linux64 + 2.4.6 + + + org.springframework + spring-test + 5.3.3 + compile + + + + com.baomidou + mybatis-plus-extension + 3.5.5 + + + + com.baomidou + mybatis-plus-boot-starter + 3.5.5 + + + + com.github.binarywang + weixin-java-common + 4.6.2.B + + + + com.github.binarywang + weixin-java-mp + 4.6.2.B + + + + com.github.binarywang + weixin-java-miniapp + 4.6.2.B + + + + com.github.binarywang + weixin-java-pay + 4.6.2.B + + + + com.alibaba + transmittable-thread-local + 2.11.4 + + + cn.hutool + hutool-all + 5.1.0 + + + + pro.fessional + kaptcha + 2.3.3 + + + servlet-api + javax.servlet + + + + + + jakarta.servlet + jakarta.servlet-api + 4.0.4 + + + + org.springframework.boot + spring-boot-starter-validation + 3.3.4 + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + + diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/IntcWeixinApplication.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/IntcWeixinApplication.java new file mode 100644 index 0000000..ea17975 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/IntcWeixinApplication.java @@ -0,0 +1,25 @@ +package com.ruoyi; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import com.ruoyi.common.security.annotation.EnableCustomConfig; +import com.ruoyi.common.security.annotation.EnableRyFeignClients; +import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2; + +/** + * 系统模块 + * + * @author ruoyi + */ +@EnableCustomConfig +@EnableCustomSwagger2 +@EnableRyFeignClients +@SpringBootApplication +public class IntcWeixinApplication +{ + public static void main(String[] args) + { + SpringApplication.run(IntcWeixinApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ 智聪微信业务模块启动成功 ლ(´ڡ`ლ)゙"); + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/config/ActuatorSecurityConfig.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/config/ActuatorSecurityConfig.java new file mode 100644 index 0000000..05433e1 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/config/ActuatorSecurityConfig.java @@ -0,0 +1,44 @@ +package com.ruoyi.config; + +import com.ruoyi.common.core.utils.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.web.SecurityFilterChain; + +/** + * @ClassName ActuatorSecurityConfig + * @Author YaphetS + * @Date 2023/3/14 9:18 + * @Version 1.0 + * @Description TODO + */ +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class ActuatorSecurityConfig { + + @Autowired + Environment env; + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + String contextPath = env.getProperty("management.endpoints.web.base-path"); + if(StringUtils.isEmpty(contextPath)) { + contextPath = "/actuator"; + } + http.csrf().disable(); + http.authorizeRequests() + .antMatchers("/**"+contextPath+"/**") + .authenticated() + .anyRequest() + .permitAll() + .and() + .httpBasic(); + return http.build(); + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/builder/AbstractBuilder.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/builder/AbstractBuilder.java new file mode 100644 index 0000000..4b5ca58 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/builder/AbstractBuilder.java @@ -0,0 +1,40 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.builder; + +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +public abstract class AbstractBuilder { + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + public abstract WxMpXmlOutMessage build(String content, + WxMpXmlMessage wxMessage, WxMpService service); +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/builder/ImageBuilder.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/builder/ImageBuilder.java new file mode 100644 index 0000000..9eefca8 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/builder/ImageBuilder.java @@ -0,0 +1,47 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.builder; + +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +public class ImageBuilder extends AbstractBuilder { + + @Override + public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, + WxMpService service) { + + WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId(content) + .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) + .build(); + + return m; + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/builder/TextBuilder.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/builder/TextBuilder.java new file mode 100644 index 0000000..470ff0e --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/builder/TextBuilder.java @@ -0,0 +1,45 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.builder; + +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +public class TextBuilder extends AbstractBuilder { + + @Override + public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, + WxMpService service) { + WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content(content) + .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) + .build(); + return m; + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/CommonConstants.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/CommonConstants.java new file mode 100644 index 0000000..f1ca61a --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/CommonConstants.java @@ -0,0 +1,47 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.config; + +/** + * @author + */ +public interface CommonConstants { + /** + * 是 + */ + String YES = "1"; + /** + * 否 + */ + String NO = "0"; + + /** + * 树形父类ID + */ + String PARENT_ID = "0"; + /** + * 编码 + */ + String UTF8 = "UTF-8"; +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WebConfig.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WebConfig.java new file mode 100644 index 0000000..9563332 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WebConfig.java @@ -0,0 +1,34 @@ +package com.ruoyi.weixin.config; + +import com.ruoyi.weixin.interceptor.ThirdSessionInterceptor; +import lombok.AllArgsConstructor; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * web配置 + */ +@Configuration +@AllArgsConstructor +public class WebConfig implements WebMvcConfigurer { + private final RedisTemplate redisTemplate; + + /** + * 拦截器 + * @param registry + */ + @Override + public void addInterceptors(InterceptorRegistry registry) { + /** + * 进入ThirdSession拦截器 + */ + registry.addInterceptor(new ThirdSessionInterceptor(redisTemplate)) + .addPathPatterns("/weixin/api/**")//拦截/api/**接口 + .excludePathPatterns("/weixin/api/ma/wxuser/login", + "/weixin/api/ma/orderinfo/notify-order", + "/weixin/api/ma/orderinfo/notify-logisticsr", + "/weixin/api/ma/orderinfo/notify-refunds");//放行接口 + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxMaConfiguration.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxMaConfiguration.java new file mode 100644 index 0000000..efe95d6 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxMaConfiguration.java @@ -0,0 +1,148 @@ +package com.ruoyi.weixin.config; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl; +import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; +import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage; +import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl; +import cn.binarywang.wx.miniapp.message.WxMaMessageHandler; +import cn.binarywang.wx.miniapp.message.WxMaMessageRouter; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.error.WxErrorException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author Binary Wang + */ +@Slf4j +@Configuration +@EnableConfigurationProperties(com.ruoyi.weixin.config.WxMaProperties.class) +public class WxMaConfiguration { + private final com.ruoyi.weixin.config.WxMaProperties properties; + + private static final Map routers = Maps.newHashMap(); + private static Map maServices; + + @Autowired + public WxMaConfiguration(com.ruoyi.weixin.config.WxMaProperties properties) { + this.properties = properties; + } + + public static WxMaService getMaService(String appId) { + WxMaService wxService = maServices.get(appId); + if (wxService == null) { + throw new IllegalArgumentException(String.format("未找到对应appId=[%s]的配置,请核实!", appId)); + } + + return wxService; + } + + public static WxMaMessageRouter getRouter(String appId) { + return routers.get(appId); + } + + @PostConstruct + public void init() { + List configs = this.properties.getConfigs(); + if (configs == null) { + throw new RuntimeException("大哥,拜托先看下项目首页的说明(readme文件),添加下相关配置,注意别配错了!"); + } + + maServices = configs.stream() + .map(a -> { + WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl(); + // 使用上面的配置时,需要同时引入jedis-lock的依赖,否则会报类无法找到的异常 + config.setAppid(a.getAppId()); + config.setSecret(a.getSecret()); + config.setToken(a.getToken()); + config.setAesKey(a.getAesKey()); + config.setMsgDataFormat(a.getMsgDataFormat()); + + WxMaService service = new WxMaServiceImpl(); + service.setWxMaConfig(config); + routers.put(a.getAppId(), this.newRouter(service)); + return service; + }).collect(Collectors.toMap(s -> s.getWxMaConfig().getAppid(), a -> a)); + } + + private WxMaMessageRouter newRouter(WxMaService service) { + final WxMaMessageRouter router = new WxMaMessageRouter(service); + router + .rule().handler(logHandler).next() + .rule().async(false).content("订阅消息").handler(subscribeMsgHandler).end() + .rule().async(false).content("文本").handler(textHandler).end() + .rule().async(false).content("图片").handler(picHandler).end() + .rule().async(false).content("二维码").handler(qrcodeHandler).end(); + return router; + } + + private final WxMaMessageHandler subscribeMsgHandler = (wxMessage, context, service, sessionManager) -> { + service.getMsgService().sendSubscribeMsg(WxMaSubscribeMessage.builder() + .templateId("此处更换为自己的模板id") + .data(Lists.newArrayList( + new WxMaSubscribeMessage.MsgData("keyword1", "339208499"))) + .toUser(wxMessage.getFromUser()) + .build()); + return null; + }; + + private final WxMaMessageHandler logHandler = (wxMessage, context, service, sessionManager) -> { + log.info("收到消息:" + wxMessage.toString()); + service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("收到信息为:" + wxMessage.toJson()) + .toUser(wxMessage.getFromUser()).build()); + return null; + }; + + private final WxMaMessageHandler textHandler = (wxMessage, context, service, sessionManager) -> { + service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("回复文本消息") + .toUser(wxMessage.getFromUser()).build()); + return null; + }; + + private final WxMaMessageHandler picHandler = (wxMessage, context, service, sessionManager) -> { + try { + WxMediaUploadResult uploadResult = service.getMediaService() + .uploadMedia("image", "png", + ClassLoader.getSystemResourceAsStream("tmp.png")); + service.getMsgService().sendKefuMsg( + WxMaKefuMessage + .newImageBuilder() + .mediaId(uploadResult.getMediaId()) + .toUser(wxMessage.getFromUser()) + .build()); + } catch (WxErrorException e) { + e.printStackTrace(); + } + + return null; + }; + + private final WxMaMessageHandler qrcodeHandler = (wxMessage, context, service, sessionManager) -> { + try { + final File file = service.getQrcodeService().createQrcode("123", 430); + WxMediaUploadResult uploadResult = service.getMediaService().uploadMedia("image", file); + service.getMsgService().sendKefuMsg( + WxMaKefuMessage + .newImageBuilder() + .mediaId(uploadResult.getMediaId()) + .toUser(wxMessage.getFromUser()) + .build()); + } catch (WxErrorException e) { + e.printStackTrace(); + } + + return null; + }; + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxMaProperties.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxMaProperties.java new file mode 100644 index 0000000..750873f --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxMaProperties.java @@ -0,0 +1,80 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.List; + +/** + * @author Binary Wang + */ +@Data +@ConfigurationProperties(prefix = "wx.ma") +public class WxMaProperties { + + private List configs; + + @Data + public static class Config { + /** + * 设置微信小程序的appid + */ + private String appId; + + /** + * 设置微信小程序的Secret + */ + private String secret; + + /** + * 设置微信小程序消息服务器配置的token + */ + private String token; + + /** + * 设置微信小程序消息服务器配置的EncodingAESKey + */ + private String aesKey; + + /** + * 消息格式,XML或者JSON + */ + private String msgDataFormat; + /** + * 微信支付商户号 + */ + private String mchId; + /** + * 微信支付商户密钥 + */ + private String mchKey; + /** + * p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头) + */ + private String keyPath; + } + +} \ No newline at end of file diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxMpConfiguration.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxMpConfiguration.java new file mode 100644 index 0000000..d17e967 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxMpConfiguration.java @@ -0,0 +1,132 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.config; + +import com.ruoyi.weixin.handler.*; +import lombok.AllArgsConstructor; +import me.chanjar.weixin.mp.api.WxMpMessageRouter; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; +import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import java.util.List; +import java.util.stream.Collectors; +import static me.chanjar.weixin.common.api.WxConsts.EventType; +import static me.chanjar.weixin.common.api.WxConsts.EventType.SUBSCRIBE; +import static me.chanjar.weixin.common.api.WxConsts.EventType.UNSUBSCRIBE; +import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; +import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType.EVENT; +import static me.chanjar.weixin.mp.constant.WxMpEventConstants.CustomerService.*; +import static me.chanjar.weixin.mp.constant.WxMpEventConstants.POI_CHECK_NOTIFY; + +/** + * wechat mp configuration + * + * @author Binary Wang(https://github.com/binarywang) + */ +@AllArgsConstructor +@Configuration +@EnableConfigurationProperties(WxMpProperties.class) +public class WxMpConfiguration { + private final LogHandler logHandler; + private final NullHandler nullHandler; + private final KfSessionHandler kfSessionHandler; + private final StoreCheckNotifyHandler storeCheckNotifyHandler; + private final LocationHandler locationHandler; + private final MenuHandler menuHandler; + private final MsgHandler msgHandler; + private final UnsubscribeHandler unsubscribeHandler; + private final SubscribeHandler subscribeHandler; + private final ScanHandler scanHandler; + private final WxMpProperties properties; + + @Bean + public WxMpService wxMpService() { + // 代码里 getConfigs()处报错的同学,请注意仔细阅读项目说明,你的IDE需要引入lombok插件!!!! + final List configs = this.properties.getConfigs(); + if (configs == null) { + throw new RuntimeException("大哥,拜托先看下项目首页的说明(readme文件),添加下相关配置,注意别配错了!"); + } + + WxMpService service = new WxMpServiceImpl(); + service.setMultiConfigStorages(configs + .stream().map(a -> { + WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl(); + configStorage.setAppId(a.getAppId()); + configStorage.setSecret(a.getSecret()); + configStorage.setToken(a.getToken()); + configStorage.setAesKey(a.getAesKey()); + return configStorage; + }).collect(Collectors.toMap(WxMpDefaultConfigImpl::getAppId, a -> a, (o, n) -> o))); + return service; + } + + @Bean + public WxMpMessageRouter messageRouter(WxMpService wxMpService) { + final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService); + + // 记录所有事件的日志 (异步执行) + newRouter.rule().handler(this.logHandler).next(); + + // 接收客服会话管理事件 + newRouter.rule().async(false).msgType(EVENT).event(KF_CREATE_SESSION) + .handler(this.kfSessionHandler).end(); + newRouter.rule().async(false).msgType(EVENT).event(KF_CLOSE_SESSION) + .handler(this.kfSessionHandler).end(); + newRouter.rule().async(false).msgType(EVENT).event(KF_SWITCH_SESSION) + .handler(this.kfSessionHandler).end(); + + // 门店审核事件 + newRouter.rule().async(false).msgType(EVENT).event(POI_CHECK_NOTIFY).handler(this.storeCheckNotifyHandler).end(); + + // 自定义菜单事件 + newRouter.rule().async(false).msgType(EVENT).event(EventType.CLICK).handler(this.menuHandler).end(); + + // 点击菜单连接事件 + newRouter.rule().async(false).msgType(EVENT).event(EventType.VIEW).handler(this.nullHandler).end(); + + // 关注事件 + newRouter.rule().async(false).msgType(EVENT).event(SUBSCRIBE).handler(this.subscribeHandler).end(); + + // 取消关注事件 + newRouter.rule().async(false).msgType(EVENT).event(UNSUBSCRIBE).handler(this.unsubscribeHandler).end(); + + // 上报地理位置事件 + newRouter.rule().async(false).msgType(EVENT).event(EventType.LOCATION).handler(this.locationHandler).end(); + + // 接收地理位置消息 + newRouter.rule().async(false).msgType(XmlMsgType.LOCATION).handler(this.locationHandler).end(); + + // 扫码事件 + newRouter.rule().async(false).msgType(EVENT).event(EventType.SCAN).handler(this.scanHandler).end(); + + // 默认 + newRouter.rule().async(false).handler(this.msgHandler).end(); + + return newRouter; + } + +} \ No newline at end of file diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxMpProperties.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxMpProperties.java new file mode 100644 index 0000000..f5171dd --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxMpProperties.java @@ -0,0 +1,69 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.config; + +import com.ruoyi.weixin.utils.JsonUtils; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.List; + +/** + * wechat mp properties + * + * @author Binary Wang(https://github.com/binarywang) + */ +@Data +@ConfigurationProperties(prefix = "wx.mp") +public class WxMpProperties { + private List 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); + } +} \ No newline at end of file diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxPayConfiguration.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxPayConfiguration.java new file mode 100644 index 0000000..dab45a9 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/config/WxPayConfiguration.java @@ -0,0 +1,51 @@ +/** + * Copyright (C) 2018-2019 + * All rights reserved, Designed By www.joolun.com + * 注意: + * 本软件为www.joolun.com开发研制,项目使用请保留此说明 + */ +package com.ruoyi.weixin.config; + +import cn.hutool.core.util.StrUtil; +import com.github.binarywang.wxpay.config.WxPayConfig; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; + +/** + * 微信支付Configuration + * @author www.joolun.com + * + */ +@Slf4j +@Configuration +public class WxPayConfiguration { + + private static WxMaProperties wxMaProperties; + + @Autowired + public WxPayConfiguration(WxMaProperties wxMaProperties) { + this.wxMaProperties = wxMaProperties; + } + + /** + * 获取WxMpService + * @return + */ + public static WxPayService getPayService() { + WxPayService wxPayService = null; + WxPayConfig payConfig = new WxPayConfig(); + payConfig.setAppId(wxMaProperties.getConfigs().get(0).getAppId()); + payConfig.setMchId(wxMaProperties.getConfigs().get(0).getMchId()); + payConfig.setMchKey(wxMaProperties.getConfigs().get(0).getMchKey()); + payConfig.setKeyPath(wxMaProperties.getConfigs().get(0).getKeyPath()); + // 可以指定是否使用沙箱环境 + payConfig.setUseSandboxEnv(false); + wxPayService = new WxPayServiceImpl(); + wxPayService.setConfig(payConfig); + return wxPayService; + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/ConfigConstant.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/ConfigConstant.java new file mode 100644 index 0000000..9d3f3d0 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/ConfigConstant.java @@ -0,0 +1,106 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.constant; + +/** + * 全局常量 + * @author www.joolun.com + * 2019年1月21日 + */ +public interface ConfigConstant { + + //订阅状态(0:已订阅;1:未订阅;2:网页授权用户) + /** + * 0:未订阅,取消订阅 + */ + String SUBSCRIBE_TYPE_NO = "0"; + /** + * 1:已订阅 + */ + String SUBSCRIBE_TYPE_YES = "1"; + /** + * 2:网页授权用户 + */ + String SUBSCRIBE_TYPE_WEBLICENS = "2"; + + /** + * 应用类型 1:小程序 + */ + String WX_APP_TYPE_1 = "1"; + /** + * 应用类型 2:公众号 + */ + String WX_APP_TYPE_2 = "2"; + + /** + * 消息自动回复类型(1、关注时回复;2、消息回复;3、关键词回复) + */ + String WX_AUTO_REPLY_TYPE_1 = "1"; + String WX_AUTO_REPLY_TYPE_2 = "2"; + String WX_AUTO_REPLY_TYPE_3 = "3"; + + /** + * 回复类型文本匹配类型(1、全匹配,2、半匹配) + */ + String WX_REP_MATE_1 = "1"; + String WX_REP_MATE_2 = "2"; + + /** + * 消息分类(1、用户发给公众号;2、公众号发给用户;) + */ + String WX_MSG_TYPE_1 = "1"; + String WX_MSG_TYPE_2 = "2"; + + /** + * 群发消息发送类型(1、分组发;2、选择用户发) + */ + String WX_MASS_SEND_TYPE_1 = "1"; + String WX_MASS_SEND_TYPE_2 = "2"; + + /** + * 群发消息发送后的状态(SUB_SUCCESS:提交成功,SUB_FAIL:提交失败,SEND_SUCCESS:发送成功,SENDING:发送中,SEND_FAIL:发送失败,DELETE:已删除) + */ + String WX_MASS_STATUS_SUB_SUCCESS = "SUB_SUCCESS"; + String WX_MASS_STATUS_SUB_FAIL = "SUB_FAIL"; + String WX_MASS_STATUS_SEND_SUCCESS = "SEND_SUCCESS"; + String WX_MASS_STATUS_SENDING = "SENDING"; + String WX_MASS_STATUS_SEND_FAIL = "SEND_FAIL"; + String WX_MASS_STATUS_DELETE = "DELETE"; + + /** + * 菜单类型(1:普通菜单,2:个性化菜单) + */ + String WX_MENU_TYPE_1 = "1"; + String WX_MENU_TYPE_2 = "2"; + + /** + * header中的app-id + */ + String HEADER_APP_ID = "app-id"; + + /** + * header中的third-session + */ + String HEADER_THIRDSESSION = "third-session"; +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/MyReturnCode.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/MyReturnCode.java new file mode 100644 index 0000000..9adb5c6 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/MyReturnCode.java @@ -0,0 +1,75 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.constant; + +/** + * 全局返回码 + * 小程序用6开头,例60001 + * @author www.joolun.com + * 2019年7月25日 + */ +public enum MyReturnCode { + + ERR_60000(60000, "系统错误,请稍候再试"){},//其它错误 + ERR_60001(60001, "登录超时,请重新登录"){}, + ERR_60002(60002, "session不能为空"){}, + + ERR_70001(70001, "该状态订单不允许操作"){}, + ERR_70002(70002, "请选择付款方式"){}, + ERR_70003(70003, "没有符合下单条件的规格商品,商品已下架或库存不足"){}, + ERR_70004(70004, "只有未支付的详单能发起支付"){}, + ERR_70005(70005, "无效订单"){}, + + ERR_80004(80004, "该商品已删除"){}, + + ; + ; + + MyReturnCode(int code, String msg) { + this.code = code; + this.msg = msg; + } + + private int code; + private String msg; + + public int getCode() { + return code; + } + public void setCode(int code) { + this.code = code; + } + public String getMsg() { + return msg; + } + public void setMsg(String msg) { + this.msg = msg; + } + + @Override + public String toString() { + return "MyReturnCode{" + "code='" + code + '\'' + "msg='" + msg + '\'' + '}'; + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/WebSocketConstant.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/WebSocketConstant.java new file mode 100644 index 0000000..5f93971 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/WebSocketConstant.java @@ -0,0 +1,34 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.constant; + +/** + * @author www.joolun.com + */ +public interface WebSocketConstant { + + String USER_DESTINATION_PREFIX = "/weixin/"; + String WX_MSG = "wx_msg"; + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/WxMaConstants.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/WxMaConstants.java new file mode 100644 index 0000000..63ab32a --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/WxMaConstants.java @@ -0,0 +1,39 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.constant; + +/** + * @author + */ +public interface WxMaConstants { + + /** + * redis中3rd_session过期时间(单位:小时) + */ + long TIME_OUT_SESSION = 6; + /** + * redis中3rd_session拼接前缀 + */ + String THIRD_SESSION_BEGIN = "wx:ma:3rd_session"; +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/WxReturnCode.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/WxReturnCode.java new file mode 100644 index 0000000..cf466b1 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/constant/WxReturnCode.java @@ -0,0 +1,259 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.constant; + +/** + * 微信接口全局返回码 + * @author www.joolun.com + * + */ +public enum WxReturnCode { + + SUC_0("0", "请求成功"){}, + ERR_1("-1", "系统繁忙,此时请开发者稍候再试"){}, + ERR_10001("10001", "涉嫌广告 "){}, + ERR_20001("20001", "涉嫌政治 "){}, + ERR_20002("20002", "涉嫌色情 "){}, + ERR_20004("20004", "涉嫌社会 "){}, + ERR_20006("20006", "涉嫌违法犯罪 "){}, + ERR_20008("20008", "涉嫌欺诈 "){}, + ERR_20013("20013", "涉嫌版权 "){}, + ERR_21000("21000", "涉嫌其他 "){}, + ERR_22000("22000", "涉嫌互推(互相宣传) "){}, + ERR_30001("30001", "原创校验出现系统错误且用户选择了被判为转载就不群发 "){}, + ERR_30002("30002", "原创校验被判定为不能群发 "){}, + ERR_30003("30003", "原创校验被判定为转载文且用户选择了被判为转载就不群发 "){}, + ERR_40001("40001", "获取access_token时AppSecret错误,或者access_token无效。请开发者认真比对AppSecret的正确性,或查看是否正在为恰当的公众号调用接口"){}, + ERR_40002("40002", "不合法的凭证类型"){}, + ERR_40003("40003", "不合法的OpenID,请开发者确认OpenID(该用户)是否已关注公众号,或是否是其他公众号的OpenID"){}, + ERR_40004("40004", "不合法的媒体文件类型"){}, + ERR_40005("40005", "不合法的文件类型"){}, + ERR_40006("40006", "不合法的文件大小"){}, + ERR_40007("40007", "不合法的媒体文件id"){}, + ERR_40008("40008", "不合法的消息类型"){}, + ERR_40009("40009", "不合法的图片文件大小"){}, + ERR_40010("40010", "不合法的语音文件大小"){}, + ERR_40011("40011", "不合法的视频文件大小"){}, + ERR_40012("40012", "不合法的缩略图文件大小"){}, + ERR_40013("40013", "不合法的AppID,请开发者检查AppID的正确性,避免异常字符,注意大小写"){}, + ERR_40014("40014", "不合法的access_token,请开发者认真比对access_token的有效性(如是否过期),或查看是否正在为恰当的公众号调用接口"){}, + ERR_40015("40015", "不合法的菜单类型"){}, + ERR_40016("40016", "不合法的按钮个数"){}, + ERR_40017("40017", "不合法的按钮个数"){}, + ERR_40018("40018", "不合法的按钮名字长度"){}, + ERR_40019("40019", "不合法的按钮KEY长度"){}, + ERR_40020("40020", "不合法的按钮URL长度"){}, + ERR_40021("40021", "不合法的菜单版本号"){}, + ERR_40022("40022", "不合法的子菜单级数"){}, + ERR_40023("40023", "不合法的子菜单按钮个数"){}, + ERR_40024("40024", "不合法的子菜单按钮类型"){}, + ERR_40025("40025", "不合法的子菜单按钮名字长度"){}, + ERR_40026("40026", "不合法的子菜单按钮KEY长度"){}, + ERR_40027("40027", "不合法的子菜单按钮URL长度"){}, + ERR_40028("40028", "不合法的自定义菜单使用用户"){}, + ERR_40029("40029", "不合法的oauth_code"){}, + ERR_40030("40030", "不合法的refresh_token"){}, + ERR_40031("40031", "不合法的openid列表"){}, + ERR_40032("40032", "不合法的openid列表个数"){}, + ERR_40033("40033", "不合法的请求字符,不能包含xxxx格式的字符"){}, + ERR_40035("40035", "不合法的参数"){}, + ERR_40055("40055", "不完整的url,前面要加http://"){}, + ERR_40037("40037", "template_id不正确"){}, + ERR_40038("40038", "不合法的请求格式"){}, + ERR_40039("40039", "不合法的URL长度"){}, + ERR_40050("40050", "不合法的分组id"){}, + ERR_40051("40051", "分组名字不合法"){}, + ERR_40062("40062", "标题长度不合法"){}, + ERR_40097("40097", "参数不合法"){}, + ERR_40113("40113", "文件名称不合法,需包含正确后缀"){}, + ERR_40117("40117", "分组名字不合法"){}, + ERR_40118("40118", "media_id大小不合法"){}, + ERR_40119("40119", "button类型错误"){}, + ERR_40120("40120", "button类型错误"){}, + ERR_40121("40121", "不合法的media_id类型"){}, + ERR_40125("40125", "不合法的AppSecret,请开发者检查AppSecret的正确性,避免异常字符,注意大小写"){}, + ERR_40130("40130", "至少需要同时发送两个用户"){}, + ERR_40132("40132", "微信号不合法"){}, + ERR_40137("40137", "不支持的图片格式"){}, + ERR_40164("40164", "调用接口的IP地址不在白名单中,请在接口IP白名单中进行设置"){}, + ERR_41001("41001", "缺少access_token参数"){}, + ERR_41002("41002", "缺少appid参数"){}, + ERR_41003("41003", "缺少refresh_token参数"){}, + ERR_41004("41004", "缺少secret参数"){}, + ERR_41005("41005", "缺少多媒体文件数据"){}, + ERR_41006("41006", "缺少media_id参数"){}, + ERR_41007("41007", "缺少子菜单数据"){}, + ERR_41008("41008", "缺少oauth code"){}, + ERR_41009("41009", "缺少openid"){}, + ERR_41028("41028", "form_id不正确,或者过期"){}, + ERR_41029("41029", "form_id已被使用"){}, + ERR_41030("41030", "page不正确"){}, + ERR_42001("42001", "access_token超时,请检查access_token的有效期,请参考基础支持-获取access_token中,对access_token的详细机制说明"){}, + ERR_42002("42002", "refresh_token超时"){}, + ERR_42003("42003", "oauth_code超时"){}, + ERR_43001("43001", "需要GET请求"){}, + ERR_43002("43002", "需要POST请求"){}, + ERR_43003("43003", "需要HTTPS请求"){}, + ERR_43004("43004", "需要接收者关注"){}, + ERR_43005("43005", "需要好友关系"){}, + ERR_44001("44001", "多媒体文件为空"){}, + ERR_44002("44002", "POST的数据包为空"){}, + ERR_44003("44003", "图文消息内容为空"){}, + ERR_44004("44004", "文本消息内容为空"){}, + ERR_45001("45001", "多媒体文件大小超过限制"){}, + ERR_45002("45002", "消息内容超过限制"){}, + ERR_45003("45003", "标题字段超过限制"){}, + ERR_45004("45004", "描述字段超过限制"){}, + ERR_45005("45005", "链接字段超过限制"){}, + ERR_45006("45006", "图片链接字段超过限制"){}, + ERR_45007("45007", "语音播放时间超过限制"){}, + ERR_45008("45008", "图文消息超过限制"){}, + ERR_45009("45009", "接口调用超过限制"){}, + ERR_45010("45010", "创建菜单个数超过限制"){}, + ERR_45015("45015", "回复时间超过限制"){}, + ERR_45016("45016", "系统分组,不允许修改"){}, + ERR_45017("45017", "分组名字过长"){}, + ERR_45018("45018", "分组数量超过上限"){}, + ERR_45028("45028", "没有群发的配额,配额已经用完"){}, + ERR_45047("45047", "客服下行消息超过上限"){}, + ERR_45157("45157", "标签名非法,请注意不能和其他标签重名"){}, + ERR_45158("45158", "标签名长度超过30个字节"){}, + ERR_45056("45056", "创建的标签数过多,请注意不能超过100个"){}, + ERR_45058("45058", "不能修改0/1/2这三个系统默认保留的标签"){}, + ERR_45057("45057", "该标签下粉丝数超过10w,不允许直接删除"){}, + ERR_45059("45059", "有粉丝身上的标签数已经超过限制"){}, + ERR_45159("45159", "非法的tag_id"){}, + ERR_46001("46001", "不存在媒体数据"){}, + ERR_46002("46002", "不存在的菜单版本"){}, + ERR_46003("46003", "不存在的菜单数据"){}, + ERR_46004("46004", "不存在的用户"){}, + ERR_47001("47001", "解析JSON/XML内容错误"){}, + ERR_48001("48001", "api功能未授权,请确认公众号已获得该接口,可以在公众平台官网-开发者中心页中查看接口权限"){}, + ERR_48002("48002", "粉丝拒收消息(粉丝在公众号选项中,关闭了 “ 接收消息 ” )"){}, + ERR_48004("48004", "api 接口被封禁,请登录 admin.weixin.qq.com 查看详情"){}, + ERR_48005("48005", "api 禁止删除被自动回复和自定义菜单引用的素材"){}, + ERR_48006("48006", "api 禁止清零调用次数,因为清零次数达到上限"){}, + ERR_48008("48008", "没有该类型消息的发送权限"){}, + ERR_49003("49003", "传入的openid不属于此AppID"){}, + ERR_50001("50001", "用户未授权该api"){}, + ERR_50002("50002", "用户受限,可能是违规后接口被封禁"){}, + ERR_50005("50005", "用户未关注公众号"){}, + ERR_61003("61003", "请确认是否取消授权(第三方平台授权)"){}, + ERR_61004("61004", "当前ip未在白名单中,直接获取本地ip添加"){}, + ERR_61005("61005", " 组件 ticket已失效,重新接受授权url反馈的ticket"){}, + ERR_61006("61006", "获取componentTicket为null"){}, + ERR_61007("61007", "当前公众号或者小程序已在公众平台解绑"){}, + ERR_61009("61009", "授权码失效,重新授权"){}, + ERR_61451("61451", "参数错误(invalid parameter)"){}, + ERR_61452("61452", "无效客服账号(invalid kf_account)"){}, + ERR_61453("61453", "客服帐号已存在(kf_account exsited)"){}, + ERR_61454("61454", "客服帐号名长度超过限制(仅允许10个英文字符,不包括@及@后的公众号的微信号)(invalid kf_acount length)"){}, + ERR_61455("61455", "客服帐号名包含非法字符(仅允许英文+数字)(illegal character in kf_account)"){}, + ERR_61456("61456", "客服帐号个数超过限制(10个客服账号)(kf_account count exceeded)"){}, + ERR_61457("61457", "无效头像文件类型(invalid file type)"){}, + ERR_61450("61450", "系统错误(system error)"){}, + ERR_61500("61500", "日期格式错误"){}, + ERR_61501("61501", "日期范围错误"){}, + ERR_65400("65400", "API不可用,即没有开通/升级到新版客服功能"){}, + ERR_65401("65401", "无效客服帐号"){}, + ERR_65403("65403", "客服昵称不合法"){}, + ERR_65404("65404", "客服帐号不合法"){}, + ERR_65405("65405", "帐号数目已达到上限,不能继续添加"){}, + ERR_65406("65406", "已经存在的客服帐号"){}, + ERR_65407("65407", "邀请对象已经是该公众号客服"){}, + ERR_65408("65408", "本公众号已经有一个邀请给该微信"){}, + ERR_65409("65409", "无效的微信号"){}, + ERR_65410("65410", "邀请对象绑定公众号客服数达到上限(目前每个微信号可以绑定5个公众号客服帐号)"){}, + ERR_65411("65411", "该帐号已经有一个等待确认的邀请,不能重复邀请"){}, + ERR_65412("65412", "该帐号已经绑定微信号,不能进行邀请"){}, + ERR_99999("99999", "无法获取到文件名"){}, + ERR_9001001("9001001", "POST数据参数不合法"){}, + ERR_9001002("9001002", "远端服务不可用"){}, + ERR_9001003("9001003", "Ticket不合法"){}, + ERR_9001004("9001004", "获取摇周边用户信息失败"){}, + ERR_9001005("9001005", "获取商户信息失败"){}, + ERR_9001006("9001006", "获取OpenID失败"){}, + ERR_9001007("9001007", "上传文件缺失"){}, + ERR_9001008("9001008", "上传素材的文件类型不合法"){}, + ERR_9001009("9001009", "上传素材的文件尺寸不合法"){}, + ERR_9001010("9001010", "上传失败"){}, + ERR_9001020("9001020", "帐号不合法"){}, + ERR_9001021("9001021", "已有设备激活率低于50%,不能新增设备"){}, + ERR_9001022("9001022", "设备申请数不合法,必须为大于0的数字"){}, + ERR_9001023("9001023", "已存在审核中的设备ID申请"){}, + ERR_9001024("9001024", "一次查询设备ID数量不能超过50"){}, + ERR_9001025("9001025", "设备ID不合法"){}, + ERR_9001026("9001026", "页面ID不合法"){}, + ERR_9001027("9001027", "页面参数不合法"){}, + ERR_9001028("9001028", "一次删除页面ID数量不能超过10"){}, + ERR_9001029("9001029", "页面已应用在设备中,请先解除应用关系再删除"){}, + ERR_9001030("9001030", "一次查询页面ID数量不能超过50"){}, + ERR_9001031("9001031", "时间区间不合法"){}, + ERR_9001032("9001032", "保存设备与页面的绑定关系参数错误"){}, + ERR_9001033("9001033", "门店ID不合法"){}, + ERR_9001034("9001034", "设备备注信息过长"){}, + ERR_9001035("9001035", "设备申请参数不合法"){}, + ERR_9001036("9001036", "查询起始值begin不合法"){} + ; + + WxReturnCode(String code, String msg) { + this.code = code; + this.msg = msg; + } + + private String code; + private String msg; + + /** + * 通过code获取msg + * @param code + * @return + */ + public static String getMsg(String code) { + try { + return WxReturnCode.valueOf(code).getMsg(); + }catch (IllegalArgumentException e){ + return "未定义的返回码:"+code; + } + } + + public String getCode() { + return code; + } + public void setCode(String code) { + this.code = code; + } + public String getMsg() { + return msg; + } + public void setMsg(String msg) { + this.msg = msg; + } + + @Override + public String toString() { + return "WxReturnCode{" + "code='" + code + '\'' + "msg='" + msg + '\'' + '}'; + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WeChatController.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WeChatController.java new file mode 100644 index 0000000..0c45e8e --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WeChatController.java @@ -0,0 +1,58 @@ +package com.ruoyi.weixin.controller; + +import com.ruoyi.weixin.utils.CheckUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; + +/** + * 业务模块 + * + * @author tianyongbao + * @date 2025/1/8 + */ + +/** + * 服务器验证 + * + * @author tianyongbao + * @date 2025/1/8 + */ +@RestController +@AllArgsConstructor +@RequestMapping("/api") +@Api(tags = "对接微信模块") +public class WeChatController { + /** + * 功能描述: 签名校验 + */ + @GetMapping("/wx") + @ApiOperation(value = "签名校验", notes = "签名校验") + public void login(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException { + request.setCharacterEncoding("UTF-8"); + String signature = request.getParameter("signature"); + String timestamp = request.getParameter("timestamp"); + String nonce = request.getParameter("nonce"); + String echostr = request.getParameter("echostr"); + PrintWriter out = null; + try { + out = response.getWriter(); + if (CheckUtil.checkSignature(signature, timestamp, nonce)) { + out.write(echostr); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + out.close(); + } + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxAutoReplyController.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxAutoReplyController.java new file mode 100644 index 0000000..54675b2 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxAutoReplyController.java @@ -0,0 +1,148 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.controller; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.core.web.controller.BaseController; +import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.common.security.annotation.RequiresPermissions; +import com.ruoyi.weixin.constant.ConfigConstant; +import com.ruoyi.weixin.entity.WxAutoReply; +import com.ruoyi.weixin.service.WxAutoReplyService; +import lombok.AllArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 消息自动回复 + * + * @author www.joolun.com + * @date 2019-04-18 15:40:39 + */ +@RestController +@AllArgsConstructor +@RequestMapping("/wxautoreply") +public class WxAutoReplyController extends BaseController { + + private final WxAutoReplyService wxAutoReplyService; + + /** + * 分页查询 + * @param page 分页对象 + * @param wxAutoReply 消息自动回复 + * @return + */ + @GetMapping("/page") + @RequiresPermissions("wxmp:wxautoreply:index") + public AjaxResult getWxAutoReplyPage(Page page, WxAutoReply wxAutoReply) { + return AjaxResult.success(wxAutoReplyService.page(page,Wrappers.query(wxAutoReply))); + } + + + /** + * 通过id查询消息自动回复 + * @param id id + * @return R + */ + @GetMapping("/{id}") + @RequiresPermissions("wxmp:wxautoreply:get") + public AjaxResult getById(@PathVariable("id") String id){ + return AjaxResult.success(wxAutoReplyService.getById(id)); + } + + /** + * 新增消息自动回复 + * @param wxAutoReply 消息自动回复 + * @return R + */ + @PostMapping + @RequiresPermissions("wxmp:wxautoreply:add") + public AjaxResult save(@RequestBody WxAutoReply wxAutoReply){ + this.jude(wxAutoReply); + return AjaxResult.success(wxAutoReplyService.save(wxAutoReply)); + } + + /** + * 修改消息自动回复 + * @param wxAutoReply 消息自动回复 + * @return R + */ + @PutMapping + @RequiresPermissions("wxmp:wxautoreply:edit") + public AjaxResult updateById(@RequestBody WxAutoReply wxAutoReply){ + this.jude(wxAutoReply); + return AjaxResult.success(wxAutoReplyService.updateById(wxAutoReply)); + } + + /** + * 通过id删除消息自动回复 + * @param id id + * @return R + */ + @DeleteMapping("/{id}") + @RequiresPermissions("wxmp:wxautoreply:del") + public AjaxResult removeById(@PathVariable String id){ + return AjaxResult.success(wxAutoReplyService.removeById(id)); + } + + /** + * //校验参数 + * @param wxAutoReply + */ + public void jude(WxAutoReply wxAutoReply){ + if(ConfigConstant.WX_AUTO_REPLY_TYPE_2.equals(wxAutoReply.getType())){ + Wrapper queryWrapper = Wrappers.lambdaQuery() + .eq(WxAutoReply::getReqType,wxAutoReply.getReqType()); + List list = wxAutoReplyService.list(queryWrapper); + if(StringUtils.isNotBlank(wxAutoReply.getId())){ + if(list != null && list.size() == 1){ + if(!list.get(0).getId().equals(wxAutoReply.getId())){ + throw new RuntimeException("请求消息类型重复"); + } + } + if(list != null && list.size()>1){ + throw new RuntimeException("请求消息类型重复"); + } + } + } + if(ConfigConstant.WX_AUTO_REPLY_TYPE_3.equals(wxAutoReply.getType())){ + Wrapper queryWrapper = Wrappers.lambdaQuery() + .eq(WxAutoReply::getReqKey,wxAutoReply.getReqKey()) + .eq(WxAutoReply::getRepType,wxAutoReply.getRepMate()); + List list = wxAutoReplyService.list(queryWrapper); + if(list != null && list.size() == 1){ + if(!list.get(0).getId().equals(wxAutoReply.getId())){ + throw new RuntimeException("关键词重复"); + } + } + if(list != null && list.size()>1){ + throw new RuntimeException("关键词重复"); + } + } + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxDraftController.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxDraftController.java new file mode 100644 index 0000000..42d02b6 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxDraftController.java @@ -0,0 +1,141 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.controller; + +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.core.web.controller.BaseController; +import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.common.security.annotation.RequiresPermissions; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.mp.api.WxMpDraftService; +import me.chanjar.weixin.mp.api.WxMpFreePublishService; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.draft.WxMpAddDraft; +import me.chanjar.weixin.mp.bean.draft.WxMpDraftArticles; +import me.chanjar.weixin.mp.bean.draft.WxMpUpdateDraft; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 微信草稿箱 + * + * @author www.joolun.com + * @date 2022-03-10 21:26:35 + */ +@Slf4j +@RestController +@AllArgsConstructor +@RequestMapping("/wxdraft") +public class WxDraftController extends BaseController { + private final WxMpService wxService; + + /** + * 新增图文消息 + * + * @param data + * @return + */ + @PostMapping + @RequiresPermissions("wxmp:wxdraft:add") + public AjaxResult add(@RequestBody JSONObject data) throws Exception { + JSONArray jSONArray = data.getJSONArray("articles"); + List articles = jSONArray.toList(WxMpDraftArticles.class); + WxMpAddDraft wxMpAddDraft = new WxMpAddDraft(); + wxMpAddDraft.setArticles(articles); + WxMpDraftService wxMpDraftService = wxService.getDraftService(); + String rs = wxMpDraftService.addDraft(wxMpAddDraft); + return AjaxResult.success(rs); + } + + /** + * 修改微信草稿箱 + * + * @param data + * @return + */ + @PutMapping + @RequiresPermissions("wxmp:wxdraft:edit") + public AjaxResult edit(@RequestBody JSONObject data) throws Exception { + String mediaId = data.getStr("mediaId"); + JSONArray jSONArray = data.getJSONArray("articles"); + List articles = jSONArray.toList(WxMpDraftArticles.class); + WxMpDraftService wxMpDraftService = wxService.getDraftService(); + WxMpUpdateDraft wxMpUpdateDraft = new WxMpUpdateDraft(); + wxMpUpdateDraft.setMediaId(mediaId); + int index = 0; + for (WxMpDraftArticles article : articles) { + wxMpUpdateDraft.setIndex(index); + wxMpUpdateDraft.setArticles(article); + wxMpDraftService.updateDraft(wxMpUpdateDraft); + index++; + } + return AjaxResult.success(); + } + + /** + * 通过id删除微信草稿箱 + * + * @param + * @return R + */ + @DeleteMapping + @RequiresPermissions("wxmp:wxdraft:del") + public AjaxResult del(String id) throws Exception { + WxMpDraftService wxMpDraftService = wxService.getDraftService(); + return AjaxResult.success(wxMpDraftService.delDraft(id)); + } + + /** + * 分页查询 + * + * @param page 分页对象 + * @param + * @return + */ + @GetMapping("/page") + @RequiresPermissions("wxmp:wxdraft:index") + public AjaxResult getPage(Page page) throws Exception { + WxMpDraftService wxMpDraftService = wxService.getDraftService(); + int count = (int) page.getSize(); + int offset = (int) page.getCurrent() * count - count; + return AjaxResult.success(wxMpDraftService.listDraft(offset, count)); + } + + /** + * 发布草稿箱 + * @param id + * @return + */ + @PostMapping("/publish/{id}") + @RequiresPermissions("wxmp:wxdraft:publish") + public AjaxResult publish(@PathVariable String id) throws Exception { + WxMpFreePublishService wxMpFreePublishService = wxService.getFreePublishService(); + wxMpFreePublishService.submit(id); + return AjaxResult.success(); + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxFreePublishController.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxFreePublishController.java new file mode 100644 index 0000000..8f624cb --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxFreePublishController.java @@ -0,0 +1,81 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.core.web.controller.BaseController; +import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.common.security.annotation.RequiresPermissions; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.mp.api.WxMpFreePublishService; +import me.chanjar.weixin.mp.api.WxMpService; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 微信发布 + * + * @author www.joolun.com + * @date 2022-03-10 21:26:35 + */ +@Slf4j +@RestController +@AllArgsConstructor +@RequestMapping("/freepublish") +public class WxFreePublishController extends BaseController { + private final WxMpService wxService; + + /** + * 删除发布 + * + * @param + * @return R + */ + @DeleteMapping + @RequiresPermissions("wxmp:wxfreepublish:del") + public AjaxResult del(String id) throws Exception { + WxMpFreePublishService wxMpFreePublishService = wxService.getFreePublishService(); + return AjaxResult.success(wxMpFreePublishService.deletePushAllArticle(id)); + } + + /** + * 获取成功发布列表 + * + * @param page 获取成功发布列表 + * @param + * @return + */ + @GetMapping("/page") + @RequiresPermissions("wxmp:wxfreepublish:index") + public AjaxResult getPage(Page page) throws Exception { + WxMpFreePublishService wxMpFreePublishService = wxService.getFreePublishService(); + int count = (int) page.getSize(); + int offset = (int) page.getCurrent() * count - count; + return AjaxResult.success(wxMpFreePublishService.getPublicationRecords(offset, count)); + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxMaterialController.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxMaterialController.java new file mode 100644 index 0000000..5c093ee --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxMaterialController.java @@ -0,0 +1,266 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.controller; + +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.core.web.controller.BaseController; +import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.common.security.annotation.RequiresPermissions; +import com.ruoyi.weixin.entity.ImageManager; +import com.ruoyi.weixin.utils.FileUtils; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpMaterialService; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult; +import me.chanjar.weixin.mp.bean.material.WxMpMaterial; +import me.chanjar.weixin.mp.bean.material.WxMpMaterialFileBatchGetResult; +import me.chanjar.weixin.mp.bean.material.WxMpMaterialUploadResult; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 微信素材 + * + * @author www.joolun.com + * @date 2019-03-23 21:26:35 + */ +@Slf4j +@RestController +@AllArgsConstructor +@RequestMapping("/wxmaterial") +public class WxMaterialController extends BaseController { + + private final WxMpService wxService; + + /** + * 上传非图文微信素材 + * @param mulFile + * @param mediaType + * @return + */ + @PostMapping("/materialFileUpload") + // @PreAuthorize("@ss.hasPermi('wxmp:wxmaterial:add')") + public AjaxResult materialFileUpload(@RequestParam("file") MultipartFile mulFile, + @RequestParam("title") String title, + @RequestParam("introduction") String introduction, + @RequestParam("mediaType") String mediaType) { + try { + WxMpMaterial material = new WxMpMaterial(); + material.setName(mulFile.getOriginalFilename()); + if(WxConsts.MediaFileType.VIDEO.equals(mediaType)){ + material.setVideoTitle(title); + material.setVideoIntroduction(introduction); + } + File file = FileUtils.multipartFileToFile(mulFile); + material.setFile(file); + WxMpMaterialService wxMpMaterialService = wxService.getMaterialService(); + WxMpMaterialUploadResult wxMpMaterialUploadResult = wxMpMaterialService.materialFileUpload(mediaType,material); + WxMpMaterialFileBatchGetResult.WxMaterialFileBatchGetNewsItem wxMpMaterialFileBatchGetResult = new WxMpMaterialFileBatchGetResult.WxMaterialFileBatchGetNewsItem(); + wxMpMaterialFileBatchGetResult.setName(file.getName()); + wxMpMaterialFileBatchGetResult.setMediaId(wxMpMaterialUploadResult.getMediaId()); + wxMpMaterialFileBatchGetResult.setUrl(wxMpMaterialUploadResult.getUrl()); + return AjaxResult.success(wxMpMaterialFileBatchGetResult); + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("上传非图文微信素材失败" + e); + return AjaxResult.error(e.getMessage()); + } catch (Exception e) { + e.printStackTrace(); + log.error("上传失败", e); + return AjaxResult.error(e.getLocalizedMessage()); + } + } + + /** + * 上传图文消息内的图片获取URL + * @param mulFile + * @return + */ + @PostMapping("/newsImgUpload") + // @PreAuthorize("@ss.hasPermi('wxmp:wxmaterial:add')") + public String newsImgUpload(@RequestParam("file") MultipartFile mulFile) throws Exception { + File file = FileUtils.multipartFileToFile(mulFile); + WxMpMaterialService wxMpMaterialService = wxService.getMaterialService(); + WxMediaImgUploadResult wxMediaImgUploadResult = wxMpMaterialService.mediaImgUpload(file); + Map responseData = new HashMap<>(); + responseData.put("link", wxMediaImgUploadResult.getUrl()); + return JSONUtil.toJsonStr(responseData); + } + + /** + * 通过id删除微信素材 + * @param + * @return R + */ + @DeleteMapping + @RequiresPermissions("wxmp:wxmaterial:del") + public AjaxResult materialDel(String id){ + WxMpMaterialService wxMpMaterialService = wxService.getMaterialService(); + try { + return AjaxResult.success(wxMpMaterialService.materialDelete(id)); + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("删除微信素材失败", e); + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 分页查询 + * @param page 分页对象 + * @param type + * @return + */ + @GetMapping("/page") + @RequiresPermissions("wxmp:wxmaterial:index") + public AjaxResult getWxMaterialPage(Page page, String type) { + try { + WxMpMaterialService wxMpMaterialService = wxService.getMaterialService(); + int count = (int)page.getSize(); + int offset = (int)page.getCurrent()*count-count; + if(WxConsts.MaterialType.NEWS.equals(type)){ + return AjaxResult.success(wxMpMaterialService.materialNewsBatchGet(offset,count)); + }else{ + return AjaxResult.success(wxMpMaterialService.materialFileBatchGet(type,offset,count)); + } + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("查询素材失败", e); + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 分页查询2 + * @param type + * @return + */ + @GetMapping("/page-manager") +// @PreAuthorize("@ss.hasPermi('wxmp:wxmaterial:index')") + public String getWxMaterialPageManager(Integer count, Integer offset, String type) throws WxErrorException { + List listImageManager = new ArrayList<>(); + WxMpMaterialService wxMpMaterialService = wxService.getMaterialService(); + List list = wxMpMaterialService.materialFileBatchGet(type,offset,count).getItems(); + list.forEach(wxMaterialFileBatchGetNewsItem -> { + ImageManager imageManager = new ImageManager(); + imageManager.setName(wxMaterialFileBatchGetNewsItem.getMediaId()); + imageManager.setUrl(wxMaterialFileBatchGetNewsItem.getUrl()); + imageManager.setThumb(wxMaterialFileBatchGetNewsItem.getUrl()); + listImageManager.add(imageManager); + }); + return JSONUtil.toJsonStr(listImageManager); + } + + /** + * 获取微信视频素材 + * @param + * @return R + */ + @GetMapping("/materialVideo") + @RequiresPermissions("wxmp:wxmaterial:get") + public AjaxResult getMaterialVideo(String mediaId){ + WxMpMaterialService wxMpMaterialService = wxService.getMaterialService(); + try { + return AjaxResult.success(wxMpMaterialService.materialVideoInfo(mediaId)); + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("获取微信视频素材失败", e); + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 获取微信素材直接文件 + * @param + * @return R + */ + @GetMapping("/materialOther") + @RequiresPermissions("wxmp:wxmaterial:get") + public ResponseEntity getMaterialOther(String mediaId, String fileName) throws Exception { + try { + WxMpMaterialService wxMpMaterialService = wxService.getMaterialService(); + //获取文件 + InputStream is = wxMpMaterialService.materialImageOrVoiceDownload(mediaId); + byte[] body = new byte[is.available()]; + is.read(body); + HttpHeaders headers = new HttpHeaders(); + //设置文件类型 + headers.add("Content-Disposition", "attchement;filename=" + URLEncoder.encode(fileName, "UTF-8")); + headers.add("Content-Type", "application/octet-stream"); + HttpStatus statusCode = HttpStatus.OK; + //返回数据 + ResponseEntity entity = new ResponseEntity(body, headers, statusCode); + return entity; + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("获取微信素材直接文件失败", e); + return null; + } + } + + /** + * 获取微信临时素材直接文件 + * @param + * @return R + */ + @GetMapping("/tempMaterialOther") + @RequiresPermissions("wxmp:wxmsg:index") + public ResponseEntity getTempMaterialOther(String mediaId, String fileName) throws Exception { + try { + WxMpMaterialService wxMpMaterialService = wxService.getMaterialService(); + //获取文件 + InputStream is = new FileInputStream(wxMpMaterialService.mediaDownload(mediaId)); + byte[] body = new byte[is.available()]; + is.read(body); + HttpHeaders headers = new HttpHeaders(); + //设置文件类型 + headers.add("Content-Disposition", "attchement;filename=" + URLEncoder.encode(fileName, "UTF-8")); + headers.add("Content-Type", "application/octet-stream"); + HttpStatus statusCode = HttpStatus.OK; + //返回数据 + ResponseEntity entity = new ResponseEntity(body, headers, statusCode); + return entity; + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("获取微信素材直接文件失败", e); + return null; + } + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxMenuController.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxMenuController.java new file mode 100644 index 0000000..c66c719 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxMenuController.java @@ -0,0 +1,84 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.controller; + +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.ruoyi.common.core.web.controller.BaseController; +import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.common.security.annotation.RequiresPermissions; +import com.ruoyi.weixin.service.WxMenuService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import org.springframework.web.bind.annotation.*; + +/** + * 自定义菜单 + * + * @author www.joolun.com + * @date 2019-03-27 16:52:10 + */ +@Slf4j +@RestController +@AllArgsConstructor +@RequestMapping("/wxmenu") +public class WxMenuController extends BaseController { + + private final WxMenuService wxMenuService; + + /** + * 通过appId查询自定义菜单 + * + * @return R + */ + @GetMapping("/list") + @RequiresPermissions("wxmp:wxmenu:get") + public AjaxResult getWxMenuButton() { + return AjaxResult.success(wxMenuService.getWxMenuButton()); + } + + /** + * 保存并发布菜单 + * + * @param + * @return R + */ + @PostMapping("/release") + @RequiresPermissions("wxmp:wxmenu:add") + public AjaxResult saveAndRelease(@RequestBody String data) { + JSONObject jSONObject = JSONUtil.parseObj(data); + String strWxMenu = jSONObject.getStr("strWxMenu"); + String appId = jSONObject.getStr("appId"); + try { + wxMenuService.saveAndRelease(strWxMenu); + return AjaxResult.success(); + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("发布自定义菜单失败appID:" + appId + ":" + e.getMessage()); + return AjaxResult.error(e.getMessage()); + } + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxMsgController.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxMsgController.java new file mode 100644 index 0000000..87632f4 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxMsgController.java @@ -0,0 +1,222 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.controller; + +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.core.web.controller.BaseController; +import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.common.security.annotation.RequiresPermissions; +import com.ruoyi.weixin.config.CommonConstants; +import com.ruoyi.weixin.constant.ConfigConstant; +import com.ruoyi.weixin.entity.WxMsg; +import com.ruoyi.weixin.entity.WxMsgVO; +import com.ruoyi.weixin.entity.WxUser; +import com.ruoyi.weixin.service.WxMsgService; +import com.ruoyi.weixin.service.WxUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpKefuService; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +/** + * 微信消息 + * + * @author www.joolun.com + * @date 2019-05-28 16:12:10 + */ +@Slf4j +@RestController +@AllArgsConstructor +@RequestMapping("/wxmsg") +public class WxMsgController extends BaseController { + + private final WxMsgService wxMsgService; + private final WxUserService wxUserService; + private final WxMpService wxService; + + /** + * 分页查询 + * @param page 分页对象 + * @param wxMsgVO 微信消息 + * @return + */ + @GetMapping("/page") + @RequiresPermissions("wxmp:wxmsg:index") + public AjaxResult getWxMsgPage(Page page, WxMsgVO wxMsgVO) { + if(StringUtils.isNotBlank(wxMsgVO.getNotInRepType())){ + return AjaxResult.success(wxMsgService.listWxMsgMapGroup(page,wxMsgVO)); + } + if(StringUtils.isNotBlank(wxMsgVO.getWxUserId())){//标记为已读 + WxMsg wxMsg = new WxMsg(); + wxMsg.setReadFlag(CommonConstants.YES); + Wrapper queryWrapper = Wrappers.lambdaQuery() + .eq(WxMsg::getWxUserId,wxMsgVO.getWxUserId()) + .eq(WxMsg::getReadFlag,CommonConstants.NO); + wxMsgService.update(wxMsg,queryWrapper); + } + return AjaxResult.success(wxMsgService.page(page,Wrappers.query(wxMsgVO))); + } + + /** + * 通过id查询微信消息 + * @param id id + * @return R + */ + @GetMapping("/{id}") + @RequiresPermissions("wxmp:wxmsg:get") + public AjaxResult getById(@PathVariable("id") String id){ + return AjaxResult.success(wxMsgService.getById(id)); + } + + /** + * 新增微信消息 + * @param wxMsg 微信消息 + * @return R + */ + @PostMapping + @RequiresPermissions("wxmp:wxmsg:add") + public AjaxResult save(@RequestBody WxMsg wxMsg){ + try { + WxUser wxUser = wxUserService.getById(wxMsg.getWxUserId()); + //入库 + wxMsg.setNickName(wxUser.getNickName()); + wxMsg.setHeadimgUrl(wxUser.getHeadimgUrl()); + wxMsg.setCreateTime(LocalDateTime.now()); + wxMsg.setType(ConfigConstant.WX_MSG_TYPE_2); + WxMpKefuMessage wxMpKefuMessage = null; + if(WxConsts.KefuMsgType.TEXT.equals(wxMsg.getRepType())){ + wxMsg.setRepContent(wxMsg.getRepContent()); + wxMpKefuMessage = WxMpKefuMessage.TEXT().build(); + wxMpKefuMessage.setContent(wxMsg.getRepContent()); + } + if(WxConsts.KefuMsgType.IMAGE.equals(wxMsg.getRepType())){//图片 + wxMsg.setRepName(wxMsg.getRepName()); + wxMsg.setRepUrl(wxMsg.getRepUrl()); + wxMsg.setRepMediaId(wxMsg.getRepMediaId()); + wxMpKefuMessage = WxMpKefuMessage.IMAGE().build(); + wxMpKefuMessage.setMediaId(wxMsg.getRepMediaId()); + } + if(WxConsts.KefuMsgType.VOICE.equals(wxMsg.getRepType())){ + wxMsg.setRepName(wxMsg.getRepName()); + wxMsg.setRepUrl(wxMsg.getRepUrl()); + wxMsg.setRepMediaId(wxMsg.getRepMediaId()); + wxMpKefuMessage = WxMpKefuMessage.VOICE().build(); + wxMpKefuMessage.setMediaId(wxMsg.getRepMediaId()); + } + if(WxConsts.KefuMsgType.VIDEO.equals(wxMsg.getRepType())){ + wxMsg.setRepName(wxMsg.getRepName()); + wxMsg.setRepDesc(wxMsg.getRepDesc()); + wxMsg.setRepUrl(wxMsg.getRepUrl()); + wxMsg.setRepMediaId(wxMsg.getRepMediaId()); + wxMpKefuMessage = WxMpKefuMessage.VIDEO().build(); + wxMpKefuMessage.setMediaId(wxMsg.getRepMediaId()); + wxMpKefuMessage.setTitle(wxMsg.getRepName()); + wxMpKefuMessage.setDescription(wxMsg.getRepDesc()); + } + if(WxConsts.KefuMsgType.MUSIC.equals(wxMsg.getRepType())){ + wxMsg.setRepName(wxMsg.getRepName()); + wxMsg.setRepDesc(wxMsg.getRepDesc()); + wxMsg.setRepUrl(wxMsg.getRepUrl()); + wxMsg.setRepHqUrl(wxMsg.getRepHqUrl()); + wxMpKefuMessage = WxMpKefuMessage.MUSIC().build(); + wxMpKefuMessage.setTitle(wxMsg.getRepName()); + wxMpKefuMessage.setDescription(wxMsg.getRepDesc()); + wxMpKefuMessage.setMusicUrl(wxMsg.getRepUrl()); + wxMpKefuMessage.setHqMusicUrl(wxMsg.getRepHqUrl()); + wxMpKefuMessage.setThumbMediaId(wxMsg.getRepThumbMediaId()); + } + if(WxConsts.KefuMsgType.NEWS.equals(wxMsg.getRepType())){ + List list = new ArrayList<>(); + JSONArray jSONArray = wxMsg.getContent().getJSONArray("articles"); + WxMpKefuMessage.WxArticle t; + for(Object object : jSONArray){ + JSONObject jSONObject = JSONUtil.parseObj(JSONUtil.toJsonStr(object)); + t = new WxMpKefuMessage.WxArticle(); + t.setTitle(jSONObject.getStr("title")); + t.setDescription(jSONObject.getStr("digest")); + t.setPicUrl(jSONObject.getStr("thumbUrl")); + t.setUrl(jSONObject.getStr("url")); + list.add(t); + } + wxMsg.setRepName(wxMsg.getRepName()); + wxMsg.setRepDesc(wxMsg.getRepDesc()); + wxMsg.setRepUrl(wxMsg.getRepUrl()); + wxMsg.setRepMediaId(wxMsg.getRepMediaId()); + wxMsg.setContent(wxMsg.getContent()); + wxMpKefuMessage = WxMpKefuMessage.NEWS().build(); + wxMpKefuMessage.setArticles(list); + } + if(wxMpKefuMessage != null){ + WxMpKefuService wxMpKefuService = wxService.getKefuService(); + wxMpKefuMessage.setToUser(wxUser.getOpenId()); + wxMpKefuService.sendKefuMessage(wxMpKefuMessage); + wxMsgService.save(wxMsg); + return AjaxResult.success(wxMsg); + }else{ + return AjaxResult.error("非法消息类型"); + } + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("新增微信消息失败"+e.getMessage()); + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 修改微信消息 + * @param wxMsg 微信消息 + * @return R + */ + @PutMapping + @RequiresPermissions("wxmp:wxmsg:edit") + public AjaxResult updateById(@RequestBody WxMsg wxMsg){ + return AjaxResult.success(wxMsgService.updateById(wxMsg)); + } + + /** + * 通过id删除微信消息 + * @param id id + * @return R + */ + @DeleteMapping("/{id}") + @RequiresPermissions("wxmp:wxmsg:del") + public AjaxResult removeById(@PathVariable String id){ + return AjaxResult.success(wxMsgService.removeById(id)); + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxPortalController.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxPortalController.java new file mode 100644 index 0000000..a53902e --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxPortalController.java @@ -0,0 +1,128 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.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("/weixin/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; + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxSummaryController.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxSummaryController.java new file mode 100644 index 0000000..722e241 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxSummaryController.java @@ -0,0 +1,127 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.controller; + + +import com.ruoyi.common.core.web.controller.BaseController; +import com.ruoyi.common.core.web.domain.AjaxResult; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpDataCubeService; +import me.chanjar.weixin.mp.api.WxMpService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.text.SimpleDateFormat; + +/** + * 微信账号配置 + * + * @author www.joolun.com + * @date 2019-03-23 21:26:35 + */ +@Slf4j +@RestController +@AllArgsConstructor +@RequestMapping("/wxsummary") +public class WxSummaryController extends BaseController { + + private final WxMpService wxService; + /** + * 获取用户增减数据 + * @param appId + * @param startDate + * @param endDate + * @return + */ + @GetMapping("/usersummary") +// @PreAuthorize("@ss.hasPermi('wxmp:wxsummary:index')") + public AjaxResult getUsersummary(String appId, String startDate, String endDate) { + try { + WxMpDataCubeService wxMpDataCubeService = wxService.getDataCubeService(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + return AjaxResult.success(wxMpDataCubeService.getUserSummary(sdf.parse(startDate), sdf.parse(endDate))); + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("获取用户增减数据失败",e); + return AjaxResult.error(e.getMessage()); + }catch (Exception e) { + e.printStackTrace(); + log.error("获取用户增减数据失败",e); + return AjaxResult.error("获取用户增减数据失败"); + } + } + + /** + * 获取累计用户数据 + * @param appId + * @param startDate + * @param endDate + * @return + */ + @GetMapping("/usercumulate") +// @PreAuthorize("@ss.hasPermi('wxmp:wxsummary:index')") + public AjaxResult getUserCumulate(String appId, String startDate, String endDate){ + try { + WxMpDataCubeService wxMpDataCubeService = wxService.getDataCubeService(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + return AjaxResult.success(wxMpDataCubeService.getUserCumulate(sdf.parse(startDate), sdf.parse(endDate))); + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("获取累计用户数据失败",e); + return AjaxResult.error(e.getMessage()); + }catch (Exception e) { + e.printStackTrace(); + log.error("获取用户增减数据失败",e); + return AjaxResult.error("获取用户增减数据失败"); + } + } + + /** + * 获取接口分析数据 + * @param appId + * @param startDate + * @param endDate + * @return + */ + @GetMapping("/interfacesummary") +// @PreAuthorize("@ss.hasPermi('wxmp:wxsummary:index')") + public AjaxResult getInterfaceSummary(String appId, String startDate, String endDate){ + try { + WxMpDataCubeService wxMpDataCubeService = wxService.getDataCubeService(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + return AjaxResult.success(wxMpDataCubeService.getInterfaceSummary(sdf.parse(startDate), sdf.parse(endDate))); + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("获取接口分析数据失败",e); + return AjaxResult.error(e.getMessage()); + }catch (Exception e) { + e.printStackTrace(); + log.error("获取接口分析数据失败",e); + return AjaxResult.error("获取接口分析数据失败"); + } + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxUserController.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxUserController.java new file mode 100644 index 0000000..c6e589d --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxUserController.java @@ -0,0 +1,195 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.controller; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.core.web.controller.BaseController; +import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.common.security.annotation.RequiresPermissions; +import com.ruoyi.weixin.entity.WxUser; +import com.ruoyi.weixin.service.WxUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.bind.annotation.*; + +/** + * 微信用户 + * + * @author www.joolun.com + * @date 2019-03-25 15:39:39 + */ +@Slf4j +@RestController +@AllArgsConstructor +@RequestMapping("/wxuser") +public class WxUserController extends BaseController { + + private final WxUserService wxUserService; + + /** + * 分页查询 + * + * @param page 分页对象 + * @param wxUser 微信用户 + * @return + */ + @GetMapping("/page") + @RequiresPermissions("wxmp:wxuser:index") + public AjaxResult getWxUserPage(Page page, WxUser wxUser, String tagId) { + Wrapper queryWrapper; + if (StringUtils.isNotBlank(tagId)) { + queryWrapper = Wrappers.lambdaQuery(wxUser) + .and(wrapper -> wrapper + .eq(WxUser::getTagidList, "[" + tagId + "]") + .or() + .like(WxUser::getTagidList, "," + tagId + ",") + .or() + .likeRight(WxUser::getTagidList, "[" + tagId + ",") + .or() + .likeLeft(WxUser::getTagidList, "," + tagId + "]")); + } else if (StrUtil.isNotBlank(wxUser.getNickName())) { + String nickName = wxUser.getNickName(); + wxUser.setNickName(null); + queryWrapper = Wrappers.lambdaQuery(wxUser) + .like(WxUser::getNickName, nickName); + } else { + queryWrapper = Wrappers.lambdaQuery(wxUser); + } + return AjaxResult.success(wxUserService.page(page, queryWrapper)); + } + + + /** + * 通过id查询微信用户 + * + * @param id id + * @return R + */ + @GetMapping("/{id}") + @RequiresPermissions("wxmp:wxuser:get") + public AjaxResult getById(@PathVariable("id") String id) { + return AjaxResult.success(wxUserService.getById(id)); + } + + /** + * 新增微信用户 + * + * @param wxUser 微信用户 + * @return R + */ + @PostMapping + @RequiresPermissions("wxmp:wxuser:add") + public AjaxResult save(@RequestBody WxUser wxUser) { + return AjaxResult.success(wxUserService.save(wxUser)); + } + + /** + * 修改微信用户 + * + * @param wxUser 微信用户 + * @return R + */ + @PutMapping + @RequiresPermissions("wxmp:wxuser:edit") + public AjaxResult updateById(@RequestBody WxUser wxUser) { + return AjaxResult.success(wxUserService.updateById(wxUser)); + } + + /** + * 通过id删除微信用户 + * + * @param id id + * @return R + */ + @DeleteMapping("/{id}") + @RequiresPermissions("wxmp:wxuser:del") + public AjaxResult removeById(@PathVariable String id) { + return AjaxResult.success(wxUserService.removeById(id)); + } + + @PostMapping("/synchron") + @RequiresPermissions("wxmp:wxuser:synchro") + public AjaxResult synchron() { + try { + wxUserService.synchroWxUser(); + return AjaxResult.success(); + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("同步微信用户失败", e); + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 修改微信用户备注 + * + * @param wxUser + * @return + */ + @PutMapping("/remark") + @RequiresPermissions("wxmp:wxuser:edit:remark") + public AjaxResult remark(@RequestBody WxUser wxUser) { + try { + return AjaxResult.success(wxUserService.updateRemark(wxUser)); + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("修改微信用户备注失败", e); + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 打标签 + * + * @param data + * @return + */ + @PutMapping("/tagid-list") + @RequiresPermissions("wxmp:wxuser:tagging") + public AjaxResult tagidList(@RequestBody JSONObject data) { + try { + String appId = data.getStr("appId"); + String taggingType = data.getStr("taggingType"); + JSONArray tagIdsArray = data.getJSONArray("tagIds"); + JSONArray openIdsArray = data.getJSONArray("openIds"); + String[] openIds = openIdsArray.toArray(new String[0]); + for (Object tagId : tagIdsArray) { + wxUserService.tagging(taggingType, Long.valueOf(String.valueOf(tagId)), openIds); + } + return AjaxResult.success(); + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("修改微信用户备注失败", e); + return AjaxResult.error(e.getMessage()); + } + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxUserTagsController.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxUserTagsController.java new file mode 100644 index 0000000..288e82b --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/controller/WxUserTagsController.java @@ -0,0 +1,174 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.controller; + +import cn.hutool.json.JSONObject; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ruoyi.common.core.web.controller.BaseController; +import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.common.security.annotation.RequiresPermissions; +import com.ruoyi.weixin.entity.WxUser; +import com.ruoyi.weixin.entity.WxUserTagsDict; +import com.ruoyi.weixin.service.WxUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.WxMpUserTagService; +import me.chanjar.weixin.mp.bean.tag.WxUserTag; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; + +/** + * 微信用户标签 + * + * @author www.joolun.com + * @date 2019-03-25 15:39:39 + */ +@Slf4j +@RestController +@AllArgsConstructor +@RequestMapping("/wxusertags") +public class WxUserTagsController extends BaseController { + + private final WxMpService wxService; + private final WxUserService wxUserService; + + /** + * 获取微信用户标签 + * @return + */ + @RequiresPermissions("wxmp:wxusertags:list") + @GetMapping("/list") + public AjaxResult getWxUserList(String appId) { + WxMpUserTagService wxMpUserTagService = wxService.getUserTagService(); + try { + List listWxUserTag = wxMpUserTagService.tagGet(); + return AjaxResult.success(listWxUserTag); + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("获取微信用户标签失败", e); + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 获取微信用户标签字典 + * @param appId + * @return + */ + @RequiresPermissions("wxmp:wxusertags:list") + @GetMapping("/dict") + public AjaxResult getWxUserTagsDict(String appId) { + WxMpUserTagService wxMpUserTagService = wxService.getUserTagService(); + try { + List listWxUserTag = wxMpUserTagService.tagGet(); + List listWxUserTagsDict = new ArrayList<>(); + WxUserTagsDict wxUserTagsDict; + for(WxUserTag wxUserTag : listWxUserTag){ + wxUserTagsDict = new WxUserTagsDict(); + wxUserTagsDict.setName(wxUserTag.getName()); + wxUserTagsDict.setValue(wxUserTag.getId()); + listWxUserTagsDict.add(wxUserTagsDict); + } + return AjaxResult.success(listWxUserTagsDict); + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("获取微信用户标签字典失败", e); + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 新增微信用户标签 + * @return + */ + @RequiresPermissions("wxmp:wxusertags:add") + @PostMapping + public AjaxResult save(@RequestBody JSONObject data){ + String appId = data.getStr("appId"); + String name = data.getStr("name"); + WxMpUserTagService wxMpUserTagService = wxService.getUserTagService(); + try { + return AjaxResult.success(wxMpUserTagService.tagCreate(name)); + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("新增微信用户标签失败", e); + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 修改微信用户标签 + * @return + */ + @RequiresPermissions("wxmp:wxusertags:edit") + @PutMapping + public AjaxResult updateById(@RequestBody JSONObject data){ + String appId = data.getStr("appId"); + Long id = data.getLong("id"); + String name = data.getStr("name"); + WxMpUserTagService wxMpUserTagService = wxService.getUserTagService(); + try { + return AjaxResult.success(wxMpUserTagService.tagUpdate(id,name)); + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("修改微信用户标签失败", e); + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 删除微信用户标签 + * @param id + * @param appId + * @return + */ + @RequiresPermissions("wxmp:wxusertags:del") + @DeleteMapping + public AjaxResult removeById(Long id,String appId){ + long count = wxUserService.count(Wrappers.lambdaQuery() + .and(wrapper -> wrapper + .eq(WxUser::getTagidList,"["+id+"]") + .or() + .like(WxUser::getTagidList,","+id+",") + .or() + .likeRight(WxUser::getTagidList,"["+id+",") + .or() + .likeLeft(WxUser::getTagidList,","+id+"]"))); + if(count>0){ + return AjaxResult.error("该标签下有用户存在,无法删除"); + } + WxMpUserTagService wxMpUserTagService = wxService.getUserTagService(); + try { + return AjaxResult.success(wxMpUserTagService.tagDelete(id)); + } catch (WxErrorException e) { + e.printStackTrace(); + log.error("删除微信用户标签失败", e); + return AjaxResult.error(e.getMessage()); + } + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/ImageManager.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/ImageManager.java new file mode 100644 index 0000000..2c24c70 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/ImageManager.java @@ -0,0 +1,42 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.entity; + +import lombok.Data; + +/** + * imageManager + * @author www.joolun.com + * @date 2019-03-23 21:26:35 + */ +@Data +public class ImageManager{ +private static final long serialVersionUID = 1L; + + private String url; + private String thumb; + private String tag; + private String name; + private Integer id; +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/LoginMaDTO.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/LoginMaDTO.java new file mode 100644 index 0000000..156c288 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/LoginMaDTO.java @@ -0,0 +1,8 @@ +package com.ruoyi.weixin.entity; + +import lombok.Data; + +@Data +public class LoginMaDTO { + private String jsCode; +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/Menu.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/Menu.java new file mode 100644 index 0000000..c2cd0af --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/Menu.java @@ -0,0 +1,63 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.entity; + +import cn.hutool.json.JSONUtil; +import lombok.Data; +import me.chanjar.weixin.common.bean.menu.WxMenuRule; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * 自定义菜单模型 + * + * @author www.joolun.com + */ +@Data +public class Menu implements Serializable { + private static final long serialVersionUID = -7083914585539687746L; + + private List button = new ArrayList<>(); + + private WxMenuRule matchrule; + + /** + * 反序列化 + */ + public static Menu fromJson(String json) { + return JSONUtil.parseObj(json).toBean(Menu.class); + } + + public String toJson() { + return JSONUtil.toJsonStr(this); + } + + @Override + public String toString() { + return this.toJson(); + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/MenuButton.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/MenuButton.java new file mode 100644 index 0000000..407a695 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/MenuButton.java @@ -0,0 +1,91 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.entity; + +import cn.hutool.json.JSONObject; +import lombok.Data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * 自定义菜单模型 + * + * @author www.joolun.com + */ +@Data +public class MenuButton implements Serializable { + + private String type; + + private String name; + + private String key; + + private String url; + + private String media_id; + + private String appid; + + private String pagepath; + + private List sub_button = new ArrayList(); + /** + * content内容 + */ + private JSONObject content; + + private String repContent; + /** + * 消息类型 + */ + private String repType; + /** + * 消息名 + */ + private String repName; + /** + * 视频和音乐的描述 + */ + private String repDesc; + /** + * 视频和音乐的描述 + */ + private String repUrl; + /** + * 高质量链接 + */ + private String repHqUrl; + /** + * 缩略图的媒体id + */ + private String repThumbMediaId; + /** + * 缩略图url + */ + private String repThumbUrl; + private String article_id; +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/ThirdSession.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/ThirdSession.java new file mode 100644 index 0000000..1c5675e --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/ThirdSession.java @@ -0,0 +1,48 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.entity; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class ThirdSession implements Serializable { + /** + * 微信用户ID + */ + private String wxUserId; + /** + * 配置项ID + */ + private String appId; + /** + * 微信sessionKey + */ + private String sessionKey; + /** + * 用户标识 + */ + private String openId; +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxAutoReply.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxAutoReply.java new file mode 100644 index 0000000..9d8408c --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxAutoReply.java @@ -0,0 +1,143 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.entity; + + +import cn.hutool.json.JSONObject; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.ruoyi.common.core.typehandler.JsonTypeHandler; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.ibatis.type.JdbcType; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + * 消息自动回复 + * + * @author www.joolun.com + * @date 2019-04-18 15:40:39 + */ +@Data +@TableName("wx_auto_reply") +@EqualsAndHashCode(callSuper = true) +public class WxAutoReply extends Model { +private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(type = IdType.ASSIGN_ID) + private String id; + /** + * 创建者 + */ + private String createId; + /** + * 创建时间 + */ + private LocalDateTime createTime; + /** + * 更新者 + */ + private String updateId; + /** + * 更新时间 + */ + private LocalDateTime updateTime; + /** + * 备注 + */ + private String remark; + /** + * 逻辑删除标记(0:显示;1:隐藏) + */ + private String delFlag; + /** + * 类型(1、关注时回复;2、消息回复;3、关键词回复) + */ + @NotNull(message = "类型不能为空") + private String type; + /** + * 关键词 + */ + private String reqKey; + /** + * 请求消息类型(text:文本;image:图片;voice:语音;video:视频;shortvideo:小视频;location:地理位置) + */ + private String reqType; + /** + * 回复消息类型(text:文本;image:图片;voice:语音;video:视频;music:音乐;news:图文) + */ + @NotNull(message = "回复消息类型不能为空") + private String repType; + /** + * 回复类型文本匹配类型(1、全匹配,2、半匹配) + */ + private String repMate; + /** + * 回复类型文本保存文字 + */ + private String repContent; + /** + * 回复的素材名、视频和音乐的标题 + */ + private String repName; + /** + * 回复类型imge、voice、news、video的mediaID或音乐缩略图的媒体id + */ + private String repMediaId; + /** + * 视频和音乐的描述 + */ + private String repDesc; + /** + * 链接 + */ + private String repUrl; + /** + * 高质量链接 + */ + private String repHqUrl; + /** + * 缩略图的媒体id + */ + private String repThumbMediaId; + /** + * 缩略图url + */ + private String repThumbUrl; + + /** + * 图文消息的内容 + */ + @TableField(typeHandler = JsonTypeHandler.class, jdbcType= JdbcType.VARCHAR) + private JSONObject content; + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxMenu.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxMenu.java new file mode 100644 index 0000000..9987386 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxMenu.java @@ -0,0 +1,142 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.entity; + +import cn.hutool.json.JSONObject; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.ruoyi.common.core.typehandler.JsonTypeHandler; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.ibatis.type.JdbcType; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +; + +/** + * 自定义菜单 + * + * @author www.joolun.com + * @date 2019-03-27 16:52:10 + */ +@Data +@TableName("wx_menu") +@EqualsAndHashCode(callSuper = true) +public class WxMenu extends Model { +private static final long serialVersionUID = 1L; + + /** + * 菜单ID(click、scancode_push、scancode_waitmsg、pic_sysphoto、pic_photo_or_album、pic_weixin、location_select:保存key) + */ + @TableId(type = IdType.ASSIGN_ID) + private String id; + /** + * 父菜单ID + */ + private String parentId; + /** + * 排序值 + */ + private Integer sort; + /** + * 创建时间 + */ + private LocalDateTime createTime; + /** + * 更新时间 + */ + private LocalDateTime updateTime; + /** + * 逻辑删除标记(0:显示;1:隐藏) + */ + private String delFlag; + /** + * 菜单类型click、view、miniprogram、scancode_push、scancode_waitmsg、pic_sysphoto、pic_photo_or_album、pic_weixin、location_select、media_id、view_limited等 + */ + @NotNull(message = "菜单类型不能为空") + private String type; + /** + * 菜单名 + */ + @NotNull(message = "菜单名不能为空") + private String name; + /** + * View:保存链接到url + */ + private String url; + /** + * Img、voice、News:保存mediaID + */ + private String repMediaId; + /** + * 回复消息类型(text:文本;image:图片;voice:语音;video:视频;music:音乐;news:图文) + */ + private String repType; + /** + * 素材名、视频和音乐的标题 + */ + private String repName; + /** + * Text:保存文字 + */ + private String repContent; + /** + * 小程序的appid + */ + private String maAppId; + /** + * 小程序的页面路径 + */ + private String maPagePath; + /** + * 视频和音乐的描述 + */ + private String repDesc; + /** + * 视频和音乐的描述 + */ + private String repUrl; + /** + * 高质量链接 + */ + private String repHqUrl; + /** + * 缩略图的媒体id + */ + private String repThumbMediaId; + /** + * 缩略图url + */ + private String repThumbUrl; + /** + * 图文消息的内容 + */ + @TableField(typeHandler = JsonTypeHandler.class, jdbcType= JdbcType.VARCHAR) + private JSONObject content; +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxMsg.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxMsg.java new file mode 100644 index 0000000..3faa899 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxMsg.java @@ -0,0 +1,166 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.entity; + +import cn.hutool.json.JSONObject; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.ruoyi.common.core.typehandler.JsonTypeHandler; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.ibatis.type.JdbcType; + +import java.time.LocalDateTime; + +/** + * 微信消息 + * + * @author www.joolun.com + * @date 2019-05-28 16:12:10 + */ +@Data +@TableName("wx_msg") +@EqualsAndHashCode(callSuper = true) +public class WxMsg extends Model { +private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(type = IdType.ASSIGN_ID) + private String id; + /** + * 创建者 + */ + private String createId; + /** + * 创建时间 + */ + private LocalDateTime createTime; + /** + * 更新者 + */ + private String updateId; + /** + * 更新时间 + */ + private LocalDateTime updateTime; + /** + * 备注 + */ + private String remark; + /** + * 逻辑删除标记(0:显示;1:隐藏) + */ + private String delFlag; + /** + * 公众号名称 + */ + private String appName; + /** + * 公众号logo + */ + private String appLogo; + /** + * 微信用户ID + */ + private String wxUserId; + /** + * 昵称 + */ + private String nickName; + /** + * 头像 + */ + private String headimgUrl; + /** + * 消息分类(1、用户发给公众号;2、公众号发给用户;) + */ + private String type; + /** + * 消息类型(text:文本;image:图片;voice:语音;video:视频;shortvideo:小视频;location:地理位置;music:音乐;news:图文;event:推送事件) + */ + private String repType; + /** + * 事件类型(subscribe:关注;unsubscribe:取关;CLICK、VIEW:菜单事件) + */ + private String repEvent; + /** + * 回复类型文本保存文字 + */ + private String repContent; + /** + * 回复类型imge、voice、news、video的mediaID或音乐缩略图的媒体id + */ + private String repMediaId; + /** + * 回复的素材名、视频和音乐的标题 + */ + private String repName; + /** + * 视频和音乐的描述 + */ + private String repDesc; + /** + * 链接 + */ + private String repUrl; + /** + * 高质量链接 + */ + private String repHqUrl; + /** + * 图文消息的内容 + */ + @TableField(typeHandler = JsonTypeHandler.class, jdbcType= JdbcType.VARCHAR) + private JSONObject content; + /** + * 缩略图的媒体id + */ + private String repThumbMediaId; + /** + * 缩略图url + */ + private String repThumbUrl; + /** + * 地理位置维度 + */ + private Double repLocationX; + /** + * 地理位置经度 + */ + private Double repLocationY; + /** + * 地图缩放大小 + */ + private Double repScale; + /** + * 已读标记(0:是;1:否) + */ + private String readFlag; + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxMsgVO.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxMsgVO.java new file mode 100644 index 0000000..c4b7583 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxMsgVO.java @@ -0,0 +1,48 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.entity; + +import lombok.Data; + +/** + * 微信消息 + * + * @author www.joolun.com + * @date 2019-05-28 16:12:10 + */ +@Data +public class WxMsgVO extends WxMsg { +private static final long serialVersionUID = 1L; + + /** + * 数量 + */ + private Integer countMsg; + + /** + * repType not in筛选 + */ + private String notInRepType; + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxOpenDataDTO.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxOpenDataDTO.java new file mode 100644 index 0000000..f7c08b5 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxOpenDataDTO.java @@ -0,0 +1,18 @@ +package com.ruoyi.weixin.entity; + +import lombok.Data; + +/** + * 微信开发数据 + */ +@Data +public class WxOpenDataDTO { + private String appId; + private String userId; + private String encryptedData; + private String errMsg; + private String iv; + private String rawData; + private String signature; + private String sessionKey; +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxUser.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxUser.java new file mode 100644 index 0000000..51534ac --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxUser.java @@ -0,0 +1,175 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.ruoyi.common.core.sensitive.Sensitive; +import com.ruoyi.common.core.sensitive.SensitiveTypeEnum; +import com.ruoyi.common.core.typehandler.ArrayLongTypeHandler; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.ibatis.type.JdbcType; + +import java.time.LocalDateTime; + +/** + * 微信用户 + * + * @author www.joolun.com + * @date 2019-03-25 15:39:39 + */ +@Data +@TableName("wx_user") +@EqualsAndHashCode(callSuper = true) +public class WxUser extends Model { +private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(type = IdType.ASSIGN_ID) + private String id; + /** + * 创建者 + */ + private String createId; + /** + * 创建时间 + */ + private LocalDateTime createTime; + /** + * 更新者 + */ + private String updateId; + /** + * 更新时间 + */ + private LocalDateTime updateTime; + /** + * 备注信息 + */ + private String remark; + /** + * 逻辑删除标记(0:显示;1:隐藏) + */ + private String delFlag; + /** + * 应用类型(1:小程序,2:公众号) + */ + private String appType; + /** + * 是否订阅(0:是;1:否;2:网页授权用户) + */ + private String subscribe; + /** + * 返回用户关注的渠道来源,ADD_SCENE_SEARCH 公众号搜索,ADD_SCENE_ACCOUNT_MIGRATION 公众号迁移,ADD_SCENE_PROFILE_CARD 名片分享,ADD_SCENE_QR_CODE 扫描二维码,ADD_SCENEPROFILE LINK 图文页内名称点击,ADD_SCENE_PROFILE_ITEM 图文页右上角菜单,ADD_SCENE_PAID 支付后关注,ADD_SCENE_OTHERS 其他 + */ + private String subscribeScene; + /** + * 关注时间 + */ + private LocalDateTime subscribeTime; + /** + * 关注次数 + */ + private Integer subscribeNum; + /** + * 取消关注时间 + */ + private LocalDateTime cancelSubscribeTime; + /** + * 用户标识 + */ + private String openId; + /** + * 昵称 + */ + private String nickName; + /** + * 性别(1:男,2:女,0:未知) + */ + private String sex; + /** + * 所在城市 + */ + private String city; + /** + * 所在国家 + */ + private String country; + /** + * 所在省份 + */ + private String province; + /** + * 手机号码 + */ + @Sensitive(type = SensitiveTypeEnum.MOBILE_PHONE) + private String phone; + /** + * 用户语言 + */ + private String language; + /** + * 头像 + */ + private String headimgUrl; + /** + * union_id + */ + private String unionId; + /** + * 用户组 + */ + private String groupId; + /** + * 标签列表 + */ + @TableField(typeHandler = ArrayLongTypeHandler.class, jdbcType= JdbcType.VARCHAR) + private Long[] tagidList; + /** + * 二维码扫码场景 + */ + private String qrSceneStr; + /** + * 地理位置纬度 + */ + private Double latitude; + /** + * 地理位置经度 + */ + private Double longitude; + /** + * 地理位置精度 + */ + private Double precision; + /** + * 会话密钥 + */ + private String sessionKey; +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxUserTagsDict.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxUserTagsDict.java new file mode 100644 index 0000000..0dac02e --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/entity/WxUserTagsDict.java @@ -0,0 +1,32 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.entity; + +import lombok.Data; + +@Data +public class WxUserTagsDict { + private String name; + private Long value; +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/AbstractHandler.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/AbstractHandler.java new file mode 100644 index 0000000..1c45e10 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/AbstractHandler.java @@ -0,0 +1,35 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.handler; + +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +public abstract class AbstractHandler implements WxMpMessageHandler { + protected Logger logger = LoggerFactory.getLogger(getClass()); +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/KfSessionHandler.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/KfSessionHandler.java new file mode 100644 index 0000000..f611264 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/KfSessionHandler.java @@ -0,0 +1,48 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.handler; + +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class KfSessionHandler extends AbstractHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + //TODO 对会话做处理 + return null; + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/LocationHandler.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/LocationHandler.java new file mode 100644 index 0000000..20ce731 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/LocationHandler.java @@ -0,0 +1,68 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.handler; + + +import com.ruoyi.weixin.builder.TextBuilder; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class LocationHandler extends AbstractHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + if (wxMessage.getMsgType().equals(XmlMsgType.LOCATION)) { + //TODO 接收处理用户发送的地理位置消息 + try { + String content = "感谢反馈,您的的地理位置已收到!"; + return new TextBuilder().build(content, wxMessage, null); + } catch (Exception e) { + this.logger.error("位置消息接收处理失败", e); + return null; + } + } + + //上报地理位置事件 + this.logger.info("上报地理位置,纬度 : {},经度 : {},精度 : {}", + wxMessage.getLatitude(), wxMessage.getLongitude(), String.valueOf(wxMessage.getPrecision())); + + //TODO 可以将用户地理位置信息保存到本地数据库,以便以后使用 + + return null; + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/LogHandler.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/LogHandler.java new file mode 100644 index 0000000..70d246e --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/LogHandler.java @@ -0,0 +1,62 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.handler; + +import cn.hutool.core.util.StrUtil; +import com.ruoyi.common.core.utils.http.HttpUtils; +import com.ruoyi.weixin.utils.JsonUtils; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class LogHandler extends AbstractHandler { + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + this.logger.info("\n接收到请求消息,内容:{}", JsonUtils.toJson(wxMessage)); + //以下为测试代码,自行删除不影响系统功能 + if (wxMessage.getMsgType().equals(WxConsts.XmlMsgType.EVENT)) { + if(wxMessage.getEvent().equals(WxConsts.EventType.SUBSCRIBE) || + wxMessage.getEvent().equals(WxConsts.EventType.SCAN)){ + if(wxMessage.getEventKey().contains("jl-wiki")){ + String openId = wxMessage.getFromUser(); + String sceneStr = StrUtil.split(wxMessage.getEventKey(), ":")[1]; + String rs = HttpUtils.sendPost("http://127.0.0.1:8083/joolun-open/user",StrUtil.format("openId={}&sceneStr={}", openId, sceneStr)); + } + } + } + return null; + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/MenuHandler.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/MenuHandler.java new file mode 100644 index 0000000..18ac03f --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/MenuHandler.java @@ -0,0 +1,194 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.handler; + +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ruoyi.weixin.config.CommonConstants; +import com.ruoyi.weixin.constant.ConfigConstant; +import com.ruoyi.weixin.entity.WxMenu; +import com.ruoyi.weixin.entity.WxMsg; +import com.ruoyi.weixin.entity.WxUser; +import com.ruoyi.weixin.mapper.WxMenuMapper; +import com.ruoyi.weixin.mapper.WxMsgMapper; +import com.ruoyi.weixin.mapper.WxUserMapper; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutNewsMessage; +import me.chanjar.weixin.mp.bean.result.WxMpUser; +import me.chanjar.weixin.mp.builder.outxml.*; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author www.joolun.com + */ +@Slf4j +@Component +@AllArgsConstructor +public class MenuHandler extends AbstractHandler { + + private final WxMenuMapper wxMenuMapper; + private final WxUserMapper wxUserMapper; + private final WxMsgMapper wxMsgMapper; + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService weixinService, + WxSessionManager sessionManager) throws WxErrorException { + //消息记录 + WxMenu wxMenu = null; + if(WxConsts.EventType.CLICK.equals(wxMessage.getEvent()) + || WxConsts.EventType.SCANCODE_WAITMSG.equals(wxMessage.getEvent())){ + wxMenu = wxMenuMapper.selectById(wxMessage.getEventKey()); + if(wxMenu == null){//菜单过期 + return new TextBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).content("非常抱歉,该菜单已删除!").build(); + } + }else{ + wxMenu = new WxMenu(); + } + WxUser wxUser = wxUserMapper.selectOne(Wrappers.lambdaQuery() + .eq(WxUser::getOpenId,wxMessage.getFromUser())); + if(wxUser==null){//库中无此用户 + WxMpUser userWxInfo = weixinService.getUserService() + .userInfo(wxMessage.getFromUser(), null); + wxUser = new WxUser(); + wxUser.setSubscribeNum(1); + SubscribeHandler.setWxUserValue(wxUser,userWxInfo); + wxUserMapper.insert(wxUser); + } + //组装菜单回复消息 + return getWxMpXmlOutMessage(wxMessage, wxMenu, wxUser); + } + + /** + * 组装菜单回复消息 + * @param wxMessage + * @param wxMenu + * @return + */ + public WxMpXmlOutMessage getWxMpXmlOutMessage(WxMpXmlMessage wxMessage, WxMenu wxMenu, WxUser wxUser){ + WxMpXmlOutMessage wxMpXmlOutMessage = null; + //记录接收消息 + WxMsg wxMsg = new WxMsg(); +// wxMsg.setTenantId(wxApp.getTenantId()); + wxMsg.setWxUserId(wxUser.getId()); + wxMsg.setNickName(wxUser.getNickName()); + wxMsg.setHeadimgUrl(wxUser.getHeadimgUrl()); + wxMsg.setType(ConfigConstant.WX_MSG_TYPE_1); + wxMsg.setRepEvent(wxMessage.getEvent()); + wxMsg.setRepType(wxMessage.getMsgType()); + wxMsg.setRepName(wxMenu.getName()); + if(WxConsts.EventType.VIEW.equals(wxMessage.getEvent())){ + wxMsg.setRepUrl(wxMessage.getEventKey()); + } + if(WxConsts.EventType.SCANCODE_WAITMSG.equals(wxMessage.getEvent())){ + wxMsg.setRepContent(wxMessage.getScanCodeInfo().getScanResult()); + } + wxMsg.setReadFlag(CommonConstants.NO); + LocalDateTime now = LocalDateTime.now(); + wxMsg.setCreateTime(now); + wxMsgMapper.insert(wxMsg); + if(WxConsts.MenuButtonType.CLICK.equals(wxMenu.getType()) + || WxConsts.MenuButtonType.SCANCODE_WAITMSG.equals(wxMenu.getType())){ + //记录回复消息 + wxMsg = new WxMsg(); + wxMsg.setWxUserId(wxUser.getId()); + wxMsg.setNickName(wxUser.getNickName()); + wxMsg.setHeadimgUrl(wxUser.getHeadimgUrl()); + wxMsg.setCreateTime(now.plusSeconds(1)); + wxMsg.setType(ConfigConstant.WX_MSG_TYPE_2); + wxMsg.setRepType(wxMenu.getRepType()); + if(WxConsts.KefuMsgType.TEXT.equals(wxMenu.getRepType())){ + wxMsg.setRepContent(wxMenu.getRepContent()); + wxMpXmlOutMessage = new TextBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).content(wxMenu.getRepContent()).build(); + } + if(WxConsts.KefuMsgType.IMAGE.equals(wxMenu.getRepType())){ + wxMsg.setRepName(wxMenu.getRepName()); + wxMsg.setRepUrl(wxMenu.getRepUrl()); + wxMsg.setRepMediaId(wxMenu.getRepMediaId()); + wxMpXmlOutMessage = new ImageBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).mediaId(wxMenu.getRepMediaId()).build(); + } + if(WxConsts.KefuMsgType.VOICE.equals(wxMenu.getRepType())){ + wxMsg.setRepName(wxMenu.getRepName()); + wxMsg.setRepUrl(wxMenu.getRepUrl()); + wxMsg.setRepMediaId(wxMenu.getRepMediaId()); + wxMpXmlOutMessage = new VoiceBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).mediaId(wxMenu.getRepMediaId()).build(); + } + if(WxConsts.KefuMsgType.VIDEO.equals(wxMenu.getRepType())){ + wxMsg.setRepName(wxMenu.getRepName()); + wxMsg.setRepDesc(wxMenu.getRepDesc()); + wxMsg.setRepUrl(wxMenu.getRepUrl()); + wxMsg.setRepMediaId(wxMenu.getRepMediaId()); + wxMpXmlOutMessage = new VideoBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).mediaId(wxMenu.getRepMediaId()) + .title(wxMenu.getRepName()).description(wxMenu.getRepDesc()).build(); + } + if(WxConsts.KefuMsgType.MUSIC.equals(wxMenu.getRepType())){ + wxMsg.setRepName(wxMenu.getRepName()); + wxMsg.setRepDesc(wxMenu.getRepDesc()); + wxMsg.setRepUrl(wxMenu.getRepUrl()); + wxMsg.setRepHqUrl(wxMenu.getRepHqUrl()); + wxMsg.setRepThumbMediaId(wxMenu.getRepThumbMediaId()); + wxMsg.setRepThumbUrl(wxMenu.getRepThumbUrl()); + wxMpXmlOutMessage = new MusicBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) + .thumbMediaId(wxMenu.getRepThumbMediaId()) + .title(wxMenu.getRepName()).description(wxMenu.getRepDesc()) + .musicUrl(wxMenu.getRepUrl()).hqMusicUrl(wxMenu.getRepHqUrl()).build(); + } + if(WxConsts.KefuMsgType.NEWS.equals(wxMenu.getRepType())){ + List list = new ArrayList<>(); + List listJSONObject = JSONUtil.toList(wxMenu.getContent().getJSONArray("articles"),JSONObject.class); + WxMpXmlOutNewsMessage.Item t; + for(JSONObject jSONObject : listJSONObject){ + t = new WxMpXmlOutNewsMessage.Item(); + t.setTitle(jSONObject.getStr("title")); + t.setDescription(jSONObject.getStr("digest")); + t.setPicUrl(jSONObject.getStr("thumbUrl")); + t.setUrl(jSONObject.getStr("url")); + list.add(t); + } + wxMsg.setRepName(wxMenu.getRepName()); + wxMsg.setRepDesc(wxMenu.getRepDesc()); + wxMsg.setRepUrl(wxMenu.getRepUrl()); + wxMsg.setRepMediaId(wxMenu.getRepMediaId()); + wxMsg.setContent(wxMenu.getContent()); + wxMpXmlOutMessage = new NewsBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).articles(list).build(); + } + wxMsgMapper.insert(wxMsg); + } + return wxMpXmlOutMessage; + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/MsgHandler.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/MsgHandler.java new file mode 100644 index 0000000..02ee80a --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/MsgHandler.java @@ -0,0 +1,234 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.handler; + +import cn.hutool.json.JSONObject; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ruoyi.weixin.config.CommonConstants; +import com.ruoyi.weixin.constant.ConfigConstant; +import com.ruoyi.weixin.constant.WebSocketConstant; +import com.ruoyi.weixin.entity.WxAutoReply; +import com.ruoyi.weixin.entity.WxMsg; +import com.ruoyi.weixin.entity.WxUser; +import com.ruoyi.weixin.mapper.WxUserMapper; +import com.ruoyi.weixin.service.WxAutoReplyService; +import com.ruoyi.weixin.service.WxMsgService; +import lombok.AllArgsConstructor; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutNewsMessage; +import me.chanjar.weixin.mp.builder.outxml.*; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; + +/** + * @author www.joolun.com + */ +@Component +@AllArgsConstructor +public class MsgHandler extends AbstractHandler { + + private final WxAutoReplyService wxAutoReplyService; + private final WxUserMapper wxUserMapper; + private final WxMsgService wxMsgService; + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + //组装回复消息 + if (!wxMessage.getMsgType().equals(XmlMsgType.EVENT)) { + WxMpXmlOutMessage rs; + //TODO 可以选择将消息保存到本地 + WxUser wxUser = wxUserMapper.selectOne(Wrappers.lambdaQuery() + .eq(WxUser::getOpenId,wxMessage.getFromUser())); + if(WxConsts.KefuMsgType.TEXT.equals(wxMessage.getMsgType())){//1、先处理是否有文本关键字回复 + //先全匹配 + List listWxAutoReply = wxAutoReplyService.list(Wrappers + .query().lambda() + .eq(WxAutoReply::getType, ConfigConstant.WX_AUTO_REPLY_TYPE_3) + .eq(WxAutoReply::getRepMate, ConfigConstant.WX_REP_MATE_1) + .eq(WxAutoReply::getReqKey, wxMessage.getContent())); + if(listWxAutoReply!=null && listWxAutoReply.size()>0){ + rs = this.getWxMpXmlOutMessage(wxMessage,listWxAutoReply,wxUser,wxMsgService); + if(rs != null){ + return rs; + } + } + //再半匹配 + listWxAutoReply = wxAutoReplyService.list(Wrappers + .query().lambda() + .eq(WxAutoReply::getType, ConfigConstant.WX_AUTO_REPLY_TYPE_3) + .eq(WxAutoReply::getRepMate, ConfigConstant.WX_REP_MATE_2) + .like(WxAutoReply::getReqKey, wxMessage.getContent())); + if(listWxAutoReply!=null && listWxAutoReply.size()>0) { + rs = this.getWxMpXmlOutMessage(wxMessage, listWxAutoReply, wxUser,wxMsgService); + if (rs != null) { + return rs; + } + } + } + //2、再处理消息回复 + List listWxAutoReply = wxAutoReplyService.list(Wrappers + .query().lambda() + .eq(WxAutoReply::getType, ConfigConstant.WX_AUTO_REPLY_TYPE_2) + .eq(WxAutoReply::getReqType, wxMessage.getMsgType())); + rs = this.getWxMpXmlOutMessage(wxMessage,listWxAutoReply,wxUser,wxMsgService); + return rs; + } + return null; + + } + + /** + * 组装回复消息,并记录消息 + * @param wxMessage + * @param listWxAutoReply + * @return + */ + public static WxMpXmlOutMessage getWxMpXmlOutMessage(WxMpXmlMessage wxMessage, List listWxAutoReply, WxUser wxUser, + WxMsgService wxMsgService){ + WxMpXmlOutMessage wxMpXmlOutMessage = null; + //记录接收消息 + WxMsg wxMsg = new WxMsg(); + wxMsg.setWxUserId(wxUser.getId()); + wxMsg.setNickName(wxUser.getNickName()); + wxMsg.setHeadimgUrl(wxUser.getHeadimgUrl()); + wxMsg.setType(ConfigConstant.WX_MSG_TYPE_1); + wxMsg.setRepEvent(wxMessage.getEvent()); + wxMsg.setRepType(wxMessage.getMsgType()); + wxMsg.setRepMediaId(wxMessage.getMediaId()); + if(WxConsts.XmlMsgType.TEXT.equals(wxMessage.getMsgType())){ + wxMsg.setRepContent(wxMessage.getContent()); + } + if(WxConsts.XmlMsgType.VOICE.equals(wxMessage.getMsgType())){ + wxMsg.setRepName(wxMessage.getMediaId() + "." + wxMessage.getFormat()); + wxMsg.setRepContent(wxMessage.getRecognition()); + } + if(WxConsts.XmlMsgType.IMAGE.equals(wxMessage.getMsgType())){ + wxMsg.setRepUrl(wxMessage.getPicUrl()); + } + if(WxConsts.XmlMsgType.LINK.equals(wxMessage.getMsgType())){ + wxMsg.setRepName(wxMessage.getTitle()); + wxMsg.setRepDesc(wxMessage.getDescription()); + wxMsg.setRepUrl(wxMessage.getUrl()); + } + if(WxConsts.MediaFileType.FILE.equals(wxMessage.getMsgType())){ + wxMsg.setRepName(wxMessage.getTitle()); + wxMsg.setRepDesc(wxMessage.getDescription()); + } + if(WxConsts.XmlMsgType.VIDEO.equals(wxMessage.getMsgType())){ + wxMsg.setRepThumbMediaId(wxMessage.getThumbMediaId()); + } + if(WxConsts.XmlMsgType.LOCATION.equals(wxMessage.getMsgType())){ + wxMsg.setRepLocationX(wxMessage.getLocationX()); + wxMsg.setRepLocationY(wxMessage.getLocationY()); + wxMsg.setRepScale(wxMessage.getScale()); + wxMsg.setRepContent(wxMessage.getLabel()); + } + wxMsg.setReadFlag(CommonConstants.NO); + LocalDateTime now = LocalDateTime.now(); + wxMsg.setCreateTime(now); + wxMsgService.save(wxMsg); + //推送websocket + String destination = WebSocketConstant.USER_DESTINATION_PREFIX + WebSocketConstant.WX_MSG + wxMsg.getWxUserId(); + if(listWxAutoReply!=null && listWxAutoReply.size()>0){ + WxAutoReply wxAutoReply = listWxAutoReply.get(0); + //记录回复消息 + wxMsg = new WxMsg(); + wxMsg.setWxUserId(wxUser.getId()); + wxMsg.setNickName(wxUser.getNickName()); + wxMsg.setHeadimgUrl(wxUser.getHeadimgUrl()); + wxMsg.setCreateTime(now.plusSeconds(1)); + wxMsg.setType(ConfigConstant.WX_MSG_TYPE_2); + wxMsg.setRepType(wxAutoReply.getRepType()); + + if(WxConsts.KefuMsgType.TEXT.equals(wxAutoReply.getRepType())){//文本 + wxMsg.setRepContent(wxAutoReply.getRepContent()); + wxMpXmlOutMessage = new TextBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).content(wxAutoReply.getRepContent()).build(); + } + if(WxConsts.KefuMsgType.IMAGE.equals(wxAutoReply.getRepType())){//图片 + wxMsg.setRepName(wxAutoReply.getRepName()); + wxMsg.setRepUrl(wxAutoReply.getRepUrl()); + wxMsg.setRepMediaId(wxAutoReply.getRepMediaId()); + wxMpXmlOutMessage = new ImageBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).mediaId(wxAutoReply.getRepMediaId()).build(); + } + if(WxConsts.KefuMsgType.VOICE.equals(wxAutoReply.getRepType())){ + wxMsg.setRepName(wxAutoReply.getRepName()); + wxMsg.setRepUrl(wxAutoReply.getRepUrl()); + wxMsg.setRepMediaId(wxAutoReply.getRepMediaId()); + wxMpXmlOutMessage = new VoiceBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).mediaId(wxAutoReply.getRepMediaId()).build(); + } + if(WxConsts.KefuMsgType.VIDEO.equals(wxAutoReply.getRepType())){ + wxMsg.setRepName(wxAutoReply.getRepName()); + wxMsg.setRepDesc(wxAutoReply.getRepDesc()); + wxMsg.setRepUrl(wxAutoReply.getRepUrl()); + wxMsg.setRepMediaId(wxAutoReply.getRepMediaId()); + wxMpXmlOutMessage = new VideoBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).mediaId(wxAutoReply.getRepMediaId()) + .title(wxAutoReply.getRepName()).description(wxAutoReply.getRepDesc()).build(); + } + if(WxConsts.KefuMsgType.MUSIC.equals(wxAutoReply.getRepType())){ + wxMsg.setRepName(wxAutoReply.getRepName()); + wxMsg.setRepDesc(wxAutoReply.getRepDesc()); + wxMsg.setRepUrl(wxAutoReply.getRepUrl()); + wxMsg.setRepHqUrl(wxAutoReply.getRepHqUrl()); + wxMsg.setRepThumbMediaId(wxAutoReply.getRepThumbMediaId()); + wxMsg.setRepThumbUrl(wxAutoReply.getRepThumbUrl()); + wxMpXmlOutMessage = new MusicBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) + .thumbMediaId(wxAutoReply.getRepThumbMediaId()) + .title(wxAutoReply.getRepName()).description(wxAutoReply.getRepDesc()) + .musicUrl(wxAutoReply.getRepUrl()).hqMusicUrl(wxAutoReply.getRepHqUrl()).build(); + } + if(WxConsts.KefuMsgType.NEWS.equals(wxAutoReply.getRepType())){ + List list = new ArrayList<>(); + List listJSONObject = wxAutoReply.getContent().getJSONArray("articles").toList(JSONObject.class); + WxMpXmlOutNewsMessage.Item t; + for(JSONObject jSONObject : listJSONObject){ + t = new WxMpXmlOutNewsMessage.Item(); + t.setTitle(jSONObject.getStr("title")); + t.setDescription(jSONObject.getStr("digest")); + t.setPicUrl(jSONObject.getStr("thumbUrl")); + t.setUrl(jSONObject.getStr("url")); + list.add(t); + } + wxMsg.setRepName(wxAutoReply.getRepName()); + wxMsg.setRepDesc(wxAutoReply.getRepDesc()); + wxMsg.setRepUrl(wxAutoReply.getRepUrl()); + wxMsg.setRepMediaId(wxAutoReply.getRepMediaId()); + wxMsg.setContent(wxAutoReply.getContent()); + wxMpXmlOutMessage = new NewsBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).articles(list).build(); + } + wxMsgService.save(wxMsg); + } + return wxMpXmlOutMessage; + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/NullHandler.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/NullHandler.java new file mode 100644 index 0000000..fb6bc6a --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/NullHandler.java @@ -0,0 +1,47 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.handler; + +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class NullHandler extends AbstractHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + return null; + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/ScanHandler.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/ScanHandler.java new file mode 100644 index 0000000..9129cab --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/ScanHandler.java @@ -0,0 +1,47 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.handler; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class ScanHandler extends AbstractHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMpXmlMessage, Map map, + WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException { + // 扫码事件处理 + return null; + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/StoreCheckNotifyHandler.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/StoreCheckNotifyHandler.java new file mode 100644 index 0000000..da51f25 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/StoreCheckNotifyHandler.java @@ -0,0 +1,50 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.handler; + +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * 门店审核事件处理 + * + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class StoreCheckNotifyHandler extends AbstractHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + // TODO 处理门店审核事件 + return null; + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/SubscribeHandler.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/SubscribeHandler.java new file mode 100644 index 0000000..25fe4cd --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/SubscribeHandler.java @@ -0,0 +1,110 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.handler; + +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ruoyi.weixin.constant.ConfigConstant; +import com.ruoyi.weixin.entity.WxAutoReply; +import com.ruoyi.weixin.entity.WxUser; +import com.ruoyi.weixin.mapper.WxUserMapper; +import com.ruoyi.weixin.service.WxAutoReplyService; +import com.ruoyi.weixin.service.WxMsgService; +import com.ruoyi.weixin.utils.LocalDateTimeUtils; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import me.chanjar.weixin.mp.bean.result.WxMpUser; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +/** + * @author www.joolun.com + */ +@Slf4j +@Component +@AllArgsConstructor +public class SubscribeHandler extends AbstractHandler { + private final WxAutoReplyService wxAutoReplyService; + private final WxUserMapper wxUserMapper; + private final WxMsgService wxMsgService; + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService weixinService, + WxSessionManager sessionManager) { + log.info("新关注用户 OPENID: " + wxMessage.getFromUser()); + // 获取微信用户基本信息 + try { + WxMpUser userWxInfo = weixinService.getUserService() + .userInfo(wxMessage.getFromUser(), null); + if (userWxInfo != null) { + // TODO 添加关注用户到本地数据库 + WxUser wxUser = wxUserMapper.selectOne(Wrappers.lambdaQuery() + .eq(WxUser::getOpenId,userWxInfo.getOpenId())); + if(wxUser==null){//第一次关注 + wxUser = new WxUser(); + wxUser.setSubscribeNum(1); + this.setWxUserValue(wxUser,userWxInfo); +// wxUser.setTenantId(wxApp.getTenantId()); + wxUserMapper.insert(wxUser); + }else{//曾经关注过 + wxUser.setSubscribeNum(wxUser.getSubscribeNum()+1); + this.setWxUserValue(wxUser,userWxInfo); +// wxUser.setTenantId(wxApp.getTenantId()); + wxUserMapper.updateById(wxUser); + } + //发送关注消息 + List listWxAutoReply = wxAutoReplyService.list(Wrappers.query() + .lambda().eq(WxAutoReply::getType, ConfigConstant.WX_AUTO_REPLY_TYPE_1)); + WxMpXmlOutMessage wxMpXmlOutMessage = MsgHandler.getWxMpXmlOutMessage(wxMessage,listWxAutoReply,wxUser,wxMsgService); + return wxMpXmlOutMessage; + } + } catch (Exception e) { + log.error("用户关注出错:"+e.getMessage()); + } + return null; + } + + public static void setWxUserValue(WxUser wxUser,WxMpUser userWxInfo){ + wxUser.setAppType(ConfigConstant.WX_APP_TYPE_2);; + wxUser.setSubscribe(ConfigConstant.SUBSCRIBE_TYPE_YES); + wxUser.setSubscribeScene(userWxInfo.getSubscribeScene()); + if(null != userWxInfo.getSubscribeTime()){ + wxUser.setSubscribeTime(LocalDateTimeUtils.timestamToDatetime(userWxInfo.getSubscribeTime()*1000)); + } + wxUser.setOpenId(userWxInfo.getOpenId()); + wxUser.setLanguage(userWxInfo.getLanguage()); + wxUser.setRemark(userWxInfo.getRemark()); + wxUser.setUnionId(userWxInfo.getUnionId()); + wxUser.setGroupId(JSONUtil.toJsonStr(userWxInfo.getGroupId())); + wxUser.setTagidList(userWxInfo.getTagIds()); + wxUser.setQrSceneStr(userWxInfo.getQrSceneStr()); + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/UnsubscribeHandler.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/UnsubscribeHandler.java new file mode 100644 index 0000000..9fbfb4b --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/handler/UnsubscribeHandler.java @@ -0,0 +1,71 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.handler; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ruoyi.weixin.constant.ConfigConstant; +import com.ruoyi.weixin.entity.WxUser; +import com.ruoyi.weixin.mapper.WxUserMapper; +import com.ruoyi.weixin.service.WxMsgService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.Map; + +/** + * @author www.joolun.com + */ +@Slf4j +@Component +@AllArgsConstructor +public class UnsubscribeHandler extends AbstractHandler { + + private final WxMsgService wxMsgService; + private final WxUserMapper wxUserMapper; + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + String openId = wxMessage.getFromUser(); + log.info("取消关注用户 OPENID: " + openId); + WxUser wxUser = wxUserMapper.selectOne(Wrappers.lambdaQuery() + .eq(WxUser::getOpenId,openId)); + if(wxUser!=null){ + wxUser.setSubscribe(ConfigConstant.SUBSCRIBE_TYPE_NO); + wxUser.setCancelSubscribeTime(LocalDateTime.now()); + wxUserMapper.updateById(wxUser); + //消息记录 + MsgHandler.getWxMpXmlOutMessage(wxMessage,null,wxUser,wxMsgService); + } + return null; + } + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/interceptor/ThirdSessionInterceptor.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/interceptor/ThirdSessionInterceptor.java new file mode 100644 index 0000000..8580c22 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/interceptor/ThirdSessionInterceptor.java @@ -0,0 +1,70 @@ +package com.ruoyi.weixin.interceptor; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.weixin.config.CommonConstants; +import com.ruoyi.weixin.constant.ConfigConstant; +import com.ruoyi.weixin.constant.MyReturnCode; +import com.ruoyi.weixin.constant.WxMaConstants; +import com.ruoyi.weixin.entity.ThirdSession; +import com.ruoyi.weixin.utils.ThirdSessionHolder; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.AsyncHandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * ThirdSession拦截器,校验每个请求的ThirdSession + * @author + */ +@Slf4j +@Component +@AllArgsConstructor +public class ThirdSessionInterceptor implements AsyncHandlerInterceptor { + + private final RedisTemplate redisTemplate; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + //获取header中的thirdSession + String thirdSessionHeader = request.getHeader(ConfigConstant.HEADER_THIRDSESSION); + if(StrUtil.isNotBlank(thirdSessionHeader)){ + //获取缓存中的ThirdSession + String key = WxMaConstants.THIRD_SESSION_BEGIN + ":" + thirdSessionHeader; + Object thirdSessionObj = redisTemplate.opsForValue().get(key); + if(thirdSessionObj == null) {//session过期 + AjaxResult r = AjaxResult.error(MyReturnCode.ERR_60001.getCode(), MyReturnCode.ERR_60001.getMsg()); + this.writerPrint(response, r); + return Boolean.FALSE; + }else { + String thirdSessionStr = String.valueOf(thirdSessionObj); + ThirdSession thirdSession = JSONUtil.toBean(thirdSessionStr, ThirdSession.class); + ThirdSessionHolder.setThirdSession(thirdSession);//设置thirdSession + } + }else{ + AjaxResult r = AjaxResult.error(MyReturnCode.ERR_60002.getCode(), MyReturnCode.ERR_60002.getMsg()); + this.writerPrint(response, r); + return Boolean.FALSE; + } + return Boolean.TRUE; + } + + private void writerPrint(HttpServletResponse response, AjaxResult r) throws IOException { + //返回超时错误码,触发小程序重新登录 + response.setCharacterEncoding(CommonConstants.UTF8); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + PrintWriter writer = response.getWriter(); + writer.print(JSONUtil.parseObj(r)); + if(writer != null){ + writer.close(); + } + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/mapper/WxAutoReplyMapper.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/mapper/WxAutoReplyMapper.java new file mode 100644 index 0000000..9dee4c8 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/mapper/WxAutoReplyMapper.java @@ -0,0 +1,37 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.weixin.entity.WxAutoReply; + +/** + * 消息自动回复 + * + * @author www.joolun.com + * @date 2019-04-18 15:40:39 + */ +public interface WxAutoReplyMapper extends BaseMapper { + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/mapper/WxMenuMapper.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/mapper/WxMenuMapper.java new file mode 100644 index 0000000..470127c --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/mapper/WxMenuMapper.java @@ -0,0 +1,37 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.weixin.entity.WxMenu; + +/** + * 自定义菜单 + * + * @author www.joolun.com + * @date 2019-03-27 16:52:10 + */ +public interface WxMenuMapper extends BaseMapper { + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/mapper/WxMsgMapper.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/mapper/WxMsgMapper.java new file mode 100644 index 0000000..c6ed159 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/mapper/WxMsgMapper.java @@ -0,0 +1,50 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.weixin.entity.WxMsg; +import com.ruoyi.weixin.entity.WxMsgVO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 微信消息 + * + * @author www.joolun.com + * @date 2019-05-28 16:12:10 + */ +public interface WxMsgMapper extends BaseMapper { + + /** + * 获取分组后的消息列表 + * @param page + * @param wxMsgVO + * @return + */ + IPage> listWxMsgMapGroup(Page page, @Param("query") WxMsgVO wxMsgVO); +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/mapper/WxUserMapper.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/mapper/WxUserMapper.java new file mode 100644 index 0000000..b13a481 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/mapper/WxUserMapper.java @@ -0,0 +1,37 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.weixin.entity.WxUser; + +/** + * 微信用户 + * + * @author www.joolun.com + * @date 2019-03-25 15:39:39 + */ +public interface WxUserMapper extends BaseMapper { + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/WxAutoReplyService.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/WxAutoReplyService.java new file mode 100644 index 0000000..98ae7b4 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/WxAutoReplyService.java @@ -0,0 +1,37 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.weixin.entity.WxAutoReply; + +/** + * 消息自动回复 + * + * @author www.joolun.com + * @date 2019-04-18 15:40:39 + */ +public interface WxAutoReplyService extends IService { + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/WxMenuService.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/WxMenuService.java new file mode 100644 index 0000000..72f107b --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/WxMenuService.java @@ -0,0 +1,52 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.weixin.entity.WxMenu; +import me.chanjar.weixin.common.error.WxErrorException; + +import java.io.Serializable; + +/** + * 自定义菜单 + * + * @author www.joolun.com + * @date 2019-03-27 16:52:10 + */ +public interface WxMenuService extends IService { + + /*** + * 获取WxApp下的菜单 + * @return + */ + String getWxMenuButton(); + + /** + * 保存并发布菜单 + * @param + */ + void saveAndRelease( String strWxMenu) throws WxErrorException; + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/WxMsgService.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/WxMsgService.java new file mode 100644 index 0000000..766577f --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/WxMsgService.java @@ -0,0 +1,49 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.weixin.entity.WxMsg; +import com.ruoyi.weixin.entity.WxMsgVO; + +import java.util.List; + +/** + * 微信消息 + * + * @author www.joolun.com + * @date 2019-05-28 16:12:10 + */ +public interface WxMsgService extends IService { + + /** + * 获取分组后的消息列表 + * @param page + * @param wxMsgVO + * @return + */ + IPage> listWxMsgMapGroup(Page page, WxMsgVO wxMsgVO); +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/WxUserService.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/WxUserService.java new file mode 100644 index 0000000..84dc5d2 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/WxUserService.java @@ -0,0 +1,81 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.weixin.entity.WxOpenDataDTO; +import com.ruoyi.weixin.entity.WxUser; +import me.chanjar.weixin.common.error.WxErrorException; + +/** + * 微信用户 + * + * @author www.joolun.com + * @date 2019-03-25 15:39:39 + */ +public interface WxUserService extends IService { + + /** + * 同步微信用户 + */ + void synchroWxUser() throws WxErrorException; + + /** + * 修改用户备注 + * @param entity + * @return + */ + boolean updateRemark(WxUser entity) throws WxErrorException; + + /** + * 认识标签 + * @param taggingType + * @param tagId + * @param openIds + * @throws WxErrorException + */ + void tagging(String taggingType, Long tagId, String[] openIds) throws WxErrorException; + + /** + * 根据openId获取用户 + * @param openId + * @return + */ + WxUser getByOpenId(String openId); + + /** + * 小程序登录 + * @param appId + * @param jsCode + * @return + */ + WxUser loginMa(String appId, String jsCode) throws WxErrorException; + + /** + * 新增、更新微信用户 + * @param wxOpenDataDTO + * @return + */ + WxUser saveOrUptateWxUser(WxOpenDataDTO wxOpenDataDTO); +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/impl/WxAutoReplyServiceImpl.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/impl/WxAutoReplyServiceImpl.java new file mode 100644 index 0000000..d990d20 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/impl/WxAutoReplyServiceImpl.java @@ -0,0 +1,41 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.weixin.entity.WxAutoReply; +import com.ruoyi.weixin.mapper.WxAutoReplyMapper; +import com.ruoyi.weixin.service.WxAutoReplyService; +import org.springframework.stereotype.Service; + +/** + * 消息自动回复 + * + * @author www.joolun.com + * @date 2019-04-18 15:40:39 + */ +@Service +public class WxAutoReplyServiceImpl extends ServiceImpl implements WxAutoReplyService { + +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/impl/WxMenuServiceImpl.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/impl/WxMenuServiceImpl.java new file mode 100644 index 0000000..8c8d2cc --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/impl/WxMenuServiceImpl.java @@ -0,0 +1,183 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.service.impl; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.weixin.config.CommonConstants; +import com.ruoyi.weixin.entity.Menu; +import com.ruoyi.weixin.entity.MenuButton; +import com.ruoyi.weixin.entity.WxMenu; +import com.ruoyi.weixin.mapper.WxMenuMapper; +import com.ruoyi.weixin.service.WxMenuService; +import lombok.AllArgsConstructor; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +/** + * 自定义菜单 + * + * @author www.joolun.com + * @date 2019-03-27 16:52:10 + */ +@Service +@AllArgsConstructor +public class WxMenuServiceImpl extends ServiceImpl implements WxMenuService { + private final WxMpService wxService; + /*** + * 获取WxApp下的菜单树结构 + * @return + */ + @Override + public String getWxMenuButton() { + //查出一级菜单 + List listWxMenu = baseMapper.selectList(Wrappers + .query().lambda() + .eq(WxMenu::getParentId, CommonConstants.PARENT_ID).orderByAsc(WxMenu::getSort)); + Menu menu = new Menu(); + List listMenuButton = new ArrayList<>(); + MenuButton menuButton; + List subButtons; + MenuButton subButton; + if(listWxMenu!=null&&listWxMenu.size()>0){ + for(WxMenu wxMenu : listWxMenu){ + menuButton = new MenuButton(); + menuButton.setName(wxMenu.getName()); + String type = wxMenu.getType(); + if(StringUtils.isNotBlank(type)){//无二级菜单 + menuButton.setType(type); + setButtonValue(menuButton,wxMenu); + }else{//有二级菜单 + //查出二级菜单 + List listWxMenu1 = baseMapper.selectList(Wrappers + .query().lambda() + .eq(WxMenu::getParentId,wxMenu.getId()).orderByAsc(WxMenu::getSort)); + subButtons = new ArrayList<>(); + for(WxMenu wxMenu1 : listWxMenu1){ + subButton = new MenuButton(); + String type1 = wxMenu1.getType(); + subButton.setName(wxMenu1.getName()); + subButton.setType(type1); + setButtonValue(subButton,wxMenu1); + subButtons.add(subButton); + } + menuButton.setSub_button(subButtons); + } + listMenuButton.add(menuButton); + } + } + menu.setButton(listMenuButton); + return menu.toString(); + } + + void setButtonValue(MenuButton menuButton,WxMenu wxMenu){ + menuButton.setKey(wxMenu.getId()); + menuButton.setUrl(wxMenu.getUrl()); + menuButton.setContent(wxMenu.getContent()); + menuButton.setRepContent(wxMenu.getRepContent()); + menuButton.setMedia_id(wxMenu.getRepMediaId()); + menuButton.setRepType(wxMenu.getRepType()); + menuButton.setRepName(wxMenu.getRepName()); + menuButton.setAppid(wxMenu.getMaAppId()); + menuButton.setPagepath(wxMenu.getMaPagePath()); + menuButton.setUrl(wxMenu.getUrl()); + menuButton.setRepUrl(wxMenu.getRepUrl()); + menuButton.setRepHqUrl(wxMenu.getRepHqUrl()); + menuButton.setRepDesc(wxMenu.getRepDesc()); + menuButton.setRepThumbMediaId(wxMenu.getRepThumbMediaId()); + menuButton.setRepThumbUrl(wxMenu.getRepThumbUrl()); + } + /** + * 保存并发布菜单 + * @param + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void saveAndRelease(String strWxMenu) throws WxErrorException { + Menu menu = Menu.fromJson(strWxMenu); + List buttons = menu.getButton(); + //先删除 + baseMapper.delete(Wrappers + .query().lambda()); + WxMenu wxMenu = null; + WxMenu wxMenu1 = null; + int sort1 = 1; + int sort2 = 1; + //入库 + for(MenuButton menuButton : buttons){ + wxMenu = new WxMenu(); + setWxMenuValue(wxMenu,menuButton); + wxMenu.setSort(sort1); + wxMenu.setParentId(CommonConstants.PARENT_ID); + baseMapper.insert(wxMenu); + menuButton.setKey(wxMenu.getId()); + sort1++; + for(MenuButton menuButton1 : menuButton.getSub_button()){ + wxMenu1 = new WxMenu(); + setWxMenuValue(wxMenu1,menuButton1); + wxMenu1.setSort(sort2); + wxMenu1.setParentId(wxMenu.getId()); + baseMapper.insert(wxMenu1); + menuButton1.setKey(wxMenu1.getId()); + sort2++; + } + } + //创建菜单 + wxService.getMenuService().menuCreate(menu.toString()); + } + + void setWxMenuValue(WxMenu wxMenu,MenuButton menuButton){ + wxMenu.setId(menuButton.getKey()); + wxMenu.setType(menuButton.getType()); + wxMenu.setName(menuButton.getName()); + wxMenu.setUrl(menuButton.getUrl()); + wxMenu.setRepMediaId(menuButton.getMedia_id()); + wxMenu.setRepType(menuButton.getRepType()); + wxMenu.setRepName(menuButton.getRepName()); + wxMenu.setMaAppId(menuButton.getAppid()); + wxMenu.setMaPagePath(menuButton.getPagepath()); + wxMenu.setRepContent(menuButton.getRepContent()); + wxMenu.setContent(menuButton.getContent()); + wxMenu.setRepUrl(menuButton.getRepUrl()); + wxMenu.setRepHqUrl(menuButton.getRepHqUrl()); + wxMenu.setRepDesc(menuButton.getRepDesc()); + wxMenu.setRepThumbMediaId(menuButton.getRepThumbMediaId()); + wxMenu.setRepThumbUrl(menuButton.getRepThumbUrl()); + menuButton.setRepUrl(null); + menuButton.setRepDesc(null); + menuButton.setRepHqUrl(null); + menuButton.setContent(null); + menuButton.setRepContent(null); + menuButton.setRepType(null); + menuButton.setRepName(null); + menuButton.setRepThumbMediaId(null); + menuButton.setRepThumbUrl(null); + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/impl/WxMsgServiceImpl.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/impl/WxMsgServiceImpl.java new file mode 100644 index 0000000..bac6ab4 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/impl/WxMsgServiceImpl.java @@ -0,0 +1,50 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.service.impl; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.weixin.entity.WxMsg; +import com.ruoyi.weixin.entity.WxMsgVO; +import com.ruoyi.weixin.mapper.WxMsgMapper; +import com.ruoyi.weixin.service.WxMsgService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 微信消息 + * + * @author www.joolun.com + * @date 2019-05-28 16:12:10 + */ +@Service +public class WxMsgServiceImpl extends ServiceImpl implements WxMsgService { + + @Override + public IPage> listWxMsgMapGroup(Page page, WxMsgVO wxMsgVO) { + return baseMapper.listWxMsgMapGroup(page, wxMsgVO); + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/impl/WxUserServiceImpl.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/impl/WxUserServiceImpl.java new file mode 100644 index 0000000..7876758 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/service/impl/WxUserServiceImpl.java @@ -0,0 +1,264 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.service.impl; + +import cn.binarywang.wx.miniapp.api.WxMaUserService; +import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.common.collect.Lists; +import com.ruoyi.weixin.config.WxMaConfiguration; +import com.ruoyi.weixin.constant.ConfigConstant; +import com.ruoyi.weixin.constant.WxMaConstants; +import com.ruoyi.weixin.entity.ThirdSession; +import com.ruoyi.weixin.entity.WxOpenDataDTO; +import com.ruoyi.weixin.entity.WxUser; +import com.ruoyi.weixin.handler.SubscribeHandler; +import com.ruoyi.weixin.mapper.WxUserMapper; +import com.ruoyi.weixin.service.WxUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.WxMpUserService; +import me.chanjar.weixin.mp.api.WxMpUserTagService; +import me.chanjar.weixin.mp.bean.result.WxMpUser; +import me.chanjar.weixin.mp.bean.result.WxMpUserList; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +/** + * 微信用户 + * + * @author www.joolun.com + * @date 2019-03-25 15:39:39 + */ +@Slf4j +@Service +@AllArgsConstructor +public class WxUserServiceImpl extends ServiceImpl implements WxUserService { + + private final WxMpService wxService; + private final RedisTemplate redisTemplate; + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateRemark(WxUser entity) throws WxErrorException { + String id = entity.getId(); + String remark = entity.getRemark(); + String openId = entity.getOpenId(); + entity = new WxUser(); + entity.setId(id); + entity.setRemark(remark); + super.updateById(entity); + WxMpUserService wxMpUserService = wxService.getUserService(); + wxMpUserService.userUpdateRemark(openId,remark); + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void tagging(String taggingType,Long tagId,String[] openIds) throws WxErrorException { + WxMpUserTagService wxMpUserTagService = wxService.getUserTagService(); + WxUser wxUser; + if("tagging".equals(taggingType)){ + for(String openId : openIds){ + wxUser = baseMapper.selectOne(Wrappers.lambdaQuery() + .eq(WxUser::getOpenId,openId)); + Long[] tagidList = wxUser.getTagidList(); + List list = Arrays.asList(tagidList); + list = new ArrayList<>(list); + if(!list.contains(tagId)){ + list.add(tagId); + tagidList = list.toArray(new Long[list.size()]); + wxUser.setTagidList(tagidList); + this.updateById(wxUser); + } + } + wxMpUserTagService.batchTagging(tagId,openIds); + } + if("unTagging".equals(taggingType)){ + for(String openId : openIds){ + wxUser = baseMapper.selectOne(Wrappers.lambdaQuery() + .eq(WxUser::getOpenId,openId)); + Long[] tagidList = wxUser.getTagidList(); + List list = Arrays.asList(tagidList); + list = new ArrayList<>(list); + if(list.contains(tagId)){ + list.remove(tagId); + tagidList = list.toArray(new Long[list.size()]); + wxUser.setTagidList(tagidList); + this.updateById(wxUser); + } + } + wxMpUserTagService.batchUntagging(tagId,openIds); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void synchroWxUser() throws WxErrorException { + //先将已关注的用户取关 + WxUser wxUser = new WxUser(); + wxUser.setSubscribe(ConfigConstant.SUBSCRIBE_TYPE_NO); + this.baseMapper.update(wxUser, Wrappers.lambdaQuery() + .eq(WxUser::getSubscribe, ConfigConstant.SUBSCRIBE_TYPE_YES)); + WxMpUserService wxMpUserService = wxService.getUserService(); + this.recursionGet(wxMpUserService,null); + } + + /** + * 递归获取 + * @param nextOpenid + */ + void recursionGet(WxMpUserService wxMpUserService,String nextOpenid) throws WxErrorException { + WxMpUserList userList = wxMpUserService.userList(nextOpenid); + List listWxUser = new ArrayList<>(); + List listWxMpUser = getWxMpUserList(wxMpUserService,userList.getOpenids()); + listWxMpUser.forEach(wxMpUser -> { + WxUser wxUser = baseMapper.selectOne(Wrappers.lambdaQuery() + .eq(WxUser::getOpenId,wxMpUser.getOpenId())); + if(wxUser == null){//用户未存在 + wxUser = new WxUser(); + wxUser.setSubscribeNum(1); + } + SubscribeHandler.setWxUserValue(wxUser,wxMpUser); + listWxUser.add(wxUser); + }); + this.saveOrUpdateBatch(listWxUser); + if(userList.getCount() >= 10000){ + this.recursionGet(wxMpUserService,userList.getNextOpenid()); + } + } + + /** + * 分批次获取微信粉丝信息 每批100条 + * @param wxMpUserService + * @param openidsList + * @return + * @throws WxErrorException + * @author + */ + private List getWxMpUserList(WxMpUserService wxMpUserService, List openidsList) throws WxErrorException { + // 粉丝openid数量 + int count = openidsList.size(); + if (count <= 0) { + return new ArrayList<>(); + } + List list = Lists.newArrayList(); + List followersInfoList; + int a = count % 100 > 0 ? count / 100 + 1 : count / 100; + for (int i = 0; i < a; i++) { + if (i + 1 < a) { + log.debug("i:{},from:{},to:{}", i, i * 100, (i + 1) * 100); + followersInfoList = wxMpUserService.userInfoList(openidsList.subList(i * 100, ((i + 1) * 100))); + if (null != followersInfoList && !followersInfoList.isEmpty()) { + list.addAll(followersInfoList); + } + } + else { + log.debug("i:{},from:{},to:{}", i, i * 100, count - i * 100); + followersInfoList = wxMpUserService.userInfoList(openidsList.subList(i * 100, count)); + if (null != followersInfoList && !followersInfoList.isEmpty()) { + list.addAll(followersInfoList); + } + } + } + log.debug("本批次获取微信粉丝数:",list.size()); + return list; + } + + @Override + public WxUser getByOpenId(String openId){ + return this.baseMapper.selectOne(Wrappers.lambdaQuery() + .eq(WxUser::getOpenId,openId)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public WxUser loginMa(String appId, String jsCode) throws WxErrorException { + WxMaJscode2SessionResult jscode2session = WxMaConfiguration.getMaService(appId).jsCode2SessionInfo(jsCode); + WxUser wxUser = this.getByOpenId(jscode2session.getOpenid()); + if(wxUser==null) { + //新增微信用户 + wxUser = new WxUser(); + wxUser.setAppType(ConfigConstant.WX_APP_TYPE_1); + wxUser.setOpenId(jscode2session.getOpenid()); + wxUser.setSessionKey(jscode2session.getSessionKey()); + wxUser.setUnionId(jscode2session.getUnionid()); + try{ + this.save(wxUser); + }catch (DuplicateKeyException e){ + if(e.getMessage().contains("uk_appid_openid")){ + wxUser = this.getByOpenId(wxUser.getOpenId()); + } + } + }else { + //更新SessionKey + wxUser.setAppType(ConfigConstant.WX_APP_TYPE_1); + wxUser.setOpenId(jscode2session.getOpenid()); + wxUser.setSessionKey(jscode2session.getSessionKey()); + wxUser.setUnionId(jscode2session.getUnionid()); + this.updateById(wxUser); + } + + String thirdSessionKey = UUID.randomUUID().toString(); + ThirdSession thirdSession = new ThirdSession(); + thirdSession.setAppId(appId); + thirdSession.setSessionKey(wxUser.getSessionKey()); + thirdSession.setWxUserId(wxUser.getId()); + thirdSession.setOpenId(wxUser.getOpenId()); + //将3rd_session和用户信息存入redis,并设置过期时间 + String key = WxMaConstants.THIRD_SESSION_BEGIN + ":" + thirdSessionKey; + redisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(thirdSession) , WxMaConstants.TIME_OUT_SESSION, TimeUnit.HOURS); + wxUser.setSessionKey(thirdSessionKey); + return wxUser; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public WxUser saveOrUptateWxUser(WxOpenDataDTO wxOpenDataDTO) { + WxMaUserService wxMaUserService = WxMaConfiguration.getMaService(wxOpenDataDTO.getAppId()).getUserService(); + WxMaUserInfo wxMaUserInfo = wxMaUserService.getUserInfo(wxOpenDataDTO.getSessionKey(), wxOpenDataDTO.getEncryptedData(), wxOpenDataDTO.getIv()); + WxUser wxUser = new WxUser(); + BeanUtil.copyProperties(wxMaUserInfo,wxUser); + wxUser.setId(wxOpenDataDTO.getUserId()); + wxUser.setSex(wxMaUserInfo.getGender()); + wxUser.setHeadimgUrl(wxMaUserInfo.getAvatarUrl()); + baseMapper.updateById(wxUser); + wxUser = baseMapper.selectById(wxUser.getId()); + return wxUser; + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/CheckUtil.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/CheckUtil.java new file mode 100644 index 0000000..c5be331 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/CheckUtil.java @@ -0,0 +1,28 @@ +package com.ruoyi.weixin.utils; + +import java.util.Arrays; + +/** + * 业务模块 + * + * @author tianyongbao + * @date 2025/1/8 + */ +public class CheckUtil { + // 接口配置信息中的Token + private static final String token = "intc"; + public static boolean checkSignature(String signature, String timestamp, String nonce) { + String[] str = new String[]{token, timestamp, nonce}; + //排序 + Arrays.sort(str); + //拼接字符串 + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < str.length; i++) { + buffer.append(str[i]); + } + //进行sha1加密 + String temp = SHA1.encode(buffer.toString()); + //与微信提供的signature进行匹对 + return signature.equals(temp); + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/FileUtils.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/FileUtils.java new file mode 100644 index 0000000..2e5e2e6 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/FileUtils.java @@ -0,0 +1,85 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.utils; + +import cn.hutool.core.lang.UUID; +import org.springframework.web.multipart.MultipartFile; + +import java.io.*; + +/** + * file工具 + */ +public class FileUtils { + + /** + * 将MultipartFile转为File + * @param mulFile + * @return + */ + public static File multipartFileToFile(MultipartFile mulFile) throws IOException { + InputStream ins = mulFile.getInputStream(); + String fileName = mulFile.getOriginalFilename(); + String prefix = getFileNameNoEx(fileName)+ UUID.fastUUID(); + String suffix = "."+getExtensionName(fileName); + File toFile = File.createTempFile(prefix,suffix); + OutputStream os = new FileOutputStream(toFile); + int bytesRead = 0; + byte[] buffer = new byte[8192]; + while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) { + os.write(buffer, 0, bytesRead); + } + os.close(); + ins.close(); + return toFile; + } + + /** + * 获取文件扩展名 + * + */ + public static String getExtensionName(String filename) { + if ((filename != null) && (filename.length() > 0)) { + int dot = filename.lastIndexOf('.'); + if ((dot >-1) && (dot < (filename.length() - 1))) { + return filename.substring(dot + 1); + } + } + return filename; + } + + /** + * 获取不带扩展名的文件名 + * + */ + public static String getFileNameNoEx(String filename) { + if ((filename != null) && (filename.length() > 0)) { + int dot = filename.lastIndexOf('.'); + if ((dot >-1) && (dot < (filename.length()))) { + return filename.substring(0, dot); + } + } + return filename; + } +} \ No newline at end of file diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/JsonUtils.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/JsonUtils.java new file mode 100644 index 0000000..8ff1600 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/JsonUtils.java @@ -0,0 +1,39 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.utils; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +public class JsonUtils { + public static String toJson(Object obj) { + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .create(); + return gson.toJson(obj); + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/LocalDateTimeUtils.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/LocalDateTimeUtils.java new file mode 100644 index 0000000..f519828 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/LocalDateTimeUtils.java @@ -0,0 +1,115 @@ +/* +MIT License + +Copyright (c) 2020 www.joolun.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +package com.ruoyi.weixin.utils; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.ChronoField; + +/** + * LocalDateTime时间工具 + */ +public class LocalDateTimeUtils { + + public static final String YYYY = "yyyy"; + public static final String YYYYMM = "yyyyMM"; + public static final String YYYYMMDD = "yyyyMMdd"; + public static final String YYYYMMDDHH = "yyyyMMddHH"; + public static final String YYYYMMDDHHMM = "yyyyMMddHHmm"; + public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; + public static final String YYYY_MM = "yyyy-MM"; + public static final String YYYY_MM_DD = "yyyy-MM-dd"; + public static final String YYYY_MM_DD_HH = "yyyy-MM-dd HH"; + public static final String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm"; + public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; + + private static final String BASE_TIME_FORMAT = "[yyyyMMddHHmmss][yyyyMMddHHmm][yyyyMMddHH][yyyyMMdd][yyyyMM][yyyy][[-][/][.]MM][[-][/][.]dd][ ][HH][[:][.]mm][[:][.]ss][[:][.]SSS]"; + /** + * 【推荐】解析常用时间字符串,支持,并不局限于以下形式: + * [yyyy][yyyy-MM][yyyy-MM-dd][yyyy-MM-dd HH][yyyy-MM-dd HH:mm][yyyy-MM-dd HH:mm:ss][yyyy-MM-dd HH:mm:ss:SSS] + * [yyyy][yyyy/MM][yyyy/MM/dd][yyyy/MM/dd HH][yyyy/MM/dd HH:mm][yyyy/MM/dd HH:mm:ss][yyyy/MM/dd HH:mm:ss:SSS] + * [yyyy][yyyy.MM][yyyy.MM.dd][yyyy.MM.dd HH][yyyy.MM.dd HH.mm][yyyy.MM.dd HH.mm.ss][yyyy.MM.dd HH.mm.ss.SSS] + * [yyyy][yyyyMM][yyyyMMdd][yyyyMMddHH][yyyyMMddHHmm][yyyyMMddHHmmss] + * [MM-dd] + * 不支持yyyyMMddHHmmssSSS,因为本身DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")就不支持这个形式 + * + * @param timeString + * @return + */ + public static LocalDateTime parse(String timeString) { + return LocalDateTime.parse(timeString, getDateTimeFormatterByPattern(BASE_TIME_FORMAT)); + } + + /** + * 根据传进来的pattern返回LocalDateTime,自动补齐 + * + * @param timeString + * @param pattern + * @return + */ + public static LocalDateTime parseByPattern(String timeString, String pattern) { + return LocalDateTime.parse(timeString, getDateTimeFormatterByPattern(pattern)); + } + + private static DateTimeFormatter getDateTimeFormatterByPattern(String pattern) { + return new DateTimeFormatterBuilder() + .appendPattern(pattern) + .parseDefaulting(ChronoField.YEAR_OF_ERA, LocalDateTime.now().getYear()) + .parseDefaulting(ChronoField.MONTH_OF_YEAR, LocalDateTime.now().getMonthValue()) + .parseDefaulting(ChronoField.DAY_OF_MONTH, 1) + .parseDefaulting(ChronoField.HOUR_OF_DAY, 0) + .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0) + .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0) + .parseDefaulting(ChronoField.NANO_OF_SECOND, 0) + .toFormatter(); + } + + /** + * 将timestamp转为LocalDateTime + * @param timestamp + * @return + */ + public static LocalDateTime timestamToDatetime(long timestamp){ + Instant instant = Instant.ofEpochMilli(timestamp); + return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); + } + + /** + * 将LocalDataTime转为timestamp + * @param ldt + * @return + */ + public static long datatimeToTimestamp(LocalDateTime ldt){ + ZoneId zone = ZoneId.systemDefault(); + return ldt.atZone(zone).toInstant().toEpochMilli(); + } + + public static void main(String[] args) { + long timeStamp = 1382694957000l; + System.out.println(timestamToDatetime(timeStamp)); + } +} \ No newline at end of file diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/SHA1.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/SHA1.java new file mode 100644 index 0000000..9cb077f --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/SHA1.java @@ -0,0 +1,35 @@ +package com.ruoyi.weixin.utils; + +import java.security.MessageDigest; + +/** + * 业务模块 + * + * @author tianyongbao + * @date 2025/1/8 + */ +public class SHA1 { + private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + private static String getFormattedText(byte[] bytes) { + int len = bytes.length; + StringBuilder buf = new StringBuilder(len * 2); + for (int j = 0; j < len; j++) { + buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]); + buf.append(HEX_DIGITS[bytes[j] & 0x0f]); + } + return buf.toString(); + } + public static String encode(String str) { + if (str == null) { + return null; + } + try { + MessageDigest messageDigest = MessageDigest.getInstance("SHA1"); + messageDigest.update(str.getBytes()); + return getFormattedText(messageDigest.digest()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/ThirdSessionHolder.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/ThirdSessionHolder.java new file mode 100644 index 0000000..e5dc011 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/ThirdSessionHolder.java @@ -0,0 +1,48 @@ +package com.ruoyi.weixin.utils; + +import com.alibaba.ttl.TransmittableThreadLocal; +import com.ruoyi.weixin.entity.ThirdSession; +import lombok.experimental.UtilityClass; + +/** + * @author + * thirdSession工具类 + */ +@UtilityClass +public class ThirdSessionHolder { + + private final ThreadLocal THREAD_LOCAL_THIRD_SESSION = new TransmittableThreadLocal<>(); + + + /** + * TTL 设置thirdSession + * + * @param thirdSession + */ + public void setThirdSession(ThirdSession thirdSession) { + THREAD_LOCAL_THIRD_SESSION.set(thirdSession); + } + + /** + * 获取TTL中的thirdSession + * + * @return + */ + public ThirdSession getThirdSession() { + return THREAD_LOCAL_THIRD_SESSION.get(); + } + + public void clear() { + THREAD_LOCAL_THIRD_SESSION.remove(); + } + + + + /** + * 获取用户商城ID + * @return + */ + public String getWxUserId(){ + return THREAD_LOCAL_THIRD_SESSION.get().getWxUserId(); + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/WxMaUtil.java b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/WxMaUtil.java new file mode 100644 index 0000000..48dbd55 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/java/com/ruoyi/weixin/utils/WxMaUtil.java @@ -0,0 +1,23 @@ +package com.ruoyi.weixin.utils; + +import com.ruoyi.weixin.constant.ConfigConstant; + +import javax.servlet.http.HttpServletRequest; + + +/** + * @author www.joolun.com + * 小程序工具类 + */ +public class WxMaUtil { + /** + * 通过request获取appId + * @param request + * @return + * @throws Exception + */ + public static String getAppId(HttpServletRequest request) { + String appId = request.getHeader(ConfigConstant.HEADER_APP_ID); + return appId; + } +} diff --git a/ruoyi-modules/intc-weixin/src/main/resources/banner.txt b/ruoyi-modules/intc-weixin/src/main/resources/banner.txt new file mode 100644 index 0000000..69673d9 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/resources/banner.txt @@ -0,0 +1,24 @@ +Spring Boot Version: ${spring-boot.version} +Spring Application Name: ${spring.application.name} +//////////////////////////////////////////////////////////////////// +// _ooOoo_ // +// o8888888o // +// 88" . "88 // +// (| ^_^ |) // +// O\ = /O // +// ____/`---'\____ // +// .' \\| |// `. // +// / \\||| : |||// \ // +// / _||||| -:- |||||- \ // +// | | \\\ - /// | | // +// | \_| ''\---/'' | | // +// \ .-\__ `-` ___/-. / // +// ___`. .' /--.--\ `. . ___ // +// ."" '< `.___\_<|>_/___.' >'"". // +// | | : `- \`.;`\ _ /`;.`/ - ` : | | // +// \ \ `-. \_ __\ /__ _/ .-` / / // +// ========`-.____`-.___\_____/___.-`____.-'======== // +// `=---=' // +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // +// 佛祖保佑 永不宕机 永无BUG // +//////////////////////////////////////////////////////////////////// diff --git a/ruoyi-modules/intc-weixin/src/main/resources/bootstrap.yml b/ruoyi-modules/intc-weixin/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..631baca --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/resources/bootstrap.yml @@ -0,0 +1,41 @@ +# Tomcat +server: + max-http-header-size: 4048576 + port: 9238 + tomcat: + max-http-form-post-size: -1 + +# Spring +spring: + application: + # 应用名称 + name: intc-weixin + profiles: + # 环境配置 + active: dev + servlet: + multipart: + enabled: true + max-file-size: -1 + max-request-size: -1 + cloud: + nacos: + discovery: + namespace: 6ff354f8-471d-46ef-bd30-b81588a009cd + # 服务注册地址 + server-addr: 101.126.95.100:8858 + group: dev +# ip: 8.140.22.151 + config: + namespace: 6ff354f8-471d-46ef-bd30-b81588a009cd + # 配置中心地址 + server-addr: 101.126.95.100:8858 + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} +# 用于服务监控可在线查看日志,该配置用于生产环境 +logging: + file: + name: logs/${spring.application.name}/info.log diff --git a/ruoyi-modules/intc-weixin/src/main/resources/logback.xml b/ruoyi-modules/intc-weixin/src/main/resources/logback.xml new file mode 100644 index 0000000..0dc6014 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/resources/logback.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/info.log + + + + ${log.path}/info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/error.log + + + + ${log.path}/error.%d{yyyy-MM}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + + + + + + + + + + + + + diff --git a/ruoyi-modules/intc-weixin/src/main/resources/mapper/weixin/WxAutoReplyMapper.xml b/ruoyi-modules/intc-weixin/src/main/resources/mapper/weixin/WxAutoReplyMapper.xml new file mode 100644 index 0000000..ee91d59 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/resources/mapper/weixin/WxAutoReplyMapper.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ruoyi-modules/intc-weixin/src/main/resources/mapper/weixin/WxMenuMapper.xml b/ruoyi-modules/intc-weixin/src/main/resources/mapper/weixin/WxMenuMapper.xml new file mode 100644 index 0000000..5ba029e --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/resources/mapper/weixin/WxMenuMapper.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ruoyi-modules/intc-weixin/src/main/resources/mapper/weixin/WxMsgMapper.xml b/ruoyi-modules/intc-weixin/src/main/resources/mapper/weixin/WxMsgMapper.xml new file mode 100644 index 0000000..a340e12 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/resources/mapper/weixin/WxMsgMapper.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ruoyi-modules/intc-weixin/src/main/resources/mapper/weixin/WxUserMapper.xml b/ruoyi-modules/intc-weixin/src/main/resources/mapper/weixin/WxUserMapper.xml new file mode 100644 index 0000000..11c95b6 --- /dev/null +++ b/ruoyi-modules/intc-weixin/src/main/resources/mapper/weixin/WxUserMapper.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ruoyi-modules/pom.xml b/ruoyi-modules/pom.xml index a66e7fe..14ffc7f 100644 --- a/ruoyi-modules/pom.xml +++ b/ruoyi-modules/pom.xml @@ -15,6 +15,7 @@ ruoyi-file intc-invest intc-health + intc-weixin ruoyi-modules