一.前言

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

二.开发前的准备

1.0模板消息官方文档地址

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

三.开始编码

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

  1. <script type="text/javascript">
  2.  
  3. //调用微信JS api 支付
  4. function jsApiCall()
  5. {
  6. WeixinJSBridge.invoke(
  7. 'getBrandWCPayRequest',
  8. <%=wxJsApiParam%>,//josn串
  9. function (res)
  10. {
  11. if (res.err_msg == "get_brand_wcpay_request:ok")
  12. {
  13. var OrderId=$("#OrderId").val();
  14. var orderProductName=$("#orderProductName").val();
  15. var orderMoneySum=$("#orderMoneySum").val();
  16.  
  17. window.location.href="http://www.baidu.com/PaySkip.aspx?OrderId="+OrderId+"&orderMoneySum="+orderMoneySum+"&orderProductName="+orderProductName;//支付成功后的跳转页面
  18.  
  19. }else
  20. {
  21. WeixinJSBridge.call('closeWindow');
  22. }
  23.  
  24. }
  25. );
  26. }
  27.  
  28. function callpay()
  29. {
  30. if (typeof WeixinJSBridge == "undefined")
  31. {
  32. if (document.addEventListener)
  33. {
  34. document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
  35. }
  36. else if (document.attachEvent)
  37. {
  38. document.attachEvent('WeixinJSBridgeReady', jsApiCall);
  39. document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
  40. }
  41. }
  42. else
  43. {
  44. jsApiCall();
  45. }
  46. }
  47.  
  48. </script>

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

  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3. //Session["openid"] = "o3XP9joyPbSxbtP30jFWRZZ3x5TU";
  4. string appid = "wx45d851b036cefeb1";
  5. string secret = "bb0fed9b39313fd1bea3c8d425a06c6f";
  6. if (!IsPostBack)
  7. {
  8. string openid = Session["openid"] as string;
  9. string accessToken = Session["access_token"] as string;
  10. string url = Uri.EscapeDataString("http://m.gwbnsh.net.cn/temp/Default.aspx");//你的页面地址
  11. var data = new
  12. {
  13. first = new
  14. {
  15. value = "尊敬的客户,您的宽带已申请成功",
  16. color = "#173177"
  17. },
  18. keyword1 = new
  19. {
  20. value = "李伟峰",
  21. color = "#173177"
  22. },
  23. keyword2 = new
  24. {
  25. value = "",
  26. color = "#173177"
  27. },
  28. keyword3 = new
  29. {
  30. value = "宽带新装申请",
  31. color = "#173177"
  32. },
  33. remark = new
  34. {
  35. value = "安装人员即将上门为您安装!请注意妥善保管宽带上网账号。",
  36. color = "#173177"
  37. },
  38.  
  39. };
  40. //string appid = "wx45d851b036cefeb1";
  41. //string secret = "bb0fed9b39313fd1bea3c8d425a06c6f";
  42. //string url = Uri.EscapeDataString("http://m.gwbnsh.net.cn/newapply/Apply_S3.aspx");//你的页面地址
  43. //string openid = System.Web.HttpContext.Current.Session["openid"] != null ? System.Web.HttpContext.Current.Session["openid"].ToString() : "";
  44. if (string.IsNullOrEmpty(openid))
  45. {
  46. string code = Request.Params["code"] as string;
  47. if (string.IsNullOrEmpty(code))
  48. {
  49. 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");
  50. Response.End();
  51. }
  52. else
  53. {
  54. 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);
  55. var client = new System.Net.WebClient();
  56. client.Encoding = System.Text.Encoding.UTF8;
  57. var dataUser = client.DownloadString(newUrl);
  58. var serializer = new JavaScriptSerializer();
  59. var obj = serializer.Deserialize<Dictionary<string, string>>(dataUser);
  60. openid = obj["openid"];
  61. }
  62. }
  63. Session["openid"] = openid;//微信OpenID
  64. string templateId = "hN2SK3Ca0aLwIR5o6okdvLMYgeOZpxGiYtWi5JJiwhM";
  65. if (!string.IsNullOrEmpty(openid))
  66. {
  67. SendTemplate(openid, "_S8B_hJXRYY3sy9_6a2tHeISTc0SyWgcAl9NPGwhW3_2yqKKf6uPYSkbSD7fOKY3lHV2zF35NyuyQRVGBrKPkuHcoEx_jOYs3m5_KDtGcIN1vk6OPINv5vfQ1dgSPSP4MRJcCFAINF", templateId, data, "");
  68. }
  69. }
  70. }
  71. /// <summary>
  72. /// 给指定的用户发送模板消息
  73. /// </summary>
  74. /// <param name="openId">用户标识openid</param>
  75. /// <param name="templateId">对应的模板id</param>
  76. /// <param name="data">对应模板的参数</param>
  77. /// <param name="url">点击对应消息弹出的地址</param>
  78. /// <returns>返回json数据包</returns>
  79. public string SendTemplate(string openId, string token, string templateId, object data, string url)
  80. {
  81. JavaScriptSerializer Jss = new JavaScriptSerializer();
  82. var msgData = new
  83. {
  84. touser = openId,
  85. template_id = templateId,
  86. url = url,
  87. data = data
  88. };
  89. string postData = Jss.Serialize(msgData);
  90. return Post("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + token, postData);
  91. }
  92. //Post数据到指定Url,并返回String类型
  93. public string Post(string Url, string Data)
  94. {
  95. HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Url);
  96. byte[] requestBytes = System.Text.Encoding.UTF8.GetBytes(Data);
  97. req.Method = "POST";
  98. req.ContentType = "application/x-www-form-urlencoded";
  99. req.ContentLength = requestBytes.Length;
  100. Stream requestStream = req.GetRequestStream();
  101. requestStream.Write(requestBytes, , requestBytes.Length);
  102. requestStream.Close();
  103.  
  104. HttpWebResponse res = (HttpWebResponse)req.GetResponse();
  105. System.IO.StreamReader sr = new System.IO.StreamReader(res.GetResponseStream(), System.Text.Encoding.UTF8);
  106. string PostJie = sr.ReadToEnd();
  107. sr.Close();
  108. res.Close();
  109. return PostJie;
  110. }

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

  1. #region 发送模板消息
  2. /// <summary>
  3. /// 发送模板消息
  4. /// </summary>
  5. /// <param name="userName">公众号</param>
  6. /// <param name="touser">接收消息的账号</param>
  7. /// <param name="templateId">模板id</param>
  8. /// <param name="detailUrl">详情地址</param>
  9. /// <param name="topColor">顶端颜色</param>
  10. /// <param name="data">数据</param>
  11. /// <param name="errorMessage">返回发送是否成功</param>
  12. /// <returns>返回消息id;如果发送失败,返回-1。</returns>
  13. public static long Send(string userName, string touser, string templateId, string detailUrl, Color topColor,
  14. Tuple<string, string, Color>[] data, out ErrorMessage errorMessage)
  15. {
  16. errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "");
  17. long id = -1;
  18. //校验参数
  19. if (string.IsNullOrWhiteSpace(touser))
  20. {
  21. errorMessage.errmsg = "接收消息的账号不能为空。";
  22. return id;
  23. }
  24. if (string.IsNullOrWhiteSpace(templateId))
  25. {
  26. errorMessage.errmsg = "模板id不能为空。";
  27. return id;
  28. }
  29. if (data == null || data.Length == 0)
  30. {
  31. errorMessage.errmsg = "模板数据不能为空。";
  32. return id;
  33. }
  34. foreach (Tuple<string, string, Color> item in data)
  35. {
  36. if (string.IsNullOrWhiteSpace(item.Item1) || string.IsNullOrWhiteSpace(item.Item2))
  37. {
  38. errorMessage.errmsg = "模板数据不能为空。";
  39. return id;
  40. }
  41. }
  42. //获取许可令牌
  43. AccessToken token = AccessToken.Get(userName);
  44. if (token == null)
  45. {
  46. errorMessage.errmsg = "获取许可令牌失败。";
  47. return id;
  48. }
  49. string url = string.Format(urlForSending, token.access_token);
  50. //生成待发送的数据
  51. dynamic postData = new ExpandoObject();
  52. postData.touser = touser;
  53. postData.template_id = templateId;
  54. postData.url = detailUrl ?? string.Empty;
  55. postData.topcolor = Utility.GetColorString(topColor);
  56. postData.data = new ExpandoObject();
  57. IDictionary<string, object> dataDict = (IDictionary<string, object>)postData.data;
  58. foreach (Tuple<string, string, Color> item in data)
  59. {
  60. dataDict.Add(item.Item1, new { value = item.Item2, color = Utility.GetColorString(item.Item3) });
  61. }
  62. string json = JsonConvert.SerializeObject(postData);
  63. //发送数据
  64. string responseContent;
  65. if (!HttpHelper.Request(url, out responseContent, httpMethod, json))
  66. {
  67. errorMessage.errmsg = "提交数据到微信服务器失败。";
  68. return id;
  69. }
  70. //解析结果
  71. JObject jo = JObject.Parse(responseContent);
  72. JToken jt;
  73. if (jo.TryGetValue("errcode", out jt) && jo.TryGetValue("errmsg", out jt))
  74. {
  75. errorMessage.errcode = (int)jo["errcode"];
  76. errorMessage.errmsg = (string)jo["errmsg"];
  77. if (jo.TryGetValue("msgid", out jt))
  78. id = (long)jt;
  79. }
  80. else
  81. errorMessage.errmsg = "解析返回结果失败。";
  82. return id;
  83. }
  84. #endregion
  1. AccessToken token = AccessToken.Get(userName);获取许可令牌上一篇文章中我们已经说过这个类,这里就不多说了,HttpHelper帮助类的代码如下:
  1. /// <summary>
  2. /// HttpHelper:http请求与响应辅助类
  3. /// </summary>
  4. public static class HttpHelper
  5. {
  6. /// <summary>
  7. /// 向微信服务器发送请求时的编码
  8. /// </summary>
  9. public static readonly Encoding RequestEncoding = Encoding.UTF8;
  10. /// <summary>
  11. /// 微信服务器响应的编码
  12. /// </summary>
  13. public static readonly Encoding ResponseEncoding = Encoding.UTF8;
  14.  
  15. /// <summary>
  16. /// 向微信服务器提交数据,并获取微信服务器响应的数据
  17. /// </summary>
  18. /// <param name="url">服务器地址</param>
  19. /// <param name="responseData">返回响应数据</param>
  20. /// /// <param name="httpMethod">http方法</param>
  21. /// <param name="data">数据</param>
  22. /// <returns>返回是否提交成功</returns>
  23. public static bool Request(string url, out byte[] responseData,
  24. string httpMethod = WebRequestMethods.Http.Get, byte[] data = null)
  25. {
  26. bool success = false;
  27. responseData = null;
  28. Stream requestStream = null;
  29. HttpWebResponse response = null;
  30. Stream responseStream = null;
  31. MemoryStream ms = null;
  32. try
  33. {
  34. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
  35. request.Method = httpMethod;
  36. if (data != null && data.Length > )
  37. {
  38. request.ContentLength = data.Length;
  39. requestStream = request.GetRequestStream();
  40. requestStream.Write(data, , data.Length);
  41. }
  42. response = (HttpWebResponse)request.GetResponse();
  43. //由于微信服务器的响应有时没有正确设置ContentLength,这里不检查ContentLength
  44. //if (response.ContentLength > 0)
  45. {
  46. ms = new MemoryStream();
  47. responseStream = response.GetResponseStream();
  48. int bufferLength = ;
  49. byte[] buffer = new byte[bufferLength];
  50. int size = responseStream.Read(buffer, , bufferLength);
  51. while (size > )
  52. {
  53. ms.Write(buffer, , size);
  54. size = responseStream.Read(buffer, , bufferLength);
  55. }
  56. responseData = ms.ToArray();
  57. }
  58. success = true;
  59. }
  60. finally
  61. {
  62. if (requestStream != null)
  63. requestStream.Close();
  64. if (responseStream != null)
  65. responseStream.Close();
  66. if (ms != null)
  67. ms.Close();
  68. if (response != null)
  69. response.Close();
  70. }
  71. return success;
  72. }
  73.  
  74. /// <summary>
  75. /// 向微信服务器提交数据,并获取微信服务器响应的数据
  76. /// </summary>
  77. /// <param name="url">服务器地址</param>
  78. /// <param name="responseData">返回响应数据</param>
  79. /// /// <param name="httpMethod">http方法</param>
  80. /// <param name="data">数据</param>
  81. /// <returns>返回是否提交成功</returns>
  82. public static bool Request(string url, out byte[] responseData,
  83. string httpMethod = WebRequestMethods.Http.Get, string data = null)
  84. {
  85. byte[] bytes = string.IsNullOrEmpty(data) ? null : RequestEncoding.GetBytes(data);
  86. return Request(url, out responseData, httpMethod, (byte[])bytes);
  87. }
  88.  
  89. /// <summary>
  90. /// 向微信服务器提交数据,并获取微信服务器响应的内容
  91. /// </summary>
  92. /// <param name="url">服务器地址</param>
  93. /// <param name="responseContent">返回响应内容</param>
  94. /// /// <param name="httpMethod">http方法</param>
  95. /// <param name="data">数据</param>
  96. /// <returns>返回是否提交成功</returns>
  97. public static bool Request(string url, out string responseContent,
  98. string httpMethod = WebRequestMethods.Http.Get, byte[] data = null)
  99. {
  100. byte[] responseData;
  101. responseContent = string.Empty;
  102. bool success = Request(url, out responseData, httpMethod, data);
  103. if (success && responseData != null && responseData.Length > )
  104. responseContent = ResponseEncoding.GetString(responseData);
  105. return success;
  106. }
  107.  
  108. /// <summary>
  109. /// 向微信服务器提交数据,并获取微信服务器响应的内容
  110. /// </summary>
  111. /// <param name="url">服务器地址</param>
  112. /// <param name="responseContent">返回响应内容</param>
  113. /// /// <param name="httpMethod">http方法</param>
  114. /// <param name="data">数据</param>
  115. /// <returns>返回是否提交成功</returns>
  116. public static bool Request(string url, out string responseContent,
  117. string httpMethod = WebRequestMethods.Http.Get, string data = null)
  118. {
  119. byte[] bytes = string.IsNullOrEmpty(data) ? null : RequestEncoding.GetBytes(data);
  120. return Request(url, out responseContent, httpMethod, (byte[])bytes);
  121. }
  122.  
  123. /// <summary>
  124. /// 向微信服务器提交数据
  125. /// </summary>
  126. /// <param name="url">服务器地址</param>
  127. /// /// <param name="httpMethod">http方法</param>
  128. /// <param name="data">数据</param>
  129. /// <returns>返回是否提交成功</returns>
  130. public static bool Request(string url, string httpMethod = WebRequestMethods.Http.Get, byte[] data = null)
  131. {
  132. bool success = false;
  133. Stream requestStream = null;
  134. HttpWebResponse response = null;
  135. try
  136. {
  137. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
  138. request.Method = httpMethod;
  139. if (data != null && data.Length > )
  140. {
  141. request.ContentLength = data.Length;
  142. requestStream = request.GetRequestStream();
  143. requestStream.Write(data, , data.Length);
  144. }
  145. response = (HttpWebResponse)request.GetResponse();
  146. success = true;
  147. }
  148. finally
  149. {
  150. if (requestStream != null)
  151. requestStream.Close();
  152. if (response != null)
  153. response.Close();
  154. }
  155. return success;
  156. }
  157.  
  158. /// <summary>
  159. /// 组合url,发送数据,然后返回响应字符串
  160. /// </summary>
  161. /// <param name="urlFormat">url格式字符串,第一个参数为userName获取到的许可令牌,然后依次为parameters中的参数</param>
  162. /// <param name="userName">公众号</param>
  163. /// <param name="urlParameters">参数</param>
  164. /// <param name="httpMethod">执行请求的http方法</param>
  165. /// <param name="data">请求的内容</param>
  166. /// <returns>返回响应内容;如果请求失败,或者发生错误,返回空字符串</returns>
  167. public static string RequestResponseContent(string urlFormat, string userName, IEnumerable<object> urlParameters = null, string httpMethod = WebRequestMethods.Http.Get, string data = null)
  168. {
  169. string responseContent = string.Empty;
  170. AccessToken token = AccessToken.Get(userName);
  171. if (token == null)
  172. return responseContent;
  173. string url;
  174. if (urlParameters == null)
  175. url = string.Format(urlFormat, token.access_token);
  176. else
  177. {
  178. List<object> paramList = new List<object>(urlParameters);
  179. paramList.Insert(, token.access_token);
  180. url = string.Format(urlFormat, paramList.ToArray());
  181. }
  182. HttpHelper.Request(url, out responseContent, httpMethod, (string)data);
  183. return responseContent;
  184. }
  185.  
  186. /// <summary>
  187. /// 组合url,发送数据,然后返回响应的错误消息。
  188. /// 注:错误消息不一定代表失败或者错误。
  189. /// </summary>
  190. /// <param name="urlFormat">url格式字符串,第一个参数为userName获取到的许可令牌,然后依次为parameters中的参数</param>
  191. /// <param name="userName">公众号</param>
  192. /// <param name="urlParameters">参数</param>
  193. /// <param name="httpMethod">执行请求的http方法</param>
  194. /// <param name="data">请求的内容</param>
  195. /// <returns>返回响应的错误消息</returns>
  196. public static ErrorMessage RequestErrorMessage(string urlFormat, string userName, IEnumerable<object> urlParameters = null, string httpMethod = WebRequestMethods.Http.Get, string data = null)
  197. {
  198. string responseContent = RequestResponseContent(urlFormat, userName, urlParameters, httpMethod, data);
  199. if (string.IsNullOrWhiteSpace(responseContent))
  200. return new ErrorMessage(ErrorMessage.ExceptionCode, "请求失败。");
  201. else if (ErrorMessage.IsErrorMessage(responseContent))
  202. return ErrorMessage.Parse(responseContent);
  203. else
  204. return new ErrorMessage(ErrorMessage.ExceptionCode, "解析响应失败。");
  205. }
  206.  
  207. /// <summary>
  208. /// 组合url,发送数据,然后返回结果。
  209. /// 注:结果为需要解析的类。
  210. /// </summary>
  211. /// <typeparam name="T">返回结果的类型</typeparam>
  212. /// <param name="urlFormat">url格式字符串,第一个参数为userName获取到的许可令牌,然后依次为parameters中的参数</param>
  213. /// <param name="userName">公众号</param>
  214. /// <param name="errorMessage">返回请求是否成功</param>
  215. /// <param name="urlParameters">参数</param>
  216. /// <param name="httpMethod">执行请求的http方法</param>
  217. /// <param name="data">请求的内容</param>
  218. /// <returns>返回结果;如果请求失败,或者发生错误,返回null。</returns>
  219. public static T RequestParsableResult<T>(string urlFormat, string userName, out ErrorMessage errorMessage, IEnumerable<object> urlParameters = null, string httpMethod = WebRequestMethods.Http.Get, string data = null)
  220. where T : IParsable, new()
  221. {
  222. T result = default(T);
  223. errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "请求失败。");
  224. string responseContent = RequestResponseContent(urlFormat, userName, urlParameters, httpMethod, data);
  225. if (string.IsNullOrWhiteSpace(responseContent))
  226. return result;
  227. if (ErrorMessage.IsErrorMessage(responseContent))
  228. errorMessage = ErrorMessage.Parse(responseContent);
  229. else
  230. {
  231. try
  232. {
  233. result = Utility.Parse<T>(responseContent);
  234. if (result != null)
  235. errorMessage = new ErrorMessage(ErrorMessage.SuccessCode, "请求成功。");
  236. else
  237. errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "解析失败。");
  238. }
  239. catch
  240. {
  241. errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "解析失败。");
  242. }
  243. }
  244. return result;
  245. }
  246.  
  247. /// <summary>
  248. /// 组合url,发送数据,然后返回结果。
  249. /// 注:结果为已知的简单值类型。
  250. /// </summary>
  251. /// <typeparam name="T">返回结果的类型</typeparam>
  252. /// <param name="urlFormat">url格式字符串,第一个参数为userName获取到的许可令牌,然后依次为parameters中的参数</param>
  253. /// <param name="userName">公众号</param>
  254. /// <param name="propertyNameInJson">返回结果在json中的键名</param>
  255. /// <param name="errorMessage">返回请求是否成功</param>
  256. /// <param name="urlParameters">参数</param>
  257. /// <param name="httpMethod">执行请求的http方法</param>
  258. /// <param name="data">请求的内容</param>
  259. /// <returns>返回结果;如果请求失败,或者发生错误,返回default(T)。</returns>
  260. 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)
  261. where T : struct
  262. {
  263. errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "请求失败。");
  264. string responseContent = RequestResponseContent(urlFormat, userName, urlParameters, httpMethod, data);
  265. return ConvertValueTypeResult<T>(responseContent, propertyNameInJson, out errorMessage);
  266. }
  267.  
  268. /// <summary>
  269. /// 获取值类型的结果
  270. /// </summary>
  271. /// <typeparam name="T">返回结果的类型</typeparam>
  272. /// <param name="responseContent">响应内容</param>
  273. /// <param name="propertyNameInJson">返回结果在json中的键名</param>
  274. /// <param name="errorMessage">返回请求是否成功</param>
  275. /// <returns>返回结果;如果请求失败,或者发生错误,返回default(T)。</returns>
  276. private static T ConvertValueTypeResult<T>(string responseContent, string propertyNameInJson, out ErrorMessage errorMessage)
  277. where T : struct
  278. {
  279. if (string.IsNullOrWhiteSpace(responseContent))
  280. {
  281. errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "请求失败。");
  282. return default(T);
  283. }
  284. if (ErrorMessage.IsErrorMessage(responseContent))
  285. errorMessage = ErrorMessage.Parse(responseContent);
  286. else
  287. errorMessage = new ErrorMessage(ErrorMessage.SuccessCode, "请求成功。");
  288. JObject jo = JObject.Parse(responseContent);
  289. JToken jt;
  290. if (jo.TryGetValue(propertyNameInJson, out jt))
  291. return ConvertValueTypeResult<T>((string)jt);
  292. else
  293. return default(T);
  294. }
  295.  
  296. /// <summary>
  297. /// 获取值类型的结果
  298. /// </summary>
  299. /// <typeparam name="T">返回结果的类型</typeparam>
  300. /// <param name="responseContent">响应内容</param>
  301. /// <param name="propertyNameInJson">返回结果在json中的键名</param>
  302. /// <param name="errorMessage">返回请求是否成功</param>
  303. /// <returns>返回结果;如果请求失败,或者发生错误,返回default(T)。</returns>
  304. private static T ConvertValueTypeResult<T>(string value)
  305. where T : struct
  306. {
  307. Type type = typeof(T);
  308. if (type.IsEnum)
  309. return (T)Enum.Parse(type, value);
  310. else if (type == typeof(sbyte))
  311. return (T)(object)Convert.ToSByte(value);
  312. else if (type == typeof(byte))
  313. return (T)(object)Convert.ToByte(value);
  314. else if (type == typeof(char))
  315. return (T)(object)Convert.ToChar(value);
  316. else if (type == typeof(short))
  317. return (T)(object)Convert.ToInt16(value);
  318. else if (type == typeof(ushort))
  319. return (T)(object)Convert.ToUInt16(value);
  320. else if (type == typeof(int))
  321. return (T)(object)Convert.ToInt32(value);
  322. else if (type == typeof(uint))
  323. return (T)(object)Convert.ToUInt32(value);
  324. else if (type == typeof(long))
  325. return (T)(object)Convert.ToInt64(value);
  326. else if (type == typeof(ulong))
  327. return (T)(object)Convert.ToUInt64(value);
  328. else if (type == typeof(float))
  329. return (T)(object)Convert.ToSingle(value);
  330. else if (type == typeof(double))
  331. return (T)(object)Convert.ToDouble(value);
  332. else if (type == typeof(decimal))
  333. return (T)(object)Convert.ToDecimal(value);
  334. else if (type == typeof(bool))
  335. return (T)(object)Convert.ToBoolean(value);
  336. else
  337. throw new ArgumentException("不支持的值类型。");
  338. }
  339.  
  340. /// <summary>
  341. /// 向微信服务器提交数据
  342. /// </summary>
  343. /// <param name="url">服务器地址</param>
  344. /// /// <param name="httpMethod">http方法</param>
  345. /// <param name="data">数据</param>
  346. /// <returns>返回是否提交成功</returns>
  347. public static bool Request(string url, string httpMethod = WebRequestMethods.Http.Get, string data = null)
  348. {
  349. byte[] bytes = string.IsNullOrEmpty(data) ? null : RequestEncoding.GetBytes(data);
  350. return Request(url, httpMethod, (byte[])bytes);
  351. }
  352.  
  353. /// <summary>
  354. /// 上传文件
  355. /// </summary>
  356. /// <param name="url">服务器地址</param>
  357. /// <param name="filename">文件名(不包含路径)</param>
  358. /// <param name="fileData">文件数据</param>
  359. /// <param name="formData">表单数据</param>
  360. /// <returns>返回服务器的响应字符串</returns>
  361. public static string Upload(string url, string filename, byte[] fileData, NameValueCollection formData = null)
  362. {
  363. string responseContent = string.Empty;
  364. if (string.IsNullOrWhiteSpace(url) || string.IsNullOrWhiteSpace(filename) || fileData == null || fileData.Length == )
  365. return responseContent;
  366. // 边界符
  367. string boundary = "AaB03xAaB03x";
  368. // 开始边界符
  369. byte[] beginBoundary = Encoding.ASCII.GetBytes("--" + boundary + "\r\n");
  370. // 结束符
  371. byte[] endBoundary = Encoding.ASCII.GetBytes("--" + boundary + "--\r\n");
  372. //换行
  373. byte[] newLine = Encoding.ASCII.GetBytes("\r\n");
  374. MemoryStream ms = null;
  375. Stream stream = null;
  376. HttpWebResponse response = null;
  377. StreamReader sr = null;
  378. try
  379. {
  380. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
  381. request.Method = WebRequestMethods.Http.Post;
  382. request.ContentType = "multipart/form-data; boundary=" + boundary;
  383. // 写入文件
  384. string header = string.Format("Content-Disposition: form-data; filename=\"{0}\"\r\n" +
  385. "Content-Type: application/octet-stream\r\n\r\n",
  386. filename);
  387. byte[] headerbytes = Encoding.UTF8.GetBytes(header);
  388. ms = new MemoryStream();
  389. ms.Write(beginBoundary, , beginBoundary.Length);
  390. ms.Write(headerbytes, , headerbytes.Length);
  391. ms.Write(fileData, , fileData.Length);
  392. // 写入表单数据
  393. if (formData != null && formData.Count > )
  394. {
  395. var formItem = "\r\n--" + boundary +
  396. "\r\nContent-Disposition: form-data; name=\"{0}\"" +
  397. "\r\n\r\n{1}\r\n";
  398. foreach (string key in formData.Keys)
  399. {
  400. string value = formData[key];
  401. byte[] bytes = Encoding.UTF8.GetBytes(string.Format(formItem, key, value));
  402. ms.Write(bytes, , bytes.Length);
  403. }
  404. }
  405. //写入结束边界符
  406. ms.Write(newLine, , newLine.Length);
  407. ms.Write(endBoundary, , endBoundary.Length);
  408. request.ContentLength = ms.Length;
  409. stream = request.GetRequestStream();
  410. stream.Write(ms.ToArray(), , (int)ms.Length);
  411. //获取响应
  412. response = (HttpWebResponse)request.GetResponse();
  413. sr = new StreamReader(response.GetResponseStream(), HttpHelper.ResponseEncoding);
  414. responseContent = sr.ReadToEnd();
  415. }
  416. finally
  417. {
  418. if (ms != null)
  419. ms.Close();
  420. if (stream != null)
  421. stream.Close();
  422. if (sr != null)
  423. sr.Close();
  424. if (response != null)
  425. response.Close();
  426. }
  427. return responseContent;
  428. }
  429.  
  430. /// <summary>
  431. /// 上传文件
  432. /// </summary>
  433. /// <param name="url">服务器地址</param>
  434. /// <param name="pathname">包含路径的文件名</param>
  435. /// <param name="formData">表单数据</param>
  436. /// <returns>返回服务器的响应字符串</returns>
  437. public static string Upload(string url, string pathname, NameValueCollection formData = null)
  438. {
  439. string filename = Path.GetFileName(pathname);
  440. byte[] data = null;
  441. FileStream fs = null;
  442. MemoryStream ms = null;
  443. try
  444. {
  445. fs = new FileStream(pathname, FileMode.Open, FileAccess.Read);
  446. ms = new MemoryStream();
  447. int bufferLength = ;
  448. byte[] buffer = new byte[bufferLength];
  449. int size = fs.Read(buffer, , bufferLength);
  450. while (size > )
  451. {
  452. ms.Write(buffer, , size);
  453. size = fs.Read(buffer, , bufferLength);
  454. }
  455. data = ms.ToArray();
  456. }
  457. finally
  458. {
  459. if (fs != null)
  460. fs.Close();
  461. if (ms != null)
  462. ms.Close();
  463. }
  464. return Upload(url, filename, data, formData);
  465. }
  466. }
  467.  
  468. 复制代码

四.最终效果如下:

.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. Arraylist<E>

    ArrayList 应该是大部分人接触JCF之后, 第一个熟悉和使用的类.它的特点主要有一下几个: 1. 基于数组 public ArrayList(int initialCapacity) { if ...

  2. windows Path变量优先级

    系统>用户 且第一次配置无需重启即可使用 如遇到升级版本,需要重新配置Path,则需要重启方可生效~~

  3. The first day to learn Englisht

    IF you want to go fast,to alone. IF you want to go far,go with others.

  4. C++利用IO流对浮点数进行格式化控制输出

    浮点数输出 (100/100 分数) 题目描述 编写一个程序,输入一个浮点数和输出格式要求,按照格式要求将该浮点数输出.给定非负整数m和n,表示输出的浮点数小数点前的宽度为m,若宽度不够则在前面补0, ...

  5. codeforces 723E (欧拉回路)

    Problem One-Way Reform 题目大意 给一张n个点,m条边的无向图,要求给每条边定一个方向,使得最多的点入度等于出度,要求输出方案. 解题分析 最多点的数量就是入度为偶数的点. 将入 ...

  6. $.ajax请求返回数据中status为200,回调的却是error?

    $.ajax({ type:'get',//使用get方法访问后台 dataType:'json',//访问json格式的数据 url:'http://job.hainan.net/api/recru ...

  7. Python 基礎 - 字典的操作使用

    接下來介紹字典,這在未來工作上,會是很常使用的,就來好好了解一下唄- 字典是一個 key(鍵)-value(值) 的數據類型,可以儲存很多訊息 #!/usr/bin/env python3 # -*- ...

  8. gdb 调试出现 ImportError: No module named 'libstdcxx'

    在emacs使用gdb调试程序,出现错误 , in <module> from libstdcxx.v6.printers import register_libstdcxx_printe ...

  9. input常用属性

    对于input的使用,大家都很熟悉的,<input> 标签用于搜集用户信息.根据不同的 type 属性值,输入字段拥有很多种形式.输入字段可以是文本字段.复选框.掩码后的文本控件.单选按钮 ...

  10. 八皇后—Java

    package queen; public class queen { static boolean col[] = new boolean[8]; static boolean main_diago ...