上一篇我们讲述了《微信公众号开发之根据标签进行群发(十二)》,这次我们讲解一下【根据OpenID列表群发】

根据OpenID列表群发【订阅号不可用,服务号认证后可用】

接口调用请求说明

http请求方式: POST https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token=ACCESS_TOKEN

POST数据说明

POST数据示例如下:

图文消息(注意图文消息的media_id需要通过上述方法来得到):

  1. {
  2. "touser":[
  3. "OPENID1",
  4. "OPENID2"
  5. ],
  6. "mpnews":{
  7. "media_id":"123dsdajkasd231jhksad"
  8. },
  9. "msgtype":"mpnews"
  10. "send_ignore_reprint":0
  11. }

文本:

  1. {
  2. "touser":[
  3. "OPENID1",
  4. "OPENID2"
  5. ],
  6. "msgtype": "text",
  7. "text": { "content": "hello from boxer."}
  8. }

语音:

  1. {
  2. "touser":[
  3. "OPENID1",
  4. "OPENID2"
  5. ],
  6. "voice":{
  7. "media_id":"mLxl6paC7z2Tl-NJT64yzJve8T9c8u9K2x-Ai6Ujd4lIH9IBuF6-2r66mamn_gIT"
  8. },
  9. "msgtype":"voice"
  10. }

图片:

  1. {
  2. "touser":[
  3. "OPENID1",
  4. "OPENID2"
  5. ],
  6. "image":{
  7. "media_id":"BTgN0opcW3Y5zV_ZebbsD3NFKRWf6cb7OPswPi9Q83fOJHK2P67dzxn11Cp7THat"
  8. },
  9. "msgtype":"image"
  10. }

视频:

请注意,此处视频的media_id需通过POST请求到下述接口特别地得到: https://api.weixin.qq.com/cgi-bin/media/uploadvideo?access_token=ACCESS_TOKEN POST数据如下(此处media_id需通过素材管理->新增素材来得到):

  1. {
  2. "media_id": "rF4UdIMfYK3efUfyoddYRMU50zMiRmmt_l0kszupYh_SzrcW5Gaheq05p_lHuOTQ",
  3. "title": "TITLE",
  4. "description": "Description"
  5. }

返回将为

  1. {
  2. "type":"video",
  3. "media_id":"IhdaAQXuvJtGzwwc0abfXnzeezfO0NgPK6AQYShD8RQYMTtfzbLdBIQkQziv2XJc",
  4. "created_at":1398848981
  5. }

然后,POST下述数据(将media_id改为上一步中得到的media_id),即可进行发送

  1. {
  2. "touser":[
  3. "OPENID1",
  4. "OPENID2"
  5. ],
  6. "mpvideo":{
  7. "media_id":"123dsdajkasd231jhksad",
  8. "title":"TITLE",
  9. "description":"DESCRIPTION"
  10. },
  11. "msgtype":"mpvideo"
  12. }

卡券:

  1. {
  2. "touser":[
  3. "OPENID1",
  4. "OPENID2"
  5. ],
  6. "wxcard": {"card_id":"123dsdajkasd231jhksad"}
  7. "msgtype":"wxcard"
  8. }

参数 是否必须 说明
touser 填写图文消息的接收者,一串OpenID列表,OpenID最少2个,最多10000个
mpnews 用于设定即将发送的图文消息
media_id 用于群发的图文消息的media_id
msgtype 群发的消息类型,图文消息为mpnews,文本消息为text,语音为voice,音乐为music,图片为image,视频为video,卡券为wxcard
title 消息的标题
description 消息的描述
thumb_media_id 视频缩略图的媒体ID
send_ignore_reprint 图文消息被判定为转载时,是否继续群发。 1为继续群发(转载),0为停止群发。 该参数默认为0。

返回说明

返回数据示例(正确时的JSON返回结果):

  1. {
  2. "errcode":0,
  3. "errmsg":"send job submission success",
  4. "msg_id":34182,
  5. "msg_data_id": 206227730
  6. }

参数 说明
type 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb),次数为news,即图文消息
errcode 错误码
errmsg 错误信息
msg_id 消息发送任务的ID
msg_data_id 消息的数据ID,,该字段只有在群发图文消息时,才会出现。可以用于在图文分析数据接口中,获取到对应的图文消息的数据,是图文分析数据接口中的msgid字段中的前半部分,详见图文分析数据接口中的msgid字段的介绍。

请注意:在返回成功时,意味着群发任务提交成功,并不意味着此时群发已经结束,所以,仍有可能在后续的发送过程中出现异常情况导致用户未收到消息,如消息有时会进行审核、服务器不稳定等。此外,群发任务一般需要较长的时间才能全部发送完毕,请耐心等待。

错误时微信会返回错误码等信息,请根据错误码查询错误信息

一、在SendUtil中添加发送的字符串和发送接口两个方法

  1. package com.xu.wemall.components.weixin;
  2. import com.alibaba.fastjson.JSONArray;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.xu.wemall.commons.constants.URIConstant;
  5. import lombok.extern.slf4j.Slf4j;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.stereotype.Component;
  8. import org.springframework.web.client.RestTemplate;
  9. import java.util.List;
  10. /**
  11. * 功能:群发工具类
  12. */
  13. @Slf4j
  14. @Component
  15. public class SendUtil {
  16. @Autowired
  17. private RestTemplate restTemplate;
  18. @Autowired
  19. private AccessTokenUtil accessTokenUtil;
  20. private String createSendAllString(boolean isToAll, String tagId, String mediaId, String msgtype){
  21. JSONObject data = new JSONObject();
  22. JSONObject filter = new JSONObject();
  23. filter.put("is_to_all",isToAll);
  24. if(tagId != null){
  25. filter.put("tag_id",tagId);
  26. }
  27. JSONObject type = new JSONObject();
  28. if(mediaId != null){
  29. type.put("media_id",mediaId);
  30. }
  31. data.put("filter",filter);
  32. //图文消息
  33. if(msgtype.equalsIgnoreCase("mpnews")){
  34. data.put("mpnews",type);
  35. data.put("send_ignore_reprint",1);
  36. }else if(msgtype.equalsIgnoreCase("text")){
  37. data.put("text",type); //文本
  38. }else if(msgtype.equalsIgnoreCase("voice")){
  39. data.put("voice",type); //声音
  40. }else if(msgtype.equalsIgnoreCase("image")){
  41. data.put("image",type); //图片
  42. }else if(msgtype.equalsIgnoreCase("mpvideo")){
  43. data.put("mpvideo",type); //声音
  44. }else if(msgtype.equalsIgnoreCase("wxcard")) {
  45. data.put("wxcard", type); //卡券
  46. }
  47. if(msgtype !=null){
  48. data.put("msgtype",msgtype);
  49. }
  50. return data.toJSONString();
  51. }
  52. private String createSendString(List<String> openIdList, String mediaId, String msgtype){
  53. JSONObject data = new JSONObject();
  54. JSONArray touser = new JSONArray();
  55. touser.addAll(openIdList);
  56. data.put("touser",touser);
  57. JSONObject type = new JSONObject();
  58. if(mediaId != null){
  59. type.put("media_id",mediaId);
  60. }
  61. //图文消息
  62. if(msgtype.equalsIgnoreCase("mpnews")){
  63. data.put("mpnews",type);
  64. data.put("send_ignore_reprint",1);
  65. }else if(msgtype.equalsIgnoreCase("text")){
  66. data.put("text",type); //文本
  67. }else if(msgtype.equalsIgnoreCase("voice")){
  68. data.put("voice",type); //声音
  69. }else if(msgtype.equalsIgnoreCase("image")){
  70. data.put("image",type); //图片
  71. }else if(msgtype.equalsIgnoreCase("mpvideo")){
  72. data.put("mpvideo",type); //声音
  73. }else if(msgtype.equalsIgnoreCase("wxcard")) {
  74. data.put("wxcard", type); //卡券
  75. }
  76. if(msgtype !=null){
  77. data.put("msgtype",msgtype);
  78. }
  79. return data.toJSONString();
  80. }
  81. /**
  82. *根据标签进行群发
  83. */
  84. public String sendByTagId(boolean isToAll, String tagId, String mediaId, String msgtype) {
  85. String accessToken = accessTokenUtil.getAccessToken();
  86. if (accessToken != null) {
  87. log.info("URL{}", URIConstant.SEND_ALL_URL);
  88. String url = URIConstant.SEND_ALL_URL.replace("ACCESS_TOKEN", accessToken);
  89. log.info("SEND_ALL_URL:{}", url);
  90. //将菜单对象转换成JSON字符串
  91. String dataString = this.createSendAllString(isToAll, tagId, mediaId, msgtype);
  92. log.info("dataString:{}",dataString);
  93. //发起POST请求创建菜单
  94. String jsonObject = restTemplate.postForObject(url, dataString,String.class);
  95. return jsonObject;
  96. }
  97. return null;
  98. }
  99. /**
  100. *根据OpenID列表群发
  101. */
  102. public String sendByOpenId(List<String> touser, String mediaId, String msgtype) {
  103. String accessToken = accessTokenUtil.getAccessToken();
  104. if (accessToken != null) {
  105. log.info("URL{}", URIConstant.SEND_URL);
  106. String url = URIConstant.SEND_URL.replace("ACCESS_TOKEN", accessToken);
  107. log.info("SEND_URL:{}", url);
  108. //将菜单对象转换成JSON字符串
  109. String dataString = this.createSendString(touser, mediaId, msgtype);
  110. log.info("dataString:{}",dataString);
  111. //发起POST请求创建菜单
  112. String jsonObject = restTemplate.postForObject(url, dataString,String.class);
  113. return jsonObject;
  114. }
  115. return null;
  116. }
  117. }
  118. 二、在SendController中添加swagger方法

  1. package com.xu.wemall.controller.weixin;
  2. import com.xu.wemall.components.weixin.SendUtil;
  3. import io.swagger.annotations.Api;
  4. import io.swagger.annotations.ApiImplicitParam;
  5. import io.swagger.annotations.ApiImplicitParams;
  6. import io.swagger.annotations.ApiOperation;
  7. import lombok.extern.slf4j.Slf4j;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RequestMethod;
  11. import org.springframework.web.bind.annotation.RequestParam;
  12. import org.springframework.web.bind.annotation.RestController;
  13. import java.util.List;
  14. /**
  15. * 类名称: SendController
  16. * 类描述: 群发API
  17. */
  18. @Slf4j
  19. @RestController
  20. @Api(tags = "群发接口")
  21. @RequestMapping(value = "/send")
  22. public class SendController {
  23. @Autowired
  24. private SendUtil sendUtil;
  25. /**
  26. * 根据标签进行群发
  27. */
  28. @ApiOperation(value = "根据标签进行群发")
  29. @RequestMapping(value = "/sendByTagId", method = RequestMethod.POST)
  30. @ApiImplicitParams({
  31. @ApiImplicitParam(name="isToAll",value="用于设定是否向全部用户发送,值为true或false,选择true该消息群发给所有用户,选择false可根据tag_id发送给指定群组的用户", paramType="query",dataType="String"),
  32. @ApiImplicitParam(name="tagId",value="群发到的标签的tag_id,参见用户管理中用户分组接口,若is_to_all值为true,可不填写tag_id", paramType="query",dataType="String"),
  33. @ApiImplicitParam(name="mediaId",value="用于群发的消息的media_id"),
  34. @ApiImplicitParam(name="msgtype",value="群发的消息类型,图文消息为mpnews,文本消息为text,语音为voice,音乐为music,图片为image,视频为video,卡券为wxcard", paramType="query",dataType="Integer")
  35. })
  36. public Object sendByTagId(boolean isToAll, String tagId, String mediaId, String msgtype) {
  37. String tempString = sendUtil.sendByTagId(isToAll, tagId, mediaId,msgtype);
  38. return tempString;
  39. }
  40. /**
  41. * 根据OpenID列表群发
  42. */
  43. @ApiOperation(value = "根据标签进行群发")
  44. @RequestMapping(value = "/sendByOpenId", method = RequestMethod.POST)
  45. @ApiImplicitParams({
  46. @ApiImplicitParam(name="mediaId",value="用于群发的消息的media_id"),
  47. @ApiImplicitParam(name="msgtype",value="群发的消息类型,图文消息为mpnews,文本消息为text,语音为voice,音乐为music,图片为image,视频为video,卡券为wxcard", paramType="query",dataType="Integer")
  48. })
  49. public Object sendByOpenId(@RequestParam(value = "touser") List<String> touser, String mediaId, String msgtype) {
  50. String tempString = sendUtil.sendByOpenId(touser, mediaId,msgtype);
  51. return tempString;
  52. }
  53. }

三,测试

我们需要先通过获取关注公众号的用户获得至少两个openid,然后测试如下

结果(泪奔中……)结果又是没有权限,因为我们用的是测试账号,测试账号现在已经没有群发功能权限了

查询微信公众号开发文档中的【全局返回码说明】确认的确是没有这个接口的权限,哎

如果您觉得此文有帮助,可以小小打赏一下,持续更新更有动力哟!

谢谢观看,下回我们继续不见不散!

微信公众号开发之根据OpenID列表群发(十四)的更多相关文章

  1. 【微信公众号开发】根据openId群发消息

    根据开发文档可知,只要使用POST方式提交固定格式的json字符串到那个地址即可.这里我写的是最简单的文本 第一步:建立对应的实体类. package cn.sp.bean; import java. ...

  2. 微信公众号开发前端获取openId

    参考 https://blog.csdn.net/qq_35430000/article/details/79299529

  3. 微信公众号开发上传图文素材带有卡片小程序报错:errcode=45166,errmsg = invalid content hint

    微信公众号开发自从支持允许在群发图文中插入小程序,方便了小程序的运营及推广.最近在三方服务开发中,要支持图文素材插入小程序遇到了一个很是棘手的问题.官方给出的插入小程序的示例支持文字.图片.卡片.如下 ...

  4. 微信公众号开发之网页中及时获取当前用户Openid及注意事项

    目录 (一)微信公众号开发之VS远程调试 (二)微信公众号开发之基础梳理 (三)微信公众号开发之自动消息回复和自定义菜单 (四)微信公众号开发之网页授权获取用户基本信息 (五)微信公众号开发之网页中及 ...

  5. ASP.NET MVC4 微信公众号开发之网页授权(二):通过公众号AppID(应用ID)和AppSecret(应用密钥)取得网页授权openid

    ASP.NET MVC4 微信公众号开发之网页授权(一):搭建基础环境 通过了上一篇文章我们已经搭建好了基础开发大环境,现在打开开发环境这里我用的是 vs2013,通过如下方式: 拼接请求链接重定向到 ...

  6. 微信公众号开发及时获取当前用户Openid及注意事项

    目录 (一)微信公众号开发之VS远程调试 (二)微信公众号开发之基础梳理 (三)微信公众号开发之自动消息回复和自定义菜单 (四)微信公众号开发之网页授权获取用户基本信息 (五)微信公众号开发之网页中及 ...

  7. NET微信公众号开发-5.0微信支付(待测试)

    开发前准备. 1.0微信支付官方开发者文档 2.0官方demo下载 我们用c#所以选择.net版本 不过这个官方的demo根本跑步起来 3.0官方demo运行起来解决方案 4.0微信支付官方.net版 ...

  8. C#微信公众号开发系列教程六(被动回复与上传下载多媒体文件)

    微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...

  9. C#微信公众号开发系列教程四(接收普通消息)

    微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...

随机推荐

  1. 新增6 n个骰子的点数

    /* * * 面试题43:n个骰子的点数 * 把n个骰子扔在地上,所有骰子朝上一面的点数之和为s. * 输入n,打印出s的所有可能的值出现的概率. * */ #include <iostream ...

  2. System.Diagnostics.Conditional 的妙用 -- 把文档放在代码中

    最近的工作跟 UI 打交道比较多, 各种坑. 今天从 Prefab 的序列化功能来说说 System.Diagnostics.Conditional 的妙用. 我们做 UI 面对各种按钮, 组件的获取 ...

  3. php中读取大文件实现方法详解

    php中读取大文件实现方法详解 来源:   时间:2013-09-05 19:27:01   阅读数:6186 分享到:0 [导读] 本文章来给各位同学介绍php中读取大文件实现方法详解吧,有需要了解 ...

  4. NSNotFound

    1.在数组或者字典中查找元素时,没有查到系统用NSNotFound表示.比如下面例子,应该养成这种编程习惯,可以减少因为’超标’而闪退的情况. if ([self.departmentNameArra ...

  5. 深入 Laravel 资料

    深入 Laravel 核心 Learning_Laravel_Kernel laravel 源码详解

  6. Centos7 下vmware NAT模式配置网络连接与DNS

    NAT模式配置网络 1.首先查看NAT模式下的网络 从这边可以知道我的vmware下的nat模式的网络是192.168.109.*网段 上图这个网段也可以修改为别的网段 2.NAT模式下的网关 3.配 ...

  7. 修改Centos7的yum源

    以下为修改Centos7的yum源: 1. 备份原镜像文件,便于后期恢复 [root@keepmydream ~]# mv /etc/yum.repos.d/CentOS-Base.repo /etc ...

  8. 题解 P5043 【【模板】树同构([BJOI2015]树的同构)】

    进入正题 题意:将所有树结构相同的树归类. 思路 嗯,这道题让我们把树的结构归类,自然而然就想到了哈希,我们对这整颗树哈希一遍.然后判同构就十分之简单了.只需要找哈希值一样的树就可以了. 其实真得很简 ...

  9. 范数(norm)

    [范数定义] 非负实值函数(非线性) 1)非负性: || a || >= 0 2)齐次性: || ka || = |k| ||a|| 3)三角不等式: || a + b || <= || ...

  10. HDFS 命令行基本操作

    1.hdfs命令行 (1)查看帮助 hdfs dfs -help (2)查看当前目录信息 hdfs dfs -ls / (3)上传文件 hdfs dfs -put /本地路径 /hdfs路径 (4)剪 ...