详细分析Java 微信公众号的推送基本知识(附Demo)

前言

🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF

爬虫神器,无代码爬取,就来:bright.cn

Java基本知识:

  1. java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
  2. 【Java项目】实战CRUD的功能整理(持续更新)

1. 公众号配置

具体配置界面如下:

在这里插入图片描述

模版创建位置,如果找不到想要的,直接创建模版信息也可!

在这里插入图片描述

由于模版中没有我想要的,创建完成之后:

在这里插入图片描述

补充模版关键词参数类型:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Template_Message_Interface.html

在这里插入图片描述

相关的数据配置都在此处:

在这里插入图片描述

由于没有我想要的模版信息,后续想申请自身的模版(不过审核机制还是比较严格)

在这里插入图片描述

2. 源码解读

为便于讲解,会科普实战中用到的源码类:

WxMpTemplateData 这个类主要用于推送消息,key value对应的值,但是颜色值已经失效了,注意甄别

补充WxMpTemplateData 接口文档

@Data
public class WxMpTemplateData implements Serializable {
  private static final long serialVersionUID = 6301835292940277870L;

  private String name;
  private String value;
  private String color;

  public WxMpTemplateData() {
  }

  public WxMpTemplateData(String name, String value) {
    this.name = name;
    this.value = value;
  }

  public WxMpTemplateData(String name, String value, String color) {
    this.name = name;
    this.value = value;
    this.color = color;
  }

}

主要解读WxMpService 的基本知识

WxMpService 是 WeChat Java SDK(weixin-java-mp) 提供的 公众号核心服务接口
封装了微信的各种 API(如消息、用户、菜单、模板消息等),方便开发者调用

主要功能有如下:

  • 获取 AccessToken(接口认证)

  • 管理用户(获取用户信息、用户列表)

  • 管理消息(发送模板消息、群发消息、客服消息)

  • 管理菜单(自定义菜单、个性化菜单)

  • 管理素材(图片、视频、文本)

  • 管理 OAuth 授权(网页授权、扫码登录)

常用方法如下:

📌(1)获取 AccessToken

String accessToken = wxMpService.getAccessToken();
System.out.println("AccessToken: " + accessToken);

🔹 作用:获取调用微信 API 所需的 access_token,通常有效期为 2小时

📌(2)获取用户信息

WxMpUser user = wxMpService.getUserService().userInfo("用户OpenID");
System.out.println("用户昵称:" + user.getNickname());

🔹 作用:
通过 OpenID 查询用户信息
WxMpUser 包含用户的 昵称、头像、性别、城市、国家 等信息

📌(3)发送模板消息

WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
        .toUser("用户OpenID")  // 接收者 OpenID
        .templateId("模板ID")  // 模板 ID
        .url("https://你的跳转链接.com")  // 点击详情跳转
        .build();

// 添加数据
templateMessage.addData(new WxMpTemplateData("keyword1", "订单号:123456"));
templateMessage.addData(new WxMpTemplateData("keyword2", "状态:已支付"));

String msgId = wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
System.out.println("消息发送成功,msgId:" + msgId);

🔹 作用:
发送 公众号模板消息
toUser() 设置 接收者 OpenID。
templateId() 绑定 微信模板 ID
url() 设置 点击跳转链接

📌(4)自定义菜单

WxMenu menu = new WxMenu();
WxMenuButton button1 = new WxMenuButton();
button1.setType("view");
button1.setName("官网");
button1.setUrl("https://yourwebsite.com");

menu.getButtons().add(button1);
wxMpService.getMenuService().menuCreate(menu);
System.out.println("菜单创建成功!");

🔹 作用:
WxMenu 定义自定义菜单
setType(“view”) 表示跳转网页
setUrl() 设置跳转链接

📌(5)OAuth 网页授权

String redirectUrl = "https://你的回调地址.com";
String authUrl = wxMpService.getOAuth2Service().buildAuthorizationUrl(redirectUrl, WxConsts.OAuth2Scope.SNSAPI_USERINFO, "state");
System.out.println("用户点击授权链接:" + authUrl);

🔹 作用:
生成网页授权链接,用户点击后跳转到 redirectUrl 获取 code
WxConsts.OAuth2Scope.SNSAPI_USERINFO 表示获取用户详细信息

📌(6)获取素材

WxMpMaterial material = wxMpService.getMaterialService().materialGet("素材ID");
System.out.println("素材名称:" + material.getName());

🔹 作用:
materialGet(“素材ID”) 获取 永久素材(图片、视频、文本等)

📌(7)发送客服消息

WxMpKefuMessage message = WxMpKefuMessage.TEXT().toUser("用户OpenID").content("你好,这是一条客服消息").build();
wxMpService.getKefuService().sendKefuMessage(message);
System.out.println("客服消息发送成功!");

🔹 作用:
TEXT() 表示文本消息(支持 图片、语音、视频)
toUser() 指定接收者 OpenID
sendKefuMessage() 发送 客服消息(用户 48小时内 互动可用)

  1. WxMpService 初始化
    在 Spring Boot 项目中,通常通过 WxMpServiceImpl 实现 WxMpService 并初始化:
@Bean
public WxMpService wxMpService() {
    WxMpService wxMpService = new WxMpServiceImpl();
    WxMpConfigStorage configStorage = new WxMpDefaultConfigImpl();
    
    configStorage.setAppId("你的公众号APPID");
    configStorage.setSecret("你的公众号Secret");
    configStorage.setToken("你的Token");
    configStorage.setAesKey("你的AESKey");

    wxMpService.setWxMpConfigStorage(configStorage);
    return wxMpService;
}

🔹 作用:

初始化 WxMpServiceImpl,并配置公众号 APPID、Secret、Token

3. Demo(可执行)

这里是一个可直接运行的 Java Demo,不依赖 Spring Boot,只使用 WeChat SDK (weixin-java-mp) 来发送公众号模板消息

主要用于理解相关的框架 基本知识

注册微信公众平台并获取:

  • appId(公众号唯一标识)
  • secret(公众号密钥)
  • 启用模板消息,并创建一个模板,记录模板 templateId

安装 WeChat Java SDK:

<dependency>
    <groupId>com.github.binarywang</groupId>
    <artifactId>weixin-java-mp</artifactId>
    <version>4.5.0</version>
</dependency>

截图如下:

import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.config.WxMpConfigStorage;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;

import java.util.HashMap;
import java.util.Map;

public class WeChatTemplateMessageDemo {
    public static void main(String[] args) {
        // 1. 初始化 WxMpService
        WxMpService wxMpService = new WxMpServiceImpl();
        WxMpConfigStorage config = new WxMpDefaultConfigImpl();
        ((WxMpDefaultConfigImpl) config).setAppId("你的公众号APPID");
        ((WxMpDefaultConfigImpl) config).setSecret("你的公众号SECRET");
        ((WxMpDefaultConfigImpl) config).setToken("你的TOKEN");
        ((WxMpDefaultConfigImpl) config).setAesKey("你的AES_KEY");

        wxMpService.setWxMpConfigStorage(config);

        // 2. 目标用户的 OpenID
        String openId = "用户的OpenID";

        try {
            // 3. 检查用户是否关注公众号
            WxMpUser user = wxMpService.getUserService().userInfo(openId);
            if (user == null || !user.getSubscribe()) {
                System.out.println("用户未关注公众号,跳过发送");
                return;
            }

            // 4. 创建模板消息
            WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                    .toUser(openId)  // 接收者 OpenID
                    .templateId("你的模板ID")  // 微信公众平台的模板 ID
                    .url("https://yourwebsite.com")  // 点击跳转的 URL
                    .build();

            // 5. 填充模板数据
            Map<String, Object> values = new HashMap<>();
            values.put("keyword1", "123456789"); // 订单号
            values.put("keyword2", "支付成功"); // 状态
            values.put("keyword3", "2024-03-31 10:30:00"); // 时间

            for (String key : values.keySet()) {
                templateMessage.addData(new WxMpTemplateData(key, values.get(key).toString()));
            }

            // 6. 发送消息
            String result = wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
            System.out.println("消息发送成功,msgId:" + result);
        } catch (WxErrorException e) {
            System.err.println("微信推送失败:" + e.getError().getErrorMsg());
        }
    }
}

关键点解析

  • 检查用户是否关注公众号
WxMpUser user = wxMpService.getUserService().userInfo(openId);
if (user == null || !user.getSubscribe()) {
    System.out.println("用户未关注公众号,跳过发送");
    return;
}

🔹 避免推送给未关注的用户
创建并填充模板消息

WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
    .toUser(openId)
    .templateId("你的模板ID")
    .url("https://yourwebsite.com")
    .build();

🔹 这里的 templateId 必须是你在公众号后台配置的模板 ID
模板参数动态赋值

for (String key : values.keySet()) {
    templateMessage.addData(new WxMpTemplateData(key, values.get(key).toString()));
}

🔹 这样可以动态填充模板参数
发送消息

String result = wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
System.out.println("消息发送成功,msgId:" + result);

🔹 如果 msgId 返回 null,说明可能参数有误

注意事项
✅ 公众号必须认证:未认证的公众号无法使用 模板消息 API
✅ 用户必须关注公众号:否则消息无法送达
✅ 模板 ID 必须正确:后台 公众号管理平台 配置的 templateId 必须匹配

代码截图:

在这里插入图片描述

公众号内部的截图:
在这里插入图片描述

4. 实战配置

first 和 remark的字段已经取消掉了(2023年设定的新规),注意甄别使用模版信息

在这里插入图片描述

截图如下:

在这里插入图片描述

4.1 方案一

目前已经没有颜色区分了,所以直接使用Object格式
具体代码如下:

主体类:

import lombok.Data;

import java.util.Map;

@Data
public class MpTemplateSendReqDTO {

    // 更改为OpenId,直接对接。原始是对接mp的user表再去找openId,但mp user表不是实时更新
    private String openId;


    private String templateId;


    private String url;


    private Map<String,Object> values;

}

发送类:

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

import javax.validation.constraints.NotNull;
import java.util.Map;

@Schema(description = "管理后台 - 公众号模版消息发送 Request VO")
@Data
public class MpTemplateSendReqVO {

    @Schema(description = "openId", requiredMode = Schema.RequiredMode.REQUIRED, example = "xxxx")
    @NotNull(message = "openId不能为空")
    private String openId;

    @Schema(description = "公众号的模版id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    @NotNull(message = "公众号的模版id不能为空")
    private String templateId;

    @Schema(description = "url", example = "1024")
    private String url;

    @Schema(description = "发送参数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    @NotNull(message = "发送参数不能为空")
    private Map<String,Object> values;

}

业务逻辑类:

在这里插入图片描述

后续模板类核心代码如下:

String result = null;
// 指定三期公众号的appID,省的多次查表!
WxMpService mpService = mpServiceFactory.getRequiredMpService("xx");

// 先判断用户是否关注公众号
try {
    WxMpUser user = mpService.getUserService().userInfo(templateSendReqVO.getOpenId());
    if (user == null || !user.getSubscribe()) {
//                log.warn("用户未关注公众号,跳过发送。openId = {}", templateSendReqVO.getOpenId());
        return null; // 直接返回,不发送
    }
} catch (WxErrorException e) {
//            log.error("查询用户关注状态失败,openId = {}", templateSendReqVO.getOpenId(), e);
    return null; // 查询失败也跳过,避免异常中断主流程
}

//创建模版类
WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
        .toUser(templateSendReqVO.getOpenId())
        .templateId(templateSendReqVO.getTemplateId())
        .url(templateSendReqVO.getUrl()).build();

Map<String,Object> map = templateSendReqVO.getValues();

for(String key: map.keySet()){
    Object value = map.get(key);
    templateMessage.addData(new WxMpTemplateData(key,value.toString()));
}

try{
    result = mpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
}catch(WxErrorException e){
    throw exception(MESSAGE_SEND_FAIL, e.getError().getErrorMsg());
}

特别说明:

时间戳 时间会这样显示:

在这里插入图片描述

要显示正确的时间,需要以特定的格式进行转化:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
coloredMap.put("keyword3", new WxMpTemplateData("keyword3", cabinetPickupDO.getCreateTime().format(formatter)));

结果如下:

在这里插入图片描述

4.2 方案二(已弃)

目前是没有颜色区分的,后续如果需要增加颜色区分:
(微信自 2021 年起已不再支持 WxMpTemplateData 的 color 参数,所有颜色属性会被微信自动忽略)

以下作为学习而已,最新版本的 weixin-java-mp SDK 已去除了 color 相关的 JSON 生成逻辑,即使手动添加 color,最终微信 API 仍然会忽略它

<dependency>
    <groupId>com.github.binarywang</groupId>
    <artifactId>weixin-java-mp</artifactId>
    <version>4.6.0</version>
    <scope>compile</scope>
</dependency>

主体类如下:

import lombok.Data;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;

import java.util.Map;

@Data
public class MpTemplateSendReqDTO {

    // 更改为OpenId,直接对接。原始是对接mp的user表再去找openId,但mp user表不是实时更新
    private String openId;


    private String templateId;


    private String url;


    private Map<String,WxMpTemplateData> values;

}

发送类:

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;

import javax.validation.constraints.NotNull;
import java.util.Map;

@Schema(description = "管理后台 - 公众号模版消息发送 Request VO")
@Data
public class MpTemplateSendReqVO {

    @Schema(description = "openId", requiredMode = Schema.RequiredMode.REQUIRED, example = "xxxx")
    @NotNull(message = "openId不能为空")
    private String openId;

    @Schema(description = "公众号的模版id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    @NotNull(message = "公众号的模版id不能为空")
    private String templateId;

    @Schema(description = "url", example = "1024")
    private String url;

    @Schema(description = "发送参数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    @NotNull(message = "发送参数不能为空")
    private Map<String, WxMpTemplateData> values;

}

由于数据待有OpenID,对应发送到相关人员即可

// 微信通知
String openId = cabinetPickupDO.getOpenId();
if(openId != null){
    // 定义格式化器
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    Map<String, WxMpTemplateData> coloredMap = new HashMap<>();
    coloredMap.put("keyword1", new WxMpTemplateData("keyword1", cabinetPickupDO.getCntr()));
    coloredMap.put("keyword2", new WxMpTemplateData("keyword2", isApproved ? "xx 【通过】" : "xx 【不通过】", isApproved ? "#173177" : "#ff0000"));
    coloredMap.put("keyword3", new WxMpTemplateData("keyword3", cabinetPickupDO.getCreateTime().format(formatter)));


    MpTemplateSendReqDTO mpTemplateSendReqDTO = new MpTemplateSendReqDTO();
    mpTemplateSendReqDTO.setOpenId(openId)
            .setTemplateId("xx")
            .setUrl("xx")
            .setValues(coloredMap);
    mpTemplateApi.sendTemplateMessageAsync(mpTemplateSendReqDTO);
}

引入这个包:import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
截图如下:
在这里插入图片描述

模版类的核心如下:

String result = null;
// 指定xxx公众号的appID,省的多次查表!
WxMpService mpService = mpServiceFactory.getRequiredMpService("xxx");

// 先判断用户是否关注公众号
try {
    WxMpUser user = mpService.getUserService().userInfo(templateSendReqVO.getOpenId());
    if (user == null || !user.getSubscribe()) {
//                log.warn("用户未关注公众号,跳过发送。openId = {}", templateSendReqVO.getOpenId());
        return null; // 直接返回,不发送
    }
} catch (WxErrorException e) {
//            log.error("查询用户关注状态失败,openId = {}", templateSendReqVO.getOpenId(), e);
    return null; // 查询失败也跳过,避免异常中断主流程
}

//创建模版类
WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
        .toUser(templateSendReqVO.getOpenId())
        .templateId(templateSendReqVO.getTemplateId())
        .url(templateSendReqVO.getUrl()).build();

// 带颜色的通知
Map<String,WxMpTemplateData> coloredMap = templateSendReqVO.getValues();
for (WxMpTemplateData data : coloredMap.values()) {
    templateMessage.addData(data);
}

try{
    result = mpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
}catch(WxErrorException e){
    throw exception(MESSAGE_SEND_FAIL, e.getError().getErrorMsg());
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

码农研究僧

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

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

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

打赏作者

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

抵扣说明:

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

余额充值