微信公众号开发——获取AccessToken接口调用凭据

news2024/11/15 9:27:47
😊 @ 作者: 一恍过去
💖 @ 主页: https://blog.csdn.net/zhuocailing3390
🎊 @ 社区: Java技术栈交流
🎉 @ 主题: 微信公众号开发——获取AccessToken接口调用凭据
⏱️ @ 创作时间: 2022年12月11日

目录

  • 准备工作
  • 1、公众平台接口调试示例
  • 2、Java代码实现
    • 1、配置Yaml
    • 2、配置参数Bean对象
    • 3、封装请求与响应参数
    • 4、配置工具类
    • 5、配置RestTemplate请求
    • 6、请求示例

准备工作

在调用微信接口获取AccessToken时,需要使用到微信公众号的appidsecret,获取方式如下:

  • 已有公众号: 有属于自己的公众号账户,登录微信公众平台(https://mp.weixin.qq.com),在左侧菜单栏下方的设置与开发中的基本配置菜单中即可获取;
    在这里插入图片描述
    在这里插入图片描述

  • 测试公众号: 如果没有现成的公众号账户,或者只是测试公众号功能,可从微信提供的沙箱测试环境(http://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo)中获取appidsecret
    在这里插入图片描述

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

1、公众平台接口调试示例

示例地址:https://mp.weixin.qq.com/debug/cgi-bin/apiinfo
在这里插入图片描述

2、Java代码实现

1、配置Yaml

wx:
  appid: wx79xxxxxxxx11b9
  secret: 1c79a1xxxxxxxxxxxxxx2a73a08
  apiUrl: https://api.weixin.qq.com/

2、配置参数Bean对象

@Component
@ConfigurationProperties(prefix = "wx")
@Data
public class WxBean {
    private String appid;
    private String secret;
    private String apiUrl;
}

3、封装请求与响应参数

AccessTokenRep:

@Data
public class AccessTokenRep {
    /**
     * 获取access_token填写client_credential
     */
    private String grant_type;

    /**
     * 第三方用户唯一凭证
     */
    private String appid;

    /**
     * 第三方用户唯一凭证密钥,即appsecret
     */
    private String secret;
}

AccessTokenRes:

@Data 
public class AccessTokenRes {
    /**
     * 获取到的凭证
     */
    private String access_token;

    /**
     * 凭证有效时间,单位:秒
     */
    private Integer expires_in;
}

4、配置工具类


public class MapUtils {

    /**
     * Map转换为 Entity
     *
     * @param params 包含参数的Map
     * @param t      需要赋值的实体
     * @param <T>    类型
     */
    public static <T> T mapToEntity(Map<String, Object> params, T t) {
        if (null == params) {
            return t;
        }
        Class<?> clazz = t.getClass();
        Field[] declaredFields = clazz.getDeclaredFields();
        try {
            for (Field declaredField : declaredFields) {
                declaredField.setAccessible(true);
                String name = declaredField.getName();
                if (null != params.get(name)) {
                    declaredField.set(t, params.get(name));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("属性设置失败!");
        }
        return t;
    }

    /**
     * 将对象转换为HashMap
     *
     * @param t   转换为Map的对象
     * @param <T> 转换为Map的类
     * @return Map
     */
    public static <T> Map<String, Object> entityToMap(T t) {
        Class<?> clazz = t.getClass();
        List<Field> allField = getAllField(clazz);
        Map<String, Object> hashMap = new HashMap<>(allField.size());
        try {
            for (Field declaredField : allField) {
                declaredField.setAccessible(true);
                Object o = declaredField.get(t);
                if (null != o) {
                    hashMap.put(declaredField.getName(), o);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("属性获取失败!");
        }
        return hashMap;
    }

    /**
     * 获取所有属性
     *
     * @param clazz class
     * @param <T>   泛型
     * @return List<Field>
     */
    public static <T> List<Field> getAllField(Class<T> clazz) {
        List<Field> fields = new ArrayList<>();
        Class<?> superClazz = clazz;
        while (null != superClazz) {
            fields.addAll(Arrays.asList(superClazz.getDeclaredFields()));
            superClazz = superClazz.getSuperclass();
        }
        return fields;
    }

    /**
     * 将Map参数转换为字符串
     *
     * @param map
     * @return
     */
    public static String mapToString(Map<String, Object> map) {
        StringBuffer sb = new StringBuffer();
        map.forEach((key, value) -> {
            sb.append(key).append("=").append(value.toString()).append("&");
        });
        String str = sb.toString();
        str = str.substring(0, str.length() - 1);
        return str;
    }

    /**
     * 将Bean对象转换Url请求的字符串
     *
     * @param t
     * @param <T>
     * @return
     */
    public static <T> String getUrlByBean(T t) {
        String pre = "?";
        Map<String, Object> map = entityToMap(t);
        return pre + mapToString(map);
    }
}

5、配置RestTemplate请求

@Component
public class RestHttpRequest {

    private final RestTemplate restTemplate;

    public RestHttpRequest(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }
    
    public Map doHttp(String url, HttpMethod method, Object obj) {
        HttpHeaders headers = new HttpHeaders();
        HttpEntity entity = new HttpEntity(obj, headers);
        ResponseEntity<Map> exchange = restTemplate.exchange(url, method, entity, Map.class);
        return exchange.getBody();
    }
}

6、请求示例

代码中为了避免频繁的请求,将获取的accessToken存入Redis中,如果Redis中存在数据,则直接从Redis中获取而不是请求微信接口获取。

@Slf4j
@Controller
@ResponseBody
public class WeChantController {
    @GetMapping("/accessToken")
    public String getAccessToken() {
        String accessTokenKey = "access_token";
        log.info("#### 获取公众号 AccessToken ####");
        RedisUtils.del(accessTokenKey);
        if (RedisUtils.hasKey(accessTokenKey)) {
            log.info("#### 从缓存中获取AccessToken ####");
            return RedisUtils.get(accessTokenKey).toString();
        }
        String url = wxBean.getApiUrl() + "cgi-bin/token";
        //封装url请求参数
        AccessTokenRep rep = new AccessTokenRep();
        rep.setAppid(wxBean.getAppid());
        rep.setSecret(wxBean.getSecret());
        rep.setGrant_type("client_credential");
        url = url + MapUtils.getUrlByBean(rep);
        Map map = restHttpRequest.doHttp(url, HttpMethod.GET, null);
        // 处理返回对象
        AccessTokenRes res = new AccessTokenRes();
        MapUtils.mapToEntity(map, res);
        // 加入Redis缓存
        String accessToken = res.getAccess_token();
        Integer expires = res.getExpires_in();
        RedisUtils.setEx(accessTokenKey, accessToken, expires / 2, TimeUnit.SECONDS);
        // 返回
        return accessToken;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/79897.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Typora的使用

一&#xff0e;标题&#xff1a;六级标题 1 .一级标题 2. 二级标题 二级标题 &#xff1a; ## 加一个空格 现在加 ## 空格 然后我们把光标放在其他地方 点击一下 3 层级列表 层级列表: > 空格 回车 在这一部分&#xff0c;我们先来讲解三个概念&#xff1a…

基于java+springboot+mybatis+vue+mysql的篮球竞赛预约平台

项目介绍 随着人们生活质量提高&#xff0c;越来越多的年轻人喜欢足球。尤其是在高校之中&#xff0c;每年都会举办一些足球和篮球比赛。甚至在国际上每年也都会有一足球和篮球联赛。很多高校为了提高学生的身体素质每年也都会举办一些篮球竞赛&#xff0c;为了让这些篮球爱好…

计算机毕业设计ssm+vue基本微信小程序的奶茶点单系统

随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受客户的喜爱&#xff0c;随便点奶茶点单小程序被客户普遍使用&#xff0c;为方便客户能够…

《发现心流》

关于作者 米哈里•契克森米哈赖&#xff0c;任教于美国加州克 菜蒙特大学&#xff0c;提出并发展了心流理论。他 一直在关注人类的积极心理体验&#xff0c;完成了 大量经典的研究工作&#xff0c;是该领域最权威的 学者之一&#xff0c;被誉为积极心理学的世界级领 军人物。 …

日期与时间

目录 一、基本概念 1.1、日期和时间 1.2、本地时间 1.3、时区 1.4、夏令时 1.5、本地化 二、Date 和 Calendar 2.1、Date 2.2、Calendar 三、TimeZone 四、LocalDateTime 4.1、LocalDateTime 4.2、Duration和Period 五、ZoneDateTime 5.1、创建实例 5.2、时区转…

电子学会2020年12月青少年软件编程(图形化)等级考试试卷(一级)答案解析

目录 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 二、判断题&#xff08;共10题&#xff0c;每题2分&#xff0c;共20分&#xff09; 三、编程题【该题由测评师线下评分】&#xff08;共2题&#xff0c;共30分&#xff09; 青少年软件…

【MySQL数据库】索引到底是什么,怎么创建索引的效率最高

面试官&#xff1a;我看你简历上写了MySQL&#xff0c;对MySQL InnoDB引擎的索引了解吗&#xff1f; 候选者&#xff1a;嗯啊&#xff0c;使用索引可以加快查询速度&#xff0c;其实上就是将无序的数据变成有序&#xff08;有序就能加快检索速度&#xff09; 候选者&#xff…

微服务守护神-Sentinel-其他

引言 书接上篇 微服务守护神-Sentinel-热点-授权-系统规则 &#xff0c;上面介绍了Sentinel热点、授权、系统规则&#xff0c;本篇继续来Sentinel 剩下其他操作 自定义异常返回 当触发sentinel流控规则之后&#xff0c; sentinel就干巴巴返回异常信息&#xff0c;单纯的文字…

JVM监控及诊断工具

本文目录命令行jps 查看正在运行的Java进程jstat&#xff1a;查看JVM统计信息jinfo&#xff1a;实时查看和修改JVM配置参数jmap&#xff1a;导出内存映像文件&内存使用情况jhat&#xff1a;JDK自带堆分析工具jstack&#xff1a;打印JVM中线程快照jcmd&#xff1a;多功能命令…

docker、LXC、LXD的区别及传统的虚拟机与操作系统虚拟化的区别

1. 概念解释 1.1. Docker Docker是一个用于在集中式平台上创建、部署和运行应用程序的开源工具。这使得主机的操作系统通过容器运行具有相同Linux内核的应用程序&#xff0c;而不是创建一个完整的虚拟机。使用docker容器不需要考虑Ram和磁盘空间的分配。它能够自己处理这些需…

CopyOnWriteArrayList源码解析

CopyOnWriteArrayList源码解析 简介 我们知道 ArrayList 是线程不安全的&#xff0c;其存在一个古老的线程安全的 Vector&#xff0c;但是由于 Vector 效率太低 (方法都加了synchronzed)&#xff0c;在 JDK1.5 时 Doug Lea 提供了一个效率较高的线程安全的 CopyOnWriteArrayL…

虚拟内存(深入理解计算机系统原书第3版9节)

深入理解计算机系统&#xff08;原书第3版&#xff09;读书笔记&#xff0c;其实就是嚼碎了原文然后把一部分挑了出来摘要&#xff0c;免得读着读着忘了 文章目录前言一、物理和虚拟寻址二、地址空间三、虚拟内存作为缓存的工具1、DRAM缓存的组织结构2、页表3、页命中4、缺页5、…

[附源码]Python计算机毕业设计SSM基于的小区物业管理系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

微服务框架 SpringCloud微服务架构 微服务保护 33 授权规则 33.1 授权规则

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 微服务保护 文章目录微服务框架微服务保护33 授权规则33.1 授权规则33.1.1 授权规则33 授权规则 33.1 授权规则 33.1.1 授权规则 看看sen…

康鹏科技将于12月16日上会:曾在纽交所上市,由杨建华家族控股

近日&#xff0c;上海康鹏科技股份有限公司&#xff08;下称“康鹏科技”&#xff09;在上海证券交易所递交招股书&#xff08;上会稿&#xff09;&#xff0c;准备在科创板上市。据贝多财经了解&#xff0c;康鹏科技将于2022年12月16日接受科创板上市委的现场审议。 根据公开信…

基于C++实现(MFC)职工工作量统计系统【100010022】

【职工工作量统计系统设计】 1、问题描述 职工包括姓名、职工号、性别、年龄、所在部门、联系方式等信息。 工作量包括职工号、完成的产品数量等信息。 该设计系统能够对职工的工作量进行统计&#xff0c;并排出名次。注意&#xff0c;一个职工的工作量是可以多次输入的。 2…

Alibaba官方上线,Java并发编程全彩图册(终极版)GitHub已置顶

都说程序员工资高、待遇好&#xff0c; 2022 金九银十到了&#xff0c;你的小目标是 30K、40K&#xff0c;还是 16薪的 20K&#xff1f;作为一名 Java 开发工程师&#xff0c;当能力可以满足公司业务需求时&#xff0c;拿到超预期的 Offer 并不算难。然而&#xff0c;提升 Java…

Python图像识别实战(一):实现按数量随机抽取图像复制到另一文件夹(附源码和实现效果)

前面我介绍了可视化的一些方法以及机器学习在预测方面的应用&#xff0c;分为分类问题&#xff08;预测值是离散型&#xff09;和回归问题&#xff08;预测值是连续型&#xff09;&#xff08;具体见之前的文章&#xff09;。 从本期开始&#xff0c;我将做一个关于图像识别的…

Qt实现全局鼠标事件监听器-Linux

Qt实现全局鼠标事件监听器-Linux版&#x1f991; var code “bc8d4eb4-a9df-48e9-8028-bbe1ae7fbd05” 文章目录Qt实现全局鼠标事件监听器-Linux版&#x1f991;1、概述&#x1f99e;2、实现效果&#x1f370;3、实现方式&#x1f980;4、关键代码&#x1f366;5、源代码&…

SpringMVC基础篇:第一个MVC程序和细节分析

文章整理自孙哥说SpringMVC&#xff0c;相关课程联系孙哥学习谢谢。第一章&#xff1a;编码开发一&#xff1a;思路分析二&#xff1a;SpringMVC程序编码三&#xff1a;控制器提供多个服务方法四&#xff1a;注意事项第二章&#xff1a;细节分析一&#xff1a;控制器创建次数二…