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

This commit is contained in:
YunaiV 2023-01-02 19:41:05 +08:00
parent cdb7348b08
commit 39d377b0bd
22 changed files with 122 additions and 716 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 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;
}

View File

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

View File

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

View File

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

View File

@ -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("该公众号没有获取用户信息权限!");
}
log.error("[handle][用户({})] 获取用户信息失败!", wxMessage.getFromUser(), e);
}
WxMpXmlOutMessage responseResult = null;
try {
responseResult = this.handleSpecial(wxMessage);
} catch (Exception e) {
log.error(e.getMessage(), e);
// 第二步保存用户信息
MpUserDO mpUser = null;
if (wxMpUser != null) {
mpUser = mpUserService.saveUser(MpContextHolder.getAppId(), wxMpUser);
}
if (responseResult != null) {
return responseResult;
}
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;
}

View File

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

View File

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

View File

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

View File

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

View File

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