本文从零开始到获取用户openid并存到数据库
运用到SpringBoot+mybatis+RestTemplate

准备条件

需要一个公众

微信公众号上完成获取用户openid—–详细教程-编程知识网

需要简单配置一下,在左方菜单最下方—-开发–基本配置—白名单这里填写电脑现自身的ip(本项目本地跑)

获取ip:https://www.ip138.com/

微信公众号上完成获取用户openid—–详细教程-编程知识网
查看微信公众平台开发文档
https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html

获取access_token

access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。

接口调用请求说明https请求方式: GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET`

官方的接口调式工具测试,走一遍获取用户列表流程

微信公众平台接口调试工具:https://mp.weixin.qq.com/debug/cgi-bin/apiinfo?t=index&type=%E5%9F%BA%E7%A1%80%E6%94%AF%E6%8C%81&form=%E8%8E%B7%E5%8F%96access_token%E6%8E%A5%E5%8F%A3%20/token
微信公众号上完成获取用户openid—–详细教程-编程知识网

失败请查阅文档,了解详情

微信公众号上完成获取用户openid—–详细教程-编程知识网

获取用户列表

公众号可通过本接口来获取帐号的关注者列表,关注者列表由一串OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的)组成。一次拉取调用最多拉取10000个关注者的OpenID,可以通过多次拉取的方式来满足需求。例如:
公众账号A拥有23000个关注的人,想通过拉取关注接口获取所有关注的人,那么分别请求url如下:https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN 返回结果:
{
“total”:23000,
“count”:10000,
“data”:{"
openid":[
“OPENID1”,
“OPENID2”,
…,
“OPENID10000”
]
},
“next_openid”:“OPENID10000”
}https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID1返回结果:
{
“total”:23000,
“count”:10000,
“data”:{
“openid”:[
“OPENID10001”,
“OPENID10002”,
…,
“OPENID20000”
]
},
“next_openid”:“OPENID20000”
}https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID2返回结果(关注者列表已返回完时,返回next_openid为空):
{
“total”:23000,
“count”:3000,
“data”:{"
“openid”:[
“OPENID20001”,
“OPENID20002”,
…,
“OPENID23000”
]
},
“next_openid”:“OPENID23000”
}

接口调用请求说明http请求方式: GET(请使用https协议)
https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID

微信公众号上完成获取用户openid—–详细教程-编程知识网
失败请查阅文档,了解详情
微信公众号上完成获取用户openid—–详细教程-编程知识网

以上都成功,我们开始写代码

所有注释都已经在代码中标识,就不做多阐述,逻辑很简单,直接贴上详细代码

项目目录结构和数据库设计

微信公众号上完成获取用户openid—–详细教程-编程知识网

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.2</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>template</artifactId><version>0.0.1-SNAPSHOT</version><name>template</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.62</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.5</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.3</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build>
</project>

application.yml —–填写自己的数据库信息

spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: ?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC&useSSL=falseusername: password: mybatis:mapper-locations: classpath*:mapper/*Mapper.xmlserver:port: 8888

Constast—更换自己相应的数据

package com.example.template.common;import lombok.Data;/*** 微信参数*/
@Data
public class Constast {//开发者IDpublic static final String AppId="wx1###########bfe";//开发者密码public static final String AppSecret="49######################667";//接口凭证access_tokenprivate String access_token;//凭证时效private int expires_in;//我的openidpublic static final String HuHaoAppId="oP######################wM";//模板template_idpublic static final String TemplateId="88d######################4ULcs";//违章查询路径public  static final String PagePath="pages/###########index?routeKey=PC01_RE############################################tagid=104.233.5";//违章查询的AppIdpublic static final String XcxAppId="wx0###########f5b2";
}

WeixinUserListVo

package com.example.template.vo;import lombok.Data;@Data
public class WeixinUserListVo {private Integer total;//关注该公众账号的总用户数private Integer count;//拉取的OPENID个数,最大值为10000private WxOpenidInfo data;//列表数据,OPENID的列表private String next_openid;//拉取列表的最后一个用户的OPENIDprivate int errcode;//错误编码private String errmsg = "ok";//错误提示
}

WxOpenidInfo

package com.example.template.vo;import lombok.Data;
import java.util.List;@Data
public class WxOpenidInfo {private List<String> openid;
}

TemplateController

package com.example.template.controller;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.template.common.Constast;
import com.example.template.service.TemplateService;
import com.example.template.vo.WeixinUserListVo;
import com.example.template.vo.WxOpenidInfo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@RestController
@RequestMapping("/a")
public class TemplateController {private static final Logger logger = LoggerFactory.getLogger(TemplateController.class);@Autowiredprivate TemplateService templateService;//获取access_token,access_token是公众号的全局唯一接口调用凭据public static Constast getAccessToken() {RestTemplate restTemplate = new RestTemplate();Map<String, String> map = new HashMap<>();map.put("AppId", Constast.AppId);map.put("AppSecret", Constast.AppSecret);//调用微信公众号接口ResponseEntity<String> forEntity = restTemplate.getForEntity("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={AppId}&secret={AppSecret}", String.class, map);String body = forEntity.getBody();JSONObject jsonObject = JSON.parseObject(body);String access_token = jsonObject.getString("access_token");String expires_in = jsonObject.getString("expires_in");//时效--7200sConstast constast = new Constast();constast.setAccess_token(access_token);return constast;}//获取用户列表的openid@RequestMapping("/a")public WeixinUserListVo getUserOpenIdList() {//获取最新的access_tokenString accessToken = TemplateController.getAccessToken().getAccess_token();RestTemplate restTemplate = new RestTemplate();WeixinUserListVo openIdList = null;synchronized (this) {try {//循环获取用户openid列表--一次获取10000String nextOpenid = null;do {//微信公众号获取用户列表信息接口地址String requestUrl = null;if (StringUtils.isBlank(nextOpenid)) {requestUrl = new StringBuffer().append("https://api.weixin.qq.com/cgi-bin/user/get?access_token=").append(accessToken).toString();} else {requestUrl = new StringBuffer().append("https://api.weixin.qq.com/cgi-bin/user/get?access_token=").append(accessToken).append("&next_openid=").append(nextOpenid).toString();}openIdList = restTemplate.getForObject(requestUrl, WeixinUserListVo.class);if (openIdList != null && openIdList.getErrcode() == 0) {//获取用户关注列表对象WxOpenidInfo data = openIdList.getData();if (data != null) {//获取当前循环的openid--10000条List<String> openid = data.getOpenid();if (openid != null && openid.size() > 0) {for (int i = 0; i < openid.size(); i += 100) {int toIndex = 100;if (i + 100 > openid.size()) {// 注意下标问题toIndex = openid.size() - i;}//循环100次,每次拿到openid列表中的集合下标;例如:(0,100),(100,200)List<String> sendList = openid.subList(i, i + toIndex);//每次insert---100条int num = templateService.insertForeach(sendList);}}}//拉取列表的最后一个用户的OPENIDnextOpenid = openIdList.getNext_openid();System.out.println(nextOpenid);} else {openIdList.setErrcode(40000);openIdList.setErrmsg("获取关注用户列表失败");return openIdList;}} while (openIdList.getCount() > 0);} catch (Exception e) {openIdList.setErrcode(40000);openIdList.setErrmsg("获取用户列表失败");return openIdList;}}return openIdList;}
}

TemplateServiceImpl

package com.example.template.service.impl;import com.example.template.mapper.TemplateMapper;
import com.example.template.service.TemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;@Service
@Transactional
public class TemplateServiceImpl implements TemplateService {@Autowiredprivate TemplateMapper templateMapper;@Overridepublic int insertForeach(List list) {int i = templateMapper.insertForeach(list);return i;}
}

TemplateService

package com.example.template.service;import java.util.List;public interface TemplateService {int insertForeach(List list);
}

TemplateMapper

package com.example.template.mapper;import org.apache.ibatis.annotations.Mapper;
import java.util.List;@Mapper
public interface TemplateMapper {int insertForeach(List list);
}

TemplateMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.template.mapper.TemplateMapper"><insert id="insertForeach" parameterType="java.util.List" useGeneratedKeys="false">insert into template (openid)values<foreach collection="list" item="item" index="index" separator=",">(#{item})</foreach></insert>
</mapper>

启动项目:http://localhost:8888/a/a

模板消息:微信公众号完成模板消息—–详细教程