微信获取accessToken及自定义公众号菜单
1 微信获取accessToken
1.1 accessToken介绍及接口文档
access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。
详细介绍:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
1.2 获取accessToken
①创建AccessToken类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AccessToken {
private String access_token;
//过期时间【此处的过期时间我求的是时间戳为多少的时候过期,而不是一个时间段】
private long expires_time;
public AccessToken(String access_token, Integer expires_in){
this.access_token = access_token;
expires_time = System.currentTimeMillis() + expires_in * 1000;
}
public boolean isExpire(){
return System.currentTimeMillis() > expires_time;
}
}
②创建配置类,读取application.properties的appId与secret
@Configuration
@Data
@NoArgsConstructor
@AllArgsConstructor
public class WxConfig {
@Value("${wx.appId}")
public String appId;
@Value("${wx.secret}")
public String secret;
}
我们测试账号的appID与secret在:
https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
测试账号申请参考:https://editor.csdn.net/md/?articleId=127282111
③获取accessToken
报文发送,我采用okHttp
<!--报文发送-->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.8.0</version>
</dependency>
service:
@Service
public class WxService {
//注入appId与secret
@Autowired
private WxConfig wxConfig;
//请求微信地址【get方式】
private String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
/**
* 获取accessToken
*
* @return
*/
public AccessToken getAccessToken() {
String APPID = wxConfig.getAppId();
String SECRET = wxConfig.getSecret();
//拼接url【传入appId和secret】
url = url.replace("APPID", APPID).replace("APPSECRET", SECRET);
OkHttpClient client = new OkHttpClient();
//构建请求
Request request = new Request.Builder().url(url).build();
Call call = client.newCall(request);
Response response = null;
try {
//获取响应体
response = call.execute();
//{"access_token":"ACCESS_TOKEN","expires_in":7200} 返回体类型
if (response != null) {
ResponseBody body = response.body();
String bodyStr = body.string();
JSONObject jsonObject = JSONObject.parseObject(bodyStr);
//获取过期时间
String access_token = (String) jsonObject.get("access_token");
Integer expires_in = (Integer) jsonObject.get("expires_in");
AccessToken accessToken = new AccessToken(access_token, expires_in);
return accessToken;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
2 自定义公众号菜单
官方文档:
https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.html
请求示例:
{
"button":[
{
"type":"click",
"name":"今日歌曲",
"key":"V1001_TODAY_MUSIC"
},
{
"name":"菜单",
"sub_button":[
{
"type":"view",
"name":"搜索",
"url":"http://www.soso.com/"
},
{
"type":"miniprogram",
"name":"wxa",
"url":"http://mp.weixin.qq.com",
"appid":"wx286b93c14bbf93aa",
"pagepath":"pages/lunar/index"
},
{
"type":"click",
"name":"赞一下我们",
"key":"V1001_GOOD"
}]
}]
}
①导入依赖
<!--报文发送-->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.8.0</version>
</dependency>
<!--处理json数据-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
②基础类创建【准备拼接返回json】
AbstractButton :
@Data
@NoArgsConstructor
public abstract class AbstractButton {
private String name;
public AbstractButton(String name){
this.name = name;
}
}
BaseButton :
@Data
public class BaseButton {
@JSONField(name = "button")
private List<AbstractButton> buttonList = new ArrayList<>();
}
ClickButton :
@Data
@NoArgsConstructor
public class ClickButton extends AbstractButton{
private String type = "click";
private String key;
public ClickButton(String name){
super(name);
}
}
SubButton :
@Data
@NoArgsConstructor
public class SubButton extends AbstractButton{
@JSONField(name = "sub_button")
private List<AbstractButton> buttonList = new ArrayList<>();
public SubButton(String name){
super(name);
}
}
ViewButton :
@Data
@NoArgsConstructor
public class ViewButton extends AbstractButton{
private String type = "view";
private String url;
public ViewButton(String name){
super(name);
}
}
其他按钮参考该模式实现
③service实现
@Service
public class WxService {
//自定义菜单【post方式】
private String url_post = " https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
public static final MediaType TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
/**
* 测试自定义菜单
*/
public String testButtonBySelf(){
//创建菜单对象
BaseButton baseButton = new BaseButton();
//第一部分一级菜单:创建clickButton
ClickButton clickButton = new ClickButton("点击有惊喜");
clickButton.setKey("click1001");
//第二部分一级菜单:创建子菜单
SubButton subButton = new SubButton("菜单");
//创建子菜单中的viewButton
ViewButton subViewButton = new ViewButton("百度一下");
subViewButton.setUrl("https://www.baidu.com/");
ClickButton subClickButton = new ClickButton("子菜单下的点击");
subClickButton.setKey("subButtonClick1002");
//将子菜单中的button添加到子菜单中
List<AbstractButton> subButtonList = subButton.getButtonList();
subButtonList.add(subViewButton);
subButtonList.add(subClickButton);
//第三部分一级菜单:创建viewButton
ViewButton viewButton = new ViewButton("网易新闻");
viewButton.setUrl("https://www.163.com/");
//拼接button
List<AbstractButton> baseButtonList = baseButton.getButtonList();
baseButtonList.add(clickButton);
baseButtonList.add(subButton);
baseButtonList.add(viewButton);
String jsonStr = JSONObject.toJSONString(baseButton);
//发送POST请求
OkHttpClient okHttpClient = new OkHttpClient();
//请求体
RequestBody body = RequestBody.create(TYPE_JSON, jsonStr);
System.out.println("jsonStr========>" + jsonStr);
//添加accessToken
AccessToken accessToken = getAccessToken();
String access_token = accessToken.getAccess_token();
url_post = url_post.replaceAll("ACCESS_TOKEN", access_token);
Request request = new Request.Builder().url(url_post).post(body).build();
try {
String responseStr = okHttpClient.newCall(request).execute().body().string();
System.out.println(responseStr);
return responseStr;
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
}
④controller调用
@RestController
public class WxController {
@Autowired
private WxService wxService;
@GetMapping("/testButton")
public String testButton(){
String s = wxService.testButtonBySelf();
return s;
}
}
⑤测试
控制台打印:
jsonStr========>{"button":[{"key":"click1001","name":"点击有惊喜","type":"click"},{"name":"菜单","sub_button":[{"name":"百度一下","type":"view","url":"https://www.baidu.com/"},{"key":"subButtonClick1002","name":"子菜单下的点击","type":"click"}]},{"name":"网易新闻","type":"view","url":"https://www.163.com/"}]}
{"errcode":0,"errmsg":"ok"}
测试号:
点击百度一下: