微信公众号群发消息java

news/2024/12/27 17:50:48

首先贴上官方文档:
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432
私以为这份文档写的还是很不错的,在开发的时候没有给我造成多大的困扰,比微信支付的文档好的不要太多。当然也可能是因为我调用的功能太少,没有碰上坑。
接下来进入正题。

这里会分步介绍代码所实现的功能,在文章最后会附上完整的类以及用到的其他类。
1. 获取AccessToken

    access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。

HttpConnection conn = new HttpConnection();
            StringBuilder sb = new StringBuilder("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential");
            sb.append("&appid="+PropertiesUtil.getInstance().getPropMap().get("wx.AppKey"));
            sb.append("&secret="+PropertiesUtil.getInstance().getPropMap().get("wx.AppSecret"));
            String result = conn.get(sb.toString());
            System.out.println(result);
            JSONObject obj = new JSONObject(result);
            String accessToken = obj.getString("access_token");
            Instance.ACCESS_TOKEN = accessToken;
            System.out.println(accessToken);

这里用到了HttpConnection类和PropertiesUtil,在文章最后会贴出该类的完整代码
2. 群发消息

String resp = "";//响应
            String reqUrl = "https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token="+Instance.ACCESS_TOKEN;
            try {
                // 构造httprequest设置
                HttpClient client = new HttpClient();
                PostMethod request = new PostMethod(reqUrl);
                // 添加request headers
                request.addRequestHeader("Content-type", "application/json");
                request.addRequestHeader("Accept", "application/json");

                Map<String, Object> param = new HashMap<String, Object>();
                param.put("touser", openId);
                param.put("msgtype", "text");
                Map<String, Object> content =  new HashMap<String, Object>();
                content.put("content", text);
                param.put("text",content);

                String json = new Gson().toJson(param);
                request.setRequestEntity(new ByteArrayRequestEntity(json.getBytes("UTF-8")));  

                client.executeMethod(request);  
                resp = request.getResponseBodyAsString();  
                System.out.println(resp);
            } catch (Exception e) {
                System.out.println("发送POST请求出现异常!" + e);
                e.printStackTrace();
            }

该方法参数中的openId为用户在微信的唯一标识,text为需要发送的消息内容。
需要注意的两点,
1.群发接口的openId数组必须包含2个及以上,如果只传一个openid会发送失败,这是我所不能理解的。
2.如果返回code为48003,这个返回码在官方文档中没有说明,出现的原因可能是你的微信公众号没有开通群发功能,需要登录微信公众号,在首页点击“新建群发”按钮,同意之后就可以了。

最后贴上完整的代码,记得把package替换掉:

package com.diecolor.wxpay;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.json.JSONObject;

import com.diecolor.util.HttpConnection;
import com.diecolor.util.PropertiesUtil;
import com.google.gson.Gson;

public class MessageUtil {

    /**
     * 内部类
     * 实例化当前对象
     *
     */
    private static class Instance{
        private static final MessageUtil mu = new MessageUtil();
        private static String ACCESS_TOKEN = null;
    }

    /**
     * 暴露在外部的方法
     * @return
     */
    public static MessageUtil getInstance() {
        return Instance.mu;
    }


    /**
     * 获取accessToken
     * @return
     * @throws Exception
     */
    private String getAssessToken() throws Exception {
        if (Instance.ACCESS_TOKEN==null) {
            HttpConnection conn = new HttpConnection();
            StringBuilder sb = new StringBuilder("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential");
            sb.append("&appid="+PropertiesUtil.getInstance().getPropMap().get("wx.AppKey"));
            sb.append("&secret="+PropertiesUtil.getInstance().getPropMap().get("wx.AppSecret"));
            String result = conn.get(sb.toString());
            System.out.println(result);
            JSONObject obj = new JSONObject(result);
            String accessToken = obj.getString("access_token");
            Instance.ACCESS_TOKEN = accessToken;
            System.out.println(accessToken);
        }

        return Instance.ACCESS_TOKEN;
    }

    /**
     * 群发文本消息
     * @param openId
     * @param text
     * @return
     */
    private boolean messTextMessage(String[] openId,String text) {
        try {
            String resp = "";//响应
            String reqUrl = "https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token="+Instance.ACCESS_TOKEN;
            try {
                // 构造httprequest设置
                HttpClient client = new HttpClient();
                PostMethod request = new PostMethod(reqUrl);
                // 添加request headers
                request.addRequestHeader("Content-type", "application/json");
                request.addRequestHeader("Accept", "application/json");

                Map<String, Object> param = new HashMap<String, Object>();
                param.put("touser", openId);
                param.put("msgtype", "text");
                Map<String, Object> content =  new HashMap<String, Object>();
                content.put("content", text);
                param.put("text",content);

                String json = new Gson().toJson(param);
                request.setRequestEntity(new ByteArrayRequestEntity(json.getBytes("UTF-8")));  

                client.executeMethod(request);  
                resp = request.getResponseBodyAsString();  
                System.out.println(resp);
            } catch (Exception e) {
                System.out.println("发送POST请求出现异常!" + e);
                e.printStackTrace();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public static void main(String[] args) throws Exception {
        MessageUtil.getInstance().getAssessToken();
        String[] openId = {"oDyjy0pvqxQMV66D7rPzekfxPOUg","oDyjy0hVQSWUU4Np3isCFPy_zC2U"};//
        MessageUtil.getInstance().messTextMessage(openId, "测试群发消息");
    }

}

 

package com.diecolor.util;

import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;


/**
 * 单例模式读取配置文件
 * @author 武佳伟丶
 *
 */
public class PropertiesUtil {

    private static Map<String, String> proMap = new HashMap<String,String>();//Maps.newHashMap();//并不知道是干什么用的

    private static class PropertiesInstance {
        private static final PropertiesUtil props = new PropertiesUtil();
    }

    public static PropertiesUtil getInstance(){
        return PropertiesInstance.props;
    }

    public Map<String,String> getPropMap() {
        return proMap;
    }

    /*
     * 构造函数
     */
    private PropertiesUtil(){
        proMap = readProperties();
    }

    @SuppressWarnings("rawtypes")
    private static Map<String, String> readProperties() {
        Properties props = new Properties();
        InputStream in = null;
        try {
            in = PropertiesUtil.class.getClassLoader().getResourceAsStream("upush.properties");
            props.load(in);
            Enumeration en = props.propertyNames();
            while (en.hasMoreElements()) {
                String key = (String) en.nextElement();
                String value = props.getProperty(key);
                proMap.put(key, value);

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return proMap;
    }
}

 

package com.diecolor.util;


import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;
import java.util.Map;

import javax.activation.MimetypesFileTypeMap;

import org.springframework.stereotype.Component;


/**
 * HTTP通信类
 *
 */
@Component
public class HttpConnection {
    /**
     * 向指定URL发送GET方法的请求
     * @param url 发送请求的URL
     * @param param 请求参数,请求参数应该是name1=value1&name2=value2的形式。
     * @return URL所代表远程资源的响应
     */
    public  String get(String url, String param) throws Exception {  
        String urlName = url + "?" + param;  
        return get(urlName);
    }  

    /**
     * 向指定URL发送GET方法的请求
     *
     * @param url
     *            发送请求的URL
     * @return URL所代表远程资源的响应
     */
    public  String get(String url) throws Exception {
        String result = "";
        BufferedReader in = null;
        URL realUrl = new URL(url);
        URLConnection conn = realUrl.openConnection();
        conn.setRequestProperty("accept", "*/*");
        conn.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.8");
        conn.setRequestProperty("Content-Type", "text/xml;charset=utf-8");
        conn.setRequestProperty("connection", "keep-alive");
        conn.setRequestProperty("user-agent",
                "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
        // 建立实际的连接
        conn.connect();

        // 定义BufferedReader输入流来读取URL的响应
        in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
        String line;
        while ((line = in.readLine()) != null) {
            result += line;
        }

        in.close();
        return result;
    }

    /**  
     * 向指定URL发送POST方法的请求  
     * @param url 发送请求的URL  
     * @param content 内容
     * @return URL所代表远程资源的响应  
     * @throws Exception
     */  
    public String post(String url,String content) throws Exception{
        String result = "";
        URL postUrl = new URL(url);
        HttpURLConnection connection = (HttpURLConnection) postUrl
                .openConnection();
        connection.setDoOutput(true);
        connection.setDoInput(true);
        connection.setRequestMethod("POST");
        connection.setUseCaches(false);
        connection.setInstanceFollowRedirects(true);
        connection.setRequestProperty("Content-Type",
                "application/x-www-form-urlencoded");
        connection.connect();
        DataOutputStream out = new DataOutputStream(connection
                .getOutputStream());
//        out.writeBytes(content);
        out.write(content.getBytes("UTF-8"));
        out.flush();
        out.close(); // flush and close
        BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),"utf-8"));//设置编码,否则中文乱码
        String line="";
        while ((line = reader.readLine()) != null){
            result += line;
        }
        reader.close();
        connection.disconnect();
        return result;
    }
    /**
     * 向指定URL发送POST方法的请求
     * @Title: post
     * @Description: TODO
     * @param @param url
     * @param @param textMap
     * @param @return    
     * @return String    
     * @throws
     */
    public String post(String url, Map<String, Object> textMap){
        String res = "";
        HttpURLConnection conn = null;
        String BOUNDARY = "---------------------------123821742118716"; //boundary就是request头和上传文件内容的分隔符
        try {
            URL postUrl = new URL(url);
            conn = (HttpURLConnection) postUrl.openConnection();
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(30000);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("User-Agent",
                            "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
            conn.setRequestProperty("Content-Type",
                    "multipart/form-data; boundary=" + BOUNDARY);

            OutputStream out = new DataOutputStream(conn.getOutputStream());
            // text
            if (textMap != null) {
                StringBuffer strBuf = new StringBuffer();
                Iterator iter = textMap.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry entry = (Map.Entry) iter.next();
                    String inputName = (String) entry.getKey();
                    String inputValue = (String) entry.getValue();
                    if (inputValue == null) {
                        continue;
                    }
                    strBuf.append("\r\n").append("--").append(BOUNDARY).append(
                            "\r\n");
                    strBuf.append("Content-Disposition: form-data; name=\""
                            + inputName + "\"\r\n\r\n");
                    strBuf.append(inputValue);
                }
                out.write(strBuf.toString().getBytes());
            }

            byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
            out.write(endData);
            out.flush();
            out.close();

            // 读取返回数据
            StringBuffer strBuf = new StringBuffer();
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    conn.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                strBuf.append(line).append("\n");
            }
            res = strBuf.toString();
            reader.close();
            reader = null;
        } catch (Exception e) {
            System.out.println("发送POST请求出错。" + url);
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.disconnect();
                conn = null;
            }
        }
        return res;
    }

    /**  
     * 向指定URL发送POST方法的请求 (带文件)
     * @param url 发送请求的URL  
     * @param textMap 文本参数键值
     * @param fileMap 文件键值
     * @return URL所代表远程资源的响应  
     * @throws Exception
     */  
    public String filePost(String url, Map<String, String> textMap,
            Map<String, String> fileMap) {
        String res = "";
        HttpURLConnection conn = null;
        String BOUNDARY = "---------------------------123821742118716"; //boundary就是request头和上传文件内容的分隔符
        try {
            URL postUrl = new URL(url);
            conn = (HttpURLConnection) postUrl.openConnection();
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(30000);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("User-Agent",
                            "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
            conn.setRequestProperty("Content-Type",
                    "multipart/form-data; boundary=" + BOUNDARY);

            OutputStream out = new DataOutputStream(conn.getOutputStream());
            // text
            if (textMap != null) {
                StringBuffer strBuf = new StringBuffer();
                Iterator iter = textMap.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry entry = (Map.Entry) iter.next();
                    String inputName = (String) entry.getKey();
                    String inputValue = (String) entry.getValue();
                    if (inputValue == null) {
                        continue;
                    }
                    strBuf.append("\r\n").append("--").append(BOUNDARY).append(
                            "\r\n");
                    strBuf.append("Content-Disposition: form-data; name=\""
                            + inputName + "\"\r\n\r\n");
                    strBuf.append(inputValue);
                }
                out.write(strBuf.toString().getBytes());
            }

            // file
            if (fileMap != null) {
                Iterator iter = fileMap.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry entry = (Map.Entry) iter.next();
                    String inputName = (String) entry.getKey();
                    String inputValue = (String) entry.getValue();
                    if (inputValue == null) {
                        continue;
                    }
                    File file = new File(inputValue);
                    String filename = file.getName();
                    String contentType = new MimetypesFileTypeMap()
                            .getContentType(file);
                    if (filename.endsWith(".png")) {
                        contentType = "image/png";
                    }
                    if (contentType == null || contentType.equals("")) {
                        contentType = "application/octet-stream";
                    }

                    StringBuffer strBuf = new StringBuffer();
                    strBuf.append("\r\n").append("--").append(BOUNDARY).append(
                            "\r\n");
                    strBuf.append("Content-Disposition: form-data; name=\""
                            + inputName + "\"; filename=\"" + filename
                            + "\"\r\n");
                    strBuf.append("Content-Type:" + contentType + "\r\n\r\n");

                    out.write(strBuf.toString().getBytes());

                    DataInputStream in = new DataInputStream(
                            new FileInputStream(file));
                    int bytes = 0;
                    byte[] bufferOut = new byte[1024];
                    while ((bytes = in.read(bufferOut)) != -1) {
                        out.write(bufferOut, 0, bytes);
                    }
                    in.close();
                }
            }

            byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
            out.write(endData);
            out.flush();
            out.close();

            // 读取返回数据
            StringBuffer strBuf = new StringBuffer();
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    conn.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                strBuf.append(line).append("\n");
            }
            res = strBuf.toString();
            reader.close();
            reader = null;
        } catch (Exception e) {
            System.out.println("发送POST请求出错。" + url);
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.disconnect();
                conn = null;
            }
        }
        return res;
    }
}
————————————————
版权声明:本文为CSDN博主「纸上得来终觉浅丶」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_28550739/article/details/78012669


http://www.niftyadmin.cn/n/3268083.html

相关文章

TensorFlow --- 01初识

由于博客园对Markdown支持不够友好&#xff0c;阅读此文请前往云栖社区&#xff1a;TensorFlow --- 01初识转载于:https://www.cnblogs.com/God-Li/p/9467957.html

公众号群发消息

权限 只有认证的的订阅号 和 服务号&#xff0c;可以群发消息。自己申请的测试号&#xff0c;或者没认证的订阅号、服务号&#xff0c;没有权限。 在这里插入图片描述 样子 发出去的文字消息、图片消息等于普通消息无差&#xff0c;我就不多说了。发送出去的图文消息是这样子…

公众号开发文章

微信公众号(一)获取access_token这里是引用 https://blog.csdn.net/FORLOVEHUAN/article/details/81512556 微信公众号(二)获取用户列表https://blog.csdn.net/FORLOVEHUAN/article/details/82760618 微信公众号群发&#xff08;三&#xff09;群发消息 https://blog.csdn.…

WPF不明内存泄露已解决,白头发也没了

原文:WPF不明内存泄露已解决&#xff0c;白头发也没了在使用OpenExpressApp进行WPF应用开发过程中遇到多个内存泄漏的地方&#xff0c;在上一篇中求助了一个内存泄露问题【WPF不明内存泄露原因&#xff0c;头发都白了几根】&#xff0c;本篇与大家分享一下如何解决此问题的过程…

Jenkins与Docker的自动化CI/CD实战

在互联网时代&#xff0c;对于每一家公司&#xff0c;软件开发和发布的重要性不言而喻&#xff0c;目前已经形成一套标准的流程&#xff0c;最重要的组成部分就是持续集成&#xff08;CI&#xff09;及持续部署、交付&#xff08;CD&#xff09;。本文基于JenkinsDockerGit实现…

idea 新建web项目以及404分析

大家可能以前用的不是idea编程软件&#xff0c;一下子使用idea可能会出现很多启动不了或者启动成功404的情况&#xff0c;一般来说这机会都是因为新建项目的时候没有配置好&#xff0c;打war包的时候配置有一定的问题导致的。 废话不多说首先如何创建一个web项目 首先到左上…

iperf测试网卡性能

1&#xff0c;iperf是一个网络性能测试工具。可以测试TCP和UDP带宽质量&#xff0c;可以测量最大TCP带宽&#xff0c;具有多种参数和UDP特性&#xff0c;可以报告带宽&#xff0c;延迟抖动和数据包丢失 2&#xff0c;安装epel源wget -O /etc/yum.repos.d/epel.repo http://mirr…

intellij idea创建第一个动态web项目的步骤方法

一.创建JavaWeb 1.第一步 点击左上角的File-->New-->Project 2.第二步 1.找到Java Enterprise之后&#xff0c;在Application Sever中找到自己的Tomcat&#xff0c;同时勾选中Web Application 2.第一项是你的工程名字&#xff0c;随便取啦&#xff0c;第二个是你的工程…