access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。
官方文档:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
package cn.kt.mywxdemo.token;
/**
* Created by tao.
* Date: 2023/3/7 16:26
* 描述:
*/
public class AccessToken {
private String token;
private long expireTime;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public long getExpireTime() {
return expireTime;
}
public void setExpireTime(long expireIn) {
this.expireTime = System.currentTimeMillis() + expireIn * 1000;
}
/**
* 判断是否超时
*
* @return
*/
public boolean isExpired() {
return System.currentTimeMillis() > this.expireTime;
}
}
package cn.kt.mywxdemo.token;
import cn.kt.mywxdemo.utils.HttpUtil;
import net.sf.json.JSONObject;
/**
* Created by tao.
* Date: 2023/3/7 16:26
* 描述:
*/
public class TokenUtil {
private static final String APP_ID = "wx90a9158b6acc5584";
private static final String APP_SECRET = "ec23a5d78f12afa569c64794570d753c";
private static AccessToken accessToken = new AccessToken();
public static void main(String[] args) {
//{"access_token":"63_8R2EcPuM3dz_D81Q2FBiSfgrlwokafQloAU33iFhHIbjabRFtC_thRqk7VOkMbarQ8lA9yyq2pgwh4pc6P-5qQutc6WWMLwFafIR6ZaLkB299OJU78npFt--I0ACXCiACAHCH","expires_in":7200}
System.out.println(getAccessToken());
}
private static void getToken() {
String url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
APP_ID,
APP_SECRET);
String result = HttpUtil.doGet(url);
JSONObject jsonObject = JSONObject.fromObject(result);
String token = jsonObject.getString("access_token");
long expiresIn = jsonObject.getLong("expires_in");
accessToken.setToken(token);
accessToken.setExpireTime(expiresIn);
}
/**
* 获取AccessToken
*
* @return
*/
public static String getAccessToken() {
if (accessToken == null || accessToken.isExpired()) {
getToken();
}
return accessToken.getToken();
}
}
之后AccessToken存了静态,过期可以自动更新可以直接使用TokenUtil.getAccessToken()获取
自定义菜单能够帮助公众号丰富界面,让用户更好更快地理解公众号的功能。开启自定义菜单后,公众号界面如图所示:
自定义菜单接口可实现多种类型按钮,如下:
具体的参数详情和请求示例可以查看官方文档:https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.html
下面使用代码多态的方式实现:
package cn.kt.mywxdemo.button;
/**
* Created by tao.
* Date: 2023/3/7 17:11
* 描述:
*/
public abstract class AbstractButton {
private String name;
public AbstractButton(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package cn.kt.mywxdemo.button;
import java.util.List;
/**
* Created by tao.
* Date: 2023/3/7 17:11
* 描述:
*/
public class Button {
private List<AbstractButton> button;
public List<AbstractButton> getButton() {
return button;
}
public void setButton(List<AbstractButton> button) {
this.button = button;
}
}
package cn.kt.mywxdemo.button;
import java.util.List;
/**
* Created by tao.
* Date: 2023/3/7 17:18
* 描述:
*/
public class SubButton extends AbstractButton {
public SubButton(String name) {
super(name);
}
private List<AbstractButton> sub_button;
public List<AbstractButton> getSub_button() {
return sub_button;
}
public void setSub_button(List<AbstractButton> sub_button) {
this.sub_button = sub_button;
}
}
package cn.kt.mywxdemo.button;
/**
* Created by tao.
* Date: 2023/3/7 17:13
* 描述:
*/
public class ClickButton extends AbstractButton{
public ClickButton(String name) {
super(name);
this.type = "click";
}
private String type;
private String key;
public String getType() {
return type;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
}
package cn.kt.mywxdemo.button;
/**
* Created by tao.
* Date: 2023/3/7 17:22
* 描述:
*/
public class ViewButton extends AbstractButton {
public ViewButton(String name, String url) {
super(name);
this.type = "view";
this.url = url;
}
private String type;
private String url;
public String getType() {
return type;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
package cn.kt.mywxdemo.button;
/**
* Created by tao.
* Date: 2023/3/7 17:15
* 描述:
*/
public class PhotoOrAlbumButton extends AbstractButton {
public PhotoOrAlbumButton(String name, String key) {
super(name);
this.type = "pic_photo_or_album";
this.key = key;
}
private String type;
private String key;
public String getType() {
return type;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
}
package cn.kt.mywxdemo.button;
import cn.kt.mywxdemo.token.TokenUtil;
import cn.kt.mywxdemo.utils.HttpUtil;
import net.sf.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
/**
* Created by tao.
* Date: 2023/3/7 17:18
* 描述:
*/
public class TestButton {
public static void main(String[] args) {
//创建一级菜单
Button button = new Button();
List<AbstractButton> buttons = new ArrayList<>();
//一级菜单中的第一个按钮
ClickButton clickButton = new ClickButton("博客");
clickButton.setKey("1");
//一级菜单中的第二个按钮
ViewButton viewButton = new ViewButton("Nickの主页", "https://mytab.qkongtao.cn/");
//一级菜单中的第三个按钮(二级菜单)
SubButton subButton = new SubButton("更多");
List<AbstractButton> subButtons = new ArrayList<>();
//二级菜单的第一个按钮
subButtons.add(new ViewButton("KT游戏厅", "http://fcgame.qkongtao.cn/"));
//二级菜单的第二个按钮
subButtons.add(new PhotoOrAlbumButton("上传图片", "2"));
subButton.setSub_button(subButtons);
//把一级菜单中的三个按钮添加进集合
buttons.add(clickButton);
buttons.add(viewButton);
buttons.add(subButton);
//把集合添加到一级菜单中
button.setButton(buttons);
//转换成json字符串
JSONObject jsonObject = JSONObject.fromObject(button);
String json = jsonObject.toString();
String url = String.format("https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%s", TokenUtil.getAccessToken());
//发送请求
String result = HttpUtil.doPostByButton(url, json);
System.out.println(result);
}
}
运行后就会根据我们代码中的设置生成公众号的菜单,结果如图
模板消息仅⽤于公众号向⽤户发送重要的服务通知,只能⽤于符合其要求的服务场景中,如信⽤卡刷卡通知,商品购买成功通知等。不⽀持⼴告等营销类消息以及其它所有可能对⽤户造成骚扰的消息。 关于使⽤规则,请注意:
关于接⼝⽂档,请注意:
微信模板消息详情具体参考:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Template_Message_Interface.html
设置⾏业可在微信公众平台后台完成,每⽉可修改⾏业1次,帐号仅可使⽤所属⾏业中相关的模板,为⽅便第三⽅开发者,提供通过接⼝调⽤的⽅式来修改账号所属⾏业,具体如下:
接⼝调⽤请求说明
http请求⽅式: POST https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token=ACCESS_TOKEN
POST数据说明 POST数据示例如下
{
"industry_id1":"1",
"industry_id2":"4"
}
参数说明
在微信公众平台根据⾏业模版案例创建消息模版。
附目前允许发的模板示例下载:点击下载
可自行根据允许的模板进行设置自己行业的消息模板。
接⼝调⽤请求说明
http请求⽅式: POST https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN
POST数据说明 POST数据示例如下:
{
"touser": "OPENID",
"template_id": "ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY",
"url": "http://weixin.qq.com/download",
"miniprogram": {
"appid": "xiaochengxuappid12345",
"pagepath": "index?foo=bar"
},
"client_msg_id": "MSG_000001",
"data": {
"first": {
"value": "恭喜你报名成功!",
"color": "#173177"
},
"keyword1": {
"value": "张三",
"color": "#173177"
},
"keyword2": {
"value": "18899887766",
"color": "#173177"
},
"keyword3": {
"value": "2023年9⽉22⽇",
"color": "#173177"
},
"keyword4": {
"value": "Java核心基础课程",
"color": "#173177"
},
"remark": {
"value": "欢迎来到新世界!",
"color": "#173177"
}
}
}
参数说明:
注:url和 miniprogram 都是⾮必填字段,若都不传则模板⽆跳转;若都传,会优先跳转⾄⼩程序。开发者可根据实际需要选择其中⼀种跳转⽅式即可。当⽤户的微信客户端版本不⽀持跳⼩程序时,将会跳转⾄url。
返回码说明 在调⽤模板消息接⼝后,会返回 JSON 数据包。正常时的返回 JSON 数据包示例:
{
"errcode": 0,
"errmsg": "ok",
"msgid": 200228332
}
package cn.kt.mywxdemo.message;
import cn.kt.mywxdemo.token.TokenUtil;
import cn.kt.mywxdemo.utils.HttpUtil;
import org.junit.Test;
/**
* Created by tao.
* Date: 2023/3/7 19:26
* 描述:
*/
public class TestModelMessage {
// 设置模板行业信息
// 参考文档:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Template_Message_Interface.html
@Test
public void testTrade() {
String url = String.format("https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token=%s",
TokenUtil.getAccessToken());
String data = "{\n" +
" \"industry_id1\":\"1\",\n" +
" \"industry_id2\":\"4\"\n" +
"}";
//使用post
System.out.println(HttpUtil.doPost(url, data));
}
// 获取设置的模板行业信息
@Test
public void testGetTrade() {
String url = String.format("https://api.weixin.qq.com/cgi-bin/template/get_industry?access_token=%s",
TokenUtil.getAccessToken());
System.out.println(HttpUtil.doGet(url));
}
// 发送模板消息
@Test
public void testModelmessage() {
String url = String.format("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s",
TokenUtil.getAccessToken());
String data = "{\n" +
" \"touser\":\"oJ4VY61KtF_VJL2Zwm_S-4cJnYCw\",\n" +
" \"template_id\":\"1_BTU1dlGB9rPWv5JL-Kkivn6OhjAt7wZMGqE9SHaG4\",\n" +
" \"data\":{\n" +
" \"first\": {\n" +
" \"value\":\"恭喜你报名成功!\",\n" +
" \"color\":\"#173177\"\n" +
" },\n" +
" \"keyword1\":{\n" +
" \"value\":\"张三\",\n" +
" \"color\":\"#173177\"\n" +
" },\n" +
" \"keyword2\": {\n" +
" \"value\":\"18899887766\",\n" +
" \"color\":\"#173177\"\n" +
" },\n" +
" \"keyword3\": {\n" +
" \"value\":\"2023年9月22日\",\n" +
" \"color\":\"#173177\"\n" +
" },\n" +
" \"keyword4\": {\n" +
" \"value\":\"Java核心基础课程\",\n" +
" \"color\":\"#173177\"\n" +
" },\n" +
" \"remark\":{\n" +
" \"value\":\"欢迎来到新世界!\",\n" +
" \"color\":\"#173177\"\n" +
" }\n" +
" }\n" +
" }";
System.out.println(HttpUtil.doPost(url, data));
}
}
公众号经常有需要⽤到⼀些临时性的多媒体素材的场景,例如在使⽤接⼝特别是发送消息时,对多媒体⽂件、多媒体消息的获取和调⽤等操作,是通过media_id来进⾏的。素材管理接⼝对所有认证的订阅号和服务号开放。通过本接⼝,公众号可以新增临时素材(即上传临时多媒体⽂件)。 注意点: 1)临时素材media_id是可复⽤的。 2)媒体⽂件在微信后台保存时间为3天,即3天后media_id失效。 3)上传临时素材的格式、⼤⼩限制与公众平台官⽹⼀致。 图⽚(image): 10M,⽀持PNG\JPEG\JPG\GIF格式 语⾳(voice):2M,播放⻓度不超过60s,⽀持AMR\MP3格式 视频(video):10MB,⽀持MP4格式 缩略图(thumb):64KB,⽀持 JPG 格式 4)需使用https调用本接口。
http请求方式:POST/FORM,使用https https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE 调用示例(使用curl命令,用FORM表单方式上传一个多媒体文件)
具体参数详情参考官方文档:https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/New_temporary_materials.html
测试代码如下: 发送请求工具还是使用之前封装的HttpUtil
package cn.kt.mywxdemo.message;
import cn.kt.mywxdemo.token.TokenUtil;
import cn.kt.mywxdemo.utils.HttpUtil;
import org.junit.Test;
/**
* 测试 素材管理
* <p>
* Created by tao.
* Date: 2023/3/7 19:56
* 描述:
*/
public class TestMedia {
//上传临时素材
@Test
public void testImage() {
String url = String.format("https://api.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=%s",
TokenUtil.getAccessToken(),
"image");
String result = HttpUtil.doPostByFile(url, null, "D:/images/bg.png", "");
System.out.println(result);
//{"type":"image","media_id":"h7mvkpNYOsmyPtPxnvwh7hopFlQ2LLBalyiCXcfGG2p943IqKHrrSTYdIDMbeRID","created_at":1670224505,"item":[]}
}
/*
https://api.weixin.qq.com/cgi-bin/media/get?access_token=66_3Tp-hBPrXQOwoMOwoIygqf_U9YBcqk5tae28kEQtW89kaqaHKcOsXi4vudWi9CiBeBBk7nyxsHirQvQdrsOkyKrBbw8p2MDQZ2BU6pCsm7viUjdS_Ya4VzJuNN4OXFaAIAAJR&media_id=1AHMhn2WLJngIZ31Fiar-SCClNE34BPvmozpfXkvwUKlAt4b4oRQ9iFwk_x1S7n8
*/
//获得临时素材
@Test
public void testGetImage() {
String mediaId = "h7mvkpNYOsmyPtPxnvwh7hopFlQ2LLBalyiCXcfGG2p943IqKHrrSTYdIDMbeRID";
String url = String.format("https://api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s",
TokenUtil.getAccessToken(),
mediaId);
String result = HttpUtil.doGet(url);
System.out.println(result);
}
}
结果如下:
使用返回的media_id,拼接获取素材的接口即可获取素材: 示例如下: https://api.weixin.qq.com/cgi-bin/media/get?access_token=66_0qO7imNJGvzK1_oSoEK461VzV9406hIL8nv0GEJLH4okCZoYGR1c4uaQDrWdVsbB2fccXTEOac4kOg4eVdyZhp4Umjsl3RMqeoRv8BwTdj-x53ro9Dkf01L4pXMOVKeABAFMB&media_id=WLZtwg8LEjKZstdxRKVGfK8cX0ctJp4rIt4wVgkx2HvTHRfF1vdG8Tlqg3ilJN6P