Java realizes SPRINGMVC mode of micro-letter access, and realizes simple automatic reply function _java

Source: Internet
Author: User
Tags sha1 sha1 encryption

Front-end time small busy for a while, the development of micro-letter public number, from scratch to see the document, stepped on a lot of pits, is also a boil over, and recently consider doing some summary, convenient later when the development of the review, but also to do related projects to do a reference.

In fact, after a time will find it is not difficult, the general idea: User messages and developers need the event push through the micro-trust server to initiate a request, forwarded to your public platform configuration of the server URL address, the micro-letter will take Signature,timestamp,nonce, ECHOSTR four parameters, our own server through the Mosaic public platform configuration token, as well as the timestamp,nonce SHA1 encrypted after the matching signature, return ture description access success.

1. Public platform Configuration

2.Controller

@Controller @RequestMapping ("/wechat") Publicclass Wechatcontroller {@Value ("${dnbx_token}") Private String Dnbx_
TOKEN;
private static final Logger Logger = Loggerfactory.getlogger (Wechatcontroller.class);
@Resource Wechatservice Wechatservice; /** * Micro-letter Access * @param WC * @return * @throws IOException/@RequestMapping (value= "/connect", method = {Requestmethod.get, R Equestmethod.post}) @ResponseBody publicvoid connectweixin (httpservletrequest request, httpservletresponse response) Throws ioexception{///The encoding of the request and response is set to UTF-8 (prevent Chinese garbled) request.setcharacterencoding ("UTF-8");//micro-letter Server post message with UTF-8 code, In the receiving also want to use the same code, otherwise Chinese will garbled; response.setcharacterencoding ("UTF-8"); 
In response to a message (reply to the message to the user), the encoding is also set to UTF-8, the principle above, Boolean isget = Request.getmethod (). toLowerCase (). Equals ("get");
PrintWriter out = Response.getwriter (); try {if (isget) {string signature = Request.getparameter ("signature");//micro-letter Encryption Signature string timestamp = Request.getparameter ("timestamp");/time stamp String nonce = Request.getparameter ("nonce");Number of machines String echostr = Request.getparameter ("Echostr");//random string//Check the request through the test signature, if the validation is successful then return to the ECHOSTR, indicating the success of the access, or access failure if (Signutil.checksignature (Dnbx_token, signature, timestamp, nonce)) {logger.info ("Connect" Weixin server is success
ful. "); 
Response.getwriter (). write (ECHOSTR); 
else {logger.error ("Failed to verify the signature!"); }}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"-weixin!); The catch (Exception e) {logger.error ("Connect the Weixin server is error.");}
finally{out.close ();} }

3. Signature Verification Checksignature

From the above controller we can see that I encapsulated a tool class Signutil, called Checksignature inside, and passed in four values, Dnbx_token, signature, timestamp, nonce. This process is very important, in fact, we can understand that the micro-letter passed the value of a process of encryption and decryption, many large projects all the interfaces to ensure that security will have such a validation process. Dnbx_token we have a token string configured in the micro-trust public platform, the idea is secret Oh! The other three are the parameters that the micro-mail server sends the GET request, and we do a layer of SHA1 encryption:

public class Signutil { 
/** 
* Authentication Signature 
* 
* @param token micro-server token, configured in the Env.properties file and configured in the developer center must be consistent 
* @param signature Micro-trust Server SHA1 encrypted certificate signature
* @param timestamp timestamp
* @param nonce random number 
* @return 
* * public static Boolean checksignature (String token,string signature, string timestamp, string nonce) { 
string[] arr = New string[] {token, timestamp, nonce}; 
The token, timestamp, nonce three parameters are sorted in dictionary order 
Arrays.sort (arr); 
Concatenation of three parameter strings into a string for SHA1 encryption 
string tmpstr = Sha1.encode (arr[0] + arr[1] + arr[2); 
The SHA1 encrypted string can be compared with signature to identify the request from the micro-letter return 
tmpstr!= null tmpstr.equals (Signature.touppercase ()): false;< c18/>} 
}

SHA1:

/** * Micro-trust 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 '}; 
/** * takes the raw bytes from the digest and formats them. 
* * @param bytes The raw bytes from the digest. 
* @return the formatted bytes. 
* * private static String getformattedtext (byte[] bytes) {int len = bytes.length; 
StringBuilder buf = new StringBuilder (len * 2); 
Converts the cipher text into a string form of 16 for (int j = 0; J < Len; J +) {Buf.append (hex_digits[(BYTES[J) >> 4) & 0x0f]); 
Buf.append (Hex_digits[bytes[j] & 0x0f]); 
return buf.tostring (); 
public static string encode (String str) {if (str = null) {return null; 
try {messagedigest messagedigest = messagedigest.getinstance ("SHA1"); 
Messagedigest.update (Str.getbytes ()); 
Return Getformattedtext (Messagedigest.digest ()); catch (Exception e) {throw new Runtimeexception (e); } 
} 
}

When you submit a save on the public platform and see the green hint "access successful", congratulations you have completed the micro-letter access. This process needs to be careful, pay attention to the case of encryption algorithm, if the access is unsuccessful, most cases are the problem of encryption algorithm, multiple checks.

4. Realize message Automatic reply service

/** * Processing of requests for micro-letters * * @param request * @return */public String weixinpost (HttpServletRequest request) {string Respmessag
e = null; try {//XML request resolution Map<string, string> Requestmap = messageutil.xmltomap (request);//Sender account (open_id) String Fromuserna
me = Requestmap.get ("Fromusername");
Public account String Tousername = Requestmap.get ("Tousername");
Message type String Msgtype = Requestmap.get ("Msgtype");
Message contents String content = Requestmap.get ("content");
Logger.info ("Fromusername is:" + Fromusername + ", Tousername are:" + Tousername + ", Msgtype is:" + msgtype); Text message if (Msgtype.equals (Messageutil.req_message_type_text)) {///here according to the keyword to execute the corresponding logic, only you can not imagine, there is no can not do if (content.equals) ("
XXX ")) {}//automatically reply textmessage text = new TextMessage ();
Text.setcontent ("The text is" + content);
Text.settousername (Fromusername);
Text.setfromusername (Tousername);
Text.setcreatetime (New Date (). GetTime () + "");
Text.setmsgtype (Msgtype);
Respmessage = Messageutil.textmessagetoxml (text); }/*else if (Msgtype.equals MessaGeutil.req_message_type_event)) {//event push String EventType = Requestmap.get ("event");//Event type if (Eventtype.equals ( Messageutil.event_type_subscribe)) {//subscribe to Respcontent = "welcome attention to XXX public number!"
";
Return Messageresponse.gettextmessage (Fromusername, Tousername, respcontent); else if (eventtype.equals (Messageutil.event_type_click)) {//custom menu click event String eventkey = Requestmap.get ("Eventkey");
/Event key value, corresponding to the key value specified when creating the custom menu Logger.info ("Eventkey is:" +eventkey);
return xxx; 2015-3-30 Else if (msgtype.equals ("Voice")) {String recvmessage = requestmap.get ("recognition") for micro-letter sound recognition test;//RESPC
Ontent = "Received speech parsing result:" +recvmessage; if (recvmessage!=null) {respcontent = Tulingapiprocess.gettulingresult (recvmessage);} else{respcontent = "You are too vague, can you say it again?"
";
} 
Return Messageresponse.gettextmessage (Fromusername, Tousername, respcontent); }//Photo function else if (msgtype.equals ("Pic_sysphoto")) {} else {return messageresponse.gettextmessage (Fromusername, Touserna 
Me, "Back to Empty"); }*///Event Push else if (Msgtype.equals (Messageutil.req_message_type_event)) {String EventType = Requestmap.get ("event");//Event type//subscription if (Eventtype.equals (
Messageutil.event_type_subscribe)) {textmessage text = new TextMessage (); Text.setcontent ("Welcome attention, XXX");
Text.settousername (Fromusername);
Text.setfromusername (Tousername);
Text.setcreatetime (New Date (). GetTime () + "");
Text.setmsgtype (Messageutil.resp_message_type_text);
Respmessage = Messageutil.textmessagetoxml (text); //TODO Unsubscribe after the user can not receive the public number sent messages, so do not need to reply to the message else if (Eventtype.equals (Messageutil.event_type_unsubscribe)) {//unsubscribe}//Custom Menu click event Else if (Eventtype.equals (Messageutil.event_type_click)) {String Eventkey = requestmap.get ("Eventkey");
The event key value that corresponds to the IF (Eventkey.equals ("Customer_telephone")) {textmessage text = new TextMessage () when the key value specified when creating the custom menu;
Text.setcontent ("0755-86671980");
Text.settousername (Fromusername);
Text.setfromusername (Tousername);
Text.setcreatetime (New Date (). GetTime () + "");
Text.setmsgtype (Messageutil.resp_message_type_text); Respmessage = MEssageutil.textmessagetoxml (text); catch (Exception e) {logger.error ("error ...")} return respmessage;}

First paste code as above, most have comments, read the basic semantics also understand that do not need more explanation.

The brief idea: when the user sends the message to the public number, the micro-trust server will send the user message in the XML format through the POST request to our configured server corresponding interface, and we do the thing is according to the message type and so on the corresponding logic processing, The final return result is also returned to the micro-trust server through the XML format, which is communicated to the user by the micro-signaling process.

There is one place that needs to be noted in particular:

the above marked red Fromusername and Tousername just the opposite, this is also one of the pits, remember I was adjusted for a long time, obviously there is no problem is not pass, and finally put the two a change of message received! In fact, back to think also right, back to the micro-trust server at this time the role of the change, so the sending and receiving side is also certainly the opposite.

5.MessageUtil

public class Messageutil {/** * return message type: text/public static final String resp_message_type_text = "text"; 
/** * Return message type: Music/public static final String resp_message_type_music = "musical"; 
/** * Return Message type: text/* public static final String resp_message_type_news = "News"; 
/** * Request Message Type: Text */public static final String req_message_type_text = "text"; 
/** * Request Message type: Picture */public static final String req_message_type_image = "image"; 
/** * Request Message Type: Link/public static final String Req_message_type_link = "link"; 
/** * Request Message Type: GEO/public static final String req_message_type_location = "LOCATION"; 
/** * Request Message Type: Audio/public static final String Req_message_type_voice = "VOICE"; 
/** * Request Message Type: Push/public static final String req_message_type_event = "EVENT"; 
/** * Event Type: Subscribe (subscribe)/public static final String event_type_subscribe = "subscribe"; 
/** * Event Type: Unsubscribe (UNSUBSCRIBE)/public static final String event_type_unsubscribe = "unsubscribe"; /** * Event Type: CLICK (custom menu click event)/public static final String Event_type_click = "click"; }

Here for the readability and extensibility of the program, I did some encapsulation, defined a few constants, and encapsulated some of the micro-letter parameters into Java Bean Persistence objects, as the core code above. Focus on the transformation between XML and map

In fact, the problem is that the micro-letter is used in XML communication, and we usually use JSON, so it may be a little bit inappropriate in a short time

1. Introducing Jar Packs

<!--parsing 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 Turn Map Collection Object

/**
* XML converted to map
* @param request
* @return
* @throws ioexception
/@SuppressWarnings (" Unchecked ") public
static map<string, string> Xmltomap (HttpServletRequest request) throws ioexception{
map<string, string> map = new hashmap<string, string> ();
Saxreader reader = new Saxreader ();
InputStream ins = null;
try {
ins = Request.getinputstream ();
} catch (IOException E1) {
e1.printstacktrace ();
}
Document doc = null;
try {
doc = reader.read (ins);
Element root = Doc.getrootelement ();
list<element> list = Root.elements ();
for (Element e:list) {
map.put (E.getname (), E.gettext ());
}
return map;
} catch (Documentexception E1) {
e1.printstacktrace ();
} finally{
ins.close ();
}
return null;
}

3. Convert text message objects to XML

/** 
* Text message object converted to XML 
* 
* @param textmessage Text Message Object 
* @return XML/Public 
static String Textmessagetoxml (TextMessage textmessage) {
XStream XStream = new XStream ();
Xstream.alias ("xml", Textmessage.getclass ());
Return Xstream.toxml (TextMessage);
}

The above is a small set of Java to introduce the implementation of SPRINGMVC way of micro-letter access, to achieve a simple automatic response function, I hope to help you, if you have any questions please give me a message, small series will promptly reply to everyone. Here also thank you very much for the cloud Habitat Community website support!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.