ASP.NET实现微信功能(2)(服务号高级群发)

前面写了一篇文章,关于微信的:http://www.cnblogs.com/kmsfan/p/4047097.html

今天打算来写本系列的第二批文章,服务号后台群发。

在写本篇文章之前,我们先来看看腾讯的后台群发是怎么实现的,因为我们无论做什么事情都要知道原理。开始吧。

由于本人的奉献精神,等下回把实现源码的框架全部公开,里面什么东西都有,由于自己才识浅薄,只弄了图文消息的群发,那么今天只会介绍图文消息的群发。

框架的源码文章最后会提到,这本来是一个开源的框架,经过一些大神的二次修改而更加的完善。

由于可以群发多条消息,那么我们今天就来说说服务号的后台群发(多篇文章)。

我们来分析一下,上面的图 :标题,封面,正文,这3项在微信里填写是必须的,也就是说,我们如果要从后台C#去推送消息,那么这3项肯定也是必须的。

但是够了吗?不够,我们群发可以根据组去群发,也可以对所有人群发,对吧?

那么这里的人,就是我们的粉丝,每个粉丝在微信里有一个唯一的东西,那就是ID,我们需要获得那些要推送的人的IDS,那样才可以发送。

另外跟大家说一下,微信的接口调用每天是100次,但是群发一周是一次,也就是说,如果你群发成功了多次,也只会以第一次的群发的消息为准。

好了,做了这么多的准备工作,大家也有点迫不及待了吧?!那我们就开始研究代码吧。

我用的是一个开源的微信框架,其中的EXTENSION是某位大神写的,我们这次只研究群发功能SendNews.因为我自己只做了群发。

其中填写APPID 和APPSECRET的地方在REQUEST下的AccessTokenGetRequest.cs文件里,大家可以把这些写在配置文件里哦

我们先来研究一下这个SendUser方法,首先我们需要明白的一点是这下面的几个参数的含义,

1.data :就是你要传递的图文消息的集合,这个稍后会提到。

2.userIDList:粉丝的ID。

3.msgType:是否图文消息

4.accesstoken,这个是凭证,不用我多说了,

5.impclient:框架自带的东西,具体的我没研究,大家有兴趣的自己去研究

大家看过官方的文档的都知道,其实我们是向那个调用的接口发送一段规定格式的XML。

那么下面也基本上是拼接好规定格式的字符串。

其中大家注意到了一个东西,那就是media_Id,这个东西怎么获得呢?

这个东西其实就是我们上传的封面图片之后,然后服务器返回给我们的ID,这个ID是必须的。

        private static string accessToken;
        private static IMpClient mpClient;

        public static string SendUser(object data, List<string> UserIDList, bool msgType, string accessToken, IMpClient mpClient)
        {
            SendNews.accessToken = accessToken;
            SendNews.mpClient = mpClient;
            StringBuilder postData = new StringBuilder("{");
            postData.AppendFormat("\"touser\":{0},", JsonConvert.SerializeObject(UserIDList));
            if (msgType)
            {
                var msgId = UpdateNews(data as List<Model.NewsList>);
                if (string.IsNullOrEmpty(msgId)) { return "-1"; }
                postData.Append(" \"mpnews\":{  \"media_id\":\"" + msgId + "\"},\"msgtype\":\"mpnews\"");
            }
            else
            {
                postData.Append("\"msgtype\": \"text\",\"text\": { \"content\":\"" + data.ToString() + "\"}}");
            }
            var rdata = HttpHelper.Example.GetWebData(new BrowserPara()
            {
                Uri = string.Format("https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token={0}", accessToken),
                PostData = postData.ToString()
            });
            return !HasError(rdata) ? Tools.GetJosnValue(rdata, "errcode") : "-1";
        }

下面我们来看一下这个updateNews 方法,然后我再带大家看看实体类,就是这个newsList.

下面是实体类

其中有几点大家要注意:

1.NID:就是点击微信文章进去后的超链接地址,就相当于你要建立一个Preview页面,这个页面是任何人可以访问的,然后这个页面带的ID不同,显示不同的文章。

2.CoverImage:这个是封面图片的地址,注意:微信只接受 本地图片,不接受IIS地址,所以你先要把IIS上的文件下载到本地,然后再从本地上传。

3.其他的没注释掉的,是不能删除的,否则会报空指针异常,比如SUMMARY,大家可以 根据需求酌情修改。

namespace Model
{
    using System;
    using System.Collections.Generic;

    public partial class NewsList
    {
        public string  NID { get; set; }
        public string Title { get; set; }
        public string CoverImage { get; set; }
        public string NContent { get; set; }
        public string Summary { get; set; }
       // public int nType { get; set; }
       // public bool Marking { get; set; }
        public System.DateTime AddTime { get; set; }
        //public bool isDel { get; set; }
    }
}

下面是UpdateNews方法。大家看看就好,反正就是从object data里,也就是newsList里面遍历数据。

        #region 2.0 上传图文新闻 static string UpdateNews(List<Model.ViewModel.NewsListEditModel> newsList)
        /// <summary>
        /// 上传图文新闻
        /// </summary>
        /// <param name="newsList"></param>
        /// <returns></returns>
        public static string UpdateNews(List<Model.NewsList> newsList)
        {

            StringBuilder postData = new StringBuilder(512);
            for (int i = 0; i < newsList.Count; i++)
            {
                UploadMediaRequest request = new UploadMediaRequest()
                {
                    AccessToken = accessToken,
                    Type = "image",
                    FileName = newsList[i].CoverImage
                };
                UploadMediaResponse response = mpClient.Execute(request);
                if (!response.IsError)
                {
                    newsList[i].CoverImage = response.MediaId;
                }
                else
                {
                    return string.Empty;
                }

            }
            postData.Append("{\"articles\": [");
            for (int j = 0; j < newsList.Count; j++)
            {
                postData.Append("{");
                postData.AppendFormat(" \"thumb_media_id\":\"{0}\",", newsList[j].CoverImage);
                postData.AppendFormat(" \"title\":\"{0}\",", newsList[j].Title.Replace("\"", "“").Replace("‘", "‘"));
                postData.AppendFormat(" \"content_source_url\":\"{0}\",", newsList[j].NID);
                postData.AppendFormat(" \"content\":\"{0}\",", newsList[j].Summary.Replace("\"", "“").Replace("‘", "‘"));
                postData.AppendFormat(" \"digest\":\"{0}\",", newsList[j].Summary.Replace("\"", "“").Replace("‘", "‘"));
                postData.Append(j == newsList.Count - 1 ? "\"show_cover_pic\":\"1\"}" : "\"show_cover_pic\":\"1\"},");
            }

            postData.Append("]}");

            var rdata = HttpHelper.Example.GetWebData(new BrowserPara()
                 {
                     Uri = string.Format("https://api.weixin.qq.com/cgi-bin/media/uploadnews?access_token={0}", accessToken),
                     PostData = postData.ToString()
                 });

            return !HasError(rdata) ? Tools.GetJosnValue(rdata, "media_id") : string.Empty;
        }

下面最后再来介绍一下调用,如果你是4.0的框架,可以不用往下面看了,因为下面的是基于4.0以下的框架的调用方法。

我这里用的是WebService去调用,因为网站是2.0的,而框架是4.0的。

首先第一步,我们必须引用这个项目,我为了方便,引用的是解决方案,大家如果要发布的话,会自动生成DLL文件的,这个不必担心。

下面的是方法,如果ReturnVal最后的值是0的话,恭喜你,操作成功!

方法是先得到关注者的IDS,然后遍历List,把数据填充到List里面去,如果 你的opeNID能取到所有关注者的IDS那么就成功了。

   [WebMethod(Description = "处理微信群发功能", EnableSession = true)]
        public string ProcessWeiXinGroupPush()
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            SysBaseTag sysbase = new SysBaseTag();
            string temp = "";
            Mobile_msg msg = new Mobile_msg();
            sysbase.data = new List<object>();

            //得到关注着的IDLIST;
            var idlist = new List<string>();

            //得到关注着的IDS
            var uidRequest = new GetAttentionsRequest()
            {
            AccessToken=OperateContextMP.Current.GetAccessToken.AccessToken.AccessToken
            };

            var createResponse = OperateContextMP.Current.MpClient.Execute(uidRequest);

            if (createResponse.IsError)
            {

            }
            else
            {
                idlist = createResponse.Attentions.data.opeNID;

            }

            try
            {
                string sql = "select * from cms_core_content a,CMS_EXT_NEWS b,CMS_WECHAT c where a.ID=b.ID and c.newsid=b.ID and c.datetime=‘" + DateTime.Now.ToShortDateString().Substring(0,10) + "‘";
                DataSet ds = DBHelperSQL.Query(sql, DBHelperSQL.GetDBString(), 2);
                List<NewsList> list = new List<NewsList>();
                foreach (DataRow Row in ds.Tables[0].Rows)
                {
                    NewsList nlist = new NewsList();

                    DownloadToLocal(Row["jumpurl"].ToString()); //下载文件到本地

                    string coverImg = "D:\\test\\" + Row["jumpurl"].ToString().Substring(Row["jumpurl"].ToString().LastIndexOf("/") + 1);
                   // string mapPath = "http://localhost/"
                    nlist.Title = Row["title"].ToString();
                    nlist.NContent = Row["text"].ToString();
                    nlist.NID = Row["id"].ToString();
                    nlist.CoverImage = coverImg;
                    // nlist.summary = "测试推送"; //暂时先这么写
                    nlist.Summary = Row["title"].ToString(); //描述:必填项
                    list.Add(nlist);
                    sysbase.data.Add(nlist);

                }

                sysbase.message = "成功";
                sysbase.result = true;
                sysbase.count = sysbase.data.Count;

                //从数据库中获取图文消息并添加
                 var newsList = new List<NewsList>();
                string returnVal = SendNews.SendUser(list, idlist, true, OperateContextMP.Current.GetAccessToken.AccessToken.AccessToken, OperateContextMP.Current.MpClient);

                 temp = returnVal;

            }
            catch (Exception e)
            {
                sysbase.message = e.Message;
                sysbase.result = false;
                sysbase.count = 0;

            }
            //return serializer.Serialize(sysbase);
            return temp;
        }

大家还要注意下,封面必须下载到本地,这里我的图片本来是在IIS中的,建议封面图片专门用一个字段去存储。

        //下载服务器上的封面文件保存到本地机器上。
        public void DownloadToLocal(string filePath)
        {

            string filePath_ = ConfigurationManager.AppSettings["basicIP"] + filePath;

            //在D盘新建一个TEST目录
            WebClient wc = new WebClient();
            string path = @"D:\WX_ESP_PIC";
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            wc.DownloadFile(filePath_, path+"\\"+filePath_.Substring(filePath_.LastIndexOf("/")));
        }

好了,说了这么多,下面的是框架源码。

大家拿去用就是的了。

http://pan.baidu.com/s/1c0Chn3a

提取码:peye

时间: 2024-10-18 19:51:29

ASP.NET实现微信功能(2)(服务号高级群发)的相关文章

【课程分享】深入浅出微信公众平台实战开发(微网站、LBS云、Api接口调用、服务号高级接口)

深入浅出微信公众平台实战开发(微网站.LBS云.Api接口调用.服务号高级接口) 课程下载地址:链接:http://pan.baidu.com/share/link?shareid=2214724072&uk=3611155194 密码:glvc 一.本课程是怎么样的一门课程(全面介绍) 1.1.课程的背景 微信公众平台的火热程度已经不用多言,无论是个人还是企业,政府还是商家,都已经开始搭建微信公众平台,微信的作用已经被各界人士认可.微信公众平台的技术需求市场缺口巨大. 1.2.课程内容简介 本

微信公众平台服务号与订阅号区别详解【有图】

微信公众平台现在分为两个类别的号:一个是服务号,一个订阅号.服务号是针对企业的,订阅号是针对个人的.这个两种类型的号有很大的区别,特别是功能上有所不同. 工具/原料 电脑.微信公众平台 微信公众平台服务号与订阅号"首页"区别 1 微信公众平台服务号首页面:主要的标志是:服务号 其他的和订阅号一样.如下图所示: 2 微信公众平台订阅号首页面:主要的标志是:订阅号 其他的和服务号一样.如下图所示: 3 微信公众平台服务号与订阅号进入的首页界面是一样的,主要的区别就是标志不一样,明确指出所登

微信公众平台开发(89) 高级群发接口

在这篇微信公众平台高级接口开发教程中,我们将介绍如何开发高级群发接口功能. 本文分为以下四个部分: 准备群发内容 选择群发对象 执行群发 接收群发结果 一.准备群发内容 群发内容可以是文本.图片.语音.视频.图文.群发文本只需要文本内容,其他内容需要获得相应的media_id. 1. 文本内容 文本内容就是一段文字,比如:"微信公众平台开发最佳实践" 2. 图片.语音.视频 要求如下: ? 图片(image): 128K,支持JPG格式 ? 语音(voice):256K,播放长度不超过

微信公众平台开发(89) 高级群发接口(转)

在这篇微信公众平台高级接口开发教程中,我们将介绍如何使用接口实现微信公众平台群发功能. 本文分为以下四个部分: 准备群发内容 选择群发对象 执行群发 接收群发结果 一.准备群发内容 群发内容可以是文本.图片.语音.视频.图文.群发文本只需要文本内容,其他内容需要获得相应的media_id. 1. 文本内容 文本内容就是一段文字,比如:"微信公众平台开发最佳实践" 2. 图片.语音.视频 要求如下: ? 图片(image): 128K,支持JPG格式 ? 语音(voice):256K,播

啊Ran讲微信开发(.net) :公众号(服务号)+自定义服务器(OAuth授权登录)

上一篇我们探讨到自定义菜单key为view带有一个"url"参数的点击事件,这边我们就聊聊"微信授权登录". 1.网页授权接口 网页授权接口允许微信公众号的第三方网页获取微信个人用户的基本信息,包括昵称,头像,性别,城市,国家,注册时间等.利用微信个人用户的基本信息,可以实现体验优化,用户来源统计,账号绑定,用户身份鉴权等功能. OAuth协议为用户资源的授权提供了一个安全的,开放而简易的标准,与以往的授权方式不同之处是OAuth的授权不会使第三方触及到用户的账户信

微信开发系列教程:(1)订阅号和服务号深入分析

微信开发系列教程,将以一个实际的微信平台项目为案例,深入浅出的讲解微信开发.应用各环节的实现方案和技术细节. 原创内容,欢迎转载,转载请注明出处. 首先在第1章节中,我们先理清什么是订阅号,什么又是服务号,以及两者的关键性区别. 订阅号和服务号统称为微信公众号. 订阅号强调媒体资讯属性,为会员提供信息订阅,适用于新闻传媒类企业.订阅号从某种意义上来讲,是拿来做内容的,如果你没有原创作品,对用户没有任何意义. 服务号强调服务和应用属性,旨在为会员提供服务并与之互动.支持所有微信高级接口,几乎所有的

多客服功能终于也向所有微信认证的订阅号开放了

多客服功能支持多人同时为一个公众号提供客服服务,经过半年多仅对认证服务号开放后,现在终于也向所有微信认证的订阅号开放了,所有微信认证的服务号和订阅号可以在“功能”-“添加功能插件”页申请开通多客服功能.开通成功后,在“功能”-“多客服”页,可使用多客服功能. 认证公众号的开发者可使用多客服相关接口,完成定制化客服功能开发 消息转发到多客服 如果公众号处于开发模式,普通微信用户向公众号发消息时,微信服务器会先将消息POST到开发者填写的url上,如果希望将消息转发到多客服系统, 则需要开发者在响应

微信服务号开发笔记

原理 微信服务号的原理比较简单.从请求响应角度来看,逻辑是: 用户微信客户端 <—> 微信服务器 <—> 微信服务号后台程序 <—> 数据库或Web Service 也就是,用户的各种请求先经过微信的服务器,微信服务器将请求转发给微信服务号后台程序. 既然是微信服务器把用户请求数据转发给我们开发的微信服务号后台程序,那么在启用服务号的开发模式时就需要提供一个URL.另外为了安全 考虑,还需要提供一个token,用来校验请求是否来自微信服务器.校验的方法见微信开发者文档.

微信服务号认证流程

一.申请微信认证 1.申请微信认证入口. 1) “设置->账户信息->认证情况“点击“申请微信认证”进入. 2) “服务->服务中心“点击“微信认证”进入. 2.申请微信认证操作全攻略. 1) 签署<微信公众平台认证服务协议>,勾选同意,点击下一步. 2) 同意<公众号命名规则>,勾选同意,点击下一步. 3) 填写资料:根据账号类型选择企业或媒体(目前只支持这两种类型),并如实填写认证资料. 特别说明:企业对公银行帐户为必填项,在审核过程中第三方审核公司会向该帐户