一.前言

为了保证用户不受到骚扰,在开发者出现需要主动提醒、通知用户时,才允许开发者在公众平台网站中模板消息库中选择模板,选择后获得模板ID,再根据模板 ID向用户主动推送提醒、通知消息。这个意思也就是,我们作为微信商户,不能主动的给用户推送消息,如果这个功能完全开放,那么用户有可能会受到大量的垃 圾信息,为了做一个很好的控制,微信那边给我们开放了一个模板消息,通过模板消息我们可以友好的给用户发送一些相关的消息提醒。

二.开发前的准备

1.0模板消息官方文档地址

2.0查看我们的模板消息是否申请成功。申请成功后你可以看到如下图片:

三.开始编码

一般我们在客户支付成功订单以后,会有一个支付的跳转页面,在我们前面的代码中也有相应的页面,代码如下:

<script type="text/javascript">

               //调用微信JS api 支付
function jsApiCall()
{
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
<%=wxJsApiParam%>,//josn串
function (res)
{
if (res.err_msg == "get_brand_wcpay_request:ok")
{
var OrderId=$("#OrderId").val();
var orderProductName=$("#orderProductName").val();
var orderMoneySum=$("#orderMoneySum").val(); window.location.href="http://www.baidu.com/PaySkip.aspx?OrderId="+OrderId+"&orderMoneySum="+orderMoneySum+"&orderProductName="+orderProductName;//支付成功后的跳转页面 }else
{
WeixinJSBridge.call('closeWindow');
} }
);
} function callpay()
{
if (typeof WeixinJSBridge == "undefined")
{
if (document.addEventListener)
{
document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
}
else if (document.attachEvent)
{
document.attachEvent('WeixinJSBridgeReady', jsApiCall);
document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
}
}
else
{
jsApiCall();
}
} </script>

在上一篇,微信支付成功后,我们有这样一个支付跳转页面,在这个支付跳转页面里,我们可以写一些我们自己的业务逻辑,比如我们今天的主角,模板消息提醒:直接上代码

 protected void Page_Load(object sender, EventArgs e)
{
//Session["openid"] = "o3XP9joyPbSxbtP30jFWRZZ3x5TU";
string appid = "wx45d851b036cefeb1";
string secret = "bb0fed9b39313fd1bea3c8d425a06c6f";
if (!IsPostBack)
{
string openid = Session["openid"] as string;
string accessToken = Session["access_token"] as string;
string url = Uri.EscapeDataString("http://m.gwbnsh.net.cn/temp/Default.aspx");//你的页面地址
var data = new
{
first = new
{
value = "尊敬的客户,您的宽带已申请成功",
color = "#173177"
},
keyword1 = new
{
value = "李伟峰",
color = "#173177"
},
keyword2 = new
{
value = "",
color = "#173177"
},
keyword3 = new
{
value = "宽带新装申请",
color = "#173177"
},
remark = new
{
value = "安装人员即将上门为您安装!请注意妥善保管宽带上网账号。",
color = "#173177"
}, };
//string appid = "wx45d851b036cefeb1";
//string secret = "bb0fed9b39313fd1bea3c8d425a06c6f";
//string url = Uri.EscapeDataString("http://m.gwbnsh.net.cn/newapply/Apply_S3.aspx");//你的页面地址
//string openid = System.Web.HttpContext.Current.Session["openid"] != null ? System.Web.HttpContext.Current.Session["openid"].ToString() : "";
if (string.IsNullOrEmpty(openid))
{
string code = Request.Params["code"] as string;
if (string.IsNullOrEmpty(code))
{
Response.Redirect("https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx45d851b036cefeb1&redirect_uri=" + url + "&response_type=code&scope=snsapi_base&state=Gwbnsh#wechat_redirect");
Response.End();
}
else
{
var newUrl = string.Format("https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code", appid, secret, code);
var client = new System.Net.WebClient();
client.Encoding = System.Text.Encoding.UTF8;
var dataUser = client.DownloadString(newUrl);
var serializer = new JavaScriptSerializer();
var obj = serializer.Deserialize<Dictionary<string, string>>(dataUser);
openid = obj["openid"];
}
}
Session["openid"] = openid;//微信OpenID
string templateId = "hN2SK3Ca0aLwIR5o6okdvLMYgeOZpxGiYtWi5JJiwhM";
if (!string.IsNullOrEmpty(openid))
{
SendTemplate(openid, "_S8B_hJXRYY3sy9_6a2tHeISTc0SyWgcAl9NPGwhW3_2yqKKf6uPYSkbSD7fOKY3lHV2zF35NyuyQRVGBrKPkuHcoEx_jOYs3m5_KDtGcIN1vk6OPINv5vfQ1dgSPSP4MRJcCFAINF", templateId, data, "");
}
}
}
/// <summary>
/// 给指定的用户发送模板消息
/// </summary>
/// <param name="openId">用户标识openid</param>
/// <param name="templateId">对应的模板id</param>
/// <param name="data">对应模板的参数</param>
/// <param name="url">点击对应消息弹出的地址</param>
/// <returns>返回json数据包</returns>
public string SendTemplate(string openId, string token, string templateId, object data, string url)
{
JavaScriptSerializer Jss = new JavaScriptSerializer();
var msgData = new
{
touser = openId,
template_id = templateId,
url = url,
data = data
};
string postData = Jss.Serialize(msgData);
return Post("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + token, postData);
}
//Post数据到指定Url,并返回String类型
public string Post(string Url, string Data)
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Url);
byte[] requestBytes = System.Text.Encoding.UTF8.GetBytes(Data);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = requestBytes.Length;
Stream requestStream = req.GetRequestStream();
requestStream.Write(requestBytes, , requestBytes.Length);
requestStream.Close(); HttpWebResponse res = (HttpWebResponse)req.GetResponse();
System.IO.StreamReader sr = new System.IO.StreamReader(res.GetResponseStream(), System.Text.Encoding.UTF8);
string PostJie = sr.ReadToEnd();
sr.Close();
res.Close();
return PostJie;
}

从上面的代码中我们可以看到TemplateMessage.Send()这个方法是我们发送消息的关键,我们来看看这个方法是怎样的:

        #region 发送模板消息
/// <summary>
/// 发送模板消息
/// </summary>
/// <param name="userName">公众号</param>
/// <param name="touser">接收消息的账号</param>
/// <param name="templateId">模板id</param>
/// <param name="detailUrl">详情地址</param>
/// <param name="topColor">顶端颜色</param>
/// <param name="data">数据</param>
/// <param name="errorMessage">返回发送是否成功</param>
/// <returns>返回消息id;如果发送失败,返回-1。</returns>
public static long Send(string userName, string touser, string templateId, string detailUrl, Color topColor,
Tuple<string, string, Color>[] data, out ErrorMessage errorMessage)
{
errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "");
long id = -1;
//校验参数
if (string.IsNullOrWhiteSpace(touser))
{
errorMessage.errmsg = "接收消息的账号不能为空。";
return id;
}
if (string.IsNullOrWhiteSpace(templateId))
{
errorMessage.errmsg = "模板id不能为空。";
return id;
}
if (data == null || data.Length == 0)
{
errorMessage.errmsg = "模板数据不能为空。";
return id;
}
foreach (Tuple<string, string, Color> item in data)
{
if (string.IsNullOrWhiteSpace(item.Item1) || string.IsNullOrWhiteSpace(item.Item2))
{
errorMessage.errmsg = "模板数据不能为空。";
return id;
}
}
//获取许可令牌
AccessToken token = AccessToken.Get(userName);
if (token == null)
{
errorMessage.errmsg = "获取许可令牌失败。";
return id;
}
string url = string.Format(urlForSending, token.access_token);
//生成待发送的数据
dynamic postData = new ExpandoObject();
postData.touser = touser;
postData.template_id = templateId;
postData.url = detailUrl ?? string.Empty;
postData.topcolor = Utility.GetColorString(topColor);
postData.data = new ExpandoObject();
IDictionary<string, object> dataDict = (IDictionary<string, object>)postData.data;
foreach (Tuple<string, string, Color> item in data)
{
dataDict.Add(item.Item1, new { value = item.Item2, color = Utility.GetColorString(item.Item3) });
}
string json = JsonConvert.SerializeObject(postData);
//发送数据
string responseContent;
if (!HttpHelper.Request(url, out responseContent, httpMethod, json))
{
errorMessage.errmsg = "提交数据到微信服务器失败。";
return id;
}
//解析结果
JObject jo = JObject.Parse(responseContent);
JToken jt;
if (jo.TryGetValue("errcode", out jt) && jo.TryGetValue("errmsg", out jt))
{
errorMessage.errcode = (int)jo["errcode"];
errorMessage.errmsg = (string)jo["errmsg"];
if (jo.TryGetValue("msgid", out jt))
id = (long)jt;
}
else
errorMessage.errmsg = "解析返回结果失败。";
return id;
}
#endregion
 AccessToken token = AccessToken.Get(userName);获取许可令牌上一篇文章中我们已经说过这个类,这里就不多说了,HttpHelper帮助类的代码如下:
   /// <summary>
/// HttpHelper:http请求与响应辅助类
/// </summary>
public static class HttpHelper
{
/// <summary>
/// 向微信服务器发送请求时的编码
/// </summary>
public static readonly Encoding RequestEncoding = Encoding.UTF8;
/// <summary>
/// 微信服务器响应的编码
/// </summary>
public static readonly Encoding ResponseEncoding = Encoding.UTF8; /// <summary>
/// 向微信服务器提交数据,并获取微信服务器响应的数据
/// </summary>
/// <param name="url">服务器地址</param>
/// <param name="responseData">返回响应数据</param>
/// /// <param name="httpMethod">http方法</param>
/// <param name="data">数据</param>
/// <returns>返回是否提交成功</returns>
public static bool Request(string url, out byte[] responseData,
string httpMethod = WebRequestMethods.Http.Get, byte[] data = null)
{
bool success = false;
responseData = null;
Stream requestStream = null;
HttpWebResponse response = null;
Stream responseStream = null;
MemoryStream ms = null;
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = httpMethod;
if (data != null && data.Length > )
{
request.ContentLength = data.Length;
requestStream = request.GetRequestStream();
requestStream.Write(data, , data.Length);
}
response = (HttpWebResponse)request.GetResponse();
//由于微信服务器的响应有时没有正确设置ContentLength,这里不检查ContentLength
//if (response.ContentLength > 0)
{
ms = new MemoryStream();
responseStream = response.GetResponseStream();
int bufferLength = ;
byte[] buffer = new byte[bufferLength];
int size = responseStream.Read(buffer, , bufferLength);
while (size > )
{
ms.Write(buffer, , size);
size = responseStream.Read(buffer, , bufferLength);
}
responseData = ms.ToArray();
}
success = true;
}
finally
{
if (requestStream != null)
requestStream.Close();
if (responseStream != null)
responseStream.Close();
if (ms != null)
ms.Close();
if (response != null)
response.Close();
}
return success;
} /// <summary>
/// 向微信服务器提交数据,并获取微信服务器响应的数据
/// </summary>
/// <param name="url">服务器地址</param>
/// <param name="responseData">返回响应数据</param>
/// /// <param name="httpMethod">http方法</param>
/// <param name="data">数据</param>
/// <returns>返回是否提交成功</returns>
public static bool Request(string url, out byte[] responseData,
string httpMethod = WebRequestMethods.Http.Get, string data = null)
{
byte[] bytes = string.IsNullOrEmpty(data) ? null : RequestEncoding.GetBytes(data);
return Request(url, out responseData, httpMethod, (byte[])bytes);
} /// <summary>
/// 向微信服务器提交数据,并获取微信服务器响应的内容
/// </summary>
/// <param name="url">服务器地址</param>
/// <param name="responseContent">返回响应内容</param>
/// /// <param name="httpMethod">http方法</param>
/// <param name="data">数据</param>
/// <returns>返回是否提交成功</returns>
public static bool Request(string url, out string responseContent,
string httpMethod = WebRequestMethods.Http.Get, byte[] data = null)
{
byte[] responseData;
responseContent = string.Empty;
bool success = Request(url, out responseData, httpMethod, data);
if (success && responseData != null && responseData.Length > )
responseContent = ResponseEncoding.GetString(responseData);
return success;
} /// <summary>
/// 向微信服务器提交数据,并获取微信服务器响应的内容
/// </summary>
/// <param name="url">服务器地址</param>
/// <param name="responseContent">返回响应内容</param>
/// /// <param name="httpMethod">http方法</param>
/// <param name="data">数据</param>
/// <returns>返回是否提交成功</returns>
public static bool Request(string url, out string responseContent,
string httpMethod = WebRequestMethods.Http.Get, string data = null)
{
byte[] bytes = string.IsNullOrEmpty(data) ? null : RequestEncoding.GetBytes(data);
return Request(url, out responseContent, httpMethod, (byte[])bytes);
} /// <summary>
/// 向微信服务器提交数据
/// </summary>
/// <param name="url">服务器地址</param>
/// /// <param name="httpMethod">http方法</param>
/// <param name="data">数据</param>
/// <returns>返回是否提交成功</returns>
public static bool Request(string url, string httpMethod = WebRequestMethods.Http.Get, byte[] data = null)
{
bool success = false;
Stream requestStream = null;
HttpWebResponse response = null;
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = httpMethod;
if (data != null && data.Length > )
{
request.ContentLength = data.Length;
requestStream = request.GetRequestStream();
requestStream.Write(data, , data.Length);
}
response = (HttpWebResponse)request.GetResponse();
success = true;
}
finally
{
if (requestStream != null)
requestStream.Close();
if (response != null)
response.Close();
}
return success;
} /// <summary>
/// 组合url,发送数据,然后返回响应字符串
/// </summary>
/// <param name="urlFormat">url格式字符串,第一个参数为userName获取到的许可令牌,然后依次为parameters中的参数</param>
/// <param name="userName">公众号</param>
/// <param name="urlParameters">参数</param>
/// <param name="httpMethod">执行请求的http方法</param>
/// <param name="data">请求的内容</param>
/// <returns>返回响应内容;如果请求失败,或者发生错误,返回空字符串</returns>
public static string RequestResponseContent(string urlFormat, string userName, IEnumerable<object> urlParameters = null, string httpMethod = WebRequestMethods.Http.Get, string data = null)
{
string responseContent = string.Empty;
AccessToken token = AccessToken.Get(userName);
if (token == null)
return responseContent;
string url;
if (urlParameters == null)
url = string.Format(urlFormat, token.access_token);
else
{
List<object> paramList = new List<object>(urlParameters);
paramList.Insert(, token.access_token);
url = string.Format(urlFormat, paramList.ToArray());
}
HttpHelper.Request(url, out responseContent, httpMethod, (string)data);
return responseContent;
} /// <summary>
/// 组合url,发送数据,然后返回响应的错误消息。
/// 注:错误消息不一定代表失败或者错误。
/// </summary>
/// <param name="urlFormat">url格式字符串,第一个参数为userName获取到的许可令牌,然后依次为parameters中的参数</param>
/// <param name="userName">公众号</param>
/// <param name="urlParameters">参数</param>
/// <param name="httpMethod">执行请求的http方法</param>
/// <param name="data">请求的内容</param>
/// <returns>返回响应的错误消息</returns>
public static ErrorMessage RequestErrorMessage(string urlFormat, string userName, IEnumerable<object> urlParameters = null, string httpMethod = WebRequestMethods.Http.Get, string data = null)
{
string responseContent = RequestResponseContent(urlFormat, userName, urlParameters, httpMethod, data);
if (string.IsNullOrWhiteSpace(responseContent))
return new ErrorMessage(ErrorMessage.ExceptionCode, "请求失败。");
else if (ErrorMessage.IsErrorMessage(responseContent))
return ErrorMessage.Parse(responseContent);
else
return new ErrorMessage(ErrorMessage.ExceptionCode, "解析响应失败。");
} /// <summary>
/// 组合url,发送数据,然后返回结果。
/// 注:结果为需要解析的类。
/// </summary>
/// <typeparam name="T">返回结果的类型</typeparam>
/// <param name="urlFormat">url格式字符串,第一个参数为userName获取到的许可令牌,然后依次为parameters中的参数</param>
/// <param name="userName">公众号</param>
/// <param name="errorMessage">返回请求是否成功</param>
/// <param name="urlParameters">参数</param>
/// <param name="httpMethod">执行请求的http方法</param>
/// <param name="data">请求的内容</param>
/// <returns>返回结果;如果请求失败,或者发生错误,返回null。</returns>
public static T RequestParsableResult<T>(string urlFormat, string userName, out ErrorMessage errorMessage, IEnumerable<object> urlParameters = null, string httpMethod = WebRequestMethods.Http.Get, string data = null)
where T : IParsable, new()
{
T result = default(T);
errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "请求失败。");
string responseContent = RequestResponseContent(urlFormat, userName, urlParameters, httpMethod, data);
if (string.IsNullOrWhiteSpace(responseContent))
return result;
if (ErrorMessage.IsErrorMessage(responseContent))
errorMessage = ErrorMessage.Parse(responseContent);
else
{
try
{
result = Utility.Parse<T>(responseContent);
if (result != null)
errorMessage = new ErrorMessage(ErrorMessage.SuccessCode, "请求成功。");
else
errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "解析失败。");
}
catch
{
errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "解析失败。");
}
}
return result;
} /// <summary>
/// 组合url,发送数据,然后返回结果。
/// 注:结果为已知的简单值类型。
/// </summary>
/// <typeparam name="T">返回结果的类型</typeparam>
/// <param name="urlFormat">url格式字符串,第一个参数为userName获取到的许可令牌,然后依次为parameters中的参数</param>
/// <param name="userName">公众号</param>
/// <param name="propertyNameInJson">返回结果在json中的键名</param>
/// <param name="errorMessage">返回请求是否成功</param>
/// <param name="urlParameters">参数</param>
/// <param name="httpMethod">执行请求的http方法</param>
/// <param name="data">请求的内容</param>
/// <returns>返回结果;如果请求失败,或者发生错误,返回default(T)。</returns>
public static T RequestValueTypeResult<T>(string urlFormat, string userName, string propertyNameInJson, out ErrorMessage errorMessage, IEnumerable<object> urlParameters = null, string httpMethod = WebRequestMethods.Http.Get, string data = null)
where T : struct
{
errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "请求失败。");
string responseContent = RequestResponseContent(urlFormat, userName, urlParameters, httpMethod, data);
return ConvertValueTypeResult<T>(responseContent, propertyNameInJson, out errorMessage);
} /// <summary>
/// 获取值类型的结果
/// </summary>
/// <typeparam name="T">返回结果的类型</typeparam>
/// <param name="responseContent">响应内容</param>
/// <param name="propertyNameInJson">返回结果在json中的键名</param>
/// <param name="errorMessage">返回请求是否成功</param>
/// <returns>返回结果;如果请求失败,或者发生错误,返回default(T)。</returns>
private static T ConvertValueTypeResult<T>(string responseContent, string propertyNameInJson, out ErrorMessage errorMessage)
where T : struct
{
if (string.IsNullOrWhiteSpace(responseContent))
{
errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "请求失败。");
return default(T);
}
if (ErrorMessage.IsErrorMessage(responseContent))
errorMessage = ErrorMessage.Parse(responseContent);
else
errorMessage = new ErrorMessage(ErrorMessage.SuccessCode, "请求成功。");
JObject jo = JObject.Parse(responseContent);
JToken jt;
if (jo.TryGetValue(propertyNameInJson, out jt))
return ConvertValueTypeResult<T>((string)jt);
else
return default(T);
} /// <summary>
/// 获取值类型的结果
/// </summary>
/// <typeparam name="T">返回结果的类型</typeparam>
/// <param name="responseContent">响应内容</param>
/// <param name="propertyNameInJson">返回结果在json中的键名</param>
/// <param name="errorMessage">返回请求是否成功</param>
/// <returns>返回结果;如果请求失败,或者发生错误,返回default(T)。</returns>
private static T ConvertValueTypeResult<T>(string value)
where T : struct
{
Type type = typeof(T);
if (type.IsEnum)
return (T)Enum.Parse(type, value);
else if (type == typeof(sbyte))
return (T)(object)Convert.ToSByte(value);
else if (type == typeof(byte))
return (T)(object)Convert.ToByte(value);
else if (type == typeof(char))
return (T)(object)Convert.ToChar(value);
else if (type == typeof(short))
return (T)(object)Convert.ToInt16(value);
else if (type == typeof(ushort))
return (T)(object)Convert.ToUInt16(value);
else if (type == typeof(int))
return (T)(object)Convert.ToInt32(value);
else if (type == typeof(uint))
return (T)(object)Convert.ToUInt32(value);
else if (type == typeof(long))
return (T)(object)Convert.ToInt64(value);
else if (type == typeof(ulong))
return (T)(object)Convert.ToUInt64(value);
else if (type == typeof(float))
return (T)(object)Convert.ToSingle(value);
else if (type == typeof(double))
return (T)(object)Convert.ToDouble(value);
else if (type == typeof(decimal))
return (T)(object)Convert.ToDecimal(value);
else if (type == typeof(bool))
return (T)(object)Convert.ToBoolean(value);
else
throw new ArgumentException("不支持的值类型。");
} /// <summary>
/// 向微信服务器提交数据
/// </summary>
/// <param name="url">服务器地址</param>
/// /// <param name="httpMethod">http方法</param>
/// <param name="data">数据</param>
/// <returns>返回是否提交成功</returns>
public static bool Request(string url, string httpMethod = WebRequestMethods.Http.Get, string data = null)
{
byte[] bytes = string.IsNullOrEmpty(data) ? null : RequestEncoding.GetBytes(data);
return Request(url, httpMethod, (byte[])bytes);
} /// <summary>
/// 上传文件
/// </summary>
/// <param name="url">服务器地址</param>
/// <param name="filename">文件名(不包含路径)</param>
/// <param name="fileData">文件数据</param>
/// <param name="formData">表单数据</param>
/// <returns>返回服务器的响应字符串</returns>
public static string Upload(string url, string filename, byte[] fileData, NameValueCollection formData = null)
{
string responseContent = string.Empty;
if (string.IsNullOrWhiteSpace(url) || string.IsNullOrWhiteSpace(filename) || fileData == null || fileData.Length == )
return responseContent;
// 边界符
string boundary = "AaB03xAaB03x";
// 开始边界符
byte[] beginBoundary = Encoding.ASCII.GetBytes("--" + boundary + "\r\n");
// 结束符
byte[] endBoundary = Encoding.ASCII.GetBytes("--" + boundary + "--\r\n");
//换行
byte[] newLine = Encoding.ASCII.GetBytes("\r\n");
MemoryStream ms = null;
Stream stream = null;
HttpWebResponse response = null;
StreamReader sr = null;
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = WebRequestMethods.Http.Post;
request.ContentType = "multipart/form-data; boundary=" + boundary;
// 写入文件
string header = string.Format("Content-Disposition: form-data; filename=\"{0}\"\r\n" +
"Content-Type: application/octet-stream\r\n\r\n",
filename);
byte[] headerbytes = Encoding.UTF8.GetBytes(header);
ms = new MemoryStream();
ms.Write(beginBoundary, , beginBoundary.Length);
ms.Write(headerbytes, , headerbytes.Length);
ms.Write(fileData, , fileData.Length);
// 写入表单数据
if (formData != null && formData.Count > )
{
var formItem = "\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\"" +
"\r\n\r\n{1}\r\n";
foreach (string key in formData.Keys)
{
string value = formData[key];
byte[] bytes = Encoding.UTF8.GetBytes(string.Format(formItem, key, value));
ms.Write(bytes, , bytes.Length);
}
}
//写入结束边界符
ms.Write(newLine, , newLine.Length);
ms.Write(endBoundary, , endBoundary.Length);
request.ContentLength = ms.Length;
stream = request.GetRequestStream();
stream.Write(ms.ToArray(), , (int)ms.Length);
//获取响应
response = (HttpWebResponse)request.GetResponse();
sr = new StreamReader(response.GetResponseStream(), HttpHelper.ResponseEncoding);
responseContent = sr.ReadToEnd();
}
finally
{
if (ms != null)
ms.Close();
if (stream != null)
stream.Close();
if (sr != null)
sr.Close();
if (response != null)
response.Close();
}
return responseContent;
} /// <summary>
/// 上传文件
/// </summary>
/// <param name="url">服务器地址</param>
/// <param name="pathname">包含路径的文件名</param>
/// <param name="formData">表单数据</param>
/// <returns>返回服务器的响应字符串</returns>
public static string Upload(string url, string pathname, NameValueCollection formData = null)
{
string filename = Path.GetFileName(pathname);
byte[] data = null;
FileStream fs = null;
MemoryStream ms = null;
try
{
fs = new FileStream(pathname, FileMode.Open, FileAccess.Read);
ms = new MemoryStream();
int bufferLength = ;
byte[] buffer = new byte[bufferLength];
int size = fs.Read(buffer, , bufferLength);
while (size > )
{
ms.Write(buffer, , size);
size = fs.Read(buffer, , bufferLength);
}
data = ms.ToArray();
}
finally
{
if (fs != null)
fs.Close();
if (ms != null)
ms.Close();
}
return Upload(url, filename, data, formData);
}
} 复制代码

四.最终效果如下:

.NET微信公众号开发-6.0模板消息的更多相关文章

  1. .NET微信公众号开发-1.0初始微信公众号

    一.前言 微信公众号是开发者或商家在微信公众平台上申请的应用账号,该帐号与QQ账号互通,通过公众号,商家可在微信平台上实现和特定群体的文字.图片.语音.视频的全方位沟通.互动 .形成了一 种主流的线上 ...

  2. .NET微信公众号开发-2.0创建自定义菜单

    一.前言 开发之前,我们需要阅读官方的接口说明文档,不得不吐槽一下,微信的这个官方文档真的很烂,但是,为了开发我们需要的功能,我们也不得不去看这些文档. 接口文档地址:http://mp.weixin ...

  3. .NET微信公众号开发-3.0查询自定义菜单

    一.前言 前面我们已经创建好了我们的自定义菜单.那么我们现在要如何查询我们自定义的菜单.原理都是一样的,而且都是相当简单,只是接口地址文档换掉了. 2.0开始编码 同样我们首先创建好我的查询页面,在这 ...

  4. .NET微信公众号开发-4.0公众号消息处理

    一.前言 微信公众平台的消息处理还是比较完善的,有最基本的文本消息,到图文消息,到图片消息,语音消息,视频消息,音乐消息其基本原理都是一样的,只不过所post的xml数据有所差别,在处理消息之前,我们 ...

  5. .NET微信公众号开发-5.0微信支付

    一.前言 在开始做这个功能之前,我们要做的第一件事情就是思考,如何做这个微信支付,从哪里开始,从哪里入手,官方的sdk说明什么的,有没有什么官方的demo,还有就是老板给我的一些资料齐全不,那些要申请 ...

  6. NET微信公众号开发-5.0微信支付(待测试)

    开发前准备. 1.0微信支付官方开发者文档 2.0官方demo下载 我们用c#所以选择.net版本 不过这个官方的demo根本跑步起来 3.0官方demo运行起来解决方案 4.0微信支付官方.net版 ...

  7. JAVA微信公众号通过openid发送模板消息~

    1,问题产生 在微信公众号开发过程中,我们有时候做不同权限的时候,比如在注册的时候,需要审核,然后我们要想办法让对方知道审核的结果.这时候我们可以通过模板消息来通知. 2,第一步,首先在微信公众号上获 ...

  8. Python webpy微信公众号开发之 回复图文消息

    新建图文回复模板reply_pictext.xml: $def with (toUser,fromUser,createTime,title1,description1,picurl1,url1)&l ...

  9. 微信公众号php从0开发,包括功能(自定义菜单,分享)

    之前写的一篇微信公众号文章. 工作需要,进行此次调研,并记录开发过程. 开发目的,页面授权,页面获取用户头像,用户昵称 微信id, 分享页面. 微信订阅号 无法获取用户个人信息 写在记录前,公众号也是 ...

随机推荐

  1. php大力力 [049节] php函数implode()

    implode()[1]  函数返回一个由数组元素组合成的字符串. 注释:implode() 函数接受两种参数顺序.但是由于历史原因,explode() 是不行的,您必须保证 separator 参数 ...

  2. difference between forward and sendredirect

    Difference between SendRedirect and forward is one of classical interview questions asked during jav ...

  3. 多线程知识点总结 -NSThread4

    NSThread 三种创建方式 NSThread的对象方法 - (void)threadDemo1 { NSLog(@"before %@", [NSThread currentT ...

  4. Android TextView设置多彩文字

    在应用开发中时常会遇到需要在一段文字中插入几个不一样颜色文字的需求; 以前本人都是用多个TextView拼起来,不仅感觉很蠢,操作起来也蛮恶心; 直到接触到了SpannableStringBuilde ...

  5. POJ 1637 混合图的欧拉回路判定

    题意:一张混合图,判断是否存在欧拉回路. 分析参考: 混合图(既有有向边又有无向边的图)中欧拉环.欧拉路径的判定需要借助网络流! (1)欧拉环的判定:一开始当然是判断原图的基图是否连通,若不连通则一定 ...

  6. codeforces 732D(二分)

    题目链接:http://codeforces.com/contest/732/problem/D 题意:有m门需要过的课程,n天的时间可以选择复习.考试(如果的d[i]为0则只能复习),一门课至少要复 ...

  7. A Simple Problem with Integers_树状数组

    Problem Description Let A1, A2, ... , AN be N elements. You need to deal with two kinds of operation ...

  8. javascript原始数据类型compareto引用数据类型--近3天不太会的地方

    ECMAScirpt 变量有两种不同的数据类型:基本类型,引用类型.也有其他的叫法,比如原始类型和对象类型,拥有方法的类型和不能拥有方法的类型,还可以分为可变类型和不可变类型,其实这些叫法都是依据这两 ...

  9. Professional.WebGL.Programming-Chapter 2(高级WebGL编程——第二章)

    (目前发现一些文章被盗用的情况,我们将在每篇文章前面添加原文地址,本文源地址:http://www.cnblogs.com/idealer3d/p/3508251.html) 这一章主要通过创建一个三 ...

  10. Spring Ioc代码阅读

    1,理解控制反转   以前一直说着这个词,然后把它等于上ioc这个词,再等于上代码里一个bean里依赖了其他bean,不用new,用注解,用xml去描述,就可以了.能用就行了,实际理论的不管也不影响编 ...