using System; using System.Collections.Generic; using System.Net; using System.Dynamic; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Common; using System.Threading.Tasks; namespace ZcPeng.weixin.PublicAccount { /// /// 群发消息 /// public static class MassMessage { /// /// 群发消息所用的http方法 /// private const string httpMethod = WebRequestMethods.Http.Post; /// /// 根据分组群发消息的地址 /// private const string urlForSendingAll = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token={0}"; /// /// 按OpenId列表群发消息的地址 /// private const string urlForSending = "https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token={0}"; /// /// 按OpenId列表群发消息的最大用户数 /// private const int maxUserCount = 10000; /// /// 删除群发消息的地址 /// private const string urlForDeleting = "https://api.weixin.qq.com/cgi-bin/message/mass/delete?access_token={0}"; /// /// 预览群发消息的地址 /// private const string urlForPreviewing = "https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token={0}"; /// /// 查询群发消息发送状态的地址 /// private const string urlForGettingStatus = "https://api.weixin.qq.com/cgi-bin/message/mass/get?access_token={0}"; /// /// 消息发送状态为发送成功的提示 /// private const string sendSuccess = "SEND_SUCCESS"; /// /// 根据分组群发消息 /// /// 公众号 /// 是否群发给所有用户 /// 如果群发给所有用户,忽略该参数;否则群发给该组中的用户 /// 群发消息类型 /// 多媒体id或者文本内容 /// 返回发送是否成功 /// 如果发送成功,返回消息ID;否则,返回-1。 public static async Task Send(string userName, bool isToAll, string groupId, MassMessageTypeEnum messageType, string mediaIdOrContent, ErrorMessage errorMessage) { long messageId = -1; if (!isToAll && string.IsNullOrWhiteSpace(groupId)) { errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "缺少分组ID。"); return messageId; } if (string.IsNullOrWhiteSpace(mediaIdOrContent)) { errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, string.Format("缺少{0}。", messageType == MassMessageTypeEnum.text ? "文本内容" : "媒体ID")); return messageId; } string json = GetMassMessageJsonString(isToAll, groupId, messageType, mediaIdOrContent); return await Send(userName, urlForSendingAll, json, errorMessage); } /// /// 根据OpenId列表群发消息 /// /// 公众号 /// OpenId列表 /// 群发消息类型 /// 多媒体id或者文本内容 /// 返回发送是否成功 /// 如果发送成功,返回消息ID;否则,返回-1。 public static async Task Send(string userName, IEnumerable tousers, MassMessageTypeEnum messageType, string mediaIdOrContent, ErrorMessage errorMessage) { long messageId = -1; if (tousers == null) { errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, string.Format("接收者不正确,数目必须大于0,小于等于{0}。", maxUserCount)); return messageId; } List touserList = new List(tousers); if (touserList.Count == 0 || touserList.Count > maxUserCount) { errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, string.Format("接收者不正确,数目必须大于0,小于等于{0}。", maxUserCount)); return messageId; } if (string.IsNullOrWhiteSpace(mediaIdOrContent)) { errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, string.Format("缺少{0}。", messageType == MassMessageTypeEnum.text ? "文本内容" : "媒体ID")); return messageId; } string json = GetMassMessageJsonString(touserList.ToArray(), messageType, mediaIdOrContent); return await Send(userName, urlForSending, json, errorMessage); } /// /// 群发消息 /// /// 公众号 /// 包含格式的服务器地址 /// 消息json字符串 /// 返回发送是否成功 /// 如果发送成功,返回消息id;否则,返回-1。 private static async Task> SendImpl(string userName, string urlFormat, string json) { long messageId = -1; ErrorMessage errorMessage; AccessToken token = AccessToken.Get(userName); if (token == null) { errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "获取许可令牌失败。"); return new Tuple(messageId, errorMessage); } string url = string.Format(urlFormat, token.access_token); string responseContent = await HttpHelper.HttpPost(url, json, "application/text"); //var data = JsonConvert.DeserializeAnonymousType(responseContent, new { msg_id = 0, msg_data_id = 0, errmsg = "",errcode = 0 }); if (responseContent == null|| responseContent == "") { errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "提交数据到微信服务器失败。"); return new Tuple(messageId, errorMessage); } JObject jo = JObject.Parse(responseContent); JToken jt; if (jo.TryGetValue("errcode", out jt) && jo.TryGetValue("errmsg", out jt)) { errorMessage = new ErrorMessage((int)jo["errcode"], (string)jo["errmsg"]); if (jo.TryGetValue("msg_id", out jt)) messageId = (long)jt; } else errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "解析返回结果出错。"); return new Tuple(messageId, errorMessage); } private static async Task Send(string userName, string urlFormat, string json, ErrorMessage errorMessage) { var result = await SendImpl(userName, urlFormat, json); var msgId = result.Item1; errorMessage = result.Item2; return msgId; } /// /// 获取群发消息的json字符串。 /// /// 是否群发给所有用户 /// 如果群发给所有用户,忽略该参数;否则群发给该组中的用户 /// 群发消息类型 /// 多媒体id或者文本内容 /// 返回群发消息的json字符串。 private static string GetMassMessageJsonString(bool isToAll, string groupId, MassMessageTypeEnum messageType, string mediaIdOrContent) { dynamic msg = new ExpandoObject(); msg.filter = new { is_to_all = isToAll, group_id = isToAll ? string.Empty : groupId }; if (messageType == MassMessageTypeEnum.text) ((IDictionary)msg).Add(messageType.ToString(), new { content = mediaIdOrContent }); else ((IDictionary)msg).Add(messageType.ToString(), new { media_id = mediaIdOrContent }); msg.msgtype = messageType.ToString(); return JsonConvert.SerializeObject(msg); } /// /// 获取群发消息的json字符串。 /// /// OpenId列表 /// 群发消息类型 /// 多媒体id或者文本内容 /// 返回群发消息的json字符串。 private static string GetMassMessageJsonString(string[] tousers, MassMessageTypeEnum messageType, string mediaIdOrContent) { dynamic msg = new ExpandoObject(); msg.touser = tousers; if (messageType == MassMessageTypeEnum.text) ((IDictionary)msg).Add(messageType.ToString(), new { content = mediaIdOrContent }); else ((IDictionary)msg).Add(messageType.ToString(), new { media_id = mediaIdOrContent }); msg.msgtype = messageType.ToString(); return JsonConvert.SerializeObject(msg); } /// /// 获取群发消息的json字符串。 /// /// OpenId /// 群发消息类型 /// 多媒体id或者文本内容 /// 返回群发消息的json字符串。 private static string GetMassMessageJsonString(string touser, MassMessageTypeEnum messageType, string mediaIdOrContent) { dynamic msg = new ExpandoObject(); msg.touser = touser; if (messageType == MassMessageTypeEnum.text) ((IDictionary)msg).Add(messageType.ToString(), new { content = mediaIdOrContent }); else ((IDictionary)msg).Add(messageType.ToString(), new { media_id = mediaIdOrContent }); msg.msgtype = messageType.ToString(); return JsonConvert.SerializeObject(msg); } /// /// 删除群发消息。 /// 注:只能删除图文消息和视频消息。 /// /// 公众号 /// 消息id /// 返回删除是否成功 //public static ErrorMessage Delete(string userName, long messageId) //{ // string json = JsonConvert.SerializeObject(new { msg_id = messageId }); // return HttpHelper.RequestErrorMessage(urlForDeleting, userName, null, httpMethod, json); //} public static async Task> PreviewImpl(string userName, string touser, MassMessageTypeEnum messageType, string mediaIdOrContent) { long messageId = -1; ErrorMessage errorMessage = null; if (string.IsNullOrWhiteSpace(mediaIdOrContent)) { errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, string.Format("缺少{0}。", messageType == MassMessageTypeEnum.text ? "文本内容" : "媒体ID")); return new Tuple(messageId, errorMessage ); } string json = GetMassMessageJsonString(touser, messageType, mediaIdOrContent); var result = await Send(userName, urlForPreviewing, json, errorMessage); return new Tuple(result, errorMessage); } /// /// 预览群发消息 /// /// 公众号 /// OpenId /// 群发消息类型 /// 多媒体id或者文本内容 /// 返回发送是否成功 /// 如果发送成功,返回消息ID;否则,返回-1。 public static async Task Preview(string userName, string touser, MassMessageTypeEnum messageType, string mediaIdOrContent, ErrorMessage errorMessage) { var tuple = await PreviewImpl(userName, touser, messageType, mediaIdOrContent); var result = tuple.Item1; errorMessage = tuple.Item2; return result; } /// /// 查询群发消息的发送状态 /// /// 公众号 /// 消息id /// 返回查询是否成功 /// 返回消息是否发送成功 //public static bool GetStatus(string userName, long messageId, out ErrorMessage errorMessage) //{ // string json = JsonConvert.SerializeObject(new { msg_id = messageId }); // string responseContent = HttpHelper.RequestResponseContent(urlForGettingStatus, userName, null, httpMethod, json); // if (string.IsNullOrWhiteSpace(responseContent)) // { // errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "从微信服务器获取响应失败。"); // return false; // } // else // { // JObject jo = JObject.Parse(responseContent); // JToken jt; // if (jo.TryGetValue("msg_status", out jt)) // { // errorMessage = new ErrorMessage(ErrorMessage.SuccessCode, "查询群发消息发送状态成功。"); // return (string)jt == sendSuccess; // } // else // { // errorMessage = ErrorMessage.Parse(responseContent); // return false; // } // } //} } }