最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来。我们都知道计算机技术发展日新月异,速度惊人的快,你我稍不留神,就会被慢慢淘汰!因此:每日不间断的学习是避免被淘汰的不二法宝。
十年河东十年河西,莫欺少年穷。
最近微信开发依然是那么火,有人请我开发一个微信海报,拿到需求后,我瞬间笑了,这不就是两年前我学习微信的时候自己做的一个案例吗?能有什么技术含量?
当然,我有点自大了,所谓骄兵必败,咱还是来分析分析这个微信海报吧!
所谓微信海报就是一个图片,这个图片上有粉丝的专属二维码,有粉丝的头像及商户宣传的广告等。
我做的微信海报如下图:
看到吗?上边有我的专属二维码,不过这个二维码是临时的,我做的有效期是7天(看了最新的开发者文档,目前临时二维码可以支持30天了)话说,腾讯也真是闲的蛋疼,专属二维码还分什么临时二维码和永久二维码,依稀记得,微信刚推出的时候,临时二维码只有N小时,后来感觉满足不了客户的需求,增加为7天,再后来,就是现在,支持30天!你们说说,腾讯这不是闲着蛋疼吗?直接给个永久的不就行了吗?
说到上述话题,我抱怨了腾讯,其实就该好好喷喷腾讯制作的开发文档,到处是坑,到处忽悠。如果你不幸成为了一名微信开发者,那么至少你会有一段时间头疼。不说别的,在这儿我就想喷微信的客服系统。微信刚开始的客服系统是多客服系统,就是那种CS的软件,类似于QQ,需要在线安装的,说实在的,这个多客服用着那不是一般的爽,不是一般的方便,你可以在PC上使用,也可以绑定在手机上使用,方便极了。后来腾讯360度大转弯,说什么运营成本高,不堪重负之类的话,硬生生的改成了现如今鸡肋般的网页版客服系统,那个体验性能不是一般的差啊,所以,我想代表广大客户及开发者对腾讯说句脏话:RNMB,能不能稳定点?能不能全心全意为客户,开发者服务?
话说多了,腾讯做的差,你可以不用啊。哎,小胳膊拧不过大腿,咱还是得老老实实的用,我还是得老老实实的讲解这种海报的生成!
首先分析下这个海报:
1、首先你得有个模板图片<这个模板图片留出两处空白,供二维码和头像占用>
2、微信带参数二维码的生成
3、粉丝头像的获取及下载
以上就是合成所需的基本图片
4、C#图片合成
5、上传合成的图片至服务器并获取MediaID
6、根据MediaID,将图片发送给粉丝
上述便是生成这张海报所需的资源及知识点,咱一步一步来哈
1、首先,模板图片,找公司PS高手,做一个就行
2、微信带参数二维码的生成(我提供的方法是直接粘贴的,不能直接用,有需要的,可以以打赏的模式,我发给你源码)
#region 获取用于换取二维码的Ticket /// <summary> /// 获取用于换取二维码(临时二维码和长久二维码)的Ticket /// </summary> /// <param name="senceId">场景值ID</param> /// <param name="type">值为:long 时:代表长久性二维码 值为short时:代表临时二维码</param> /// <returns></returns> public static string GeterweimaTicket(int senceId, string type = "short") { string Ticket = ""; CreateQrCodeResult re = new CreateQrCodeResult(); try { if (type == "short")//临时二维码 { re = QrCodeApi.Create(IsExistAccess_Token2(), 604800, senceId); } else { re = QrCodeApi.Create(IsExistAccess_Token2(), 0, senceId); } Ticket = re.ticket; } catch { if (type == "short")//临时二维码 { Ticket = CreateTicket(IsExistAccess_Token2()); } else { Ticket = CreateLongTicket(IsExistAccess_Token2()); } } return Ticket; } #region 原方法 /// <summary> /// 创建二维码ticket 临时二维码 /// </summary> /// <returns></returns> public static string CreateTicket(string TOKEN) { string result = ""; string strJson = @"{""expire_seconds"": 604800, ""action_name"": ""QR_SCENE"", ""action_info"": {""scene"": {""scene_id"": 321}}}"; string wxurl = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + TOKEN + ""; result = GetPage(wxurl, strJson); result = GetJsonValue(result, "ticket");//获取票据 ////LogHelper.WriteLog(result); return result; } /// <summary> /// 获取永久二维码Ticket /// </summary> /// <param name="TOKEN"></param> /// <returns></returns> public static string CreateLongTicket(string TOKEN) { string result = ""; string strJson = @"{""action_name"": ""QR_LIMIT_SCENE"", ""action_info"": {""scene"": {""scene_id"": 123}}}"; string wxurl = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + TOKEN + ""; result = GetPage(wxurl, strJson); result = GetJsonValue(result, "ticket");//获取票据 ////LogHelper.WriteLog(result); return result; } //{"ticket":"gQFw8DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL3pFZ3lETjdsMVNDcy1DRW9PMmE3AAIEP1TcVAMECAcAAA==","expire_seconds":1800,"url":"http:\/\/weixin.qq.com\/q\/zEgyDN7l1SCs-CEoO2a7"} /// <summary> /// 通过ticket换取二维码 /// </summary> /// <param name="TICKET">票据</param> /// <param name="openId">二维码依照openId 命名</param> /// <param name="Pth">相对路径 @"\weixin\HuLu\erweima2"</param> /// <returns>下载二维码成功后的物理路径:D:\XXXXXX.com\kkk\erweima2\201503031044566511190.jpg</returns> public static string GetTicketImage(string TICKET, string openId, string Pth) { string content = string.Empty; string strpath = string.Empty;//生成的URL 也就是 关注的URL string savepath = string.Empty;//图片保存的路径 string stUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + HttpContext.Current.Server.UrlEncode(TICKET); HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(stUrl); req.Method = "GET"; using (WebResponse wr = req.GetResponse()) { HttpWebResponse myResponse = (HttpWebResponse)req.GetResponse(); strpath = myResponse.ResponseUri.ToString(); WebClient mywebclient = new WebClient(); // @" savepath = HttpContext.Current.Server.MapPath(Pth) + "\\" + openId + "." + myResponse.ContentType.Split('/')[1].ToString(); // //LogHelper.WriteLog(savepath); try { mywebclient.DownloadFile(strpath, savepath);//下载生成的二维码图片 } catch (Exception ex) { savepath = ex.ToString(); LogHelper.WriteLog("错误了" + savepath); } } //LogHelper.WriteLog(savepath.ToString() + "都给我滚!"); return savepath.ToString(); } #endregion #endregion
3、获取用户头像并下载:
#region 获取用户的详细信息 /// <summary> /// 获取用户的详细信息 /// </summary> /// <param name="REFRESH_TOKEN">Token</param> /// <param name="OPENID">用户的OpenId</param> /// <returns>str</returns> public static Dictionary<string, object> Get_UserInfo(string REFRESH_TOKEN, string OPENID) { // Response.Write("获得用户信息REFRESH_TOKEN:" + REFRESH_TOKEN + "||OPENID:" + OPENID); string UserInfo = GetJson("https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + REFRESH_TOKEN + "&openid=" + OPENID); Dictionary<string, Object> obj2 = JsonConvert.DeserializeObject<Dictionary<string, Object>>(UserInfo); return obj2; } protected static string GetJson(string url) { WebClient wc = new WebClient(); wc.Credentials = CredentialCache.DefaultCredentials; wc.Encoding = Encoding.UTF8; string returnText = wc.DownloadString(url); if (returnText.Contains("errcode")) { //可能发生错误 } //Response.Write(returnText); return returnText; } #endregion
用户信息用有个HeardImage 就是粉丝的头像路径,然后根据这个路径,我们把它下载下来!
public class HttpDownLoad { private long fileLength; private long downLength;//已经下载文件大小,外面想用就改成公共属性 private static bool stopDown; public HttpDownLoad() { fileLength = 0; downLength = 0; stopDown = false; // // TODO: 在此处添加构造函数逻辑 // } /// <summary> /// 文件下载 /// </summary> /// <param name="url">连接</param> /// <param name="fileName">本地保存文件名</param> public void httpDownFile(string url, string fileName) { stopDown = false; Stream str = null, fs = null; try { //获取下载文件长度 fileLength = getDownLength(url); downLength = 0; if (fileLength > 0) { WebClient DownFile = new WebClient(); str = DownFile.OpenRead(url); //判断并建立文件 if (createFile(fileName)) { byte[] mbyte = new byte[1024]; int readL = str.Read(mbyte, 0, 1024); fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write); //读取流 while (readL != 0) { if (stopDown) break; downLength += readL;//已经下载大小 fs.Write(mbyte, 0, readL);//写文件 readL = str.Read(mbyte, 0, 1024);//读流 //progressBar.Value = (int)(downLength * 100 / fileLength); //label.Text = progressBar.Value.ToString() + "%"; //System.Windows.Forms.Application.DoEvents(); } str.Close(); fs.Close(); } } } catch (Exception ex) { if (str != null) str.Close(); if (fs != null) fs.Close(); } } /// <summary> /// 文件下载 /// </summary> /// <param name="url">连接</param> /// <param name="fileName">本地保存文件名</param> public void httpDownFile2(string url, string fileName) { try { WebClient DownFile = new WebClient(); DownFile.DownloadFile(url, fileName); } catch (Exception ex) { throw ex; } } /// <summary> /// 获取下载文件大小 /// </summary> /// <param name="url">连接</param> /// <returns>文件长度</returns> private long getDownLength(string url) { try { WebRequest wrq = WebRequest.Create(url); WebResponse wrp = (WebResponse)wrq.GetResponse(); wrp.Close(); return wrp.ContentLength; } catch (Exception ex) { return 0; throw ex; } } /// <summary> /// 建立文件(文件如已经存在,删除重建) /// </summary> /// <param name="fileName">文件全名(包括保存目录)</param> /// <returns></returns> private bool createFile(string fileName) { try { if (File.Exists(fileName)) { File.Delete(fileName); } Stream s = File.Create(fileName); s.Close(); return true; } catch (Exception ex) { return false; throw ex; } } public void downClose() { stopDown = true; } }
调用LoadDowmFile()即可
此时:二维码和头像都生成了,我们就可以调用图片合成的方法了<注意:此处需要二次图片合成,第一次是模板和二维码合成,第二次是把得到的新图片和头像再做一次合成>
#region C#图片处理 合并图片 /// <summary> /// 调用此函数后使此两种图片合并,类似相册,有个 /// 背景图,中间贴自己的目标图片 /// </summary> /// <param name="sourceImg">粘贴的源图片</param> /// <param name="destImg">粘贴的目标图片</param> /// 使用说明: string pic1Path = Server.MapPath(@"\testImg\wf.png"); /// 使用说明: string pic2Path = Server.MapPath(@"\testImg\yj.png"); /// 使用说明: System.Drawing.Image img = CombinImage(pic1Path, pic2Path); /// 使用说明:img.Save(Server.MapPath(@"\testImg\Newwf.png")); public static System.Drawing.Image CombinImage(string sourceImg, string destImg) { System.Drawing.Image imgBack = System.Drawing.Image.FromFile(sourceImg); //相框图片 System.Drawing.Image img = System.Drawing.Image.FromFile(destImg); //照片图片 //从指定的System.Drawing.Image创建新的System.Drawing.Graphics Graphics g = Graphics.FromImage(imgBack); g.DrawImage(imgBack, 0, 0, 148, 124); // g.DrawImage(imgBack, 0, 0, 相框宽, 相框高); g.FillRectangle(System.Drawing.Brushes.Black, 16, 16, (int)112 + 2, ((int)73 + 2));//相片四周刷一层黑色边框 //g.DrawImage(img, 照片与相框的左边距, 照片与相框的上边距, 照片宽, 照片高); g.DrawImage(img, 17, 17, 112, 73); GC.Collect(); return imgBack; } #endregion
最后就是上传至服务器并获取MediaId和发送给粉丝了,这一块相信大家都比较熟悉,不作多的解释!
还有一些个人总结的好方法,也是公共的方法,贴给大家:
#region XML KEY /// <summary> /// XML KEY 通用方法 /// </summary> /// <returns></returns> public static string GetXMLstrByKey(string Key, XmlDocument xml) { object strValue = xml.SelectSingleNode("xml").SelectSingleNode(Key).InnerText; if (strValue != null) { return strValue.ToString(); } else { return ""; } } #endregion
#region 获取接收事件推送的XML结构 /// <summary> /// 获取接收事件推送的XML结构 /// </summary> /// <returns></returns> public static XmlDocument GetMsgXML() { Stream stream = HttpContext.Current.Request.InputStream; byte[] byteArray = new byte[stream.Length]; stream.Read(byteArray, 0, (int)stream.Length); string postXmlStr = System.Text.Encoding.UTF8.GetString(byteArray); XmlDocument xmldoc = new XmlDocument(); xmldoc.LoadXml(postXmlStr); return xmldoc; } #endregion #region 发送客服消息 //1 发送文本消息 //2 发送图片消息 //3 发送语音消息 //4 发送视频消息 //5 发送音乐消息 //6 发送图文消息 /// <summary> /// 发送客服消息 /// </summary> /// <param name="posturl">请求的URL</param> /// <param name="postData">发送的数据 Json格式</param> /// <returns>json格式的字符串 通过获取Key为:errcode的值,判断accessToken是否过期,如果返回值为:40001 则accessToken无效,需要重新获取。实例代码:请参考WX_SendNews类</returns> public static string GetPage(string posturl, string postData) { //WX_SendNews news = new WX_SendNews(); //posturl: news.Posturl; //postData:news.PostData; System.IO.Stream outstream = null; Stream instream = null; StreamReader sr = null; HttpWebResponse response = null; HttpWebRequest request = null; Encoding encoding = Encoding.UTF8; byte[] data = encoding.GetBytes(postData); // 准备请求... try { // 设置参数 request = WebRequest.Create(posturl) as HttpWebRequest; CookieContainer cookieContainer = new CookieContainer(); request.CookieContainer = cookieContainer; request.AllowAutoRedirect = true; request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = data.Length; outstream = request.GetRequestStream(); outstream.Write(data, 0, data.Length); outstream.Close(); //发送请求并获取相应回应数据 response = request.GetResponse() as HttpWebResponse; //直到request.GetResponse()程序才开始向目标网页发送Post请求 instream = response.GetResponseStream(); sr = new StreamReader(instream, encoding); //返回结果网页(html)代码 string content = sr.ReadToEnd(); string err = string.Empty; return content; } catch (Exception ex) { string err = ex.Message; return string.Empty; } } #endregion #region 获取Json字符串某节点的值 /// <summary> /// 获取Json字符串某节点的值 /// </summary> public static string GetJsonValue(string jsonStr, string key) { string result = string.Empty; if (!string.IsNullOrEmpty(jsonStr)) { key = "\"" + key.Trim('"') + "\""; int index = jsonStr.IndexOf(key) + key.Length + 1; if (index > key.Length + 1) { //先截逗号,若是最后一个,截“}”号,取最小值 int end = jsonStr.IndexOf(',', index); if (end == -1) { end = jsonStr.IndexOf('}', index); } result = jsonStr.Substring(index, end - index); result = result.Trim(new char[] { '"', ' ', '\'' }); //过滤引号或空格 } } return result; } #endregion
好啦,就是这么多,如果需要制作海报的具体方法,请加我微信:18137070152(给点打赏哦) 注明为什么加我哦
@陈卧龙的博客