程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#微信公眾號開發系列教程六(被動回復與上傳下載多媒體文件)

C#微信公眾號開發系列教程六(被動回復與上傳下載多媒體文件)

編輯:C#入門知識

C#微信公眾號開發系列教程六(被動回復與上傳下載多媒體文件)


第四,第五章已經講了怎麼處理用戶發送的消息,本章就來講講怎麼響應用戶的請求。想必新手看到這個標題也就懵了,千萬別懵,微信的接口就這樣,在回復圖片、音樂、語音等都需要將我們的媒體文件上傳到微信的服務器才能使用。不知道這樣的做法是出於什麼考慮的,而且同是給用戶回復消息,客服接口和群發接口發送的消息體格式竟然是不同的。估計是這幾處接口不是同一個人寫的,沒有做好代碼的統一,咱們屌絲開發者只能無力吐槽了。   在講上傳下載接口前,需要先將下先來講講access_token獲取方法。在微信接口開發的過程access_token是至關重要的,是公眾號的全局唯一票據,公眾號調用各接口時都需使用access_token。開發者需要進行妥善保存。access_token的存儲至少要保留512個字符空間。access_token的有效期目前為2個小時,需定時刷新,重復獲取將導致上次獲取的access_token失效。需要注意的時,一個公眾號同時只存在一個有效的access_token,開發者需要在access_token過期前,刷新access_token。在刷新的過程中,公眾平台後台會保證在刷新短時間內,新老access_token都可用,這保證了第三方業務的平滑過渡。   公眾號可以使用AppID和AppSecret調用本接口來獲取access_token。AppID和AppSecret可在微信公眾平台官網-開發者中心頁中獲得(需要已經成為開發者,且帳號沒有異常狀態)。如下圖:   image   獲取access_token的接口地址是:   https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET 將appid和secret替換成你自己的。 發送get請求到這個地址,返回的數據如下:   {"access_token":"eEd6dhp0s24JfWwDyGBbrvJxnhqHTSYZ8MKdQ7MuCGBKxAjHv-tEIwhFZzn102lGvIWxnjZZreT6C1NCT9fpS7NREOkEX42yojVnqKVaicg","expires_in":7200} 我們只需解析這個json,即可獲取到我們所需的access_token.代碼如下: AccessToken實體類: public class AccessToken     {         public string token { get; set; }         public DateTime expirestime { get; set; }     } 獲取access token     /// <summary>         /// 獲取access token         /// </summary>         /// <param name="appid">第三方用戶唯一憑證</param>         /// <param name="secret">第三方用戶唯一憑證密鑰,即appsecret</param>         /// <returns>AccessToken對象,expirestime是過期時間</returns>         public static AccessToken GetAccessToken(string appid, string secret)         {             try             {                 string url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", appid, secret);                 string retdata = Utils.HttpGet(url);                 if (retdata.Contains("access_token"))                 {                     JObject obj = (JObject)JsonConvert.DeserializeObject(retdata);                     string token = obj.Value<string>("access_token");                     int expirestime = obj.Value<int>("expires_in");                     return new AccessToken { token = token, expirestime = DateTime.Now.AddSeconds(expirestime) };                 }                 else                 {                     WriteBug(retdata);//寫錯誤日志                 }                 return null;             }             catch (Exception e)             {                 WriteBug(e.ToString());//寫錯誤日志                 return null;             }           }     access_token獲取成功後,下面來講上傳下載多媒體文件吧。官方說,公眾號在使用接口時,對多媒體文件、多媒體消息的獲取和調用等操作,是通過media_id來進行的(咱讀書少,不明白為什麼不能使用url,而要多此一舉先上傳到服務器在發送)。通過本接口,公眾號可以上傳或下載多媒體文件。但請注意,每個多媒體文件(media_id)會在上傳、用戶發送到微信服務器3天後自動刪除,以節省服務器資源。   上傳多媒體的接口地址是:   http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE   其中access_token為調用接口憑證,type是媒體文件類型,分別有圖片(image)、語音(voice)、視頻(video)和縮略圖(thumb)   注意事項:   上傳的多媒體文件有格式和大小限制,如下:   圖片(image): 1M,支持JPG格式 語音(voice):2M,播放長度不超過60s,支持AMR\MP3格式 視頻(video):10MB,支持MP4格式 縮略圖(thumb):64KB,支持JPG格式 媒體文件在後台保存時間為3天,即3天後media_id失效。   為了方便調用,將媒體文件的類型定義為枚舉,代碼如下:     public enum MediaType     {         /// <summary>         /// 圖片(image): 1M,支持JPG格式         /// </summary>         image,         /// <summary>         /// 語音(voice):2M,播放長度不超過60s,支持AMR\MP3格式         /// </summary>         voice,         /// <summary>         /// 視頻(video):10MB,支持MP4格式         /// </summary>         video,         /// <summary>         /// 縮略圖(thumb):64KB,支持JPG格式         /// </summary>         thumb     }   然後定義返回值的類型:     public class UpLoadInfo     {         /// <summary>         /// 媒體文件類型,分別有圖片(image)、語音(voice)、視頻(video)和縮略圖(thumb,主要用於視頻與音樂格式的縮略圖)         /// </summary>         public string type { get; set; }         /// <summary>         /// 媒體文件上傳後,獲取時的唯一標識         /// </summary>         public string media_id { get; set; }         /// <summary>         /// 媒體文件上傳時間戳         /// </summary>         public string created_at { get; set; }     }   最後使用WebClient類來上傳文件,並讀出返回值,代碼如下:     /// <summary>         /// 微信上傳多媒體文件         /// </summary>         /// <param name="filepath">文件絕對路徑</param>         public static ReceiveModel.UpLoadInfo WxUpLoad(string filepath, string token, MediaType mt)         {             using (WebClient client = new WebClient())             {                 byte[] b = client.UploadFile(string.Format("http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token={0}&type={1}", token, mt.ToString()), filepath);//調用接口上傳文件                 string retdata = Encoding.Default.GetString(b);//獲取返回值                 if (retdata.Contains("media_id"))//判斷返回值是否包含media_id,包含則說明上傳成功,然後將返回的json字符串轉換成json                 {                     return JsonConvert.DeserializeObject<UpLoadInfo>(retdata);                 }                 else                 {//否則,寫錯誤日志                       WriteBug(retdata);//寫錯誤日志                     return null;                 }             }         }   至此,在講回復消息之前,插入了兩個基礎支持接口,由於各位整理歸納能力太爛了,各位看官請多包涵,如有問題就留言和我交流。 下面正式開始講回復消息。在看下面內容的時候,請大家結合第四,第五章進行閱讀。   前面兩章講述了接收並處理用戶發送的消息,講到了一個消息基類BaseMessage,而不管我們接收到什麼類型的消息,都需要可以調用方法,進行響應用戶的請求,所以,用戶回復用戶請求的方法需要封裝到基類中。下面先簡單了解下公眾號可以回復的消息類型,以及消息格式。   注意:   一旦遇到以下情況,微信都會在公眾號會話中,向用戶下發系統提示“該公眾號暫時無法提供服務,請稍後再試”:   1、開發者在5秒內未回復任何內容 2、開發者回復了異常數據,比如JSON數據等 回復文本消息   <xml> <ToUserName><![CDATA[接收方帳號(收到的OpenID)]]></ToUserName> <FromUserName><![CDATA[開發者微信號]]></FromUserName> <CreateTime>消息創建時間 (整型)</CreateTime> <MsgType><![CDATA[image]]></MsgType> <Content><![CDATA[回復的消息內容(換行:在content中能夠換行,微信客戶端就支持換行顯示)]]></Content> </xml>   回復圖片消息   <xml> <ToUserName><![CDATA[接收方帳號(收到的OpenID)]]></ToUserName> <FromUserName><![CDATA[開發者微信號]]></FromUserName> <CreateTime>消息創建時間 (整型)</CreateTime> <MsgType><![CDATA[image]]></MsgType> <Image> <MediaId><![CDATA[通過上傳多媒體文件,得到的id。]]></MediaId> </Image> </xml>   回復語音消息   <xml> <ToUserName><![CDATA[接收方帳號(收到的OpenID)]]></ToUserName> <FromUserName><![CDATA[開發者微信號]]></FromUserName> <CreateTime>消息創建時間 (整型)</CreateTime> <MsgType><![CDATA[voice]]></MsgType> <Voice> <MediaId><![CDATA[通過上傳多媒體文件,得到的id。]]></MediaId> </Voice> </xml>   回復視頻消息   <xml> <ToUserName><![CDATA[接收方帳號(收到的OpenID)]]></ToUserName> <FromUserName><![CDATA[開發者微信號]]></FromUserName> <CreateTime>消息創建時間 (整型)</CreateTime> <MsgType><![CDATA[video]]></MsgType> <Video> <MediaId><![CDATA[通過上傳多媒體文件,得到的id。]]></MediaId> <Title><![CDATA[視頻消息的標題]]></Title>  <Description><![CDATA[視頻消息的描述]]></Description>  </Video> </xml>   回復音樂消息   <xml> <ToUserName><![CDATA[接收方帳號(收到的OpenID)]]></ToUserName> <FromUserName><![CDATA[開發者微信號]]></FromUserName> <CreateTime>消息創建時間 (整型)</CreateTime> <MsgType><![CDATA[music]]></MsgType> <Music> <ThumbMediaId><![CDATA[縮略圖的媒體id,通過上傳多媒體文件,得到的id。]]></ThumbMediaId> <Title><![CDATA[視頻消息的標題]]></Title>  <Description><![CDATA[視頻消息的描述]]></Description>  <MusicURL><![CDATA[音樂鏈接]]></MusicURL>  <HQMusicUrl><![CDATA[高質量音樂鏈接,WIFI環境優先使用該鏈接播放音樂]]></HQMusicUrl>  </Music> </xml>   回復圖文消息   <xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><![CDATA[news]]></MsgType> <ArticleCount>2</ArticleCount> <Articles> <item> <Title><![CDATA[title1]]></Title>  <Description><![CDATA[description1]]></Description> <PicUrl><![CDATA[picurl]]></PicUrl> <Url><![CDATA[url]]></Url> </item> <item> <Title><![CDATA[title]]></Title> <Description><![CDATA[description]]></Description> <PicUrl><![CDATA[picurl]]></PicUrl> <Url><![CDATA[url]]></Url> </item> </Articles> </xml>   回復圖文中,item是一個項,一個item代碼一個圖文。在響應的時候,我們只需根據數據格式,替換掉對應的屬性,然後Response.Write(s)即可。結合前兩章的講解,BaseMessage的最終代碼如下:     /// <summary>     /// 消息體基類     /// </summary>     public abstract class BaseMessage     {         /// <summary>         /// 開發者微信號         /// </summary>         public string ToUserName { get; set; }        /// <summary>         /// 發送方帳號(一個OpenID)        /// </summary>         public string FromUserName { get; set; }         /// <summary>         /// 消息創建時間 (整型)         /// </summary>         public string CreateTime { get; set; }         /// <summary>         /// 消息類型         /// </summary>         public MsgType MsgType { get; set; }           public virtual void ResponseNull()         {             Utils.ResponseWrite("");         }         public virtual void ResText(EnterParam param, string content)         {             StringBuilder resxml = new StringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>", FromUserName, ToUserName, Utils.ConvertDateTimeInt(DateTime.Now)));             resxml.AppendFormat("<MsgType><![CDATA[text]]></MsgType><Content><![CDATA[{0}]]></Content><FuncFlag>0</FuncFlag></xml>", content);             Response(param, resxml.ToString());         }         /// <summary>         /// 回復消息(音樂)         /// </summary>         public  void ResMusic(EnterParam param, Music mu)         {             StringBuilder resxml = new StringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName, Utils.ConvertDateTimeInt(DateTime.Now)));             resxml.Append(" <MsgType><![CDATA[music]]></MsgType>");             resxml.AppendFormat("<Music><Title><![CDATA[{0}]]></Title><Description><![CDATA[{1}]]></Description>", mu.Title, mu.Description);             resxml.AppendFormat("<MusicUrl><![CDATA[http://{0}{1}]]></MusicUrl><HQMusicUrl><![CDATA[http://{2}{3}]]></HQMusicUrl></Music><FuncFlag>0</FuncFlag></xml>", VqiRequest.GetCurrentFullHost(), mu.MusicUrl, VqiRequest.GetCurrentFullHost(), mu.HQMusicUrl);             Response(param, resxml.ToString());         }         public  void ResVideo(EnterParam param, Video v)         {             StringBuilder resxml = new StringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName, Utils.ConvertDateTimeInt(DateTime.Now)));             resxml.Append(" <MsgType><![CDATA[video]]></MsgType>");             resxml.AppendFormat("<Video><MediaId><![CDATA[{0}]]></MediaId>", v.media_id);             resxml.AppendFormat("<Title><![CDATA[{0}]]></Title>", v.title);             resxml.AppendFormat("<Description><![CDATA[{0}]]></Description></Video></xml>", v.description);             Response(param, resxml.ToString());         }           /// <summary>         /// 回復消息(圖片)         /// </summary>         public  void ResPicture(EnterParam param, Picture pic, string domain)         {             StringBuilder resxml = new StringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName, Utils.ConvertDateTimeInt(DateTime.Now)));             resxml.Append(" <MsgType><![CDATA[image]]></MsgType>");             resxml.AppendFormat("<PicUrl><![CDATA[{0}]]></PicUrl></xml>", domain + pic.PictureUrl);             Response(param, resxml.ToString());         }           /// <summary>         /// 回復消息(圖文列表)         /// </summary>         /// <param name="param"></param>         /// <param name="art"></param>         public  void ResArticles(EnterParam param, List<Articles> art)         {             StringBuilder resxml = new StringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName, Utils.ConvertDateTimeInt(DateTime.Now)));             resxml.AppendFormat("<MsgType><![CDATA[news]]></MsgType><ArticleCount>{0}</ArticleCount><Articles>", art.Count);             for (int i = 0; i < art.Count; i++)             {                 resxml.AppendFormat("<item><Title><![CDATA[{0}]]></Title>  <Description><![CDATA[{1}]]></Description>", art[i].Title, art[i].Description);                 resxml.AppendFormat("<PicUrl><![CDATA[{0}]]></PicUrl><Url><![CDATA[{1}]]></Url></item>", art[i].PicUrl.Contains("http://") ? art[i].PicUrl : "http://" + VqiRequest.GetCurrentFullHost() + art[i].PicUrl, art[i].Url.Contains("http://") ? art[i].Url : "http://" + VqiRequest.GetCurrentFullHost() + art[i].Url);             }             resxml.Append("</Articles><FuncFlag>0</FuncFlag></xml>");             Response(param, resxml.ToString());         }         /// <summary>         /// 多客服轉發         /// </summary>         /// <param name="param"></param>         public  void ResDKF(EnterParam param)         {             StringBuilder resxml = new StringBuilder();             resxml.AppendFormat("<xml><ToUserName><![CDATA[{0}]]></ToUserName>",FromUserName);             resxml.AppendFormat("<FromUserName><![CDATA[{0}]]></FromUserName><CreateTime>{1}</CreateTime>",ToUserName,CreateTime);             resxml.AppendFormat("<MsgType><![CDATA[transfer_customer_service]]></MsgType></xml>");             Response(param, resxml.ToString());         }         /// <summary>         /// 多客服轉發如果指定的客服沒有接入能力(不在線、沒有開啟自動接入或者自動接入已滿),該用戶會一直等待指定客服有接入能力後才會被接入,而不會被其他客服接待。建議在指定客服時,先查詢客服的接入能力指定到有能力接入的客服,保證客戶能夠及時得到服務。         /// </summary>         /// <param name="param">用戶發送的消息體</param>         /// <param name="KfAccount">多客服賬號</param>         public  void ResDKF(EnterParam param, string KfAccount)         {             StringBuilder resxml = new StringBuilder();             resxml.AppendFormat("<xml><ToUserName><![CDATA[{0}]]></ToUserName>",FromUserName);             resxml.AppendFormat("<FromUserName><![CDATA[{0}]]></FromUserName><CreateTime>{1}</CreateTime>",ToUserName,CreateTime);             resxml.AppendFormat("<MsgType><![CDATA[transfer_customer_service]]></MsgType><TransInfo><KfAccount>{0}</KfAccount></TransInfo></xml>", KfAccount);             Response(param, resxml.ToString());         }         private  void Response(EnterParam param, string data)         {             if (param.IsAes)             {                 var wxcpt = new MsgCrypt(param.token, param.EncodingAESKey, param.appid);                 wxcpt.EncryptMsg(data, Utils.ConvertDateTimeInt(DateTime.Now).ToString(), Utils.GetRamCode(), ref data);             }             Utils.ResponseWrite(data);           }     }   上面的代碼中,public  void ResDKF(EnterParam param),public  void ResDKF(EnterParam param, string KfAccount)兩個方法時多客服中,用戶轉發用戶發送的消息的,多客服將在後期的博文中進行更新,敬請期待。      public  void ResMusic(EnterParam param, Music mu)方法中的Music類的定義如下:   public class Music     {         #region 屬性         /// <summary>         /// 音樂鏈接         /// </summary>         public string MusicUrl { get; set; }         /// <summary>         /// 高質量音樂鏈接,WIFI環境優先使用該鏈接播放音樂         /// </summary>         public string HQMusicUrl { get; set; }         /// <summary>         /// 標題         /// </summary>         public string Title { get; set; }         /// <summary>         /// 描述         /// </summary>         public string Description { get; set; }         #endregion     }   public  void ResVideo(EnterParam param, Video v)方法中的Video類的定義如下:   public class Video     {         public string title { get; set; }         public string media_id { get; set; }         public string description { get; set; }     } public  void ResArticles(EnterParam param, List<Articles> art)中的Articles定義如下:     public class Articles     {         #region 屬性         /// <summary>         /// 圖文消息標題         /// </summary>         public string Title { get; set; }         /// <summary>         /// 圖文消息描述         /// </summary>         public string Description { get; set; }         /// <summary>         /// 圖片鏈接,支持JPG、PNG格式,較好的效果為大圖640*320,小圖80*80。         /// </summary>         public string PicUrl { get; set; }         /// <summary>         /// 點擊圖文消息跳轉鏈接         /// </summary>         public string Url { get; set; }         #endregion     }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved