关于java对接微信公众号(对接百度AI实现图片文字识别,对接聚合数据实现笑话、谜语大全,成语接龙等功能)

前言:

  • 只是自己学习使用,所以有点不规范,请见谅 
  • 本文直接附上源码与效果图,具体操作步骤请参考另一篇文章:http://t.csdnimg.cn/PQu25

1.运行效果图

1.1 关注事件

1.2 笑话大全

1.3 谜语大全

1.3 多级菜单

1.4 按钮跳转事件

1.5 心灵鸡汤

1.6 图片文字识别

1.7成语接龙(有点智障)

2.项目结构

3.xml依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.11</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.zsh</groupId>
    <artifactId>wx_account1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>wx_account1</name>
    <description>wx_account1</description>
    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- DOM4J是 dom4j.org 出品的一个开源XML解析包-->
        <dependency>
            <groupId>org.dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>2.1.3</version>
        </dependency>
        <!-- XStream是个很强大的工具,能将java对象和xml之间相互转化-->
        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.19</version>
        </dependency>

        <!-- 和fastjson作用一样,对json进行解析与构建-->
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.2.3</version>
            <classifier>jdk15</classifier>
        </dependency>
        <!-- 引入百度ai的依赖 -->
        <dependency>
            <groupId>com.baidu.aip</groupId>
            <artifactId>java-sdk</artifactId>
            <version>4.16.12</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-simple</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>


        <!--httpClient需要的依赖-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.2</version>
        </dependency>
        <!--//httpclient缓存-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient-cache</artifactId>
            <version>4.5</version>
        </dependency>
        <!--//http的mime类型都在这里面-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpmime</artifactId>
            <version>4.3.2</version>
        </dependency>
        <!-- 随机笑话  -->
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.2.3</version>
            <classifier>jdk15</classifier>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

4.工具类

4.1 HttpUtil:http请求工具类

package com.zsh.wx_account1.util;

import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * @Author ZhaoShuHao
 * @Date 2023/8/23 9:35
 */
public class HttpUtil {
    /**
     * get⽅式的http请求
     *
     * @param httpUrl 请求地址
     * @return 返回结果
     */
    public static String doGet(String httpUrl) {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        BufferedReader bufferedReader = null;
        String result = null;// 返回结果字符串
        try {
            // 创建远程url连接对象
            URL url = new URL(httpUrl);
            // 通过远程url连接对象打开⼀个连接,强转成httpURLConnection类
            connection = (HttpURLConnection)
                    url.openConnection();
            // 设置连接⽅式:get
            connection.setRequestMethod("GET");
            // 设置连接主机服务器的超时时间:15000毫秒
            connection.setConnectTimeout(15000);
            // 设置读取远程返回的数据时间:60000毫秒
            connection.setReadTimeout(60000);
            // 发送请求
            connection.connect();
            // 通过connection连接,获取输⼊流
            if (connection.getResponseCode() == 200) {
                inputStream = connection.getInputStream();
                // 封装输⼊流,并指定字符集
                bufferedReader = new BufferedReader(new
                        InputStreamReader(inputStream, StandardCharsets.UTF_8));
                // 存放数据
                StringBuilder sbf = new StringBuilder();
                String temp;
                while ((temp = bufferedReader.readLine()) !=
                        null) {
                    sbf.append(temp);

                    sbf.append(System.getProperty("line.separator"));
                }
                result = sbf.toString();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (null != bufferedReader) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();// 关闭远程连接
            }
        }
        return result;
    }
    /**
     * post⽅式的http请求
     *
     * @param httpUrl 请求地址
     * @param param 请求参数
     * @return 返回结果
     */
    public static String doPost(String httpUrl, String param,String contentType) {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;
        BufferedReader bufferedReader = null;
        String result = null;
        try {
            java.net.URL url = new URL(httpUrl);
            // 通过远程url连接对象打开连接
            connection = (HttpURLConnection)
                    url.openConnection();
            // 设置连接请求⽅式
            connection.setRequestMethod("POST");
            // 设置连接主机服务器超时时间:15000毫秒
            connection.setConnectTimeout(15000);
            // 设置读取主机服务器返回数据超时时间:60000毫秒
            connection.setReadTimeout(60000);
            // 默认值为:false,当向远程服务器传送数据/写数据时,需要设置为true
            connection.setDoOutput(true);
            // 设置传⼊参数的格式:请求参数应该是name1=value1&name2=value2 的形式。
            connection.setRequestProperty("Content-Type",contentType);
            // 通过连接对象获取⼀个输出流
            outputStream = connection.getOutputStream();
            // 通过输出流对象将参数写出去/传输出去,它是通过字节数组写出的
            outputStream.write(param.getBytes());
            // 通过连接对象获取⼀个输⼊流,向远程读取
            if (connection.getResponseCode() == 200) {
                inputStream = connection.getInputStream();
                // 对输⼊流对象进⾏包装:charset根据⼯作项⽬组的要求来设置
                bufferedReader = new BufferedReader(new
                        InputStreamReader(inputStream, StandardCharsets.UTF_8));
                StringBuilder sbf = new StringBuilder();
                String temp;
                // 循环遍历⼀⾏⼀⾏读取数据
                while ((temp = bufferedReader.readLine()) !=
                        null) {
                    sbf.append(temp);

                    sbf.append(System.getProperty("line.separator"));
                }
                result = sbf.toString();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (null != bufferedReader) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != outputStream) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
        return result;
    }


    //httpClient发送携带文件的post请求

    /**
     * 以post方式调用第三方接口,以form-data 形式  发送 文件
     * @param url post请求url
     * @param map
     * @param localFile 文件地址
     * @param fileParamName 文件参数名称
     * @return
     */
    public static String doPostByFile(String url, Map<String, String> map, String localFile, String fileParamName) {
        HttpPost httpPost = new HttpPost(url);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String resultString = "";
        CloseableHttpResponse response = null;
        try {
            // 把文件转换成流对象FileBody
            FileBody bin = new FileBody(new File(localFile));
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.addPart(fileParamName, bin);
            if (map != null) {
                for (String key : map.keySet()) {
                    builder.addPart(key,
                            new StringBody(map.get(key), ContentType.create("text/plain", Consts.UTF_8)));
                }
            }
            HttpEntity reqEntity = builder.build();
            httpPost.setEntity(reqEntity);
            // 发起请求 并返回请求的响应
            response = httpClient.execute(httpPost, HttpClientContext.create());
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        }  catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null)
                    response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }
}

4.2 TokenUtil:获取 Access token的工具类

package com.zsh.wx_account1.util;

import com.zsh.wx_account1.entity.AccessToken;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.ObjectUtils;

/**
 * 获取 Access token的工具类
 * @Author ZhaoShuHao
 * @Date 2023/8/23 9:44
 */
public class TokenUtil {
    //自己的公众号信息
    //测试号
    private static final String APP_ID = "321312321321";
    private static final String APP_SECRET = "321321321321312332";
    //自己的公众号
   /* private static final String APP_ID = "321321321321";
    private static final String APP_SECRET = "3123123123123";*/
    private static AccessToken accessToken = new AccessToken();
    public static void main(String[] args) {

    //{"access_token":"63_8R2EcPuM3dz_D81Q2FBiSfgrlwokafQloAU33iFhHIbjabRFtC_thRqk7VOkMbarQ8lA9yyq2pgwh4pc6P-5qQutc6WWMLwFafIR6ZaLkB299OJU78npFt--I0ACXCiACAHCH","expires_in":7200}
        System.out.println(getAccessToken());
    }
    private static void getToken(){
        String url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
                APP_ID,
                APP_SECRET);
        String result = HttpUtil.doGet(url);
        if(StringUtils.isNotBlank(result)){
            JSONObject jsonObject = JSONObject.fromObject(result);
            String token = jsonObject.getString("access_token");
            long expiresIn = jsonObject.getLong("expires_in");
            accessToken.setToken(token);
            accessToken.setExpireTime(expiresIn);
        }
    }
    /**
     * 获取AccessToken
     * @return
     */
    public static String getAccessToken(){
        //如果accessToken为空或者超时,都重新获取token
        if(ObjectUtils.isEmpty(accessToken) || accessToken.isExpired()){
            getToken();
        }
        return accessToken.getToken();
    }
}

 4.3 AccessTokenUtil:微信授权登录

package com.zsh.wx_account1.util;

import com.alibaba.fastjson.JSON;
import org.junit.jupiter.api.Test;

import java.util.Map;

/**
 * 关于微信授权登录
 * @Author ZhaoShuHao
 * @Date 2023/9/1 13:48
 */
//微信授权登录,第二步,根据第一步授权后返回的code获取access_token(code可以从重定向的路径中获取)
public class AccessTokenUtil {
    private static final String url="https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";

    //自己的公众号信息
    //测试号
    private static final String APP_ID = "3123213421432423";
    private static final String APP_SECRET = "421412421344";
    //code一般只有5分钟的过期时间,过期后需要重新获取
    private static final String CODE="071Iy4ml2pjvXb4ujbll2Eg5644Iy4mb";
    public static void main(String[] args) {
        //1、根据code获取信息
      /*  Map accessToken = getAccessToken();
        System.out.println("accessToken:"+accessToken);*/
        //2、根据refreshToken刷新token
     /*   String s = refreshTokenTest();
        System.out.println(s);*/
        //3、拉去用户信息
//        String s = pullUserInfo();
        //微信授权获取用户信息的完整流程
        weChatAuthorization();
    }
    /*1、根据code获取的数据
    {
	"access_token": "72_hts4ZVuBZJKc2vROr84IZLudWXkBPrn_1pE44FgTWo_UYxu-AwzWdaI81RMulEDXrYwuOe2Src0FH4UVo_YoArFBvWW8rQEu_O5tDbUaJBs",
	"expires_in": 7200,
	  "refresh_token": "72_ESvv83WfSTTPr4MAUH4ecI-2RWRhASkWgKqyCeWWLBABWIhxWUr-_R7E1i5Yxs4CFwEf6Y44fUi0UyPinV0xdDnnXsJKe_2xYabiNyDd7W0",
	"openid": "okuVs5iLGbRWwjjotu8EsKVURyDM",
	"scope": "snsapi_userinfo"
    }
    * */
    public static Map<String,Object> getAccessToken(){
        String formatUrl = String.format(url, APP_ID, APP_SECRET, CODE);
        System.out.println("formatUrl:"+formatUrl);
        String s = HttpUtil.doGet(formatUrl);
        Map<String,Object> map = JSON.parseObject(s, Map.class);
        return map;
    }

    /*
    {
	"openid": "okuVs5iLGbRWwjjotu8EsKVURyDM",
	"access_token": "72_DmkvFgDsiySmI22VMVn82qlzlZ_tQfdu5sns-81ALUFXMK7StU9fRgxKRFQaQuW_QIgC2oGGF9jSAAowb3TVBW1jSPpCZSJgFAsmjXxQ6wc",
	"expires_in": 7200,
	"refresh_token": "72_VXoP27NOxJxILa1-MRT_2N-8Tt6mUwOrycLGjGt61j1UicZx3uwcVONRrpJdDXJvvUmSOfuiZ0iI5DD6HBB0LbgmUMEqJSMEsb7VXQXifNE",
	"scope": "snsapi_userinfo"
    }
    * */
    //2、(可选)因为accessToken的过期时间较短,可以使用refresh_token去刷新accessToken
    public static String refreshToken(String refreshToken){
        String format = String.format("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s", APP_ID, refreshToken);
        String s = HttpUtil.doGet(format);
        System.out.println("tokenInfo:"+s);
        return s;
    }
    //因为accessToken的过期时间较短,可以使用refresh_token去刷新accessToken
    public static String refreshTokenTest(){
        String format = String.format("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s", APP_ID, "72_VXoP27NOxJxILa1-MRT_2N-8Tt6mUwOrycLGjGt61j1UicZx3uwcVONRrpJdDXJvvUmSOfuiZ0iI5DD6HBB0LbgmUMEqJSMEsb7VXQXifNE");
        String s = HttpUtil.doGet(format);
        System.out.println("tokenInfo:"+s);
        return s;
    }

    /*
    {
	"openid": "okuVs5iLGbRWwjjotu8EsKVURyDM",
	"nickname": "要开心吖",
	"sex": 0,
	"language": "",
	"city": "",
	"province": "",
	"country": "",
	"headimgurl": "https:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/DYAIOgq83erD0Q9Iv5YFf31GpZG36Mjmtcee8VyOxmnrlXn1hXH61P3DZmENrrpBalGP5WJ0Qe2KW6g7bPopiaQ\/132",
	"privilege": []
}
    * */
    //3、拉取用户信息
    public static String pullUserInfo(){
        String accessToken="72_DmkvFgDsiySmI22VMVn82qlzlZ_tQfdu5sns-81ALUFXMK7StU9fRgxKRFQaQuW_QIgC2oGGF9jSAAowb3TVBW1jSPpCZSJgFAsmjXxQ6wc";
        String openId="okuVs5iLGbRWwjjotu8EsKVURyDM";
        String format = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN", accessToken, openId);
        String s = HttpUtil.doGet(format);
        System.out.println(s);
        return s;
    }

    //微信授权的完整流程
    public static String weChatAuthorization(){
        String formatUrl = String.format(url, APP_ID, APP_SECRET, CODE);
        System.out.println("formatUrl:"+formatUrl);
        String tokeninfo = HttpUtil.doGet(formatUrl);
        Map<String,Object> map = JSON.parseObject(tokeninfo, Map.class);
        String accessToken= (String) map.get("access_token");
        String openId= (String) map.get("openid");
        String format = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN", accessToken, openId);
        String userInfo = HttpUtil.doGet(format);
        System.out.println("tokeninfo:"+tokeninfo);
        System.out.println("userInfo:"+userInfo);
        return userInfo;
    }


}

4.4 IdiomJielongUtil:聚合数据-成语接龙

package com.zsh.wx_account1.util;
import com.alibaba.fastjson.JSON;
import net.sf.json.JSONObject;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Random;

/**
 * 成语接龙
 * @Author ZhaoShuHao
 * @create 2023/08/25
 */
public class IdiomJielongUtil {
    public static void main(String[] args) {
        startIdiomJielong("一心一意");
    }

    public static String startIdiomJielong(String parm){
        // 发送http请求的url
        String url = "http://apis.juhe.cn/idiomJie/query";

        Map<String, String> params = new HashMap<String, String>();
        params.put("key", "e3e9e5aaa95d4fe394d16f3d46621362"); // 在个人中心->我的数据,接口名称上方查看
        params.put("wd", parm); // 查询的成语,如:一心一意
        String paramsStr = urlencode(params);
        System.out.println(paramsStr);
        String response = doGet(url,paramsStr);
        // // post请求
        // String response = doPost(url,paramsStr);

        // 输出请求结果
        System.out.println(response);

        try {
            Map map = JSON.parseObject(response, Map.class);
            Map<String,Object> result = (Map<String, Object>) map.get("result");
            List<String> data = (List<String>) result.get("data");
            String last_word = (String) result.get("last_word");
            int i = new Random().nextInt(data.size());

            // 解析请求结果,json:
            JSONObject jsonObject = JSONObject.fromObject(response);
            System.out.println(jsonObject);

            System.out.println("成句接龙:最后一个字为:"+last_word+",俺的回答是:"+data.get(i)+",请老大您回答");
            return "成句接龙:最后一个字为:"+last_word+",俺的回答是:"+data.get(i)+",请老大您继续作答:";
            // 具体返回示例值,参考返回参数说明、json返回示例
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "您太牛了,我认输!";
    }
    // 将map型转为请求参数型
    public static String urlencode(Map<String, String> data) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry i : data.entrySet()) {
            try {
                sb.append(i.getKey()).append("=").append(URLEncoder.encode(i.getValue() + "", "UTF-8")).append("&");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }

    /**
     * get方式的http请求
     *
     * @param httpUrl 请求地址
     * @param paramStr 请求参数
     * @return 返回结果
     */

    public static String doGet(String httpUrl,String paramStr) {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        BufferedReader bufferedReader = null;
        String result = null;// 返回结果字符串
        try {
            httpUrl += "?"+paramStr;
            // 创建远程url连接对象
            URL url = new URL(httpUrl);
            // 通过远程url连接对象打开一个连接,强转成httpURLConnection类
            connection = (HttpURLConnection) url.openConnection();
            // 设置连接方式:get
            connection.setRequestMethod("GET");
            // 设置连接主机服务器的超时时间:15000毫秒
            connection.setConnectTimeout(15000);
            // 设置读取远程返回的数据时间:60000毫秒
            connection.setReadTimeout(60000);
            // 设置请求头
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            // 发送请求
            connection.connect();
            // 通过connection连接,获取输入流
            if (connection.getResponseCode() == 200) {
                inputStream = connection.getInputStream();
                // 封装输入流,并指定字符集
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
                // 存放数据
                StringBuilder sbf = new StringBuilder();
                String temp;
                while ((temp = bufferedReader.readLine()) != null) {
                    sbf.append(temp);
                    sbf.append(System.getProperty("line.separator"));
                }
                result = sbf.toString();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (null != bufferedReader) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();// 关闭远程连接
            }
        }
        return result;
    }

    /**
     * post方式的http请求
     *
     * @param httpUrl 请求地址
     * @param paramStr   请求参数
     * @return 返回结果
     */
    public static String doPost(String httpUrl, String paramStr) {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;
        BufferedReader bufferedReader = null;
        String result = null;
        try {
            URL url = new URL(httpUrl);
            // 通过远程url连接对象打开连接
            connection = (HttpURLConnection) url.openConnection();
            // 设置连接请求方式
            connection.setRequestMethod("POST");
            // 设置连接主机服务器超时时间:15000毫秒
            connection.setConnectTimeout(15000);
            // 设置读取主机服务器返回数据超时时间:60000毫秒
            connection.setReadTimeout(60000);
            // 默认值为:false,当向远程服务器传送数据/写数据时,需要设置为true
            connection.setDoOutput(true);
            // 设置传入参数的格式:请求参数应该是 name1=value1&name2=value2 的形式。
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            // 通过连接对象获取一个输出流
            outputStream = connection.getOutputStream();
            // 通过输出流对象将参数写出去/传输出去,它是通过字节数组写出的
            outputStream.write(paramStr.getBytes());
            // 通过连接对象获取一个输入流,向远程读取
            if (connection.getResponseCode() == 200) {
                inputStream = connection.getInputStream();
                // 对输入流对象进行包装:charset根据工作项目组的要求来设置
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
                StringBuilder sbf = new StringBuilder();
                String temp;
                // 循环遍历一行一行读取数据
                while ((temp = bufferedReader.readLine()) != null) {
                    sbf.append(temp);
                    sbf.append(System.getProperty("line.separator"));
                }
                result = sbf.toString();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (null != bufferedReader) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != outputStream) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
        return result;
    }
}

 4.5 JokesUtil:聚合数据-笑话大全

package com.zsh.wx_account1.util;
import com.alibaba.fastjson.JSON;
import com.google.common.primitives.Ints;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;


/**
 * 笑话大全工具类
 * @Author ZhaoShuHao
 * @create 2023/08/25
 */
public class JokesUtil {
    //接口请求地址
    //按更新时间查询笑话
    public static final String URL_A = "http://v.juhe.cn/joke/content/list.php?key=%s&&time=%d&pagesize=%d";

    //最新笑话
    public static final String URL_B = "http://v.juhe.cn/joke/content/text.php?key=%s&pagesize=%d";

    //随机笑话
    public static final String URL_C = "http://v.juhe.cn/joke/randJoke.php?key=%s";

    //申请接口的请求key
    // TODO: 您需要改为自己的请求key
    public static final String KEY = "0b2273f36f7be68b3a78bd9c4d2279b4";


    public static void main(String[] args) {

        // TODO: 日期

        //时间戳
        long time = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
        //每页数量
        int pageSize = 2;

       /* System.out.println("------------按更新时间查询笑话-----------------");
        printA(time, pageSize);
        System.out.println("------------最新笑话-----------------");
        printB(pageSize);*/
        System.out.println("------------随机笑话-----------------");
        String s = printC();
        System.out.println(s);
    }
    /**
     * 随机笑话
     *
     */
    public static String printC() {
        //发送http请求的url
        String url = String.format(URL_C, KEY);
        final String response = HttpUtil.doGet(url);
        StringBuilder contents = new StringBuilder();
        List<String> list = new ArrayList<>();
        System.out.println("接口返回:" + response);
        final int[] num = {0};
        try {
            JSONObject jsonObject = JSONObject.fromObject(response);
            int error_code = jsonObject.getInt("error_code");
            if (error_code == 0) {
                System.out.println("调用接口成功");
                JSONArray result = jsonObject.getJSONArray("result");
                result.stream().map(JSONObject::fromObject).forEach(hour -> {
                    list.add(((JSONObject) hour).getString("content"));
                    System.out.println("content:" + ((JSONObject) hour).getString("content"));
                    System.out.println("hashId:" + ((JSONObject) hour).getString("hashId"));
                    System.out.println("unixtime:" + ((JSONObject) hour).getString("unixtime"));
                });

            } else {
                System.out.println("调用接口失败:" + jsonObject.getString("reason"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        contents.append("1、"+ list.get(0)+"\r\n")
                .append("2、"+ list.get(3)+"\r\n")
                .append("3、"+ list.get(5)+"\r\n")
                .append("4、"+ list.get(7)+"\r\n")
                .append("5、"+ list.get(9)+"\r\n");;
        return String.valueOf(contents);
    }
    /**
     * 最新笑话
     *
     * @param pageSize int 每页数量
     */
    public static void printB( int pageSize) {
        //发送http请求的url
        String url = String.format(URL_B, KEY, pageSize);
        final String response = HttpUtil.doGet(url);
        System.out.println("接口返回:" + response);
        try {
            JSONObject jsonObject = JSONObject.fromObject(response);
            int error_code = jsonObject.getInt("error_code");
            if (error_code == 0) {
                System.out.println("调用接口成功");
                JSONArray result = jsonObject.getJSONObject("result").getJSONArray("data");
                result.stream().map(JSONObject::fromObject).forEach(hour -> {
                    System.out.println("content:" + ((JSONObject) hour).getString("content"));
                    System.out.println("hashId:" + ((JSONObject) hour).getString("hashId"));
                    System.out.println("unixtime:" + ((JSONObject) hour).getString("unixtime"));
                    System.out.println("updatetime:" + ((JSONObject) hour).getString("updatetime"));
                });

            } else {
                System.out.println("调用接口失败:" + jsonObject.getString("reason"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 按更新时间查询笑话
     *
     * @param time     long 时间戳
     * @param pageSize int 每页数量
     */
    public static void printA(long time, int pageSize) {
        //发送http请求的url
        String url = String.format(URL_A, KEY, time, pageSize);

        final String response = HttpUtil.doGet(url);
        System.out.println("接口返回:" + response);
        try {
            JSONObject jsonObject = JSONObject.fromObject(response);
            int error_code = jsonObject.getInt("error_code");
            if (error_code == 0) {
                System.out.println("调用接口成功");
                JSONArray result = jsonObject.getJSONObject("result").getJSONArray("data");
                result.stream().map(JSONObject::fromObject).forEach(hour -> {
                    System.out.println("content:" + ((JSONObject) hour).getString("content"));
                    System.out.println("hashId:" + ((JSONObject) hour).getString("hashId"));
                    System.out.println("unixtime:" + ((JSONObject) hour).getString("unixtime"));
                    System.out.println("updatetime:" + ((JSONObject) hour).getString("updatetime"));
                });

            } else {
                System.out.println("调用接口失败:" + jsonObject.getString("reason"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



}

 4.6 RddleUtil:聚合数据-谜语大全

package com.zsh.wx_account1.util;


import com.alibaba.fastjson.JSON;

import java.util.Map;

/**
 * 谜语大全
 * @Author ZhaoShuHao
 * @create 2023/08/26
 */
public class RddleUtil {
    //申请接口的请求key
    // TODO: 您需要改为自己的请求key
    public static final String KEY = "213213213123213123";

    //谜语大全
    public static final String URL_C = "http://apis.juhe.cn/fapigx/riddle/query?key=%s";

    public static void main(String[] args) {
        getRddle();
    }
    //获取谜语
    public static String getRddle(){
        String url =String.format(URL_C,KEY);
        String result =  "对不起大佬,谜语大全出了点问题,请联系管理员小弟";
        try {
            String rddle = HttpUtil.doGet(url);;
            Map map = JSON.parseObject(rddle, Map.class);
            Map result1 = (Map) map.get("result");
            String quest = (String) result1.get("quest");
            String answer = (String) result1.get("answer");
            result= "大佬请猜猜谜语:"+"\r\n\r\n\r\n"+quest+"\r\n\r\n\r\n"+"您猜到了吗?"+"\r\n\r\n\r\n\r\n\r\n"+"让小子为您揭晓谜底吧,它就是:"+"\r\n\r\n\r\n\r\n\r\n"+answer;
            System.out.println(result);
        }catch (Exception e){
            e.printStackTrace();
        }
        return result;
    }
}

 4.7 SoupUtil:聚合数据-心灵鸡汤

package com.zsh.wx_account1.util;


import com.alibaba.fastjson.JSON;

import java.util.Map;

/**
 * 心灵鸡汤
 * @Author ZhaoShuHao
 * @create 2023/08/26
 */
public class SoupUtil {
    //申请接口的请求key
    // TODO: 您需要改为自己的请求key
    public static final String KEY = "xxxxxxxxxxxxxxxxxxx";

    //谜语大全
    public static final String URL_C = "https://apis.juhe.cn/fapig/soup/query?key=%s";

    public static void main(String[] args) {
        getSoup();
    }
    //获取谜语
    public static String getSoup(){
        String url =String.format(URL_C,KEY);
        String result =  "对不起大佬,心灵鸡汤出了点问题,请联系管理员小弟";
        try {
            String soup = HttpUtil.doGet(url);;
            System.out.println(soup);
            Map map = JSON.parseObject(soup, Map.class);
            Map result1 = (Map) map.get("result");
            String quest = (String) result1.get("text");
            result= "Good Good Study,Day Day Up;"+"\r\n\r\n\r\n"+"大佬正能量哦:"+"\r\n\r\n\r\n"+quest+"\r\n\r\n\r\n"+"传播新思想,弘扬正能量,大佬要开心哦!";
            System.out.println(result);
        }catch (Exception e){
            e.printStackTrace();
        }
        return result;
    }
}

 4.8 WordUtil:聚合数据-同义词/反义词

package com.zsh.wx_account1.util;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
 * @Author ZhaoShuHao
 * @Date 2023/8/22 16:36
 */
public class WordUtil {
    //聚合数据网站的api接口(同义词/反义词查询)
    public static final String WORD_URL = "http://apis.juhe.cn/tyfy/query?key=%s";
    //申请接⼝的请求key
    // TODO: 您需要改为⾃⼰的请求key
    public static final String KEY = "xxxxxxxxxxxxxxxxx";
    public static String getWords(String word) {
        HttpUtil httpUtil = new HttpUtil();
        //发送http请求的url
        String url = String.format(WORD_URL, KEY);
        final String response =httpUtil.doPost(url,"word="+word,"application/x-www-form-urlencoded");
        System.out.println("接⼝返回:" + response);
        try {
            JSONObject jsonObject =
                    JSONObject.fromObject(response);
            int error_code = jsonObject.getInt("error_code");
            if (error_code == 0) {
                System.out.println("调⽤接⼝成功");
                JSONObject result =
                        jsonObject.getJSONObject("result");
                JSONArray words = result.getJSONArray("words");
                StringBuilder stringBuilder = new
                        StringBuilder();
                words.stream().forEach(w->stringBuilder.append(w+" "));
                System.out.println(stringBuilder);
                return "'"+word+"'的同义词有:"+stringBuilder.toString();
            } else {
                System.out.println("调⽤接⼝失败:" +
                        jsonObject.getString("reason"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "'"+word+"'的同义词暂没找到,请联系管理员扩展";
    }

}

5.接口测试

5.1 自定义菜单

package com.zsh.wx_account1.controller;

import com.zsh.wx_account1.entity.*;
import com.zsh.wx_account1.util.HttpUtil;
import com.zsh.wx_account1.util.TokenUtil;
import net.sf.json.JSONObject;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

/**
 *  二级菜单
 * @Author ZhaoShuHao
 * @Date 2023/8/23 9:37
 */
public class TestButton {

    public static void main(String[] args) {
        //测试号
        String APP_ID = "xxxxxxxxxxxxxx";
        String url1="https://blog.csdn.net/ZhShH0413?spm=1010.2135.3001.5343";
        String encode = URLEncoder.encode(url1);
        String url2="https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
        String formatUrl = String.format(url2, APP_ID, encode);
        System.out.println(formatUrl);
        //创建一级菜单
        Button button = new Button();
        List<AbstractButton> buttons = new ArrayList<>();
        //一级菜单中的第一个按钮
        ClickButton clickButton = new ClickButton("笑话大全","jokes");
        //一级菜单中的第二个按钮
        ClickButton clickButton2 = new ClickButton("谜语大全","rddle");
        //一级菜单中的第三个按钮(二级菜单)
        SubButton subButton = new SubButton("快快点我");
        List<AbstractButton> subButtons = new ArrayList<>();
        //二级菜单的第一个按钮
//        subButtons.add(new ViewButton("大佬给个关注吧","https://blog.csdn.net/ZhShH0413?spm=1010.2135.3001.5343"));
        subButtons.add(new ViewButton("大佬给个关注吧",formatUrl));
        //二级菜单的第二个按钮
        subButtons.add(new ClickButton("心灵鸡汤","soup"));
        //二级菜单的第二个按钮
        subButtons.add(new PhotoOrAlbumButton("上传图片(带有文字的图片有惊喜哦)"));
        subButton.setSub_button(subButtons);
        //把一级菜单中的三个按钮添加进集合
        buttons.add(clickButton);
        buttons.add(clickButton2);
        buttons.add(subButton);
        //把集合添加到一级菜单中
        button.setButton(buttons);
        //转换成json字符串
        JSONObject jsonObject = JSONObject.fromObject(button);
        System.out.println(jsonObject);
        String json = jsonObject.toString();
        String url = String.format("https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%s", TokenUtil.getAccessToken());
        //发送请求
        String result = HttpUtil.doPost(url, json,"application/json;charset=utf-8");
        System.out.println(result);

    }

}

5.2 素材管理

package com.zsh.wx_account1.controller;

import com.zsh.wx_account1.util.HttpUtil;
import com.zsh.wx_account1.util.TokenUtil;
import org.junit.jupiter.api.Test;

/**
 * 素材管理
 * @Author ZhaoShuHao
 * @Date 2023/8/25 11:40
 */
public class TestMaterialManagement {
    //上传临时素材
    @Test
    public void testImage(){
        //这里上传了一个图片
        String url = String.format("https://api.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=%s",
                TokenUtil.getAccessToken(),
                "image");
        String result = HttpUtil.doPostByFile(url, null, "src/main/resources/static/image/image1.jpg", "");
        System.out.println(result);
//{"type":"image","media_id":"gw-BxwWm3mP6T2M_OBR1IzPwl6YcFFncr4fx3CrS-wtJOd78l7evdmUm5e3b2BZP","created_at":1692935476,"item":[]}
    }

    /*
    图片地址:https://api.weixin.qq.com/cgi-bin/media/get?access_token=token的值&media_id=图片id
    https://api.weixin.qq.com/cgi-bin/media/get?access_token=71_3PiSMSASfd1s9s5CFK30XX3CaG3IamKRjT25tmfShuk4i2I3y3Ze0ebR0SSES-hro5T7zO5YVEo0pWiaedG3Yv5y4qRcoETPNRbqJJKOYxpH5ac_rD3CPtfCuZQTGGdAIAYLL&media_id=gw-BxwWm3mP6T2M_OBR1IzPwl6YcFFncr4fx3CrS-wtJOd78l7evdmUm5e3b2BZP
     */

    //获得临时素材
    @Test
    public void testGetImage(){
        String mediaId = "gw-BxwWm3mP6T2M_OBR1IzPwl6YcFFncr4fx3CrS-wtJOd78l7evdmUm5e3b2BZP";
        String url = String.format("https://api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s",
                TokenUtil.getAccessToken(),
                mediaId);
        String result = HttpUtil.doGet(url);
        System.out.println(result);

    }
}

5.3 自定义模板消息

package com.zsh.wx_account1.controller;

import com.zsh.wx_account1.util.HttpUtil;
import com.zsh.wx_account1.util.TokenUtil;
import org.junit.jupiter.api.Test;

/**
 * 测试模板消息
 * @Author ZhaoShuHao
 * @Date 2023/8/25 9:28
 */
public class TestModelMessage {
    //测试设置所属行业(模版消息的前置条件)
    @Test
    public void testSetTrade(){
        String url = String.format("https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token=%s", TokenUtil.getAccessToken());
        String data = "{\n" +
                "    \"industry_id1\":\"1\",\n" +
                "    \"industry_id2\":\"4\"\n" +
                "}";
        String s = HttpUtil.doPost(url, data, "application/x-www-form-urlencoded");
        System.out.println(s);
    }
    //测试查询所属行业
    @Test
    public void testGetTrade(){
        String url = String.format("https://api.weixin.qq.com/cgi-bin/template/get_industry?access_token=%s",TokenUtil.getAccessToken());
        System.out.println(HttpUtil.doGet(url));
    }
    //获取模版列表
    @Test
    public void testGetModelMessage(){
        String url = String.format("https://api.weixin.qq.com/cgi-bin/template/get_all_private_template?access_token=%s", TokenUtil.getAccessToken());
        String s = HttpUtil.doGet(url);
        System.out.println(s);
    }


    //测试发送模版消息
    @Test
    public void testModelmessage(){
        String url = String.format("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s", TokenUtil.getAccessToken());
         /*  String data = "{\n" +
                "           \"touser\":\"okuVs5iLGbRWwjjotu8EsKVURyDM\",\n" +
                "           \"template_id\":\"EOlNyURgdR1rnZx3_x_k9iHb4j5CZ3dshCZxZbCsU1w\",\n" +
                "           \"url\":\"https://blog.csdn.net/ZhShH0413?spm=1010.2135.3001.5343\",\n" +
                "           \"data\":{\n" +
                "                   \"keyword1\": {\n" +
                "                       \"value\":\"张三,恭喜您报名比赛成功\"\n" +
                "                   },\n" +
                "                   \"keyword2\":{\n" +
                "                       \"value\":\"A队\"\n" +
                "                   },\n" +
                "                   \"keyword3\": {\n" +
                "                       \"value\":\"2023年8月26日 7:00\"\n" +
                "                   },\n" +
                "                   \"keyword4\": {\n" +
                "                       \"value\":\"XX集团东大门\"\n" +
                "                   },\n" +
                "                   \"keyword5\": {\n" +
                "                       \"value\":\"A队1人,B队66人\"\n" +
                "                   },\n" +
                "                   \"keyword6\":{\n" +
                "                       \"value\":\"点击链接有惊喜,双击关注666\"\n" +
                "                   }\n" +
                "           }\n" +
                "       }";*/
        String data = "{\n" +
                "\t\"data\":{\n" +
                "\t\t\"CONTENT\":{\n" +
                "\t\t\t\"color\":\"\",\n" +
                "\t\t\t\"value\":\"通知通知通知通知通知\"\n" +
                "\t\t}\n" +
                "\t},\n" +
                "\t\"template_id\":\"gDN9OJDU4aXG0I4jbwww-6RFjS3YLMs8cHG8bJSpdU0\",\n" +
                "\t\"touser\":\"okuVs5iLGbRWwjjotu8EsKVURyDM\"\n" +
                "}";
        System.out.println(HttpUtil.doPost(url, data,"application/x-www-form-urlencoded"));
    }



}

5.4 用户账号管理

package com.zsh.wx_account1.controller;

import com.zsh.wx_account1.util.HttpUtil;
import com.zsh.wx_account1.util.TokenUtil;
import org.junit.jupiter.api.Test;

import java.net.HttpCookie;

/**
 * 用户账号管理
 * @Author ZhaoShuHao
 * @Date 2023/8/25 13:25
 */
public class TestAccountManagement {
    //生成带参数的二维码
    @Test
    public void testQRcode(){
        String url = String.format(" https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s",
                TokenUtil.getAccessToken());
        String data = "{\"expire_seconds\": 604800, \"action_name\": \"QR_SCENE\", \"action_info\": {\"scene\": {\"scene_id\": 123}}}";
        String s = HttpUtil.doPost(url, data, "application/x-www-form-urlencoded");
        System.out.println(s);
    }
    /*
    https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET
    * https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQEA8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyeW1TVFVPaUJkSUMxVFhTTk5BMVkAAgR7POhkAwSAOgkA
     * */
    //通过ticket换取二维码
    @Test
    public void testGetQRcode(){
        String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQEA8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyeW1TVFVPaUJkSUMxVFhTTk5BMVkAAgR7POhkAwSAOgkA";
        String s = HttpUtil.doGet(url);
        System.out.println(s);
    }
}

5.5 处理公众号的一些事件(关注、文字、图片、按钮)

package com.zsh.wx_account1.controller;

import com.baidu.aip.ocr.AipOcr;
import com.thoughtworks.xstream.XStream;
import com.zsh.wx_account1.entity.Article;
import com.zsh.wx_account1.entity.NewsMessage;
import com.zsh.wx_account1.entity.TextMessage;
import com.zsh.wx_account1.util.*;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.function.Consumer;

/**
 * @Author ZhaoShuHao
 * @Date 2023/8/21 16:11
 */
@RestController
@RequestMapping("/wxTest/wx")
public class GetWxController {
    //百度AI的个人相关信息
    public static final String APP_ID = "xxxxxxx";
    public static final String API_KEY = "xxxxxxxxxxxxxxxx";
    public static final String SECRET_KEY = "xxxxxxxxxxxxx";
    //定义click按钮的eventKey,方便区分
    //笑话大全
    public static final String JOKES = "jokes";
    //谜语大全
    public static final String RDDLE = "rddle";
    //心灵鸡汤
    public static final String SOUP = "soup";
    /*校验信息是否来自微信服务器
    signature:微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
    timestamp: 时间戳
    nonce:随机数
    echostr:随机字符串
    * */
    @GetMapping("/")
    public String checkToken(String signature,String timestamp,String nonce,String echostr){
        // 1)将token、timestamp、nonce三个参数进⾏字典序排序
        String token = "zsh";
        List<String> list = Arrays.asList(token, timestamp, nonce);
        //排序
        Collections.sort(list);
        System.out.println("signature:"+signature);
        System.out.println("list:"+list);
        // 2)将三个参数字符串拼接成⼀个字符串进⾏sha1加密
        StringBuilder stringBuilder = new StringBuilder();
        list.stream().forEach(s -> stringBuilder.append(s));
        System.out.println("stringBuilder.toString():"+stringBuilder.toString());
        //加密
        try {
            MessageDigest sha1 = MessageDigest.getInstance("sha1");
            //使用sha1进行加密,获得byte[]数组
            byte[] digest = sha1.digest(stringBuilder.toString().getBytes());
            System.out.println("digest:"+digest);
            System.out.println("digest.toString():"+  digest.toString());
            System.out.println("new String(digest):"+ new String(digest));
            System.out.println("Arrays.toString(digest):"+ Arrays.toString(digest));
//            String sum = integerToHexString(digest);
//            String sum = stringFormat(digest);
            String sum = integerToHexString2(digest);
            // 3)开发者获得加密后的字符串可与 signature 对⽐,标识该请求来源于微信
            if (!StringUtils.isEmpty(signature) && signature.equals(sum)) {
                System.out.println("sum:"+sum);
                return echostr;
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }
    //第一种方式,课程上的方式(使用Integer.toHexString)
    private String integerToHexString(byte[] digest){
        StringBuilder sum = new StringBuilder();
        for (byte b : digest) {
            sum.append(Integer.toHexString((b>>4)&15));
            sum.append(Integer.toHexString(b&15));
        }
        return sum.toString();
    }
   /* 第二种方式(字符串格式 %02xString.format())
   * 这String.format是将字节数组转换为十六进制的最简单和明显的方法,%02x对于小写十六进制,%02X大写十六进制。
   * */
    private String stringFormat(byte[] digest){
        StringBuilder sum = new StringBuilder();
        for (byte b : digest) {
            sum.append(String.format("%02x", b));
        }
        return sum.toString();
    }
    //第三种方式(Integer.toHexString(decimal))
    private String integerToHexString2(byte[] digest){
        StringBuilder result = new StringBuilder();
        for (byte aByte : digest) {
            int decimal = (int) aByte & 0xff;               // bytes widen to int, need mask, prevent sign extension
            // get last 8 bits
            String hex = Integer.toHexString(decimal);
            if (hex.length() % 2 == 1) {                    // if half hex, pad with zero, e.g \t
                hex = "0" + hex;
            }
            result.append(hex);
        }
        return result.toString();
    }

    //获取用户向测试号发送的消息,输出到控制台上
    /*@PostMapping("/")
    public String receiveMessage(HttpServletRequest request) throws IOException{
        ServletInputStream inputStream = request.getInputStream();
        byte[] bytes = new byte[1024];
        System.out.println("inputStream:"+inputStream);
        int len = 0;
        while ((len=inputStream.read(bytes))!=-1){
            System.out.println(new String(bytes, 0, len));
        }
        return "";
    }*/
    //获取用户向测试号发送的消息,并解析,封装成map结构
    @PostMapping("/")
    public String receiveMessage(HttpServletRequest request) throws IOException{
        ServletInputStream inputStream = request.getInputStream();
        Map<String, String> map = new HashMap<>();
        //获取xml解析工具类
        SAXReader saxReader = new SAXReader();
        try {
            //读取request输⼊流,获得Document对象
            Document document = saxReader.read(inputStream);
            //获得root节点
            Element rootElement = document.getRootElement();
            //获取所有子节点
            List<Element> elements = rootElement.elements();
            elements.stream().forEach(new Consumer<Element>() {
                @Override
                public void accept(Element element) {
                    map.put(element.getName(),element.getStringValue());
                }
            });

        } catch (DocumentException e) {
            e.printStackTrace();
        }
        System.out.println("消息为:"+map);
        //回复消息的格式必须为xml的格式
        //1、简单的回复
        /*String message ="<xml> " +
                "<ToUserName><![CDATA[okuVs5iLGbRWwjjotu8EsKVURyDM]]></ToUserName>" +
                " <FromUserName><![CDATA[gh_54b74a688c3b]]></FromUserName>" +
                " <CreateTime>1692685746</CreateTime> <MsgType><![CDATA[text]]>" +
                "</MsgType> <Content><![CDATA[你好]]></Content> " +
                "</xml>";*/
        //2、封装消息回复
//        String message = getReplyMessageByWord(map);

        String message = null;
        String msgType = map.get("MsgType");
        switch (msgType){
            case "text":
                if(map.get("Content").equals("图文")){
                    //回复图文信息
                    message = getReplyNewsMessage(map);
                }else {
                    //成语接龙
                    String content = IdiomJielongUtil.startIdiomJielong(map.get("Content"));
                    message = assembleTextXMLFormat(content,map);
                    //3、消息处理案例-接⼊第三⽅服务接⼝(获取同义词)
                    //message = getReplyMessageByWord(map);
                }
                break;
            case "event":
                //处理事件
                message = handleEvent(map);
                break;
            case "image":
                message=handleImage(map);
                break;
            default:
                break;
        }
        System.out.println(message);
        return message;
    }
    //2、封装消息格式
   /* private String getReplyMessageByWord(Map<String, String> map) {
        TextMessage textMessage = new TextMessage();
        textMessage.setToUserName(map.get("FromUserName"));
        textMessage.setFromUserName(map.get("ToUserName"));
        textMessage.setMsgType("text");
        textMessage.setContent("哈哈哈哈哈哈哈哈哈");
        textMessage.setCreateTime(System.currentTimeMillis()/1000);
        //XStream将Java对象转换成xml字符串
        XStream xStream = new XStream();
        xStream.processAnnotations(TextMessage.class);
        String xml = xStream.toXML(textMessage);
        return xml;
    }*/
    //封装文本text的xml结构(回复文本消息可以通用)
    private String assembleTextXMLFormat(String content,Map<String,String > map){
        TextMessage textMessage = new TextMessage();
        textMessage.setToUserName(map.get("FromUserName"));
        textMessage.setFromUserName(map.get("ToUserName"));
        textMessage.setMsgType("text");
        textMessage.setContent(content);
        textMessage.setCreateTime(System.currentTimeMillis()/1000);
        //XStream将Java对象转换成xml字符串
        XStream xStream = new XStream();
        xStream.processAnnotations(TextMessage.class);
        String xml = xStream.toXML(textMessage);
        return xml;
    }
    //3.消息处理案例-接⼊第三⽅服务接⼝(获取同义词)
    private String getReplyMessageByWord(Map<String, String> map)
    {
        String content = WordUtil.getWords(map.get("Content"));
        return assembleTextXMLFormat(content,map);
    }
    //获取图文消息
    private String getReplyNewsMessage(Map<String, String> map) {
        NewsMessage newsMessage = new NewsMessage();
        newsMessage.setToUserName(map.get("FromUserName"));
        newsMessage.setFromUserName(map.get("ToUserName"));
        newsMessage.setMsgType("news");

        newsMessage.setCreateTime(System.currentTimeMillis()/1000);
        newsMessage.setArticleCount(1);
        List<Article> articles = new ArrayList<>();
        Article article = new Article();
        article.setTitle("要开心呀的csdn个人中心");
        article.setDescription("要开心呀的csdn个人中心,个人笔记、学习记录");
                article.setUrl("https://blog.csdn.net/ZhShH0413?spm=1000.2115.3001.5343");

        article.setPicUrl("http://mmbiz.qpic.cn/sz_mmbiz_jpg/IPwvTbhAHQL1rPJgNdCuD2udSmC7icF7bFtqdOejlAIFQo9HibTFLggqtbRfObia9XP90f9gSQ2mYWApBkSjcl1lA/0");
                articles.add(article);
        newsMessage.setArticles(articles);
        //XStream将Java对象转换成xml字符串
        XStream xStream = new XStream();
        xStream.processAnnotations(NewsMessage.class);
        String xml = xStream.toXML(newsMessage);
        return xml;
    }

    /**
     * 处理事件推送
     * @param map
     * @return
     */
    private String handleEvent(Map<String, String> map) {
        String message = null;
        String event = map.get("Event");
        switch (event){
            case "CLICK":
                String eventKey = map.get("EventKey");
                if(JOKES.equals(eventKey)){
                    String s = JokesUtil.printC();
                    message =assembleTextXMLFormat(s,map);
                }else if(RDDLE.equals(eventKey)){
                    String rddle = RddleUtil.getRddle();
                    message =assembleTextXMLFormat(rddle,map);
                }else if(SOUP.equals(eventKey)){
                    String soup = SoupUtil.getSoup();
                    message =assembleTextXMLFormat(soup,map);
                }
                break;
            case "VIEW":
                message =  assembleTextXMLFormat("view",map);
                System.out.println("view");
                break;
            case "pic_photo_or_album":
                message =  assembleTextXMLFormat("pic_photo_or_album",map);
                System.out.println("pic_photo_or_album");
            case "unsubscribe":
            case "subscribe":
                message = handleSubscribe(map);
                System.out.println("subscribe");
                break;
            default:
                break;
        }
        return message;
    }

    //借用百度Api实现网络图片文字识别
    private String handleImage(Map<String, String> map) {
        // 初始化⼀个AipOcr
        AipOcr client = new AipOcr(APP_ID, API_KEY, SECRET_KEY);
        // ⽹络图⽚⽂字识别, 图⽚参数为远程url图⽚
        String url = map.get("PicUrl");
        JSONObject res = client.webImageUrl(url, new HashMap<String,String>());
        System.out.println(res.toString(2));
        JSONArray wordsResult = res.getJSONArray("words_result");
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("大佬瞅我眼不眼熟:\r\n\r\n\r\n\r\n");
        Iterator<Object> iterator = wordsResult.iterator();
        while(iterator.hasNext()){
            JSONObject next = (JSONObject) iterator.next();
            stringBuilder.append(next.getString("words"));
        }
        stringBuilder.append("\r\n\r\n\r\n\r\n"+"没错,小弟我啊,还能文字识图,给个关注吧!");
        return  assembleTextXMLFormat(stringBuilder.toString(),map);
    }

    //关注事件
    private String handleSubscribe(Map<String,String > map){
        String content= "尊敬的大佬,欢迎您关注本公众号,小弟可以为您服务的有:\r\n(1)成语接龙:您只要输入一个成语,小弟就能做出回答,快来和小弟比划比划!" +
                "\r\n(2)图片文字识别:您发送一个带文字的图片,小弟就可以帮您识别文字!\r\n(3)笑话大全:可能不好笑,但小弟还是希望大佬能哈哈哈哈!" +
                "\r\n(4)谜语大全:快点来猜猜看吧,不能偷看答案哦!\r\n(5)心灵鸡汤:让小弟用鸡汤来安抚您吧,当然鸡汤可能不咋地!" +
                "\r\n大佬注意了:给小弟一个关注好不好,csdn求个关注,谢谢大佬!";
        return assembleSubscribeEnventXMLFormat(content,map);
    }

    //封装文本text的xml结构(回复文本消息可以通用)
    private String assembleSubscribeEnventXMLFormat(String content,Map<String,String > map){
        TextMessage textMessage = new TextMessage();
        textMessage.setToUserName(map.get("FromUserName"));
        textMessage.setFromUserName(map.get("ToUserName"));
        textMessage.setMsgType("text");
        textMessage.setContent(content);
        textMessage.setCreateTime(System.currentTimeMillis()/1000);
        //XStream将Java对象转换成xml字符串
        XStream xStream = new XStream();
        xStream.processAnnotations(TextMessage.class);
        String xml = xStream.toXML(textMessage);
        return xml;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/576811.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL基础知识——MySQL索引

深入浅出索引 索引的意义 索引的意义&#xff1a;在大量数据中&#xff0c;加速访问少量特定数据&#xff1b; 使用索引的前提条件&#xff1a; 1&#xff09;索引块数量小于数据块数量&#xff1b; 2&#xff09;索引键有序&#xff0c;故可以使用二分查找等高效的查找方式&…

互联网安全面临的全新挑战

前言 当前移动互联网安全形势严峻&#xff0c;移动智能终端漏洞居高不下、修复缓慢&#xff0c;移动互联网恶意程序持续增长&#xff0c;同时影响个人和企业安全。与此同时&#xff0c;根据政策形势移动互联网安全监管重心从事前向事中事后转移&#xff0c;需加强网络安全态势感…

ETF期权是什么详解

ETF期权是什么 ETF期权的本质是一种金融衍生品&#xff0c;与交易所交易基金&#xff08;Exchange-Traded Fund&#xff0c;简称ETF&#xff09;相关的期权合约。其核心在于赋予了投资者在未来某个时间点以约定价格买入或卖出特定ETF&#xff08;交易所交易基金&#xff09;的…

百望云发布金盾企业经营大模型,暨光明食品、法雷奥、西奥电梯财税数字化实践分享

百望云发布金盾企业经营大模型&#xff0c;暨光明食品、法雷奥、西奥电梯财税数字化实践分享 数字化转型思想指导下&#xff0c;如何标定好、利用好、管理好数据资产&#xff0c;已经成为企业寻找发展新动能的着力点。 基于此&#xff0c;“2024数字商业创新论坛”于4月26号在上…

2017美亚杯--个人赛

1、Gary的笔记本电脑已成功取证并制作成镜像 (Forensic Image)&#xff0c;下列哪个是其MD5哈希值。A.0CFB3A0BB016165F1BDEB87EE9F710C9 B.5F1BDEB87EE9F710C90CFB3A0BB01616 C.A0BB016160CFB3A0BB0161661670CFB3 D.16160CFB3A0BB016166A0BB016166167 E.FB3A0BB016165 B016166…

【论文阅读】Self-DC:何时检索,何时生成?

对于RAG来说&#xff0c;什么时候利用外部检索&#xff0c;什么时候使用大模型产生已知的知识&#xff0c;以回答当前的问题?这是一个非常有趣的话题。 《Self-DC: When to retrieve and When to generate? Self Divide-and-Conquer for Compositional Unknown Questions》这…

环境配置——Windows平台配置VScode运行环境为远程服务器或虚拟机

1. 远程机需要先安装SSH服务&#xff0c;命令如下 sudo apt install openssh-server 2. 安装好后需要开启SSH服务&#xff1a; sudo service sshd start 3. 查看SSH服务是否有被开启&#xff1a; sudo systemctl status sshd.service 4. 本地Windows需要生成密钥将公钥放…

Windows 安全中心:页面不可用 你的 IT 管理员已限制对此应用的某些区域的访问,并且你尝试访问的项目不可用。有关详细信息,请与 IT 支持人员联系。

问题 1&#xff1a;Windows 安全中心提示&#xff1a;【页面不可用 你的 IT 管理员已限制对此应用的某些区域的访问&#xff0c;并且你尝试访问的项目不可用。有关详细信息&#xff0c;请与 IT 支持人员联系。】 修复 Microsoft.SecHealthUI 方法 1&#xff1a;命令自动重装安…

IDM下载器_Internet Download Manager 6.42.7

网盘下载 IDM下载器是一款针对互联网所打造的下载管理器。IDM下载器能将下载速度提高5倍&#xff0c;恢复因丢失的连接&#xff0c;网络问题&#xff0c;计算机关闭或意外断电而重新启动中断或中断的下载。IDM下载器还可支持所有流行的浏览器&#xff0c;以使用独特的“高级浏…

mysql8.0免安装版windows

1.下载 MySQL下载链接 2.解压与新建my.ini文件 解压的路径最好不要有中文路径在\mysql-8.0.36-winx64文件夹下新建my.ini文件&#xff0c;不建data文件夹(会自动生成) [mysqld] # 设置3306端口 port3306 # 设置mysql的安装目录(尽量用双斜杠\\,单斜杠\可能会报错) basedirD:\…

Linux系统----信号(万字文章超级详细并且简单易学附有实操shell指令图及注释!)

绪论​ “Do one thing at a time, and do well.”&#xff0c;本章开始Linux系统其中信号是学习操作系统的基本下面将会讲到什么是信号、信号的多种产生方式、信号如何保存的、信号如何处理的、以及一些信号的细节。话不多说安全带系好&#xff0c;发车啦&#xff08;建议电脑…

qmt教程2----订阅单股行情,提供源代码

链接 qmt教程2----订阅单股行情&#xff0c;提供源代码 (qq.com) qmt教程1---qmt安装&#xff0c;提供下载链接 今天我重新封装了全部qmt的内容&#xff0c;包括数据&#xff0c;交易 qmt交易 我本来打算全部上次git的&#xff0c;但是考虑到毕竟是实盘的内容&#xff0c;就放…

w64devkit 下载,不需要下载MinGW了

w64devkit一个很方便的工具&#xff0c;不需要下载MinGW了 介绍 这里后面我为大家准备了 3 种下载方式&#xff0c;总有一个适合你&#xff0c;嘿嘿&#xff01;&#xff01; 在 linux 上大家常用的编译工具就是 gcc&#xff0c;这些工具 windows 上也是有的&#xff0c;常用…

平衡小车的控制算法--结合自动控制原理学习

单纯的去看自控原理&#xff0c;很多概念有点抽象&#xff0c;最好找些应用去理解相关的概念&#xff0c;就找了实验室的一个平衡小车作为应用&#xff0c;不过主要根据小车去跑matlab去验证一些控制算法。结合台湾国立交通大学林沛群的自控线上课的总结 一、自控原理重要概念 …

从零入门区块链和比特币(第二期)

欢迎来到我的区块链与比特币入门指南&#xff01;如果你对区块链和比特币感兴趣&#xff0c;但不知道从何开始&#xff0c;那么你来对地方了。本博客将为你提供一个简明扼要的介绍&#xff0c;帮助你了解这个领域的基础知识&#xff0c;并引导你进一步探索这个激动人心的领域。…

Java Web 网页设计(3)

3.servlet JavaWeb——Servlet&#xff08;全网最详细教程包括Servlet源码分析&#xff09;-CSDN博客 servlet java不支持 只有Tomcat支持 使用时添加一下 servlet中最常用的两个&#xff08;固定&#xff09;方法&#xff1a; 下面我们创建一个servlet类 package com.oracle…

[极客大挑战 2019]Upload、[ACTF2020 新生赛]Upload、[MRCTF2020]你传你呢

[极客大挑战 2019]Upload 打开环境&#xff0c;是上传一句话木马的题 先上传1.php试试&#xff0c;发现不可以 试试改后缀为phtml&#xff0c;提示语句中不能包含<?&#xff0c;只能改木马&#xff1a; <script language"php">eval($_POST[line]);</sc…

[C++][算法基础]欧拉函数(常规求质数)

给定 n 个正整数 &#xff0c;请你求出每个数的欧拉函数。 欧拉函数的定义 1∼N 中与 N 互质的数的个数被称为欧拉函数&#xff0c;记为 ϕ(N)。 若在算数基本定理中&#xff0c;N…&#xff0c;则&#xff1a; ϕ(N) N… 输入格式 第一行包含整数 n。 接下来 n 行&#xf…

通信原理(2)--随机过程

通信原理(2)–随机过程 3.1随机过程的基本概念 随机过程{x(t)}由一族时间函数 x i ( t ) x_i(t) xi​(t)&#xff0c;i1,2.3…组成&#xff0c;每一个时间函数 x i ( t ) x_i(t) xi​(t)称为随机过程{x(t)}的一个样本函数&#xff08;一个实现&#xff09; 每个样本函数在时间…

使用composer开发自己的扩展包

前言 日常的开发中我们经常用到composer去安装其他人封装好的扩展包&#xff0c;如果你有好的功能代码想分享给其他人使用&#xff0c;就可以使用composer打包成扩展包。其他人用composer安装后就可以使用你的扩展包了。这篇文章教你如何打包自己的composer扩展包。 1.新建仓…