C# 微信海报

时间:2021-05-24 09:13:56

最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来。我们都知道计算机技术发展日新月异,速度惊人的快,你我稍不留神,就会被慢慢淘汰!因此:每日不间断的学习是避免被淘汰的不二法宝。

十年河东十年河西,莫欺少年穷。

最近微信开发依然是那么火,有人请我开发一个微信海报,拿到需求后,我瞬间笑了,这不就是两年前我学习微信的时候自己做的一个案例吗?能有什么技术含量?

当然,我有点自大了,所谓骄兵必败,咱还是来分析分析这个微信海报吧!

所谓微信海报就是一个图片,这个图片上有粉丝的专属二维码,有粉丝的头像及商户宣传的广告等。

我做的微信海报如下图:

C# 微信海报

看到吗?上边有我的专属二维码,不过这个二维码是临时的,我做的有效期是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(), , senceId);
}
else
{
re = QrCodeApi.Create(IsExistAccess_Token2(), , 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('/')[].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 = ;
downLength = ;
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 = ;
if (fileLength > )
{
WebClient DownFile = new WebClient();
str = DownFile.OpenRead(url);
//判断并建立文件
if (createFile(fileName))
{
byte[] mbyte = new byte[];
int readL = str.Read(mbyte, , );
fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write);
//读取流
while (readL != )
{
if (stopDown)
break;
downLength += readL;//已经下载大小
fs.Write(mbyte, , readL);//写文件
readL = str.Read(mbyte, , );//读流
//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 ;
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, , , , ); // g.DrawImage(imgBack, 0, 0, 相框宽, 相框高);
g.FillRectangle(System.Drawing.Brushes.Black, , , (int) + , ((int) + ));//相片四周刷一层黑色边框 //g.DrawImage(img, 照片与相框的左边距, 照片与相框的上边距, 照片宽, 照片高);
g.DrawImage(img, , , , );
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, , (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, , 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 + ;
if (index > key.Length + )
{
//先截逗号,若是最后一个,截“}”号,取最小值
int end = jsonStr.IndexOf(',', index);
if (end == -)
{
end = jsonStr.IndexOf('}', index);
} result = jsonStr.Substring(index, end - index);
result = result.Trim(new char[] { '"', ' ', '\'' }); //过滤引号或空格
}
}
return result;
}
#endregion

好啦,就是这么多,如果需要制作海报的具体方法,请加我微信:18137070152(给点打赏哦) 注明为什么加我哦

@陈卧龙的博客