微信小程序订阅消息
概述
消息能力是小程序能力中的重要组成,我们为开发者提供了订阅消息能力,以便实现服务的闭环和更优的体验。
- 订阅消息推送位置:服务通知
- 订阅消息下发条件:用户自主订阅
- 订阅消息卡片跳转能力:点击查看详情可提爱转至该小程序的页面

消息类型
- 一次性订阅消息
一次性订阅消息用于解决用户使用小程序后,后续服务环节的通知问题。用户自主订阅后,开发这可不限时间的下发一条对应的服务消息 ; 每条消息可单独订阅或退订(开发者自行控制发送)。 - 长期订阅消息
一次性订阅消息可满足小程序的大部分服务场景需求,但线下公共服务领域存在一次性订阅无法满足的场景,如航班延误,需根据航班实时动态来多次发送消息提醒,为便于服务,因此提供了长期性订阅消息,用户订阅一次后,开发者可长期下发多条消息。
目前长期性订阅消息仅向政务民生、医疗、交通、金融、教育等线下公共服务开放。
使用步骤
第一步 选择/配置模板
在微信公众号平台配置并获取模板ID。
登录https://mp.weixin.qq.com 在功能 >订阅消息栏目,在我的模板中列出了当前用户定义的所有模板信息,

当不存在模板或没有合适的模板时,可在 公共模板 中申请添加新模板,待审核通过后便可使用。
第二步 订阅消息
在小程序中通过编码的方式调用微信接口 wx.requestSubscribeMessage 进行消息订阅。
示例
布局代码
<button bindtap="dingyue_message" >订阅消息</button>
js 代码
/**
* 订阅-消息
* @param {*} e
*/
dingyue_message : function(e){
wx.requestSubscribeMessage({
tmplIds: ['模板ID'],
success:function(res){
console.log('success:' + res.errMsg)
},
fail: function(res){
console.log('error:' + res.errMsg + " " + res.errCode)
}
})
}
实例中点击订阅消息按钮,会弹出订阅消息界面,返回用户订阅消息的结果。
注意事项
- 一次性模板 Id 和永久模板 Id 不可同时使用
- 低版本基础库2.4.4~2.8.3 已支持订阅消息接口调用,仅支持传入一个一次性 tmplId / 永久 tmplId。
- 2.8.2 版本开始,用户发生点击行为或者发起支付回调后,才可以调起订阅消息界面。
- 2.10.0 版本开始,开发版和体验版小程序将禁止使用模板消息 formId。
- 一次授权调用里,每个tmplId对应的模板标题不能存在相同的,若出现相同的,只保留一个。
- 2.10.0 版本开始,支持订阅语音消息提醒
第三步 服务端消息发送
发送订阅消息的调用方式有 HTTPS调用 和 云调用 两种方式,本文只介绍 HTTPS调用。
请求地址
POST https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN
请求参数
| 参数名 | 类型 | 默认值 | 必须 | 说明 |
|---|---|---|---|---|
| access_token / cloudbase_access_token | string | 是 | 接口调用凭证 | |
| touser | string | 是 | 接收者(用户)的 openid | |
| template_id | string | 是 | 所需下发的订阅模板id | |
| page | string | 否 | 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。 | |
| data | Object | 是 | 模板内容,格式形如 { "key1": { "value": any }, "key2": { "value": any } } | |
| miniprogram_state | string | 否 | 跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版 | |
| string | 否 | 进入小程序查看”的语言类型,支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为zh_CN |
返回值
| 属性 | 类型 | 说明 |
|---|---|---|
| errCode | number | 错误码 |
| errMsg | string | 错误信息 |
errCode 代码说明
| 代码 | 说明 |
|---|---|
| 0 | 成功 |
| 40003 | touser字段openid为空或者不正确 |
| 40037 | 订阅模板id为空不正确 |
| 43101 | 用户拒绝接受消息,如果用户之前曾经订阅过,则表示用户取消了订阅关系 |
| 47003 | 模板参数不准确,可能为空或者不满足规则,errmsg会提示具体是哪个字段出错 |
| 41030 | page路径不正确,需要保证在现网版本小程序中存在,与app.json保持一致 |
请求示例
/// <summary>
/// 微信发送消息
/// </summary>
public class MessageService : IMessageService
{
/// <summary>
/// 发送秒杀活动消息
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<ServiceResult<WeixinResultBase>> SendSeckillMessageAsync(SeckillMessageRequest request)
{
var goodsName = request.GoodsName;
if (goodsName.Length >= 20)
{
goodsName = request.GoodsName.Substring(0, 15) + "...";
}
var req = new SendMessageRequest
{
OpenId = request.OpenId,
TemplateId = request.TemplateId,
Page = $"{_seckillPagePath}?corpId={request.CorpId}&customerId={request.CustomerId}",
Data = new Dictionary<string, object>()
{
{"thing1",new { value = goodsName } },
{"time2",new { value = request.Time } },
{"thing3",new { value = "秒杀活动即将开始,支持一键发布到商店" } }
}
};
return await SendMessageAsync(req);
}
public async Task<ServiceResult<WeixinResultBase>> SendMessageAsync(SendMessageRequest request)
{
//先从缓存读取token
var accessToken = await _cache.GetStringAsync("store_assistant_accesstoken");
var url = $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={_appId}&secret={_appSecret}";
var response = await _httpClientFactory.GetClient().GetAsync(url);
var accessTokenResult = await response.Content.ReadAsAsync<WxAccessTokenQueryResult>();
if (accessTokenResult != null && accessTokenResult.ErrCode == 0)
accessToken = accessTokenResult.AccessToken;
var url = $"https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token={access_token.Result}";
var response = await _httpClientFactory.GetClient().PostDataAsync(url, request);
var responseTxt = await response.Content.ReadAsStringAsync();
var sendMsgResult = JsonConvert.DeserializeObject<WeixinResultBase>(responseTxt);
if (sendMsgResult != null && sendMsgResult.ErrCode == 0)
return ServiceResult.Succeed(sendMsgResult);
return ServiceResult.Failed(sendMsgResult, sendMsgResult.ErrCode, sendMsgResult.ErrMsg);
}
}
/// <summary>
/// 发送微信消息通知
/// </summary>
public class SendMessageRequest
{
/// <summary>
/// 用户openId
/// </summary>
[JsonProperty("touser")]
public string OpenId { get; set; }
/// <summary>
/// 订阅模板id
/// </summary>
[JsonProperty("template_id")]
public string TemplateId { get; set; }
/// <summary>
/// 跳转页面
/// </summary>
[JsonProperty("page")]
public string Page { get; set; }
/// <summary>
/// 模板类型
/// </summary>
[JsonProperty("data")]
public Dictionary<string, object> Data { get; set; }
/// <summary>
/// 跳转小程序类型 (eveloper为开发版;trial为体验版;formal为正式版;默认为正式版)
/// </summary>
[JsonProperty("miniprogram_state")]
public string MiniType { get; set; } = "formal";
/// <summary>
/// 语言类型(默认为zh_CN)
/// </summary>
[JsonProperty("lang")]
public string Lang { get; set; } = "zh_CN";
}
微信小程序订阅消息的更多相关文章
- 微信小程序订阅消息,我踩过的坑都在这里了!
旧的模板消息将在 2020 年 1 月 10 号全面下架,也就是今天,不过貌似现在还可以用!!!我已经改好了,只不过还没有上线,准备坚持到最后一天! 0.订阅消息 简单介绍一下订阅消息的特点: 用户授 ...
- 微信小程序订阅消息调研
相关资料 背景:微信模板消息已正式下架,改为订阅消息,详情如下: 服务变更通知 订阅消息:订阅消息相关内容如下: 订阅消息 接口设计 获取接口访问凭证 :根据appId和secret获取接口访问凭证a ...
- 微信小程序的模板消息与小程序订阅消息
小程序订阅消息 功能介绍 消息能力是小程序能力中的重要组成,我们为开发者提供了订阅消息能力,以便实现服务的闭环和更优的体验. 订阅消息推送位置:服务通知 订阅消息下发条件:用户自主订阅 订阅消息卡片跳 ...
- 微信小程序订阅
微信小程序订阅 摘要 1.基于promise封装微信小程序订阅 2.解决由于微信基础库版本低下的兼容 3.解决“总是保持以上选择,不再询问”的取消状态 主要运用API: requestSubscrib ...
- node配置微信小程序解密消息以及推送消息
上一篇文章介绍过 微信小程序配置消息推送,没有看过的可以先去查看一下,这里就直接去把那个客服消息接口去解密那个消息了. 在这里我选择的还是json格式的加密. 也就是给小程序客服消息发送的消息都会被微 ...
- 微信小程序模板消息群发解决思路
基于微信的通知渠道,微信为开发者提供了可以高效触达用户的模板消息能力,以便实现服务的闭环并提供更佳的体验.(微信6.5.2及以上版本支持模板功能.低于该版本将无法收到模板消息.) 模板推送位置:服务通 ...
- 微信小程序模板消息后端代码
利用spring 事件发送模板消息 1.定义事件 import com.ruoyi.project.salerauth.domain.TemplateMessage; import org.sprin ...
- 微信小程序-滚动消息通知
写在前面: 微信小程序学的不太多,做了一个简单的项目,回来很快时间内把在深圳两天的房租给赚回来了. 这次我主要想总结一下微信小程序实现上下滚动消息提醒,主要是利用swiper组件来实现,swiper组 ...
- 微信小程序-滚动消息通知效果
这次我主要想总结一下微信小程序实现上下滚动消息提醒,主要是利用swiper组件来实现,swiper组件在小程序中是滑块视图容器. 我们通过vertical属性(默认为false,实现默认左右滚动)设置 ...
随机推荐
- error LNK2019: 无法解析的外部符号 _WinMain@16,该符号在函数。。。使用
一,问题描述 MSVCRTD.lib(crtexew.obj) : error LNK2019: 无法解析的外部符号 _WinMain@16,该符号在函数 ___tmainCRTStartup 中被引 ...
- Spring Boot 的核心配置文件有哪几个?它们的区别是什么?
Spring Boot 的核心配置文件是 application 和 bootstrap 配置文件.application 配置文件这个容易理解,主要用于 Spring Boot 项目的自动化配置.b ...
- Spring支持的事务管理类型?
Spring支持两种类型的事务管理: 编程式事务管理 :这意味你通过编程的方式管理事务,给你带来极大的灵活性,但是难维护. 声明式事务管理: 这意味着你可以将业务代码和事务管理分离,你只需用注解和XM ...
- Redis的Jedis操作(五)
需要把jedis依赖的jar包添加到工程中.Maven工程中需要把jedis的坐标添加到依赖. 推荐添加到服务层. 1.连接单机版 第一步:创建一个Jedis对象.需要指定服务端的ip及端口. 第二步 ...
- ApplicationContext通常的实现是什么?
FileSystemXmlApplicationContext :此容器从一个XML文件中加载beans的定义,XML Bean 配置文件的全路径名必须提供给它的构造函数. ClassPathXmlA ...
- Java 中如何实现序列化,有什么意义?
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流 化.可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间. 序列化是为了解决对象流读写操作时可能引发的问题(如果不进 ...
- java常用方法集合
1.获取当前日期 // 获取当前日期 public Date getDate(int num) { Calendar cal = new GregorianCalendar(); cal.setTim ...
- 数据库SQL之学习SUM总和套用条件CASE WHEN语句
1.SQL之学习SUM总和套用条件CASE WHEN语句 2.条件语句CASE WHEN 格式已经在图中写的很明白了 -- 查询t_wzw库中所有数据 总和(条件为t_wzw.birthday > ...
- python udp socket通信
前段时间学习了一下c++的socket通信,但发现那玩意儿比较复杂还是转向python了,下面就是一个简单的udpsocket通信程序,欢迎大佬前来指正 udp聊天 import socket # 创 ...
- 记离线缓存(manifest)一大坑,断定其只适用于静态网站或离线应用
今天看了离线缓存(manifest)方面的资料,兴冲冲地就想给自己的网站用上.待我把代码都写好部署上服务器,并测试过OK的时候,在SegmentFault刷了一把manifest方面的问答,才发现这个 ...