微信对接2

pom.xml

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.company</groupId>
    <artifactId>javademo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>javademo</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
        <relativePath />
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>23.0</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.54</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.7</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
        </dependency>
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

application.properties

server.port=80
logging.path=./logs/

WeiXinUtils.java

package com.company.javademo;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;

/**
 * 依赖以下jar包
 * <dependency>
 *     <groupId>com.google.guava</groupId>
 *     <artifactId>guava</artifactId>
 *     <version>23.0</version>
 * </dependency>
 * <dependency>
 *     <groupId>com.alibaba</groupId>
 *     <artifactId>fastjson</artifactId>
 *     <version>1.2.54</version>
 * </dependency>
 * <dependency>
 *     <groupId>org.apache.httpcomponents</groupId>
 *     <artifactId>httpclient</artifactId>
 *     <version>4.5.6</version>
 * </dependency>
 */

/**
 * 微信操作帮助类
 */
public class WeiXinUtils {

    static Logger logger = LoggerFactory.getLogger(WeiXinUtils.class);

    /**
     * 微信用户基本信息
     */
    static class UserInfo {
        public Integer subscribe;
        public String openid;
        public String nickname;
        public Integer sex;
        public String language;
        public String city;
        public String province;
        public String country;
        public String headimgurl;
        public Long subscribe_time;
        public String unionid;
        public String remark;
        public Integer groupid;
        public List<Integer> tagid_list;
        public String subscribe_scene;
        public Integer qr_scene;
        public String qr_scene_str;
    }

    /**
     * 批量获取用户基本信息
     *
     * @param access_token
     * @param openids
     * @return
     */
    public static List<UserInfo> batchgetUsers(String access_token, List<String> openids) {

        class UserOpenId {
            public String openid;
            public String lang = "zh_CN";

            public UserOpenId(String openid) {
                this.openid = openid;
                this.lang = "zh_CN";
            }
        }

        class UserInfoBatchGetRequest {
            public List<UserOpenId> user_list;

            public UserInfoBatchGetRequest(List<UserOpenId> user_list) {
                this.user_list = user_list;
            }
        }

        class UserInfoBatchGetResponse {
            public List<UserInfo> user_info_list;

        }

        List<UserOpenId> userOpenIds = null;

        List<List<String>> parts = Lists.partition(openids, 100);

        List<UserInfo> userInfos = new ArrayList<UserInfo>();

        for (List<String> part : parts) {

            userOpenIds = new ArrayList<UserOpenId>();

            for (String openid : part) {
                userOpenIds.add(new UserOpenId(openid));
            }

            String url = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token=" + access_token;

            UserInfoBatchGetRequest request = new UserInfoBatchGetRequest(userOpenIds);
            String res = httpPost(url, JSONObject.toJSONString(request));

            UserInfoBatchGetResponse response = JSONObject.parseObject(res, UserInfoBatchGetResponse.class);

            userInfos.addAll(response.user_info_list);

        }

        return userInfos;
    }

    /**
     * 获取用户列表
     *
     * @param access_token
     * @return
     */
    public static List<String> userGet(String access_token) {

        String url = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=" + access_token + "&next_openid=";

        class UserGetResponseData {
            public List<String> openid;
        }

        class UserGetResponse {
            public int total;
            public int count;
            public UserGetResponseData data;
            public String next_openid;
        }

        List<String> openids = new ArrayList<String>();

        int total = 0;

        String next_openid = "";

        do {

            url = url + next_openid;

            String res = httpGet(url);

            UserGetResponse response = JSONObject.parseObject(res, UserGetResponse.class);

            openids.addAll(response.data.openid);

            total = response.total;

            next_openid = response.next_openid;

        } while (openids.size() < total);

        return openids;
    }

    /**
     * 永久素材总数
     */
    static class GetMaterialcountResponse {
        public int voice_count;
        public int video_count;
        public int image_count;
        public int news_count;
    }

    /**
     * 获取素材总数
     *
     * @param access_token
     * @return
     */
    public static GetMaterialcountResponse getMaterialcount(String access_token) {

        String url = "https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token=";

        String res = httpGet(url);

        GetMaterialcountResponse response = JSONObject.parseObject(res, GetMaterialcountResponse.class);

        return response;
    }

    public static class MaterialNewsItem {
        public String title;
        public String thumb_media_id;
        public int show_cover_pic;
        public String author;
        public String digest;
        public String content;
        public String url;
        public String content_source_url;
    }

    public static class MaterialNewsContent {
        public List<MaterialNewsItem> news_item;
    }

    public static class MaterialNews {
        public String media_id;
        public MaterialNewsContent content;
        public Long update_time;
    }

    public static class Material {
        public String media_id;
        public String name;
        public Long update_time;
        public String url;
    }

    /**
     * 批量获取图文素材
     *
     * @param access_token
     * @return
     */
    public static List<MaterialNews> batchgetMaterialNews(String access_token) {

        class Request {
            public String type;
            public int offset;
            public int count;

            public Request(String type, int offset, int count) {
                this.type = type;
                this.offset = offset;
                this.count = count;
            }
        }

        class Response {
            public int total_count;
            public int item_count;
            public List<MaterialNews> item;
        }

        int start = 0;
        int size = 20;
        int total = 0;

        List<MaterialNews> materialNewsList = new ArrayList<MaterialNews>();

        do {

            String url = "https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=" + access_token;

            Request request = new Request("news", start, size);

            String res = httpPost(url, JSONObject.toJSONString(request));

            Response response = JSONObject.parseObject(res, Response.class);

            total = response.total_count;

            materialNewsList.addAll(response.item);

            start = start + size;
        } while (start < total);

        return materialNewsList;
    }

    /**
     * 批量获取其它素材
     *
     * @param access_token
     * @return
     */
    public static List<Material> batchgetMaterial(String access_token, String type) {

        class Request {
            public String type;
            public int offset;
            public int count;

            public Request(String type, int offset, int count) {
                this.type = type;
                this.offset = offset;
                this.count = count;
            }
        }

        class Response {
            public int total_count;
            public int item_count;
            public List<Material> item;
        }

        int start = 0;
        int size = 20;
        int total = 0;

        List<Material> materialList = new ArrayList<Material>();

        do {

            String url = "https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=" + access_token;

            Request request = new Request(type, start, size);

            String res = httpPost(url, JSONObject.toJSONString(request));

            Response response = JSONObject.parseObject(res, Response.class);

            total = response.total_count;

            materialList.addAll(response.item);

            start = start + size;
        } while (start < total);

        return materialList;
    }

    // guava缓存
    static Cache<String, String> guavaCache = CacheBuilder.newBuilder().maximumSize(100)
            .expireAfterWrite(30, TimeUnit.MINUTES).concurrencyLevel(10).recordStats().build();

    /**
     * 获取accessToken
     *
     * @param appid
     * @param appsecret
     * @return
     */
    public static String getAccessToken(String appid, String appsecret) {

        String cacheKey = appid + "_access_token";

        String access_token = guavaCache.getIfPresent(cacheKey);

        if (StringUtils.isEmpty(access_token)) {
            String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid
                    + "&secret=" + appsecret;

            class Response {
                public String access_token;
                public int expires_in;
            }

            String res = httpGet(url);

            Response response = JSONObject.parseObject(res, Response.class);

            access_token = response.access_token;

            guavaCache.put(cacheKey, access_token);
        }

        return access_token;
    }

    /**
     * 获取授权url 如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE
     *
     * @param appid
     * @param redirectUrl
     * @param state
     * @return
     */
    public static String getAuthorize(String appid, String redirectUrl, String state) {
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri="
                + redirectUrl + "&response_type=code&scope=snsapi_userinfo&state=" + state + "#wechat_redirect";

        return url;
    }

    /**
     * 网页授权accesstoken
     */
    static class AuthorizationAccessToken {
        public String access_token;
        public int expires_in;
        public String refresh_token;
        public String openid;
        public String scope;
    }

    /**
     * 通过网页code换取授权accesstoken
     *
     * @param appid
     * @param appsecret
     * @param code
     * @return
     */
    public static AuthorizationAccessToken getAccessTokenByCode(String appid, String appsecret, String code) {

        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appid + "&secret=" + appsecret
                + "&code=" + code + "&grant_type=authorization_code";

        String res = httpGet(url);
        AuthorizationAccessToken response = JSONObject.parseObject(res, AuthorizationAccessToken.class);

        return response;
    }

    /**
     * 网页授权码用户返回信息
     */
    static class AuthorizationUserInfo {
        public String openid;
        public String nickname;
        public String sex;
        public String province;
        public String city;
        public String country;
        public String headimgurl; // 若用户更换头像,原有头像URL将失效
        public List<String> privilege;
        public String unionid; // 绑定到微信开放平台帐号后,才会出现该字段
    }

    /**
     * 通过授权码token获取用户信息
     *
     * @param authorization_access_token
     * @param openid
     * @return
     */
    public static AuthorizationUserInfo getAuthorizationUserInfo(String authorization_access_token, String openid) {

        String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + authorization_access_token + "&openid="
                + openid + "&lang=zh_CN";

        String res = httpGet(url);

        AuthorizationUserInfo response = JSONObject.parseObject(res, AuthorizationUserInfo.class);

        return response;
    }

    public static String httpPost(String url, String jsonBody) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);

        httpPost.addHeader("Content-Type", "application/json");

        StringEntity reqEntity = new StringEntity(jsonBody, "utf-8");

        httpPost.setEntity(reqEntity);

        CloseableHttpResponse response = null;
        String result = null;
        try {

            logger.info("post url :" + url + ", body :" + jsonBody);

            response = httpClient.execute(httpPost);

            logger.info("post response status :" + response.getStatusLine());

            HttpEntity resEntity = response.getEntity();
            
            result = EntityUtils.toString(resEntity, "UTF-8");
            
            logger.info("post response body :" + result);
            
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    public static String httpGet(String url) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);

        CloseableHttpResponse response = null;
        String result = null;
        try {

            logger.info("get url :" + url);

            response = httpClient.execute(httpGet);

            logger.info("get response status :" + response.getStatusLine());

            HttpEntity resEntity = response.getEntity();

            result = EntityUtils.toString(resEntity, "UTF-8");

            logger.info("get response body :" + result);
            
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }
}

WeiXinCallbackController.java

package com.company.javademo;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Node;
import org.springframework.stereotype.Controller;
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.ResponseBody;

@Controller
@RequestMapping("/weixin")
public class WeiXinCallbackController {

    @GetMapping(value = "/callback")
    @ResponseBody
    public String checkSignature(String signature, String timestamp, String nonce, String echostr) {

        String token = "mytoken";

        List<String> list = Arrays.asList(token, timestamp, nonce);
        list.sort(null);

        String tmpStr = DigestUtils.sha1Hex(String.join("", list));

        if (tmpStr.equals(signature)) {

            return echostr;
        }

        return null;
    }

    @PostMapping("/callback")
    @ResponseBody
    public String sendWxMessage(HttpServletRequest request
            , HttpServletResponse response) throws IOException, DocumentException {

        String xml = IOUtils.toString(request.getInputStream());

        // SAXReader saxReader = new SAXReader();
        // Document document = saxReader.read(request.getInputStream());
        Document document = DocumentHelper.parseText(xml);

        Node nodeMsgType = document.selectSingleNode("//MsgType");

        String msgType = nodeMsgType.getText();

        //处理文本消息
        if ("text".equals(msgType)) {

            String fromUser = document.selectSingleNode("//FromUserName").getText();
            String toUser = document.selectSingleNode("//ToUserName").getText();
            String content = document.selectSingleNode("//Content").getText();
            String createTime = document.selectSingleNode("//CreateTime").getText();
            String msgId =   document.selectSingleNode("//MsgId").getText();
            
            String answerMsg="<xml>"+
                    " <ToUserName><![CDATA["+fromUser+"]]></ToUserName>"+
                    " <FromUserName><![CDATA["+toUser+"]]></FromUserName>" + 
                    " <CreateTime>"+createTime+"</CreateTime>" + 
                    " <MsgType><![CDATA["+msgType+"]]></MsgType>" + 
                    " <Content><![CDATA["+content+"]]></Content>" + 
                    " </xml>";
            
            return answerMsg;
        } else {
            
            System.out.println("非文本字段暂时不做处理");
            return "success";
        }
    }
}

App.java

package com.company.javademo;

import java.util.List;

import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.alibaba.fastjson.JSONObject;
import com.company.javademo.WeiXinUtils.Material;
import com.company.javademo.WeiXinUtils.MaterialNews;

/**
 * Hello world!
 *
 */
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(App.class);
        // 关闭banner
        app.setBannerMode(Banner.Mode.OFF);
        app.run(args);

        String appid = "appid";
        String appsecret = "appsecret";


        String access_token = WeiXinUtils.getAccessToken(appid, appsecret);

        List<MaterialNews> materialNewsList = WeiXinUtils.batchgetMaterialNews(access_token);

        System.out.println(JSONObject.toJSONString(materialNewsList));
        
        List<Material> materialList = WeiXinUtils.batchgetMaterial(access_token,"image");
        
        System.out.println(JSONObject.toJSONString(materialList));

    }
}

 

posted @ 2019-12-06 10:43  liuxm-刘小明  阅读(162)  评论(0编辑  收藏  举报