Development of custom menu java for wechat subscription number

Posted by KevinMG on Sun, 19 May 2019 21:15:31 +0200

The younger brother should change the menu of the public number according to the operation requirement. He thought it was configurable on the public number official website. Who knows that it was edited by the developer mode? Helplessly, I have never contacted the public number development. Some began to gnaw away at the api developed by Weixin, which was originally made by a small partner and ran away. But no handover. Ah ~ ~ ~

Don't talk much nonsense. Open the process.

1. The younger brother is just the development of Subscription Number. Go to the public number and find the menu on the left.

This is a list of key parameters used in the development of the public number, as follows:

Here are some important parameters used in development:

1. Developer ID (AppId): The developer's account for developing the subscription number

2. Developer's password (AppSecret): The password that the developer is developing for the subscription number

3. IP whitelist: This parameter is the verification of an IP whitelist of the Wechat server. Without the whitelist, the Wechat server would not admit that your address is secure. access_token parameter cannot be obtained

4. Server Address (URL): He calls back the address of your server by Wechat. Remember that this server address is yours. It's not Weixin. And this address has some hard conditions.

(1) The url must have an extranet mapping, whether you are in the company or at home. This address must be accessible outside the network.

(2) The url port number must be 80, and it doesn't matter if the mapping to the local application port is XXXX. To configure extranet mapping, I use Sunny-Ngrok (https://www.ngrok.cc/) intranet penetration service, which is provided by a website with free http extranet mapping. Other mapping services failed (probably their own dish). Format, Extranet Mapping Address + Application Verification Interface

5. Token: A custom string used for validation

6. Message Encryption and Decryption Key: This parameter is used for encryption when sending/receiving cancellation. But if the settings are plaintext, then this parameter is not used. I didn't use it.

7. Message encryption/decryption: plaintext, compatibility and security

The above parameters constitute the basic parameters of the development of Wechat. But there are still some preparations for real development.

1. Verification:

Not directly in the production environment development, Daniel did very little. So we need a test environment. So that is in the developer tool [public number test account], you can create, at present, I just look at a few other items that have not been carefully studied, later reissue. Click to enter:

You can login directly with the authorization of Wechat on your mobile phone:

To illustrate briefly, the content of the test account information table is generated by the registered micro-message. I tried several times and it won't change. Should be account bound. Note that at this time, the test account number and password, the former account password is the production environment. Also, the logged-in tweet must be a tweet account authorized by the public number administrator to bind.

Add a person to the menu staff settings on the left side of the public number (the creator ignores it), and then bind the Web developer tools in the developer tools to a developer's micro-signal.
 

* Then we talk about the interface configuration information. The first test account configuration is empty. The url is your server address. It must be an address accessible to the external network of port 80 or 443 (that is, HTTP and https default ports). The address of your authentication application interface is identical to the fourth configuration routine, such as http://xxxx.cn/wx/yanzheng Api. The validated Java is:

@ResponseBody
	@RequestMapping(value = "/WechatCallbackApi", method = RequestMethod.GET)
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// Wechat Encrypted Signature
		String signature = request.getParameter("signature");
		System.out.println("Wechat Encrypted Signature=====" + signature);
		// Random string
		String echostr = request.getParameter("echostr");
		System.out.println("Random string=====" + echostr);
		// time stamp
		String timestamp = request.getParameter("timestamp");
		System.out.println("time stamp=====" + echostr);
		// random number
		String nonce = request.getParameter("nonce");
		System.out.println("random number=====" + echostr);
		String[] str = { TOKEN, timestamp, nonce };
		Arrays.sort(str); // Lexicographic ordering
		String bigStr = str[0] + str[1] + str[2];
		System.out.println("=====================" + bigStr);

		MessageDigestUtils digestutil = new MessageDigestUtils();
		String sha1 = MessageDigestUtils.sha1(bigStr);
		// Confirmation of requests to Wechat
		if (sha1.equals(signature)) {
			System.out.println("=====Verify success============");
			response.getWriter().print(echostr);
		}

	}

There must be a controller mapping on this demo method. Write it yourself.

* The following token is the token of point 5 above.

Single submission, if there is no problem, will be prompted to configure successfully (here you need to determine the response time of your excuse after receiving the request, too long Wechat is not recognized, try a few more times on it), otherwise the configuration will fail. The reason for failure is simple. That's the problem with your url configuration. In general, token will not be a problem. The above picture is a screenshot of my configuration that took a long time to succeed. It can be modified. Submit validation is to request the demo above. Big Brother knows what's going on at breakpoint. And Wechat's api document is clear about this. It is not stated that the url configuration requires 80 or 443 ports (PS: Actually, the api documentation also shows that. But it's on another page. [Begin development] - [Access Guide] The bottom part just shows that there's nothing to say about configuring URLs here.)

Complete the above work for a long time with the most basic configuration of subscription number development.

* JS interface security domain name I did not use. There is no introduction here.

Scanning the tweet with your login test account will make the current tweet pay attention to this subscription number. Click Attention. After entering, I found nothing. How. New menu, this custom menu can be created using the web page provided by Wechat or written in java. The demo of Java is as follows

Tools:

package com.tiancaibao.service.weixin;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.log4j.Logger;
import org.springframework.util.StringUtils;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tiancaibao.weixin.pojo.token.WeixinToken; 

/** 
 * Get the Wechat access_token tool class 

 */  
public class WeiXinAccessTokenUtil  
{  
    private static final Logger DEBUG_LOGGER = Logger.getLogger(WeiXinAccessTokenUtil.class);  
      
    /** 
     * From WeChat
     * Get Wechat access_token 
     * 
     */  
    public static WeixinToken getWeiXinAccessToken(String appid,String secret)  
    {  
        if(StringUtils.isEmpty(appid)|| StringUtils.isEmpty(secret))  
        {  
            DEBUG_LOGGER.error("appid or secret is null");  
            return null;  
        }  
        WeixinToken token = new WeixinToken();  
        try  
        {  
          String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appid+"&secret="+secret;  
              HttpClient httpClient = new HttpClient();  
            GetMethod getMethod = new GetMethod(url);  
            int execute = httpClient.executeMethod(getMethod);  
            System.out.println("execute:"+execute);  
            String getResponse = getMethod.getResponseBodyAsString();  
            System.out.println("========return Of json========"+getResponse);
            JSONObject json = (JSONObject) JSON.parseObject(getResponse);  
               token.setAccessToken(json.getString("access_token"));
               token.setExpiresIn(new Integer(json.getString("expires_in"))); 
               Date createtime=new Date();;
			token.setCreatetime(createtime);
        }  
        catch (IOException e)  
        {  
            DEBUG_LOGGER.error("getAccessToken failed,desc:::"+e);  
            e.printStackTrace();  
        }  
    
        return token; 
    }  


}  

access_token entity:

package com.tiancaibao.weixin.pojo.token;

import java.io.Serializable;
import java.util.Date;

public class WeixinToken implements Serializable {
    private Integer id;

    private String accessToken;

    private Integer expiresIn;

    private Date createtime;

    protected String fields;

    private static final long serialVersionUID = 1L;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getAccessToken() {
        return accessToken;
    }

    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken == null ? null : accessToken.trim();
    }

    public Integer getExpiresIn() {
        return expiresIn;
    }

    public void setExpiresIn(Integer expiresIn) {
        this.expiresIn = expiresIn;
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public void setFields(String fields) {
        this.fields = fields;
    }

    public String getFields() {
        return fields;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getSimpleName());
        sb.append(" [");
        sb.append("Hash = ").append(hashCode());
        sb.append(", id=").append(id);
        sb.append(", accessToken=").append(accessToken);
        sb.append(", expiresIn=").append(expiresIn);
        sb.append(", createtime=").append(createtime);
        sb.append(", fields=").append(fields);
        sb.append(", serialVersionUID=").append(serialVersionUID);
        sb.append("]");
        return sb.toString();
    }
}

Request Creation Tool:

package com.tiancaibao.weixin.menu;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tiancaibao.service.weixin.MyX509TrustManager; 



/**
* 

* Developer: liming</br>

 */
public class WeixinUtil {
    
    private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);
    

    // Menu Creation (POST) Limit 100 (times/day)
    public static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
/***
 * Custom menu creation interface:
http Request mode: POST (use HTTPS protocol) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
Custom menu query interface:
http Request: GET https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN
Custom menu deletion interface:
http Request: GET https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN
 * 
 */
    /**
     * create menu
     * 
     * @param menu Menu instance
     * @param accessToken Effective access_token
     * @return 0 Represents success and other values indicate failure
     */
    public static int createMenu(Menu menu, String accessToken) {
        int result = 0;
        // Assemble URLs to create menus
        String url = menu_create_url.replace("ACCESS_TOKEN", accessToken);
        // Converting menu objects to json strings
        String jsonMenu = JSONObject.toJSONString(menu);
        // Call interface to create menu
        JSONObject jsonObject = httpRequest(url, "POST", jsonMenu);
        if (null != jsonObject) {
            if (0 != jsonObject.getInteger("errcode")) {
                result = jsonObject.getInteger("errcode");
                log.error("Failed to create menu errcode:{} errmsg:{}", jsonObject.getInteger("errcode"), jsonObject.getString("errmsg"));
            }
        }

        return result;
    }
    

    
    
    /**
     * Description: Initiate https requests and obtain results
     * @param requestUrl Request address
     * @param requestMethod Request mode (GET, POST)
     * @param outputStr Data submitted
     * @return JSONObject(Get the attribute value of the json object by JSONObject.get(key)
     */
    public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        StringBuffer buffer = new StringBuffer();
        try {
            // Create the SSLContext object and initialize it using the trust manager we specified
            TrustManager[] tm = { new MyX509TrustManager() };
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // Get the SSLSocketFactory object from the above SSLContext object
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
            httpUrlConn.setSSLSocketFactory(ssf);

            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);
            
            // Setting Request Mode (GET/POST)
            httpUrlConn.setRequestMethod(requestMethod);

            if ("GET".equalsIgnoreCase(requestMethod))
                httpUrlConn.connect();

            // When data needs to be submitted
            if (null != outputStr) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // Pay attention to the coding format to prevent Chinese scrambling
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // Converting the returned input stream to a string
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // Release resources
            inputStream.close();
            inputStream = null;
            httpUrlConn.disconnect();
            jsonObject = JSONObject.parseObject(buffer.toString());
        } catch (ConnectException ce) {
            log.error("Weixin server connection timed out.");
        } catch (Exception e) {
            log.error("https request error:{}", e);
        }
        return jsonObject;
    }
    /**
     * Send Picture Messages
     * @param accesstoken
     * {
    "touser":"OPENID",
    "msgtype":"image",
    "image":
    {
      "media_id":"MEDIA_ID"
    }
}
     * @param openid
     */
    public static int SendCustomerMessage(String accesstoken ){
    	      String url="https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token="+accesstoken;
    	      ImageMsg image =new ImageMsg();
    	      Image ima= new Image();
    	      ima.setMedia_id("FsM7Uo7Nk1YDdSZr8zYu7p079vyXhsvdbW3ArYpwqcM");
    	      image.setImage(ima);
    	      image.setTouser("ovlNE1A7Zlufu0wfMYiweE6igo-c");
    	      image.setMsgtype("image");// Picture type message

    	      
    	      String jsonMenu = JSONObject.toJSONString(image);
    	      System.out.println(jsonMenu);
    	        // Call interface to create menu
  	        JSONObject jsonObject = httpRequest(url, "POST", jsonMenu);
    	      int  result = 0;
				if (null != jsonObject) {
    	            if (0 != jsonObject.getInteger("errcode")) {
    	                result = jsonObject.getInteger("errcode");
    	                log.error("Failed to create menu errcode:{} errmsg:{}", jsonObject.getInteger("errcode"), jsonObject.getString("errmsg"));
    	            }
    	        }

    	        return result;
      	
    }
    
 public static void main(String[] args) {
	}
}

Custom menu creation main:

package com.tiancaibao.weixin.menu;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tiancaibao.service.weixin.WeiXinAccessTokenUtil;
import com.tiancaibao.weixin.pojo.token.WeixinToken;


/**
* Class name: MenuManager</br>
* 
* Description: Menu Manager Class</br>

 */
public class MenuManager {
    private static Logger log = LoggerFactory.getLogger(MenuManager.class);

    public static void main(String[] args) {
      // Third-party User Unique Credential Testing
     String appId = "wxxxxxxx";
        // Third party user unique credential key
        String appSecret = "xxxxxxxxxxxx";
    	    
        WeixinToken weiXinAccessToken = WeiXinAccessTokenUtil.getWeiXinAccessToken(appId, appSecret);
        
       if (null != weiXinAccessToken) {
        	String asstoken=weiXinAccessToken.getAccessToken();
        			// Call interface to create menu
            int result = WeixinUtil.createMenu(getMenu(), asstoken);

            // Judge the result of menu creation
            if (0 == result)
                log.info("Menu Creation Successful!");
            else
                log.info("Menu creation failed, error code:" + result);
       }
    }

    /**
     * Assembly menu data
     * 
     * @return
     */
    private static Menu getMenu() {


        //New menu customization

        CommonButton mainBtn1New = new CommonButton();
        mainBtn1New.setName("Ah! activity");
        mainBtn1New.setType("view");
        mainBtn1New.setKey("http://weixin.xxxx");

        CommonButton btn2_1 = new CommonButton();
        btn2_1.setName("Historical articles");
        btn2_1.setType("view");
        btn2_1.setUrl("xxxx");

        CommonButton btn2_2 = new CommonButton();
        btn2_2.setName("Integral mall");
        btn2_2.setType("view");
        btn2_2.setUrl("http://xxxx");

        CommonButton btn2_3 = new CommonButton();
        btn2_3.setName("customer service hotline");
        btn2_3.setType("click");
        btn2_3.setKey("Our service hotline xx,Working hours 9:00-20:00,Welcome to call the hotline if you have any questions.~");

        CommonButton btn3_1 = new CommonButton();
        btn3_1.setName("My assets");
        btn3_1.setType("view");
        btn3_1.setKey("http://xxxx");

        CommonButton btn3_2 = new CommonButton();
        btn3_2.setName("Login registration");
        btn3_2.setType("view");
        btn3_2.setKey("http://xxx");

        CommonButton btn3_3 = new CommonButton();
        btn3_3.setName("I want to lend.");
        btn3_3.setType("view");
        btn3_3.setKey("http://xxx");

        CommonButton btn3_4 = new CommonButton();
        btn3_4.setName("download APP");
        btn3_4.setType("view");
        btn3_4.setKey("https://xxx");
        
        /**
         * Wechat: three first-level menus at the bottom of main Btn1, main Btn2 and main Btn3. Observe whether the appSecret parameter needs to be reset before execution. If you remember, you don't need it. It's not urgent. Estimates are in suspense. To reset,
         * But will resetting affect all menus? ~ ~
         */
        
//        ComplexButton mainBtn1 = new ComplexButton();
//        mainBtn1.setName("Ah! Activity "";
//        // There are four sub-menus at level 1
//        mainBtn1.setSub_button(new CommonButton[] {btn8,btn9});

        
        ComplexButton mainBtn2 = new ComplexButton();
        mainBtn2.setName("Ah! posture");
        mainBtn2.setSub_button(new CommonButton[] { btn2_1,btn2_2, btn2_3 });

        
        ComplexButton mainBtn3 = new ComplexButton();
        mainBtn3.setName("Ah! My");
        mainBtn3.setSub_button(new CommonButton[] { btn3_1,btn3_2,btn3_3, btn3_4 });

        
        /**
         * Encapsulate the entire menu
         */
        Menu menu = new Menu();
        menu.setButton(new Button[] { mainBtn1New, mainBtn2, mainBtn3 });

        return menu;
    }
}

CommonButton:

package com.tiancaibao.weixin.menu;

/**
* Class name: CommonButton</br>
* Package name: com.souvc.weixin.menu
* Description: Submenu items: Menu items without submenu, may be secondary menu items, or may be primary menu items without secondary menu. </br>

 */
public class CommonButton extends Button {
    
    private String type;
    private String key;
    private String  url;

    public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }
}

complexButton:

package com.tiancaibao.weixin.menu;

public class ComplexButton extends Button {
    private Button[] sub_button;

    public Button[] getSub_button() {
        return sub_button;
    }

    public void setSub_button(Button[] sub_button) {
        this.sub_button = sub_button;
    }
}

Button:

package com.tiancaibao.weixin.menu;


/**
* Class name: Button</br>
* Package name: com.souvc.weixin.menu
* Description: Base Class of Menu Items</br>
 */
public class Button {
    
    private String name;//All first-level menus and second-level menus share the same attribute: name.

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Menu:

package com.tiancaibao.weixin.menu;

/**
* Class name: Menu</br>
* Package name: com.souvc.weixin.menu
* Description: Encapsulation of the entire menu object</br>

 */
public class Menu {
    private Button[] button;

    public Button[] getButton() {
        return button;
    }

    public void setButton(Button[] button) {
        this.button = button;
    }
}

The above is the source code and process of creating custom menu. The editing of the first-level menu and the second-level menu uses the polymorphism of java. Specific demo is also provided in the api document for reference. For related events and features, please refer to the api documentation, which is written in detail, without further elaboration.

Additionally, receiving micro-message callback processing method:

/*
	 * In particular, req.getInputStream() can only be retrieved once and read only once. If you want to read more than once, you need to think about something else. For simplicity,
	 */
	@ResponseBody
	@RequestMapping(value = "/WechatCallbackApi", method = RequestMethod.POST)
	public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// Set encoding
		req.setCharacterEncoding("utf-8");
		resp.setContentType("html/text;charset=utf-8");
		resp.setCharacterEncoding("utf-8");
		/*
		 * In this part, we get the information sent by users and parse it into < K, V > for display.
		 */
		// Parsing information sent by users
		InputStream is = req.getInputStream();// Fetch request stream
		// Store parsed results in HashMap
		Map<String, String> map = new HashMap<String, String>();
		// Parse xml and parse the returned result xml into the text information we are used to
		SAXReader reader = new SAXReader();//
		Document document = null;
		try {
			document = reader.read(is);// Read the content in the stream
		} catch (DocumentException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		// Get the xml root element
		Element root = document.getRootElement();
		// Get all the child nodes of the root element
		List<Element> elementList = root.elements();
		// Traverse all the sub-nodes, store all the nodes in the map, easy to read
		for (Element e : elementList)
			map.put(e.getName(), e.getText());

		Set<String> keySet = map.keySet();
		// Output of parsed information sent by users
		System.out.println("===Start by parsing the information sent by the user");
		String FromUserName = "";// User's openid
		String event = "";// Event type
		boolean ismessage = false;
		String messsgeContent = "";
		String shopid = "";
		String EventKey = "";
		for (String key : keySet) {
			System.out.println(key + ":" + map.get(key));
			if ("FromUserName".equals(key)) {
				FromUserName = map.get(key);
			}
			if ("Event".equals(key)) {
				event = map.get(key);
			}
			// Keyword message beginning
			if ("MsgId".equals(key)) {
				ismessage = true;
			}
			if ("Content".equals(key)) {
				messsgeContent = map.get(key);
			}
			if ("EventKey".equals(key)) {
				EventKey = map.get(key);
			}
		}

		System.out.println("==========Whether to send message==============" + ismessage);
		System.out.println(": End of parsing messages sent by users");

		/*
		 * In this part, we try to reply the text information and graphic message to the user according to the format required by the document. Emphasis: Construct the required parameters according to the document requirements. Special note: Parameters are case sensitive.
		 */
		// Send plain text messages. See the document's xml format for "Reply to Text Messages"

		// Step 1: Construct the required parameters according to the reply text information
		TextMsg textMsg = new TextMsg();
		textMsg.setToUserName(map.get("FromUserName"));// Sending and receiving information "User" is just the opposite
		textMsg.setFromUserName(map.get("ToUserName"));
		textMsg.setCreateTime(new Date().getTime());// Message creation time (integer)
		textMsg.setMsgType("text");// Text type message
		Date subscribedate = new Date();
		// Custom menu for CLICK, focus on subscribe
		if (event.equals("CLICK")) {
			textMsg.setContent("Our service hotline xxxx,Working hours 9:00-20:00,Welcome to call the hotline if you have any questions.~\ue415");
		} else if (event.equals("subscribe")) {
			// Query whether there is a record of interest
			Weixinshopsubscriberecord selectInfoByOpenId = wexinSubscibeservice.selectInfoByOpenId(FromUserName);
			System.out.println("=============Query whether there is a record of interest==========" + selectInfoByOpenId);
			if (EventKey != "" || EventKey != null || !"".equals(EventKey)) {
				System.out.println("===========================EventKey===============" + EventKey.toString());
				String[] Str = EventKey.split("_");
				// The purpose of this judgment is to prevent the two-dimensional code parameters from being empty.
				if (Str.length > 1) {
					shopid = Str[1];
				}
			}
			// Unconcerned
			if (selectInfoByOpenId == null) {
				// First concern
				String FirstSubscribe = "Finally, when you're okay, I haven't given up. Go to the bottom right corner and start your journey of wealth." ;
				if(!"".equals(shopid)){

					FirstSubscribe+="   Source number:"+ shopid;

				}
				
				
				textMsg.setContent(FirstSubscribe);
				Weixinshopsubscriberecord weixinshop = new Weixinshopsubscriberecord();
				weixinshop.setOpenid(FromUserName);
				weixinshop.setShopid(shopid);
				weixinshop.setState("1");
				weixinshop.setSubscribedate(subscribedate);
				weixinshop.setSubscribetime(subscribedate);
				// Save openid
				wexinSubscibeservice.SubscribeSave(weixinshop);

			} else {
				// Re-focus after cancellation
				selectInfoByOpenId.setState("2");
				selectInfoByOpenId.setSubscribedate(subscribedate);
				selectInfoByOpenId.setSubscribetime(subscribedate);
				selectInfoByOpenId.setOpenid(FromUserName);
				selectInfoByOpenId.setShopid(shopid);
				wexinSubscibeservice.UpdateSubscribe(selectInfoByOpenId);// Change record
				
				String SecondSubscribe = "Welcome back to the road of wealth, waiting for you to start!" ;
				if(!"".equals(shopid)){
					SecondSubscribe+="  Source number:"+ shopid;
				}
				
				
				
				
				textMsg.setContent(SecondSubscribe);

			}
		} else if (event.equals("unsubscribe")) {
			Weixinshopsubscriberecord weixinshop = new Weixinshopsubscriberecord();
			weixinshop.setState("0");// Cancellation of attention to 0
			weixinshop.setSubscribedate(subscribedate);
			weixinshop.setSubscribetime(subscribedate);
			weixinshop.setOpenid(FromUserName);
			weixinshop.setShopid(shopid);
			wexinSubscibeservice.UpdateSubscribe(weixinshop);

		}
		// Whether to send customer service messages
		Boolean issend = false;

		/**
		 * Reply to Picture Messages
		 */
		ImageMsg imagemsg = new ImageMsg();
		imagemsg.setToUserName(map.get("FromUserName"));// Sending and receiving information "User" is just the opposite
		imagemsg.setFromUserName(map.get("ToUserName"));
		imagemsg.setCreateTime(new Date().getTime());// Message creation time (integer)
		imagemsg.setMsgType("image");// Text type message
		Image Image = new Image();
		// Image.setMediaId ("FsM7Uo7Nk1YDdSZr8z Yu7p079vyXhsvdbW3ArYpwqcM"); //Picture ID, not fixed

		Image.setMediaId("6GTGDx7tGKMgnHv2Qzd9-orxsSaNBr4TdLN_n2zdw14");// Picture ID, not fixed

		imagemsg.setImage(Image);
		// Message content
		if (ismessage) {
			if (messsgeContent.indexOf("Happy Army Day!") != -1) {
				textMsg.setContent("The activity is over. Welcome to join us next time.\ue409");
			}else if(messsgeContent.indexOf("Mid-autumn Festival") != -1){
			   textMsg.setContent("http://4xxx/index.jsp?aid=fe66eb90a5ea40e3a956ecaf2926f1c9&activityid=110312&wuid=457767&keyversion=0&isFromApiFilter=1");
		     }else if (messsgeContent.indexOf("Customer Service Contact Telephone") != -1) {
				textMsg.setContent("Our customer service hotline: xxx,Call now, beautiful customer service girl is waiting for you.~");
			} else if (messsgeContent.indexOf("Hello") != -1 || messsgeContent.indexOf("Are you there?") != -1
					|| messsgeContent.indexOf("stay") != -1 || messsgeContent.indexOf("In?") != -1
					|| messsgeContent.indexOf("Hello?") != -1 || messsgeContent.indexOf("Hello!") != -1
					|| messsgeContent.indexOf("Hello?") != -1 || messsgeContent.indexOf("How do you do?") != -1
					|| messsgeContent.indexOf("hi") != -1 || messsgeContent.indexOf("hello") != -1) {
				textMsg.setContent("Hi~~~Do you miss me? If you have any questions, please call our customer service. xxx \ue032");
			} else if (messsgeContent.indexOf("Good buy wine") != -1 || messsgeContent.indexOf("Good selling wine") != -1
					|| messsgeContent.indexOf("Alcohol") != -1) {
				// textMsg.setContent("Ah, you're a good buyer of wine"? Long journey, hard work
				// \ From now on, scanning the two-dimensional code real name registration xxx above, you can enjoy 5000 yuan experience gold \ ue106+80 yuan cash red envelope \ ue106+20% coupon \ ue106  triple gift gift package. It's not lost, no longer come, go and complete the registration quickly.

				XStream xStream = new XStream();
				xStream.alias("xml", imagemsg.getClass());
				String imagemsgXml = xStream.toXML(imagemsg);
				System.out.println("Responding to pictures xml====" + imagemsgXml);
				PrintWriter printWriter = resp.getWriter();
				printWriter.print(imagemsgXml);
				issend = true;
			} else {
				textMsg.setContent(
						"Hold back~means~emergency~Ha~\ue415 Your message, Xiaobian I have received, let me slowly reply Ha~\ue056 If you have any questions, you'd better find our customer service sister. xxx,People can compare with me, who only knows how to send points by code all day long.~~~\ue409");
			}
		}

		XStream xStream = new XStream();
		xStream.alias("xml", textMsg.getClass());
		String textMsg2Xml = xStream.toXML(textMsg);
		System.out.println("Return to the Wechat Server to send a message to the user====" + textMsg2Xml);

		// The third step is to send the format information of xml to the wechat server, which forwards it to the user.
		// In addition to this, the re-scan event has been noted
		if (!event.equals("SCAN")) {
			PrintWriter printWriter = resp.getWriter();
			printWriter.print(textMsg2Xml);
			System.out.println("======Text was sent============");

		}

		if (issend) {
			/**
			 * Send customer service text message
			 */
			// The first step is to get access token
			String accesstoken = "";
			Date date1 = new Date();
			Date date2 = new Date();
			Weixincommoninfo selectaccesstoken = weixincommoInfoservice.selectInfo();
			// Check to see if there is access token
			if (selectaccesstoken == null) {

				selectaccesstoken = new Weixincommoninfo();
				WeixinToken weiXinAccessToken = WeiXinAccessTokenUtil.getWeiXinAccessToken();
				accesstoken = weiXinAccessToken.getAccessToken();
				selectaccesstoken.setSavefiled("accesstoken");
				selectaccesstoken.setSaveinfo(accesstoken);
				selectaccesstoken.setExpiresIn(weiXinAccessToken.getExpiresIn());
				selectaccesstoken.setCreatetime(date1);
				date2.setHours(date1.getHours() + 1);// Here, set the accesstoken validity period to 1 hour
				selectaccesstoken.setEffectivetime(date2);
				weixincommoInfoservice.Saveinfo(selectaccesstoken);

			} else {
				Date date = new Date();
				// Determine whether the current time is within the validity period of access token.
				Date effectivetime = selectaccesstoken.getEffectivetime();
				if (effectivetime.getTime() > date.getTime()) {
					accesstoken = selectaccesstoken.getSaveinfo();
					System.out.println("In the database accesstoken Can use");
				} else {
					WeixinToken weiXinAccessToken = WeiXinAccessTokenUtil.getWeiXinAccessToken();
					selectaccesstoken = new Weixincommoninfo();
					accesstoken = weiXinAccessToken.getAccessToken();
					selectaccesstoken.setSavefiled("accesstoken");
					selectaccesstoken.setSaveinfo(accesstoken);
					selectaccesstoken.setExpiresIn(weiXinAccessToken.getExpiresIn());
					selectaccesstoken.setCreatetime(date1);
					date2.setHours(date1.getHours() + 1);
					selectaccesstoken.setEffectivetime(date2);
					weixincommoInfoservice.upadateInfo(selectaccesstoken);
					System.out.println("In the database accesstoken No, it can be used to retrieve the update.");
				}
			}

			// Step 2 Send Messages
			System.out.println("Send customer service messages=======================");
			String mescont = "Ah, you're a good buyer of wine, aren't you? Long journey, hard work\ue056 \n From now on, the two-dimensional code registration under the scan xxx,Can enjoy 5000 yuan experience gold\ue106+80 Dollar cash red envelope\ue106+20%Coupon coupon\ue106"Triple courtesy "big gift bag, opportunity is not lost, lost no longer come, go to complete the registration bar\ue056";
			WeixinUtil.SendCustomerTextMessage(accesstoken, FromUserName, mescont);
		}

	}

Topics: Programming Java JSON xml SSL