English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Let's get to the point:
WeChat Public Account Development Document, official version (https://mp.weixin.qq.com/wiki), believe me, I am at a loss for words about the person who wrote this document, I really want to smash this keyboard, but I found out that the keyboard is actually bought by myself... Embarrassing.
No more chatter, let's talk about how to deploy and how to develop directly.
Firstly, you need to have a Public Platform account, okay, let's start digging the pit.
The first pit,Don't think that you can't develop because it's not a corporate account, you can apply for a test account, which is much more than the so-called subscription account interface.
After entering the background management, click Developer Tools, you can see the Public Platform test account, directly enter it and start filling in your configuration.
Pay attention to the doodle part, this part is something that must be configured in the program. If it is not configured, it is definitely not going to work.
The second pitOf course, you are bound to fail with this configuration, don't ask me why. No picture, what the hell are you talking about...
Don't think that Penguin Emperor is playing around, this is true, it must be8Port 0, in fact, just publish a website with a domain name. Because all domain name websites are8Out of port 0, let's continue with the main topic.
Penguin Emperor tells us that in order to use WeChat accounts, we must have a server, and then configure the website we published. Please note that the token is self-set, this is not automatically generated, self-set... The URL is the name of the website we published
The third pit,The website does not publish, the interface configuration information can never be configured, remember, it's forever.
JS interface security domain name, please refer to the document directly (http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html).
The purpose of the JS interface security domain is to download pictures, call WeChat picture interfaces, etc., such as when you need to call the camera or need to upload photos, in this case, you need the JS security interface. The specific content will not be described in detail here.
In the background of the WeChat public account test account version, there is an experience interface permission table item that must be configured. It is not necessarily a mandatory configuration, but this interface can obtain some information of WeChat users. It is worth reminding that each public account corresponds to a unique ID, that is to say, even if the website intranet does not change, if a public account is changed, then the data of this WeChat public account cannot be shared, it is just relatively unique to the public account.
The fourth pit isWhen applying for WeChat web page authorization, the basic information of the web page authorization user here is not a problem, but there is a problem without any prompts.
Please note the URL here,It must not contain www, and there is no backslash at the endThat is to say, the callback format of the URL here is abc.com OK. Please remember this format, it must be done like this. Alright, let's put the server aside for now and start talking with code.
Let's start with the server verification first. This is an example on the official website, but it is actually PHP. In short, it is to verify a random number first, and then check the return value in the POST case. Let's directly show the code
public ActionResult Index() { if (Request.HttpMethod.ToLower() == "post") { if (CheckSignature())//Verify whether the server is passed { GetMenuList();//Load the menu } else { Response.Write("<h1>Oh</h1><h2>Meet us on Mars!!!</h2"> Response.End(); } } else { CheckWechat(); } return View(); } /// <summary> /// Return a random number to indicate successful verification /// </summary> private void CheckWechat() { if (string.IsNullOrEmpty(Request.QueryString["echoStr"])) { Response.Write("The message is not from WeChat"); Response.End(); } string echoStr = Request.QueryString["echoStr"]; if (CheckSignature()) { Response.Write(echoStr); Response.End(); } } /// <summary> /// Verify the WeChat signature /// </summary> /// <returns></returns> /// Sort the parameters token, timestamp, and nonce in dictionary order /// Concatenate three parameter strings into a single string for SHA1Encryption}} /// The developer can obtain the encrypted string and compare it with signature to identify that the request comes from WeChat. private bool CheckSignature() { string signature = Convert.ToString(Request["signature"]); string timestamp = Convert.ToString(Request["timestamp"]); string nonce = Convert.ToString(Request["nonce"]); string[] ArrTmp = { Token, timestamp, nonce }; Array.Sort(ArrTmp); //Dictionary Sorting string tmpStr = string.Join("", ArrTmp); tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA"1"); tmpStr = tmpStr.ToLower(); if (tmpStr == signature) { return true; } else { return false; } }
Then, the public platform can customize the menu when it has the permission, but once the customization of the menu starts, the original manually edited menu cannot be used, that is to say, if the server verification passes, it is necessary to control it with your own code.
Let's take a look at the GetMenuList() method, which is actually very simple, just use a JSON format string at will. Then call the WeChat interface.
<em id="__mceDel"> { string weixin1 = ""; weixin1 = @" { "button":[ { "type":"click" "name":"你好!" "key":"hello" }, { "type":"view" "name":"公司简介" "url":"http://www.xnfhtech.com" }, { "name":"产品介绍" "sub_button":[ { "type":"click" "name":"产品"1", "key":"p"1"" }, { "type":"click" "name":"产品"2", "key":"p"2"" }]}} }] }"; string access_token = Tools.WA_GetAccess_Token.IsExistAccess_Token(); string i = this.MenuCreate(menu, access_token); Response.Write(i); }<br><br> </em>
public string MenuCreate(string MenuJson, string access_token) { JavaScriptSerializer Jss = new JavaScriptSerializer(); string setMenuUrl = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token={0}"; setMenuUrl = string.Format(setMenuUrl, access_token);//获取token、拼凑url string respText = WebRequestPostOrGet(setMenuUrl, MenuJson); Dictionary<string, object> respDic = (Dictionary<string, object>)Jss.DeserializeObject(respText); return respDic["errcode"].ToString();//返回0发布成功 } /// <summary> /// Post/get 提交调用抓取 /// </summary> /// <param name="url">提交地址</param> /// <param name="param">参数</param> /// <returns>string</returns> public string WebRequestPostOrGet(string sUrl, string sParam) { byte[] bt = System.Text.Encoding.UTF8.GetBytes(sParam); Uri uriurl = new Uri(sUrl); HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uriurl);//HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url + (url.IndexOf("?") > -1 ? "" : "? + param); req.Method = "Post"; req.Timeout = 120 * 1000; req.ContentType = "application/x-www-form-urlencoded;"; req.ContentLength = bt.Length; using (Stream reqStream = req.GetRequestStream())//Using can release the memory within the using block { reqStream.Write(bt, 0, bt.Length); reqStream.Flush(); } try { using (WebResponse res = req.GetResponse()) { //Here, process the received page content Stream resStream = res.GetResponseStream(); StreamReader resStreamReader = new StreamReader(resStream, System.Text.Encoding.UTF8); string resLine; System.Text.StringBuilder resStringBuilder = new System.Text.StringBuilder(); while ((resLine = resStreamReader.ReadLine()) != null) { resStringBuilder.Append(resLine + System.Environment.NewLine); } resStream.Close(); resStreamReader.Close(); return resStringBuilder.ToString(); } } catch (Exception ex) { return ex.Message;//Return error when the URL is incorrect } }
Alright, I admit that I am an ignorant eater of little knowledge, how did another access_token=IsExistAccess_Token(); appear? Don't worry, baby, I'll tell you.
When we read the document, we will find that the Access_Token here expires every two hours. The method here is to automatically obtain it when it expires.
The fifth pit, here is the JSON string, which is the menu to be displayed, I hope everyone uses lowercase. If you use uppercase, then, hahaha, it's really annoying, it will tell you that it is not using UTF8Encoding, but you really are encoding, unfortunately, it still goes wrong, so, it's better to be lowercase, sigh
To continue, after two hours of automatic acquisition, it is output through MenuCreate (call the WeChat menu interface). Here is the code.
/// <summary> /// To prevent the token from changing every two hours with each request /// </summary> public class WA_GetAccess_Token { public WA_GetAccess_Token() { } public static WAEntity.Access_token GetAccess_Token() { string url = "https://api.weixin.qq.com/cgi-bin/token#63;grant_type=client_credential&appid="+ ConfigurationManager.AppSettings["AppID"]; + &secret=+ ConfigurationManager.AppSettings["AppSecret"]; Access_token entity = new Access_token(); try { HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url); req.Method = "GET"; using (WebResponse wr = req.GetResponse()) { HttpWebResponse myResponse = (HttpWebResponse)req.GetResponse(); StreamReader reader = new StreamReader(myResponse.GetResponseStream(), System.Text.Encoding.UTF8);8); string content = reader.ReadToEnd(); Access_token token = new Access_token(); token = JsonHelper.ParseFromJson<Access_token>(content); entity.access_token = token.access_token; entity.expires_in = token.expires_in; } } catch{ //Log the record} return entity; } /// <summary> /// Determine if the Access_Token has expired based on the current date. If it has expired, return a new Access_Token; otherwise, return the previous Access_Token /// </summary> /// <param name="datetime"></param> /// <returns></returns> public static string IsExistAccess_Token() { try { string Token = string.Empty; DateTime YouXRQ; //Read data from the XML file and display it string filepath = HttpContext.Current.Request.MapPath("~/XMLFile.xml"); StreamReader str = new StreamReader(filepath, System.Text.Encoding.UTF8); XmlDocument xml = new XmlDocument(); xml.Load(str); str.Close(); str.Dispose(); Token = xml.SelectSingleNode("xml").SelectSingleNode("Access_Token").InnerText; YouXRQ = Convert.ToDateTime(xml.SelectSingleNode("xml").SelectSingleNode("Access_YouXRQ").InnerText); if (DateTime.Now > YouXRQ) { DateTime _youxrq = DateTime.Now; WAEntity.Access_token mode = GetAccess_Token(); xml.SelectSingleNode("xml").SelectSingleNode("Access_Token").InnerText = mode.access_token; _youxrq = _youxrq.AddSeconds(Convert.ToInt)32(mode.expires_in)); xml.SelectSingleNode("xml").SelectSingleNode("Access_YouXRQ").InnerText = _youxrq.ToString(); xml.Save(filepath); Token = mode.access_token; } return Token; } catch (Exception ex) { return "";//Log record } } } public class Access_token { public Access_token() { } public string access_token { get; set; } public string expires_in { get; set; } } public class JsonHelper { /// <summary> /// Generate JSON format /// </summary> /// <typeparam name="T"></typeparam> /// <param name="obj"></param> /// <returns></returns> public static string GetJson<T>(T obj) { DataContractJsonSerializer json = new DataContractJsonSerializer(obj.GetType()); using (MemoryStream stream = new MemoryStream()) { json.WriteObject(stream, obj); string szJson = Encoding.UTF8.GetString(stream.ToArray()); return szJson; } } /// <summary> /// Get Model from Json /// </summary> /// <typeparam name="T"></typeparam> /// <param name="szJson"></param> /// <returns></returns> public static T ParseFromJson<T>(string szJson) { T obj = Activator.CreateInstance<T>(); using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(szJson))) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType()); return (T)serializer.ReadObject(ms); } } }
Forgive me for not understanding the truth, what is this XMLFile.xml again, alright, I actually don't want to say it so directly, it's better to show the code directly.
<?xml version="1.0" encoding="utf-8"?> <xml> <Access_Token>Get TOKEN</Access_Token>/Access_Token> <Access_YouXRQ>2015/9/12 17:56:31</Access_YouXRQ> </xml>
I'm sure you really don't want to say anything about this
Alright, quietly eating sunflower seeds, silently watching you continue, let's stop here today, we have walked five pits already, and the baby is really upset.
That's all for this article. I hope it will be helpful to your studies, and I also hope everyone will support the Shouting Tutorial.
Declaration: The content of this article is from the Internet, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been manually edited, and does not assume relevant legal liabilities. If you find any suspected copyright content, please send an email to: notice#w3Please report any infringement by email to codebox.com (replace # with @), and provide relevant evidence. Once verified, this site will immediately delete the suspected infringing content.