This article will talk about the first step in WeChat development, the access to the official account and the management of access_token.
1. Access to WeChat official account
In the WeChat official account development manual, the content about the official account access section is written in more detail. The document says that accessing the official account requires three steps, namely:
In fact, step 3 can no longer be considered as the step of accessing the official account. However, after access, developers can do some development based on the interface provided by the WeChat official account.
In step 1, the server configuration includes the server address (URL), Token and EncodingAESKey.
The server address is the entrance address that provides business logic to the backend of the official account. Currently, it only supports port 80. After that, access verification and any other operation requests (such as message sending, menu management, material management, etc.) must be entered from this address. The difference between access verification and other requests is that when access verification is a get request, and when other times it is a post request;
The token can be filled in by the developer and used as a signature to generate (the token will be compared with the token contained in the interface URL to verify security);
EncodingAESKey is manually filled in or randomly generated by the developer and will be used as the message body encrypted decryption key. In this example, all are unencrypted plaintext messages, and this configuration item is not involved.
Step 2: Verify the validity of the server address. When clicking the "Submit" button, the WeChat server will send an http get request to the server address you just filled in, and carry four parameters:
After receiving the request, we need to do the following three steps. If we confirm that the GET request comes from the WeChat server and return the echostr parameter content as it is, the access will take effect, otherwise the access will fail.
The code can talk. The following is an entry servlevt I defined, in which the verification method is defined in the doGet method:
//tokenprivate final String token = "fengzheng"; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("Start signature verification"); String signature = request.getParameter("signature"); String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); ArrayList<String> array = new ArrayList<String>(); array.add(signature); array.add(timestamp); array.add(nonce); //Sorting String sortString = sort(token, timestamp, nonce); //Encrypt String mytoken = Descript.SHA1(sortString); //Check signature if (mytoken != null && mytoken != "" && mytoken.equals(signature)) { System.out.println("Signature verification passes."); response.getWriter().println(echostr); //If the verification is successfully outputted echostr, the WeChat server will confirm that the verification is completed only after receiving this output. } else { System.out.println("Signature verification failed."); }} /** * Sort method* @param token * @param timestamp * @param nonce * @return */public static String sort(String token, String timestamp, String nonce) { String[] strArray = { token, timestamp, nonce }; Arrays.sort(strArray); StringBuilder sbuilder = new StringBuilder(); for (String str: strArray) { sbuilder.append(str); } return sbuilder.toString();}The following code is the encryption method:
public class Descript { public static String SHA1(String descript) { try { MessageDigest digest = MessageDigest .getInstance("SHA-1"); digest.update(descript.getBytes()); byte messageDigest[] = digest.digest(); // Create Hex String StringBuffer hexString = new StringBuffer(); // Convert byte array to hexadecimal number for (int i = 0; i < messageDigest.length; i++) { String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); if (shaHex.length() < 2) { hexString.append(0); } hexString.append(shaHex); } return hexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; }}The xml mapped by the servlet is as follows:
<servlet> <servlet-name>Start</servlet-name> <servlet-class>org.fengzheng.wechat.Start</servlet-class></servlet><servlet-mapping> <servlet-name>Start</servlet-name> <url-pattern>/wechat</url-pattern></servlet-mapping>
I am using IntelliJ IDEA+tomcat7.0 development here, start the project directly, and then use ngrok to map the local 8080 port to the external network. Enter the WeChat test official account management interface, fill in the mapped external network address and token in the interface configuration information.
Click the Submit button and the page will prompt that the configuration is successful.
You will go to the IDE and see the information output in the console
2. Access_token management
Before access_token, there are two important parameters that need to be known. These two parameters are appID and appsecret. This is automatically assigned to the official account when applying for an official account. It is equivalent to the identity mark of the official account. These two parameters are needed in many interfaces. Next, when requesting access_token, these two parameters are needed.
After the official account is successfully accessed, the corresponding logic must be implemented. When using the WeChat official account interface, I found that many requests require access_token. access_token is the global unique credential of the official account. Access_token is required when calling each interface of the official account. Developers need to save it properly. The storage of access_token must retain at least 512 character space. The validity period of access_token is currently 2 hours and needs to be refreshed regularly. Repeated acquisition will cause the access_token you obtained last time to be invalid. And the upper limit of the access_token interface is called every day is 2,000 times.
To summarize the above explanation, access_token needs to do the following two points:
In this regard, the solution adopted here is as follows: define a default startup servlet, start a Thread in the init method, and define an infinite loop method in this process to obtain access_token. When the acquisition is successful, the process sleeps for 7000 seconds, otherwise it will sleep for 3 seconds to continue to obtain. The flow chart is as follows:
The following is the above idea that has been implemented in the project, because the returned data is all in json format, Alibaba's fastjson library will be used here to provide support for data serialization and deserialization after constructing requests and processing requests. Other subsequent interfaces will also be used.
1. Define an AccessToken entity
public class AccessToken { public String getAccessToken() { return accessToken; } public void setAccessToken(String accessToken) { this.accessToken = accessToken; } public int getExpiresin() { return expiresin; } public void setExpiresin(int expiresin) { this.expiresin = expiresin; } private String accessToken; private int expiresin; } 2. Define a default startup servlet, start a Thread in the init method, and set this servlet to the default self-start in web.xml.
import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;@WebServlet(name = "AccessTokenServlet")public class AccessTokenServlet extends HttpServlet { public void init() throws ServletException { TokenThread.appId = getInitParameter("appid"); //Get the initial parameters of servlet appid and appsecret TokenThread.appSecret = getInitParameter("appsecret"); System.out.println("appid:"+TokenThread.appId); System.out.println("appSecret:"+TokenThread.appSecret); new Thread(new TokenThread()).start(); //Start the process} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { }} Set servlet autostart in web.xml and set initialization parameters appid and appsecret
<servlet> <servlet-name>initAccessTokenServlet</servlet-name> <servlet-class> org.fengzheng.wechat.accesstoken.AccessTokenServlet </servlet-class> <init-param> <param-name>appid</param-name> <param-value>your appid</param-value> </init-param> <init-param> <param-name>appsecret</param-name> <param-value>your appsecret</param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet>
3. Define the Thread class, call access_token in this class to get the interface, and abstract the resulting data to a static entity for use in other places. The interface address is https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET, where grant_type is fixedly written as client_credential. This request is a https get request, and the returned data format is {"access_token":"ACCESS_TOKEN","expires_in":7200}.
The process class implementation is as follows:
import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import org.fengzheng.wechat.common.NetWorkHelper;public class TokenThread implements Runnable { public static String appId = ""; public static String appSecret= "";<br> //Note that it is static public static AccessToken accessToken = null; public void run(){ while (true){ try{ accessToken = this.getAccessToken(); if(null!=accessToken){ System.out.println(accessToken.getAccessToken()); Thread.sleep(7000 * 1000); //Get access_token to sleep for 7000 seconds}else{ Thread.sleep(1000*3); //The access_token obtained is empty sleep for 3 seconds} } catch(Exception e){ System.out.println("Exception occurs: "+e.getMessage()); e.printStackTrace(); try{ Thread.sleep(1000*10); //The exception occurs to sleep for 1 second} catch (Exception e1){ } } } } } /** * Get access_token * @return */ private AccessToken getAccessToken(){ NetWorkHelper netHelper = new NetWorkHelper(); String Url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",this.appId,this.appSecret); String result = netHelper.getHttpsResponse(Url,""); System.out.println(result); //response.getWriter().println(result); JSONObject json = JSON.parseObject(result); AccessToken token = new AccessToken(); token.setAccessToken(json.getString("access_token")); token.setExpiresin(json.getInteger("expires_in")); return token; }}The getHttpsResponse method in NetWorkHelper requests an https address, the parameter requestMethod is the string "GET" or "POST", and the default is the get method.
Implementation is as follows:
public String getHttpsResponse(String hsUrl,String requestMethod) { URL url; InputStream is = null; String resultData = ""; try { url = new URL(hsUrl); HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); TrustManager[] tm = {xtm}; SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(null, tm, null); con.setSSLSocketFactory(ctx.getSocketFactory()); con.setHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String arg0, SSLSession arg1) { return true; } }); con.setDoInput(true); //Allow input streams, that is, downloads,/In android, this item must be set to false con.setDoOutput(false); //Allow output streams, that is, uploads con.setUseCaches(false); //Do not use buffering if(null!=requestMethod && !requestMethod.equals("")) { con.setRequestMethod(requestMethod); //Use the specified method} else{ con.setRequestMethod("GET"); //Use get request} is = con.getInputStream(); //Get the input stream, and then the link is actually established. InputStreamReader isr = new InputStreamReader(is); BufferedReader bufferReader = new BufferedReader(isr); String inputLine = ""; while ((inputLine = bufferReader.readLine()) != null) { resultData += inputLine + "/n"; } System.out.println(resultData); Certificate[] certs = con.getServerCertificates(); int certNum = 1; for (Certificate cert : certs) { X509Certificate xcert = (X509Certificate) cert; } } catch (Exception e) { e.printStackTrace(); } return resultData; } X509TrustManager xtm = new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { // TODO Auto-generated method stub return null; } @Override public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { // TODO Auto-generated method stub } @Override public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { // TODO Auto-generated method stub } };At this point, after the code is implemented, the project is deployed, and the console output is as follows:
To view the effect, you can set the sleep time a little shorter, such as obtaining it once in 30 seconds, and then outputting access_token. Let’s do a test jsp page and set the sleep time to 30 seconds. In this way, after 30 seconds, you can see the changes. By the way, how to get access_token in other places
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%@ page import="org.fengzheng.wechat.accesstoken.TokenThread" %><html> <head> <title></title> </head> <body> access_token is: <%=TokenThread.accessToken.getAccessToken()%> </body></html>
This way, browse this page on the browser, and the display effect is as follows:
Refreshed after 30 seconds, this value changed:
This article has been compiled into "Android WeChat Development Tutorial Summary", and "Java WeChat Development Tutorial Summary" welcomes everyone to learn and read.
The above is all about this article. I hope it will be helpful for everyone to develop a java WeChat official account.