微信小程序结合微信公众号进行消息发送

由于小程序的模板消息已经废弃了,官方让使用订阅消息功能。而订阅消息的使用限制比较大,用户必须得订阅、需要获取用户同意接收消息的权限、用户必须得和小程序有交互的时候才能发送且只能发送一次。而我们的需求有可能是不限时间不限“次数”的发送消息。那么就可以使用官方提供的统一服务消息

统一服务消息

该功能还是有一点的使用限制的。

第一:小程序和公众号的主体必须是同一个。
第二:用户必须关注公众号。
第三:我们得有消息模板,小程序消息模板和公众号消息模板都可以。

结合文档,使用Java对发送消息的功能进行简单的封装

第一:使用httpClient请求地址,获取access_token

GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
根据官方接口的返回值,我们封装返回值对象
@Data
public class AccessToken {
/** 接口调用凭证 */
private String access_token;
/** 过期时间 */
private Long expires_in;
/** 错误信息代码 */
private String errcode;
/** 错误信息 */
private String errmsg;
}
使用httpClient发送请求
AccessToken accessToken = new AccessToken();

String url = WxMessageConstant.GET_XCX_ACCESS_TOKEN_URL + "&appid=" + WxMessageConstant.APP_ID + "&secret=" + WxMessageConstant.SECRET;
String result = HttpClientUtils.doGet(url); accessToken = JSON.parseObject(result, AccessToken.class);

注意:获得的token结果可以放在redis里面,设置上过期时间,防止应用重复获取access_token!

第二:构造请求

构造请求url

根据官方提供的接口再加上我们的获取的access_token进行构造

POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=ACCESS_TOKEN
构造请求参数

根据官方文档,我们一步一步来构造请求参数对象,我们用的是公众号的消息模板,所以这里没有weapp_template_msg参数

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ReqSendMessageData {
/**
* 消息接收者
*/
private String touser;
/**
* 公众号模板消息信息
*/
private MpTemplateMsg mp_template_msg;
}

构造mp_template_msg对象

@Data
@NoArgsConstructor
@AllArgsConstructor
public class MpTemplateMsg {
/** 公众号openId */
private String appid;
/** 公众号模板id */
private String template_id;
/** 跳转到公众号的地址,文档上写的必填,我没填,没有报错 */
private String url;
/** 公众号绑定的小程序信息 */
private Miniprogram miniprogram;
/** 数据 */
private Map<String,Object> data;
}

构造小程序信息

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Miniprogram {
/** 小程序appid */
private String appid;
/** 要跳转到小程序的页面 */
private String page;
}

贴出httpClient发送post请求的方式

public static String postSendJsonParam(String url, String param) {
CloseableHttpClient httpClient = HttpClients.createDefault();
String result = null;
// 请求方式
HttpPost httpPost = null;
// 响应
CloseableHttpResponse httpResponse = null;
httpPost = new HttpPost(url);
httpPost.setHeader("Connection", REQUEST_HEADER_CONNECTION);
httpPost.setHeader("User-Agent", REQUEST_HEADER_USER_AGENT);
httpPost.addHeader("content-type", "application/json;charset=utf-8");
httpPost.addHeader("accept", "application/json");
httpPost.setEntity(new StringEntity(param, "UTF-8")); try { httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
result = EntityUtils.toString(httpEntity);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} return result;
}

构造返回值对象,我们根据错误代码进行扩展操作

@Data
public class ResSendMessageDTO {
/** 错误代码 */
private String errcode;
/** 错误信息 */
private String errmsg;
}

最后我们可以把这些封装成一个service交给spring管理。

public interface MessageService {
/**
* @author: taoym
* @date: 2020/7/2 9:08
* @desc: 推送消息
*/
ResSendMessageDTO sendMessage(ReqSendMessageData data);
}

具体实现不展示了。

封装消息发送者

@Component
public class MessageSender { @Autowired
private MessageService messageService; /**
* @param first 消息标题
* @param keywordMap 消息内容
* @param page 要跳转到小程序的页面
* @param templateId 模板消息编号
* @param touser 消息接收者openId
* @author: taoym
* @date: 2020/9/28 11:25
* @desc: 消息发送者
*/
public ResSendMessageDTO sendMessage(String first, Map<String, Keyword> keywordMap, String touser, String page, String templateId) { // 消息模板上的数据
Map<String, Object> messageData = Maps.newHashMap();
// first,可以理解为 标题
messageData.put("first", new First(first));
// keywordMap 可以理解为内容
messageData.putAll(keywordMap); ReqSendMessageData reqSendMessageData = new ReqSendMessageData();
reqSendMessageData.setTouser(PasswordUtils.decrypt(touser));
MpTemplateMsg mpTemplateMsg = new MpTemplateMsg();
Miniprogram miniprogram = new Miniprogram();
miniprogram.setPage(page);
mpTemplateMsg.setMiniprogram(miniprogram);
mpTemplateMsg.setData(messageData);
mpTemplateMsg.setTemplate_id(templateId);
reqSendMessageData.setMp_template_msg(mpTemplateMsg);
ResSendMessageDTO resSendMessageDTO = messageService.sendMessage(reqSendMessageData);
// 0为成功的标志
if (!resSendMessageDTO.getErrcode().equals("0")) {
throw new ExceptionCore(resSendMessageDTO.getErrcode(), resSendMessageDTO.getErrmsg());
}
return resSendMessageDTO;
}
}

最后我们只需要根据模板消息的内容构造合理的参数,然后调用该方法即可发送消息。

微信小程序结合微信公众号进行消息发送的更多相关文章

  1. 微信小程序和微信公众号的id是一个吗

    首先,简单说下我遇到的问题是我们的程序调用微信小程序得到openid,然后通过openID得到用户的唯一标识,用户得以登录,然而,当我们调用微信公众号也同样的到openid,同一以用户两个不同的ope ...

  2. [转]微信小程序、微信公众号、H5之间相互跳转

    本文转自:https://www.cnblogs.com/colorful-paopao1/p/8608609.html 转自慕课网 一.小程序和公众号 答案是:可以相互关联. 在微信公众号里可以添加 ...

  3. 微信小程序、微信公众号、H5之间相互跳转

    转自慕课网 一.小程序和公众号 答案是:可以相互关联. 在微信公众号里可以添加小程序. 图片有点小,我把文字打出来吧: 可关联已有的小程序或快速创建小程序.已关联的小程序可被使用在自定义菜单和模版消息 ...

  4. 使用Appium 测试微信小程序和微信公众号方法

    由于腾讯系QQ.微信等都是基于腾讯自研X5内核,不是google原生webview,需要打开TBS内核Inspector调试功能才能用Chrome浏览器查看页面元素,并实现Appium自动化测试微信小 ...

  5. 微信小程序与微信公众号同一用户登录问题

    微信小程序与微信公众号同一用户登录问题 最近在做微信小程序与微信公众号登录合并的接口.整理相关资料以及个人认识的心得写了这篇文章与大家一起分享. 首先,简单说下我遇到的问题是我们的程序调用微信小程序得 ...

  6. 微信小程序(原名微信应用号)开发工具0.9版安装教程

    微信小程序全称微信公众平台·小程序,原名微信公众平台·应用号(简称微信应用号) 声明 微信小程序开发工具类似于一个轻量级的IDE集成开发环境,目前仅开放给了少部分受微信官方邀请的人士(据说仅200个名 ...

  7. 微信小程序(微信应用号)开发ide安装解决方法

    这两天整个技术圈都炸锅了,微信小程序(微信应用号)发布内测,首批200家收到邀请,但是没受邀请的同学,也不用担心,下面介绍一下解决方法. 首先需要下载ide,昨天只需要下载0.9版本的编辑器并替换文件 ...

  8. 微信小程序(微信应用号)组件讲解[申明:来源于网络]

    微信小程序(微信应用号)组件讲解[申明:来源于网络] 地址:http://www.cnblogs.com/muyixiaoguang/p/5902008.html

  9. 如何玩转小程序+公众号?手把手教你JeeWx小程序CMS与公众号关联

    随着微信小程序新功能.新入口的不断更新,小程序的商业价值逐步增强,特别是小程序与公众号的深度融合,已经让小程序成为各行业新的营销渠道.Jeewx平台专注小程序的开发,逐步完善小程序生态圈,通过简单操作 ...

随机推荐

  1. JS手写call、bind、apply

    call方法的实现 Function.prototype.MyCall = function(content,...args){ const self = content || window; con ...

  2. Netty之旅二:口口相传的高性能Netty到底是什么?

    高清思维导图原件(xmind/pdf/jpg)可以关注公众号:一枝花算不算浪漫 回复netty01即可. 前言 上一篇文章讲了NIO相关的知识点,相比于传统IO,NIO已经做得很优雅了,为什么我们还要 ...

  3. java安全编码指南之:基础篇

    目录 简介 java平台本身的安全性 安全第一,不要写聪明的代码 在代码设计之初就考虑安全性 避免重复的代码 限制权限 构建可信边界 封装 写文档 简介 作为一个程序员,只是写出好用的代码是不够的,我 ...

  4. 图解JAVA容器核心类库

    JAVA容器详解 类继承结构图 HashMap 1. 对象的HashCode是用来在散列存储结构中确定对象的存储地址的.   2. 如果两个对象的HashCode相同,即在数组中的地址相同.而数组的元 ...

  5. [CSP-S2019]树的重心 题解

    CSP-S2 2019 D2T3 考场上扔了T2来打这题的部分分,然后没看到数据范围是等号,不知道怎么判完全二叉树然后40分滚粗…… ---- 思路分析 很容易想到$O(n^2)$每次暴力找重心,这个 ...

  6. activiti app 6.0 乱码

    登录activiti-admin 乱码,解决后如下: 在catalina.bat文件中设置 -Dfile.encoding=UTF-8 1,windows 修改catalina.bat tomcat7 ...

  7. 关于提高服务器的带宽策略bonding

    一:bonding的概念 所谓bonding就是将多块网卡绑定同一IP地址对外提供服务,可以实现网卡的带宽扩容.高可用或者负载均衡. 二:bonding的优势 1 网络负载均衡 2 提高带宽网络传输效 ...

  8. ABP开发框架的技术点分析(1)

    ABP是ASP.NET Boilerplate的简称,ABP是一个开源且文档友好的应用程序框架.ABP不仅仅是一个框架,它还提供了一个最徍实践的基于领域驱动设计(DDD)的体系结构模型.ABP框架可以 ...

  9. 谁告诉的你们Python是强类型语言!站出来,保证不打你!

    1. 真的能用隐式类型转换作为强弱类型的判断标准吗?   最近有些学员问我,Python到底是强类型语言,还是弱类型语言.我就直接脱口而出:Python是弱类型语言.没想到有一些学员给我了一些文章,有 ...

  10. Flutter —布局系统概述

    老孟导读:此篇文章非常详细的讲解了 Flutter 布局系统的工作原理. 翻译自:https://itnext.io/flutter-layout-system-overview-c70bbe9ba9 ...