浏览代码

add
微信公众号扫码登录;多公众号消息推送;

zoujiajian 3 年之前
父节点
当前提交
6390103364
共有 35 个文件被更改,包括 1011 次插入330 次删除
  1. 7 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 17 13
      netflix-common/src/main/java/com/cyksj/common/constant/TemplateEnum.java
  3. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/gzh/GzhMsgTemplateRelationMapper.java
  4. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/gzh/UserGzhRelationMapper.java
  5. 157 0
      netflix-dao/src/main/java/com/cyksj/model/dto/MsgEvent.java
  6. 27 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GzhMsgTemplateRelation.java
  7. 35 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserGzhRelation.java
  8. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/WxApp.java
  9. 38 0
      netflix-dao/src/main/java/com/cyksj/model/views/WxAppTemplateView.java
  10. 2 0
      netflix-service/src/main/java/com/cyksj/common/EnvCommonService.java
  11. 1 0
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  12. 7 0
      netflix-service/src/main/java/com/cyksj/service/distribute/DistributeService.java
  13. 30 3
      netflix-service/src/main/java/com/cyksj/service/distribute/impl/DistributeServiceImpl.java
  14. 13 0
      netflix-service/src/main/java/com/cyksj/service/gzh/GzhService.java
  15. 151 0
      netflix-service/src/main/java/com/cyksj/service/gzh/factory/EventMsgService.java
  16. 13 0
      netflix-service/src/main/java/com/cyksj/service/gzh/factory/GzhMsgService.java
  17. 28 0
      netflix-service/src/main/java/com/cyksj/service/gzh/factory/GzhMsgServiceFactory.java
  18. 20 0
      netflix-service/src/main/java/com/cyksj/service/gzh/factory/TextMsgService.java
  19. 26 0
      netflix-service/src/main/java/com/cyksj/service/gzh/impl/GzhServiceImpl.java
  20. 0 2
      netflix-service/src/main/java/com/cyksj/service/mange/CmsAccountService.java
  21. 0 48
      netflix-service/src/main/java/com/cyksj/service/mange/account/CmsAccountServiceImpl.java
  22. 11 55
      netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java
  23. 20 12
      netflix-service/src/main/java/com/cyksj/service/mange/impl/SpotifySendMsgServiceImpl.java
  24. 5 30
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  25. 18 14
      netflix-service/src/main/java/com/cyksj/service/register/impl/SpotifyServiceImpl.java
  26. 27 4
      netflix-service/src/main/java/com/cyksj/service/template/TemplateCommonService.java
  27. 168 26
      netflix-service/src/main/java/com/cyksj/service/template/impl/TemplateCommonServiceImpl.java
  28. 11 33
      netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java
  29. 1 1
      netflix-service/src/main/java/com/cyksj/service/wechat/WeChatService.java
  30. 6 2
      netflix-service/src/main/java/com/cyksj/service/wechat/impl/WeChatServiceImpl.java
  31. 52 45
      netflix-service/src/main/java/com/cyksj/task/Scheduler.java
  32. 2 1
      netflix-web/src/main/java/com/cyksj/config/SaTokenConfigure.java
  33. 4 1
      netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java
  34. 68 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/gzh/GzhController.java
  35. 15 40
      netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java

+ 7 - 0
netflix-common/src/main/java/com/cyksj/common/constant/Constant.java

@@ -11,4 +11,11 @@ public interface Constant {
 	 * 一天秒数
 	 */
 	Long DAY_MILLS = 86400000l;
+
+	String DEFAULT_NAME = "银河用户";
+
+	/**
+	 * 默认头像
+	 */
+	String DEFAULT_HEAD_IMG = "https://cdn.sxfoundation.com/picture/f6ee11101c4f5f0bc48d88aca7a5dbfd-1666945673391.png";
 }

+ 17 - 13
netflix-common/src/main/java/com/cyksj/common/constant/TemplateEnum.java

@@ -12,20 +12,24 @@ import lombok.Getter;
 @Getter
 @AllArgsConstructor
 public enum TemplateEnum {
-	//	ORDER_TRANSPORT_ENV_TEMPLATE("发货通知测试环境模板", "eQ8IXwudD5yJ6HPgyqTq9O9IZBb5Qvd1_BjoztmsbvA", " "),
-	ORDER_TRANSPORT_PRD_TEMPLATE("发货通知正式环境模板", "IfQ4Z9b_rTBjfwywYtJVj9-dWmQUpQ8V4PXO9cnCFYo", " "),
-	//	NEW_ORDER_ENV_TEMPLATE("新订单通知正式测试模板", "ArKvAzb193viawglfkiaNv7RgOZFP4Zq3EqrwRWlbPg", " "),
-	NEW_ORDER_PRD_TEMPLATE("新订单通知正式环境模板", "ArKvAzb193viawglfkiaNv7RgOZFP4Zq3EqrwRWlbPg", " "),
-	//	EMPTY_ENV_TEMPLATE("空车位通知测试环境模板", "ArZr9oCJYelqCfn0pU7RQqRbRIWuyRNaU7N_Oo6p2vM", " "),
-	EMPTY_PRD_TEMPLATE("正式环境空车位通知模板", "ArKvAzb193viawglfkiaNv7RgOZFP4Zq3EqrwRWlbPg", " "),
-	//	SPOTIFY_ENV_TEMPLATE("Spotify注册测试环境模板", "gsGFRefPlGKfvNoqB5Vd43ZOsmCsZNsH4UDWefWG0sg", " "),
-	SPOTIFY_PRD_TEMPLATE("Spotify注册正式环境模板", "PswFyVYMurzJbdV8weJW2kuSAGpS_fnAKJQR7qMNlQI", " "),
-	PLAT_ACCOUNT_UPDATE_PRD_TEMPLATE("账号修改密码正式环境通知模板", "krTse4JDgR-upgx3JiB7XNOqpTEFhwLnA-yD1u-BZlw", " "),
-	SPOTIFY_ACCOUNT_UN_LIMIT_SUCCESS_PRD_TEMPLATE("Spotify账号解除限制成功正式环境模板", "o51fvp6AriFaIzlweupK2qjR5afsnKy2JabKocX5wHU", " "),
-	WX_GZH_QR_CODE_LOGIN("微信公众号扫码登录正式环境模板", "t4YTQcMwjT9VYlPUGXxJuWSpXvVyqyq_8-xKBhuFBC8", "")
+	ORDER_TRANSPORT_TEMPLATE("发货通知模板"),
+
+	NEW_ORDER_TEMPLATE("新订单通知模板"),
+
+	EMPTY_TEMPLATE("空车位通知模板"),
+
+	SPOTIFY_TEMPLATE("Spotify注册通知模板"),
+
+	PLAT_ACCOUNT_UPDATE_TEMPLATE("账号修改密码通知模板"),
+
+	SPOTIFY_ACCOUNT_EXPIRED_PRD_TEMPLATE("Spotify账号到期通知模板"),
+
+	SPOTIFY_ACCOUNT_UN_LIMIT_SUCCESS_TEMPLATE("Spotify账号解除限制成功模板"),
+
+	EXPIRY_TEMPLATE("用户平台账号过期通知模板"),
+
+	WX_GZH_QR_CODE_LOGIN("微信公众号扫码登录模板")
 
 	;
 	private String desc;
-	private String templateId;
-	private String url;
 }

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/gzh/GzhMsgTemplateRelationMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.gzh;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GzhMsgTemplateRelation;
+
+/*
+ *项目名: netflix
+ *文件名: GzhMsgTemplateRelationMapper
+ *创建者: JavaZou
+ *创建时间:2023/1/16 12:27
+ */
+public interface GzhMsgTemplateRelationMapper extends BaseMapper<GzhMsgTemplateRelation> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/gzh/UserGzhRelationMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.gzh;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.UserGzhRelation;
+
+/*
+ *项目名: netflix
+ *文件名: UserGzhRelationMapper
+ *创建者: JavaZou
+ *创建时间:2023/1/16 10:58
+ */
+public interface UserGzhRelationMapper extends BaseMapper<UserGzhRelation> {
+}

+ 157 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/MsgEvent.java

@@ -0,0 +1,157 @@
+package com.cyksj.model.dto;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlCData;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * @author valor.
+ * @date 2019-08-02 12:53
+ */
+@Getter
+@Setter
+@JacksonXmlRootElement(localName = "xml")
+public class MsgEvent {
+
+    /**
+     * 开发者微信号
+     */
+    @JacksonXmlCData
+    @JacksonXmlProperty(localName = "ToUserName")
+    private String toUserName;
+
+    /**
+     * 发送方帐号 (一个OpenID)
+     */
+    @JacksonXmlCData
+    @JacksonXmlProperty(localName = "FromUserName")
+    private String fromUserName;
+
+    /**
+     * 消息创建时间 (整型)
+     */
+    @JacksonXmlCData
+    @JacksonXmlProperty(localName = "CreateTime")
+    private Long createTime;
+
+    /**
+     * 消息类型
+     */
+    @JacksonXmlCData
+    @JacksonXmlProperty(localName = "MsgType")
+    private MsgType msgType;
+
+    /**
+     * 当消息为event时 触发的事件类型
+     */
+    @JacksonXmlCData
+    @JacksonXmlProperty(localName = "Event")
+    private Event event;
+
+    /**
+     * 事件KEY值
+     */
+    @JacksonXmlCData
+    @JacksonXmlProperty(localName = "EventKey")
+    private String eventKey;
+
+    /**
+     * 二维码扫码时 会出现该参数
+     */
+    @JacksonXmlCData
+    @JacksonXmlProperty(localName = "Ticket")
+    private String ticket;
+
+    /**
+     * 当消息为text时 消息内容
+     */
+    @JacksonXmlCData
+    @JacksonXmlProperty(localName = "Content")
+    private String content;
+
+    /**
+     * 图文消息个数
+     *   当用户发送文本、图片、视频、图文、地理位置这五种消息时,开发者只能回复1条图文消息
+     *   其余场景最多可回复8条图文消息
+     */
+    @JacksonXmlCData
+    @JacksonXmlProperty(localName = "ArticleCount")
+    private Integer articleCount;
+
+    /**
+     * 图文消息信息,注意,如果图文数超过限制,则将只发限制内的条数
+     */
+    @JacksonXmlProperty(localName = "item")
+    @JacksonXmlElementWrapper(localName = "Articles")
+    private List<Article> articles;
+
+    public enum MsgType {
+        /**
+         * 消息类型
+         */
+        event("事件消息"),
+        text("文本消息"),
+        news("图文消息"),
+        image("图片消息"),
+        voice("语音消息"),
+        video("视频消息"),
+        shortvideo("小视频消息"),
+        location("地理位置消息"),
+        link("链接消息");
+
+        MsgType(String desc) { }
+    }
+
+    public enum Event {
+        /**
+         * 当消息为event时 可能是下列事件
+         */
+        subscribe("订阅"),
+        unsubscribe("取消订阅"),
+        SCAN("订阅状态中, 扫码二维码"),
+        LOCATION("上报地理位置"),
+        CLICK("点击自定义菜单(拉取子菜单 微信不会调用接口)"),
+        VIEW("点击菜单跳转链接"),
+        TEMPLATESENDJOBFINISH("模板消息"),
+        view_miniprogram("点击菜单跳转小程序");
+
+        Event(String desc) { }
+    }
+
+    @Getter
+    @Setter
+    public static class Article {
+        /**
+         * 扫码 图文消息标题
+         */
+        @JacksonXmlCData
+        @JacksonXmlProperty(localName = "Title")
+        private String title;
+
+        /**
+         * 扫码 图文消息描述
+         */
+        @JacksonXmlCData
+        @JacksonXmlProperty(localName = "Description")
+        private String desc;
+
+        /**
+         * 扫码 图文消息图片链接
+         */
+        @JacksonXmlCData
+        @JacksonXmlProperty(localName = "PicUrl")
+        private String picUrl;
+
+        /**
+         * 扫码 图文消息跳转链接
+         */
+        @JacksonXmlCData
+        @JacksonXmlProperty(localName = "Url")
+        private String link;
+    }
+}

+ 27 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GzhMsgTemplateRelation.java

@@ -0,0 +1,27 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: GzhMsgTemplateRelation
+ *创建者: JavaZou
+ *创建时间:2023/1/16 12:26
+ */
+@Getter
+@Setter
+public class GzhMsgTemplateRelation extends BaseEntity{
+	private Long wxAppId;
+
+	private String templateId;
+
+	private String url;
+
+	private String remark;
+
+	/**
+	 * 测试/线上(dev\prd)
+	 */
+	private String type;
+}

+ 35 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserGzhRelation.java

@@ -0,0 +1,35 @@
+package com.cyksj.model.entity;
+
+import com.cyksj.model.dto.MsgEvent;
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: UserGzhRelation
+ *创建者: JavaZou
+ *创建时间:2023/1/16 10:56
+ */
+@Getter
+@Setter
+public class UserGzhRelation extends BaseEntity{
+	private Long wxAppId;
+
+	private Long userId;
+
+	private String openId;
+
+	private String unionid;
+
+	private MsgEvent.Event event;
+
+	/**
+	 * 是否关注
+	 */
+	private Boolean isSubscribe;
+
+	/**
+	 * 是否是扫描二维码
+	 */
+	private Boolean isQrScene;
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/WxApp.java

@@ -24,6 +24,11 @@ public class WxApp extends BaseEntity {
      */
     private String appId;
 
+    /**
+     * 公众号的原始id
+     */
+    private String gzhOriginalId;
+
     /**
      * appSecret
      */

+ 38 - 0
netflix-dao/src/main/java/com/cyksj/model/views/WxAppTemplateView.java

@@ -0,0 +1,38 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: WxAppTemplateView
+ *创建者: JavaZou
+ *创建时间:2023/1/16 13:39
+ */
+@Getter
+@Setter
+@SearchBean(tables = "gzh_msg_template_relation gtr left join wx_app wa on wa.id = gtr.wx_app_id")
+public class WxAppTemplateView {
+	@DbField("gtr.id")
+	private Long id;
+
+	@DbField("gtr.wx_app_id")
+	private Long wxAppId;
+
+	@DbField("gtr.template_id")
+	private String templateId;
+
+	@DbField("gtr.type")
+	private String type;
+
+	@DbField("gtr.remark")
+	private String remark;
+
+	/**
+	 * 公众号appid
+	 */
+	@DbField("wa.app_id")
+	private String appId;
+}

+ 2 - 0
netflix-service/src/main/java/com/cyksj/common/EnvCommonService.java

@@ -18,6 +18,8 @@ public class EnvCommonService {
 
 	public static final String active = "dev";
 
+	public static final String active_prd = "prd";
+
 	@Value(value = "${spring.profiles.active}")
 	private String env;
 

+ 1 - 0
netflix-service/src/main/java/com/cyksj/redis/RedisService.java

@@ -594,6 +594,7 @@ public class RedisService {
         LOTTERY_KEY("lottery_key:%s", "抽奖key", 60 * 60 * 24l),
         TASK_TIME_LIMIT_KEY("task_time_limit:%s", "一次性任务key", 30),
         WX_GZH_QRCODE_LOGIN("wx_gzh_qrcode_login:%s", "微信公众号扫码登录key", 60),
+        WX_GZH_QRCODE_SHARED_LOGIN("wx_gzh_qrcode_shared_login:%s", "微信公众号扫码分享邀请key", 60),
         ;
 
         private String name;

+ 7 - 0
netflix-service/src/main/java/com/cyksj/service/distribute/DistributeService.java

@@ -12,4 +12,11 @@ public interface DistributeService {
 	void insertDistribute(UserDistributeReq userDistributeReq);
 
 	void editDistribute(UserDistributeReq userDistributeReq);
+
+	/**
+	 * 保存分销邀请记录
+	 * sharedId: 邀请人
+	 * userId: 被邀请人
+	 */
+	void saveDistributionInvitation(Long sharedId, Long userId);
 }

+ 30 - 3
netflix-service/src/main/java/com/cyksj/service/distribute/impl/DistributeServiceImpl.java

@@ -1,16 +1,20 @@
 package com.cyksj.service.distribute.impl;
 
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.constant.TaskTypeEnum;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.mapper.GoodsDonMapper;
 import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
+import com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper;
 import com.cyksj.mapper.manage.distribute.UserPlatDistributeRateMapper;
-import com.cyksj.model.entity.GoodsDon;
-import com.cyksj.model.entity.UserDistribute;
-import com.cyksj.model.entity.UserPlatDistributeRate;
+import com.cyksj.mapper.market.task.TaskTypeMapper;
+import com.cyksj.model.entity.*;
 import com.cyksj.model.request.UserDistributeReq;
 import com.cyksj.service.distribute.DistributeService;
+import com.cyksj.service.market.task.TaskService;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -22,6 +26,7 @@ import org.springframework.transaction.annotation.Transactional;
  */
 @Service
 @RequiredArgsConstructor
+@Slf4j
 public class DistributeServiceImpl implements DistributeService {
 	private final UserDistributeMapper userDistributeMapper;
 
@@ -29,6 +34,12 @@ public class DistributeServiceImpl implements DistributeService {
 
 	private final GoodsDonMapper goodsDonMapper;
 
+	private final TaskService taskService;
+
+	private final TaskTypeMapper taskTypeMapper;
+
+	private final UserDistributeSharedMapper userDistributeSharedMapper;
+
 	@Override
 	@Transactional(rollbackFor = Throwable.class)
 	public void insertDistribute(UserDistributeReq userDistributeReq) {
@@ -75,4 +86,20 @@ public class DistributeServiceImpl implements DistributeService {
 			userPlatDistributeRateMapper.updateById(rate);
 		}
 	}
+
+	@Override
+	public void saveDistributionInvitation(Long sharedId, Long userId) {
+		UserDistributeShared userDistributeShared = new UserDistributeShared();
+		userDistributeShared.setSharedId(sharedId);
+		//存在分销
+		userDistributeShared.setUserId(userId);
+		try {
+			userDistributeSharedMapper.insert(userDistributeShared);
+			TaskType taskType = taskTypeMapper.selectOne(Wrappers.lambdaQuery(TaskType.class)
+					.eq(TaskType::getName, TaskTypeEnum.share.getDesc()).last("limit 1"));
+			taskService.completeTask(taskType, sharedId);
+		} catch (DuplicateKeyException e) {
+			log.info("分销被邀请人重复插入");
+		}
+	}
 }

+ 13 - 0
netflix-service/src/main/java/com/cyksj/service/gzh/GzhService.java

@@ -0,0 +1,13 @@
+package com.cyksj.service.gzh;
+
+import com.cyksj.model.dto.MsgEvent;
+
+/*
+ *项目名: netflix
+ *文件名: GzhService
+ *创建者: JavaZou
+ *创建时间:2023/1/13 17:09
+ */
+public interface GzhService {
+	String gzhMsg(MsgEvent msgEvent);
+}

+ 151 - 0
netflix-service/src/main/java/com/cyksj/service/gzh/factory/EventMsgService.java

@@ -0,0 +1,151 @@
+package com.cyksj.service.gzh.factory;
+
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.constant.Constant;
+import com.cyksj.common.util.Codec;
+import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.WxAppMapper;
+import com.cyksj.mapper.gzh.UserGzhRelationMapper;
+import com.cyksj.model.dto.GzhUnionidUserinfo;
+import com.cyksj.model.dto.MsgEvent;
+import com.cyksj.model.entity.User;
+import com.cyksj.model.entity.UserGzhRelation;
+import com.cyksj.model.entity.WxApp;
+import com.cyksj.redis.RedisService;
+import com.cyksj.service.distribute.DistributeService;
+import com.cyksj.service.wechat.WeChatService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.stereotype.Service;
+
+/*
+ *项目名: netflix
+ *文件名: EventMsgService
+ *创建者: JavaZou
+ *创建时间:2023/1/13 18:16
+ */
+@Service("event")
+@RequiredArgsConstructor
+@Slf4j
+public class EventMsgService implements GzhMsgService {
+	private final UserMapper userMapper;
+
+	private final UserGzhRelationMapper userGzhRelationMapper;
+
+	private final WeChatService weChatService;
+
+	private final WxAppMapper wxAppMapper;
+
+	private final RedisService redisService;
+
+	private final DistributeService distributeService;
+
+	@Override
+	public String handleNotify(MsgEvent msgEvent) {
+		try {
+			if (msgEvent.getEvent() == MsgEvent.Event.subscribe) {
+				String eventKey = msgEvent.getEventKey();
+				if (StrUtil.isNotEmpty(eventKey) && eventKey.contains("qrscene")) {
+					msgEvent.setEventKey(eventKey.substring(eventKey.indexOf("qrscene_") + 8));
+				}
+				if (!saveOrGetUser(msgEvent)) {
+					return "";
+				}
+			} else if (msgEvent.getEvent() == MsgEvent.Event.unsubscribe) {
+				UserGzhRelation userGzhRelation = userGzhRelationMapper.selectOne(Wrappers.lambdaQuery(UserGzhRelation.class)
+						.eq(UserGzhRelation::getOpenId, msgEvent.getFromUserName()).last("limit 1"));
+				if (userGzhRelation == null) {
+					return "";
+				}
+				userGzhRelation.setIsSubscribe(false);
+				userGzhRelationMapper.updateById(userGzhRelation);
+			} else if (msgEvent.getEvent() == MsgEvent.Event.SCAN) {
+				if (!saveOrGetUser(msgEvent)) {
+					return "";
+				}
+			}
+			return "";
+		} catch (Exception e) {
+			log.error("接收微信公众:{},报错:{}", msgEvent.getToUserName(), e == null ? "" : e.getMessage());
+			return "";
+		}
+	}
+
+	public Boolean saveOrGetUser(MsgEvent msgEvent) throws Exception {
+		//扫描带参数二维码 场景值
+		String sceneKey = msgEvent.getEventKey();
+
+		String openId = msgEvent.getFromUserName();
+		if (StrUtil.isEmpty(openId)) {
+			return false;
+		}
+		//该用户是否存在于用户表里面
+		User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
+				.eq(User::getOpenId, openId)
+				.select(User::getId)
+				.last("limit 1"));
+		GzhUnionidUserinfo info = weChatService.getUserInfo2(weChatService.getAccessToken(), openId);
+		if (user == null) {
+			user = new User();
+			user.setNickname(String.format("%s%s", Constant.DEFAULT_NAME, Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.MD5).setStringData(RandomUtil.randomString(10)).toHexString().substring(0, 6)))
+					.setSex(info.getSex())
+					.setCountry(info.getCountry())
+					.setProvince(info.getProvince())
+					.setCity(info.getCity())
+					.setHeadimgurl(Constant.DEFAULT_HEAD_IMG);
+			user.setOpenId(openId);
+			user.setUnionid(info.getUnionid());
+			userMapper.insert(user);
+
+			Object sharedIdObj = redisService.get(RedisService.key.WX_GZH_QRCODE_SHARED_LOGIN.getNameFormat(sceneKey));
+			if (sharedIdObj != null) {
+				Long sharedId = Long.parseLong(sharedIdObj.toString());
+				distributeService.saveDistributionInvitation(sharedId, user.getId());
+			}
+
+			saveGzhUserRelation(msgEvent, user.getId(), openId, info.getUnionid());
+		} else {
+			//之前关注过
+			if (user.getUnionid() == null || !user.getUnionid().equals(info.getUnionid())) {
+				user.setUnionid(info.getUnionid());
+				userMapper.updateById(user);
+			}
+			UserGzhRelation userGzhRelation = userGzhRelationMapper.selectOne(Wrappers.lambdaQuery(UserGzhRelation.class)
+					.eq(UserGzhRelation::getOpenId, msgEvent.getFromUserName()).last("limit 1"));
+			if (userGzhRelation == null) {
+				saveGzhUserRelation(msgEvent, user.getId(), openId, info.getUnionid());
+			}
+		}
+		//场景值扫描公众号二维码 登录
+		if (StrUtil.isNotEmpty(sceneKey)) {
+			redisService.set(RedisService.key.WX_GZH_QRCODE_LOGIN.getNameFormat(sceneKey), user.getId(), RedisService.key.WX_GZH_QRCODE_LOGIN.getTimeout());
+		}
+		return true;
+	}
+
+	private void saveGzhUserRelation(MsgEvent msgEvent, Long userId, String openId, String unionid) {
+		UserGzhRelation userGzhRelation = new UserGzhRelation();
+		userGzhRelation.setUserId(userId);
+
+		WxApp wxApp = wxAppMapper.selectOne(Wrappers.lambdaQuery(WxApp.class)
+				.eq(WxApp::getGzhOriginalId, msgEvent.getToUserName()).last("limit 1"));
+		if (wxApp != null) {
+			userGzhRelation.setWxAppId(wxApp.getId());
+			userGzhRelation.setIsSubscribe(true);
+			userGzhRelation.setEvent(msgEvent.getEvent());
+			userGzhRelation.setOpenId(openId);
+			userGzhRelation.setUnionid(unionid);
+			if (StrUtil.isNotEmpty(msgEvent.getEventKey())) {
+				userGzhRelation.setIsQrScene(true);
+			}
+			try {
+				userGzhRelationMapper.insert(userGzhRelation);
+			} catch (DuplicateKeyException e) {
+
+			}
+		}
+	}
+}

+ 13 - 0
netflix-service/src/main/java/com/cyksj/service/gzh/factory/GzhMsgService.java

@@ -0,0 +1,13 @@
+package com.cyksj.service.gzh.factory;
+
+import com.cyksj.model.dto.MsgEvent;
+
+/*
+ *项目名: netflix
+ *文件名: GzhMsgService
+ *创建者: JavaZou
+ *创建时间:2023/1/13 18:22
+ */
+public interface GzhMsgService{
+	String handleNotify(MsgEvent msgEvent);
+}

+ 28 - 0
netflix-service/src/main/java/com/cyksj/service/gzh/factory/GzhMsgServiceFactory.java

@@ -0,0 +1,28 @@
+package com.cyksj.service.gzh.factory;
+
+import com.cyksj.model.dto.MsgEvent;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/*
+ *项目名: netflix
+ *文件名: GzhMsgServiceFactory
+ *创建者: JavaZou
+ *创建时间:2023/1/13 18:16
+ */
+@Component
+public class GzhMsgServiceFactory {
+
+	@Resource
+	Map<String, GzhMsgService> ghzMsgServiceMap = new ConcurrentHashMap<>();
+
+
+	public String handleMsg(MsgEvent msgEvent) {
+		GzhMsgService gzhMsgService = ghzMsgServiceMap.get(msgEvent.getMsgType().name());
+
+		return gzhMsgService.handleNotify(msgEvent);
+	}
+}

+ 20 - 0
netflix-service/src/main/java/com/cyksj/service/gzh/factory/TextMsgService.java

@@ -0,0 +1,20 @@
+package com.cyksj.service.gzh.factory;
+
+import com.cyksj.model.dto.MsgEvent;
+import org.springframework.stereotype.Service;
+
+/*
+ *项目名: netflix
+ *文件名: TextMsgService
+ *创建者: JavaZou
+ *创建时间:2023/1/13 18:16
+ */
+@Service("text")
+public class TextMsgService implements GzhMsgService{
+
+	@Override
+	public String handleNotify(MsgEvent msgEvent) {
+
+		return "";
+	}
+}

+ 26 - 0
netflix-service/src/main/java/com/cyksj/service/gzh/impl/GzhServiceImpl.java

@@ -0,0 +1,26 @@
+package com.cyksj.service.gzh.impl;
+
+import com.cyksj.model.dto.MsgEvent;
+import com.cyksj.service.gzh.GzhService;
+import com.cyksj.service.gzh.factory.GzhMsgServiceFactory;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/*
+ *项目名: netflix
+ *文件名: GzhServiceImpl
+ *创建者: JavaZou
+ *创建时间:2023/1/13 17:09
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class GzhServiceImpl implements GzhService {
+	private final GzhMsgServiceFactory gzhMsgServiceFactory;
+
+	@Override
+	public String gzhMsg(MsgEvent msgEvent){
+		return gzhMsgServiceFactory.handleMsg(msgEvent);
+	}
+}

+ 0 - 2
netflix-service/src/main/java/com/cyksj/service/mange/CmsAccountService.java

@@ -22,6 +22,4 @@ public interface CmsAccountService extends IService<Account> {
 	List<OrderDon> getNoAppleOneOrderDon(List<Long> skuIds, Date yesZeroDate, Date thisZeroDate, List<String> noOrderStatus);
 
 	List<ExcelAccountData> getExpiredAccountViewNoPage(Boolean isCorpWx, String customerService, Integer goodsId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, String startDate, String endDate, String toString);
-
-	void sendAccountTemplateMsg(Account account) throws Exception;
 }

+ 0 - 48
netflix-service/src/main/java/com/cyksj/service/mange/account/CmsAccountServiceImpl.java

@@ -1,27 +1,14 @@
 package com.cyksj.service.mange.account;
 
-import cn.hutool.core.date.DateTime;
 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.cyksj.common.EnvCommonService;
-import com.cyksj.common.constant.TemplateEnum;
-import com.cyksj.common.util.Jsons;
 import com.cyksj.mapper.AccountMapper;
-import com.cyksj.mapper.UserMapper;
-import com.cyksj.model.dto.WxMpTemplateData;
-import com.cyksj.model.dto.WxMpTemplateMessage;
 import com.cyksj.model.entity.Account;
 import com.cyksj.model.entity.OrderDon;
-import com.cyksj.model.entity.User;
 import com.cyksj.model.excel.ExcelAccountData;
-import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.views.ExpiredAccountDataView;
 import com.cyksj.service.mange.CmsAccountService;
-import com.cyksj.service.wechat.WeChatService;
-import com.ejlchina.searcher.BeanSearcher;
-import com.ejlchina.searcher.param.Operator;
-import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -39,14 +26,6 @@ import java.util.List;
 public class CmsAccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements CmsAccountService {
 	private final AccountMapper accountMapper;
 
-	private final WeChatService weChatService;
-
-	private final BeanSearcher beanSearcher;
-
-	private final EnvCommonService envCommonService;
-
-	private final UserMapper userMapper;
-
 	@Override
 	public IPage<ExpiredAccountDataView> getExpiredAccountView(Boolean isCorpWx, String customerService, Integer goodsId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, String startTime, String endTime, String now, Long offset, Long limit) {
 		return accountMapper.getExpiredAccountView(isCorpWx, customerService, goodsId, account, renewStatus, handleStatus, cnAccount, usAccount, userId, startTime, endTime, now, new Page<>(offset, limit));
@@ -57,33 +36,6 @@ public class CmsAccountServiceImpl extends ServiceImpl<AccountMapper, Account> i
 		return accountMapper.getExpiredAccountViewNoPage(isCorpWx, customerService, goodsId, account, renewStatus, handleStatus, cnAccount, usAccount, userId, startTime, endTime, now);
 	}
 
-	@Override
-	public void sendAccountTemplateMsg(Account account) throws Exception {
-		List<GroupsRelationView> relations = beanSearcher.searchList(GroupsRelationView.class, MapUtils.builder()
-				.field(GroupsRelationView::getAccountId, account.getId()).op(Operator.Equal)
-				.field(GroupsRelationView::getStatus, "validity").op(Operator.Equal)
-				.build());
-		String url = String.format("%sauth/weChat?url=%syinhe/web/ticket", envCommonService.getHost(), envCommonService.getDomain());
-		log.info("开始发送账号修改密码模板消息,大小:{}", relations.size());
-		for (GroupsRelationView relation : relations) {
-			TemplateEnum templateEnum = TemplateEnum.PLAT_ACCOUNT_UPDATE_PRD_TEMPLATE;
-			User user = userMapper.selectById(relation.getUserId());
-			if (user != null) {
-				WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
-						.setToUser(user.getOpenId())
-						.setTemplateId(templateEnum.getTemplateId())
-						.setUrl(url);
-				WxMpTemplateMessage.TemplateData data = templateMessage.getData();
-				data.setFirst(new WxMpTemplateData(String.format("%s账号密码更改提醒", relation.getTitle())));
-				data.setKeyword1(new WxMpTemplateData(relation.getTripsAccount()));
-				data.setKeyword2(new WxMpTemplateData(DateTime.now().toString("YYYY-MM-mm HH:mm:ss")));
-				data.setRemark(new WxMpTemplateData("您的账号密码已经更新,请到我的车票查看,长期用户请选择拼车/年付。\n" +
-						"如您不是在公众号购买,请在浏览器登录查看我的车票"));
-				weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
-			}
-		}
-	}
-
 	@Override
 	public List<Account> getNoAppleOneAccount(String appleOne) {
 		return accountMapper.getNoAppleOneAccount(appleOne);

+ 11 - 55
netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java

@@ -2,22 +2,20 @@ package com.cyksj.service.mange.impl;
 
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.cyksj.common.EnvCommonService;
-import com.cyksj.common.constant.TemplateEnum;
-import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
-import com.cyksj.common.util.Jsons;
-import com.cyksj.mapper.*;
+import com.cyksj.mapper.OrderDonMapper;
+import com.cyksj.mapper.OrderDonTransportMapper;
+import com.cyksj.mapper.OrderDonWaybillMapper;
 import com.cyksj.mapper.stock.GoodsSkuStockRelateMapper;
-import com.cyksj.mapper.stock.OrderDonStockMapper;
-import com.cyksj.model.dto.WxMpTemplateData;
-import com.cyksj.model.dto.WxMpTemplateMessage;
-import com.cyksj.model.entity.*;
+import com.cyksj.model.entity.GoodsSkuStockRelate;
+import com.cyksj.model.entity.OrderDon;
+import com.cyksj.model.entity.OrderDonTransport;
+import com.cyksj.model.entity.OrderDonWaybill;
 import com.cyksj.model.excel.ExcelOrderDonInfo;
 import com.cyksj.model.manage.request.ReqSetLogisticsPost;
 import com.cyksj.service.mange.CmsOrderDonService;
 import com.cyksj.service.mange.stock.GoodsDonStockService;
-import com.cyksj.service.wechat.WeChatService;
+import com.cyksj.service.template.TemplateCommonService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -39,20 +37,12 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
 
     private final OrderDonWaybillMapper orderDonWaybillMapper;
 
-    private final UserMapper userMapper;
-
-    private final EnvCommonService envCommonService;
-
-    private final GoodsDonMapper goodsDonMapper;
-
-    private final WeChatService weChatService;
-
     private final GoodsSkuStockRelateMapper skuStockRelateMapper;
 
-    private final OrderDonStockMapper orderDonStockMapper;
-
     private final GoodsDonStockService goodsDonStockService;
 
+    private final TemplateCommonService templateCommonService;
+
     private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
 
     @Override
@@ -91,7 +81,7 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
             TASK_POOL.execute(()->{
                 try {
                     log.info("发送发货通知至{}用户", orderDon.getUserId());
-                    sendTransportMsgNotify(orderDon, reqSetLogisticsPost);
+                    templateCommonService.sendTransportMsgNotify(orderDon, reqSetLogisticsPost);
                 } catch (Exception e) {
                     log.error("发送发货通知至{}用户失败:{}", orderDon.getUserId(), e);
                 }
@@ -106,38 +96,4 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
         return orderDonWaybill;
     }
 
-
-    private void sendTransportMsgNotify(OrderDon orderDon, ReqSetLogisticsPost reqSetLogisticsPost) throws Exception {
-        TemplateEnum templateEnum = null;
-        if (EnvCommonService.active.equals(envCommonService.getEnv())) {
-            return;
-        }else {
-            templateEnum = TemplateEnum.ORDER_TRANSPORT_PRD_TEMPLATE;
-        }
-        String openId = orderDon.getOpenId();
-        if (openId == null) {
-            User u  = userMapper.selectById(orderDon.getUserId());
-            if (u == null) {
-                throw BusinessRuntimeException.getInstance("用户不存在");
-            }
-            openId = u.getOpenId();
-        }
-        WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
-                .setToUser(openId)
-                .setTemplateId(templateEnum.getTemplateId())
-                //TODO
-                .setUrl(" ");
-        GoodsDon goodsDon = goodsDonMapper.selectById(orderDon.getGoodsId());
-        OrderDonTransport transport = transportMapper.selectOne(Wrappers.lambdaQuery(OrderDonTransport.class).eq(OrderDonTransport::getOrderId, reqSetLogisticsPost.getOrderId()).last("limit 1"));
-        WxMpTemplateMessage.TemplateData data = templateMessage.getData();
-        data.setFirst(new WxMpTemplateData("订单发货通知"));
-        data.setKeyword1(new WxMpTemplateData(orderDon.getOrderNo()));
-        data.setKeyword2(new WxMpTemplateData(goodsDon.getTitle()));
-        data.setKeyword3(new WxMpTemplateData(reqSetLogisticsPost.getCodeCn()));
-        data.setKeyword4(new WxMpTemplateData(reqSetLogisticsPost.getTrackingNumber()));
-        data.setKeyword5(new WxMpTemplateData(String.format("%s%s%s%s", transport.getProvince(), transport.getCity(), transport.getDistrict(), transport.getAddress())));
-        data.setRemark(new WxMpTemplateData("可复制运单编号查询物流信息"));
-        weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
-    }
-
 }

+ 20 - 12
netflix-service/src/main/java/com/cyksj/service/mange/impl/SpotifySendMsgServiceImpl.java

@@ -10,7 +10,9 @@ import com.cyksj.model.dto.WxMpTemplateData;
 import com.cyksj.model.dto.WxMpTemplateMessage;
 import com.cyksj.model.entity.SpotifyUnLimitRecord;
 import com.cyksj.model.entity.User;
+import com.cyksj.model.views.WxAppTemplateView;
 import com.cyksj.service.mange.SpotifySendMsgService;
+import com.cyksj.service.template.TemplateCommonService;
 import com.cyksj.service.wechat.WeChatService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -38,6 +40,8 @@ public class SpotifySendMsgServiceImpl implements SpotifySendMsgService {
 
 	private static String spotifyUnLimitSuccessUrl;
 
+	private final TemplateCommonService templateCommonService;
+
 	@PostConstruct
 	public void init() {
 		String host = envCommonService.getHost();
@@ -53,18 +57,22 @@ public class SpotifySendMsgServiceImpl implements SpotifySendMsgService {
 			if (unLimitRecord != null && !unLimitRecord.getIsSend()) {
 				User user = userMapper.selectById(unLimitRecord.getUserId());
 				if (user != null) {
-					WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
-							.setToUser(user.getOpenId())
-							.setTemplateId(TemplateEnum.SPOTIFY_ACCOUNT_UN_LIMIT_SUCCESS_PRD_TEMPLATE.getTemplateId())
-							.setUrl(spotifyUnLimitSuccessUrl);
-					WxMpTemplateMessage.TemplateData data = templateMessage.getData();
-					data.setFirst(new WxMpTemplateData("您的Spotify账号登录限制解除成功"));
-					data.setKeyword1(new WxMpTemplateData(user.getNickname()));
-					data.setKeyword2(new WxMpTemplateData(DateUtil.format(unLimitRecord.getUpdateTime(), "yyyy-MM-dd HH:mm:ss")));
-					data.setRemark(new WxMpTemplateData("建议您购买Spotify年付会员,无需每过14天解除限制,点击了解"));
-					weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
-					unLimitRecord.setIsSend(true);
-					spotifyUnLimitRecordMapper.updateById(unLimitRecord);
+					Long userId = user.getId();
+					WxAppTemplateView wxAppTemplateView = templateCommonService.getWxAppByUserId(userId, TemplateEnum.SPOTIFY_ACCOUNT_UN_LIMIT_SUCCESS_TEMPLATE.getDesc());
+					if (wxAppTemplateView != null) {
+						WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
+								.setToUser(user.getOpenId())
+								.setTemplateId(wxAppTemplateView.getTemplateId())
+								.setUrl(spotifyUnLimitSuccessUrl);
+						WxMpTemplateMessage.TemplateData data = templateMessage.getData();
+						data.setFirst(new WxMpTemplateData("您的Spotify账号登录限制解除成功"));
+						data.setKeyword1(new WxMpTemplateData(user.getNickname()));
+						data.setKeyword2(new WxMpTemplateData(DateUtil.format(unLimitRecord.getUpdateTime(), "yyyy-MM-dd HH:mm:ss")));
+						data.setRemark(new WxMpTemplateData("建议您购买Spotify年付会员,无需每过14天解除限制,点击了解"));
+						weChatService.sendTemplateMessage(weChatService.getAccessToken(wxAppTemplateView.getAppId()), Jsons.toJson(templateMessage));
+						unLimitRecord.setIsSend(true);
+						spotifyUnLimitRecordMapper.updateById(unLimitRecord);
+					}
 				}
 			}
 		}

+ 5 - 30
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -20,7 +20,6 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.cyksj.common.AliPayCommon;
 import com.cyksj.common.EnvCommonService;
 import com.cyksj.common.constant.TaskTypeEnum;
-import com.cyksj.common.constant.TemplateEnum;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.snowflake.Sequence;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
@@ -40,7 +39,9 @@ import com.cyksj.mapper.manage.coupon.CouponSkuMapper;
 import com.cyksj.mapper.manage.coupon.CouponUserMapper;
 import com.cyksj.mapper.manage.distribute.*;
 import com.cyksj.mapper.market.task.TaskTypeMapper;
-import com.cyksj.model.dto.*;
+import com.cyksj.model.dto.AliPayParams;
+import com.cyksj.model.dto.CouponPopularizeDto;
+import com.cyksj.model.dto.H5JsPayParams;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.OrderDonView;
 import com.cyksj.model.request.OrderAttach;
@@ -311,7 +312,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 					List<CustomerService> customerServices = customerServiceMapper.selectList(null);
 					for (CustomerService customerService : customerServices) {
 						log.info("发送客服{}空车位通知消息", customerService.getNickName());
-						emptySendMsgNotify(orderDon, customerService.getOpenId());
+						templateCommonService.emptySendMsgNotify(orderDon, customerService.getOpenId());
 					}
 				} catch (Exception e) {
 					log.error("发送{}空车位模板消息至客服失败:{}", orderDon.getGoodsId(), e);
@@ -537,32 +538,6 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		}
 	}
 
-	private void emptySendMsgNotify(OrderDon orderDon, String toPeople) throws Exception {
-		TemplateEnum templateEnum = null;
-		if (EnvCommonService.active.equals(envCommonService.getEnv())) {
-			return;
-		} else {
-			templateEnum = TemplateEnum.EMPTY_PRD_TEMPLATE;
-		}
-		User u = userMapper.selectById(orderDon.getUserId());
-		WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
-				.setToUser(toPeople)
-				.setTemplateId(templateEnum.getTemplateId())
-				//TODO
-				.setUrl(" ");
-		GoodsDon goodsDon = goodsDonMapper.selectById(orderDon.getGoodsId());
-		GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
-		WxMpTemplateMessage.TemplateData data = templateMessage.getData();
-		data.setFirst(new WxMpTemplateData("空车位通知!"));
-		data.setKeyword1(new WxMpTemplateData(orderDon.getOrderNo()));
-		data.setKeyword2(new WxMpTemplateData(String.format("%s,%s", goodsDon.getTitle(), goodsDonSku.getSpecVal())));
-		data.setKeyword3(new WxMpTemplateData((u == null ? " " : u.getNickname())));
-		data.setKeyword4(new WxMpTemplateData(orderDon.getMoney().divide(BigDecimal.valueOf(100)).toString()));
-		data.setKeyword5(new WxMpTemplateData(DateUtil.format(orderDon.getCreatedTime(), "yyyy-MM-dd HH:mm:ss")));
-		data.setRemark(new WxMpTemplateData("请尽快关联账号信息"));
-		weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
-	}
-
 	@Override
 	@Transactional(rollbackFor = Throwable.class)
 	public OrderDon renewal(OrderPayRequest payRequest) throws Exception {
@@ -1462,7 +1437,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 					List<CustomerService> customerServices = customerServiceMapper.selectList(null);
 					for (CustomerService customerService : customerServices) {
 						log.info("发送客服{}空车位通知消息", customerService.getNickName());
-						emptySendMsgNotify(order, customerService.getOpenId());
+						templateCommonService.emptySendMsgNotify(order, customerService.getOpenId());
 					}
 				} catch (Exception e) {
 					log.error("发送{}空车位模板消息至客服失败:{}", order.getGoodsId(), e);

+ 18 - 14
netflix-service/src/main/java/com/cyksj/service/register/impl/SpotifyServiceImpl.java

@@ -26,10 +26,12 @@ import com.cyksj.model.entity.RegisterOrderDon;
 import com.cyksj.model.entity.SysConfig;
 import com.cyksj.model.request.SpotifyRegisterReq;
 import com.cyksj.model.response.ProxyInfo;
+import com.cyksj.model.views.WxAppTemplateView;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.mange.coupon.CouponCommonService;
 import com.cyksj.service.register.SpotifyService;
 import com.cyksj.service.sys.SysConfigService;
+import com.cyksj.service.template.TemplateCommonService;
 import com.cyksj.service.wechat.WeChatService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -70,6 +72,8 @@ public class SpotifyServiceImpl implements SpotifyService {
 
     private final SysConfigService sysConfigService;
 
+    private final TemplateCommonService templateCommonService;
+
     private static final List<String> User_Agent_LIST =  List.of(
             "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
             "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
@@ -311,21 +315,21 @@ public class SpotifyServiceImpl implements SpotifyService {
     }
 
     private void spotifyTemplateMsg(RegisterOrderDon registerOrderDon, String url, Boolean isSuccess) throws Exception {
-        TemplateEnum templateEnum = null;
-        if (EnvCommonService.active.equals(envCommonService.getEnv())) {
-            return;
-        }else {
-            templateEnum = TemplateEnum.SPOTIFY_PRD_TEMPLATE;
+        if (!EnvCommonService.active.equals(envCommonService.getEnv())) {
+            Long userId = registerOrderDon.getUserId();
+            WxAppTemplateView wxAppTemplateView = templateCommonService.getWxAppByUserId(userId, TemplateEnum.SPOTIFY_TEMPLATE.getDesc());
+            if (wxAppTemplateView != null) {
+                WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
+                        .setToUser(registerOrderDon.getOpenId())
+                        .setTemplateId(wxAppTemplateView.getTemplateId())
+                        .setUrl(url);
+                WxMpTemplateMessage.TemplateData data = templateMessage.getData();
+                data.setFirst(new WxMpTemplateData(isSuccess ? "Spotify账号已注册成功" : "Spotify账号注册失败,请修改后重新提交"));
+                data.setKeyword1(new WxMpTemplateData(registerOrderDon.getPhone()));
+                data.setKeyword2(new WxMpTemplateData(DateUtil.format(registerOrderDon.getCreatedTime(), "yyyy-MM-dd HH:mm:ss")));
+                weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
+            }
         }
-        WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
-                .setToUser(registerOrderDon.getOpenId())
-                .setTemplateId(templateEnum.getTemplateId())
-                .setUrl(url);
-        WxMpTemplateMessage.TemplateData data = templateMessage.getData();
-        data.setFirst(new WxMpTemplateData(isSuccess ? "Spotify账号已注册成功" : "Spotify账号注册失败,请修改后重新提交"));
-        data.setKeyword1(new WxMpTemplateData(registerOrderDon.getPhone()));
-        data.setKeyword2(new WxMpTemplateData(DateUtil.format(registerOrderDon.getCreatedTime(), "yyyy-MM-dd HH:mm:ss")));
-        weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
     }
 
 }

+ 27 - 4
netflix-service/src/main/java/com/cyksj/service/template/TemplateCommonService.java

@@ -1,9 +1,8 @@
 package com.cyksj.service.template;
 
-import com.cyksj.model.entity.GoodsDon;
-import com.cyksj.model.entity.GoodsDonSku;
-import com.cyksj.model.entity.OrderDon;
-import com.cyksj.model.entity.User;
+import com.cyksj.model.entity.*;
+import com.cyksj.model.manage.request.ReqSetLogisticsPost;
+import com.cyksj.model.views.WxAppTemplateView;
 
 /*
  *项目名: netflix
@@ -21,4 +20,28 @@ public interface TemplateCommonService {
 	 * 公众号扫描登录成功模板消息
 	 */
 	void sendWxGzhQrCodeSuccessMsg(User user) throws Exception;
+
+	/**
+	 * 获取发送模板消息的公众号
+	 */
+	WxAppTemplateView getWxAppByUserId(Long userId, String templateMark);
+
+	/**
+	 * 发货通知模板消息
+	 */
+	void sendTransportMsgNotify(OrderDon orderDon, ReqSetLogisticsPost reqSetLogisticsPost) throws Exception;
+
+	/**
+	 * 空车位通知模板
+	 */
+	void emptySendMsgNotify(OrderDon orderDon, String toPeople) throws Exception;
+
+	/**
+	 * 账号修改密码通知模板
+	 */
+	void sendAccountTemplateMsg(Account account) throws Exception;
+
+	/**
+	 * Spotify账号到期通知模板
+	 */
 }

+ 168 - 26
netflix-service/src/main/java/com/cyksj/service/template/impl/TemplateCommonServiceImpl.java

@@ -2,22 +2,35 @@ package com.cyksj.service.template.impl;
 
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.EnvCommonService;
 import com.cyksj.common.constant.TemplateEnum;
+import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
+import com.cyksj.config.WeChatConfig;
+import com.cyksj.mapper.GoodsDonMapper;
+import com.cyksj.mapper.GoodsDonSkuMapper;
+import com.cyksj.mapper.OrderDonTransportMapper;
+import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.gzh.UserGzhRelationMapper;
 import com.cyksj.model.dto.WxMpTemplateData;
 import com.cyksj.model.dto.WxMpTemplateMessage;
-import com.cyksj.model.entity.GoodsDon;
-import com.cyksj.model.entity.GoodsDonSku;
-import com.cyksj.model.entity.OrderDon;
-import com.cyksj.model.entity.User;
+import com.cyksj.model.entity.*;
+import com.cyksj.model.manage.request.ReqSetLogisticsPost;
+import com.cyksj.model.manage.views.GroupsRelationView;
+import com.cyksj.model.views.WxAppTemplateView;
 import com.cyksj.service.template.TemplateCommonService;
 import com.cyksj.service.wechat.WeChatService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapBuilder;
+import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
+import java.util.List;
 
 /*
  *项目名: netflix
@@ -33,38 +46,74 @@ public class TemplateCommonServiceImpl implements TemplateCommonService {
 
 	private final WeChatService weChatService;
 
+	private final BeanSearcher beanSearcher;
+
+	private final UserGzhRelationMapper userGzhRelationMapper;
+
+	private final WeChatConfig weChatConfig;
+
+	private final UserMapper userMapper;
+
+	private final GoodsDonMapper goodsDonMapper;
+
+	private final OrderDonTransportMapper transportMapper;
+
+	private final GoodsDonSkuMapper goodsDonSkuMapper;
+
 	public void newOderSendMsgByType(OrderDon order, GoodsDon goodsDon, GoodsDonSku sku, User user, String toPeople) throws Exception {
-		TemplateEnum templateEnum = null;
-		if (EnvCommonService.active.equals(envCommonService.getEnv())) {
-			return;
+		if (!EnvCommonService.active.equals(envCommonService.getEnv())) {
+			Long userId = order.getUserId();
+			WxAppTemplateView wxAppTemplateView = this.getWxAppByUserId(userId, TemplateEnum.NEW_ORDER_TEMPLATE.getDesc());
+			if (wxAppTemplateView != null) {
+				WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
+						.setToUser(toPeople)
+						.setTemplateId(wxAppTemplateView.getTemplateId())
+						//TODO
+						.setUrl(" ");
+				WxMpTemplateMessage.TemplateData data = templateMessage.getData();
+				data.setFirst(new WxMpTemplateData("新订单通知!"));
+				data.setKeyword1(new WxMpTemplateData(order.getOrderNo()));
+				data.setKeyword2(new WxMpTemplateData(String.format("%s,%s", goodsDon.getTitle(), sku.getSpecVal())));
+				data.setKeyword3(new WxMpTemplateData(user == null ? "推广未登录用户" : user.getNickname()));
+				data.setKeyword4(new WxMpTemplateData(order.getMoney().divide(BigDecimal.valueOf(100)).toString()));
+				data.setKeyword5(new WxMpTemplateData(DateUtil.format(order.getCreatedTime(), "yyyy-MM-dd HH:mm:ss")));
+				data.setRemark(new WxMpTemplateData("点击查看详情"));
+				weChatService.sendTemplateMessage(weChatService.getAccessToken(wxAppTemplateView.getAppId()), Jsons.toJson(templateMessage));
+			}
+		}
+	}
+
+	@Override
+	public WxAppTemplateView getWxAppByUserId(Long userId, String templateMark) {
+		UserGzhRelation userGzhRelation = userGzhRelationMapper.selectOne(Wrappers.lambdaQuery(UserGzhRelation.class)
+				.eq(UserGzhRelation::getUserId, userId).last("limit 1"));
+		MapBuilder builder = MapUtils.builder()
+				.field(WxAppTemplateView::getRemark, templateMark);
+		if (userGzhRelation == null) {
+			builder.field(WxAppTemplateView::getAppId, weChatConfig.getAppid());
 		}else {
-			templateEnum = TemplateEnum.NEW_ORDER_PRD_TEMPLATE;
+			builder.field(WxAppTemplateView::getWxAppId, userGzhRelation.getWxAppId());
+		}
+		String type;
+		if (EnvCommonService.active.equals(envCommonService.getEnv())) {
+			type = EnvCommonService.active;
+		} else {
+			type = EnvCommonService.active_prd;
 		}
-		WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
-				.setToUser(toPeople)
-				.setTemplateId(templateEnum.getTemplateId())
-				//TODO
-				.setUrl(" ");
-		WxMpTemplateMessage.TemplateData data = templateMessage.getData();
-		data.setFirst(new WxMpTemplateData("新订单通知!"));
-		data.setKeyword1(new WxMpTemplateData(order.getOrderNo()));
-		data.setKeyword2(new WxMpTemplateData(String.format("%s,%s", goodsDon.getTitle(), sku.getSpecVal())));
-		data.setKeyword3(new WxMpTemplateData(user == null ? "推广未登录用户" : user.getNickname()));
-		data.setKeyword4(new WxMpTemplateData(order.getMoney().divide(BigDecimal.valueOf(100)).toString()));
-		data.setKeyword5(new WxMpTemplateData(DateUtil.format(order.getCreatedTime(), "yyyy-MM-dd HH:mm:ss")));
-		data.setRemark(new WxMpTemplateData("点击查看详情"));
-		weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
+		builder.field(WxAppTemplateView::getType, type);
+		return beanSearcher.searchFirst(WxAppTemplateView.class, builder.build());
 	}
 
 	@Override
 	public void sendWxGzhQrCodeSuccessMsg(User user) throws Exception {
 		if (!EnvCommonService.active.equals(envCommonService.getEnv())) {
-			TemplateEnum templateEnum = TemplateEnum.WX_GZH_QR_CODE_LOGIN;
+			Long userId = user.getId();
+			WxAppTemplateView wxAppTemplateView = this.getWxAppByUserId(userId, TemplateEnum.WX_GZH_QR_CODE_LOGIN.getDesc());
+			String url = String.format("%sauth/weChat?url=%s", envCommonService.getHost(), envCommonService.getDomain() + "yinhe/web/");
 			WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
 					.setToUser(user.getOpenId())
-					.setTemplateId(templateEnum.getTemplateId())
-					//TODO
-					.setUrl(" ");
+					.setTemplateId(wxAppTemplateView.getTemplateId())
+					.setUrl(url);
 			WxMpTemplateMessage.TemplateData data = templateMessage.getData();
 			data.setFirst(new WxMpTemplateData("您已登录成功"));
 			data.setKeyword1(new WxMpTemplateData("银河录像局"));
@@ -73,4 +122,97 @@ public class TemplateCommonServiceImpl implements TemplateCommonService {
 			weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
 		}
 	}
+
+	@Override
+	public void sendTransportMsgNotify(OrderDon orderDon, ReqSetLogisticsPost reqSetLogisticsPost) throws Exception {
+		if (!EnvCommonService.active.equals(envCommonService.getEnv())) {
+			Long userId = orderDon.getUserId();
+			WxAppTemplateView wxAppTemplateView = this.getWxAppByUserId(userId, TemplateEnum.ORDER_TRANSPORT_TEMPLATE.getDesc());
+			if (wxAppTemplateView != null) {
+				String openId = orderDon.getOpenId();
+				if (openId == null) {
+					User u = userMapper.selectById(orderDon.getUserId());
+					if (u == null) {
+						throw BusinessRuntimeException.getInstance("用户不存在");
+					}
+					openId = u.getOpenId();
+				}
+				WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
+						.setToUser(openId)
+						.setTemplateId(wxAppTemplateView.getTemplateId())
+						//TODO
+						.setUrl(" ");
+				GoodsDon goodsDon = goodsDonMapper.selectById(orderDon.getGoodsId());
+				OrderDonTransport transport = transportMapper.selectOne(Wrappers.lambdaQuery(OrderDonTransport.class).eq(OrderDonTransport::getOrderId, reqSetLogisticsPost.getOrderId()).last("limit 1"));
+				WxMpTemplateMessage.TemplateData data = templateMessage.getData();
+				data.setFirst(new WxMpTemplateData("订单发货通知"));
+				data.setKeyword1(new WxMpTemplateData(orderDon.getOrderNo()));
+				data.setKeyword2(new WxMpTemplateData(goodsDon.getTitle()));
+				data.setKeyword3(new WxMpTemplateData(reqSetLogisticsPost.getCodeCn()));
+				data.setKeyword4(new WxMpTemplateData(reqSetLogisticsPost.getTrackingNumber()));
+				data.setKeyword5(new WxMpTemplateData(String.format("%s%s%s%s", transport.getProvince(), transport.getCity(), transport.getDistrict(), transport.getAddress())));
+				data.setRemark(new WxMpTemplateData("可复制运单编号查询物流信息"));
+				weChatService.sendTemplateMessage(weChatService.getAccessToken(wxAppTemplateView.getAppId()), Jsons.toJson(templateMessage));
+			}
+		}
+	}
+
+	@Override
+	public void emptySendMsgNotify(OrderDon orderDon, String toPeople) throws Exception {
+		if (!EnvCommonService.active.equals(envCommonService.getEnv())) {
+			Long userId = orderDon.getUserId();
+			WxAppTemplateView wxAppTemplateView = this.getWxAppByUserId(userId, TemplateEnum.EMPTY_TEMPLATE.getDesc());
+			if (wxAppTemplateView != null) {
+				User u = userMapper.selectById(orderDon.getUserId());
+				WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
+						.setToUser(toPeople)
+						.setTemplateId(wxAppTemplateView.getTemplateId())
+						//TODO
+						.setUrl(" ");
+				GoodsDon goodsDon = goodsDonMapper.selectById(orderDon.getGoodsId());
+				GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
+				WxMpTemplateMessage.TemplateData data = templateMessage.getData();
+				data.setFirst(new WxMpTemplateData("空车位通知!"));
+				data.setKeyword1(new WxMpTemplateData(orderDon.getOrderNo()));
+				data.setKeyword2(new WxMpTemplateData(String.format("%s,%s", goodsDon.getTitle(), goodsDonSku.getSpecVal())));
+				data.setKeyword3(new WxMpTemplateData((u == null ? " " : u.getNickname())));
+				data.setKeyword4(new WxMpTemplateData(orderDon.getMoney().divide(BigDecimal.valueOf(100)).toString()));
+				data.setKeyword5(new WxMpTemplateData(DateUtil.format(orderDon.getCreatedTime(), "yyyy-MM-dd HH:mm:ss")));
+				data.setRemark(new WxMpTemplateData("请尽快关联账号信息"));
+				weChatService.sendTemplateMessage(weChatService.getAccessToken(wxAppTemplateView.getAppId()), Jsons.toJson(templateMessage));
+			}
+		}
+	}
+
+	@Override
+	public void sendAccountTemplateMsg(Account account) throws Exception {
+		if (!EnvCommonService.active.equals(envCommonService.getEnv())) {
+			List<GroupsRelationView> relations = beanSearcher.searchList(GroupsRelationView.class, MapUtils.builder()
+					.field(GroupsRelationView::getAccountId, account.getId()).op(Operator.Equal)
+					.field(GroupsRelationView::getStatus, "validity").op(Operator.Equal)
+					.build());
+			String url = String.format("%sauth/weChat?url=%syinhe/web/ticket", envCommonService.getHost(), envCommonService.getDomain());
+			log.info("开始发送账号修改密码模板消息,大小:{}", relations.size());
+			for (GroupsRelationView relation : relations) {
+				Long userId = relation.getUserId();
+				WxAppTemplateView wxAppTemplateView = this.getWxAppByUserId(userId, TemplateEnum.PLAT_ACCOUNT_UPDATE_TEMPLATE.getDesc());
+				if (wxAppTemplateView != null) {
+					User user = userMapper.selectById(relation.getUserId());
+					if (user != null) {
+						WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
+								.setToUser(user.getOpenId())
+								.setTemplateId(wxAppTemplateView.getTemplateId())
+								.setUrl(url);
+						WxMpTemplateMessage.TemplateData data = templateMessage.getData();
+						data.setFirst(new WxMpTemplateData(String.format("%s账号密码更改提醒", relation.getTitle())));
+						data.setKeyword1(new WxMpTemplateData(relation.getTripsAccount()));
+						data.setKeyword2(new WxMpTemplateData(DateTime.now().toString("YYYY-MM-mm HH:mm:ss")));
+						data.setRemark(new WxMpTemplateData("您的账号密码已经更新,请到我的车票查看,长期用户请选择拼车/年付。\n" +
+								"如您不是在公众号购买,请在浏览器登录查看我的车票"));
+						weChatService.sendTemplateMessage(weChatService.getAccessToken(wxAppTemplateView.getAppId()), Jsons.toJson(templateMessage));
+					}
+				}
+			}
+		}
+	}
 }

+ 11 - 33
netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java

@@ -5,23 +5,20 @@ import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.cyksj.common.constant.TaskTypeEnum;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.config.WeChatConfig;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.UserTransferLogMapper;
 import com.cyksj.mapper.WxSyncLogMapper;
-import com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper;
-import com.cyksj.mapper.market.task.TaskTypeMapper;
 import com.cyksj.model.dto.GzhOAuth2UserInfo;
 import com.cyksj.model.dto.UserWhoami;
-import com.cyksj.model.entity.*;
-import com.cyksj.service.market.task.TaskService;
+import com.cyksj.model.entity.User;
+import com.cyksj.model.entity.UserTransferLog;
+import com.cyksj.model.entity.WxSyncLog;
+import com.cyksj.service.distribute.DistributeService;
 import com.cyksj.service.user.UserService;
-import com.cyksj.service.wechat.WeChatService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
 import org.springframework.util.Assert;
 
@@ -35,22 +32,14 @@ import java.util.Optional;
 @Service
 @RequiredArgsConstructor
 public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
-
-
-    private final WeChatService weChatService;
-
-    private final UserDistributeSharedMapper userDistributeSharedMapper;
-
-    private final TaskService taskService;
-
-    private final TaskTypeMapper taskTypeMapper;
-
     private final WeChatConfig weChatConfig;
 
     private final UserTransferLogMapper userTransferLogMapper;
 
     private final WxSyncLogMapper wxSyncLogMapper;
 
+    private final DistributeService distributeService;
+
     @Override
     public User saveAuth(GzhOAuth2UserInfo info, Long sharedId) {
         final String unionid = info.getUnionid();
@@ -104,25 +93,14 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
         }
         user.setUnionid(unionid);
         user.setOpenId(info.getOpenid());
-        UserDistributeShared userDistributeShared = null;
+
+        Boolean isNewUser = false;
         if (user.getId() == null) {
-            User shared = this.getById(sharedId);
-            if (shared != null) {
-                userDistributeShared = new UserDistributeShared();
-                userDistributeShared.setSharedId(sharedId);
-            }
+            isNewUser = true;
         }
         this.saveOrUpdate(user);
-        if (userDistributeShared != null) {
-            userDistributeShared.setUserId(user.getId());
-            try {
-                userDistributeSharedMapper.insert(userDistributeShared);
-                TaskType taskType = taskTypeMapper.selectOne(Wrappers.lambdaQuery(TaskType.class)
-                        .eq(TaskType::getName, TaskTypeEnum.share.getDesc()).last("limit 1"));
-                taskService.completeTask(taskType, sharedId);
-            } catch (DuplicateKeyException e) {
-                log.info("分销被邀请人重复插入");
-            }
+        if (sharedId != null && isNewUser) {
+            distributeService.saveDistributionInvitation(sharedId, user.getId());
         }
         return user;
     }

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/wechat/WeChatService.java

@@ -77,5 +77,5 @@ public interface WeChatService {
      * 获取公众号带参数的二维码
      * @return
      */
-    WxGzhQrCodeTicketRep getWxGzhQrCode() throws Exception;
+    WxGzhQrCodeTicketRep getWxGzhQrCode(Long sharedId) throws Exception;
 }

+ 6 - 2
netflix-service/src/main/java/com/cyksj/service/wechat/impl/WeChatServiceImpl.java

@@ -479,12 +479,12 @@ public class WeChatServiceImpl implements WeChatService {
     }
 
     @Override
-    public WxGzhQrCodeTicketRep getWxGzhQrCode() throws Exception {
+    public WxGzhQrCodeTicketRep getWxGzhQrCode(Long sharedId) throws Exception {
         String gzhQrCodeUrl = String.format("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s", this.getAccessToken());
         //scene_str:场景值ID(字符串形式的ID),字符串类型,长度限制为1到64
         String scene_str = RandomUtil.randomString(16);
         DateTime dateTime = DateUtil.offsetSecond(DateTime.now(), 60);
-        String body = String.format("{\"expire_seconds\": %s, \"action_name\": \"%s\", \"action_info\": {\"scene\": {\"scene_str\": %s}}}",
+        String body = String.format("{\"expire_seconds\": %s, \"action_name\": \"%s\", \"action_info\": {\"scene\": {\"scene_str\": \"%s\"}}}",
                 60,
                 "QR_STR_SCENE",
                 scene_str);
@@ -497,6 +497,10 @@ public class WeChatServiceImpl implements WeChatService {
             throw BusinessRuntimeException.getInstance("获取微信登录二维码失败: " + response.body());
         }
 
+        if (sharedId != null) {
+            redisService.set(RedisService.key.WX_GZH_QRCODE_SHARED_LOGIN.getNameFormat(scene_str), sharedId, RedisService.key.WX_GZH_QRCODE_SHARED_LOGIN.getTimeout());
+        }
+
         JSONObject re = Jsons.parseObject(response.body(), JSONObject.class);
         String ticket = re.getStr("ticket");
         WxGzhQrCodeTicketRep wxGzhQrCodeTicketRep = new WxGzhQrCodeTicketRep();

+ 52 - 45
netflix-service/src/main/java/com/cyksj/task/Scheduler.java

@@ -4,6 +4,7 @@ import cn.hutool.core.date.DateField;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.constant.TemplateEnum;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.dto.RedisKey;
@@ -12,10 +13,12 @@ import com.cyksj.mapper.manage.distribute.DistributeWaitingSendPointsMapper;
 import com.cyksj.model.dto.WxMpTemplateData;
 import com.cyksj.model.dto.WxMpTemplateMessage;
 import com.cyksj.model.entity.*;
+import com.cyksj.model.views.WxAppTemplateView;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.order.OrderDonService;
 import com.cyksj.service.register.RegisterOrderDonService;
 import com.cyksj.service.register.SpotifyService;
+import com.cyksj.service.template.TemplateCommonService;
 import com.cyksj.service.wechat.WeChatService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -27,8 +30,6 @@ import org.springframework.transaction.annotation.Transactional;
 import java.util.*;
 import java.util.stream.Collectors;
 
-import static com.cyksj.common.constant.WeChatTemplateConst.EXPIRY_TEMPLATE;
-
 @Component
 @Slf4j
 @RequiredArgsConstructor
@@ -68,6 +69,8 @@ public class Scheduler {
 
         private final RealGoodsInterestUserMapper realGoodsInterestUserMapper;
 
+        private final TemplateCommonService templateCommonService;
+
 
     /**
      * 每5分钟清理过期账号
@@ -90,49 +93,53 @@ public class Scheduler {
         List<GroupsRelation> groupsRelations = groupsRelationMapper.selectList(Wrappers.lambdaQuery(GroupsRelation.class).le(GroupsRelation::getExpiryTime, time));
         for (GroupsRelation relation : groupsRelations) {
             User user = userMapper.selectById(relation.getUserId());
-            WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
-                    .setToUser(user.getOpenId())
-                    .setTemplateId(EXPIRY_TEMPLATE)
-                    .setUrl(" ");
-
-            /**
-             * 您的账号即将到期
-             * 账号名称:Netflix账号
-             * 平台:Netflix
-             * 失效日期:5天后
-             * 异常原因:账号即将到期
-             * 请尽快续费,以免影响使用
-             */
-            GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
-            GoodsDonSku donSku = skuMapper.selectById(groupsTrips.getSkuId());
-            GoodsDon goodsDon = donMapper.selectById(donSku.getGoodsId());
-            WxMpTemplateMessage.TemplateData data = templateMessage.getData();
-            data.setFirst(new WxMpTemplateData("您的账号即将到期"));
-            data.setKeyword1(new WxMpTemplateData(goodsDon.getTitle()));
-            data.setKeyword2(new WxMpTemplateData(goodsDon.getTitle()));
-            data.setKeyword3(new WxMpTemplateData(DateUtil.format(relation.getExpiryTime(), "yyyy-MM-dd HH:mm:ss")));
-            data.setKeyword4(new WxMpTemplateData("账号即将到期"));
-            data.setRemark(new WxMpTemplateData("请尽快续费,以免影响使用"));
-            log.info("发送账号即将到期消息至用户:{}", user.getId());
-            weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
-
-            List<Account> accounts = accountMapper.selectList(Wrappers.lambdaQuery(Account.class).le(Account::getExpiryTime, time));
-            List<CustomerService> customerServices = customerServiceMapper.selectList(null);
-            if(!accounts.isEmpty()){
-                for (CustomerService customerService : customerServices) {
-                    WxMpTemplateMessage manageMessage = new WxMpTemplateMessage()
-                            .setToUser(customerService.getOpenId())
-                            .setTemplateId(EXPIRY_TEMPLATE)
-                            .setUrl(" ");
-                    WxMpTemplateMessage.TemplateData data2 = manageMessage.getData();
-                    data2.setFirst(new WxMpTemplateData("您有" + accounts.size() + "个主账号即将到期"));
-                    data2.setKeyword1(new WxMpTemplateData("车队主账号"));
-                    data2.setKeyword2(new WxMpTemplateData("车队主账号"));
-                    data2.setKeyword3(new WxMpTemplateData("5天后"));
-                    data2.setKeyword4(new WxMpTemplateData("账号即将到期"));
-                    data2.setRemark(new WxMpTemplateData("请尽快登录后台-在账号管理中查看"));
-                    log.info("发送账号即将到期消息至客服:{}", customerService.getNickName());
-                    weChatService.sendTemplateMessage(weChatService.getAccessToken(),Jsons.toJson(manageMessage));
+            Long userId = user.getId();
+            WxAppTemplateView wxAppTemplateView = templateCommonService.getWxAppByUserId(userId, TemplateEnum.EXPIRY_TEMPLATE.getDesc());
+            if (wxAppTemplateView != null) {
+                WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
+                        .setToUser(user.getOpenId())
+                        .setTemplateId(wxAppTemplateView.getTemplateId())
+                        .setUrl(" ");
+
+                /**
+                 * 您的账号即将到期
+                 * 账号名称:Netflix账号
+                 * 平台:Netflix
+                 * 失效日期:5天后
+                 * 异常原因:账号即将到期
+                 * 请尽快续费,以免影响使用
+                 */
+                GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
+                GoodsDonSku donSku = skuMapper.selectById(groupsTrips.getSkuId());
+                GoodsDon goodsDon = donMapper.selectById(donSku.getGoodsId());
+                WxMpTemplateMessage.TemplateData data = templateMessage.getData();
+                data.setFirst(new WxMpTemplateData("您的账号即将到期"));
+                data.setKeyword1(new WxMpTemplateData(goodsDon.getTitle()));
+                data.setKeyword2(new WxMpTemplateData(goodsDon.getTitle()));
+                data.setKeyword3(new WxMpTemplateData(DateUtil.format(relation.getExpiryTime(), "yyyy-MM-dd HH:mm:ss")));
+                data.setKeyword4(new WxMpTemplateData("账号即将到期"));
+                data.setRemark(new WxMpTemplateData("请尽快续费,以免影响使用"));
+                log.info("发送账号即将到期消息至用户:{}", user.getId());
+                weChatService.sendTemplateMessage(weChatService.getAccessToken(wxAppTemplateView.getAppId()), Jsons.toJson(templateMessage));
+
+                List<Account> accounts = accountMapper.selectList(Wrappers.lambdaQuery(Account.class).le(Account::getExpiryTime, time));
+                List<CustomerService> customerServices = customerServiceMapper.selectList(null);
+                if(!accounts.isEmpty()){
+                    for (CustomerService customerService : customerServices) {
+                        WxMpTemplateMessage manageMessage = new WxMpTemplateMessage()
+                                .setToUser(customerService.getOpenId())
+                                .setTemplateId(wxAppTemplateView.getTemplateId())
+                                .setUrl(" ");
+                        WxMpTemplateMessage.TemplateData data2 = manageMessage.getData();
+                        data2.setFirst(new WxMpTemplateData("您有" + accounts.size() + "个主账号即将到期"));
+                        data2.setKeyword1(new WxMpTemplateData("车队主账号"));
+                        data2.setKeyword2(new WxMpTemplateData("车队主账号"));
+                        data2.setKeyword3(new WxMpTemplateData("5天后"));
+                        data2.setKeyword4(new WxMpTemplateData("账号即将到期"));
+                        data2.setRemark(new WxMpTemplateData("请尽快登录后台-在账号管理中查看"));
+                        log.info("发送账号即将到期消息至客服:{}", customerService.getNickName());
+                        weChatService.sendTemplateMessage(weChatService.getAccessToken(wxAppTemplateView.getAppId()),Jsons.toJson(manageMessage));
+                    }
                 }
             }
         }

+ 2 - 1
netflix-web/src/main/java/com/cyksj/config/SaTokenConfigure.java

@@ -26,7 +26,8 @@ public class SaTokenConfigure implements WebMvcConfigurer {
 						"/manage/coupon/corp/send",
 						"/manage/coupon",
 						"/manage/register/wx/refund/notify",
-						"/manage/register/unLimit"));
+						"/manage/register/unLimit",
+						"/manage/gzh/msg/notify"));
 	}
 }
 

+ 4 - 1
netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java

@@ -21,6 +21,7 @@ import com.cyksj.model.excel.ExcelManageAccountData;
 import com.cyksj.model.manage.request.ReqAccountIncrExpiryTime;
 import com.cyksj.model.manage.views.AccountView;
 import com.cyksj.service.mange.CmsAccountService;
+import com.cyksj.service.template.TemplateCommonService;
 import com.cyksj.web.util.EasyExcelUtils;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
@@ -58,6 +59,8 @@ public class CmsAccountController {
 
     private final GroupsMapper groupsMapper;
 
+	private final TemplateCommonService templateCommonService;
+
     @GetMapping("/get")
     public Result<SearchResult<AccountView>> get(Long userId ,String nickName ,String submitAccount ,String expiryStartTime, String expiryEndTime) {
         MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
@@ -143,7 +146,7 @@ public class CmsAccountController {
 							account.setPassword(data.getPassword());
 							flag = true;
 							//发放模板消息
-							accountService.sendAccountTemplateMsg(account);
+							templateCommonService.sendAccountTemplateMsg(account);
 						}
 						if (flag) {
 							accountService.updateById(account);

+ 68 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/gzh/GzhController.java

@@ -0,0 +1,68 @@
+package com.cyksj.web.controller.manage.gzh;
+
+import cn.hutool.core.util.StrUtil;
+import com.cyksj.common.util.IoKit;
+import com.cyksj.common.util.StringUtil;
+import com.cyksj.common.util.Xmls;
+import com.cyksj.model.dto.MsgEvent;
+import com.cyksj.service.gzh.GzhService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+/*
+ *项目名: netflix
+ *文件名: GzhController
+ *创建者: JavaZou
+ *创建时间:2023/1/13 16:50
+ */
+@RestController
+@RequestMapping("/manage/gzh")
+@RequiredArgsConstructor
+@Slf4j
+public class GzhController {
+	private final HttpServletRequest request;
+
+	private final GzhService gzhService;
+
+	@RequestMapping(value = "/msg/notify", method = {RequestMethod.GET, RequestMethod.POST})
+	public String msgNotify(@RequestParam(value = "echostr", required = false) String echoStr) throws IOException {
+		if (StrUtil.endWithIgnoreCase(request.getMethod(), RequestMethod.GET.name())) {
+			if (StrUtil.isBlank(echoStr)) {
+				return StrUtil.EMPTY;
+			}
+			//验证消息推送URL是否正确
+			return echoStr;
+		}
+
+		String content = IoKit.toString(request.getInputStream(), IoKit.Charsets.UTF_8);
+		log.info("公众号消息推送通知: \n{}", content);
+
+		if (StringUtils.isBlank(content)) {
+			return StringUtil.EMPTY;
+		}
+		MsgEvent msgEvent;
+		try {
+			msgEvent = Xmls.parseObject(content, MsgEvent.class);
+		} catch (Exception e) {
+			log.warn(" ! 解析公众号推送XML 失败.");
+			return "";
+		}
+		if (null == msgEvent) {
+			return "";
+		}
+
+		if (msgEvent.getMsgType() == null) {
+			return "";
+		}
+
+		return gzhService.gzhMsg(msgEvent);
+	}
+}

+ 15 - 40
netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java

@@ -10,7 +10,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.EnvCommonService;
 import com.cyksj.common.annotation.NoSubmit;
-import com.cyksj.common.constant.TaskTypeEnum;
+import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.snowflake.Sequence;
 import com.cyksj.common.util.Codec;
@@ -22,24 +22,18 @@ import com.cyksj.config.wxlogin.WxOpenPlatYHLXLoginConfig;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.PhoneCodeMapper;
-import com.cyksj.mapper.WxAppMapper;
-import com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper;
-import com.cyksj.mapper.market.task.TaskTypeMapper;
 import com.cyksj.model.dto.AuthRedirect;
 import com.cyksj.model.dto.AuthToken;
 import com.cyksj.model.dto.GzhOAuth2UserInfo;
 import com.cyksj.model.dto.JsSdkTicket;
 import com.cyksj.model.entity.PhoneCode;
-import com.cyksj.model.entity.TaskType;
 import com.cyksj.model.entity.User;
-import com.cyksj.model.entity.UserDistributeShared;
 import com.cyksj.model.request.LoginPhoneReq;
 import com.cyksj.model.response.LoginPhoneRep;
 import com.cyksj.model.response.WxGzhQrCodeTicketRep;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.authorization.AuthorizationService;
-import com.cyksj.service.market.task.TaskService;
-import com.cyksj.service.order.OrderDonService;
+import com.cyksj.service.distribute.DistributeService;
 import com.cyksj.service.template.TemplateCommonService;
 import com.cyksj.service.user.UserService;
 import com.cyksj.service.wechat.WeChatService;
@@ -48,7 +42,6 @@ import com.cyksj.web.util.StpUserUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
-import org.springframework.dao.DuplicateKeyException;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
@@ -81,8 +74,6 @@ public class AuthorizationController {
 
     private final WeChatService weChatService;
 
-    private final WxAppMapper wxAppMapper;
-
     private final WeChatConfig weChatConfig;
 
     private final RedisService redisService;
@@ -91,20 +82,14 @@ public class AuthorizationController {
 
     private final EnvCommonService envCommonService;
 
-    private final OrderDonService orderDonService;
-
     private final PhoneCodeMapper phoneCodeMapper;
 
-    private final UserDistributeSharedMapper userDistributeSharedMapper;
-
-    private final TaskService taskService;
-
-    private final TaskTypeMapper taskTypeMapper;
-
     private final MailService mailService;
 
     private final TemplateCommonService templateCommonService;
 
+    private final DistributeService distributeService;
+
     @GetMapping(value = "/weChat")
     public void base(String url,Long sharedId, String authType, HttpServletResponse response) throws Exception {
 
@@ -262,9 +247,9 @@ public class AuthorizationController {
      * 网页扫描微信公众号二维码 临时凭证ticket  关注后登录
      */
     @GetMapping("/wx/gzh/login/qrCode")
-    public Result<WxGzhQrCodeTicketRep> getWxGzhQrCode() throws Exception {
+    public Result<WxGzhQrCodeTicketRep> getWxGzhQrCode(Long sharedId) throws Exception {
         //获取gzh带参数的二维码
-        WxGzhQrCodeTicketRep result = weChatService.getWxGzhQrCode();
+        WxGzhQrCodeTicketRep result = weChatService.getWxGzhQrCode(sharedId);
         return GatewayResponse.SUCCESS.newBuilder().toResult(result);
     }
 
@@ -273,10 +258,14 @@ public class AuthorizationController {
      */
     @GetMapping("/wx/gzh/sceneStr/checkQrCode")
     public Result<String> checkQrCodeByGzhSceneStr(String sceneStr) throws Exception {
-        Long userId = (Long) redisService.get(RedisService.key.WX_GZH_QRCODE_LOGIN.getNameFormat(sceneStr));
-        if (userId == null) {
+        String key = RedisService.key.WX_GZH_QRCODE_LOGIN.getNameFormat(sceneStr);
+        Object value = redisService.get(key);
+        if (value == null) {
             return GatewayResponse.SUCCESS.newBuilder().setMsg("用户未扫码").toResult();
         }
+        Long userId = Long.parseLong(value.toString());
+
+        redisService.del(key);
         User user = userService.getById(userId);
         StpUserUtil.login(userId);
         String token = StpUserUtil.getTokenValue();
@@ -388,7 +377,6 @@ public class AuthorizationController {
         }
         //保存用户信息
         User user = userService.getOne(wrapper);
-        UserDistributeShared userDistributeShared = null;
         Long sharedId = loginPhoneReq.getSharedId();
         if (user == null) {
             user = new User();
@@ -400,35 +388,22 @@ public class AuthorizationController {
             } else if (loginPhoneReq.getType() == 2) {
                 user.setEmail(loginPhoneReq.getEmail());
             }
-            String name = "银河用户";
+            String name = Constant.DEFAULT_NAME;
             if (loginPhoneReq.getType() == 2) {
                 name += "@";
             }
             user.setNickname(String.format("%s%s", name, Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.MD5).setStringData(String.format("%s%s", user.getId(), loginPhoneReq.getType() == 1 ? user.getLoginPhone() : user.getEmail())).toHexString().substring(0, 6)));
             //默认头像
-            user.setHeadimgurl("https://cdn.sxfoundation.com/picture/f6ee11101c4f5f0bc48d88aca7a5dbfd-1666945673391.png");
+            user.setHeadimgurl(Constant.DEFAULT_HEAD_IMG);
             userService.save(user);
             //新用户分销
             if (sharedId != null) {
-                userDistributeShared = new UserDistributeShared();
-                userDistributeShared.setSharedId(loginPhoneReq.getSharedId());
+                distributeService.saveDistributionInvitation(sharedId, user.getId());
             }
         }
         //写回登陆信息
         StpUserUtil.login(user.getId());
         LoginPhoneRep loginPhoneRep = new LoginPhoneRep(StpUserUtil.getTokenValue(), user.getId(), user.getNickname(), user.getHeadimgurl());
-        //存在分销
-        if (userDistributeShared != null) {
-            userDistributeShared.setUserId(user.getId());
-            try {
-                userDistributeSharedMapper.insert(userDistributeShared);
-                TaskType taskType = taskTypeMapper.selectOne(Wrappers.lambdaQuery(TaskType.class)
-                        .eq(TaskType::getName, TaskTypeEnum.share.getDesc()).last("limit 1"));
-                taskService.completeTask(taskType, sharedId);
-            } catch (DuplicateKeyException e) {
-                log.info("分销被邀请人重复插入");
-            }
-        }
         return GatewayResponse.SUCCESS.newBuilder().toResult(loginPhoneRep);
     }
 }