写自未接触过公众号,也不知道什么是token的搬运工。
一、需求
要求后台管理系统生成带用户标签的二维码,用户扫码后获取参数并为用户打上标签,之后微信根据标签的不同显示不同的菜单
二、技术调研
生成带参数的二维码
- 首先需要获得access_token,可以根据appid和secret直接调用接口直接获取,但是是新生成的并且是占用了次数,可以从token管理中获取一个未失效的token
- 根据token调用获取所有标签的接口,获得标签id
- 根据token调用获得二维码ticket的接口,根据参数设置有效时长和是否有效
- 根据ticket调用查看二维码接口
搭建微信认证服务器
- git搜索公众号demo
- 修改appid、secret、令牌、密钥参数
- 修改开源项目端口为80,使用https://natapp.cn/内网穿透到本地80端口
- 将穿透的域名认证服务器的地址填写到公众号服务器地址上
- 之后就可以愉快的打断点,随意调教
三、结果
流程是没有问题的,能够实现,只不过标签对应的自定义菜单是在第三方维护的,用户扫码后立刻能打上标签,但是并不能立刻显示对应的自定义菜单,好像很5分钟获取一次菜单有关。需求不了了之。
四、上线
- 后续,两星期之后上线,配置认证服务器之后,每次获取的token都是40001,token失效,清除redis存储的缓存之后,获取的token不到1小时又失效了,查看了官方文档,原本2小时的有效期,根本不靠谱,随后又修改token刷新时间,基本稳定。
四、坑-总结
- 坑不大,只要看着微信文档就可以知道调什么接口,搜索也很方便,比百度好使。文档整理:
获取用户信息标签文档:
为用户打标签接口文档:
关注获取到参数:
-
token的获取最好由一个服务提供,还需要配置白名单,不可能每个项目都生成token
-
推荐入门开源项目: 项目为weixin-java-tools的Demo演示程序,推荐了内网穿透的使用,而且是springboot项目,基本事件的处理。
-
更加强大的开源项目: 内容太多,代码优美,学习一下如何构建微信项目。
-
发起http请求,可以使用apache.http.client、okHttp。贴出apache工具类:若有觉得不怎么好,可自行百度
彻底入门OkHttp使用
package com.wechat.web.util;import org.apache.http.*;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.HttpClient;import org.apache.http.client.ResponseHandler;import org.apache.http.client.entity.UrlEncodedFormEntity;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.message.BasicHeader;import org.apache.http.message.BasicNameValuePair;import org.apache.http.protocol.HTTP;import org.apache.http.util.EntityUtils;import javax.servlet.ServletRequest;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.nio.charset.Charset;import java.util.ArrayList;import java.util.List;import java.util.Map; public class HttpUtil { /** * * @param url 请求地址 * @param data 请求数据 * @return String 响应string * @throws Exception 异常 */ public static String post(String url, Mapdata) throws Exception{ HttpClient httpClient = HttpClients.createDefault(); HttpPost httpPost = new HttpPost(url); if (data != null) { List nvps = new ArrayList<>(); data.forEach((key, value) -> { nvps.add(new BasicNameValuePair(key, value)); }); httpPost.setEntity(new UrlEncodedFormEntity(nvps)); } ResponseHandler responseHandler = getStringResponseHandler(); return httpClient.execute(httpPost, responseHandler); } /** * @param url 请求地址 * @param body 请求数据 * @return responseContent 响应数据 */ public static String post(String url, String body) { String responseContent = ""; CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; try { httpClient = HttpClients.createDefault(); HttpPost httpPost = new HttpPost(url); httpPost.addHeader("Content-Type", "application/json"); StringEntity s = new StringEntity(body, "utf-8"); s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json")); httpPost.setEntity(s);// httpPost.setEntity(new StringEntity(body)); response = httpClient.execute(httpPost); HttpEntity entity = response.getEntity(); responseContent = EntityUtils.toString(entity, Consts.UTF_8); } catch (ParseException | IOException e) { e.printStackTrace(); } finally { if (response != null) { try { response.close(); } catch (IOException e) { e.printStackTrace(); } } if (httpClient != null) { try { httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } return responseContent; } /** * * @param url 请求地址 * @throws Exception todo 是否异常 */ public static String get(String url) { HttpClient httpClient = HttpClients.createDefault(); HttpGet httpGet = new HttpGet(url); ResponseHandler responseHandler = getStringResponseHandler(); try { return httpClient.execute(httpGet, responseHandler); } catch (IOException e) { e.printStackTrace(); } return ""; } /** * Create a custom response handler */ private static ResponseHandler getStringResponseHandler() { return (final HttpResponse response) -> { int status = response.getStatusLine().getStatusCode(); if (status >= 200 && status < 300) { HttpEntity entity = response.getEntity(); return entity != null ? EntityUtils.toString(entity, Consts.UTF_8) : null; } else { throw new ClientProtocolException("Unexpected response status: " + status); } }; } /** * 获取请求Body * * @param request ServletRequest * @return String */ public static String getBodyString(ServletRequest request) { StringBuilder sb = new StringBuilder(); InputStream inputStream = null; BufferedReader reader = null; try { inputStream = request.getInputStream(); reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); String line = ""; while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); }}复制代码