猫了个眯 發表於 2022-1-15 11:48:00

微信公众号开发之Access token+redis存储token(三)

<h2 id="自定义菜单需要获取access-token">自定义菜单需要获取Access token</h2>
<blockquote>
<p>公众号使用AppID和AppSecret调用接口来获取access_token<br>
公众号和小程序均可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在“微信公众平台-开发-基本配置”页中获得</p>
</blockquote>
<blockquote>
<p>access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。</p>
</blockquote>
<blockquote>
<p>access_token的有效期是7200秒(两小时),在有效期内,可以一直使用,只有当access_token过期时,才需要再次调用接口 获取access_token。在理想情况下,一个7x24小时运行的系统,每天只需要获取12次access_token,即每2小时获取一次。如果在 有效期内,再次获取access_token,那么上一次获取的access_token将失效。<br>
目前,获取access_token接口的调用频率限制为2000次/天,如果每次发送客服消息、获取用户信息、群发消息之前都要先调用获取 access_token接口得到接口访问凭证,这显然是不合理的,一方面会更耗时(多了一次接口调用操作),另一方面2000次/天的调用限制恐怕也不 够用。因此,在实际应用中,我们需要将获取到的access_token存储起来,然后定期调用access_token接口更新它,以保证随时取出的 access_token都是有效的。</p>
</blockquote>
<p>原文链接</p>
<blockquote>
<p>先看完成的例子</p>
</blockquote>
<p><img src="https://img2022.cnblogs.com/blog/1898315/202201/1898315-20220119004512063-2108853638.gif" alt="" loading="lazy"></p>
<h3 id="接口调用请求说明">接口调用请求说明</h3>
<blockquote>
<p>https请求方式: GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&amp;appid=APPID&amp;secret=APPSECRET</p>
</blockquote>
<h3 id="参数说明">参数说明</h3>
<table>
<thead>
<tr>
<th>参数</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>grant_type</td>
<td>获取access_token填写client_credential</td>
</tr>
<tr>
<td>appid</td>
<td>第三方用户唯一凭证</td>
</tr>
<tr>
<td>secret</td>
<td>第三方用户唯一凭证密钥,即appsecret</td>
</tr>
</tbody>
</table>
<h3 id="返回说明">返回说明</h3>
<p>正常情况下,微信会返回下述JSON数据包给公众号:</p>
<blockquote>
<p>{"access_token":"ACCESS_TOKEN","expires_in":7200}<br>
参数说明</p>
</blockquote>
<table>
<thead>
<tr>
<th>参数</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>access_token</td>
<td>获取到的凭证</td>
</tr>
<tr>
<td>expires_in</td>
<td>凭证有效时间,单位:秒</td>
</tr>
</tbody>
</table>
<h3 id="封装这两个参数">封装这两个参数</h3>
<pre><code class="language-java">package com.rzk.pojo;

import lombok.Data;

@Data
public class Token {
    private String accessToken;
    private int expiresIn;
}
</code></pre>
<h3 id="httpconstant">HttpConstant</h3>
<pre><code class="language-java">package com.rzk.util;
public class HttpConstant {

    //获取Access token URI
    public static String API_URI = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&amp;appid=APPID&amp;secret=APPSECRET";
}
</code></pre>
<h3 id="httpclient-工具类">HttpClient 工具类</h3>
<pre><code class="language-java">package com.rzk.util;

import com.rzk.pojo.Token;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;

public class HttpClient {

    /**
   * GET请求
   * @param url
   * @return
   */
    public static String doGetRequest(String url) {
      String result = "";
      CloseableHttpClient httpClient = HttpClientBuilder.create().build();
      HttpGet httpGet = new HttpGet(url);
      CloseableHttpResponse response = null;
      try {
            response = httpClient.execute(httpGet);
            HttpEntity responseEntity = response.getEntity();
            result = EntityUtils.toString(responseEntity);
      } catch (Exception e) {
            e.printStackTrace();
      }finally {
            try {
                if (httpClient != null) {
                  httpClient.close();
                }
                if (response != null) {
                  response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
      }return result;
    }
}
</code></pre>
<h3 id="wxservercontroller">WxServerController</h3>
<pre><code class="language-java">    @GetMapping(value = "accessToken")
    public String AccessToken(){
      Token token = new Token();
      //使用httpclient请求
      String result = HttpClient.doGetRequest(HttpConstant.API_URI.replace("APPID", environment.getProperty("wx.appid")).replace("APPSECRET", environment.getProperty("wx.secret")));
      //转成json对象
      JSONObject json = JSON.parseObject(result);
      token.setAccessToken(String.valueOf(json.get("access_token")));

      return token.getAccessToken();
    }
</code></pre>
<h3 id="请求accesstoken">请求accessToken</h3>
<blockquote>
<p>还要去公众号基础设置开启白名单访问列表,填上你的服务器ip地址即可</p>
</blockquote>
<p><img src="https://img2020.cnblogs.com/blog/1898315/202201/1898315-20220115002515158-676657563.png" alt="" loading="lazy"></p>
<h2 id="整合redis存储accesstoken">整合redis存储accessToken</h2>
<h3 id="pomxml">pom.xml</h3>
<pre><code class="language-pom">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
    &lt;parent&gt;
      &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
      &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
      &lt;version&gt;2.6.2&lt;/version&gt;
      &lt;relativePath/&gt; &lt;!-- lookup parent from repository --&gt;
    &lt;/parent&gt;
    &lt;groupId&gt;com.rzk&lt;/groupId&gt;
    &lt;artifactId&gt;wxserver&lt;/artifactId&gt;
    &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
    &lt;name&gt;wxserver&lt;/name&gt;
    &lt;description&gt;wxserver&lt;/description&gt;
    &lt;properties&gt;
      &lt;java.version&gt;1.8&lt;/java.version&gt;
      &lt;httpclient.version&gt;4.5.13&lt;/httpclient.version&gt;
      &lt;fastjson.version&gt;1.2.76&lt;/fastjson.version&gt;
      &lt;commons-lang.version&gt;2.6&lt;/commons-lang.version&gt;
    &lt;/properties&gt;
    &lt;dependencies&gt;
      &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
      &lt;/dependency&gt;

      &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-devtools&lt;/artifactId&gt;
            &lt;scope&gt;runtime&lt;/scope&gt;
            &lt;optional&gt;true&lt;/optional&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
            &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
            &lt;artifactId&gt;lombok&lt;/artifactId&gt;
            &lt;optional&gt;true&lt;/optional&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
            &lt;scope&gt;test&lt;/scope&gt;
      &lt;/dependency&gt;
      &lt;!--httpclient --&gt;
      &lt;dependency&gt;
            &lt;groupId&gt;org.apache.httpcomponents&lt;/groupId&gt;
            &lt;artifactId&gt;httpclient&lt;/artifactId&gt;
            &lt;version&gt;${httpclient.version}&lt;/version&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
            &lt;groupId&gt;com.alibaba&lt;/groupId&gt;
            &lt;artifactId&gt;fastjson&lt;/artifactId&gt;
            &lt;version&gt;${fastjson.version}&lt;/version&gt;
      &lt;/dependency&gt;
      &lt;!--redis--&gt;
      &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-data-redis&lt;/artifactId&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
            &lt;groupId&gt;commons-lang&lt;/groupId&gt;
            &lt;artifactId&gt;commons-lang&lt;/artifactId&gt;
            &lt;version&gt;${commons-lang.version}&lt;/version&gt;
      &lt;/dependency&gt;
    &lt;/dependencies&gt;

    &lt;build&gt;
      &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
                &lt;configuration&gt;
                  &lt;excludes&gt;
                        &lt;exclude&gt;
                            &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
                            &lt;artifactId&gt;lombok&lt;/artifactId&gt;
                        &lt;/exclude&gt;
                  &lt;/excludes&gt;
                &lt;/configuration&gt;
            &lt;/plugin&gt;
      &lt;/plugins&gt;
    &lt;/build&gt;
&lt;/project&gt;
</code></pre>
<h3 id="applicationyml配置文件">application.yml配置文件</h3>
<blockquote>
<p>配置文件</p>
</blockquote>
<pre><code class="language-yml">
spring:
redis:
    #超过时间
    timeout: 10000ms
    #地址
    host: ip
    #端口
    port: 6382
    #数据库
    database: 0
    password: 密码
    lettuce:
      pool:
      #最大连接数 默认8
      max-active: 1024
      # 最大连接阻塞等待时间,默认-1
      max-wait: 10000ms
      #最大空闲连接
      max-idle: 200
      #最小空闲连接
      min-idle: 5
    #哨兵模式
    sentinel:
      #主节点名称
      master: mymaster
      #节点
      nodes: ip:26381,ip:26382,ip:26383
</code></pre>
<h3 id="controller">Controller</h3>
<pre><code class="language-java">
    @GetMapping(value = "accessToken")
    public String getAccessToken(){
      Token token = new Token();
      //如果不等于空 或者小于600秒
      if (redisTemplate.getExpire("expires_in")&lt;600||redisTemplate.getExpire("expires_in")==null){

            //使用httpclient请求
            String result = HttpClient.doGetRequest(HttpConstant.API_URI.replace("APPID", environment.getProperty("wx.appid")).replace("APPSECRET", environment.getProperty("wx.secret")));

            //转成json对象
            JSONObject json = JSON.parseObject(result);
            System.out.println(json);
            token.setAccessToken(String.valueOf(json.get("access_token")));
            token.setExpiresIn((Integer) json.get("expires_in"));
            System.out.println(json.get("expires_in"));
            System.out.println(token.getExpiresIn());
            redisTemplate.opsForValue().set("accessToken",json.get("access_token"));
            redisTemplate.opsForValue().set("expiresIn",json.get("expires_in"),7200, TimeUnit.SECONDS);
      }
      String accessToken = redisTemplate.opsForValue().get("accessToken").toString();
      Long expiresIn = redisTemplate.getExpire("expiresIn");
      logger.info("accessToken{}:"+accessToken);
      logger.info("expiresIn{}:"+expiresIn);

      return token.getAccessToken();
    }

</code></pre>
<p>我使用redis流程</p>
<p><img src="https://img2022.cnblogs.com/blog/1898315/202201/1898315-20220119004542247-1863131944.png" alt="" loading="lazy"></p>
<blockquote>
<p>后续可用springboot自带的定时任务处理器去开启定时任务功能<br>
这里就不贴定时任务的代码了</p>
</blockquote><br><br>
来源:https://www.cnblogs.com/rzkwz/p/15806642.html
頁: [1]
查看完整版本: 微信公众号开发之Access token+redis存储token(三)