写自未接触过公众号,也不知道什么是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刷新时间,基本稳定。
四、坑-总结
- 坑不大,只要看着微信文档就可以知道调什么接口,搜索也很方便,比百度好使。文档整理:
获取用户信息标签文档:mp.weixin.qq.com/wiki?t=reso…
为用户打标签接口文档:mp.weixin.qq.com/wiki?t=reso…
关注获取到参数:mp.weixin.qq.com/wiki?t=reso…
-
token的获取最好由一个服务提供,还需要配置白名单,不可能每个项目都生成token
-
推荐入门开源项目:github.com/binarywang/… 项目为weixin-java-tools的Demo演示程序,推荐了内网穿透的使用,而且是springboot项目,基本事件的处理。
-
更加强大的开源项目:github.com/Wechat-Grou… 内容太多,代码优美,学习一下如何构建微信项目。
-
发起http请求,可以使用apache.http.client、okHttp。贴出apache工具类:若有觉得不怎么好,可自行百度
彻底入门OkHttp使用 blog.csdn.net/u013651026/…
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, Map<String,String> data) throws Exception{
HttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
if (data != null) {
List<NameValuePair> nvps = new ArrayList<>();
data.forEach((key, value) -> {
nvps.add(new BasicNameValuePair(key, value));
});
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
}
ResponseHandler<String> 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<String> responseHandler = getStringResponseHandler();
try {
return httpClient.execute(httpGet, responseHandler);
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
/**
* Create a custom response handler
*/
private static ResponseHandler<String> 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();
}
}