微信小程序订阅消息

概述

消息能力是小程序能力中的重要组成,我们为开发者提供了订阅消息能力,以便实现服务的闭环和更优的体验。

  • 订阅消息推送位置:服务通知
  • 订阅消息下发条件:用户自主订阅
  • 订阅消息卡片跳转能力:点击查看详情可提爱转至该小程序的页面

avatar

消息类型

  1. 一次性订阅消息
    一次性订阅消息用于解决用户使用小程序后,后续服务环节的通知问题。用户自主订阅后,开发这可不限时间的下发一条对应的服务消息 ; 每条消息可单独订阅或退订(开发者自行控制发送)。
  2. 长期订阅消息
    一次性订阅消息可满足小程序的大部分服务场景需求,但线下公共服务领域存在一次性订阅无法满足的场景,如航班延误,需根据航班实时动态来多次发送消息提醒,为便于服务,因此提供了长期性订阅消息,用户订阅一次后,开发者可长期下发多条消息。
    目前长期性订阅消息仅向政务民生、医疗、交通、金融、教育等线下公共服务开放。

使用步骤

第一步 选择/配置模板

在微信公众号平台配置并获取模板ID。
登录https://mp.weixin.qq.com功能 >订阅消息栏目,在我的模板中列出了当前用户定义的所有模板信息,

avatar

当不存在模板或没有合适的模板时,可在 公共模板 中申请添加新模板,待审核通过后便可使用。

第二步 订阅消息

在小程序中通过编码的方式调用微信接口 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";
}

相关文章

概述 消息能力是小程序能力中的重要组成,我们为开发者提供了...
判断H5页面环境在微信中还是小程序中 用小程序提供的wx.mini...
wx.reLaunch和wx.navigateTo,wx.navigateTo的区别 2019-03-...
微信小程序如何从数组里取值_微信小程序 传值取值的几种方法...
H5项目接入微信授权登录,通过 UA 区分微信还是普通浏览器:...
微信小程序获取data-xx=&quot;&quot;属性的值,自定...