Ich war schon eine Weile mit der Front-End-Zeit beschäftigt. Ich habe die Dokumente von Grund auf neu gelesen und habe viele Fallstricke getreten. Ich habe es in letzter Zeit durchgemacht. Ich habe darüber nachgedacht, eine Zusammenfassung zu machen, damit ich es in Zukunft überprüfen kann, wenn ich es entwickle. Ich werde auch einen Hinweis auf Studenten geben, die an verwandten Projekten arbeiten.
Tatsächlich werden Sie nach dem einmaligen Tun feststellen, dass es nicht schwierig ist. Die allgemeine Idee ist: Benutzernachrichten und Ereignisse, die von Entwicklern erforderlich sind, leiten eine Anforderung über den WeChat -Server ein und leiten sie an die auf der öffentliche Plattform konfigurierte Server -URL -Adresse weiter. Der WeChat -Server bringt vier Parameter mit: Signatur, Zeitstempel, Nonce und Echostr. Unser Server spleißt das von der öffentlichen Plattform konfigurierte Token und den hochgeladenen Zeitstempel. Nonce wird in SHA1 verschlüsselt und entspricht der Signatur. Geben Sie die Ture zurück, um anzuzeigen, dass der Zugang erfolgreich ist.
1. Konfiguration der öffentlichen Plattform
2.Kontroller
@Controller@RequestMapping ("/wechat") publicClass WechatController {@Value ("$ {dnbx_token}") private String dnbx_token; private static Final Logger Logger = Loggerfactory.getLogger (WechatController. @return * @throws ioException */ @requestMapping (value = "/connect", method = {requestMethod.get, requestMethod.post}) @responseBodypublicvoid-ConnectWeixin (httpServletRetRetRetRetrequest-Anforderung, HTTPServletResponse). request.setcharactercoding ("utf-8"); // Der WeChat-Server verwendet die UTF-8-Codierung bei Postnachrichten, und bei Empfangen muss die gleiche Codierung verwendet werden. Andernfalls wird chinesischer verstümmelter Code verstümmelt. response.setcharactercoding ("utf-8"); // Bei der Beantwortung von Nachrichten (Antwort auf den Benutzer) ist die Codierungsmethode auch auf UTF-8 festgelegt, das Prinzip ist das gleiche wie oben. boolean isget = request.getMethod (). TolowerCase (). Equals ("get"); Printwriter out = response.getWriter (); try {if (isget) {String Signature = Request.getParameter ("Signature"); // Wechat -Verschlüsselungssignatur String String Timestamp = Anrequenz.GetParameter ("Timestamp"); // Timestamp String Nonce = Request.getParameter ("Nonce"; // Zufällige Zähle echoStr = request.getParameter ("echostr"); // zufällige String // Überprüfen Sie die Anforderung durch Überprüfen der Signatur. Wenn die Überprüfung erfolgreich ist, geben Sie Echostr so zurück, was darauf hinweist, dass der Zugang erfolgreich ist. Andernfalls schlägt der Zugriff fehl, wenn (Signutil.Checksignature (DNBX_TOKE, Signatur, Zeitstempel, Nonce)) {logger.info ("Verbinden Sie den Wixin -Server an, ist erfolgreich."); response.getWriter (). Write (echostr); } else {logger.Error ("Die Signatur nicht überprüft!"); }}else{String respMessage = "Exception message! ";try {respMessage = wechatService.weixinPost(request);out.write(respMessage);LOGGER.info("The request completed successfully");LOGGER.info("to weixin server "+respMessage);} catch (Exception e) {LOGGER.error("Failed to convert the message from wixin! "); }}} catch (Exception E) {logger.Error ("Verbinden Sie den Weixin -Server ist Fehler.");} schließlich {out.close ();}}}3. Signaturüberprüfungsprüfung
Aus dem obigen Controller können wir feststellen, dass ich eine Werkzeugklasse -Signutil, die als Checksignatur bezeichnet wurde, in Einkapitseln habe und in vier Werten bestanden habe, dnbx_token, Signature, Zeitstempel, Nonce. Dieser Prozess ist sehr wichtig. Tatsächlich können wir es als Verschlüsselungs- und Entschlüsselungsprozess des von WeChat übertragenen Wertes verstehen. Um die Sicherheit zu gewährleisten, haben alle Schnittstellen in vielen großen Projekten einen solchen Überprüfungsprozess. Dnbx_token Wir haben eine Token -Zeichenfolge auf der Wechat Public Platform konfiguriert, die Idee vertraulich halten! Die anderen drei sind Parameter, die vom WeChat -Server gesendet werden, um eine GET -Anforderung zu senden. Wir führen eine Schicht von SHA1 -Verschlüsselung durch:
public class Signutil { / *** Überprüfungssignatur* @param Token WeChat Server -Token, konfiguriert in der Env.Properties -Datei und im Entwicklerzentrum konfiguriert sein muss konsistent sein Signatur, String Timestamp, String nonce) {String [] arr = new String [] {Token, Timestamp, nonce}; // Sortieren Sie die Wörterbuchordnung von Token, Zeitstempel und Nonce; // Die drei Parameterzeichenfolgen in eine Zeichenfolge für die SHA1 -Verschlüsselungszeichenfolge tmpstr = sha1.encode (arr [0] + arr [1] + arr [2]); // Die String verschlüsselte SHA1 kann mit der Signatur verglichen werden und identifiziert, dass die Anfrage von WeChat Return tmpstr! = NULL stammt? tmpstr.equals (Signature.ToUpperCase ()): Falsch; }}SHA1:
/** * WeChat Public Platform (JAVA) SDK * * SHA1 Algorithm * @author helijun 2016/06/15 19:49*/ public final class SHA1 { private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'c', 'd', 'e', 'f'}; /*** Nimmt die rohen Bytes aus dem Digest und formatiert sie korrekt. * * @param Bytes die rohen Bytes aus der Digest. * @return die formatierten Bytes. */ private statische String getFormattedText (byte [] bytes) {int len = bytes.length; StringBuilder buf = new StringBuilder (len * 2); // den Chiffretext in ein hexadezimales Zeichenfolgenform für (int j = 0; j <len; j ++) {buf.Append (hex_digits [(bytes [j] >> 4) & 0x0f] konvertieren; buf.Append (hex_digits [bytes [j] & 0x0f]); } return buf.toString (); } public static String codem (string str) {if (str == null) {return null; } try {MessagedIGest MessagedIGest = MessagedIGest.getInstance ("SHA1"); MessagedIGest.Update (str.getBytes ()); return GetFormattedText (MessagedIGest.Digest ()); } catch (Ausnahme e) {neue runTimeException (e) werfen; }}} Wenn Sie es auf der öffentlichen Plattform einreichen und speichern und die grüne Eingabeaufforderung "Zugangserfolge" sehen, herzlichen Glückwunsch zum Abschluss des WeChat -Zugriffs. Dieser Prozess erfordert etwas mehr sorgfältiger und achtet auf den Fall im Verschlüsselungsalgorithmus. Wenn der Zugang nicht erfolgreich ist, sind die meisten Fälle Probleme mit dem Verschlüsselungsalgorithmus, überprüfen Sie ihn mehr.
4. Implementieren Sie den automatischen Nachrichten -Antwortdienst
/*** Prozessanfragen von WeChat** @param request* @return*/public String weixinPost (httpServletRequest -Anforderung) {String respMessage = null; try {// xml requestars analyse map <String, String> requestmap = messageutil.xmltomap (Request); // Sender Account (Open_id) String von username = requestmap.get ("fromusername"); // öffentliches Konto String tousername = requestmap.get ("tousername"); // Nachrichtentyp String msgType = RequestMap.get ("msgType"); // Nachrichteninhaltsstring -Inhalt = Requestmap.get ("Inhalt"); Logger.info ("Ausname". ", MsgType ist:" + msgType); // Textnachricht if (msgType.equals (messageutil.req_message_type_text)) {// Die entsprechende Logik wird gemäß den Keywords ausgeführt. Es gibt nur einen, den Sie sich nicht vorstellen können. Es gibt nicht so etwas, wie Sie es nicht tun können, wenn (content.equals ("xxx") {} // automatische Antwort textMessage text = new textMessage (); text.setContent ("Der Text ist" + content); text.settousername (fromusername); textfromusername (tousername); ""); text.setmsgType (msgType); respMessage = messageutil.textMessAgetoxml (text);}/*else if (msgtype.equals (messageUtil.req_message_type_event)) {// Ereignisstreicher EreignisType = Anforderung ("Ereignis ("; (eventType.equals (messageutil.event_type_subscribe)) {// resspcontent = "Willkommen, um dem offiziellen XXX -Account zu folgen!"; eventKey = requestmap.get ("eventKey"); // Ereignisschlüsselwert, entsprechend dem Schlüsselwert beim Erstellen des benutzerdefinierten Menü logger.info ("EventKey ist:" +Ereigniskey); RequestMap.get ("Erkennung"); // respcontent = "Empfangenes Sprachanalyseergebnis:"+RecvMessage; if (recvMessage! } // Fotografiefunktion else if (msgType.equals ("pic_SySthoto")) {} else {return messageresponse.getTextMessage (from Unername, tousername, "leer return"); }*// Ereignisschub sonst if (msgType.equals (messageutil.req_message_type_event) {String eventType = RequestMap.get ("Ereignis"); // Ereignistyp // Abonnieren Sie (eventType.equals (messageutil.event_ttype_ssscon) {textType. folgen, xxx "); text.settousername (fromusername); text.setfromusername (tousername); text.setCreateTime (neuer Date (). GetTime () +"); text.setmsgtype (MessageUtil.Resp_Message_Ttype_tex); Der Benutzer kann die vom offiziellen Konto gesendete Nachricht nicht empfangen, sodass nicht auf die Nachricht antworten muss. Ereignisschlüsselwert, entsprechend dem beim Erstellen des benutzerdefinierten Menüs angegebenen Schlüsselwerts (EventKey.equals ("Customer_telephone")) {TextMessage text = new textMessage (); text.setContent ("07555-86671980"); Date (). GetTime () + ""); text.setmsgType (messageUtil.resp_message_type_text); respMessage = messageUtil.textMessAgetoxml (text);}}}}} catch (Ausnahme E) {Logger.Rror ("Fehler ...")} zurücksagen;}} zurückrückerung;}}}}Der Code wird wie oben veröffentlicht. Die meisten von ihnen haben Kommentare. Wenn Sie die grundlegende Semantik einmal lesen, müssen Sie sie nicht erklären.
Kurze Idee: Wenn ein Benutzer eine Nachricht an das offizielle Konto sendet, fordert der WeChat -Server die Benutzernachricht über die entsprechende Schnittstelle des Servers an, das wir im XML -Format konfiguriert haben. Was wir tun müssen, ist, die entsprechende logische Verarbeitung basierend auf dem Nachrichtentyp usw. durchzuführen und das endgültige Rückgabeergebnis über das XML -Format an den WeChat -Server zurückzugeben und es dann an den Benutzer zu übermitteln.
Es gibt einen Ort, an dem besondere Aufmerksamkeit erforderlich ist:
Die roten Färbemöglichkeiten und Tousername sind genau das Gegenteil, was auch eine der Fallstricke ist. Ich erinnere mich, dass ich es schon lange angepasst hatte, aber es war kein Problem, aber es funktionierte nicht. Schließlich habe ich die Nachricht erhalten, nachdem ich diese beiden geändert hatte! Tatsächlich ist es richtig, darüber nachzudenken. Wenn Sie zum WeChat -Server zurückkehren, ändert sich Ihre Rolle, sodass der Absender und der Empfänger definitiv das Gegenteil sind.
5. MessageUtil
public class messageutil {/ *** Rückgabenachricht Typ: Text*/ public static Final String resp_message_type_text = "text"; / *** Rückgabenachrichtentyp: Musik*/ public static Final String resp_message_type_music = "musik"; / *** Rückgabenachricht Typ: Grafischer Text*/ public static Final String resp_message_type_news = "news"; / *** Anforderungsnachricht Typ: Text*/ public static Final String req_message_type_text = "text"; / *** Anforderungsnachricht Typ: Image*/ public static Final String req_message_type_image = "Bild"; / *** Anforderungsnachricht Typ: Link*/ public static Final String req_message_type_link = "link"; / *** Meldungstyp anfordern: Geografischer Standort*/ public static Final String req_message_type_location = "locum"; / *** Anforderungsnachricht Typ: Audio*/ public static Final String req_message_type_voice = "voice"; / ** * Anforderungsnachricht Typ: Push */ public static Final String req_message_type_event = "event"; / ** * Ereignisart: abonnieren (abonnieren) */ public static final String event_type_subscribe = "abonnieren"; / ** * Ereignisart: Absubscribe (Absubscribe) */ public static Final String event_type_unsubScribe = "Absubscribe"; / ** * Ereignisart: Klicken Sie auf (Benutzerdefiniertes Menü klicken Sie auf Ereignis) */ public static Final String event_type_click = "klicken"; }Um die Lesbarkeit und Skalierbarkeit der Programme zu verbessern, habe ich hier einige Einkapselungen vorgenommen, mehrere Konstanten definiert und einige Parameter verkapselt, die von WeChat in Java Bean anhaltenden Objekten übergeben wurden. Der Kerncode ist wie oben. Konzentrieren Sie sich auf die Konvertierung zwischen XML und MAP
Tatsächlich wird dieses Problem mit der XML -Kommunikation WeChat zugeschrieben, und wir verwenden normalerweise JSON, sodass wir uns möglicherweise in kurzer Zeit ein wenig unwohl fühlen.
1. Schleifpaket einlegen
<!-- parse xml --><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency><dependency><groupId>com.thoughtworks.xstream</groupId><artifactId>xstream</artifactId><version>1.4.9</version></dependency>
2.xml, um das Sammlungsobjekt zu kartieren
/*** xml konvertieren auf map = null; try {iNS = request.getInputStream ();} catch (ioException e1) {e1.printstacktrace ();} document doc = null; try {doc = reader.read (Ins); Element root = doc.getRoTelement (); list <element> list = root.elements (); für () für () () () () () () () () () () () () () () () () () () () () () () () () () () ()öde ich () () () () () () () () () () () ()öde ich () () () () () () () ()af ()ömer E.GetText ());} return map;} catch (documentException e1) {e1.printstacktrace ();} schließlich {Ins.close ();} return null;}3.. Konvertieren Sie das SMS -Objekt in XML
/ ** * Textnachricht Objekt in xml * * @param textMessage Textnachricht Objekt * @return xml */ public static String textMessagetoxml (textMessage textMessage) {xstream xstream = new xstream (); xstream.alias ("xml", textmessage.get);Das obige ist die Einführung des Editors in Java zur Implementierung des SpringMVC -WeChat -Zugriffs und der einfachen automatischen Antwortfunktion. Ich hoffe, es wird für alle hilfreich sein. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht und der Editor wird allen rechtzeitig antworten. Vielen Dank für Ihre Unterstützung auf der Wulin.com -Website!