起因:最近工作上有一個項目需要在公眾號頁面用到評論然后發起微信支付的操作,之前未接觸過微信,
特別記錄一下開發過程的一些細節
stemp1:閱讀微信公眾號開發文檔,十分重要
登錄授權:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN
微信支付:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_4
2個頁面講解參數是比較清晰的,但是細節方面其實很多開發者都查閱了很多其他文獻才能繼續調試開發
stemp2: 登錄授權需要前台獲取到code 然后提交給后台,后台拿到code才能提交到微信拿到
//通過code獲取openid
private string getToken(string code)
{
string _url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appid + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code";
WebClient wc = new WebClient();
//取得微信返回的openid,access_token數據
String strReturn = wc.DownloadString(_url);
return strReturn;
}
此處直接使用WebClient,是比較笨的方法,后來使用了幾個統一的方法
多參數使用 string param = JSONHelper.ObjectToJSON(obj);轉化后的串

1 /// <summary> 2 /// POST方式調用接口 3 /// </summary> 4 /// <param name="Url">要請求Url</param> 5 /// <returns></returns> 6 public static string RequestUrlByPOST(string Url, string postData = "UTF-8") 7 { 8 string strHtml = ""; 9 try 10 { 11 HttpWebRequest wr; 12 System.GC.Collect(); 13 wr = (HttpWebRequest)WebRequest.Create(Url); 14 wr.Headers.Add("charset:utf-8"); 15 var encoding = Encoding.GetEncoding("utf-8"); 16 byte[] bytes = encoding.GetBytes(postData); 17 wr.Method = "POST"; 18 wr.Timeout = Int32.MaxValue; 19 wr.Credentials = CredentialCache.DefaultCredentials; 20 wr.ContentType = "text/xml"; 21 wr.ContentLength = bytes.Length; 22 wr.ServicePoint.Expect100Continue = false; 23 using (Stream requestStream = wr.GetRequestStream()) 24 { 25 requestStream.Write(bytes, 0, bytes.Length); 26 } 27 using (HttpWebResponse response = (HttpWebResponse)wr.GetResponse()) 28 { 29 if (response.StatusCode == HttpStatusCode.OK && wr.HaveResponse) 30 { 31 if (response != null) 32 { 33 using (Stream stream = response.GetResponseStream())//獲取返回的字符流格式 34 { 35 using (StreamReader sr = new StreamReader(stream, System.Text.Encoding.UTF8))//解決亂碼:設置utf-8字符格式 36 { 37 if (sr != null) 38 { 39 strHtml = sr.ReadToEnd(); 40 } 41 } 42 } 43 } 44 } 45 } 46 } 47 catch (WebException ex) 48 { 49 throw new Exception(ex.Message); 50 } 51 return strHtml; 52 } 53 54 /// <summary> 55 /// POST方式調用接口 56 /// </summary> 57 /// <param name="Url">要請求Url</param> 58 /// <returns></returns> 59 public static string RequestUrlByPOSTWithParam(string Url, string Parameter) 60 { 61 string strHtml = ""; 62 try 63 { 64 HttpWebRequest wr; 65 System.GC.Collect(); 66 wr = (HttpWebRequest)WebRequest.Create(Url); 67 //ASCIIEncoding encoding = new ASCIIEncoding(); 68 byte[] bytes = Encoding.UTF8.GetBytes(Parameter);//encoding.GetBytes(codestr); 69 wr.Method = "POST"; 70 //wr.KeepAlive = false; 71 //wr.ServicePoint.ConnectionLimit = 300; 72 //wr.AllowAutoRedirect = true; 73 //wr.ReadWriteTimeout = 10000; 74 wr.Timeout = Int32.MaxValue; 75 wr.Credentials = CredentialCache.DefaultCredentials; 76 wr.ContentType = "application/json"; 77 wr.Accept = "application/xml"; 78 wr.Headers.Add("X-Auth-Token", HttpUtility.UrlEncode("OpenStack")); 79 wr.ContentLength = bytes.Length; 80 wr.ServicePoint.Expect100Continue = false; 81 using (Stream requestStream = wr.GetRequestStream()) 82 { 83 requestStream.Write(bytes, 0, bytes.Length); 84 } 85 using (HttpWebResponse response = (HttpWebResponse)wr.GetResponse()) 86 { 87 if (response.StatusCode == HttpStatusCode.OK && wr.HaveResponse) 88 { 89 if (response != null) 90 { 91 using (Stream stream = response.GetResponseStream())//獲取返回的字符流格式 92 { 93 using (StreamReader sr = new StreamReader(stream, System.Text.Encoding.UTF8))//解決亂碼:設置utf-8字符格式 94 { 95 if (sr != null) 96 { 97 strHtml = sr.ReadToEnd(); 98 } 99 } 100 } 101 } 102 } 103 } 104 } 105 catch (WebException ex) 106 { 107 throw new Exception(ex.Message); 108 } 109 return strHtml; 110 }
使用到的方法,剛開始寫的時候不注意統一,后來需要時間優化
基礎方法與獲取微信相關信息並返回

1 #region 獲取AccessToken 2 public static string GetAccessToken() 3 { 4 string tokenUrl = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type={0}&appid={1}&secret={2}", grant_type, appid, secret); 5 var wc = new WebClient(); 6 var strReturn = wc.DownloadString(tokenUrl); 7 return strReturn; 8 } 9 #endregion 10 #region 獲取Jsapi_Ticket 11 public static string GetWeiXinJsapi_Ticket(string accessToken) 12 { 13 string tokenUrl = string.Format("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type={1}", accessToken, type); 14 var wc = new WebClient(); 15 var strReturn = wc.DownloadString(tokenUrl); //取得微信返回的json數據 16 return strReturn; 17 } 18 #endregion 19 #region 基礎字符 20 private static string[] strs = new string[] 21 { 22 "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z", 23 "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z" 24 }; 25 #endregion 26 #region 創建隨機字符串 27 public static string CreatenNonce_str() 28 { 29 Random r = new Random(); 30 var sb = new StringBuilder(); 31 var length = strs.Length; 32 for (int i = 0; i < 15; i++) 33 { 34 sb.Append(strs[r.Next(length - 1)]); 35 } 36 return sb.ToString(); 37 } 38 #endregion 39 #region 創建時間戳 40 public static long CreatenTimestamp() 41 { 42 return (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000; 43 } 44 #endregion 45 #region 簽名算法 46 /// <summary> 47 /// 簽名算法 48 ///本代碼來自開源微信SDK項目:https://github.com/night-king/weixinSDK 49 /// </summary> 50 /// <param name="jsapi_ticket">jsapi_ticket</param> 51 /// <param name="noncestr">隨機字符串(必須與wx.config中的nonceStr相同)</param> 52 /// <param name="timestamp">時間戳(必須與wx.config中的timestamp相同)</param> 53 /// <param name="url">當前網頁的URL,不包含#及其后面部分(必須是調用JS接口頁面的完整URL)</param> 54 /// <returns></returns> 55 public static string GetSignature(string jsapi_ticket, string noncestr, long timestamp, string url, out string string1) 56 { 57 var string1Builder = new StringBuilder(); 58 string1Builder.Append("jsapi_ticket=").Append(jsapi_ticket).Append("&") 59 .Append("noncestr=").Append(noncestr).Append("&") 60 .Append("timestamp=").Append(timestamp).Append("&") 61 .Append("url=").Append(url.IndexOf("#") >= 0 ? url.Substring(0, url.IndexOf("#")) : url); 62 string1 = string1Builder.ToString(); 63 return FormsAuthentication.HashPasswordForStoringInConfigFile(string1, "SHA1"); 64 //return Util.Sha1(string1); 65 } 66 #endregion

1 //GET api/GetInfoMation 2 /// <summary> 3 ///初始化的數據調用微信接口返回參數 4 /// </summary> 5 /// <returns></returns> 6 [AllowAnonymous] 7 [ActionName("GetInfoMation")] 8 [HttpGet] 9 public IHttpActionResult GetInfoMation(string ID, string url = "") 10 { 11 try 12 { 13 //生成tokcen 14 string tocken = GetAccessToken(); 15 JObject TokenJO = (JObject)JsonConvert.DeserializeObject(tocken); 16 //驗證簽名 17 string Jsapi_Ticket = GetWeiXinJsapi_Ticket(TokenJO["access_token"].ToString()); 18 JObject Jsapi_TicketJo = (JObject)JsonConvert.DeserializeObject(Jsapi_Ticket); 19 #region 20 string rtn = ""; 21 string jsapi_ticket = Jsapi_TicketJo["ticket"].ToString(); 22 string noncestr = CreatenNonce_str(); 23 long timestamp = CreatenTimestamp(); 24 string outstring = ""; 25 string JS_SDK_Result = GetSignature(jsapi_ticket, noncestr, timestamp, url, out outstring); 26 //拼接json串返回前台 27 rtn = "{\"appid\":\"" + appid + "\",\"jsapi_ticket\":\"" + jsapi_ticket + "\",\"noncestr\":\"" + noncestr + "\",\"timestamp\":\"" + timestamp + "\",\"outstring\":\"" + outstring + "\",\"signature\":\"" + JS_SDK_Result.ToLower() + "\"}"; 28 #endregion 29 return Json(Success(rtn)); 30 } 31 catch (CustomException ce) 32 { 33 return Json(getException(ce.Message)); 34 } 35 catch (Exception ex) 36 { 37 return Json(getException(ex)); 38 } 39 }
獲取公眾號下的微信會員信息

1 //GET api/Login/getCweixinInfo 2 /// <summary> 3 ///獲取網頁授權並返回微信賬號信息同時更新微信信息 4 /// </summary> 5 /// <param name="code">code</param> 6 /// <param name="UserId">對象ID</param> 7 /// <param name="Type">對象類型</param> 8 /// <returns></returns> 9 [AllowAnonymous] 10 [ActionName("getCweixinInformation")] 11 [HttpGet] 12 public IHttpActionResult getCweixinInformation(string code, string UserId, string Type = "1") 13 { 14 try 15 { 16 int uid = UserId.ToIntForPage(); 17 string strReturn = ""; 18 DateTime dtnow = DateTime.Now; 19 string openId = ""; 20 string accessToken = ""; 21 var log = dbo.mf_Weixinlog.OrderByDescending(c => c.ID).FirstOrDefault(); 22 var user = dbo.mf_User.Where(c => c.UserId == uid).FirstOrDefault(); 23 //if (uid > 0 && log != null && dtnow < log.PastTime && !string.IsNullOrEmpty(user.openid) && user.openid != "oW9b7t-XCA5B2VblXh9rt5bYBo9s") 24 //{ 25 // openId = user.openid; 26 // accessToken = log.Token; 27 //} 28 //else 29 { 30 strReturn = getToken(code); 31 //轉換成Json 32 Newtonsoft.Json.Linq.JObject TickectJO = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(strReturn); 33 openId = TickectJO["openid"].ToString(); 34 accessToken = TickectJO["access_token"].ToString(); 35 Weixinlog model = new Weixinlog 36 { 37 Itime = DateTime.Now, 38 Token = accessToken, 39 Openid = openId, 40 Seconds = 7200, 41 State = 0, 42 PastTime = DateTime.Now.AddSeconds(7080), 43 Ticket = "", 44 UserId = uid 45 }; 46 dbo.mf_Weixinlog.Add(model); 47 } 48 string rnt = ""; 49 50 strReturn = getWeiXinInfo(accessToken, openId); 51 52 rnt = strReturn; 53 54 #region 更新微信信息操作 55 //更新表 User 56 Newtonsoft.Json.Linq.JObject Cweinxin = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(strReturn); 57 int id = UserId.ToIntForPage(); 58 if (id > 0) 59 { 60 if (Type == "1") 61 { 62 User usermodel = dbo.User.Where(c => c.UserId == id).FirstOrDefault(); 63 if (usermodel != null) 64 { 65 usermodel.updateTime = DateTime.Now; 66 usermodel.openid = Cweinxin["openid"].ToString(); 67 usermodel.NickName = Cweinxin["nickname"].ToString(); 68 usermodel.Headimgurl = Cweinxin["headimgurl"].ToString(); 69 usermodel.City = Cweinxin["city"].ToString(); 70 usermodel.Province = Cweinxin["province"].ToString(); 71 usermodel.Sex = Cweinxin["sex"].ToString(); 72 dbo.Entry(usermodel).State = System.Data.Entity.EntityState.Modified; 73 //dbo.SaveChanges(); 74 } 75 } 76 #endregion 77 78 int r = dbo.SaveChanges(); 79 return Json(rnt); 80 } 81 catch (CustomException ce) 82 { 83 return Json(getException(ce.Message)); 84 } 85 catch (Exception ex) 86 { 87 return Json(getException(ex)); 88 } 89 }
到此 微信基本信息已獲取完畢,需要獲取更詳細的信息則需要更多的權限
當時做這個的時候,由於開發項目是前后端分離,測試的時候各種疑難雜症,前后台的問題交叉在一起,終究還是獲益良多