当前位置: 首页 > news >正文

Java企业微信服务商代开发获取AccessToken示例

这里主要针对的是企业微信服务商代开发模式 文档地址

在这里插入图片描述

可以看到里面大致有三种token,一个是服务商的token,一个是企业授权token,还有一个是应用的token
这里面主要有下面几个参数
首先是服务商的 corpid 和 provider_secret ,这个可以在 应用管理-通用开发参数 里面查看

在这里插入图片描述

然后是企业的 corpid 和企业的永久授权码 permanent_code ,这两个是需要在企业授权的的时候通过回调获取的,具体请参考官方文档 获取永久授权码

最后就是应用的 suite_id 和 suite_secret 还需要一个 suite_ticket ,前面两个在应用信息里面就可以看到,suite_ticket 这个也是需要通过回调获取 ,具体参考官方文档 推送suite_ticket

在这里插入图片描述

拿到这些参数后就好说了,剩下的都是调接口
直接上代码

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qyzj.common.base.exception.BusinessException;
import com.qyzj.common.base.util.HttpsRequestUtil;
import com.qyzj.common.redis.constant.CacheKey;
import com.qyzj.common.redis.util.RedisUtil;
import com.qyzj.service.task.constant.WeiXinProviderConst;
import com.qyzj.service.task.constant.WeixinCorpKeyConst;
import com.qyzj.service.task.constant.WeixinCorpUrlConst;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** @author Sakura* @date 2024/7/2 11:48*/
@Component
@Log
public class WxTokenUtil {@Autowiredprivate RedisUtil redisUtil;// 获取服务商token// 这里有一个问题,企业微信本身可能会使token提前失效,所以有时需要强制重新获取token,详情见官方文档// https://developer.work.weixin.qq.com/document/path/91200// 所以此处加了一个cache用来判断是否需要走缓存拿token,正常情况默认走缓存即可public String getProviderAccessToken(Boolean cache) {try {// 如果Redis里面有则直接取Redis里面的if (cache &&redisUtil.hasKey(CacheKey.KEY_CORP_PROVIDER_ACCESS_TOKEN)) {return redisUtil.get(CacheKey.KEY_CORP_PROVIDER_ACCESS_TOKEN).toString();}// 封装请求参数JSONObject json = new JSONObject();json.put("corpid", WeiXinProviderConst.corpId);json.put("provider_secret", WeiXinProviderConst.providerSecret);// 请求微信接口String accessTokenStr = HttpsRequestUtil.sendPostRequest(WeixinCorpUrlConst.PROVIDER_ACCESS_TOKEN, json.toJSONString());log.info("get provider access token return :" + accessTokenStr);JSONObject accessTokenJson = JSON.parseObject(accessTokenStr);// 获取 access_tokenString accessToken = accessTokenJson.getString(WeixinCorpKeyConst.providerAccessToken);//官方 expires_in 为 2个小时, 这里设置100分钟redisUtil.set(CacheKey.KEY_CORP_PROVIDER_ACCESS_TOKEN, accessToken, CacheKey.expireTime100);return accessToken;} catch (Exception e) {log.info("get provider access token error");e.printStackTrace();throw new BusinessException("get provider access token error");}}// 获取企业授权tokenpublic String getCorpAccessToken(String corpId, String permanentCode) {try {// 如果Redis里面有则直接取Redis里面的if (redisUtil.hasKey(CacheKey.KEY_CORP_ACCESS_TOKEN + "_" + corpId)) {return redisUtil.get(CacheKey.KEY_CORP_ACCESS_TOKEN + "_" + corpId).toString();}String accessTokenUrl = WeixinCorpUrlConst.CORP_ACCESS_TOKEN.replace("#{CORP_ID}", corpId).replace("#{CORP_SECRET}", permanentCode);String accessTokenStr = HttpsRequestUtil.sendGetRequest(accessTokenUrl);log.info("get corp access token return :" + accessTokenStr);JSONObject accessTokenJson = JSON.parseObject(accessTokenStr);// 获取 access_tokenString accessToken = accessTokenJson.getString(WeixinCorpKeyConst.accessToken);//官方 expires_in 为 2个小时, 这里设置 100 分钟redisUtil.set(CacheKey.KEY_CORP_ACCESS_TOKEN + "_" + corpId, accessToken, CacheKey.expireTime100);return accessToken;} catch (Exception e) {log.info("get corp access token error");e.printStackTrace();throw new BusinessException("get corp access token error");}}// SuiteTicket是通过回调获取的,企微每10分钟会推送一次// 如果没有可手动在服务商企业微信后台刷新public String getSuiteTicket() {// 如果Redis里面有则直接取Redis里面的if (redisUtil.hasKey(CacheKey.KEY_CORP_SUITE_TICKET)) {return redisUtil.get(CacheKey.KEY_CORP_SUITE_TICKET).toString();} else {log.info("get suite ticket error");throw new BusinessException("get suite ticket error");}}// 获取应用token// 注意suiteTicket是从回调接口获取的// 注意该token需要配置ip白名单public String getSuiteAccessToken() {try {// 如果Redis里面有则直接取Redis里面的if (redisUtil.hasKey(CacheKey.KEY_SUITE_ACCESS_TOKEN)) {return redisUtil.get(CacheKey.KEY_SUITE_ACCESS_TOKEN).toString();}// 封装请求参数JSONObject json = new JSONObject();json.put(WeixinCorpKeyConst.suiteId, WeiXinProviderConst.suiteId);json.put(WeixinCorpKeyConst.suiteSecret, WeiXinProviderConst.suiteSecret);json.put(WeixinCorpKeyConst.suiteTicket, getSuiteTicket());String accessTokenStr = HttpsRequestUtil.sendPostRequest(WeixinCorpUrlConst.SUITE_ACCESS_TOKEN, json.toJSONString());log.info("get suite access token return :" + accessTokenStr);JSONObject accessTokenJson = JSON.parseObject(accessTokenStr);//获取 accessTokenString accessToken = accessTokenJson.getString(WeixinCorpKeyConst.suiteAccessToken);//官方 expires_in 为 2个小时, 这里设置 100分钟redisUtil.set(CacheKey.KEY_SUITE_ACCESS_TOKEN, accessToken, CacheKey.expireTime100);return accessToken;} catch (Exception e) {log.info("get suite access token error");e.printStackTrace();throw new BusinessException("get suite access token error");}}
}

这里面用到的 HttpsRequestUtil 工具类

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;/*** @author Sakura* @date 2024/6/24 17:07*/
public class HttpsRequestUtil {public static String sendPostRequest(String urlString, String jsonInputString) throws IOException {URL url = new URL(urlString);HttpURLConnection connection = (HttpURLConnection) url.openConnection();// 设置请求方法为POSTconnection.setRequestMethod("POST");// 设置请求头connection.setRequestProperty("Content-Type", "application/json");connection.setRequestProperty("Accept", "application/json");// 启用输出流,用于发送请求数据connection.setDoOutput(true);try (OutputStream os = connection.getOutputStream()) {byte[] input = jsonInputString.getBytes("utf-8");os.write(input, 0, input.length);}// 获取响应try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"))) {StringBuilder response = new StringBuilder();String responseLine;while ((responseLine = br.readLine()) != null) {response.append(responseLine.trim());}return response.toString();} finally {// 关闭连接connection.disconnect();}}public static String sendGetRequest(String urlString) throws IOException {URL url = new URL(urlString);HttpURLConnection connection = (HttpURLConnection) url.openConnection();// 设置请求方法为GETconnection.setRequestMethod("GET");// 设置请求头connection.setRequestProperty("Accept", "application/json");// 获取响应try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"))) {StringBuilder response = new StringBuilder();String responseLine;while ((responseLine = br.readLine()) != null) {response.append(responseLine.trim());}return response.toString();} finally {// 关闭连接connection.disconnect();}}}

还有企业微信的两个基本配置类

public class WeixinCorpUrlConst {/*** 获取 provider_access_token 的 url*/public static final String PROVIDER_ACCESS_TOKEN = "https://qyapi.weixin.qq.com/cgi-bin/service/get_provider_token";/*** 获取 suite_access_token 的 url*/public static final String SUITE_ACCESS_TOKEN = "https://qyapi.weixin.qq.com/cgi-bin/service/get_suite_token";/*** 获取 pre_auth_code 的 url*/public static final String PRE_AUTH_CODE = "https://qyapi.weixin.qq.com/cgi-bin/service/get_pre_auth_code?suite_access_token=";/*** 前端授权页面 的 url*/public static final String URL_AUTH_PAGE = "https://open.work.weixin.qq.com/3rdapp/install";/*** 前端登录页面 的 url*/public static final String URL_LOGIN_PAGE = "https://open.work.weixin.qq.com/wwopen/sso/3rd_qrConnect";/*** 获取 permanent_code 的 url*/public static final String PERMANENT_CODE = "https://qyapi.weixin.qq.com/cgi-bin/service/get_permanent_code?suite_access_token=";/*** 获取 企业授权 access_token 的 url*/public static final String CORP_ACCESS_TOKEN = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=#{CORP_ID}&corpsecret=#{CORP_SECRET}";/*** 获取 企业应用 access_token 的 url*/public static final String ACCESS_TOKEN = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";/*** 获取 应用信息 的 url*/public static final String AGENT_INFO = "https://qyapi.weixin.qq.com/cgi-bin/agent/get?access_token=#{ACCESS_TOKEN}&agentid=#{AGENT_ID}";/*** 获取 部门列表 的 url*/public static final String DEPARTMENT_LIST = "https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=#{ACCESS_TOKEN}";/*** 获取 部门成员列表 的 url*/public static final String USER_LIST = "https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token=#{ACCESS_TOKEN}&department_id=#{DEPARTMENT_ID}&fetch_child=1";/*** 获取 成员信息 的 url*/public static final String USER_INFO = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=#{ACCESS_TOKEN}&userid=#{USER_ID}";/*** 获取 企业管理员 的 url*/public static final String ADMIN_USER_LIST = "https://qyapi.weixin.qq.com/cgi-bin/service/get_admin_list?suite_access_token=";/*** 第三方应用:获取 企业成员登录信息 的 url*/public static final String PROVIDER_LOGIN_INFO = "https://qyapi.weixin.qq.com/cgi-bin/service/get_login_info?access_token=";/*** 自建应用:获取 企业成员登录信息 的 url*/public static final String LOCAL_LOGIN_INFO = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=#{ACCESS_TOKEN}&code=#{CODE}";public static final String LOGIN_DETAIL_INFO = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserdetail?access_token=#{ACCESS_TOKEN}";/*** 批量获取 客户列表 的 url*/public static final String BATCH_CUSTOMER_LIST = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/batch/get_by_user?access_token=#{ACCESS_TOKEN}";/*** 获取 客户详情 的 url*/public static final String CUSTOMER_INFO = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get?access_token=#{ACCESS_TOKEN}&external_userid=#{EXTERNAL_USERID}";/*** 修改 客户备注信息 的url*/public static final String UPDATE_CUSTOMER_REMARK = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/remark?access_token=#{ACCESS_TOKEN}";/*** 编辑 客户标签 的url*/public static final String MARK_CUSTOMER_TAG = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/mark_tag?access_token=#{ACCESS_TOKEN}";/*** 获取 企业标签 的 url*/public static final String TAG_GROUP_LIST = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_corp_tag_list?access_token=";/*** 添加 企业标签 的 url*/public static final String ADD_TAG_GROUP = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_corp_tag?access_token=";/*** 修改 企业标签 的 url*/public static final String UPDATE_TAG_GROUP = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/edit_corp_tag?access_token=";/*** 删除 企业标签 的 url*/public static final String DELETE_TAG_GROUP = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/del_corp_tag?access_token=";/*** 获取 客户群列表 的 url*/public static final String GROUP_CHAT_LIST = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat/list?access_token=#{ACCESS_TOKEN}";/*** 获取 客户群详情 的 url*/public static final String GROUP_CHAT_INFO = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat/get?access_token=#{ACCESS_TOKEN}";/*** 查询 联系我 的 url*/public static final String GET_CONTACT_WAY = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_contact_way?access_token=#{ACCESS_TOKEN}";/*** 添加 联系我 的 url*/public static final String ADD_CONTACT_WAY = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_contact_way?access_token=#{ACCESS_TOKEN}";/*** 更新 联系我 的 url*/public static final String UPDATE_CONTACT_WAY = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/update_contact_way?access_token=#{ACCESS_TOKEN}";/*** 删除 联系我 的 url*/public static final String DEL_CONTACT_WAY = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/del_contact_way?access_token=#{ACCESS_TOKEN}";/*** 发送 欢迎语  的 url*/public static final String SEND_WELCOME_MSG = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/send_welcome_msg?access_token=#{ACCESS_TOKEN}";/*** 上传 临时素材 的 url*/public static final String UPLOAD_MEDIA = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=";/*** 添加 入群欢迎语素材  的 url*/public static final String ADD_GROUP_WELCOME_TEMPLATE = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/group_welcome_template/add?access_token=#{ACCESS_TOKEN}";/*** 更新 入群欢迎语素材  的 url*/public static final String UPDATE_GROUP_WELCOME_TEMPLATE = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/group_welcome_template/edit?access_token=#{ACCESS_TOKEN}";/*** 删除 入群欢迎语素材  的 url*/public static final String DEL_GROUP_WELCOME_TEMPLATE = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/group_welcome_template/del?access_token=#{ACCESS_TOKEN}";/*** 发送 应用消息  的 url*/public static final String SEND_APPLICATION_MESSAGE = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=#{ACCESS_TOKEN}";/*** 获取待分配的离职成员列表 的url*/public static final String DIMISSION_WAIT_ALLOT_CLIENT = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_unassigned_list?access_token=#{ACCESS_TOKEN}";/*** 分配离职成员的客户*/public static final String DIMISSION_ALLOT_Client = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/resigned/transfer_customer?access_token=#{ACCESS_TOKEN}";/***  分配离职成员的客户群*/public static final String DIMISSION_ALLOT_GROUP = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat/transfer?access_token=#{ACCESS_TOKEN}";/*** 创建企业群发*/public static final String ADD_CORP_MASS_URL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_msg_template?access_token=#{ACCESS_TOKEN}";/*** 编辑客户企业标签*/public static final String EDIT_CUSTOMER_CORP_TAG = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/mark_tag?access_token=#{ACCESS_TOKEN}";/*** 获取企业的jsapi_ticket*/public static final String CORP_JS_API_TICKET = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=";/*** 获取应用的jsapi_ticket*/public static final String AGENT_JS_API_TICKET = "https://qyapi.weixin.qq.com/cgi-bin/ticket/get?type=agent_config&access_token=";/*** 获取 开通了会话存档的员工*/public static final String MSG_AUDIT_EMPLOYEE = "https://qyapi.weixin.qq.com/cgi-bin/msgaudit/get_permit_user_list?access_token=#{ACCESS_TOKEN}";/*** corpid转换 的 url*/public static final String CORPID_TO_OPENCORPID = "https://qyapi.weixin.qq.com/cgi-bin/service/corpid_to_opencorpid?provider_access_token=";/*** userid转换 的 url*/public static final String USERID_TO_OPENUSERID = "https://qyapi.weixin.qq.com/cgi-bin/batch/userid_to_openuserid?access_token=";public static final String GET_NEW_EXTERNAL_USERID = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_new_external_userid?access_token=";public static final String UNIONID_TO_EXTERNAL_USERID = "https://qyapi.weixin.qq.com/cgi-bin/idconvert/unionid_to_external_userid?access_token=";public static final String EXTERNAL_USERID_TO_PENDING_ID = "https://qyapi.weixin.qq.com/cgi-bin/idconvert/batch/external_userid_to_pending_id?access_token=";public static final String FINISH_OPENID_MIGRATION = "https://qyapi.weixin.qq.com/cgi-bin/service/finish_openid_migration?provider_access_token=";
}
public class WeixinCorpKeyConst {public static String errcode = "errcode";public static String errmsg = "errmsg";// 服务商相关public static String corpId = "corpid";public static String authCorpId = "auth_corpid";public static String corpName = "corp_name";public static String suiteId = "suite_id";public static String suiteSecret = "suite_secret";public static String providerSecret = "provider_secret";public static String corpSecret = "corpsecret";public static String suiteTicket = "suite_ticket";public static String suiteAccessToken = "suite_access_token";public static String providerAccessToken = "provider_access_token";public static String preAuthCode = "pre_auth_code";public static String authCode = "auth_code";public static String permanentCode = "permanent_code";public static String authCorpInfo = "auth_corp_info";public static String authInfo = "auth_info";public static String agent = "agent";public static String agentId = "agentid";public static String accessToken = "access_token";}

WeiXinProviderConst 就不贴了,里面就是记录上面那几个参数的

到这里可以发现,其实对接企业微信并不难,麻烦的地方就在于各种配置各种参数,然后就是回调,回调这个后面有空我也会整理出来

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 《Linux系统开发入门定制专栏导读》
  • 白骑士的PyCharm教学高级篇 3.3 Web开发支持
  • 网安新声 | 微软蓝屏事件安全启示录
  • RpcProvider发送Rpc服务一
  • 速盾:cdn可以定时刷新缓存吗?
  • Cesium初探-CallbackProperty
  • 推荐系统与搜索系统架构
  • MySQL --- 内置函数介绍
  • 常见面试题(一)
  • Loki配置存储有效期
  • 【Python】数据类型之列表(下)
  • PCIe学习笔记(16)
  • 《pygame游戏开发实战指南》第四节 认识Recct对象
  • 测试GPT4o分析巴黎奥运会奖牌数据
  • 【数据驱动领域EI会议推荐】2024年智能电力系统与数据驱动创新国际研讨会(IPSDDI 2024)
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • Angularjs之国际化
  • chrome扩展demo1-小时钟
  • Consul Config 使用Git做版本控制的实现
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • Docker入门(二) - Dockerfile
  • Druid 在有赞的实践
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • node学习系列之简单文件上传
  • python学习笔记-类对象的信息
  • React as a UI Runtime(五、列表)
  • Vue学习第二天
  • 机器学习学习笔记一
  • 盘点那些不知名却常用的 Git 操作
  • 如何设计一个微型分布式架构?
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 微服务入门【系列视频课程】
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 阿里云重庆大学大数据训练营落地分享
  • 容器镜像
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • #13 yum、编译安装与sed命令的使用
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • $.ajax()方法详解
  • (10)STL算法之搜索(二) 二分查找
  • (19)夹钳(用于送货)
  • (el-Date-Picker)操作(不使用 ts):Element-plus 中 DatePicker 组件的使用及输出想要日期格式需求的解决过程
  • (pytorch进阶之路)扩散概率模型
  • (附源码)python房屋租赁管理系统 毕业设计 745613
  • (论文阅读22/100)Learning a Deep Compact Image Representation for Visual Tracking
  • (十八)三元表达式和列表解析
  • (一)WLAN定义和基本架构转
  • (转)3D模板阴影原理
  • .NET C# 使用 iText 生成PDF
  • @Controller和@RestController的区别?
  • @zabbix数据库历史与趋势数据占用优化(mysql存储查询)
  • [8-27]正则表达式、扩展表达式以及相关实战
  • [bbk5179]第66集 第7章 - 数据库的维护 03
  • [BJDCTF 2020]easy_md5