First, new projects

  1. Create a new Spring project

  1. Fill in the Group and Artifact information

  1. You can skip this step and import it on demand later

  1. Select project address

Second, the configuration

pom.xml

<dependencies> <! Spring framework.boot</ grouppid > <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId>  <scope>test</scope> </dependency> <! - HTTP request - > < the dependency > < groupId > org). Apache httpcomponents < / groupId > < artifactId > httpclient < / artifactId > The < version > 4.5.6 < / version > < / dependency > <! -- Toolkit --> <dependency dependency> < grouppid >cn.hutool</ grouppid > <artifactId>hutool-all</artifactId> <version>5.5.8</version> </dependency> <! > <dependency> < grouppid >dom4j</ grouppid > <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency> </dependencies>

application.yml

Spring: Application: Name: WeChat Server: Port: 8900 AppID: # WeChat Developer AppID: # WeChat Developer AppSecret Token: # Server Verify Token

3. Related categories

AccessToken / AccessTokenInfo

/** ** AccessToken * @Author Unidentifiable * @Date 2021-02-28 */ public class AccessToken {/** ** Collective ID */ private ID ** ** String tokenName; Private int expireSecond; /** * private int expireSecond; /** * get/set ... * * * * /} / AccessToken entity class * @ author unidentifiable * @ the date 2021-02-28 * / public class AccessTokenInfo {/ * * * AccessToken: The AccessToken */ public static AccessToken AccessToken = null for requests like WeChat; }

MessageUtil

/** ** Public class MessageUtil {/** ** Param ** ** @Author unidentifiable * @Date 2021-02-28 */ Public class MessageUtil {/** ** Param ** ** * Public static map <String, String, String, String, String, String, String, String String> parsexML (HttpServletRequest Request) {// Stores parsing results in HashMap Map<String, String> Map = new HashMap<>(16); Try (inputStream = request.getInputStream()) {System.out.println(" get the InputStream "); SaxReader = new saxReader (); Document document = reader.read(inputStream); Document.getRoot = document.getRootElement(); List<Element> elementList = root.elements(); / / to iterate through all child nodes for (Element e: elementList) {System. Out. Println (um participant etName () + "|" + um participant etText ()); map.put(e.getName(), e.getText()); } } catch (Exception e) { e.printStackTrace(); } return map; Public static String getUserInfo(String openId) {/** * getUserInfo(String openId) {/** * getUserInfo(String openId) {/** * getUserInfo(); . A HTTP get request String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + AccessTokenInfo.accessToken.getTokenName() + "&openid=" + openId + "&lang=zh_CN"; return HttpUtil.get(url); }}

AccessTokenConfig

** * @author unidentifiable * @date 2021-02-28 */ public class accesstokenConf {static {** ** ** ** ** ** ** ** ** * Properties prop = new Properties(); String appid = null; String secret = null; Try {// Read application.yml to get WeChat developer AppID and AppSecret InputStream in = MessageUtil.class.getClassLoader().getResourceAsStream("application.yml"); prop.load(in); appid = prop.getProperty("appid"); secret = prop.getProperty("secret"); } catch (Exception e) { e.printStackTrace(); } / / interface address for https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET, Where grant_type is fixed to client_credential. String url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appid, secret); Get (url) {"access_token":" access_token","expires_in":7200} String result = httputil.get (url); Println (" access_token=" + result); JsonObject Json = new jsonObject (result); AccessToken token = new AccessToken(); token.setTokenName(json.get("access_token", String.class)); token.setExpireSecond(json.get("expires_in", Integer.class)); // Start a thread to update the AccesToken loop for 2 hours. Need to manually refresh the new Thread (() - > {the while (true) {try {/ / get accessToken AccessTokenInfo. AccessToken = token; / / to be successful if (AccessTokenInfo accessToken! Thread.sleep(7000 * 1000) {// get the access_token sleep(7000 * 1000); } else {// Get the access_token for empty sleep for 3 seconds Thread.sleep(3000); }} if (test.getMessage (test.getMessage ()) {test.getMessage (); test.getMessage (); e.printStackTrace(); Try {// Thread.sleep(1000); } catch (Exception e1) { e.printStackTrace(); } } } }).start(); }}

SubscribeService

package com.unidentifiable.wechat.service; import com.unidentifiable.wechat.util.MessageUtil; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Map; /** * Service * @author unidentifiable * @date 2021-02-28 */ @Service("subscribeService") public class SubscribeService { @Value("${subscriptionKey}") public String subscriptionKey; @Value("${uriBase}") public String uriBase; @Value("${token}") public String token; Public String Verification (" Verification ") {// Verification (" Verification ") {// Verification (" Verification ") String signature = req.getParameter("signature"); String signature = req.getParameter("signature"); String timestamp = req.getParameter("timestamp"); String nonce = req.getParameter("nonce"); String echostr = req.getParameter("echostr"); String sortStr = sort(token, timestamp, nonce); String sortStr = sort(token, timestamp, nonce); String mySignature = shal(sortStr); mySignature = shal(sortStr); // Check that the signature sent by the WeChat server is consistent with the encrypted string. If it is consistent, the signature is passed by if (!" ".equals(signature) && !" Equals (mySignature)) {System.out.println("----- signature validation is OK "); return echostr; } else {System.out.println("----- verification signature failed "); return ""; }} /** ** @param token custom token * @param timestamp timestamp * @param nonce nonce * @return string */ public String sort(String token, String timestamp, String nonce) { String[] strArray = {token, timestamp, nonce}; Arrays.sort(strArray); StringBuilder sb = new StringBuilder(); for (String str : strArray) { sb.append(str); } return sb.toString(); Public String shal(String STR) {try {MessageDigest digest = MessageDigest.getInstance("SHA-1"); digest.update(str.getBytes()); byte messageDigest[] = digest.digest(); StringBuilder hexString = new StringBuilder(); 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 ""; } /** * care request ** @param req request * @return care result */ public String SubscribeEvent (HttpServletRequest req) {String result = null; Map<String, String> map = null; Try {/* Parse the request, Get information about FromUserName | openid user ID CreateTime | 1614499703 time MsgType | event message type event | the subscribe event type EventKey | * / map = MessageUtil.parseXml(req); } catch (Exception e) { e.printStackTrace(); } final Map<String, String> m = Map;} final Map<String, String> m = Map; final String[] str = new String[1]; New Thread(() -> {if (NULL! = m && "event".equals(m.get("MsgType")) && "subscribe".equals(m.get("Event"))) { str[0] = MessageUtil.getUserInfo(m.get("FromUserName")); System.out.println(str[0]); }}).start();}).start();}).start(); return result; }}

SubscribeController

package com.unidentifiable.wechat.controller; import com.unidentifiable.wechat.service.SubscribeService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import javax.servlet.http.HttpServletRequest; /** * Controller * @author unidentifiable * @date 2021-02-28 */ public class SubscribeController { @Autowired private SubscribeService subscribeService; /** * @Verification ("/") public String Verification (HttpServletRequest Req) { return subscribeService.verification(req); } /** * Message Event * @Param Req Request * @Return Result */ @PostMapping("/") public Boolean SubscribeEvent (HttpServletRequest Req) { String s = subscribeService.subscribeEvent(req); return null ! = s; }}

IV. Intranet penetration (this step can be omitted if there is a domain name)

NatApp is the tool used here. Download the corresponding version of the tool

https://natapp.cn/


Create a free tunnel, configure the address and port you want to map, and copyauthtoken



Modify the authToken in the client configuration file (this is the WIN version, Linux version does not have this file, it is suggested to add a new one, otherwise the connection may time out after background startup)

config.ini

# If you place this file in the same directory as natapp, the program will read the [default] section. # In the command-line parameter mode, the same parameter such as natapp-authtoken = XXX will override this configuration. # Command-line parameter -config= can specify any config.ini file [default] authToken = # authToken for a tunnel clientToken = # for the client clientToken, will ignore the authToken, if no please leave blank, log=none #log file, can specify local file, NONE = NONE LOGLEVEL =DEBUG # DEBUG, INFO, WARNING, NONE LOGLEVEL =DEBUG The ERROR defaults to DEBUG http_proxy= # Proxy Settings such as http://10.123.10.10:3128 for non-proxies must be left blank

Configure the completion of direct double-click to run, Linux version of the background start available(./natapp &)Command run, note the parentheses. If the following interface appears, it is successful.

V. WeChat public platform interface test account

https://mp.weixin.qq.com/debu…

Get the AppID and AppSecret and fill them into the appliation. YML configuration file, start the project, start NatApp, fill in the domain name and custom token for interface configuration verification.

After binding the server information, you can scan the QR code below for testing.

Tutorial here is over, you want to achieve what custom functions can view the WeChat official document, see what functions are provided, and then modify the corresponding judgment can be.

Project Address:
https://gitee.com/unidentifia…