JAVA实现判断小步调用户是否关注公众号

打印 上一主题 下一主题

主题 963|帖子 963|积分 2889

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本文重要形貌了判断小步调用户是否关注公众号的逻辑实现及部分代码
首先论述一下大抵流程:
   1、在将小步调和公众号绑定至同一个微信开发平台下;
  2、后端拉取公众号已关注用户列表,并获取此中每一个用户的unionID, 建立已关注用户表;
  3、后端可做定时任务更新该表;
  4、用户在小步调中登录注册时后端用code拿到用户的unionID并生存;
  5、前端请求查询时,后端根据发起请求用户的unionID查表,判断该用户是否已关注;
   一、数据库表和Mapper层
  1. 这里简单给出了建表语句和实体类, 具体mapper/service层可自行实现
  2. CREATE TABLE `public_user` (
  3.   `id` bigint(20) NOT NULL AUTO_INCREMENT,
  4.   `open_id` varchar(50) DEFAULT NULL COMMENT 'openId',
  5.   `union_id` varchar(50) DEFAULT NULL COMMENT 'union',
  6.   PRIMARY KEY (`id`)
  7. ) ENGINE=InnoDB AUTO_INCREMENT=1DEFAULT CHARSET=utf8mb4;
  8. @Table(name = "public_user")
  9. @NoArgsConstructor
  10. @AllArgsConstructor
  11. @Builder
  12. @Data
  13. public class PublicUser implements Serializable {
  14.     @Id
  15.     @GeneratedValue(
  16.             strategy = GenerationType.IDENTITY
  17.     )
  18.     private Long id;
  19.     @Column(name = "open_id")
  20.     private String openId;
  21.     @Column(name = "union_id")
  22.     private String unionId;
  23. }
  24. public interface PublicUserMapper {
  25. }
复制代码
二、微信公众号对接接口相关逻辑代码
        1.三个基础接收对象类
 
  1. @Data
  2. public class WeixinUserInfoVo {
  3.   private String openid;
  4.   private String unionid;
  5.   /**
  6.    * 该值为0值 则没有openId和unionId
  7.    */
  8.   private Integer subscribe;
  9.   private Integer errcode;
  10. }
  11. @Data
  12. public class WeixinUserListVo {
  13.   private Integer errcode;
  14.   @ApiModelProperty("关注该公众账号的总用户数")
  15.   private Integer total;
  16.   @ApiModelProperty("拉取的OPENID个数,最大值为10000")
  17.   private Integer count;
  18.   @ApiModelProperty("列表数据,OPENID的列表")
  19.   private WxOpenidInfo data;
  20.   @ApiModelProperty("拉取列表的最后一个用户的OPENID")
  21.   private String next_openid;
  22. }
  23. @Data
  24. public class WxOpenidInfo {
  25.   private List<String> openid;
  26. }
复制代码
        2.调用微信接口相关
  1. import cn.hutool.core.collection.CollectionUtil;
  2. import cn.hutool.core.util.ObjectUtil;
  3. import cn.hutool.core.util.StrUtil;
  4. import com.alibaba.fastjson.JSON;
  5. import com.alibaba.fastjson.JSONObject;
  6. import com.google.common.base.Strings;
  7. import com.mzlion.easyokhttp.HttpClient;
  8. import jodd.util.StringUtil;
  9. import lombok.extern.slf4j.Slf4j;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.beans.factory.annotation.Value;
  12. import org.springframework.data.redis.core.RedisTemplate;
  13. import org.springframework.stereotype.Service;
  14. import org.springframework.web.client.RestTemplate;
  15. import tk.mybatis.mapper.entity.Example;
  16. import javax.annotation.Resource;
  17. import java.util.*;
  18. import java.util.stream.Collectors;
  19. @Slf4j
  20. @Service
  21. public class WeixinPublicService {
  22.     @Autowired
  23.     private RedisTemplate redisTemplate;
  24.     //公众号appId
  25.     @Value("${weixin.mp.account:xxxxxxxx}")
  26.     private String miniappAppId;
  27.     //公众号secret
  28.     @Value("${weixin.mp.secret:xxxxxxxxxxxxxxxxx}")
  29.     private String miniappSecret;
  30.     @Resource
  31.     private PublicUserMapper publicUserMapper;
  32.     public static final String ACCESS_TOKEN="weixin:access_token";
  33.     /**
  34.      * 判断小程序用户是否否关注的主要方法-根据unionId来查询用户观众公众号信息
  35.      * @param unionId
  36.      * @return
  37.      */
  38.     public WeixinUserInfoVo selectWeixinPublicUserInfoByUnionId(String unionId) {
  39.         //现查询数据库-根据unionid获取到openid-逻辑可自行实现
  40.         PublicUser dbPublicUser = publicUserMapper.selectPublicUserByUnionId(unionId);
  41.         WeixinUserInfoVo weixinUserInfoVo = null;
  42.         if (Objects.isNull(dbPublicUser)) {
  43.             //查询数据库-逻辑可自行实现
  44.             List<PublicUser> existPublicUsers = publicUserMapper.selectPublicUserList();
  45.             // 查询所有 openid
  46.             HashSet<String> openidSet = getUserOpenIdList();
  47.             if (!CollectionUtil.isEmpty(openidSet)) {
  48.                 if (!openidSet.isEmpty()) {
  49.                     // 差集
  50.                     for (PublicUser user : existPublicUsers) {
  51.                         openidSet.remove(user.getOpenId());
  52.                     }
  53.                 }
  54.             }
  55.             // 更新 未入库的 公众号信息
  56.             String openid = null;
  57.             RestTemplate restTemplate = new RestTemplate();
  58.             List<PublicUser> publicUserList = new ArrayList<>();
  59.             for (String id : openidSet) {
  60.                 // 根据openid查询unionId
  61.                 String requestUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token="
  62.                         + getAccessToken()
  63.                         + "&openid=" + id + "&lang=zh_CN";
  64.                 weixinUserInfoVo = restTemplate.getForObject(requestUrl, WeixinUserInfoVo.class);
  65.                 if (!ObjectUtil.isNull(weixinUserInfoVo) && ObjectUtil.isNull(weixinUserInfoVo.getErrcode())) {
  66.                     if (!StrUtil.isEmpty(weixinUserInfoVo.getUnionid())) {
  67.                         publicUserList.add(PublicUser.builder().openId(weixinUserInfoVo.getOpenid()).unionId(weixinUserInfoVo.getUnionid()).build());
  68.                         if (unionId.equals(weixinUserInfoVo.getUnionid())) {
  69.                             openid = id;
  70.                         }
  71.                     }
  72.                 }
  73.             }
  74.             if (!CollectionUtil.isEmpty(publicUserList)) {
  75.                 this.publicUserMapper.insertList(publicUserList);
  76.             }
  77.         }else {
  78.             RestTemplate restTemplate = new RestTemplate();
  79.             String requestUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token="
  80.                     + getAccessToken()
  81.                     + "&openid=" + dbPublicUsers.get(0).getOpenId() + "&lang=zh_CN";
  82.             weixinUserInfoVo = restTemplate.getForObject(requestUrl, WeixinUserInfoVo.class);
  83.         }
  84.         return weixinUserInfoVo;
  85.     }
  86.     /**
  87.      * 获取请求token
  88.      * @return
  89.      */
  90.     private String getAccessToken() {
  91.         String accessToken = (String) this.redisTemplate.opsForValue().get(ACCESS_TOKEN);
  92.         if (StrUtil.isEmpty(accessToken)) {
  93.             String result = HttpClient.get(
  94.                             "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET".replace(
  95.                                     "APPID", this.miniappAppId).replace("APPSECRET", this.miniappSecret))
  96.                     .asString();
  97.             log.info("getAccessToken---result===>"+result);
  98.             if (!Strings.isNullOrEmpty(result)) {
  99.                 Integer expiresIn = null;
  100.                 JSONObject jsonObject = JSON.parseObject(result);
  101.                 if (ObjectUtil.isNotNull(jsonObject)) {
  102.                     expiresIn = (Integer) jsonObject.get("expires_in");
  103.                     accessToken = (String) jsonObject.get("access_token");
  104.                 }
  105.                 log.info("getAccessToken---accessToken===>"+accessToken);
  106.                 if (StrUtil.isNotEmpty(accessToken) && ObjectUtil.isNotNull(expiresIn)) {
  107.                     this.redisTemplate.opsForValue().set(ACCESS_TOKEN, accessToken, expiresIn - 20);
  108.                 }
  109.             }
  110.         }
  111.         return accessToken;
  112.     }
  113.     /**
  114.      * 初始化所有公众号用户数据
  115.      */
  116.     public void init() {
  117.         //查询数据库-逻辑可自行实现
  118.         List<PublicUser> dbPublicUsers = publicUserMapper.selectPublicUserList();
  119.         List<String> existOpenIds = new ArrayList<>();
  120.         if (dbPublicUsers != null && !dbPublicUsers.isEmpty()) {
  121.             existOpenIds.addAll(dbPublicUsers.stream().map(PublicUser::getOpenId)
  122.                     .collect(Collectors.toList()));
  123.         }
  124.         // 查询所有 openid
  125.         HashSet<String> openidSet = getUserOpenIdList();
  126.         //去除已经存在的
  127.         openidSet.removeIf(existOpenIds::contains);
  128.         // 更新 未入库的 公众号信息
  129.         RestTemplate restTemplate = new RestTemplate();
  130.         List<PublicUser> publicUserList = new ArrayList<>();
  131.         for (String openId : openidSet) {
  132.             // 根据openid查询unionId
  133.             String requestUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token="
  134.                     + getAccessToken()
  135.                     + "&openid=" + openId + "&lang=zh_CN";
  136.             WeixinUserInfoVo weixinUserInfoVo = restTemplate.getForObject(requestUrl, WeixinUserInfoVo.class);
  137.             if (!ObjectUtil.isNull(weixinUserInfoVo) && ObjectUtil.isNull(weixinUserInfoVo.getErrcode())) {
  138.                 if (!StrUtil.isEmpty(weixinUserInfoVo.getUnionid())) {
  139.                     publicUserList.add(PublicUser.builder().openId(weixinUserInfoVo.getOpenid()).unionId(weixinUserInfoVo.getUnionid()).build());
  140.                 }
  141.             }
  142.             //一次性插入一百条 防止服务断掉 导致全没拉下来
  143.             if (!CollectionUtil.isEmpty(publicUserList) && publicUserList.size() == 100) {
  144.                 this.publicUserMapper.insertList(publicUserList);
  145.                 publicUserList.clear();
  146.             }
  147.         }
  148.         if (!CollectionUtil.isEmpty(publicUserList)) {
  149.             this.publicUserMapper.insertList(publicUserList);
  150.         }
  151.     }
  152.     /**
  153.      * 获取公众号关注用户列表的openid
  154.      * @return
  155.      */
  156.     public HashSet<String> getUserOpenIdList() {
  157.         //获取最新的access_token
  158.         String accessToken = getAccessToken();
  159.         log.info("accessToken===>"+new String(accessToken));
  160.         RestTemplate restTemplate = new RestTemplate();
  161.         WeixinUserListVo openIdList = null;
  162.         HashSet<String> openidSet = new HashSet<String>();
  163.         synchronized (this) {
  164.             try {
  165.                 //循环获取用户openid列表--一次获取10000
  166.                 String nextOpenid = null;
  167.                 do {
  168.                     //微信公众号获取用户列表信息接口地址
  169.                     String requestUrl = null;
  170.                     if (StringUtil.isBlank(nextOpenid)) {
  171.                         requestUrl = "https://api.weixin.qq.com/cgi-bin/user/get?access_token="
  172.                                 + accessToken;
  173.                     } else {
  174.                         requestUrl = "https://api.weixin.qq.com/cgi-bin/user/get?access_token="
  175.                                 + accessToken + "&next_openid=" + nextOpenid;
  176.                     }
  177.                     openIdList = restTemplate.getForObject(requestUrl, WeixinUserListVo.class);
  178.                     if (openIdList != null && Objects.nonNull(openIdList.getData())) {
  179.                         //获取用户关注列表对象
  180.                         WxOpenidInfo data = openIdList.getData();
  181.                         //获取当前循环的openid--10000条
  182.                         openidSet.addAll(data.getOpenid());
  183.                         //拉取列表的最后一个用户的OPENID
  184.                         nextOpenid = openIdList.getNext_openid();
  185.                     }
  186.                 } while (Objects.nonNull(openIdList.getData()));
  187.             } catch (Exception e) {
  188.                 log.debug("获取用户列表失败:{}", openIdList);
  189.                 return null;
  190.             }
  191.         }
  192.         return openidSet;
  193.     }
  194. }
复制代码
3.判断是否关注的逻辑
   根据调用selectWeixinPublicUserInfoByUnionId的返回判断是否关注
          ①已关注(subscribe字段判断 1:已关注) 
 


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

梦见你的名字

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表