mp:实现 tag 模块的后端接口
parent
acee075260
commit
d1cc9dde0c
|
@ -14,12 +14,19 @@ public interface ErrorCodeConstants {
|
|||
ErrorCode ACCOUNT_GENERATE_QR_CODE_FAIL = new ErrorCode(1006000001, "生成公众号二维码失败,原因:{}");
|
||||
ErrorCode ACCOUNT_CLEAR_QUOTA_FAIL = new ErrorCode(1006000001, "清空公众号的 API 配额失败,原因:{}");
|
||||
|
||||
// ========== 公众号账号 1006001000============
|
||||
// ========== 公众号统计 1006001000============
|
||||
ErrorCode STATISTICS_GET_USER_SUMMARY_FAIL = new ErrorCode(1006001000, "获取用户增减数据失败,原因:{}");
|
||||
ErrorCode STATISTICS_GET_USER_CUMULATE_FAIL = new ErrorCode(1006001001, "获得用户累计数据失败,原因:{}");
|
||||
ErrorCode STATISTICS_GET_UPSTREAM_MESSAGE_FAIL = new ErrorCode(1006001002, "获得消息发送概况数据失败,原因:{}");
|
||||
ErrorCode STATISTICS_GET_INTERFACE_SUMMARY_FAIL = new ErrorCode(1006001003, "获得接口分析数据失败,原因:{}");
|
||||
|
||||
// ========== 公众号标签 1006002000============
|
||||
ErrorCode TAG_NOT_EXISTS = new ErrorCode(1006002000, "标签不存在");
|
||||
ErrorCode TAG_CREATE_FAIL = new ErrorCode(1006002001, "创建标签失败,原因:{}");
|
||||
ErrorCode TAG_UPDATE_FAIL = new ErrorCode(1006002001, "更新标签失败,原因:{}");
|
||||
ErrorCode TAG_DELETE_FAIL = new ErrorCode(1006002001, "删除标签失败,原因:{}");
|
||||
ErrorCode TAG_GET_FAIL = new ErrorCode(1006002001, "获得标签失败,原因:{}");
|
||||
|
||||
// TODO 要处理下
|
||||
ErrorCode COMMON_NOT_EXISTS = new ErrorCode(1006001002, "用户不存在");
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
### 请求 /login 接口 => 成功
|
||||
### 请求 /mp/menu/save 接口 => 成功
|
||||
POST {{baseUrl}}/mp/menu/save
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
### 请求 /mp/tag/create 接口 => 成功
|
||||
POST {{baseUrl}}/mp/tag/create
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
{
|
||||
"accountId": "1",
|
||||
"name": "测试"
|
||||
}
|
||||
|
||||
### 请求 /mp/tag/update 接口 => 成功
|
||||
PUT {{baseUrl}}/mp/tag/update
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
{
|
||||
"id": "3",
|
||||
"name": "测试标签啦"
|
||||
}
|
||||
|
||||
### 请求 /mp/tag/delete 接口 => 成功
|
||||
DELETE {{baseUrl}}/mp/tag/delete?id=3
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
### 请求 /mp/tag/page 接口 => 成功
|
||||
GET {{baseUrl}}/mp/tag/page?accountId=1&pageNo=1&pageSize=10
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
### 请求 /mp/tag/sync 接口 => 成功
|
||||
POST {{baseUrl}}/mp/tag/sync?accountId=1
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
|
@ -62,4 +62,13 @@ public class MpTagController {
|
|||
return success(MpTagConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
@PostMapping("/sync")
|
||||
@ApiOperation("同步公众标签")
|
||||
@ApiImplicitParam(name = "id", value = "公众号账号的编号", required = true, dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('mp:tag:sync')")
|
||||
public CommonResult<Boolean> syncTag(@RequestParam("accountId") Long accountId) {
|
||||
mpTagService.syncTag(accountId);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import lombok.Data;
|
|||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel("管理后台 - 公众号标签 Response VO")
|
||||
|
@ -15,10 +14,12 @@ import java.util.Date;
|
|||
@ToString(callSuper = true)
|
||||
public class MpTagRespVO extends MpTagBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true)
|
||||
@NotNull(message = "编号不能为空")
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "此标签下粉丝数量", required = true, example = "0")
|
||||
private Integer count;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package cn.iocoder.yudao.module.mp.convert.tag;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagCreateReqVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.tag.MpTagDO;
|
||||
import me.chanjar.weixin.mp.bean.tag.WxUserTag;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -16,8 +18,6 @@ public interface MpTagConvert {
|
|||
|
||||
MpTagConvert INSTANCE = Mappers.getMapper(MpTagConvert.class);
|
||||
|
||||
WxUserTag convert(MpTagCreateReqVO bean);
|
||||
|
||||
WxUserTag convert(MpTagUpdateReqVO bean);
|
||||
|
||||
MpTagRespVO convert(WxUserTag bean);
|
||||
|
@ -26,4 +26,14 @@ public interface MpTagConvert {
|
|||
|
||||
PageResult<MpTagRespVO> convertPage(PageResult<MpTagDO> page);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(target = "id", ignore = true),
|
||||
@Mapping(source = "tag.id", target = "tagId"),
|
||||
@Mapping(source = "tag.name", target = "name"),
|
||||
@Mapping(source = "tag.count", target = "count"),
|
||||
@Mapping(source = "account.id", target = "accountId"),
|
||||
@Mapping(source = "account.appId", target = "appId"),
|
||||
})
|
||||
MpTagDO convert(WxUserTag tag, MpAccountDO account);
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import lombok.*;
|
|||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import me.chanjar.weixin.mp.bean.tag.WxUserTag;
|
||||
|
||||
/**
|
||||
* 公众号标签 DO
|
||||
|
@ -31,6 +32,12 @@ public class MpTagDO extends BaseDO {
|
|||
* 标签名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 此标签下粉丝数
|
||||
*
|
||||
* 冗余:{@link WxUserTag#getCount()} 字段,需要管理员点击【同步】后,更新该字段
|
||||
*/
|
||||
private Integer count;
|
||||
|
||||
/**
|
||||
* 微信公众号 ID
|
||||
|
|
|
@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagPageReqVO;
|
|||
import cn.iocoder.yudao.module.mp.dal.dataobject.tag.MpTagDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface MpTagMapper extends BaseMapperX<MpTagDO> {
|
||||
|
||||
|
@ -17,4 +19,8 @@ public interface MpTagMapper extends BaseMapperX<MpTagDO> {
|
|||
.orderByDesc(MpTagDO::getId));
|
||||
}
|
||||
|
||||
default List<MpTagDO> selectListByAccountId(Long accountId) {
|
||||
return selectList(MpTagDO::getAccountId, accountId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@ import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
|
|||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants.ACCOUNT_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* 公众号账号 Service 接口
|
||||
*
|
||||
|
@ -51,6 +54,20 @@ public interface MpAccountService {
|
|||
*/
|
||||
MpAccountDO getAccount(Long id);
|
||||
|
||||
/**
|
||||
* 获得公众号账号。若不存在,则抛出业务异常
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 公众号账号
|
||||
*/
|
||||
default MpAccountDO getRequiredAccount(Long id) {
|
||||
MpAccountDO account = getAccount(id);
|
||||
if (account == null) {
|
||||
throw exception(ACCOUNT_NOT_EXISTS);
|
||||
}
|
||||
return account;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从缓存中,获得公众号账号
|
||||
*
|
||||
|
|
|
@ -45,4 +45,11 @@ public interface MpTagService {
|
|||
*/
|
||||
PageResult<MpTagDO> getTagPage(MpTagPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 同步公众号标签
|
||||
*
|
||||
* @param accountId 公众号账号的编号
|
||||
*/
|
||||
void syncTag(Long accountId);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,18 +1,33 @@
|
|||
package cn.iocoder.yudao.module.mp.service.tag;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagCreateReqVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagPageReqVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.mp.convert.tag.MpTagConvert;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.tag.MpTagDO;
|
||||
import cn.iocoder.yudao.module.mp.dal.mysql.tag.MpTagMapper;
|
||||
import cn.iocoder.yudao.module.mp.framework.mp.core.MpServiceFactory;
|
||||
import cn.iocoder.yudao.module.mp.service.account.MpAccountService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.tag.WxUserTag;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
import static cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 公众号标签 Service 实现类
|
||||
|
@ -27,29 +42,113 @@ public class MpTagServiceImpl implements MpTagService {
|
|||
@Resource
|
||||
private MpTagMapper mpTagMapper;
|
||||
|
||||
@Resource
|
||||
private MpAccountService mpAccountService;
|
||||
|
||||
@Resource
|
||||
@Lazy // 延迟加载,为了解决延迟加载
|
||||
private MpServiceFactory mpServiceFactory;
|
||||
|
||||
@Override
|
||||
public Long createTag(MpTagCreateReqVO createReqVO) {
|
||||
// return wxMpService.getUserTagService().tagCreate(createReqVO.getName());
|
||||
return null;
|
||||
// 获得公众号账号
|
||||
MpAccountDO account = mpAccountService.getRequiredAccount(createReqVO.getAccountId());
|
||||
|
||||
// 第一步,新增标签到公众号平台。标签名的唯一,交给公众号平台
|
||||
WxMpService mpService = mpServiceFactory.getRequiredMpService(createReqVO.getAccountId());
|
||||
WxUserTag wxTag;
|
||||
try {
|
||||
wxTag = mpService.getUserTagService().tagCreate(createReqVO.getName());
|
||||
} catch (WxErrorException e) {
|
||||
throw exception(TAG_CREATE_FAIL, e.getError().getErrorMsg());
|
||||
}
|
||||
|
||||
// 第二步,新增标签到数据库
|
||||
MpTagDO tag = MpTagConvert.INSTANCE.convert(wxTag, account);
|
||||
mpTagMapper.insert(tag);
|
||||
return tag.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTag(MpTagUpdateReqVO updateReqVO) {
|
||||
// return wxMpService.getUserTagService().tagUpdate(updateReqVO.getId(), updateReqVO.getName());
|
||||
// 校验标签存在
|
||||
MpTagDO tag = validateTagExists(updateReqVO.getId());
|
||||
|
||||
// 第一步,更新标签到公众号平台。标签名的唯一,交给公众号平台
|
||||
WxMpService mpService = mpServiceFactory.getRequiredMpService(tag.getAccountId());
|
||||
try {
|
||||
mpService.getUserTagService().tagUpdate(tag.getTagId(), updateReqVO.getName());
|
||||
} catch (WxErrorException e) {
|
||||
throw exception(TAG_UPDATE_FAIL, e.getError().getErrorMsg());
|
||||
}
|
||||
|
||||
// 第二步,更新标签到数据库
|
||||
mpTagMapper.updateById(new MpTagDO().setId(tag.getId()).setName(updateReqVO.getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTag(Long id) {
|
||||
// return wxMpService.getUserTagService().tagDelete(id);
|
||||
// 校验标签存在
|
||||
MpTagDO tag = validateTagExists(id);
|
||||
|
||||
// 第一步,删除标签到公众号平台。
|
||||
WxMpService mpService = mpServiceFactory.getRequiredMpService(tag.getAccountId());
|
||||
try {
|
||||
mpService.getUserTagService().tagDelete(tag.getTagId());
|
||||
} catch (WxErrorException e) {
|
||||
throw exception(TAG_DELETE_FAIL, e.getError().getErrorMsg());
|
||||
}
|
||||
|
||||
// 第二步,删除标签到数据库
|
||||
mpTagMapper.deleteById(tag.getId());
|
||||
}
|
||||
|
||||
private MpTagDO validateTagExists(Long id) {
|
||||
MpTagDO tag = mpTagMapper.selectById(id);
|
||||
if (tag == null) {
|
||||
throw exception(TAG_NOT_EXISTS);
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<MpTagDO> getTagPage(MpTagPageReqVO pageReqVO) {
|
||||
return null;
|
||||
return mpTagMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void syncTag(Long accountId) {
|
||||
MpAccountDO account = mpAccountService.getRequiredAccount(accountId);
|
||||
|
||||
// 第一步,从公众号平台获取最新的标签列表
|
||||
WxMpService mpService = mpServiceFactory.getRequiredMpService(accountId);
|
||||
List<WxUserTag> wxTags;
|
||||
try {
|
||||
wxTags = mpService.getUserTagService().tagGet();
|
||||
} catch (WxErrorException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// 第二步,合并更新回自己的数据库;由于标签只有 100 个,所以直接 for 循环操作
|
||||
Map<Long, MpTagDO> tagMap = convertMap(mpTagMapper.selectListByAccountId(accountId),
|
||||
MpTagDO::getTagId);
|
||||
wxTags.forEach(wxTag -> {
|
||||
MpTagDO tag = tagMap.remove(wxTag.getId());
|
||||
// 情况一,不存在,新增
|
||||
if (tag == null) {
|
||||
tag = MpTagConvert.INSTANCE.convert(wxTag, account);
|
||||
mpTagMapper.insert(tag);
|
||||
return;
|
||||
}
|
||||
// 情况二,存在,则更新
|
||||
mpTagMapper.updateById(new MpTagDO().setId(tag.getId())
|
||||
.setName(wxTag.getName()).setCount(wxTag.getCount()));
|
||||
});
|
||||
// 情况三,部分标签已经不存在了,删除
|
||||
if (CollUtil.isNotEmpty(tagMap)) {
|
||||
mpTagMapper.deleteBatchIds(convertList(tagMap.values(), MpTagDO::getId));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue