微信公众平台开发(二)——自定义菜单、模板消息&微信素材

获取AccessToken

access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。

官方文档:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html

1. 新建一个AccessToken对象

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;
    }
}

2. 新建一个TokenUtil工具类

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

下面使用代码多态的方式实现:

  1. 一级菜单,二级菜单
  2. 点击类型按钮
  3. 跳转类型按钮
  4. 拍照或者相册选择事件按钮

代码实现如下

  1. 抽象类AbstractButton
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;
    }
}

  1. 菜单父类Button
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;
    }
}

  1. 二级菜单类SubButton
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;
    }
}

  1. 点击类型按钮类ClickButton
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;
    }
}

  1. 跳转类型按钮类ViewButton
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;
    }
}

  1. 拍照或者相册选择事件按钮类PhotoOrAlbumButton
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;
    }
}

  1. 主方法测试类TestButton
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);
    }
}

效果如下

运行后就会根据我们代码中的设置生成公众号的菜单,结果如图
在这里插入图片描述

发送模板消息

模板消息仅⽤于公众号向⽤户发送重要的服务通知,只能⽤于符合其要求的服务场景中,如信⽤卡刷卡通知,商品购买成功通知等。不⽀持⼴告等营销类消息以及其它所有可能对⽤户造成骚扰的消息。
关于使⽤规则,请注意:

  • 所有服务号都可以在功能->添加功能插件处看到申请模板消息功能的⼊⼝,但只有认证后的服务号才可以申请模板消息的使⽤权限并获得该权限;
  • 需要选择公众账号服务所处的2个⾏业,每⽉可更改1次所选⾏业;
  • 在所选择⾏业的模板库中选⽤已有的模板进⾏调⽤;
  • 每个账号可以同时使⽤25个模板。
  • 当前每个账号的模板消息的⽇调⽤上限为10万次,单个模板没有特殊限制。【2014年11⽉18⽇将接⼝调⽤频率从默认的⽇1万次提升为⽇10万次,可在 MP 登录后的开发者中⼼查看】。当账号粉丝数超过10W/100W/1000W时,模板消息的⽇调⽤上限会相应提升,以公众号 MP 后台开发者中⼼⻚⾯中标明的数字为准。

关于接⼝⽂档,请注意:

  • 模板消息调⽤时主要需要模板 ID 和模板中各参数的赋值内容;
  • 模板中参数内容必须以".DATA"结尾,否则视为保留字;
  • 模板保留符号""。

微信模板消息详情具体参考:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Template_Message_Interface.html

1. 设置⾏业

设置⾏业可在微信公众平台后台完成,每⽉可修改⾏业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"
}

参数说明
在这里插入图片描述

2. 创建模版

在微信公众平台根据⾏业模版案例创建消息模版。
在这里插入图片描述

附目前允许发的模板示例下载:点击下载

可自行根据允许的模板进行设置自己行业的消息模板。
在这里插入图片描述

3. 发送模版消息

接⼝调⽤请求说明

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
}

4. 后台示例代码

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));
    }
}

5. 三个方法测试效果

在这里插入图片描述

微信素材的上传与获取

公众号经常有需要⽤到⼀些临时性的多媒体素材的场景,例如在使⽤接⼝特别是发送消息时,对多媒体⽂件、多媒体消息的获取和调⽤等操作,是通过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

源码下载

源码链接:https://gitee.com/qkongtao/my-wx-demo

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不愿意做鱼的小鲸鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值