您好,登錄后才能下訂單哦!
php微信公眾賬號(hào)開發(fā)中容易遇到的坑有哪些,相信很多沒有經(jīng)驗(yàn)的人對(duì)此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
菜單回復(fù)是需要處理XML文件的,我們根據(jù)微信返回的XML文件,可以得到每個(gè)微信用戶相對(duì)于微信公眾號(hào)的唯一標(biāo)識(shí)。微信公眾平臺(tái)的機(jī)制簡單的將就是我們自己輸出固定格式的xml文件,然后微信APP負(fù)責(zé)解析,得到我們想要的信息,然后對(duì)信息統(tǒng)一處理。
第六坑,如果你看微信文檔,那么,絕對(duì)坑死你,上圖。這里的ToUserName和FromUserName一定特么的要分清楚了,記住,千萬不要寫反了,用戶對(duì)于微信而言是A→B,那么微信對(duì)于用戶就是反著來的,貌似現(xiàn)在應(yīng)該說清楚了。
/// <summary> /// 接收微信發(fā)送的XML消息并且解析 /// </summary> private void ReceiveXml() { try { Stream requestStream = System.Web.HttpContext.Current.Request.InputStream; byte[] requestByte = new byte[requestStream.Length]; requestStream.Read(requestByte, 0, (int)requestStream.Length); string requestStr = Encoding.UTF8.GetString(requestByte); if (!string.IsNullOrEmpty(requestStr)) { //封裝請(qǐng)求類 XmlDocument requestDocXml = new XmlDocument(); requestDocXml.LoadXml(requestStr); XmlElement rootElement = requestDocXml.DocumentElement; WxXmlModel WxXmlModel = new WxXmlModel(); if (rootElement != null) { WxXmlModel.ToUserName = rootElement.SelectSingleNode("ToUserName") == null ? "" : rootElement.SelectSingleNode("ToUserName").InnerText; WxXmlModel.FromUserName = rootElement.SelectSingleNode("FromUserName") == null ? "" : rootElement.SelectSingleNode("FromUserName").InnerText; WxXmlModel.CreateTime = rootElement.SelectSingleNode("CreateTime") == null ? "" : rootElement.SelectSingleNode("CreateTime").InnerText; WxXmlModel.MsgType = rootElement.SelectSingleNode("MsgType") == null ? "" : rootElement.SelectSingleNode("MsgType").InnerText; switch (WxXmlModel.MsgType) { case "text"://文本 WxXmlModel.Content = rootElement.SelectSingleNode("Content") == null ? "" : rootElement.SelectSingleNode("Content").InnerText; break; case "image"://圖片 WxXmlModel.PicUrl = rootElement.SelectSingleNode("PicUrl") == null ? "" : rootElement.SelectSingleNode("PicUrl").InnerText; break; case "event"://事件 WxXmlModel.Event = rootElement.SelectSingleNode("Event") == null ? "" : rootElement.SelectSingleNode("Event").InnerText; if (WxXmlModel.Event != "TEMPLATESENDJOBFINISH")//關(guān)注類型 { WxXmlModel.EventKey = rootElement.SelectSingleNode("EventKey") == null ? "" : rootElement.SelectSingleNode("EventKey").InnerText; } break; default: break; } } ResponseXML(WxXmlModel);//回復(fù)消息 } } catch (Exception ee) { //記錄錯(cuò)誤日志 } } /// <summary> /// 回復(fù)消息 /// </summary> /// <param name="WxXmlModel"></param> private void ResponseXML(WxXmlModel WxXmlModel) { string XML = ""; switch (WxXmlModel.MsgType) { case "text"://文本回復(fù) var info = oauth.GetUserInfo(Tools.WA_GetAccess_Token.IsExistAccess_Token(), WxXmlModel.FromUserName); Tools.WAEntity.OAuthUser user = Tools.JsonHelper.ParseFromJson<Tools.WAEntity.OAuthUser>(info); var content = WxXmlModel.Content.ToUpper(); string NcbActUrl = ConfigurationManager.AppSettings["NcbActUrl"]; string appid = ConfigurationManager.AppSettings["AppID"]; if (content.Contains("T"))//接受的文字如果包含T { //業(yè)務(wù)處理 } else { XML = ResponseMessage.ReText(WxXmlModel.FromUserName, WxXmlModel.ToUserName, "/:rose農(nóng)場大數(shù)據(jù)歡迎你!/:rose"); } break; case "event": switch (WxXmlModel.Event.ToLower()) { case "subscribe": if (string.IsNullOrEmpty(WxXmlModel.EventKey)) { XML = ResponseMessage.ReText(WxXmlModel.FromUserName, WxXmlModel.ToUserName, "關(guān)注成功!/:rose"); } else { XML = ResponseMessage.SubScanQrcode(WxXmlModel.FromUserName, WxXmlModel.ToUserName, WxXmlModel.EventKey);//掃描帶參數(shù)二維碼先關(guān)注后推送事件 } break; case "scan": XML = ResponseMessage.ScanQrcode(WxXmlModel.FromUserName, WxXmlModel.ToUserName, WxXmlModel.EventKey);//掃描帶參數(shù)二維碼已關(guān)注 直接推送事件 break; case "click"://處理單擊事件 if (WxXmlModel.EventKey == "p1") { //自己的業(yè)務(wù)邏輯 } else { //自己的業(yè)務(wù)邏輯 } break; case "unsubscribe"://取消關(guān)注 break; } break; default://默認(rèn)回復(fù) break; } Response.Write(XML);//輸出組織的XML信息 }
這就是菜單的信息處理,不明真相的群眾貌似會(huì)問那個(gè)所謂的ResponseMessage到底有幾個(gè)意思呢,OK,我已經(jīng)無力吐槽我這三天研究出來的微信公共平臺(tái)的東西了。
public class ResponseMessage { #region 接收的類型 /// <summary> /// 接收文本 /// </summary> /// <param name="FromUserName"></param> /// <param name="ToUserName"></param> /// <param name="Content"></param> /// <returns></returns> public static string GetTextTest(string FromUserName, string ToUserName, string Content, string key) { CommonMethod.WriteTxt(Content);//接收的文本消息 string XML = ""; switch (Content) { case "關(guān)鍵字": XML = ReText(FromUserName, ToUserName, "關(guān)鍵詞回復(fù)測試——興農(nóng)豐華:" + key); break; case "單圖文": XML = ReArticle(FromUserName, ToUserName, "測試標(biāo)題", "測試詳情——興農(nóng)豐華:" + key, "http://www.xnfhtech.com/templets/boze/images/20120130083143544.gif", "http://www.xnfhtech.com/"); break; default: XML = ReText(FromUserName, ToUserName, "無對(duì)應(yīng)關(guān)鍵字——興農(nóng)豐華:" + key); break; } return XML; } /// <summary> /// 未關(guān)注掃描帶參數(shù)二維碼 /// </summary> /// <param name="FromUserName"></param> /// <param name="ToUserName"></param> /// <param name="EventKey"></param> /// <returns></returns> public static string SubScanQrcode(string FromUserName, string ToUserName, string EventKey) { return ""; } /// <summary> /// 已關(guān)注掃描帶參數(shù)二維碼 /// </summary> /// <param name="FromUserName"></param> /// <param name="ToUserName"></param> /// <param name="EventKey"></param> /// <returns></returns> public static string ScanQrcode(string FromUserName, string ToUserName, string EventKey) { return ""; } #endregion #region 回復(fù)方式 /// <summary> /// 回復(fù)文本 /// </summary> /// <param name="FromUserName">發(fā)送給誰(openid)</param> /// <param name="ToUserName">來自誰(公眾賬號(hào)ID)</param> /// <param name="Content">回復(fù)類型文本</param> /// <returns>拼湊的XML</returns> public static string ReText(string FromUserName, string ToUserName, string Content) { string XML = "<xml><ToUserName><![CDATA[" + FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + ToUserName + "]]></FromUserName>";//發(fā)送給誰(openid),來自誰(公眾賬號(hào)ID) XML += "<CreateTime>" + CommonMethod.ConvertDateTimeInt(DateTime.Now) + "</CreateTime>";//回復(fù)時(shí)間戳 XML += "<MsgType><![CDATA[text]]></MsgType>";//回復(fù)類型文本 XML += "<Content><![CDATA[" + Content + "]]></Content><FuncFlag>0</FuncFlag></xml>";//回復(fù)內(nèi)容 FuncFlag設(shè)置為1的時(shí)候,自動(dòng)星標(biāo)剛才接收到的消息,適合活動(dòng)統(tǒng)計(jì)使用 return XML; } /// <summary> /// 回復(fù)單圖文 /// </summary> /// <param name="FromUserName">發(fā)送給誰(openid)</param> /// <param name="ToUserName">來自誰(公眾賬號(hào)ID)</param> /// <param name="Title">標(biāo)題</param> /// <param name="Description">詳情</param> /// <param name="PicUrl">圖片地址</param> /// <param name="Url">地址</param> /// <returns>拼湊的XML</returns> public static string ReArticle(string FromUserName, string ToUserName, string Title, string Description, string PicUrl, string Url) { string XML = "<xml><ToUserName><![CDATA[" + FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + ToUserName + "]]></FromUserName>";//發(fā)送給誰(openid),來自誰(公眾賬號(hào)ID) XML += "<CreateTime>" + CommonMethod.ConvertDateTimeInt(DateTime.Now) + "</CreateTime>";//回復(fù)時(shí)間戳 XML += "<MsgType><![CDATA[news]]></MsgType><Content><![CDATA[]]></Content><ArticleCount>1</ArticleCount><Articles>"; XML += "<item><Title><![CDATA[" + Title + "]]></Title><Description><![CDATA[" + Description + "]]></Description><PicUrl><![CDATA[" + PicUrl + "]]></PicUrl><Url><![CDATA[" + Url + "]]></Url></item>"; XML += "</Articles><FuncFlag>0</FuncFlag></xml>"; return XML; } /// <summary> /// 多圖文回復(fù) /// </summary> /// <param name="FromUserName">發(fā)送給誰(openid)</param> /// <param name="ToUserName">來自誰(公眾賬號(hào)ID)</param> /// <param name="ArticleCount">圖文數(shù)量</param> /// <param name="dtArticle"></param> /// <returns></returns> public static string ReArticle(string FromUserName, string ToUserName, int ArticleCount, System.Data.DataTable dtArticle) { string XML = "<xml><ToUserName><![CDATA[" + FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + ToUserName + "]]></FromUserName>";//發(fā)送給誰(openid),來自誰(公眾賬號(hào)ID) XML += "<CreateTime>" + CommonMethod.ConvertDateTimeInt(DateTime.Now) + "</CreateTime>";//回復(fù)時(shí)間戳 XML += "<MsgType><![CDATA[news]]></MsgType><Content><![CDATA[]]></Content><ArticleCount>" + ArticleCount + "</ArticleCount><Articles>"; foreach (System.Data.DataRow Item in dtArticle.Rows) { XML += "<item><Title><![CDATA[" + Item["Title"] + "]]></Title><Description><![CDATA[" + Item["Description"] + "]]></Description><PicUrl><![CDATA[" + Item["PicUrl"] + "]]></PicUrl><Url><![CDATA[" + Item["Url"] + "]]></Url></item>"; } XML += "</Articles><FuncFlag>0</FuncFlag></xml>"; return XML; } #endregion }
OK,加上自己的邏輯代碼,是不是完美的實(shí)現(xiàn)了回復(fù)?
第七坑,我真心不想計(jì)數(shù)了,你確定這個(gè)回復(fù)可以么?說真的,寶寶不確定,因?yàn)槟銓懥酥笾涝谀睦镎{(diào)用么,我的乖乖,尼瑪,服務(wù)器驗(yàn)證通過就把回復(fù)加上去是最保險(xiǎn)的。我已經(jīng)沒有節(jié)操了。
接下來我們說什么呢,我們就說說獲取用戶信息這個(gè)東西吧,因?yàn)槲覀冞@些東西一般都是基于H5頁面的。所以,就要用到之前我們配置的
這個(gè)東東,其實(shí)這個(gè)相對(duì)于前面的至少坑少了很多,真心的,寶寶就暫時(shí)不說他坑了。上個(gè)代碼吧。
//微信網(wǎng)頁授權(quán)2.0 public class Oauth3 { JavaScriptSerializer Jss = new JavaScriptSerializer(); public Oauth3() { } /// <summary> /// 對(duì)頁面是否要用授權(quán) /// </summary> /// <param name="Appid">微信應(yīng)用id</param> /// <param name="redirect_uri">回調(diào)頁面</param> /// <param name="scope">應(yīng)用授權(quán)作用域snsapi_userinfo(不彈出授權(quán)頁面,直接跳轉(zhuǎn),只能獲取用戶openid),snsapi_userinfo (彈出授權(quán)頁面,可通過openid拿到昵稱、性別、所在地。并且,即使在未關(guān)注的情況下,只要用戶授權(quán),也能獲取其信息)</param> /// <returns>授權(quán)地址</returns> public string GetCodeUrl(string Appid, string redirect_uri, string scope) { return string.Format("https://open.weixin.qq.com/connect/oauth3/authorize?appid={0}&redirect_uri={1}&response_type=code&scope={2}&state=STATE#wechat_redirect", Appid, redirect_uri, scope); } /// <summary> /// 對(duì)頁面是否要用授權(quán) /// </summary> /// <param name="Appid">微信應(yīng)用id</param> /// <param name="redirect_uri">回調(diào)頁面</param> /// <param name="scope">應(yīng)用授權(quán)作用域snsapi_userinfo(不彈出授權(quán)頁面,直接跳轉(zhuǎn),只能獲取用戶openid),snsapi_userinfo (彈出授權(quán)頁面,可通過openid拿到昵稱、性別、所在地。并且,即使在未關(guān)注的情況下,只要用戶授權(quán),也能獲取其信息)</param> /// <returns>授權(quán)地址</returns> public string GetCodeUrl(string Appid, string redirect_uri, string scope,string state) { return string.Format("https://open.weixin.qq.com/connect/oauth3/authorize?appid={0}&redirect_uri={1}&response_type=code&scope={2}&state={3}#wechat_redirect", Appid, redirect_uri, scope, state); } /// <summary> /// 用code換取openid 此方法一般是不獲取用戶昵稱時(shí)候使用 /// </summary> /// <param name="Appid"></param> /// <param name="Appsecret"></param> /// <param name="Code">回調(diào)頁面帶的code參數(shù)</param> /// <returns>微信用戶唯一標(biāo)識(shí)openid</returns> public string CodeGetOpenid(string Appid, string Appsecret, string Code) { string url = string.Format("https://api.weixin.qq.com/sns/oauth3/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code", Appid, Appsecret, Code); string ReText = CommonMethod.WebRequestPostOrGet(url, "");//post/get方法獲取信息 Dictionary<string, object> DicText = (Dictionary<string, object>)Jss.DeserializeObject(ReText); if (!DicText.ContainsKey("openid")) return ""; return DicText["openid"].ToString(); } /// <summary> ///用code換取獲取用戶信息(包括非關(guān)注用戶的) /// </summary> /// <param name="Appid"></param> /// <param name="Appsecret"></param> /// <param name="Code">回調(diào)頁面帶的code參數(shù)</param> /// <returns>獲取用戶信息(json格式)</returns> public string GetUserInfo(string Appid, string Appsecret, string Code) { string url = string.Format("https://api.weixin.qq.com/sns/oauth3/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code", Appid, Appsecret, Code); string ReText = CommonMethod.WebRequestPostOrGet(url, "");//post/get方法獲取信息 Dictionary<string, object> DicText = (Dictionary<string, object>)Jss.DeserializeObject(ReText); if (!DicText.ContainsKey("openid")) { log.Error("獲取openid失敗,錯(cuò)誤碼:" + DicText["errcode"].ToString()); return ""; } else { return CommonMethod.WebRequestPostOrGet("https://api.weixin.qq.com/sns/userinfo?access_token=" + DicText["access_token"] + "&openid=" + DicText["openid"] + "&lang=zh_CN", ""); } } /// <summary> /// 通過openId獲取用戶信息 /// </summary> /// <param name="accesstoken"></param> /// <param name="openid"></param> /// <returns></returns> public string GetUserInfo(string accesstoken, string openid) { string url = string.Format("https://api.weixin.qq.com/cgi-bin/user/info?access_token={0}&openid={1}&lang=zh_CN", accesstoken, openid); return CommonMethod.WebRequestPostOrGet(url, "");//post/get方法獲取信息 } }
我們需要調(diào)用的時(shí)候直接用里面的方法,獲取微信網(wǎng)頁授權(quán)即可,比如對(duì)于A控制器下面的B視圖要獲取授權(quán),并且要獲取用戶的相關(guān)信息,那么我們直接調(diào)用即可,如 GetCodeUrl(appid, "http://" + Url + "/A/B", "snsapi_userinfo")
在這里我還是吐槽一下吧。
第八坑,微信菜單JSON的url拼接,里面的前面不是加了js驗(yàn)證么,so,特么的,還是乖乖的加上http://。
不過這里授權(quán)之后,因?yàn)橛脩舻暮芏嘈畔⑽覀兌家玫?,這就是H5頁面?zhèn)髦档膯栴},我在項(xiàng)目里面用的是Session,直接寫一個(gè)公用方法,如果Session有值,則直接取值的。對(duì)于里面的一些東東,我想說明一下,并不是所有的代碼都要貼出來,我這邊的代碼只是我個(gè)人認(rèn)為需要貼出來的。所以里面的方法可能有大家看不到的,如果需要,可以留言本寶寶,謝謝。
public string getSession() { log.Error("GetSession"); string oauthStr = ""; try { if (Session != null && (Session["oauthStr"] == null || string.IsNullOrEmpty(Session["oauthStr"].ToString()))) { if (!string.IsNullOrEmpty(Request.QueryString["code"])) { Oauth3 oauth = new Oauth3(); string code = Convert.ToString(Request["code"]); oauthStr = oauth.GetUserInfo(ConfigurationManager.AppSettings["AppID"], ConfigurationManager.AppSettings["AppSecret"], code); Session["oauthStr"] = oauthStr; Tools.WAEntity.OAuthUser oAuthUser = new Tools.WAEntity.OAuthUser(); oAuthUser = Tools.JsonHelper.ParseFromJson<Tools.WAEntity.OAuthUser>(oauthStr); } return oauthStr; } else { Tools.WAEntity.OAuthUser oAuthUser = new Tools.WAEntity.OAuthUser(); oAuthUser = Tools.JsonHelper.ParseFromJson<Tools.WAEntity.OAuthUser>(Session["oauthStr"].ToString()); return Session["oauthStr"].ToString(); } } catch (Exception e) { log.Error(e.ToString()); return oauthStr; }; }
然后每次遇到需要獲取信息的頁面,我一般都是調(diào)用這個(gè)就可以了。
基本上剩下的都是我們自己要處理的業(yè)務(wù)邏輯了,繼續(xù)說坑吧。
第九坑,微信上傳圖片,坑的絕對(duì)不只是自己。對(duì)于這個(gè)寶寶真的信了,不管你信不信。特么的圖片不能for循環(huán)上傳。當(dāng)然,這個(gè)只限蘋果機(jī)型,大Android還是沒有問題的。
前面說到了JS安全驗(yàn)證的問題,這里就是調(diào)用這些個(gè)驗(yàn)證,請(qǐng)求一些應(yīng)該的權(quán)限,然后獲取圖片信息等等。
放心好了,寶寶現(xiàn)在都是上圖說話,沒圖說個(gè)小弟弟呀。。。。。
我們繼續(xù)回來看代碼。
先來個(gè)處理Json的
public class JsApi { JavaScriptSerializer Jss = new JavaScriptSerializer(); public JsApi() { } const string URL_FORMAT_TICKET = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi"; #region 驗(yàn)證JsApi權(quán)限配置 /// <summary> /// 獲取JsApi權(quán)限配置的數(shù)組/四個(gè)參數(shù) /// </summary> /// <param name="Appid">應(yīng)用id</param> /// <param name="Appsecret">密鑰</param> /// <returns>json格式的四個(gè)參數(shù)</returns> public string GetJsApiInfo(string Appid, string Appsecret) { string jsapi_ticket = ""; //ticket 緩存7200秒 if (System.Web.HttpContext.Current.Session["jsapi_ticket"] == null) { string ticketurl = string.Format(URL_FORMAT_TICKET, BasicApi.GetAccessToken(Appid, Appsecret));//"https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + GetAccessToken(Appid, Appsecret) + "&type=jsapi" jsapi_ticket = CommonMethod.WebRequestPostOrGet(ticketurl, "");//BasicApi.GetTokenSession System.Web.HttpContext.Current.Session["jsapi_ticket"] = jsapi_ticket; System.Web.HttpContext.Current.Session.Timeout = 7200; BasicApi.WriteTxt("jsapi_ticket1:" + jsapi_ticket); } else { jsapi_ticket = System.Web.HttpContext.Current.Session["jsapi_ticket"].ToString(); BasicApi.WriteTxt("jsapi_ticket2:" + jsapi_ticket); } Dictionary<string, object> respDic = (Dictionary<string, object>)Jss.DeserializeObject(jsapi_ticket); jsapi_ticket = respDic["ticket"].ToString();//獲取ticket string timestamp = CommonMethod.ConvertDateTimeInt(DateTime.Now).ToString();//生成簽名的時(shí)間戳 string nonceStr = CommonMethod.GetRandCode(16);//生成簽名的隨機(jī)串 string url = System.Web.HttpContext.Current.Request.Url.AbsoluteUri.ToString();//當(dāng)前的地址 BasicApi.WriteTxt("url:" + url); string[] ArrayList = { "jsapi_ticket=" + jsapi_ticket, "timestamp=" + timestamp, "noncestr=" + nonceStr, "url=" + url }; Array.Sort(ArrayList); string signature = string.Join("&", ArrayList); signature = FormsAuthentication.HashPasswordForStoringInConfigFile(signature, "SHA1").ToLower(); string r = "{\"appId\":\"" + Appid + "\",\"timestamp\":" + timestamp + ",\"nonceStr\":\"" + nonceStr + "\",\"signature\":\"" + signature + "\",\"jsApiList\":[\"chooseImage\",\"previewImage\",\"uploadImage\",\"downloadImage\",\"scanQRCode\",\"onMenuShareQQ\"]}"; BasicApi.WriteTxt("r:" + r.Replace(" ", "")); return r.Replace(" ", ""); } }
然后看具體調(diào)用。
后臺(tái)代碼其實(shí)很簡單的,直接輸出配置文件,然后前臺(tái)js直接調(diào)用即可。
JsApi jsApi = new JsApi(); string config = jsApi.GetJsApiInfo(appId, appSecret); ViewBag.config = config;
前臺(tái)代碼,其實(shí)也不難,這個(gè)有官方的例子的。
<script type="text/javascript"> wx.config(@Html.Raw(ViewBag.config));//后臺(tái)傳遞的微信配置文件 wx.ready(function () { $("#avatar").click(function () { wx.chooseImage({ count: 1, // 圖片數(shù)量 默認(rèn)9 sizeType: ['compressed'], // 可以指定是原圖還是壓縮圖,默認(rèn)二者都有'original', sourceType: ['album', 'camera'], // 可以指定來源是相冊(cè)還是相機(jī),默認(rèn)二者都有 success: function (res) { var localIds = res.localIds; // 返回選定照片的本地ID列表,localId可以作為img標(biāo)簽的src屬性顯示圖片 wx.uploadImage({ localId: '' + localIds, isShowProgressTips: 1, success: function (res) { serverId = res.serverId; getWxPhoto(serverId); } }); } }); }); }); wx.error(function (res) { alert("接口驗(yàn)證失敗,詳細(xì)信息:\n" + JSON.stringify(res)); }); var types = 1; function getWxPhoto(mediaId) { $.ajax({ async: false, type: "post", url: "/ActivityRegistration/DownloadWxPhoto",//自己的處理方法 data: { mediaId: mediaId, types: types }, success: function (data) { $("#imageico").val(data.result); $("#hed_pic").attr('src', ".." + data.result); $("#hed_pic").attr('alt', "avatarImg"); } }); } </script>
OK,后臺(tái)方法其實(shí)也很簡單,就是一個(gè)二進(jìn)制文件處理,不對(duì),簡單個(gè)蛋蛋,特么的,因?yàn)槁窂降膯栴},坑了寶寶一個(gè)小時(shí),特么的。還有這里建議,等微信圖片下載完成之后再給前臺(tái)加載圖片,保證每一個(gè)圖片都加載完成,保證后臺(tái)的圖片的上傳完成。
/// <summary> /// 下載多媒體文件 /// </summary> /// <param name="userName">公眾號(hào)</param> /// <param name="mediaId">媒體ID</param> /// <param name="data">返回下載是否成功</param> /// <param name="types">添加的圖片類型</param> /// <returns>返回多媒體文件數(shù)據(jù);如果下載失敗,返回null。</returns> public JsonResult DownloadWxPhoto(string mediaId, int types) { ErrorMessage errorMessage; string access_token = BasicApi.GetAccessToken(ConfigurationManager.AppSettings["AppID"], ConfigurationManager.AppSettings["AppSecret"]); byte[] data = MediaHelper.Download(access_token, mediaId, out errorMessage); string files = String.Empty, fileName = String.Empty; files = Server.MapPath("~/Wxinphoto/"); if (!Directory.Exists(files)) { Directory.CreateDirectory(files); } fileName = files + DateTime.Now.Ticks + ".jpg"; if (data != null) { bool flag = writeFile(data, fileName); if (flag) { errorMessage = new ErrorMessage(ErrorMessage.SuccessCode, "下載多媒體文件成功。"); } else { errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "從微信服務(wù)器下載多媒體文件失敗。"); } } else errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "從微信服務(wù)器下載多媒體文件失敗。"); return Json(new { result = "/" + urlconvertor(fileName), errorMessage = errorMessage }); } //讀filename到byte[] private byte[] ReadFile(string fileName) { FileStream pFileStream = null; byte[] pReadByte = new byte[0]; try { pFileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read); BinaryReader r = new BinaryReader(pFileStream); r.BaseStream.Seek(0, SeekOrigin.Begin); //將文件指針設(shè)置到文件開 pReadByte = r.ReadBytes((int)r.BaseStream.Length); return pReadByte; } catch { return pReadByte; } finally { if (pFileStream != null) pFileStream.Close(); } } //寫byte[]到fileName private bool writeFile(byte[] pReadByte, string fileName) { FileStream pFileStream = null; try { pFileStream = new FileStream(fileName, FileMode.OpenOrCreate); pFileStream.Write(pReadByte, 0, pReadByte.Length); } catch { return false; } finally { if (pFileStream != null) pFileStream.Close(); } return true; } /// <summary> /// 判斷目標(biāo)字節(jié)數(shù)組是否位于源字節(jié)數(shù)組的開始 /// </summary> /// <param name="source">源字節(jié)數(shù)組</param> /// <param name="target">目標(biāo)字節(jié)數(shù)組</param> /// <returns>返回目標(biāo)字節(jié)數(shù)組是否位于源字節(jié)數(shù)組的開始</returns> private bool StartsWithBytes(byte[] source, byte[] target) { if (source == null && target == null) return true; if (source == null && target != null || source != null && target == null) return false; if (source.Length < target.Length) return false; bool startsWith = true; for (int i = 0; i < target.Length; i++) { if (source[i] != target[i]) { startsWith = false; break; } } return startsWith; }
是不是以為這就算完事了,我的乖乖,頭像上傳了,微信攝像頭也特么該調(diào)用的調(diào)用了,寶寶好幸福,寶寶也是牛人一個(gè)了,記住前面的東東,寶寶還沒有說坑呢。
來重復(fù)我們的第九個(gè)坑,特么的,你JS寫個(gè)for循環(huán)要是能循環(huán)把圖片上傳到后臺(tái),寶寶也服氣,真的,寶寶服氣。
直接說吧,最后我自己想了下,也和隊(duì)友討論了下,可能是因?yàn)槲⑿庞惺裁打?yàn)證,導(dǎo)致之后一張圖片上傳成功之后,才能進(jìn)行一張,但是我們Iphone就是特么的特例,大Android沒用問題的,就是Iphone有了問題,而且問題不小,上傳四張圖片吧,老特么是最后一張,最后,找到了萬能的網(wǎng)友,感謝你,不過寶寶已經(jīng)忘記了在哪里找到的了,尷尬了。。。。。。。。。。。
<script type="text/javascript"> var types = 2; var urlList=""; var i = 0; function up(resurl) { if (i < resurl.localIds.length) { // 上傳照片resu.localIds[i] wx.uploadImage({ localId: '' + resurl.localIds[i], isShowProgressTips: 1, success: function (res) { // alert("res.serverId:" + res.serverId); mediaId = res.serverId; $.ajax({ async: false, type: "post", url: "/ActivityRegistration/DownloadWxPhoto", data: { mediaId: mediaId, types: types }, success: function (data) { $("#picPath").append('<li><div class="imgbox"><img src="/img/cechanadd.png" id="picture' + i + '" alt="" /></div></li>'); $("#picture" + i).attr('src', data.result); $("#picPath").append('<input value=' + data.result + ' type="hidden" id="picurl' + i + '" class="picclass" />'); i++; if (i == resurl.localIds.length - 1) { $("#picPath").append('<li><div class="imgbox"><img src="/img/cechanadd.png" id="picture" alt="" /></div></li>'); } up(resurl); } }); } }); } else { i = 0; } } //上傳圖片 wx.config(@Html.Raw(ViewBag.config)); wx.ready(function () { $("#picPath").click(function () { wx.chooseImage({ count: 3, // 默認(rèn)9 sizeType: ['compressed'], // 可以指定是原圖還是壓縮圖,默認(rèn)二者都有'original', sourceType: ['album', 'camera'], // 可以指定來源是相冊(cè)還是相機(jī),默認(rèn)二者都有 success: function (resu) { var localIds = resu.localIds; // 返回選定照片的本地ID列表,localId可以作為img標(biāo)簽的src屬性顯示圖片 if (localIds.indexOf("wxlocalresource") != -1) { localIds = localIds.replace("wxlocalresource", "wxLocalResource"); } @(index += 1) if (localIds != '') { $("#picPath").html(""); var sear = new RegExp(','); if (sear.test(localIds)) { up(resu); } else { $("#picPath").append(' <li><div class="imgbox"><img src="/img/cechanadd.png" id="picture' + '@index' + '" alt="" " /></div></li>'); $("#picture" + "@index").attr('src', localIds); // 上傳照片 wx.uploadImage({ localId: '' + localIds, isShowProgressTips: 1, success: function (res) { mediaId = res.serverId; $.ajax({ async: false, type: "post", url: "/ActivityRegistration/DownloadWxPhoto", data: { mediaId: mediaId, types: types }, success: function (data) { $("#picPath").append('<input value=' + data.result + ' type="hidden" id="picurl' + @index + '" class="picclass" />'); $("#picPath").append('<li><div class="imgbox"><img src="/img/cechanadd.png" id="picture" alt="" /></div></li>'); } }); } }); } // $("#picPath").append('<li><div class="imgbox"><img src="/img/cechanadd.png" id="picture" alt="" /></div></li>'); } } }); }); }); wx.error(function (res) { alert("接口驗(yàn)證失敗,詳細(xì)信息:\n" + JSON.stringify(res)); }); </script>
請(qǐng)記住,遞歸就特么可以了。
說到這里,寶寶已經(jīng)不想多說什么了,特么的產(chǎn)品你能不能不裝逼,你特么見過那個(gè)微信能回復(fù)一個(gè)信息直接跳轉(zhuǎn)網(wǎng)頁的,你咋不去屎呢,聯(lián)想到前幾天大阿里的月餅時(shí)間,突然感覺我們程序員挺悲劇的,成功的都是特么的產(chǎn)品,然后出問題的都是我們程序員的鍋?試問一下,這個(gè)鍋真心我們程序員該背么。
算了,還是不吐槽了,已經(jīng)無力了。。。。寶寶92年降臨,現(xiàn)在確實(shí)82年的皮膚呀,唉,寶寶累了,真的。
順便給點(diǎn)H5頁面的建議吧。比如當(dāng)點(diǎn)擊返回鍵的時(shí)候,我們需要刷新頁面的時(shí)候,就是所謂的判斷頁面要不要刷新,這里有很多種方法,但是微信里面寶寶還是覺得這么干靠譜。
<script type="text/javascript"> if (window.name != "hasLoad") { location.reload(); window.name = "hasLoad"; } else { window.name = ""; } </script>
還有,那個(gè)微信執(zhí)行完成之后想直接退出當(dāng)前界面進(jìn)入微信公眾號(hào)界面的,直接調(diào)用微信的一個(gè)內(nèi)置的方法即可。記得寫到<script></script>里面。
WeixinJSBridge.call('closeWindow'); //這是微信關(guān)閉當(dāng)前網(wǎng)頁
這么自信的以為自己搞定了所有,你跑呀,你要跑起來,嗯哼,別不服氣。
微信公眾賬號(hào)指第十坑,我自己加的,哈哈,就是前面的JS驗(yàn)證的時(shí)候,你不要頭文件,怎么搞定這些事情,哈哈。是不是寶寶贏了。Oh perfect,I like it。
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
看完上述內(nèi)容,你們掌握php微信公眾賬號(hào)開發(fā)中容易遇到的坑有哪些的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。