This article mainly introduces step 4 of java API development, custom menu and personalized menu implementation, interested friends can refer to this article for details on java API development step 4, custom menus and personalized menu implementation. interested friends can refer
The following describes how to customize a menu.
1. global description
For more information, see the first two articles.
II. description
This article is divided into five parts:
* Encapsulation of AccessTokenUtils
* Reading and parsing of custom menus and personalized menu documents
* Analyze menu JSON and build corresponding bean
* Implementation of custom menus
* Implementation of personalized menus
A demonstration is provided for all types of custom menus.
At the end of this article, we will provide all the demo source code including the first four articles in this article.
Encapsulation of AccessTokenUtils
The AccessToken acquisition and timed saving in the above section have been described in detail. here, the AccessTokenUtils encapsulated after processing is provided directly. the implementation principle and documentation are not provided.
AccessTokenUtils. java
Package com. gist. utils; import java. io. file; import java. io. fileInputStream; import java. io. fileOutputStream; import java. io. IOException; import java. io. inputStreamReader; import java.net. URL; import javax.net. ssl. httpsURLConnection; import com. gist. bean. access_token; import com. google. gson. gson;/*** @ author GaoyuanEmail: wgyscsf@163.comBlog http://blog.csdn.net/wgyscsf </N> * write period 5:44:33 */public class AccessTokenUtils {private static final long MAX_TIME = 7200*1000; // allow maximum Access_token validity period (MS) private static final String TAG = "WeixinApiTest"; // TAG private static final String APPID = "wx889b020b3666b0b8"; // APPID private static final String SECERT = "secret "; // key/** this method is used to obtain and save Access_token for only two hours. If it is more than two hours, you can get it again. if it is less than two hours, you can get it directly. This method depends on *: public static String getAccessToken (); ** train of thought: store the obtained Access_token and current time in file, * determine the time difference between the current time and the time of the records in the storage. if the time difference is greater than MAX_TIME, obtain the record again and replace the obtained file with the original content *, if it is less than MAX_TIME, you can obtain it directly. * /// Catch all exceptions here to ensure that no exception is thrown for the call. the code is a bit long public static String getSavedAccess_token () {Gson gson = new Gson (); // third-party jar, string mAccess_token = null for converting json and bean; // Access_token to be obtained; FileOutputStream fos = null; // output stream FileInputStream FD = null; // input stream File file = new File ("temp_access_token.temp"); // try {// create if (! File. exists () {file. createNewFile () ;}} catch (Exception e1) {e1.printStackTrace () ;}// if the file size is equal to 0, it indicates the first time Access_token if (file. length () = 0) {try {mAccess_token = getAccessToken (); // Obtain the AccessToken Access_token at = new Access_token ();. setAccess_token (mAccess_token);. setExpires_in (System. currentTimeMillis () + ""); // Set the storage time String json = gson. toJson (at); fos = new FileOutputStream (fi Le, false); // do not allow appending fos. write (json ). getBytes (); // Save the AccessToken and current time to the file fos. close (); return mAccess_token;} catch (Exception e) {e. printStackTrace () ;}} else {// read the file content byte [] B = new byte [2048]; int len = 0; try {fs = new FileInputStream (file ); len = fi. read (B);} catch (IOException e1) {// TODO Auto-generated catch block e1.printStackTrace ();} String mJsonAccess_token = new String (B, 0, len); // Access_token access_token = gson. fromJson (mJsonAccess_token, new Access_token (). getClass (); if (access_token.getExpires_in ()! = Null) {long saveTime = Long. parseLong (access_token.getExpires_in (); long nowTime = System. currentTimeMillis (); long remianTime = nowTime-saveTime; // System. out. println (TAG + "Time difference:" + remianTime + "ms"); if (remianTime <MAX_TIME) {Access_token at = gson. fromJson (mJsonAccess_token, new Access_token (). getClass (); mAccess_token =. getAccess_token (); return mAccess_token;} else {mAccess_to Ken = getAccessToken (); Access_token at = new Access_token ();. setAccess_token (mAccess_token);. setExpires_in (System. currentTimeMillis () + ""); String json = gson. toJson (at); try {fos = new FileOutputStream (file, false); // do not allow appending fos. write (json ). getBytes (); fos. close ();} catch (IOException e) {// TODO Auto-generated catch block e. printStackTrace ();} return mAccess_token;} else {return Null ;}} return mAccess_token;}/** get the server AccessToken. This part is consistent with getAccess_token () and no comments are added */public static String getAccessToken () {String urlString =" https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid= "+ APPID +" & secret = "+ SECERT; String reslut = null; try {URL reqURL = new URL (urlString); HttpsURLConnection httpsConn = (HttpsURLConnection) reqURL. openConnection (); InputStreamReader isr = new InputStreamReader (httpsConn. getInputStream (); char [] chars = new char [1024]; reslut = ""; int len; while (len = isr. read (chars ))! =-1) {reslut + = new String (chars, 0, len);} isr. close ();} catch (IOException e) {e. printStackTrace ();} Gson gson = new Gson (); Access_token access_token = gson. fromJson (reslut, new Access_token (). getClass (); if (access_token.getAccess_token ()! = Null) {return access_token.getAccess_token () ;}else {return null ;}}}
Reading and parsing of custom menus and personalized menu documents
• Custom menu
Interfaces for creating custom menus
◦ Custom menu query interface
◦ Custom menu deletion interface
◦ Custom menu event push
Customized Menu interface
◦ Obtain the menu configuration of the public account
• Documentation: http://mp.weixin.qq.com/wiki/10/0234e39a2025342c17a7d23595c6b40a.html
• The official documentation provides the following explanation:
* The custom menu interface supports multiple types of buttons: 1. click: click event ...; 2. view: Jump event ...; 3 ,... (about custom menus)
* Interface call request description http request method: POST (please use https protocol) https://api.weixin.qq.com/cgi-bin/menu/create? Access_token = ACCESS_TOKEN (about custom menus)
* Click and view request example {"button": [...]} (about custom menu)
* Parameter description... (about the custom menu)
* Create personalized menu http request method: POST (please use https protocol) https://api.weixin.qq.com/cgi-bin/menu/addconditional? Access_token = ACCESS_TOKEN (about personalized menus)
* Request example: {"button": [...], "matchrule": {...} (about the personalized menu)
* Parameter description... (about personalized menu)
* Developers can set menus that users can see (about personalized menus) by using the following conditions ):
1. user groups (developers can use user groups to meet their business needs)
2. Gender
3. mobile OS
4. region (the region set by the user on the client)
5. language (language set by the user on the client)
• Understanding:
Callback is a familiar POST request. However, the call seems vague and unclear. We only know that we need to use "? Access_token = ACCESS_TOKEN ", which we have obtained in the previous article. If we replace "ACCESS_TOKEN" in the request address given by the document with our own ACCESS_TOKEN, and access this URL, we will see "{" errcode ": 44002," errmsg ": "empty post data hint: [Gdveda0984vr23]"} ". It indicates that the post request data is empty. Therefore, we need to pass the parameter to the server in the form of a POST request. the format of the parameter is also given below: {"button": […]}, Therefore, we need to pass parameters to the server in this format.
For Parameter descriptions, we can see that there are seven parameters in the custom menu creation. In addition to these seven parameters, the personalized menu interface has eight more parameters. In this document, we can see that these eight parameters are used for personalized menus for matching and filtering.
Parse now, we need to construct json according to the requirements of the document to send this string of json data to the server through the post request. json contains various types of button events we have created.
Analyze menu JSON and build corresponding bean
Custom menu json analysis (excluding personalized menus ). The following code is an example provided by the document.
Click and view request example
{"Button": [{"type": "click", "name": "Today's songs", "key": "V1001_TODAY_MUSIC" },{ "name ": "Menu", "sub_button": [{"type": "view", "name": "Search", "url": "http://www.soso.com /"}, {"type": "view", "name": "video", "url": "http://v.qq.com/" },{ "type": "click", "name ": "Like Us", "key": "V1001_GOOD"}]}
After analysis, we can see that the json data is divided into three layers: "" button ":[{...}, {…}]" , "[{…}, {"Name": menu, "sub_button": [{},{}]}] "," {"type": "view", "name :": "Video", "url ":"..."}, {},{} ", May look dizzy.
However, if we can think of the menus we see in reality, it will be better understood: Level 1: menu (one menu), including one or three parent buttons; Level 2: parent button (1 ~ Three parent buttons), including one to five child buttons; Level 3: child buttons (1 ~ 5 Sub-buttons ).
Now we can see that json corresponds to the menu we understand. The focus now is on how to confirm the "level name" of each level, which is also the corresponding javabean object in java.
At the same time, because there are multiple parent buttons under the level-1 menu, it is a List <父菜单> . The parent button may have multiple sub-menus, which are also a List <子菜单> However, the parent button may also be a single response button. Is a separate parent button object. A sub-button is a separate sub-button object.
For more information about the parameters of the custom menu, we can see that the buttons are divided into Level 1 buttons ("button") and Level 2 buttons ("sub_button "). There are also some common data types, such as: menu response type ("type"), menu title ("name"), click type parameters ("key ") view parameters ("url"), media_id, and view_limited parameters ("media_id ").
• Data abstraction (no setter or getter is written ):
// Button base class public class BaseButton {private String type; private String name; private String key; private String url; private String media_id ;} // subbutton public class SonButton extends BaseButton {private String sub_button;} // parent button public class FatherButton extends BaseButton {private String button; // A parent button may directly respond @ SerializedName ("sub_button") // to ensure that the name of the child button after Gson resolution is "sub_button", please search for private List
SonButtons; // multiple sub-buttons may exist} public class Menu {@ SerializedName ("button") private List
FatherButtons ;}
The above is the complete analysis of the custom menu and the construction of the corresponding javabean.
For a personalized menu, if you view this part of the document, you will find that it is roughly the same as the custom menu, but there are multiple "configuration" json files in the format of {"button ": […]," Matchrule ":{...}}.
We found that the "match" json and "button" are at the same level. the analysis and implementation are basically the same as those above, and the implementation of the javabean is provided directly.
// Jsonpublic class MatchRule {private String group_id; private String sex; private String client_platform_type; private String country; private String province; private String city; private String language ;} // modify Menu. javapublic class Menu {@ SerializedName ("button") private List
FatherButtons; private MatchRule matchrule ;}
Implementation of custom menus
Task, we implement all button response types:
Task (note: "m-0" represents the parent button; "m-n" represents the m parent button, the n child button (m, n = 0): 1-0: name: click, response click event: click push event. 2-0: Name: parent button 2. 2-1: Name: view, response event: Jump to webpage; 2-2: Name: scancode_push, response event: scan code push event; 2-3: Name: scancode_waitmsg, response event: Scan the QR code to push the event and the prompt box "message receiving in progress" is displayed. 2-4: Name: pic_sysphoto, which responds to the event
: The system screenshot is displayed. 2-5: Name: pic_photo_or_album. Response event: a photo or album is displayed. 3-0: Name: parent button 3. 3-1: Name
: Pic_weixin, response event: pop-up album poster; 3-2: Name: location_select, response event: pop-up location selector; 3-3: Name: media_id, response event: send downstream messages (except text messages); 3-4: Name: view_limited; response event: Jump to the url of the text message.
Implementation source code (the referenced AccessTokenUtils. java is encapsulated in the first part: the tool class AccessTokenUtils)
/** Create a custom menu. * // @ Test public void createCommMenu () {String ACCESS_TOKEN = AccessTokenUtils. getAccessToken (); // Obtain the AccessToken. AccessTokenUtils is the encapsulated class. // The httpsurl link required by the splicing api String urlString =" https://api.weixin.qq.com/cgi-bin/menu/create?access_token= "+ ACCESS_TOKEN; try {// Create a url URL reqURL = new URL (urlString); // Obtain the link HttpsURLConnection httpsConn = (HttpsURLConnection) reqURL. openConnection (); httpsConn. setDoOutput (true); // gets the output stream of the connection to read the response content OutputStreamWriter osr = new OutputStreamWriter (httpsConn. getOutputStream (); osr. write (getMenuJson (); // use the external method of this class getMenuJson () osr. close (); // The Returned result InputStreamReader isr = new InputStreamReader (HttpsConn. getInputStream (); // read the server's response and display char [] chars = new char [1024]; String reslut = ""; int len; while (len = isr. read (chars ))! =-1) {reslut + = new String (chars, 0, len);} System. out. println ("returned result:" + reslut); isr. close ();} catch (IOException e) {e. printStackTrace () ;}} public String getMenuJson () {Gson gson = new Gson (); // json processing tool Menu menu = new Menu (); // Menu class List
FatherButtons = new ArrayList
(); // Parent button set in the menu // ----------- // parent button 1 FatherButton fb1 = new FatherButton (); fb1.setName ("click"); fb1.setType ("click "); fb1.setKey ("10"); // ------------- // parent button 2 FatherButton fb2 = new FatherButton (); fb2.setName ("Parent button 2"); List
SonButtons2 = new ArrayList
(); // Subbutton set // subbutton 2-1 SonButton sb21 = new SonButton (); sb21.setName ("view"); sb21.setUrl ("http://www.baidu.com "); sb21.setType ("view"); // sub-button 2-2 SonButton sb22 = new SonButton (); sb22.setName ("scancode_push"); sb22.setType ("scancode_push "); sb22.setKey ("22"); // sub-button 2-3 SonButton sb23 = new SonButton (); sb23.setName ("scancode_waitmsg"); sb23.setType ("scancode_waitmsg "); sb23.setKey ("23"); // sub-button 2-4 SonButton sb24 = new SonButton (); sb24.setName ("pic_sysphoto"); sb24.setType ("pic_sysphoto "); sb24.setKey ("24"); // sub-button 2-5 SonButton sb25 = new SonButton (); sb25.setName ("pic_photo_or_album"); sb25.setType ("pic_photo_or_album "); sb25.setKey ("25"); // add the child button to the child button set sonButtons2.add (sb21); sonButtons2.add (sb22); sonButtons2.add (sb23); sonButtons2.add (sb24 ); sonButtons2.add (sb25); // place the child button to a 2-0 parent button set fb2.setSonButtons (sonButtons2); // ---------------- // parent button 3 FatherButton fb3 = new FatherButton (); fb3.setName ("Parent button 3"); List
SonButtons3 = new ArrayList
(); // Subbutton 3-1 SonButton sb31 = new SonButton (); sb31.setName ("pic_weixin"); sb31.setType ("pic_weixin"); sb31.setKey ("31 "); // subbutton 3-2 SonButton sb32 = new SonButton (); sb32.setName ("locatselect"); sb32.setType ("location_select"); sb32.setKey ("32 "); //// the sub-button 3-3 --> cannot be tested because media_id is required. You need to call the clip id. // SonButton sb33 = new SonButton (); // sb33.setName ("media_id"); // sb33.setType ("media_id"); // sb33.setMedia _ id ("??? "); // Subbutton 3-4 --> cannot be tested because media_id is required. You need to call the clip id. // SonButton sb34 = new SonButton (); // sb34.setName ("view_limited"); // sb34.setType ("view_limited"); // sb34.setMedia _ id ("??? "); // Add the subbutton to the subbutton queue sonButtons3.add (sb31); sonButtons3.add (sb32); // sonButtons3.add (sb33); // sonButtons3.add (sb34 ); // put the child button in the 3-0 parent button queue fb3.setSonButtons (sonButtons3); // ------------------- // add the parent button to the parent button set fatherButtons. add (fb1); fatherButtons. add (fb2); fatherButtons. add (fb3); // add the parent button queue to the menu bar menu. setFatherButtons (fatherButtons); String json = gson. toJson (menu); System. out. println (json); // return json for the test output ;}
Personalized menu implementation
• Task: Display buttons based on gender (you can display buttons based on gender, region, and group mobile phone OS)
• Modify code 1. because it is implemented in different backgrounds, the interfaces are different. However, for POST requests, you only need to replace the original urlString without modifying the code.
// Concatenate the httpsurl link String urlString = "https://api.weixin.qq.com/cgi-bin/menu/addconditional? Access_token = "+ ACCESS_TOKEN;
• Modify code 2. create a MatchRule, set matching rules, and add matchrule to the menu to complete matching rules.
// ----- // Set the personalized menu MatchRule matchrule = new MatchRule (); matchrule. setSex ("2"); // Boys' menu. setMatchrule (matchrule );//----
The above is the detailed content of the instance code of java development API custom personalized menu implementation. For more information, see other related articles on php Chinese network!