Estou ocupado com o tempo de front-end há um tempo. Eu li os documentos do zero e pisei em muitas armadilhas. Eu já passei por isso recentemente. Eu pensei em fazer algum resumo para que eu possa revisá -lo no futuro quando o desenvolver. Também darei uma referência aos alunos que estão trabalhando em projetos relacionados.
De fato, depois de fazê -lo uma vez, você descobrirá que não é difícil. A idéia geral é: as mensagens do usuário e os empurrões exigidos pelos desenvolvedores iniciarão uma solicitação através do servidor WeChat e a encaminharão para o endereço do URL do servidor que você configurou na plataforma pública. O servidor WeChat trará quatro parâmetros: assinatura, registro de data e hora, Nonce e ECHOSTR. Nosso servidor vai consumir o token configurado pela plataforma pública e o registro de data e hora é enviado. Nonce será criptografado no SHA1 e corresponderá à assinatura. Retorne a termo para indicar que o acesso é bem -sucedido.
1. Configuração da plataforma pública
2. Controlador
@Controlador@requestmapping ("/weChat") publicClass weChatController {@Value ("$ {dnbx_token}") private string dnbx_token; private static final Logger = LoggerFactory.GetLogger (WechController.Class); @throws IOException */@RequestMapping(value="/connect",method = {RequestMethod.GET, RequestMethod.POST})@ResponseBodypublicvoid connectWeixin(HttpServletRequest request, HttpServletResponse response) throws IOException{// Set the encoding of the request and response to UTF-8 (prevent Chinese garbled code) request.setcharacterencoding ("UTF-8"); // O servidor WeChat usa a codificação do UTF-8 quando as mensagens postais e a mesma codificação deve ser usada ao receber, caso contrário, o código ilegal chinês será um código ilegível; Response.Setcharacterencoding ("UTF-8"); // Ao responder às mensagens (respondendo ao usuário), o método de codificação também está definido como UTF-8, o princípio é o mesmo que acima; boolean isget = request.getMethod (). tolowerCase (). igual ("get"); PrintWriter out = Response.getWriter (); Try {if (isGet) {String Signature = request.getParameter ("Signature"); // WeChat Criptografia Signature String Timestamp = request.GetParameter ("Timestamp"); // Timestamp String String = request.TeoSTParameter ("Nonce"; request.getParameter ("ECHOSTR"); // String aleatória // Verifique a solicitação verificando a assinatura. Se a verificação for bem -sucedida, o Return EchoStr como está, indicando que o acesso é bem -sucedido. Caso contrário, o acesso falha se (signutil.checkSignature (dnbx_token, assinatura, registro de data e hora, nonce)) {logger.info ("Connect the weixin servidor é bem -sucedido."); resposta.getWriter (). Write (ECHOSTR); } else {Logger.error ("Falha ao verificar a assinatura!"); }} else {string respMessage = "Mensagem de exceção!"; tente {respmessage = wechatService.weixinpost (request); out.write (respmessage); logger.info ("a solicitação concluída com sucesso"); Logger.info ("para Weixin Server"+(respmessage); weixin! "); }}} catch (Exceção e) {Logger.error ("Connect the Weixin Server é erro.");} finalmente {out.close ();}}}3. Assinatura de verificação de assinatura
A partir do controlador acima, podemos ver que eu encapsulei uma classe de ferramentas Signutil, denominada design de verificação e passei em quatro valores, dnbx_token, assinatura, registro de data e hora. Este processo é muito importante. De fato, podemos entendê -lo como um processo de criptografia e descriptografia do valor transmitido pelo WeChat. Para garantir a segurança, todas as interfaces em muitos grandes projetos terão esse processo de verificação. DNBX_TOKen Configuramos uma string de token na plataforma pública do WeChat, mantenha a ideia confidencial! Os outros três são parâmetros enviados pelo servidor WeChat para enviar uma solicitação GET. Realizamos uma camada de criptografia SHA1:
classe pública SignUtil { / *** Assinatura de verificação* Token do servidor WeChat @param, configurado no arquivo Env.Properties e configurado no centro do desenvolvedor deve ser consistente* @param assinatura O servidor weChat envia o sha1 recriado de certificado* @param @PoTamMOTAMPOTAMPATAMP* @Part INPARTAMENTO REMOTENCO REMOTEN @PoTATIM @ParTaMeCT Randimated Nourset Numberature* @param TimunMUNGamMonTamp* @Panda @Panda @Panda @Panda NonCoMenc Random Numberature* @param timestampampulp* @paramen @PartEn Random Numberd Token, String Signature, String Timestamp, String nonce) {String [] arr = new String [] {token, Timestamp, Nonce}; // Classifica a ordem do dicionário de token, registro de data e hora e nonce; // cedem as três cadeias de parâmetros em uma string para string de criptografia sha1 tmpstr = sha1.encode (arr [0] + arr [1] + arr [2]); // O string criptografado SHA1 pode ser comparado com a assinatura, identificando que a solicitação vem do WeChat Return tmpstr! = NULL? tmpstr.equals (assinatura.touppercase ()): false; }}SHA1:
/** * Plataforma pública WeChat (Java) SDK * * SHA1 Algoritmo * @Author Helijun 2016/06/06/15 19: 49 */public Final Class SHA1 {private Static Final [] hex_digits = {'0', '1', '2', '' 3 ',' 4 '' '' '' '' '' '' '', 'B', 'c', 'd', 'e', 'f'}; /*** pega os bytes crus do digerido e os formam corretos. * * @param bytes Os bytes crus do digerir. * @return os bytes formatados. */ string estática privada getFormattedText (byte [] bytes) {int len = bytes.length; StringBuilder BUF = new StringBuilder (Len * 2); // converte o CipherText em uma forma de sequência hexadecimal para (int j = 0; j <len; j ++) {buf.append (hex_digits [(bytes [j] >> 4) & 0x0f]); buf.append (hex_digits [bytes [j] & 0x0f]); } retornar buf.toString (); } public static string cody (string str) {if (str == null) {return null; } tente {Messagedigest Messagedigest = MessAgedigest.getInstance ("sha1"); Messagedigest.Update (str.getBytes ()); return getFormattedText (Messagedigest.Digest ()); } catch (Exceção e) {lança nova RunTimeException (e); }}} Quando você envia e salva -o na plataforma pública e vê o prompt verde "Access Success", parabéns por concluir o acesso do WeChat. Esse processo requer um pouco mais de cuidado e preste atenção ao caso no algoritmo de criptografia. Se o acesso não for bem -sucedido, a maioria dos casos são problemas com o algoritmo de criptografia, verifique mais.
4. Implementar serviço de resposta de mensagem automática
/*** Solicitações de processo do weChat** @param request* @return*/public string weixInpost (httpServletRequest request) {string respmessage = null; tente {// xml request parsing map <string, string> requestMap = messageTil.xmltOMAP (request); // severa requestmap.get ("FromUserName"); // Public Conta String touserName = requestMap.get ("touserName"); // Tipo de mensagem Tipo string msgtype = requestmap.get ("msgtype"); // message content content = requestMap.get ("content"); Logger.InFo ("FromiStame é:" ", MsgType é:" + msgtype); // mensagem de texto se (msgtype.equals (messageutil.req_message_type_text)) {// A lógica correspondente é executada de acordo com as palavras -chave. Existe apenas um que você não pode imaginar. Não existe o que você não pode fazer se (content.equals ("xxx")) {} // resposta automática textMessage text = new textMessage (); text.setContent ("o texto é" + content); text.setTouserName (fromUsename); textfromusername (tousername); ""); text.setmsgtype (msgtype); respmessage = messageUtil.textMessageToxml (text);}/*else if (msgtype.equals (messageutil.req_message_type_event) {// event push string stringtype = request.get.get_type_event) {// Event Push) (EventType.equals (messageUtil.Event_Type_SubScribe)) {// assine o respcontent = "Bem -vindo a seguir a conta oficial xxx!"; retorna messagerponse.getTextMessage (spustername, tousername, respContent); mais, if (eventtype.equals (sustername, tousername, respContent); EventKey = requestMap.get ("EventKey"); // Valor da chave do evento, correspondendo ao valor da chave especificado ao criar o menu personalizado Logger.info ("EventKey é:" +EventKey); retorna xxx;}} // Ligue o teste de reconhecimento de som WeChat 2015-3-30Else se (msgtype.equals ("Voice) {)) requestmap.get ("reconhecimento"); // respcontent = "Recebido Resultado da análise de fala:"+Recvmessage; if (recvmessage! = null) {respcontent = tulingapiprocess.gettulingResult (recvmessage);} else {respcontent = "o que você disse é muito vago, você pode dizer novamente? } // Função fotográfica else if (msgtype.equals ("pic_sysphoto")) {} else {return messagerponse.getTextMessage (FromUserName, tousername, "retornar vazio"); }*// Evento Push else if (msgtype.equals (messageutil.req_message_type_event)) {string eventtype = requestmap.get ("event"); // typet // assinou. if (eventtype.equals (textil.event_type_subScribe. (eventtype.equals (textil.Ext); Siga, xxx "); text.setTouserName (FromUserName); text.SetFromUserName (touserName); text.setCreateTime (new Date (). gettime () +" "); textmsgtype (MessageTutil.Resp_Message_typext_Text); respmessage = MessageTutil.Resp_Message_TyExt_Text); respmessage =; Descrenda a inscrição, o usuário não pode receber a mensagem enviada pela conta oficial; portanto, não há necessidade de responder à mensagem se (eventtype.equals (messageUtil.event_type_unsubscribe)) {// unsubscribe} // menu personalizado clique em Event se (eventtype.equals (MessageUtil.EVent_Type_Pe) Valor da chave do evento, correspondente ao valor da chave especificado ao criar o menu personalizado if (eventKey.equals ("Customer_telephone")) {textMessage text = new textMessage (); text.setContent ("0755-86671980"); textTousousame (doUMername); Date().getTime() + "");text.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);respMessage = MessageUtil.textMessageToXml(text);}}}}}catch (Exception e) {Logger.error("error...")}return respMessage;}O código é publicado como acima. A maioria deles tem comentários. Se você ler a semântica básica uma vez, não precisará explicá -las.
Idéia breve: quando um usuário envia uma mensagem para a conta oficial, o servidor WeChat solicitará a mensagem do usuário por meio da interface correspondente do servidor que configuramos no formato XML. O que precisamos fazer é executar o processamento lógico correspondente com base no tipo de mensagem, etc. e retornar o resultado final de retorno ao servidor WeChat através do formato XML e transmiti -lo ao usuário.
Há um lugar que precisa de atenção especial:
O nome vermelho e o nome de Tousername são exatamente o oposto, o que também é uma das armadilhas. Lembro que o ajustei há muito tempo, mas não foi um problema, mas não estava funcionando. Finalmente, recebi a mensagem depois de alterar esses dois! Na verdade, é correto pensar sobre isso. Quando você retornar ao servidor WeChat, sua função mudará, para que o remetente e o receptor sejam definitivamente o oposto.
5.MessageUtil
public class MessageUtil {/ *** Retornar Tipo de mensagem: Texto*/ public static final String resp_message_type_text = "text"; / *** Return Message Type: Music*/ public static final string resp_message_type_music = "music"; / *** Retornar Tipo de mensagem: Texto gráfico*/ public static final string resp_message_type_news = "News"; / *** Tipo de mensagem de solicitação: texto*/ public static final string req_message_type_text = "text"; / *** Tipo de mensagem de solicitação: imagem*/ public static final string req_message_type_image = "image"; / *** Tipo de mensagem de solicitação: link*/ public static final string req_message_type_link = "link"; / *** Tipo de mensagem de solicitação: localização geográfica*/ public static string final req_message_type_location = "location"; / *** Tipo de mensagem de solicitação: áudio*/ public static string final req_message_type_voice = "voz"; / ** * Tipo de mensagem de solicitação: push */ public static final string req_message_type_event = "event"; / ** * Tipo de evento: Inscreva -se (assinando) */ public static final string event_type_subscribe = "assinando"; / * * / ** * Tipo de evento: clique (menu personalizado, clique em Evento) */ public static final string event_type_click = "clique"; }Aqui, para melhorar o programa e a escalabilidade, fiz alguns encapsulamento, defini várias constantes e encapsulou alguns parâmetros passados do WeChat para os objetos persistentes do Java Bean. O código principal é como acima. Concentre -se na conversão entre XML e mapa
De fato, esse problema é atribuído ao WeChat usando a comunicação XML e geralmente usamos o JSON, para que possamos nos sentir um pouco desconfortáveis em um curto período de tempo.
1. Introduzir o pacote JAR
<!-Parse xml-> <pendency> <puperiD> dom4j </groupiD> <TROTIFACTID> DOM4J </ARTIFACTID> <Versão> 1.6.1 </versão </dependency> <pendence> <pream> com.thoughtworks.xstream </groupid> <stifactId> xstream </artiftId.
2.xml para mapear objeto de coleta
/*** xml convert para mapa* @param request* @return* @throws ioexception*/ @represswarnings ("desmarcado") public static map <string, string> xmlTOMap (httpServLeTrequest Soldes) lança IoException {Map, string> map = new HasHmAp <string, string) (string; null; try {ins = request.getInputStream ();} catch (ioexception e1) {e1.printStackTrace ();} document doc = null; try {doc = leitor.read.read (ins); elemento root = Doc.GoTrooTELEMENT (); list <lement> list = root.Elements (); elemento (elemento e:); e.getText ());} retornar mapa;} catch (documentException e1) {e1.printStackTrace ();} finalmente {ins.close ();} retornar null;}3. Converta o objeto de mensagem de texto em xml
/ ** * Converta o objeto de mensagem de texto em xml * * @param textMessage Mensagem de texto Objeto * @return xml */ public static string textMessageToxml (textMessage textMessage) {xStream xStream = new XStream (); xStream.alias ("xml", textMessage.clas;O exposto acima é a introdução do editor ao Java para implementar o SpringMVC WeChat Access e implementar a função de resposta automática simples. Espero que seja útil para todos. Se você tiver alguma dúvida, deixe -me uma mensagem e o editor responderá a todos a tempo. Muito obrigado pelo seu apoio ao site wulin.com!