Browse Source

mp:完成关注和取消的 user 保存

YunaiV 2 years ago
parent
commit
39d377b0bd
22 changed files with 122 additions and 716 deletions
  1. 4 1
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/open/MpOpenController.java
  2. 0 103
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/subscribetext/WxSubscribeTextController.java
  3. 0 22
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/subscribetext/vo/WxSubscribeTextBaseVO.java
  4. 0 12
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/subscribetext/vo/WxSubscribeTextCreateReqVO.java
  5. 0 32
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/subscribetext/vo/WxSubscribeTextExcelVO.java
  6. 0 33
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/subscribetext/vo/WxSubscribeTextExportReqVO.java
  7. 0 36
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/subscribetext/vo/WxSubscribeTextPageReqVO.java
  8. 0 21
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/subscribetext/vo/WxSubscribeTextRespVO.java
  9. 0 18
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/subscribetext/vo/WxSubscribeTextUpdateReqVO.java
  10. 0 3
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/user/vo/MpUserBaseVO.java
  11. 0 34
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/convert/subscribetext/WxSubscribeTextConvert.java
  12. 25 0
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/convert/user/MpUserConvert.java
  13. 0 43
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/dataobject/subscribetext/WxSubscribeTextDO.java
  14. 6 9
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/dataobject/user/MpUserDO.java
  15. 5 0
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/mysql/accountfans/MpUserMapper.java
  16. 0 38
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/mysql/subscribetext/WxSubscribeTextMapper.java
  17. 17 114
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/user/SubscribeHandler.java
  18. 4 27
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/user/UnsubscribeHandler.java
  19. 0 80
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/subscribetext/WxSubscribeTextService.java
  20. 0 90
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/subscribetext/WxSubscribeTextServiceImpl.java
  21. 20 0
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/user/MpUserService.java
  22. 41 0
      yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/user/MpUserServiceImpl.java

+ 4 - 1
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/open/MpOpenController.java

@@ -100,6 +100,9 @@ public class MpOpenController {
         // 第二步,处理消息
         WxMpMessageRouter mpMessageRouter = mpServiceFactory.getRequiredMpMessageRouter(appId);
         WxMpXmlOutMessage outMessage = mpMessageRouter.route(inMessage);
+        if (outMessage == null) {
+            return "";
+        }
 
         // 第三步,返回消息
         if (StrUtil.isBlank(reqVO.getEncrypt_type())) { // 明文模式
@@ -107,7 +110,7 @@ public class MpOpenController {
         } else if (Objects.equals(reqVO.getEncrypt_type(), MpOpenHandleMessageReqVO.ENCRYPT_TYPE_AES)) { // AES 加密模式
             return outMessage.toEncryptedXml(mppService.getWxMpConfigStorage());
         }
-        return null;
+        return "";
     }
 
 }

+ 0 - 103
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/subscribetext/WxSubscribeTextController.java

@@ -1,103 +0,0 @@
-package cn.iocoder.yudao.module.mp.controller.admin.subscribetext;
-
-import org.springframework.web.bind.annotation.*;
-
-import javax.annotation.Resource;
-
-import org.springframework.validation.annotation.Validated;
-import org.springframework.security.access.prepost.PreAuthorize;
-import io.swagger.annotations.*;
-
-import javax.validation.*;
-import javax.servlet.http.*;
-import java.util.*;
-import java.io.IOException;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-
-import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
-
-import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
-
-import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
-
-import cn.iocoder.yudao.module.mp.controller.admin.subscribetext.vo.*;
-import cn.iocoder.yudao.module.mp.dal.dataobject.subscribetext.WxSubscribeTextDO;
-import cn.iocoder.yudao.module.mp.convert.subscribetext.WxSubscribeTextConvert;
-import cn.iocoder.yudao.module.mp.service.subscribetext.WxSubscribeTextService;
-
-@Api(tags = "管理后台 - 关注欢迎语")
-@RestController
-@RequestMapping("/wechatMp/wx-subscribe-text")
-@Validated
-public class WxSubscribeTextController {
-
-    @Resource
-    private WxSubscribeTextService wxSubscribeTextService;
-
-    @PostMapping("/create")
-    @ApiOperation("创建关注欢迎语")
-    @PreAuthorize("@ss.hasPermission('wechatMp:wx-subscribe-text:create')")
-    public CommonResult<Integer> createWxSubscribeText(@Valid @RequestBody WxSubscribeTextCreateReqVO createReqVO) {
-        return success(wxSubscribeTextService.createWxSubscribeText(createReqVO));
-    }
-
-    @PutMapping("/update")
-    @ApiOperation("更新关注欢迎语")
-    @PreAuthorize("@ss.hasPermission('wechatMp:wx-subscribe-text:update')")
-    public CommonResult<Boolean> updateWxSubscribeText(@Valid @RequestBody WxSubscribeTextUpdateReqVO updateReqVO) {
-        wxSubscribeTextService.updateWxSubscribeText(updateReqVO);
-        return success(true);
-    }
-
-    @DeleteMapping("/delete")
-    @ApiOperation("删除关注欢迎语")
-    @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Integer.class)
-    @PreAuthorize("@ss.hasPermission('wechatMp:wx-subscribe-text:delete')")
-    public CommonResult<Boolean> deleteWxSubscribeText(@RequestParam("id") Integer id) {
-        wxSubscribeTextService.deleteWxSubscribeText(id);
-        return success(true);
-    }
-
-    @GetMapping("/get")
-    @ApiOperation("获得关注欢迎语")
-    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Integer.class)
-    @PreAuthorize("@ss.hasPermission('wechatMp:wx-subscribe-text:query')")
-    public CommonResult<WxSubscribeTextRespVO> getWxSubscribeText(@RequestParam("id") Integer id) {
-        WxSubscribeTextDO wxSubscribeText = wxSubscribeTextService.getWxSubscribeText(id);
-        return success(WxSubscribeTextConvert.INSTANCE.convert(wxSubscribeText));
-    }
-
-    @GetMapping("/list")
-    @ApiOperation("获得关注欢迎语列表")
-    @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
-    @PreAuthorize("@ss.hasPermission('wechatMp:wx-subscribe-text:query')")
-    public CommonResult<List<WxSubscribeTextRespVO>> getWxSubscribeTextList(@RequestParam("ids") Collection<Integer> ids) {
-        List<WxSubscribeTextDO> list = wxSubscribeTextService.getWxSubscribeTextList(ids);
-        return success(WxSubscribeTextConvert.INSTANCE.convertList(list));
-    }
-
-    @GetMapping("/page")
-    @ApiOperation("获得关注欢迎语分页")
-    @PreAuthorize("@ss.hasPermission('wechatMp:wx-subscribe-text:query')")
-    public CommonResult<PageResult<WxSubscribeTextRespVO>> getWxSubscribeTextPage(@Valid WxSubscribeTextPageReqVO pageVO) {
-        PageResult<WxSubscribeTextDO> pageResult = wxSubscribeTextService.getWxSubscribeTextPage(pageVO);
-        return success(WxSubscribeTextConvert.INSTANCE.convertPage(pageResult));
-    }
-
-    @GetMapping("/export-excel")
-    @ApiOperation("导出关注欢迎语 Excel")
-    @PreAuthorize("@ss.hasPermission('wechatMp:wx-subscribe-text:export')")
-    @OperateLog(type = EXPORT)
-    public void exportWxSubscribeTextExcel(@Valid WxSubscribeTextExportReqVO exportReqVO,
-                                           HttpServletResponse response) throws IOException {
-        List<WxSubscribeTextDO> list = wxSubscribeTextService.getWxSubscribeTextList(exportReqVO);
-        // 导出 Excel
-        List<WxSubscribeTextExcelVO> datas = WxSubscribeTextConvert.INSTANCE.convertList02(list);
-        ExcelUtils.write(response, "关注欢迎语.xls", "数据", WxSubscribeTextExcelVO.class, datas);
-    }
-
-}

+ 0 - 22
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/subscribetext/vo/WxSubscribeTextBaseVO.java

@@ -1,22 +0,0 @@
-package cn.iocoder.yudao.module.mp.controller.admin.subscribetext.vo;
-
-import lombok.*;
-import io.swagger.annotations.*;
-
-/**
- * 关注欢迎语 Base VO,提供给添加、修改、详细的子 VO 使用
- * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
- */
-@Data
-public class WxSubscribeTextBaseVO {
-
-    @ApiModelProperty(value = "消息类型 1文本消息;2图文消息;")
-    private String msgType;
-
-    @ApiModelProperty(value = "模板ID")
-    private String tplId;
-
-    @ApiModelProperty(value = "微信账号ID")
-    private String wxAccountId;
-
-}

+ 0 - 12
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/subscribetext/vo/WxSubscribeTextCreateReqVO.java

@@ -1,12 +0,0 @@
-package cn.iocoder.yudao.module.mp.controller.admin.subscribetext.vo;
-
-import lombok.*;
-import io.swagger.annotations.*;
-
-@ApiModel("管理后台 - 关注欢迎语创建 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class WxSubscribeTextCreateReqVO extends WxSubscribeTextBaseVO {
-
-}

+ 0 - 32
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/subscribetext/vo/WxSubscribeTextExcelVO.java

@@ -1,32 +0,0 @@
-package cn.iocoder.yudao.module.mp.controller.admin.subscribetext.vo;
-
-import lombok.*;
-
-import java.util.*;
-
-import com.alibaba.excel.annotation.ExcelProperty;
-
-/**
- * 关注欢迎语 Excel VO
- *
- * @author 芋道源码
- */
-@Data
-public class WxSubscribeTextExcelVO {
-
-    @ExcelProperty("主键")
-    private Integer id;
-
-    @ExcelProperty("消息类型 1文本消息;2图文消息;")
-    private String msgType;
-
-    @ExcelProperty("模板ID")
-    private String tplId;
-
-    @ExcelProperty("微信账号ID")
-    private String wxAccountId;
-
-    @ExcelProperty("创建时间")
-    private Date createTime;
-
-}

+ 0 - 33
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/subscribetext/vo/WxSubscribeTextExportReqVO.java

@@ -1,33 +0,0 @@
-package cn.iocoder.yudao.module.mp.controller.admin.subscribetext.vo;
-
-import lombok.*;
-
-import java.util.*;
-
-import io.swagger.annotations.*;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@ApiModel(value = "管理后台 - 关注欢迎语 Excel 导出 Request VO", description = "参数和 WxSubscribeTextPageReqVO 是一致的")
-@Data
-public class WxSubscribeTextExportReqVO {
-
-    @ApiModelProperty(value = "消息类型 1文本消息;2图文消息;")
-    private String msgType;
-
-    @ApiModelProperty(value = "模板ID")
-    private String tplId;
-
-    @ApiModelProperty(value = "微信账号ID")
-    private String wxAccountId;
-
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @ApiModelProperty(value = "开始创建时间")
-    private Date beginCreateTime;
-
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @ApiModelProperty(value = "结束创建时间")
-    private Date endCreateTime;
-
-}

+ 0 - 36
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/subscribetext/vo/WxSubscribeTextPageReqVO.java

@@ -1,36 +0,0 @@
-package cn.iocoder.yudao.module.mp.controller.admin.subscribetext.vo;
-
-import lombok.*;
-
-import java.util.*;
-
-import io.swagger.annotations.*;
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@ApiModel("管理后台 - 关注欢迎语分页 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class WxSubscribeTextPageReqVO extends PageParam {
-
-    @ApiModelProperty(value = "消息类型 1文本消息;2图文消息;")
-    private String msgType;
-
-    @ApiModelProperty(value = "模板ID")
-    private String tplId;
-
-    @ApiModelProperty(value = "微信账号ID")
-    private String wxAccountId;
-
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @ApiModelProperty(value = "开始创建时间")
-    private Date beginCreateTime;
-
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @ApiModelProperty(value = "结束创建时间")
-    private Date endCreateTime;
-
-}

+ 0 - 21
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/subscribetext/vo/WxSubscribeTextRespVO.java

@@ -1,21 +0,0 @@
-package cn.iocoder.yudao.module.mp.controller.admin.subscribetext.vo;
-
-import lombok.*;
-
-import java.util.*;
-
-import io.swagger.annotations.*;
-
-@ApiModel("管理后台 - 关注欢迎语 Response VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class WxSubscribeTextRespVO extends WxSubscribeTextBaseVO {
-
-    @ApiModelProperty(value = "主键", required = true)
-    private Integer id;
-
-    @ApiModelProperty(value = "创建时间", required = true)
-    private Date createTime;
-
-}

+ 0 - 18
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/subscribetext/vo/WxSubscribeTextUpdateReqVO.java

@@ -1,18 +0,0 @@
-package cn.iocoder.yudao.module.mp.controller.admin.subscribetext.vo;
-
-import lombok.*;
-import io.swagger.annotations.*;
-
-import javax.validation.constraints.*;
-
-@ApiModel("管理后台 - 关注欢迎语更新 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class WxSubscribeTextUpdateReqVO extends WxSubscribeTextBaseVO {
-
-    @ApiModelProperty(value = "主键", required = true)
-    @NotNull(message = "主键不能为空")
-    private Integer id;
-
-}

+ 0 - 3
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/user/vo/MpUserBaseVO.java

@@ -31,9 +31,6 @@ public class MpUserBaseVO {
     @ApiModelProperty(value = "昵称")
     private String nickname;
 
-    @ApiModelProperty(value = "性别,1男,2女,0未知")
-    private Integer gender;
-
     @ApiModelProperty(value = "语言")
     private String language;
 

+ 0 - 34
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/convert/subscribetext/WxSubscribeTextConvert.java

@@ -1,34 +0,0 @@
-package cn.iocoder.yudao.module.mp.convert.subscribetext;
-
-import java.util.*;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
-import org.mapstruct.Mapper;
-import org.mapstruct.factory.Mappers;
-import cn.iocoder.yudao.module.mp.controller.admin.subscribetext.vo.*;
-import cn.iocoder.yudao.module.mp.dal.dataobject.subscribetext.WxSubscribeTextDO;
-
-/**
- * 关注欢迎语 Convert
- *
- * @author 芋道源码
- */
-@Mapper
-public interface WxSubscribeTextConvert {
-
-    WxSubscribeTextConvert INSTANCE = Mappers.getMapper(WxSubscribeTextConvert.class);
-
-    WxSubscribeTextDO convert(WxSubscribeTextCreateReqVO bean);
-
-    WxSubscribeTextDO convert(WxSubscribeTextUpdateReqVO bean);
-
-    WxSubscribeTextRespVO convert(WxSubscribeTextDO bean);
-
-    List<WxSubscribeTextRespVO> convertList(List<WxSubscribeTextDO> list);
-
-    PageResult<WxSubscribeTextRespVO> convertPage(PageResult<WxSubscribeTextDO> page);
-
-    List<WxSubscribeTextExcelVO> convertList02(List<WxSubscribeTextDO> list);
-
-}

+ 25 - 0
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/convert/user/MpUserConvert.java

@@ -1,9 +1,15 @@
 package cn.iocoder.yudao.module.mp.convert.user;
 
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserRespVO;
+import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
 import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO;
+import me.chanjar.weixin.mp.bean.result.WxMpUser;
 import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.Mappings;
 import org.mapstruct.factory.Mappers;
 
 import java.util.List;
@@ -19,4 +25,23 @@ public interface MpUserConvert {
 
     PageResult<MpUserRespVO> convertPage(PageResult<MpUserDO> page);
 
+    @Mappings(value = {
+            @Mapping(source = "openId", target = "openid"),
+            @Mapping(source = "headImgUrl", target = "headImageUrl"),
+            @Mapping(target = "subscribeTime", ignore = true), // 单独转换
+    })
+    MpUserDO convert(WxMpUser wxMpUser);
+
+    default MpUserDO convert(MpAccountDO account, WxMpUser wxMpUser) {
+        MpUserDO user = convert(wxMpUser);
+        user.setSubscribeStatus(wxMpUser.getSubscribe() ? CommonStatusEnum.ENABLE.getStatus()
+                : CommonStatusEnum.DISABLE.getStatus());
+        user.setSubscribeTime(LocalDateTimeUtil.of(wxMpUser.getSubscribeTime() * 1000L));
+        if (account != null) {
+            user.setAccountId(account.getId());
+            user.setAppId(account.getAppId());
+        }
+        return user;
+    }
+
 }

+ 0 - 43
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/dataobject/subscribetext/WxSubscribeTextDO.java

@@ -1,43 +0,0 @@
-package cn.iocoder.yudao.module.mp.dal.dataobject.subscribetext;
-
-import lombok.*;
-
-import java.util.*;
-
-import com.baomidou.mybatisplus.annotation.*;
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-
-/**
- * 关注欢迎语 DO
- *
- * @author 芋道源码
- */
-@TableName("wx_subscribe_text")
-@KeySequence("wx_subscribe_text_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class WxSubscribeTextDO extends BaseDO {
-
-    /**
-     * 主键
-     */
-    @TableId
-    private Integer id;
-    /**
-     * 消息类型 1文本消息;2图文消息;
-     */
-    private String msgType;
-    /**
-     * 模板ID
-     */
-    private String tplId;
-    /**
-     * 微信账号ID
-     */
-    private String wxAccountId;
-
-}

+ 6 - 9
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/dataobject/user/MpUserDO.java

@@ -52,15 +52,16 @@ public class MpUserDO extends BaseDO {
     private LocalDateTime unsubscribeTime;
     /**
      * 昵称
+     *
+     * 注意,2021-12-27 公众号接口不再返回头像和昵称,只能通过微信公众号的网页登录获取
      */
     private String nickname;
     /**
-     * 性别
+     * 头像地址
      *
-     * 1- 男
-     * 2- 女
+     * 注意,2021-12-27 公众号接口不再返回头像和昵称,只能通过微信公众号的网页登录获取
      */
-    private Integer gender;
+    private String headImageUrl;
     /**
      * 语言
      */
@@ -77,10 +78,6 @@ public class MpUserDO extends BaseDO {
      * 城市
      */
     private String city;
-    /**
-     * 头像地址
-     */
-    private String headImageUrl;
     /**
      * 备注
      */
@@ -91,7 +88,7 @@ public class MpUserDO extends BaseDO {
      *
      * 关联 {@link MpAccountDO#getId()}
      */
-    private String accountId;
+    private Long accountId;
     /**
      * 微信公众号 appid
      *

+ 5 - 0
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/mysql/accountfans/MpUserMapper.java

@@ -18,4 +18,9 @@ public interface MpUserMapper extends BaseMapperX<MpUserDO> {
                 .orderByDesc(MpUserDO::getId));
     }
 
+    default MpUserDO selectByAppIdAndOpenid(String appId, String openId) {
+        return selectOne(MpUserDO::getAppId, appId,
+                MpUserDO::getOpenid, openId);
+    }
+
 }

+ 0 - 38
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/mysql/subscribetext/WxSubscribeTextMapper.java

@@ -1,38 +0,0 @@
-package cn.iocoder.yudao.module.mp.dal.mysql.subscribetext;
-
-import java.util.*;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
-import cn.iocoder.yudao.module.mp.dal.dataobject.subscribetext.WxSubscribeTextDO;
-import org.apache.ibatis.annotations.Mapper;
-import cn.iocoder.yudao.module.mp.controller.admin.subscribetext.vo.*;
-
-/**
- * 关注欢迎语 Mapper
- *
- * @author 芋道源码
- */
-@Mapper
-public interface WxSubscribeTextMapper extends BaseMapperX<WxSubscribeTextDO> {
-
-    default PageResult<WxSubscribeTextDO> selectPage(WxSubscribeTextPageReqVO reqVO) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<WxSubscribeTextDO>()
-                .eqIfPresent(WxSubscribeTextDO::getMsgType, reqVO.getMsgType())
-                .eqIfPresent(WxSubscribeTextDO::getTplId, reqVO.getTplId())
-                .eqIfPresent(WxSubscribeTextDO::getWxAccountId, reqVO.getWxAccountId())
-                .betweenIfPresent(WxSubscribeTextDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
-                .orderByDesc(WxSubscribeTextDO::getId));
-    }
-
-    default List<WxSubscribeTextDO> selectList(WxSubscribeTextExportReqVO reqVO) {
-        return selectList(new LambdaQueryWrapperX<WxSubscribeTextDO>()
-                .eqIfPresent(WxSubscribeTextDO::getMsgType, reqVO.getMsgType())
-                .eqIfPresent(WxSubscribeTextDO::getTplId, reqVO.getTplId())
-                .eqIfPresent(WxSubscribeTextDO::getWxAccountId, reqVO.getWxAccountId())
-                .betweenIfPresent(WxSubscribeTextDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
-                .orderByDesc(WxSubscribeTextDO::getId));
-    }
-
-}

+ 17 - 114
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/user/SubscribeHandler.java

@@ -1,19 +1,10 @@
 package cn.iocoder.yudao.module.mp.service.handler.user;
 
-import cn.hutool.core.date.DateUtil;
-import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 import cn.iocoder.yudao.module.mp.builder.TextBuilder;
-import cn.iocoder.yudao.module.mp.controller.admin.user.vo.WxAccountFansCreateReqVO;
-import cn.iocoder.yudao.module.mp.controller.admin.user.vo.WxAccountFansUpdateReqVO;
-import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
 import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO;
-import cn.iocoder.yudao.module.mp.dal.dataobject.subscribetext.WxSubscribeTextDO;
-import cn.iocoder.yudao.module.mp.dal.dataobject.texttemplate.WxTextTemplateDO;
+import cn.iocoder.yudao.module.mp.framework.mp.core.context.MpContextHolder;
 import cn.iocoder.yudao.module.mp.service.account.MpAccountService;
 import cn.iocoder.yudao.module.mp.service.user.MpUserService;
-import cn.iocoder.yudao.module.mp.service.accountfanstag.WxAccountFansTagService;
-import cn.iocoder.yudao.module.mp.service.subscribetext.WxSubscribeTextService;
-import cn.iocoder.yudao.module.mp.service.texttemplate.WxTextTemplateService;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.session.WxSessionManager;
@@ -22,12 +13,10 @@ 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.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
-import java.io.UnsupportedEncodingException;
 import java.util.Map;
 
 /**
@@ -41,120 +30,33 @@ import java.util.Map;
 @Slf4j
 public class SubscribeHandler implements WxMpMessageHandler {
 
-    @Autowired
-    private WxTextTemplateService wxTextTemplateService;
-
     @Resource
     @Lazy // 延迟加载,解决循环依赖的问题
     private MpAccountService mpAccountService;
 
-    @Autowired
-    private WxSubscribeTextService wxSubscribeTextService;
-
-    @Autowired
-    private MpUserService wxAccountFansService;
-
-    @Autowired
-    private WxAccountFansTagService wxAccountFansTagService;
+    @Resource
+    private MpUserService mpUserService;
 
     @Override
-    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
-                                    Map<String, Object> context, WxMpService weixinService,
-                                    WxSessionManager sessionManager) throws WxErrorException {
-
-        log.info("新关注用户 OPENID: " + wxMessage.getFromUser());
-
-        // 获取微信用户基本信息
+    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
+                                    WxMpService weixinService, WxSessionManager sessionManager) throws WxErrorException {
+        // 第一步,从公众号平台,获取用户信息
+        log.info("[handle][用户({}) 关注]", wxMessage.getFromUser());
+        WxMpUser wxMpUser = null;
         try {
-            WxMpUser wxmpUser = weixinService.getUserService()
-                    .userInfo(wxMessage.getFromUser(), null);
-            if (wxmpUser != null) {
-                // 可以添加关注用户到本地数据库
-                MpAccountDO wxAccount = mpAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser());
-                if (wxAccount != null) {
-                    MpUserDO wxAccountFans = wxAccountFansService.findBy(MpUserDO::getOpenid, wxmpUser.getOpenId());
-                    if (wxAccountFans == null) {//insert
-                        WxAccountFansCreateReqVO wxAccountFansCreateReqVO = new WxAccountFansCreateReqVO();
-                        wxAccountFansCreateReqVO.setOpenid(wxmpUser.getOpenId());
-                        wxAccountFansCreateReqVO.setSubscribeStatus(wxmpUser.getSubscribe() ? "1" : "0");
-                        wxAccountFansCreateReqVO.setSubscribeTime(DateUtil.date(wxmpUser.getSubscribeTime() * 1000L));
-                        try {
-                            wxAccountFansCreateReqVO.setNickname(wxmpUser.getNickname().getBytes("UTF-8"));
-                        } catch (UnsupportedEncodingException e) {
-                            e.printStackTrace();
-                        }
-                        wxAccountFansCreateReqVO.setLanguage(wxmpUser.getLanguage());
-                        wxAccountFansCreateReqVO.setHeadimgUrl(wxmpUser.getHeadImgUrl());
-                        wxAccountFansCreateReqVO.setRemark(wxmpUser.getRemark());
-                        wxAccountFansCreateReqVO.setWxAccountId(String.valueOf(wxAccount.getId()));
-                        wxAccountFansCreateReqVO.setWxAccountAppid(wxAccount.getAppId());
-                        wxAccountFansService.createWxAccountFans(wxAccountFansCreateReqVO);
-
-                        //process tags
-                        wxAccountFansTagService.processFansTags(wxAccount, wxmpUser);
-
-                    } else {//update
-                        WxAccountFansUpdateReqVO wxAccountFansUpdateReqVO = new WxAccountFansUpdateReqVO();
-                        wxAccountFansUpdateReqVO.setId(wxAccountFans.getId());
-                        wxAccountFansUpdateReqVO.setOpenid(wxmpUser.getOpenId());
-                        wxAccountFansUpdateReqVO.setSubscribeStatus(wxmpUser.getSubscribe() ? "1" : "0");
-                        wxAccountFansUpdateReqVO.setSubscribeTime(DateUtil.date(wxmpUser.getSubscribeTime() * 1000L));
-                        try {
-                            wxAccountFans.setNickname(wxmpUser.getNickname().getBytes("UTF-8"));
-                        } catch (UnsupportedEncodingException e) {
-                            e.printStackTrace();
-                        }
-                        wxAccountFansUpdateReqVO.setLanguage(wxmpUser.getLanguage());
-                        wxAccountFansUpdateReqVO.setHeadimgUrl(wxmpUser.getHeadImgUrl());
-                        wxAccountFansUpdateReqVO.setRemark(wxmpUser.getRemark());
-                        wxAccountFansUpdateReqVO.setWxAccountId(String.valueOf(wxAccount.getId()));
-                        wxAccountFansUpdateReqVO.setWxAccountAppid(wxAccount.getAppId());
-                        wxAccountFansService.updateWxAccountFans(wxAccountFansUpdateReqVO);
-
-                        //process tags
-                        wxAccountFansTagService.processFansTags(wxAccount, wxmpUser);
-
-                    }
-                }
-
-            }
+            wxMpUser = weixinService.getUserService().userInfo(wxMessage.getFromUser());
         } catch (WxErrorException e) {
-            if (e.getError().getErrorCode() == 48001) {
-                log.info("该公众号没有获取用户信息权限!");
-            }
-        }
-
-
-        WxMpXmlOutMessage responseResult = null;
-        try {
-            responseResult = this.handleSpecial(wxMessage);
-        } catch (Exception e) {
-            log.error(e.getMessage(), e);
+            log.error("[handle][用户({})] 获取用户信息失败!", wxMessage.getFromUser(), e);
         }
 
-        if (responseResult != null) {
-            return responseResult;
+        // 第二步,保存用户信息
+        MpUserDO mpUser = null;
+        if (wxMpUser != null) {
+            mpUser = mpUserService.saveUser(MpContextHolder.getAppId(), wxMpUser);
         }
 
-        try {
-            String content = "感谢关注!";//默认
-            MpAccountDO wxAccount = mpAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser());
-            if (wxAccount != null) {
-                WxSubscribeTextDO wxSubscribeText = wxSubscribeTextService.findBy(WxSubscribeTextDO::getWxAccountId, String.valueOf(wxAccount.getId()));
-                if (wxSubscribeText != null) {
-                    WxTextTemplateDO wxTextTemplate = wxTextTemplateService.getWxTextTemplate(Integer.parseInt(wxSubscribeText.getTplId()));
-                    if (wxTextTemplate != null) {
-                        content = wxTextTemplate.getContent();
-                    }
-                }
-            }
-            log.info("wxMessage : {}", JsonUtils.toJsonString(wxMessage));
-            return new TextBuilder().build(content, wxMessage, weixinService);
-        } catch (Exception e) {
-            log.error(e.getMessage(), e);
-        }
-
-        return null;
+        // 第三步,回复关注的欢迎语  TODO 芋艿:关注的欢迎语
+        return new TextBuilder().build("感谢关注", wxMessage, weixinService);
     }
 
     /**
@@ -162,6 +64,7 @@ public class SubscribeHandler implements WxMpMessageHandler {
      */
     private WxMpXmlOutMessage handleSpecial(WxMpXmlMessage wxMessage)
             throws Exception {
+
         //TODO
         return null;
     }

+ 4 - 27
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/user/UnsubscribeHandler.java

@@ -1,9 +1,6 @@
 package cn.iocoder.yudao.module.mp.service.handler.user;
 
-import cn.iocoder.yudao.module.mp.controller.admin.user.vo.WxAccountFansUpdateReqVO;
-import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
-import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO;
-import cn.iocoder.yudao.module.mp.service.account.MpAccountService;
+import cn.iocoder.yudao.module.mp.framework.mp.core.context.MpContextHolder;
 import cn.iocoder.yudao.module.mp.service.user.MpUserService;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.session.WxSessionManager;
@@ -11,7 +8,6 @@ import me.chanjar.weixin.mp.api.WxMpMessageHandler;
 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.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Component;
 
@@ -22,8 +18,6 @@ import java.util.Map;
  * 取消关注的事件处理器
  *
  * @author 芋道源码
- *
- * // TODO 芋艿:待实现
  */
 @Component
 @Slf4j
@@ -31,31 +25,14 @@ public class UnsubscribeHandler implements WxMpMessageHandler {
 
     @Resource
     @Lazy // 延迟加载,解决循环依赖的问题
-    private MpAccountService mpAccountService;
-
-    @Autowired
-    private MpUserService wxAccountFansService;
+    private MpUserService mpUserService;
 
     @Override
     public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
                                     Map<String, Object> context, WxMpService wxMpService,
                                     WxSessionManager sessionManager) {
-        String openId = wxMessage.getFromUser();
-        log.info("取消关注用户 OPENID: " + openId);
-        // TODO 可以更新本地数据库为取消关注状态
-
-        MpAccountDO wxAccountDO = mpAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser());
-        if (wxAccountDO != null) {
-            MpUserDO wxAccountFansDO = wxAccountFansService.findBy(MpUserDO::getOpenid, openId);
-            if (wxAccountFansDO != null) {
-                WxAccountFansUpdateReqVO wxAccountFansUpdateReqVO = new WxAccountFansUpdateReqVO();
-                wxAccountFansUpdateReqVO.setId(wxAccountDO.getId());
-                wxAccountFansDO.setSubscribeStatus("0");//取消订阅
-                wxAccountFansService.updateWxAccountFans(wxAccountFansUpdateReqVO);
-            }
-        }
-
-
+        log.info("[handle][用户({}) 取消关注]", wxMessage.getFromUser());
+        mpUserService.updateUserUnsubscribe(MpContextHolder.getAppId(), wxMessage.getFromUser());
         return null;
     }
 

+ 0 - 80
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/subscribetext/WxSubscribeTextService.java

@@ -1,80 +0,0 @@
-package cn.iocoder.yudao.module.mp.service.subscribetext;
-
-import java.util.*;
-import javax.validation.*;
-
-import cn.iocoder.yudao.module.mp.controller.admin.subscribetext.vo.*;
-import cn.iocoder.yudao.module.mp.dal.dataobject.subscribetext.WxSubscribeTextDO;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
-
-/**
- * 关注欢迎语 Service 接口
- *
- * @author 芋道源码
- */
-public interface WxSubscribeTextService {
-
-    /**
-     * 创建关注欢迎语
-     *
-     * @param createReqVO 创建信息
-     * @return 编号
-     */
-    Integer createWxSubscribeText(@Valid WxSubscribeTextCreateReqVO createReqVO);
-
-    /**
-     * 更新关注欢迎语
-     *
-     * @param updateReqVO 更新信息
-     */
-    void updateWxSubscribeText(@Valid WxSubscribeTextUpdateReqVO updateReqVO);
-
-    /**
-     * 删除关注欢迎语
-     *
-     * @param id 编号
-     */
-    void deleteWxSubscribeText(Integer id);
-
-    /**
-     * 获得关注欢迎语
-     *
-     * @param id 编号
-     * @return 关注欢迎语
-     */
-    WxSubscribeTextDO getWxSubscribeText(Integer id);
-
-    /**
-     * 获得关注欢迎语列表
-     *
-     * @param ids 编号
-     * @return 关注欢迎语列表
-     */
-    List<WxSubscribeTextDO> getWxSubscribeTextList(Collection<Integer> ids);
-
-    /**
-     * 获得关注欢迎语分页
-     *
-     * @param pageReqVO 分页查询
-     * @return 关注欢迎语分页
-     */
-    PageResult<WxSubscribeTextDO> getWxSubscribeTextPage(WxSubscribeTextPageReqVO pageReqVO);
-
-    /**
-     * 获得关注欢迎语列表, 用于 Excel 导出
-     *
-     * @param exportReqVO 查询条件
-     * @return 关注欢迎语列表
-     */
-    List<WxSubscribeTextDO> getWxSubscribeTextList(WxSubscribeTextExportReqVO exportReqVO);
-
-    /**
-     * 关注欢迎语分页
-     *
-     * @param column
-     * @param obj
-     * @return
-     */
-    WxSubscribeTextDO findBy(SFunction<WxSubscribeTextDO, ?> column, Object obj);
-}

+ 0 - 90
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/subscribetext/WxSubscribeTextServiceImpl.java

@@ -1,90 +0,0 @@
-package cn.iocoder.yudao.module.mp.service.subscribetext;
-
-import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-
-import org.springframework.validation.annotation.Validated;
-
-import java.util.*;
-
-import cn.iocoder.yudao.module.mp.controller.admin.subscribetext.vo.*;
-import cn.iocoder.yudao.module.mp.dal.dataobject.subscribetext.WxSubscribeTextDO;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
-import cn.iocoder.yudao.module.mp.convert.subscribetext.WxSubscribeTextConvert;
-import cn.iocoder.yudao.module.mp.dal.mysql.subscribetext.WxSubscribeTextMapper;
-
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants.*;
-
-/**
- * 关注欢迎语 Service 实现类
- *
- * @author 芋道源码
- */
-@Service
-@Validated
-public class WxSubscribeTextServiceImpl implements WxSubscribeTextService {
-
-    @Resource
-    private WxSubscribeTextMapper wxSubscribeTextMapper;
-
-    @Override
-    public Integer createWxSubscribeText(WxSubscribeTextCreateReqVO createReqVO) {
-        // 插入
-        WxSubscribeTextDO wxSubscribeText = WxSubscribeTextConvert.INSTANCE.convert(createReqVO);
-        wxSubscribeTextMapper.insert(wxSubscribeText);
-        // 返回
-        return wxSubscribeText.getId();
-    }
-
-    @Override
-    public void updateWxSubscribeText(WxSubscribeTextUpdateReqVO updateReqVO) {
-        // 校验存在
-        this.validateWxSubscribeTextExists(updateReqVO.getId());
-        // 更新
-        WxSubscribeTextDO updateObj = WxSubscribeTextConvert.INSTANCE.convert(updateReqVO);
-        wxSubscribeTextMapper.updateById(updateObj);
-    }
-
-    @Override
-    public void deleteWxSubscribeText(Integer id) {
-        // 校验存在
-        this.validateWxSubscribeTextExists(id);
-        // 删除
-        wxSubscribeTextMapper.deleteById(id);
-    }
-
-    private void validateWxSubscribeTextExists(Integer id) {
-        if (wxSubscribeTextMapper.selectById(id) == null) {
-            throw exception(COMMON_NOT_EXISTS);
-        }
-    }
-
-    @Override
-    public WxSubscribeTextDO getWxSubscribeText(Integer id) {
-        return wxSubscribeTextMapper.selectById(id);
-    }
-
-    @Override
-    public List<WxSubscribeTextDO> getWxSubscribeTextList(Collection<Integer> ids) {
-        return wxSubscribeTextMapper.selectBatchIds(ids);
-    }
-
-    @Override
-    public PageResult<WxSubscribeTextDO> getWxSubscribeTextPage(WxSubscribeTextPageReqVO pageReqVO) {
-        return wxSubscribeTextMapper.selectPage(pageReqVO);
-    }
-
-    @Override
-    public List<WxSubscribeTextDO> getWxSubscribeTextList(WxSubscribeTextExportReqVO exportReqVO) {
-        return wxSubscribeTextMapper.selectList(exportReqVO);
-    }
-
-    @Override
-    public WxSubscribeTextDO findBy(SFunction<WxSubscribeTextDO, ?> column, Object obj) {
-        return wxSubscribeTextMapper.selectOne(column, obj);
-    }
-}

+ 20 - 0
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/user/MpUserService.java

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.mp.service.user;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserPageReqVO;
 import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO;
+import me.chanjar.weixin.mp.bean.result.WxMpUser;
 
 import java.util.Collection;
 import java.util.List;
@@ -38,4 +39,23 @@ public interface MpUserService {
      */
     PageResult<MpUserDO> getUserPage(MpUserPageReqVO pageReqVO);
 
+    /**
+     * 保存微信公众号粉丝
+     *
+     * 新增或更新,根据是否存在数据库中
+     *
+     * @param appId 微信公众号 appId
+     * @param wxMpUser 微信公众号粉丝的信息
+     * @return 微信公众号粉丝
+     */
+    MpUserDO saveUser(String appId, WxMpUser wxMpUser);
+
+    /**
+     * 更新微信公众号粉丝,取消关注
+     *
+     * @param appId 微信公众号 appId
+     * @param openId 微信公众号粉丝的 openid
+     */
+    void updateUserUnsubscribe(String appId, String openId);
+
 }

+ 41 - 0
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/user/MpUserServiceImpl.java

@@ -1,13 +1,21 @@
 package cn.iocoder.yudao.module.mp.service.user;
 
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserPageReqVO;
+import cn.iocoder.yudao.module.mp.convert.user.MpUserConvert;
+import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
 import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO;
 import cn.iocoder.yudao.module.mp.dal.mysql.accountfans.MpUserMapper;
+import cn.iocoder.yudao.module.mp.service.account.MpAccountService;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.mp.bean.result.WxMpUser;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
+import java.time.LocalDateTime;
 import java.util.Collection;
 import java.util.List;
 
@@ -18,8 +26,13 @@ import java.util.List;
  */
 @Service
 @Validated
+@Slf4j
 public class MpUserServiceImpl implements MpUserService {
 
+    @Resource
+    @Lazy // 延迟加载,解决循环依赖的问题
+    private MpAccountService accountService;
+
     @Resource
     private MpUserMapper mpUserMapper;
 
@@ -38,4 +51,32 @@ public class MpUserServiceImpl implements MpUserService {
         return mpUserMapper.selectPage(pageReqVO);
     }
 
+    @Override
+    public MpUserDO saveUser(String appId, WxMpUser wxMpUser) {
+        // 构建保存的 MpUserDO 对象
+        MpAccountDO account = accountService.getAccountFromCache(appId);
+        MpUserDO user = MpUserConvert.INSTANCE.convert(account, wxMpUser);
+
+        // 根据情况,插入或更新
+        MpUserDO dbUser = mpUserMapper.selectByAppIdAndOpenid(appId, wxMpUser.getOpenId());
+        if (dbUser == null) {
+            mpUserMapper.insert(user);
+        } else {
+            user.setId(dbUser.getId());
+            mpUserMapper.updateById(user);
+        }
+        return user;
+    }
+
+    @Override
+    public void updateUserUnsubscribe(String appId, String openId) {
+        MpUserDO dbUser = mpUserMapper.selectByAppIdAndOpenid(appId, openId);
+        if (dbUser == null) {
+            log.error("[updateUserUnsubscribe][微信公众号粉丝 appId({}) openId({}) 不存在]", appId, openId);
+            return;
+        }
+        mpUserMapper.updateById(new MpUserDO().setId(dbUser.getId()).setSubscribeStatus(CommonStatusEnum.DISABLE.getStatus())
+                .setSubscribeTime(LocalDateTime.now()));
+    }
+
 }