程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP綜合 >> php微信公眾賬號開發之五個坑(二)

php微信公眾賬號開發之五個坑(二)

編輯:PHP綜合

上篇說到微信公眾賬號的幾個坑,前面五個,已經說到菜單,寶寶繼續往下贅述了。可惜,還不知道寶寶的寶寶到底是不是心疼寶寶呢,完了,我凌亂了。。。 

回到正題,我們就不吐槽其他的了,上一篇說到微信的菜單了,那麼,我們現在說說菜單回復等等的吧。 

菜單回復是需要處理XML文件的,我們根據微信返回的XML文件,可以得到每個微信用戶相對於微信公眾號的唯一標識。微信公眾平台的機制簡單的將就是我們自己輸出固定格式的xml文件,然後微信APP負責解析,得到我們想要的信息,然後對信息統一處理。 

第六坑,如果你看微信文檔,那麼,絕對坑死你,上圖。這裡的ToUserName和FromUserName一定特麼的要分清楚了,記住,千萬不要寫反了,用戶對於微信而言是A→B,那麼微信對於用戶就是反著來的,貌似現在應該說清楚了。

/// <summary>
 /// 接收微信發送的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))
  { 

  //封裝請求類
  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")//關注類型
    {
    WxXmlModel.EventKey = rootElement.SelectSingleNode("EventKey") == null ? "" : rootElement.SelectSingleNode("EventKey").InnerText;
    }
    break;
   default:
    break;
   }
  }
  ResponseXML(WxXmlModel);//回復消息
  }

 

 }
 catch (Exception ee)
 {
  //記錄錯誤日志
 }
 }

 /// <summary>
 /// 回復消息
 /// </summary>
 /// <param name="WxXmlModel"></param>
 private void ResponseXML(WxXmlModel WxXmlModel)
 {
 string XML = "";
 switch (WxXmlModel.MsgType)
 {
  case "text"://文本回復
  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
  {
   //業務處理
  }
  else
  {
   XML = ResponseMessage.ReText(WxXmlModel.FromUserName, WxXmlModel.ToUserName, "/:rose農場大數據歡迎你!/:rose");

  }
  break;
  case "event":
  switch (WxXmlModel.Event.ToLower())
  {
   case "subscribe":
   if (string.IsNullOrEmpty(WxXmlModel.EventKey))
   {
    XML = ResponseMessage.ReText(WxXmlModel.FromUserName, WxXmlModel.ToUserName, "關注成功!/:rose");

   }
   else
   {
    XML = ResponseMessage.SubScanQrcode(WxXmlModel.FromUserName, WxXmlModel.ToUserName, WxXmlModel.EventKey);//掃描帶參數二維碼先關注後推送事件
   }
   break;
   case "scan":
   XML = ResponseMessage.ScanQrcode(WxXmlModel.FromUserName, WxXmlModel.ToUserName, WxXmlModel.EventKey);//掃描帶參數二維碼已關注 直接推送事件
   break;
   case "click"://處理單擊事件
   if (WxXmlModel.EventKey == "p1")
   {
    //自己的業務邏輯
   }
   else
   {
    //自己的業務邏輯
   }
   break;
   case "unsubscribe"://取消關注
   break;
  }
  break;
  default://默認回復
  break;
 }
 Response.Write(XML);//輸出組織的XML信息

 }

這就是菜單的信息處理,不明真相的群眾貌似會問那個所謂的ResponseMessage到底有幾個意思呢,OK,我已經無力吐槽我這三天研究出來的微信公共平台的東西了。 

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 "關鍵字":
  XML = ReText(FromUserName, ToUserName, "關鍵詞回復測試——興農豐華:" + key);
  break;
  case "單圖文":
  XML = ReArticle(FromUserName, ToUserName, "測試標題", "測試詳情——興農豐華:" + key, "http://www.xnfhtech.com/templets/boze/images/20120130083143544.gif", "http://www.xnfhtech.com/");
  break;
  default:
  XML = ReText(FromUserName, ToUserName, "無對應關鍵字——興農豐華:" + key);
  break;
 }
 return XML;

 }

 /// <summary>
 /// 未關注掃描帶參數二維碼
 /// </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>
 /// 已關注掃描帶參數二維碼
 /// </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 回復方式
 /// <summary>
 /// 回復文本
 /// </summary>
 /// <param name="FromUserName">發送給誰(openid)</param>
 /// <param name="ToUserName">來自誰(公眾賬號ID)</param>
 /// <param name="Content">回復類型文本</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>";//發送給誰(openid),來自誰(公眾賬號ID)
 XML += "<CreateTime>" + CommonMethod.ConvertDateTimeInt(DateTime.Now) + "</CreateTime>";//回復時間戳
 XML += "<MsgType><![CDATA[text]]></MsgType>";//回復類型文本
 XML += "<Content><![CDATA[" + Content + "]]></Content><FuncFlag>0</FuncFlag></xml>";//回復內容 FuncFlag設置為1的時候,自動星標剛才接收到的消息,適合活動統計使用
 return XML;

 }
 

 /// <summary>
 /// 回復單圖文
 /// </summary>
 /// <param name="FromUserName">發送給誰(openid)</param>
 /// <param name="ToUserName">來自誰(公眾賬號ID)</param>
 /// <param name="Title">標題</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>";//發送給誰(openid),來自誰(公眾賬號ID)
 XML += "<CreateTime>" + CommonMethod.ConvertDateTimeInt(DateTime.Now) + "</CreateTime>";//回復時間戳
 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>
 /// 多圖文回復
 /// </summary>
 /// <param name="FromUserName">發送給誰(openid)</param>
 /// <param name="ToUserName">來自誰(公眾賬號ID)</param>
 /// <param name="ArticleCount">圖文數量</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>";//發送給誰(openid),來自誰(公眾賬號ID)
 XML += "<CreateTime>" + CommonMethod.ConvertDateTimeInt(DateTime.Now) + "</CreateTime>";//回復時間戳
 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,加上自己的邏輯代碼,是不是完美的實現了回復? 

第七坑,我真心不想計數了,你確定這個回復可以麼?說真的,寶寶不確定,因為你寫了之後知道在哪裡調用麼,我的乖乖,尼瑪,服務器驗證通過就把回復加上去是最保險的。我已經沒有節操了。

接下來我們說什麼呢,我們就說說獲取用戶信息這個東西吧,因為我們這些東西一般都是基於H5頁面的。所以,就要用到之前我們配置的

這個東東,其實這個相對於前面的至少坑少了很多,真心的,寶寶就暫時不說他坑了。上個代碼吧。 

//微信網頁授權2.0
public class Oauth2
{
 JavaScriptSerializer Jss = new JavaScriptSerializer();
 public Oauth2() { }
 

 /// <summary>
 /// 對頁面是否要用授權
 /// </summary>
 /// <param name="Appid">微信應用id</param>
 /// <param name="redirect_uri">回調頁面</param>
 /// <param name="scope">應用授權作用域snsapi_userinfo(不彈出授權頁面,直接跳轉,只能獲取用戶openid),snsapi_userinfo (彈出授權頁面,可通過openid拿到昵稱、性別、所在地。並且,即使在未關注的情況下,只要用戶授權,也能獲取其信息)</param>
 /// <returns>授權地址</returns>

 public string GetCodeUrl(string Appid, string redirect_uri, string scope)
 {
 return string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope={2}&state=STATE#wechat_redirect", Appid, redirect_uri, scope);
 }

 

 /// <summary>
 /// 對頁面是否要用授權
 /// </summary>
 /// <param name="Appid">微信應用id</param>
 /// <param name="redirect_uri">回調頁面</param>
 /// <param name="scope">應用授權作用域snsapi_userinfo(不彈出授權頁面,直接跳轉,只能獲取用戶openid),snsapi_userinfo (彈出授權頁面,可通過openid拿到昵稱、性別、所在地。並且,即使在未關注的情況下,只要用戶授權,也能獲取其信息)</param>
 /// <returns>授權地址</returns>
 public string GetCodeUrl(string Appid, string redirect_uri, string scope,string state)
 {
 return string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope={2}&state={3}#wechat_redirect", Appid, redirect_uri, scope, state);
 }

 

 /// <summary>
 /// 用code換取openid 此方法一般是不獲取用戶昵稱時候使用
 /// </summary>
 /// <param name="Appid"></param>
 /// <param name="Appsecret"></param>
 /// <param name="Code">回調頁面帶的code參數</param>
 /// <returns>微信用戶唯一標識openid</returns>
 public string CodeGetOpenid(string Appid, string Appsecret, string Code)
 {
 string url = string.Format("https://api.weixin.qq.com/sns/oauth2/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換取獲取用戶信息(包括非關注用戶的)
 /// </summary>
 /// <param name="Appid"></param>
 /// <param name="Appsecret"></param>
 /// <param name="Code">回調頁面帶的code參數</param>
 /// <returns>獲取用戶信息(json格式)</returns>

 public string GetUserInfo(string Appid, string Appsecret, string Code)
 {

 string url = string.Format("https://api.weixin.qq.com/sns/oauth2/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失敗,錯誤碼:" + 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方法獲取信息

 }

}

我們需要調用的時候直接用裡面的方法,獲取微信網頁授權即可,比如對於A控制器下面的B視圖要獲取授權,並且要獲取用戶的相關信息,那麼我們直接調用即可,如 GetCodeUrl(appid, "http://" + Url + "/A/B", "snsapi_userinfo")

在這裡我還是吐槽一下吧。 

第八坑,微信菜單JSON的url拼接,裡面的前面不是加了js驗證麼,so,特麼的,還是乖乖的加上http://。 

不過這裡授權之後,因為用戶的很多信息我們都要用到,這就是H5頁面傳值的問題,我在項目裡面用的是Session,直接寫一個公用方法,如果Session有值,則直接取值的。對於裡面的一些東東,我想說明一下,並不是所有的代碼都要貼出來,我這邊的代碼只是我個人認為需要貼出來的。所以裡面的方法可能有大家看不到的,如果需要,可以留言本寶寶,謝謝。 

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"]))
  {
  Oauth2 oauth = new Oauth2();
  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; };

}

然後每次遇到需要獲取信息的頁面,我一般都是調用這個就可以了。 

基本上剩下的都是我們自己要處理的業務邏輯了,繼續說坑吧。 

第九坑,微信上傳圖片,坑的絕對不只是自己。對於這個寶寶真的信了,不管你信不信。特麼的圖片不能for循環上傳。當然,這個只限蘋果機型,大Android還是沒有問題的。
前面說到了JS安全驗證的問題,這裡就是調用這些個驗證,請求一些應該的權限,然後獲取圖片信息等等。 

放心好了,寶寶現在都是上圖說話,沒圖說個小弟弟呀。。。。。 

我們繼續回來看代碼。 

先來個處理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 驗證JsApi權限配置
 /// <summary>
 /// 獲取JsApi權限配置的數組/四個參數
 /// </summary>
 /// <param name="Appid">應用id</param>
 /// <param name="Appsecret">密鑰</param>
 /// <returns>json格式的四個參數</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();//生成簽名的時間戳
 string nonceStr = CommonMethod.GetRandCode(16);//生成簽名的隨機串
 string url = System.Web.HttpContext.Current.Request.Url.AbsoluteUri.ToString();//當前的地址
 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(" ", "");

 }

}

然後看具體調用。

後台代碼其實很簡單的,直接輸出配置文件,然後前台js直接調用即可。 

JsApi jsApi = new JsApi();
string config = jsApi.GetJsApiInfo(appId, appSecret);
ViewBag.config = config;

前台代碼,其實也不難,這個有官方的例子的。 

<script type="text/javascript">
 wx.config(@Html.Raw(ViewBag.config));//後台傳遞的微信配置文件
 wx.ready(function () {
 $("#avatar").click(function () {
  wx.chooseImage({
  count: 1, // 圖片數量 默認9
  sizeType: ['compressed'], // 可以指定是原圖還是壓縮圖,默認二者都有'original',
  sourceType: ['album', 'camera'], // 可以指定來源是相冊還是相機,默認二者都有
  success: function (res) {
   var localIds = res.localIds; // 返回選定照片的本地ID列表,localId可以作為img標簽的src屬性顯示圖片
   wx.uploadImage({
   localId: '' + localIds,
   isShowProgressTips: 1,
   success: function (res) {
    serverId = res.serverId;
    getWxPhoto(serverId);

   }

   });

  }

  });

 });

 });

 wx.error(function (res) {
 alert("接口驗證失敗,詳細信息:\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,後台方法其實也很簡單,就是一個二進制文件處理,不對,簡單個蛋蛋,特麼的,因為路徑的問題,坑了寶寶一個小時,特麼的。還有這裡建議,等微信圖片下載完成之後再給前台加載圖片,保證每一個圖片都加載完成,保證後台的圖片的上傳完成。 

/// <summary>
/// 下載多媒體文件
/// </summary>
/// <param name="userName">公眾號</param>
/// <param name="mediaId">媒體ID</param>
/// <param name="data">返回下載是否成功</param>
/// <param name="types">添加的圖片類型</param>
/// <returns>返回多媒體文件數據;如果下載失敗,返回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, "從微信服務器下載多媒體文件失敗。");
 }

 }
 else
 errorMessage = new ErrorMessage(ErrorMessage.ExceptionCode, "從微信服務器下載多媒體文件失敗。");
 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); //將文件指針設置到文件開
 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>
/// 判斷目標字節數組是否位於源字節數組的開始
/// </summary>
/// <param name="source">源字節數組</param>
/// <param name="target">目標字節數組</param>
/// <returns>返回目標字節數組是否位於源字節數組的開始</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;

}

 是不是以為這就算完事了,我的乖乖,頭像上傳了,微信攝像頭也特麼該調用的調用了,寶寶好幸福,寶寶也是牛人一個了,記住前面的東東,寶寶還沒有說坑呢。
來重復我們的第九個坑,特麼的,你JS寫個for循環要是能循環把圖片上傳到後台,寶寶也服氣,真的,寶寶服氣。 

直接說吧,最後我自己想了下,也和隊友討論了下,可能是因為微信有什麼驗證,導致之後一張圖片上傳成功之後,才能進行一張,但是我們Iphone就是特麼的特例,大Android沒用問題的,就是Iphone有了問題,而且問題不小,上傳四張圖片吧,老特麼是最後一張,最後,找到了萬能的網友,感謝你,不過寶寶已經忘記了在哪裡找到的了,尴尬了。。。。。。。。。。。 

<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, // 默認9
   sizeType: ['compressed'], // 可以指定是原圖還是壓縮圖,默認二者都有'original',
   sourceType: ['album', 'camera'], // 可以指定來源是相冊還是相機,默認二者都有
   success: function (resu) {
   var localIds = resu.localIds; // 返回選定照片的本地ID列表,localId可以作為img標簽的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("接口驗證失敗,詳細信息:\n" + JSON.stringify(res));
 });
 </script>

請記住,遞歸就特麼可以了。

說到這裡,寶寶已經不想多說什麼了,特麼的產品你能不能不裝逼,你特麼見過那個微信能回復一個信息直接跳轉網頁的,你咋不去屎呢,聯想到前幾天大阿裡的月餅時間,突然感覺我們程序員挺悲劇的,成功的都是特麼的產品,然後出問題的都是我們程序員的鍋?試問一下,這個鍋真心我們程序員該背麼。 

算了,還是不吐槽了,已經無力了。。。。寶寶92年降臨,現在確實82年的皮膚呀,唉,寶寶累了,真的。 

順便給點H5頁面的建議吧。比如當點擊返回鍵的時候,我們需要刷新頁面的時候,就是所謂的判斷頁面要不要刷新,這裡有很多種方法,但是微信裡面寶寶還是覺得這麼干靠譜。 

<script type="text/javascript">
 if (window.name != "hasLoad") {
 location.reload();
 window.name = "hasLoad";
 } else {
 window.name = "";
 }
</script>

還有,那個微信執行完成之後想直接退出當前界面進入微信公眾號界面的,直接調用微信的一個內置的方法即可。記得寫到<script></script>裡面。 

WeixinJSBridge.call('closeWindow'); //這是微信關閉當前網頁

這麼自信的以為自己搞定了所有,你跑呀,你要跑起來,嗯哼,別不服氣。 

微信公眾賬號指第十坑,我自己加的,哈哈,就是前面的JS驗證的時候,你不要頭文件,怎麼搞定這些事情,哈哈。是不是寶寶贏了。Oh  perfect,I like it。

<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

 這個東西一定不能忘記哈。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持。

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