利用缓存、Timer间隔时间发送微信的实例,很有用的例子

//Class WechatOfferExcutor

此类为微信触发类,属于上层调用类,其中有用到用静态变量缓存offer信息,Task异步执行发送方法等

using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Velites.Utility.SharedLibrary;
using Newtonsoft.Json;
using System.Configuration;

namespace xxx.Peripheral.Wechat
{
    [ParametrType(typeof(WechatOfferParameter))]
    public class WechatOfferExcutor : MemberOfferExecutorBase<WechatOfferParameter>
    {
        static KeyValuePair<long, WechatOfferParameter> offerInfo = new KeyValuePair<long, WechatOfferParameter>();
        static WechatBatchProcess proc = new WechatBatchProcess(Send);

        protected override IOfferExecutionResult ExecuteWithIDataAndMember(IData data, IMember member, WechatOfferParameter offer)
        {
            bool isValid = AssertHits(data, member, offer);
            LogStub.Log(new LogEntry("txt - AssertHits isValid", LogStub.LOG_LEVEL_ERROR));
            if (isValid && !string.IsNullOrWhiteSpace(offer.Content))
            {
                string memCode = member.GetProperty(ThreeMMemberEntitySchema.ThreeMMember.CODE).ToString();
                string toWechat = member.GetProperty(ThreeMMemberEntitySchema.ThreeMMember.WECHAT_OPENID).ToString();

                List<ImgItem> itemList = new List<ImgItem>()
                {
                    new ImgItem() {
                    title = offer.Subject,
                    content = offer.Content
                    }
                };

                LogEntry entry = new LogEntry(string.Format("txt - 微信发送开始, memCode = {0}, wechatOpenID = {1}, offerID = {2}", memCode, toWechat, offer.OfferID), LogStub.LOG_LEVEL_ERROR);
                LogStub.Log(entry);

                proc.AddOpenIDAndSendWechat(offer.OfferID, toWechat, itemList, offer.ExecuteTime);
                //EmailServiceApiConfigurationHub.Instance.EmailProvider.Provide().Send(wechat);

                LogEntry endEntry = new LogEntry("txt - 微信发送结束", LogStub.LOG_LEVEL_ERROR);
                LogStub.Log(endEntry);
            }
            return null;
        }

        private static void Send(List<string> openIDs, List<ImgItem> imgDesc)
        {

            //注意,此处必须为异步调用发送方法,否则可能导致发送超时,以至于发送失败
            Task.Run(() => WechatUtility.SendText(openIDs, imgDesc));
            offerInfo = new KeyValuePair<long, WechatOfferParameter>();
        }

        public bool AssertHits(IData data, IMember member, WechatOfferParameter offer)
        {
            bool ret = true;
            if (data == null || member == null || offer == null || member.GetProperty(ThreeMMemberEntitySchema.ThreeMMember.WECHAT_OPENID) == null
                || string.IsNullOrWhiteSpace(member.GetProperty(ThreeMMemberEntitySchema.ThreeMMember.WECHAT_OPENID).ToString()))
            {
                ret = false;
                return ret;
            }
            return ret;
        }

        public override WechatOfferParameter ParseToParameter(JObject jOffer, IOffer offer)
        {
            if (offerInfo.Key != offer.ID)
            {
                WechatOfferParameter wechatOffer = base.ParseToParameter(jOffer, offer);
                wechatOffer.Category = offer.CategoryKey;
                var offerParameterToken = JToken.Parse(offer.Parameter);
                if (offerParameterToken["content"] != null)
                {
                    wechatOffer.Content = offerParameterToken["content"].ToString();
                    wechatOffer.Subject = offer.Name;
                    wechatOffer.OfferID = offer.ID;

                    //此处给发送时间赋值
                    //如果是市场活动,没有执行时间,那么可以设置为当前时间的5分钟之后
                    //测试时可以设置为10秒
                    //wechatOffer.ExecuteTime = DateTime.Now.AddSeconds(10);
                    wechatOffer.ExecuteTime = DateTime.Now.AddMinutes(5);
                    var interval = ConfigurationManager.AppSettings["ActivityInterval"];
                    if (interval != null)
                    {
                        wechatOffer.ExecuteTime = DateTime.Now.AddMinutes(Int32.Parse(interval.ToString()));
                    }

                    if (jOffer != null)
                    {
                        IDictionary<string, JToken> data = JsonConvert.DeserializeObject<JObject>(jOffer.ToString());
                        var item = data.Where(p => p.Key.ToLower() == "executetime");
                        if (item != null && item.Any())
                        {
                            wechatOffer.ExecuteTime = Convert.ToDateTime(item.FirstOrDefault().Value);
                        }
                    }

                    offerInfo = new KeyValuePair<long, WechatOfferParameter>(offer.ID, wechatOffer);
                    return wechatOffer;
                }
            }
            return offerInfo.Value;
        }
    }
}

 

 

 

 

//Class  WechatBatchProcess

此类是发送微信的中间处理类,包括了Timer间隔触发等,并发处理Lock机制等,其他的项目可以借鉴此类。

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace ThreeM.Peripheral.Wechat
{
    public class WechatBatchProcess
    {
        List<SendInfo> SendInfoList = new List<SendInfo>();
        Action<List<string>, List<ImgItem>> sendAct { set; get; }
        Timer timer;

        public WechatBatchProcess(Action<List<string>, List<ImgItem>> act)
        {
            timer = new Timer();
            sendAct = act;
            //正式的可以改10分钟,测试时可以为30000即30秒
            timer.Interval = 600000;
            var interval = ConfigurationManager.AppSettings["TimerInterval"];
            if (interval != null)
            {
                timer.Interval = Int32.Parse(interval);
            }
            timer.AutoReset = false;
            timer.Elapsed += new System.Timers.ElapsedEventHandler(Timers_Timer_Elapsed);
        }

        void Timers_Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            lock (this)
            {
                var itemList = SendInfoList.Where(p => p.SendTime <= DateTime.Now).ToList();
                SendInfoList = SendInfoList.Where(p => p.SendTime > DateTime.Now).ToList();
                foreach (var item in itemList)
                {
                    Send(item);
                }

                if (SendInfoList.Any())
                {
                    timer.Start();
                }
            }
        }

        public void AddOpenIDAndSendWechat(long OfferID, string OpenID, List<ImgItem> ImgDesc, DateTime? SendTime)
        {
            if (!string.IsNullOrWhiteSpace(OpenID) && ImgDesc != null && ImgDesc.Any())
            {
                lock (this)
                {
                    var item = SendInfoList.FirstOrDefault(p => p.OfferID == OfferID);
                    if (item == null)
                    {
                        item = new SendInfo()
                        {
                            OfferID = OfferID,
                            OpenidList = new List<string>(),
                            ImgDesc = ImgDesc,
                        };

                        SendInfoList.Add(item);

                    }
                    item.SendTime = SendTime;
                    item.OpenidList.Add(OpenID);
                }
                timer.Start();
            }
        }

        private void Send(SendInfo item)
        {
            if (item.OpenidList.Any())
            {
                sendAct(item.OpenidList, item.ImgDesc);
            }
        }
    }

    public class SendInfo
    {
        public List<string> OpenidList { get; set; }
        public List<ImgItem> ImgDesc { get; set; }
        public long OfferID { get; set; }
        public DateTime? SendTime { get; set; }
    }
}

 

 

 

//Class  WechatUtility

此类为基础工具类,包含了发送微信时需要的HttpPost请求等方法,

包括文本请求和多张图片请求等,是一个非常有用的工具类

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Configuration;
using System.Collections.Specialized;
using Velites.Utility.SharedLibrary;

namespace xxx.Peripheral.Wechat
{
    public class WechatUtility
    {
        public static string SendText(List<string> openIDList, string content)
        {
            string url = ConfigurationManager.AppSettings["wechatImgUrl"];
            string result = string.Empty;

            if (openIDList != null && openIDList.Any() && !string.IsNullOrWhiteSpace(content))
            {
                string param = string.Format("open_ids={0}&text={1}", string.Join(",",openIDList), content);
                result = HttpPostData(url, param);
            }
           
            return result;
        }

        public static string SendText(List<string> openIDList, List<ImgItem> imgDesc)
        {
            string url = ConfigurationManager.AppSettings["wechatImgUrl"];
            string result = string.Empty;
            var imgInfo = imgDesc.FirstOrDefault();

            if (openIDList != null && openIDList.Any() && !string.IsNullOrWhiteSpace(imgInfo.content))
            {
                //微信群发要求至少2个账号才能发送,如果只有一个时,添加一个相同的微信号
                if (openIDList.Count() == 1)
                {
                    openIDList.Add(openIDList.FirstOrDefault());
                }

                string param = string.Format("open_ids={0}&text={1}", string.Join(",", openIDList), imgInfo.content);
                result = HttpPostData(url, param);
            }

            return result;
        }

        public static string SendImgAndText(List<string> openIDList, string title, string content, string filePath)
        {
            string url = ConfigurationManager.AppSettings["wechatImgUrl"];
            string result = string.Empty;

            if (openIDList != null && openIDList.Any() && !string.IsNullOrWhiteSpace(content))
            {
                NameValueCollection col = new NameValueCollection();
                //col.Add("media", filePath);
                col.Add("title", title);
                col.Add("content", content);
                col.Add("open_ids", string.Join(",", openIDList));

                result = HttpPostData(url, 60000, "media1", filePath, col);
            }

            return result;
        }

        public static string SendImgAndText(List<string> openIDList, List<ImgItem> imgDesc)
        {
            string url = ConfigurationManager.AppSettings["wechatImgUrl"];
            string result = string.Empty;

            if (openIDList != null && openIDList.Any() && imgDesc != null)
            {
                Dictionary<string, string> imgDic = new Dictionary<string, string>();
                foreach (var item in imgDesc)
                {
                    imgDic.Add(item.name, item.path);
                }

                NameValueCollection col = new NameValueCollection();
                col.Add("imgDesc", Newtonsoft.Json.JsonConvert.SerializeObject(imgDesc));
                col.Add("open_ids", string.Join(",", openIDList));
                result = HttpPostData(url, 60000, imgDic, col);
            }

            return result;
        }

        public static string HttpPostData(string url, string param)
        {
            LogEntry entry = new LogEntry("发送微信文本开始-HttpPostData -- " + param, LogStub.LOG_LEVEL_ERROR);
            LogStub.Log(entry);

            var result = string.Empty;
            //注意提交的编码 这边是需要改变的 这边默认的是Default:系统当前编码
            byte[] postData = Encoding.UTF8.GetBytes(param);

            // 设置提交的相关参数
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            Encoding myEncoding = Encoding.UTF8;
            request.Method = "POST";
            request.KeepAlive = false;
            request.AllowAutoRedirect = true;
            request.ContentType = "application/x-www-form-urlencoded";
            request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR  3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)";
            request.ContentLength = postData.Length;

            // 提交请求数据
            System.IO.Stream outputStream = request.GetRequestStream();
            outputStream.Write(postData, 0, postData.Length);
            outputStream.Close();

            HttpWebResponse response;
            Stream responseStream;
            StreamReader reader;
            string srcString;
            response = request.GetResponse() as HttpWebResponse;
            responseStream = response.GetResponseStream();
            reader = new System.IO.StreamReader(responseStream, Encoding.GetEncoding("UTF-8"));
            srcString = reader.ReadToEnd();
            result = srcString;   //返回值赋值
            reader.Close();

            entry = new LogEntry("发送微信文本结束-HttpPostData -- " + result, LogStub.LOG_LEVEL_ERROR);
            LogStub.Log(entry);
            return result;
        }

        private static string HttpPostData(string url, int timeOut, string fileKeyName,
                                    string filePath, NameValueCollection stringDict)
        {
            string fileKeyName2 = "media2";
            string filePath2 = @"C:\Users\gaoj007\Pictures\1aliuh.jpg";


            string responseContent;
            var memStream = new MemoryStream();
            var webRequest = (HttpWebRequest)WebRequest.Create(url);
            // 边界符
            var boundary = "---------------" + DateTime.Now.Ticks.ToString("x");
            // 边界符
            var beginBoundary = Encoding.ASCII.GetBytes("--" + boundary + "\r\n");
            var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            // 最后的结束符
            var endBoundary = Encoding.ASCII.GetBytes("--" + boundary + "--\r\n");

            // 设置属性
            webRequest.Method = "POST";
            webRequest.Timeout = timeOut;
            webRequest.ContentType = "multipart/form-data; boundary=" + boundary;

            // 写入文件
            const string filePartHeader =
                "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
                 "Content-Type: application/octet-stream\r\n\r\n";
            var header = string.Format(filePartHeader, fileKeyName, filePath);
            var headerbytes = Encoding.UTF8.GetBytes(header);

            memStream.Write(beginBoundary, 0, beginBoundary.Length);
            memStream.Write(headerbytes, 0, headerbytes.Length);

            var buffer = new byte[1024];
            int bytesRead; // =0

            while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
            {
                memStream.Write(buffer, 0, bytesRead);
            }

            //第二章图片
            //memStream.Write(beginBoundary, 0, beginBoundary.Length);

           
            //var aaa = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
            //memStream.Write(aaa, 0, aaa.Length);

            string nxetFileFormat = "\r\n--" + boundary + "\r\n" + filePartHeader;

            header = string.Format(nxetFileFormat, fileKeyName2, filePath2);
            headerbytes = Encoding.UTF8.GetBytes(header);

            memStream.Write(headerbytes, 0, headerbytes.Length);
            fileStream = new FileStream(filePath2, FileMode.Open, FileAccess.Read);
            while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
            {
                memStream.Write(buffer, 0, bytesRead);
            }

            // 写入字符串的Key
            var stringKeyHeader = "\r\n--" + boundary +
                                   "\r\nContent-Disposition: form-data; name=\"{0}\"" +
                                   "\r\n\r\n{1}\r\n";

            foreach (byte[] formitembytes in from string key in stringDict.Keys
                                             select string.Format(stringKeyHeader, key, stringDict[key])
                                                 into formitem
                                                 select Encoding.UTF8.GetBytes(formitem))
            {
                memStream.Write(formitembytes, 0, formitembytes.Length);
            }

            // 写入最后的结束边界符
            memStream.Write(endBoundary, 0, endBoundary.Length);

            webRequest.ContentLength = memStream.Length;

            var requestStream = webRequest.GetRequestStream();

            memStream.Position = 0;
            var tempBuffer = new byte[memStream.Length];
            memStream.Read(tempBuffer, 0, tempBuffer.Length);
            memStream.Close();

            requestStream.Write(tempBuffer, 0, tempBuffer.Length);
            requestStream.Close();

            var httpWebResponse = (HttpWebResponse)webRequest.GetResponse();

            using (var httpStreamReader = new StreamReader(httpWebResponse.GetResponseStream(),
                                                            Encoding.GetEncoding("utf-8")))
            {
                responseContent = httpStreamReader.ReadToEnd();
            }

            fileStream.Close();
            httpWebResponse.Close();
            webRequest.Abort();

            return responseContent;
        }


        private static string HttpPostData(string url, int timeOut, Dictionary<string, string> imgDic, NameValueCollection stringDict)
        {
            LogEntry entry = new LogEntry("发送微信图片开始-HttpPostData open_ids-- " + stringDict["open_ids"], LogStub.LOG_LEVEL_ERROR);
            LogStub.Log(entry);
            try
            {
                entry = new LogEntry("发送微信图片开始-HttpPostData imgDic-- " + string.Join(",", imgDic), LogStub.LOG_LEVEL_ERROR);
                LogStub.Log(entry);

                entry = new LogEntry("发送微信图片开始-HttpPostData imgDic-- first--" + imgDic.FirstOrDefault().Key + " -- " +
                imgDic.FirstOrDefault().Value + "--last--" + imgDic.LastOrDefault().Key + " -- " + imgDic.LastOrDefault().Value + "--count--" + imgDic.Count(), LogStub.LOG_LEVEL_ERROR);
                LogStub.Log(entry);

                var firstImg = imgDic.FirstOrDefault();
                string fileKeyName = firstImg.Key;
                string filePath = firstImg.Value;

                string responseContent;
                var memStream = new MemoryStream();
                var webRequest = (HttpWebRequest)WebRequest.Create(url);
                // 边界符
                var boundary = "---------------" + DateTime.Now.Ticks.ToString("x");
                // 边界符
                var beginBoundary = Encoding.ASCII.GetBytes("--" + boundary + "\r\n");
                //var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);

                // 最后的结束符
                var endBoundary = Encoding.ASCII.GetBytes("--" + boundary + "--\r\n");

                // 设置属性
                webRequest.Method = "POST";
                webRequest.Timeout = timeOut;
                webRequest.ContentType = "multipart/form-data; boundary=" + boundary;

                // 写入文件
                const string filePartHeader =
                    "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
                     "Content-Type: application/octet-stream\r\n\r\n";
                var header = string.Format(filePartHeader, fileKeyName, filePath);
                var headerbytes = Encoding.UTF8.GetBytes(header);

                memStream.Write(beginBoundary, 0, beginBoundary.Length);
                memStream.Write(headerbytes, 0, headerbytes.Length);

                //var buffer = new byte[1024];
                //int bytesRead; // =0

                //while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                //{
                //    memStream.Write(buffer, 0, bytesRead);
                //}

                WebClient wc = new WebClient();
                byte[] buffer = wc.DownloadData(filePath);
                memStream.Write(buffer, 0, buffer.Length);

                string imgName = string.Empty;
                string imgPath = string.Empty;
                foreach (var img in imgDic.Where(p => p.Key != fileKeyName))
                {
                    imgName = img.Key;
                    imgPath = img.Value;

                    string nxetFileFormat = "\r\n--" + boundary + "\r\n" + filePartHeader;

                    header = string.Format(nxetFileFormat, imgName, imgPath);
                    headerbytes = Encoding.UTF8.GetBytes(header);

                    memStream.Write(headerbytes, 0, headerbytes.Length);
                    //fileStream = new FileStream(imgPath, FileMode.Open, FileAccess.Read);
                    //while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                    //{
                    //    memStream.Write(buffer, 0, bytesRead);
                    //}

                    buffer = wc.DownloadData(imgPath);
                    memStream.Write(buffer, 0, buffer.Length);
                }

                // 写入字符串的Key
                var stringKeyHeader = "\r\n--" + boundary +
                                       "\r\nContent-Disposition: form-data; name=\"{0}\"" +
                                       "\r\n\r\n{1}\r\n";

                foreach (byte[] formitembytes in from string key in stringDict.Keys
                                                 select string.Format(stringKeyHeader, key, stringDict[key])
                                                     into formitem
                                                     select Encoding.UTF8.GetBytes(formitem))
                {
                    memStream.Write(formitembytes, 0, formitembytes.Length);
                }
                // 写入最后的结束边界符
                memStream.Write(endBoundary, 0, endBoundary.Length);

                webRequest.ContentLength = memStream.Length;
                var requestStream = webRequest.GetRequestStream();
                memStream.Position = 0;
                var tempBuffer = new byte[memStream.Length];
                memStream.Read(tempBuffer, 0, tempBuffer.Length);
                memStream.Close();
                requestStream.Write(tempBuffer, 0, tempBuffer.Length);
                requestStream.Close();

                var httpWebResponse = (HttpWebResponse)webRequest.GetResponse();
                using (var httpStreamReader = new StreamReader(httpWebResponse.GetResponseStream(),
                                                                Encoding.GetEncoding("utf-8")))
                {
                    responseContent = httpStreamReader.ReadToEnd();
                }
                //fileStream.Close();
                httpWebResponse.Close();
                webRequest.Abort();

                entry = new LogEntry("发送微信图片结束-HttpPostData -- " + responseContent, LogStub.LOG_LEVEL_ERROR);
                LogStub.Log(entry);

                return responseContent;
            }
            catch (Exception er)
            {
                entry = new LogEntry("发送微信图文发生异常 -- HttpPostData -- " + er.ToString(), LogStub.LOG_LEVEL_ERROR);
                LogStub.Log(entry);
            }

            return null;
        }

    }
}


 


 

利用缓存、Timer间隔时间发送微信的实例,很有用的例子

上一篇:Java 微信公众号平台接入 视频


下一篇:Hibernate Validator 的使用