diff --git a/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountFansServiceImpl.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountFansServiceImpl.java index bf9578464..b9411d55b 100755 --- a/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountFansServiceImpl.java +++ b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountFansServiceImpl.java @@ -18,8 +18,10 @@ package com.pig4cloud.pigx.mp.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.pig4cloud.pigx.common.data.tenant.TenantBroker; import com.pig4cloud.pigx.mp.config.WxMpInitConfigRunner; @@ -29,21 +31,20 @@ import com.pig4cloud.pigx.mp.mapper.WxAccountFansMapper; import com.pig4cloud.pigx.mp.mapper.WxAccountMapper; import com.pig4cloud.pigx.mp.service.WxAccountFansService; import lombok.AllArgsConstructor; -import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpUserService; +import me.chanjar.weixin.mp.bean.result.WxMpUser; import me.chanjar.weixin.mp.bean.result.WxMpUserList; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * @author lengleng @@ -68,8 +69,6 @@ public class WxAccountFansServiceImpl extends ServiceImplquery().lambda().eq(WxAccount::getAppid, appId)); @@ -77,67 +76,95 @@ public class WxAccountFansServiceImpl extends ServiceImpl WxMpInitConfigRunner.getTenants().get(appId), - (id) -> fetchUser(null, wxAccount, wxMpUserService)); + (id) -> fetchUser(finalNextOpenId, wxAccount, wxMpUserService)); + + log.info("公众号 {} 粉丝同步完成", wxAccount.getName()); return Boolean.TRUE; } /** * 获取微信用户 - * @param nextOpenid - * @param wxAccount - * @param wxMpUserService - * @throws WxErrorException + * @param nextOpenid 下一组开始的openid + * @param wxAccount 公众号信息 + * @param wxMpUserService mp操作类 */ - private void fetchUser(String nextOpenid, WxAccount wxAccount, WxMpUserService wxMpUserService) - throws WxErrorException { - WxMpUserList wxMpUserList = wxMpUserService.userList(nextOpenid); - - // openId 分组 每组 100个 openid - CollUtil.split(wxMpUserList.getOpenids(), SIZE).stream().filter(CollUtil::isNotEmpty).forEach(openIdList -> { - log.info("开始批量获取用户信息 {}", openIdList); - List wxAccountFansList = new ArrayList<>(); - try { + private void fetchUser(String nextOpenid, WxAccount wxAccount, WxMpUserService wxMpUserService) { + try { + WxMpUserList wxMpUserList = wxMpUserService.userList(nextOpenid); + // openId 分组 每组 100个 openid + List> openIdsList = CollUtil.split(wxMpUserList.getOpenids(), SIZE).stream() + .filter(CollUtil::isNotEmpty).collect(Collectors.toList()); + // 处理每个分组. 调用查询用户信息 + for (List openIdList : openIdsList) { + log.info("开始批量获取用户信息 {}", openIdList); + List wxAccountFansList = new ArrayList<>(); wxMpUserService.userInfoList(openIdList).forEach(wxMpUser -> { - WxAccountFans wxAccountFans = baseMapper.selectOne(Wrappers.query().lambda() - .eq(WxAccountFans::getOpenid, wxMpUser.getOpenId())); - // 为空初始化一个新的对象 - if (wxAccountFans == null) { - wxAccountFans = new WxAccountFans(); - } - - wxAccountFans.setOpenid(wxMpUser.getOpenId()); - wxAccountFans.setSubscribeStatus(String.valueOf(BooleanUtil.toInt(wxMpUser.getSubscribe()))); - wxAccountFans.setSubscribeTime(LocalDateTime.ofInstant( - Instant.ofEpochMilli(wxMpUser.getSubscribeTime() * 1000L), ZoneId.systemDefault())); - wxAccountFans.setNickname(wxMpUser.getNickname()); - wxAccountFans.setGender(String.valueOf(wxMpUser.getSex())); - wxAccountFans.setLanguage(wxMpUser.getLanguage()); - wxAccountFans.setCountry(wxMpUser.getCountry()); - wxAccountFans.setProvince(wxMpUser.getProvince()); - wxAccountFans.setCity(wxMpUser.getCity()); - wxAccountFans.setHeadimgUrl(wxMpUser.getHeadImgUrl()); - wxAccountFans.setRemark(wxMpUser.getRemark()); - wxAccountFans.setWxAccountId(wxAccount.getId()); - wxAccountFans.setWxAccountAppid(wxAccount.getAppid()); - wxAccountFans.setWxAccountName(wxAccount.getName()); + WxAccountFans wxAccountFans = buildDbUser(wxAccount, wxMpUser); wxAccountFansList.add(wxAccountFans); }); this.saveOrUpdateBatch(wxAccountFansList); log.info("批量插入用户信息完成 {}", openIdList); } - catch (WxErrorException e) { - log.error("批量同步粉丝失败", e); + // 如果nextOpenId 不为空,则继续获取 + if (StrUtil.isNotBlank(wxMpUserList.getNextOpenid())) { + fetchUser(wxMpUserList.getNextOpenid(), wxAccount, wxMpUserService); } - }); - - // 如果nextOpenId 不为空,则继续获取 - if (StrUtil.isNotBlank(wxMpUserList.getNextOpenid())) { - fetchUser(wxMpUserList.getNextOpenid(), wxAccount, wxMpUserService); + } + catch (Exception e) { + log.warn("同步微信公众号 {} 粉丝异常 {}", wxAccount.getName(), e.getMessage()); + // 失败重试逻辑 + String finalNextOpenId = queryNextOpenId(wxAccount.getAppid()); + fetchUser(finalNextOpenId, wxAccount, wxMpUserService); } - log.info("批量同步微信用户信息完成"); + } + + /** + * 构建数据库存取对象 + * @param wxAccount 公众号信息 + * @param wxMpUser 用户微信信息 + */ + private WxAccountFans buildDbUser(WxAccount wxAccount, WxMpUser wxMpUser) { + WxAccountFans wxAccountFans = new WxAccountFans(); + wxAccountFans.setOpenid(wxMpUser.getOpenId()); + wxAccountFans.setSubscribeStatus(String.valueOf(BooleanUtil.toInt(wxMpUser.getSubscribe()))); + + // 2020-11-25 部分用户订阅时间为空,跳过此字段处理 + if (ObjectUtil.isNotEmpty(wxMpUser.getSubscribeTime())) { + wxAccountFans.setSubscribeTime(LocalDateTime + .ofInstant(Instant.ofEpochMilli(wxMpUser.getSubscribeTime() * 1000L), ZoneId.systemDefault())); + } + wxAccountFans.setNickname(wxMpUser.getNickname()); + wxAccountFans.setGender(String.valueOf(wxMpUser.getSex())); + wxAccountFans.setLanguage(wxMpUser.getLanguage()); + wxAccountFans.setCountry(wxMpUser.getCountry()); + wxAccountFans.setProvince(wxMpUser.getProvince()); + wxAccountFans.setCity(wxMpUser.getCity()); + wxAccountFans.setHeadimgUrl(wxMpUser.getHeadImgUrl()); + wxAccountFans.setRemark(wxMpUser.getRemark()); + wxAccountFans.setWxAccountId(wxAccount.getId()); + wxAccountFans.setWxAccountAppid(wxAccount.getAppid()); + wxAccountFans.setWxAccountName(wxAccount.getName()); + return wxAccountFans; + } + + /** + * 查询当前公众号最后插入的openId + * @param appId 公众号标识 + * @return openid / null + */ + private String queryNextOpenId(String appId) { + Page queryPage = new Page<>(0, 1); + Page fansPage = baseMapper.selectPage(queryPage, Wrappers.query().lambda() + .eq(WxAccountFans::getWxAccountAppid, appId).orderByDesc(WxAccountFans::getCreateTime)); + String nextOpenId = null; + if (fansPage.getTotal() > 0) { + nextOpenId = fansPage.getRecords().get(0).getOpenid(); + } + return nextOpenId; } }