English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
주제로 돌아가서
위챗 공공 계정 개발 문서, 공식 버전 (https://mp.weixin.qq.com/wiki), 저는 이 문서를 쓴 사람에 대해 더 이상 탓할 수 없습니다. 제가 키보드를 부수고 싶었지만, 손을 뻗으면 깨달았습니다. 키보드는 제가 돈을 주고 사신 것입니다... 고맙습니다.
말도 안 되는 말을 하지 않고, 배포와 개발 방법을 직접 설명하겠습니다.
먼저, 공공 플랫폼 계정이 하나 있어야 합니다. 잘되었습니다, 전쟁을 시작해보겠습니다.
첫 번째 전쟁기업 계정이 아니어도 개발할 수 없다고 생각하지 마세요. 테스트 계정을 신청할 수 있습니다. 이는 주장하는 구독자 인터페이스 API보다 훨씬 많습니다.
백엔드 관리에 접속한 후, 개발자 도구를 클릭하여 공众 플랫폼 테스트 계정을 볼 수 있습니다. 직접 접속하여 설정을 시작하세요.
스케치 부분에 주의하세요. 이 부분은 프로그램에서 반드시 구성해야 하는 부분이며, 구성하지 않으면 반드시 실패합니다.
두 번째 전쟁물론, 이렇게 구성하면 성공하지 않을 것입니다. 왜 그렇게 되는지 물어도 답을 드리지 않습니다. 그림이 없으면 말도 안 됩니다...
企鹅帝는 놀고 있지 않다고 생각하지 마세요, 이是真的입니다. 반드시 이렇게 해야 합니다80 포트는 사실상 단순히 도메인 웹사이트를 발표하면 됩니다. 왜냐하면 도메인 웹사이트는 모두80 포트에서 나오는, 주제로 돌아가서 말씀드리겠습니다.
企鹅帝가 말했습니다. 웨이보 계정을 사용하려면 반드시 서버가 하나 있어야 하며, 그런 다음 우리가 발표한 웹사이트를 구성하면 됩니다. 주의하세요, 토큰은 자신이 설정한 것이며, 이는 자동으로 생성되는 것이 아닙니다. 자신이 설정해야 합니다. URL은 우리가 발표한 웹사이트 이름입니다
세 번째 전쟁웹사이트에서는 발표하지 않지만, 인터페이스 구성 정보는 영원히 구성될 수 없습니다. 기억하세요, 영원히입니다.
JS 인터페이스 보안 도메인, 이 부분은 문서를 직접 참조하세요 (http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html)。
JS 인터페이스 보안 도메인의 목적은 이미지를 다운로드하거나, 위챗 이미지 인터페이스를 호출하는 등입니다. 예를 들어, 카메라를 호출하거나 사진을 업로드할 때, 이 때는 JS 보안 인터페이스가 필요합니다. 구체적인 내용에 대해 자세히 설명하지 않겠습니다.
위챗 공공 계정 테스트 계정의 버전 백엔드에서, 경험 인터페이스 권한 테이블에 이 항목도 설정해야 합니다. 이는 필수 설정이 아닙니다. 그러나 이 인터페이스는 위챗 사용자의 일부 정보를 얻을 수 있습니다. 주의해야 할 것은 각 공공 계정에 대해 각 ID가 유일하다는 것입니다. 즉, 웹 사이트 내 네트워크가 변하지 않더라도 공공 계정을 변경하면, 이 때의 위챗 공공 계정 데이터는 공통되지 않으며, 공공 계정에 대해 유일합니다.
네 번째 문제는위챗 웹 페이지 권한 요청을 제출할 때, 이 URL의 웹 권한 사용자 기본 정보는 문제가 없지만, 경고 메시지가 없으면 문제가 있습니다.
이 URL에 주의하세요절대 www를 포함하지 않으며, 뒤에는 슬래시가 없습니다따라서 여기의 URL의 콜백 형식은 'abc.com OK'입니다. 이 형식을 기억해야 합니다. 반드시 이렇게 해야 합니다. 그럼 서버는 이렇게 하고, 이제 코드로 이야기해보겠습니다.
먼저 서버 인증부터 설명하겠습니다. 이 부분은 공식 웹사이트에 예제가 있습니다. 그러나 PHP의 예제입니다. 결국 먼저 랜덤 숫자를 확인한 후 POST 상황에서 반환 값을 검사하는 것입니다. 코드를 바로 보여드리겠습니다.
public ActionResult Index() { if (Request.HttpMethod.ToLower() == "post") { if (CheckSignature())//서버가 인증을 통과했는지 확인합니다 { GetMenuList();//메뉴를 로드합니다 } else { Response.Write("<h1>Oh</h1><h2>우리는 화성에서 만나요!!!</h2"> Response.End(); } } else { CheckWechat(); } return View(); } /// <summary> /// 랜덤 숫자를 반환하여 인증 성공을 나타냅니다 /// </summary> private void CheckWechat() { if (string.IsNullOrEmpty(Request.QueryString["echoStr"])) { Response.Write("메시지는 위챗에서 오지 않았습니다"); Response.End(); } string echoStr = Request.QueryString["echoStr"]; if (CheckSignature()) { Response.Write(echoStr); Response.End(); } } /// <summary> /// 위챗 서명을 확인합니다 /// </summary> /// <returns></returns> /// token, timestamp, nonce 세 가지 매개변수를 사전 순으로 정렬합니다 /// 세 가지 매개변수 문자열을 하나의 문자열로 병합하여 sha를 수행합니다1암호화 /// 개발자는 암호화된 문자열을 signature와 비교하여, 이 요청이 위챗에서 온 것인지 확인할 수 있습니다. 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); //사전 정렬 string tmpStr = string.Join("", ArrTmp); tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1"); tmpStr = tmpStr.ToLower(); if (tmpStr == signature) { return true; } else { return false; } }
그런 다음, 공개 플랫폼은 권한이 있을 때 맞춤 메뉴를 사용할 수 있습니다. 그러나 맞춤 메뉴를 시작하면 원래 수동으로 편집한 메뉴는 사용할 수 없습니다. 다시 말해, 서버 검증이 성공하면 반드시 자신의 코드로 제어해야 합니다.
우리 함께 GetMenuList() 메서드를 보도록 하겠습니다. 이는 매우 간단합니다. JSON 형식 문자열을 무작위로 사용하여, 그런 다음 위챗의 인터페이스를 호출하면 됩니다. public void GetMenuList()
<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("}})63(url.IndexOf("}} -1 ; "") >63;? "" : " + 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을 사용하면 using 문 내의 메모리를 해제할 수 있습니다 { reqStream.Write(bt, 0, bt.Length); reqStream.Flush(); } try { using (WebResponse res = req.GetResponse()) { //여기서 수신된 페이지 내용을 처리합니다 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;//url이 오류일 때는 오류를 보고합니다 } }
좋아, 나는 모른척 먹어치우는 먹는 것을 고백합니다. 또 하나의 access_token=IsExistAccess_Token();이 어떻게 생겼는지, 궁금하지 마세요, 나가 말씀드릴게요.
문서를 읽을 때 우리는, 여기의 Access_Token이 두 시간마다 만료된다는 것을 발견하게 됩니다. 여기서의 방법은 만료될 때 자동으로 얻을 수 있게 합니다.
第五坑,这里的JSON字符串,也就是要展示的菜单,我希望大家都用小写,如果用了大写,那么,呵呵,哈哈了真心的,很操蛋的,他会告诉你没有用UTF88编码,但是你真心是编码过的,可惜还是出错,所以,还是小写吧,唉
继续说两个小时自动获取之后,就是通过MenuCreate(调用微信菜单接口)输出即可。上代码。
/// <summary> /// 防止每次请求的token两个小时的变化 /// </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{ //로그 기록} return entity; } /// <summary> /// 현재 날짜에 따라 Access_Token이 만료되었는지 확인합니다. 만료되면 새로운 Access_Token을 반환하고, 아니면 이전의 Access_Token을 반환합니다. /// </summary> /// <param name="datetime"></param> /// <returns></returns> public static string IsExistAccess_Token() { try { string Token = string.Empty; DateTime YouXRQ; //XML 파일의 데이터를 읽고 표시합니다. 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 "";//记录日志 } } } public class Access_token { public Access_token() { } public string access_token { get; set; } public string expires_in { get; set; } } public class JsonHelper { /// <summary> /// 生成Json格式 /// </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> /// 获取Json的Model /// </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); } } }
제발 다시 한 번 불명확한 상황에 대해 이야기하지 않도록 해 주세요. XMLFile.xml이라는 것은 무엇인가요? 제발 그렇게 직설적이지 않게 이야기해 주세요. 코드를 직접 보는 것이 더 좋습니다.
<?xml version="1.0" encoding="utf-8"?> <xml> <Access_Token>TOKEN을 얻기 위해</Access_Token> <Access_YouXRQ>2015/9/12 17:56:31</Access_YouXRQ> </xml>
이제 여러분이 무엇도 말하고 싶지 않다는 것을 확신합니다
좋아, 조용히 호두를 먹으며, 조용히 여러분이 계속하시는 것을 보고 있습니다. 오늘은 여기서 멈추고, 나중에 계속하기로 했습니다. 이미 다섯 개의 구멍이 열렸습니다. 아이들에게 아쉽습니다.
이것이 본 문서의 전부입니다. 많은 도움이 되었기를 바랍니다. 또한, 나는呐喊 강의를 많이 지지해 주셔서 감사합니다.
언급: 본 내용은 인터넷에서 가져왔으며, 저작권자의 소유물입니다. 내용은 인터넷 사용자가 자발적으로 기여하고 업로드한 것이며, 이 사이트는 소유권을 가지지 않으며, 인공적인 편집 처리를 하지 않았으며, 관련 법적 책임도 부담하지 않습니다. 저작권 위반 내용을 발견하면, 이메일을 notice#w로 보내 주시기 바랍니다.3codebox.com에 대한 신고를 위해 #을 @으로 변경하여 이메일을 보내고, 관련 증거를 제공하십시오. 사실이 확인되면, 이 사이트는 즉시 위반 내용을 삭제합니다.