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;
// }
// }
//}
}
}