English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Os Primeiros Cinco Buracos no Desenvolvimento de Conta Pública de WeChat em PHP (Parte 1)

Vamos direto ao ponto:

Documento de desenvolvimento da conta pública do WeChat, versão oficial (https://mp.weixin.qq.com/wiki),confie em mim, eu já não tenho forças para xingar a pessoa que escreveu esse documento, eu realmente quero esmagar o teclado, mas quando eu fiz, descobri que o teclado foi comprado com meu próprio dinheiro....... embaraçoso. 

Não há palavras, vamos direto ao ponto de como implantar, como desenvolver. 

Primeiro, você precisa de uma conta da plataforma pública, bem, vamos começar a cavar buracos. 

Primeira trapaçaNão pense que você não pode desenvolver se não for uma conta de empresa, você pode solicitar uma conta de teste, muito mais do que a interface da conta de assinatura.

 

Após entrar na administração do backend, clique em Ferramentas do Desenvolvedor, você pode ver a conta de teste da plataforma pública, entre diretamente. Comece a preencher sua configuração. 


Atenção para a parte de esboço, essa parte é necessária para a configuração do programa. Sem configuração, isso definitivamente não terá sucesso. 

Segunda trapaçaClaro, você definitivamente não terá sucesso com essa configuração, não me perguntem por quê. Sem imagens, é impossível explicar... 


Não acredite que o imperador do pinguim está brincando, é verdadeiro, deve ser8Porta 0, na verdade, é suficiente publicar um site com um domínio. Porque todos os sites com domínio são8Porta 0, continuemos com o assunto principal. 

O imperador do pinguim nos diz que para usar a conta do WeChat, é necessário ter um servidor e configurar o site que publicamos. Preste atenção, o token é definido por você mesmo, não é gerado automaticamente, você mesmo define... A URL é o nome do site que publicamos 

Terceira trapaça,O site não publica, as informações de configuração da interface nunca serão configuradas, lembre-se, é para sempre. 

Domínio de segurança da interface JS, por favor, consulte o documento diretamente (http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html)。 

O objetivo do domínio de segurança da interface JS é para baixar imagens, chamar interfaces de imagens WeChat etc., por exemplo, quando precisamos chamar a câmera ou precisamos carregar uma foto, neste momento é necessário usar a interface de segurança JS, sobre o conteúdo específico não será descrito em detalhes. 

No painel de teste do WeChat, há um item na tabela de permissões de interface de experiência que também deve ser configurado. Não é realmente necessário configurar, mas essa interface pode obter parte das informações do usuário WeChat. É importante lembrar que cada ID correspondente a cada conta WeChat é único, o que significa que, mesmo que a rede interna do site não mude, se mudar o WeChat, os dados do WeChat público dessa vez não podem ser compartilhados, apenas relativamente únicos para o público. 

Quarto buracoQuando solicitamos permissão de autorização da página WeChat, as informações básicas do usuário de autorização da página, isso em si não há problema, mas sem aviso há problema. 

Atenção para a URL aquiDeve ser sem o www e não deve haver barras invertidas no finalIsso significa que o formato da URL de callback aqui é abc.com OK. Lembre-se desse formato, é necessário fazer assim. Bem, o servidor está temporariamente assim, vamos começar a falar com código. 

Primeiro vamos falar sobre a verificação do servidor. Isso há exemplos no site oficial, embora sejam exemplos em PHP. Em resumo, primeiro verifica-se um número aleatório, e em casos de POST, verifica-se o valor de retorno. Vamos direto ao código 

 public ActionResult Index()
 {
 if (Request.HttpMethod.ToLower() == "post")
 {
 if (CheckSignature())//Verificar se o servidor foi aprovado
 {
 GetMenuList();//Carregar o menu
 }
 else
 {
 Response.Write("<h1>Oh</1><h2>Encontramo-nos em Marte!!!</2">
 Response.End();
 }
 }
 else
 {
 CheckWechat();
 }
 return View();
 }
 /// <summary>
 /// Retornar um número aleatório para representar a verificação bem-sucedida
 /// </summary>
 private void CheckWechat()
 {
 if (string.IsNullOrEmpty(Request.QueryString["echoStr"]))
 {
 Response.Write("A mensagem não veio do WeChat");
 Response.End();
 }
 string echoStr = Request.QueryString["echoStr"];
 if (CheckSignature())
 {
 Response.Write(echoStr);
 Response.End();
 }
 }
/// <summary>
 /// Verificar a assinatura do WeChat
 /// </summary>
 /// <returns></returns>
 /// Ordenar alfabeticamente os três parâmetros token, timestamp e nonce
 /// Juntar três strings de parâmetros em uma string para sha1Criptografia}}
 /// O desenvolvedor pode comparar a string criptografada com signature para identificar que a solicitação veio do 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); //Classificação de dicionário 
 string tmpStr = string.Join("", ArrTmp);
 tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");
 tmpStr = tmpStr.ToLower();
 if (tmpStr == signature)
 {
 return true;
 }
 else
 {
 return false;
 }
 }

Em seguida, a plataforma pública pode personalizar o menu com permissão, mas assim que começar a personalizar o menu, o menu editado manualmente não pode ser usado, o que significa que, se a verificação do servidor for bem-sucedida, é necessário controlar com seu próprio código. 

Vamos juntos olhar para o método GetMenuList(), que é realmente simples, é apenas um JSON string formatado. Em seguida, chame a interface do WeChat. 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("? -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 pode liberar a memória dentro do bloco using
 {
 reqStream.Write(bt, 0, bt.Length);
 reqStream.Flush();
 }
 try
 {
 using (WebResponse res = req.GetResponse())
 {
 //Aqui é onde o conteúdo da página recebida é processado
 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;//Quando o URL estiver errado, retornará um erro.
 }
 }

Bem, eu admito que sou um comer sem saber o que é, como é que mais um access_token=IsExistAccess_Token(); apareceu? Não se preocupe, o bebê te conta.

Quando lemos documentos, percebemos que o Access_Token aqui expira a cada duas horas. O método aqui é permitir que ele seja obtido automaticamente quando expira. 

第五坑,这里的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{ //Registrar log}
 return entity;
 }
 /// <summary> 
 /// Verifique se o Access_Token está vencido com base na data atual. Se estiver vencido, retorne um novo Access_Token; caso contrário, retorne o Access_Token anterior 
 /// </summary> 
 /// <param name="datetime"></param> 
 /// <returns></returns> 
 public static string IsExistAccess_Token()
 {
 try
 {
 string Token = string.Empty;
 DateTime YouXRQ;
 //Ler os dados do arquivo XML e exibi-los
 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);
 }
 }
}

Perdoem-me por não entender a verdadeira situação, o que é esse XMLFile.xml, certo? Bem, na verdade, eu não quero ser tão direto, é melhor mostrar o código diretamente.

<?xml version="1.0" encoding="utf-8"?>
<xml>
 <Access_Token>Obter TOKEN</Access_Token>
 <Access_YouXRQ>2015/9/12 17:56:31</Access_YouXRQ>
</xml>

Estou certo de que você realmente não quer dizer nada 

Bem, estou quieto, comendo pipoca e observando vocês continuarem. Hoje, vamos parar por aqui, continuaremos em breve, já temos cinco buracos, o meu coração está doendo.

Isso é tudo sobre este artigo. Espero que ajude no seu aprendizado e que você também apoie o Tutorial Yell.

Declaração: o conteúdo deste artigo é extraído da internet, pertence ao respectivo proprietário e foi carregado voluntariamente pelos usuários da internet. Este site não possui direitos de propriedade, não foi editado artificialmente e não assume responsabilidades legais relacionadas. Se você encontrar conteúdo suspeito de violação de direitos autorais, por favor, envie um e-mail para: notice#oldtoolbag.com (ao enviar e-mail, troque # por @ para denunciar e forneça provas relevantes. Caso seja confirmado, o site deletará imediatamente o conteúdo suspeito de violação de direitos autorais.)

Você Também Pode Gostar