java实现微信公众号图文、视频一键发布

这篇具有很好参考价值的文章主要介绍了java实现微信公众号图文、视频一键发布。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

微信公众号开发

一、准备工作

在微信开发平台申请一个测试账号(优先选择这个),如果可以使用认证过的订阅号最好,不过我们在开发阶段很多功能都是测试用的,申请一个测试账号完全够用
个人的订阅号是不可以申请认证的,所以很多微信API不可以用

二、开始开发

写在前面

项目所需依赖

  <!-- SpringBoot Web容器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--httpclient工具类https://github.com/Arronlong/httpclientutil-->
        <dependency>
            <groupId>com.arronlong</groupId>
            <artifactId>httpclientutil</artifactId>
            <version>1.0.4</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.72</version>
        </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>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.0</version>
        </dependency>
        <dependency>
            <groupId>com.hankcs</groupId>
            <artifactId>hanlp</artifactId>
            <version>portable-1.2.8</version>
        </dependency>
所有涉及到的微信api接口地址
    private static ObjectMapper objectMapper = new ObjectMapper();
    private static final String DRAFTADD = "https://api.weixin.qq.com/cgi-bin/draft/add?access_token=";//新建草稿文章
    private static final String PUBLISH = "https://api.weixin.qq.com/cgi-bin/freepublish/submit?access_token="; //正式发布文章
    private static final String PUBLISHRESULT = "https://api.weixin.qq.com/cgi-bin/freepublish/get?access_token=";//获取发布文章结果
    private static final String GETMATERIAL = "https://api.weixin.qq.com/cgi-bin/material/get_material?access_token="; //获取上传素材信息
    private static final String ARTICLEDELETE = "https://api.weixin.qq.com/cgi-bin/freepublish/delete?access_token=";//删除已发布文章
    private static final String UPLOADVIDEO = "https://api.weixin.qq.com/cgi-bin/media/uploadvideo?access_token=";//发送预览视频(视频群发)时的上传视频素材
    private static final String PREVIEW = "https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token=";//视频预览
    private static final String SENDALL = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token=";//视频、图文群发
    private static final String SENDALLDELETE = "https://api.weixin.qq.com/cgi-bin/message/mass/delete?access_token=";//群发视频删除
1:开发准备工作
(1):由于我调用微信API是通过http请求来的,所以需要一个HTTP请求工具类

​ 具体代码如下:

参数说明:json,传的参数

​ url:请求api地址

@Slf4j
public class HttpUtil {

 
    /**
     * 发送post请求
     * @param json 参数体
     * @param URL 请求地址
     * @return 返回结果
     */
    public static String sendPost(JSONObject json, String URL) {
        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost post = new HttpPost(URL);
        post.setHeader("Content-Type", "application/json");
        post.setHeader("User-Agent", "Apipost client Runtime/+https://www.apipost.cn/");
        // post.addHeader("Authorization", "Basic YWRtaW46");
        String result;
        try {
            StringEntity s = new StringEntity(json.toString(), "utf-8");
            s.setContentType(new BasicHeader(HTTP.CONTENT_TYPE,
                    "application/json"));
            post.setEntity(s);
            // 发送请求
            HttpResponse httpResponse = client.execute(post);
            // 获取响应输入流
            InputStream inStream = httpResponse.getEntity().getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader( inStream, "utf-8"));
            StringBuilder strBuilder = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null)
                strBuilder.append(line + "\n");
            inStream.close();
            result = strBuilder.toString();
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                log.info("请求服务器SUCCESS");
                // System.out.println("请求服务器成功,做相应处理");
            } else {
                log.info("请求服务端FALSE");
                // System.out.println("请求服务端失败");
            }
        } catch (Exception e) {
            log.error("请求异常EXCEPTION:"+e.getMessage());
            throw new RuntimeException(e);
        }
        return result;
    }
 
    /**
     * 发送get请求
     * @param url 请求URL
     * @param param 请求参数 key:value url携带参数 或者无参可不填
     * @return
     */
    public static String sendGet(String url, Map<String, String> param) {
 
        // 创建Httpclient对象
        CloseableHttpClient httpclient = HttpClients.createDefault();
 
        String resultString = "";
        CloseableHttpResponse response = null;
        try {
            // 创建uri
            URIBuilder builder = new URIBuilder(url);
            if (param != null) {
                for (String key : param.keySet()) {
                    builder.addParameter(key, param.get(key));
                }
            }
            URI uri = builder.build();
 
            // 创建http GET请求
            HttpGet httpGet = new HttpGet(uri);
 
            // 执行请求
            response = httpclient.execute(httpGet);
            // 判断返回状态是否为200
            if (response.getStatusLine().getStatusCode() == 200) {
                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }

 
}
(2)每个需要请求的接口都会用到token,所以我们需要一个获取token的公用方法,

获取token 所需要数据:APPID,SECRET(这两个参数会在申请过测试账号后得到)

获取token方法如下

  private static final String APPID = "wx0d1f0bdf5254710b";

    private static final String SECRET = "8af23658e88c12a087d27a531a9a86a9";

    private static final String TOKENURL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";

/**
     * 获取token
     */
    public static String getAccessToken() throws HttpProcessException {
        String url=TOKENURL+"&appid="+APPID+"&secret="+SECRET;
        System.out.println(url);
        String result = HttpClientUtil.get(HttpConfig.custom().url(url));
        JSONObject resultObj = JSON.parseObject(result);
        if (!resultObj.containsKey("access_token")) {
            throw new RuntimeException(result);
        }
        String token = resultObj.getString("access_token");
        return token;
    }
2:开始开发

所涉及请求的api以及需要传的参数可以根据微信公众号开发文档进行借鉴,

参考地址:链接地址

特别说明:

微信公众号所涉及的图文群发,新闻等里面所引用的图片地址必须是微信服务器下的才能识别到,如果图片或则视频存在其他服务器上是访问不到的,需要把这些素材上传到微信公众号素材里面,然后根据这些返回的mediaid,链接地址在内容里面进行替换

(1):上传素材(分为临时素材和永久素材,由于临时素材上传后在内容里面也无法引用,所以只展示上传永久素材的方法)
  /**
     * 上传永久素材
     * @param	file
     * @param	type
     * @param	title type为video时需要,其他类型设null
     * @param	introduction type为video时需要,其他类型设null
     * @return	{"media_id":MEDIA_ID,"url":URL}
     */
    public static String uploadPermanentMaterial(File file, String type, String title, String introduction) throws HttpProcessException {

        String access_token = getAccessToken();
        String url = ADDMATERIAL + access_token + "&type=" + type;
        String result = null;
        try {
            URL uploadURL = new URL(url);

            HttpURLConnection conn = (HttpURLConnection) uploadURL.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("Cache-Control", "no-cache");
            String boundary = "-----------------------------" + System.currentTimeMillis();
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);

            OutputStream output = conn.getOutputStream();
            output.write(("--" + boundary + "\r\n").getBytes());
            output.write(String.format("Content-Disposition: form-data; name=\"media\"; filename=\"%s\"\r\n", file.getName()).getBytes());
            output.write("Content-Type: video/mp4 \r\n\r\n".getBytes());

            byte[] data = new byte[1024];
            int len = 0;
            FileInputStream input = new FileInputStream(file);
            while ((len = input.read(data)) > -1) {
                output.write(data, 0, len);
            }

            /*对类型为video的素材进行特殊处理*/
            if ("video".equals(type)) {
                output.write(("--" + boundary + "\r\n").getBytes());
                output.write("Content-Disposition: form-data; name=\"description\";\r\n\r\n".getBytes());
                output.write(String.format("{\"title\":\"%s\", \"introduction\":\"%s\"}", title, introduction).getBytes());
            }

            output.write(("\r\n--" + boundary + "--\r\n\r\n").getBytes());
            output.flush();
            output.close();
            input.close();

            InputStream resp = conn.getInputStream();

            StringBuffer sb = new StringBuffer();

            while ((len = resp.read(data)) > -1)
                sb.append(new String(data, 0, len, "utf-8"));
            resp.close();
            result = sb.toString();
        } catch (IOException e) {
            //....
        }

        return result;
    }

2:新闻、图文具体发布过程

1:需要借用新建草稿api将内容给创建到草稿箱里(在这个过程中,如果文章包含图片,需要把图片路径通过正则表达式给匹配出来,根据这些图片的地址将图片从公司服务器上传到微信服务器,得到一个图片地址,然后替换新闻内容,将图片引用到微信服务器的地址),然后通过草稿箱id进行发布、群发,这样我们才能看到

一键发布传参实体类

/**
 * TODO 类描述
 *
 * @author zhaoqilong
 * @version 1.0
 * @date 2022/10/26 16:05
 */
@Data
public class ContentEntity {

    /***
     * 标题
     */
    private String title;

    /***
     *  作者
     */
    private String author;

    /***
     * 图文消息的摘要,仅有单图文消息才有摘要,多图文此处为空。如果本字段为没有填写,则默认抓取正文前54个字。
     */
    private String digest;

    /***
     * 图文消息的具体内容,支持 HTML 标签,必须少于2万字符,小于1M,且此处会去除 JS ,涉及图片 url
     *  必须来源 "上传图文消息内的图片获取URL"接口获取。外部图片 url 将被过滤
     */
    private String content;

    /***
     * *图文消息的原文地址,即点击“阅读原文”后的URL
     */
    private String contentSourceUrl;

    /***
     * 封面图片服务器地址
     */
    private String thumbPath;

    /***
     *  图文消息的封面图片素材id(必须是永久MediaID)
     */
    private String thumbMediaId;

    /***
     * *Uint32 是否打开评论,0不打开(默认),1打开
     */
    private String needOpenComment;

    /***
     * *Uint32 是否粉丝才可评论,0所有人可评论(默认),1粉丝才可评论
     */
    private String onlyFansCanComment;


}

一键发布:

private static ObjectMapper objectMapper = new ObjectMapper();
    private static final String DRAFTADD = "https://api.weixin.qq.com/cgi-bin/draft/add?access_token=";//新建草稿文章
    private static final String PUBLISH = "https://api.weixin.qq.com/cgi-bin/freepublish/submit?access_token="; //正式发布文章
    private static final String PUBLISHRESULT = "https://api.weixin.qq.com/cgi-bin/freepublish/get?access_token=";//获取发布文章结果
    private static final String GETMATERIAL = "https://api.weixin.qq.com/cgi-bin/material/get_material?access_token="; //获取上传素材信息
    private static final String ARTICLEDELETE = "https://api.weixin.qq.com/cgi-bin/freepublish/delete?access_token=";//删除已发布文章
    private static final String UPLOADVIDEO = "https://api.weixin.qq.com/cgi-bin/media/uploadvideo?access_token=";//发送预览视频(视频群发)时的上传视频素材
    private static final String PREVIEW = "https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token=";//视频预览
    private static final String SENDALL = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token=";//视频群发
    private static final String SENDALLDELETE = "https://api.weixin.qq.com/cgi-bin/message/mass/delete?access_token=";//群发视频删除

    /***
     * 一键新闻发布
     * 具体分为以下几个步骤
     * 1:先获取到新闻的图片地址
     * 2:通过图片地址将图片下载下来,然后上传到微信服务器
     * 3:将上传后返回的图文地址在新闻内容中进行替换
     * 4:替换后发布到草稿箱,获取到一个meia_id
     * 5:最后通过这个草稿id(media_id) 进行新闻发布
     * @param contentEntity
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/one-click-release", method = RequestMethod.POST)
    public String oneClickRelease(ContentEntity contentEntity) throws Exception {
        JSONArray eventArray = new JSONArray();
        JSONObject eventTraceInput = new JSONObject();
        String accessToken = WeiXinUtil.getAccessToken();
        String url = DRAFTADD + accessToken;
        String thumbPath = "";
        if (StringUtils.isNotBlank(contentEntity.getThumbPath())) {
            thumbPath = contentEntity.getThumbPath();
            Map<String, String> map = uploadImageLast(thumbPath);
            contentEntity.setThumbMediaId(map.get("media_id"));
            log.info("***************" + map.get("media_id"));
        } else {
            String content = contentEntity.getContent();
            if (StringUtils.isNotBlank(content)) {
                List<String> imgUrlList = ImageToolsUtil.listContentImgUrl(content);
                if (imgUrlList.size() > 0) {
                    for (String s : imgUrlList) {
                        Map<String, String> map = uploadImageLast(s);
                        contentEntity.setThumbMediaId(map.get("media_id"));
                        log.info("***************没有首页图" + map.get("media_id"));
                        break;
                    }
                }
            }
        }
        String content = contentEntity.getContent();
        if (StringUtils.isNotBlank(content)) {
            List<String> imgUrlList = ImageToolsUtil.listContentImgUrl(content);
            for (String s : imgUrlList) {
                log.info("*****************" + s);
                String s1 = s.replace(">", "");
                Map<String, String> map = uploadImageLast(s1);
                if (StringUtils.isNotBlank(map.get("url"))) {
                    content = content.replace(s, map.get("url"));
                }
            }
            contentEntity.setContent(content);
            log.info("替换内容后为" + content);
        }
        JSONObject jsonArray = new JSONObject();
        jsonArray.put("title", contentEntity.getTitle());//新闻标题
        jsonArray.put("author", contentEntity.getAuthor());//作者
        if(StringUtils.isBlank(contentEntity.getDigest())){
            contentEntity.setDigest(ContentUtil.summary(contentEntity.getContent()));
        }
        jsonArray.put("digest", contentEntity.getDigest());//摘要
        jsonArray.put("content", contentEntity.getContent());//内容
        jsonArray.put("content_source_url", contentEntity.getContentSourceUrl());//内容链接
        if (StringUtils.isNotBlank(contentEntity.getThumbMediaId())) {
            jsonArray.put("thumb_media_id", contentEntity.getThumbMediaId());//封面图片素材id
        }
        jsonArray.put("need_open_comment", contentEntity.getNeedOpenComment());//Uint32 是否打开评论,0不打开(默认),1打开
        jsonArray.put("only_fans_can_comment", contentEntity.getOnlyFansCanComment());//Uint32 是否粉丝才可评论,0所有人可评论(默认),1粉丝才可评论

        eventArray.add(jsonArray);
        eventTraceInput.put("articles", eventArray);
        // 发送请求
        String s1 = HttpUtil.sendPost(eventTraceInput, url);
        log.info("strResult:{}", s1);
        Gson gson1 = new Gson();
        Map<String, String> map1 = new HashMap<>();
        JSONObject strJson1 = JSONObject.parseObject(s1);
        map1 = gson1.fromJson(strJson1.toString(), map1.getClass());
//        String reslutCode = rePublish(map1.get("media_id"));//正式发布方法
        String result = sendNewsAll(map1.get("media_id"));//图文群发方法,参数是草稿id
        return result;
    }

    /***
     * * 群发图文
     * @param mediaId  草稿箱id
     * @return
     * @throws Exception
     */
    private String sendNewsAll(String mediaId) throws Exception {
        //获取access_token
        String accessToken = WeiXinUtil.getAccessToken();
        //根据media_id进行发送
        String url = SENDALL + accessToken;
        JSONObject eventTraceInput = new JSONObject();
        JSONObject eventTraceInput2 = new JSONObject();
        eventTraceInput2.put("is_to_all", true);
//        eventTraceInput2.put("tag_id","");//如果是全部群发,则这个群发标签不需要设置
        eventTraceInput.put("filter", eventTraceInput2);
        JSONObject eventTraceInput3 = new JSONObject();
        eventTraceInput3.put("media_id", mediaId);
        eventTraceInput.put("mpnews", eventTraceInput3);
        eventTraceInput.put("msgtype", "mpnews");
        eventTraceInput.put("send_ignore_reprint", "0");
        String result = HttpUtil.sendPost(eventTraceInput, url);
        return result;
    }

    /***
     * *正式发布新闻
     * @param mediaId 草稿箱文章id
     * @return
     * @throws HttpProcessException
     */
    private String rePublish(String mediaId) throws HttpProcessException {
        String accessToken = WeiXinUtil.getAccessToken();
        // 构造参数消息体
        JSONObject eventTraceInput = new JSONObject();
        String url = PUBLISH + accessToken;
        eventTraceInput.put("media_id", mediaId);
        // 发送请求
        String strResult = HttpUtil.sendPost(eventTraceInput, url);
        System.out.println(strResult);
        try {
            Map mapResult = objectMapper.readValue(strResult, Map.class);
            System.out.println(mapResult);

            if (null != mapResult && StringUtils.isNotBlank(mapResult.get("errcode").toString())) {
                if ("0".equals(mapResult.get("errcode").toString())) {
                    log.info("发布文章(草稿)SUCCESS,ERRCODE状态码:{}", 0);
                    return "发布成功";
                }
                if ("40001".equals(mapResult.get("errcode").toString())) {
                    return mapResult.get("errmsg").toString();
                } else {
                    return mapResult.get("errcode").toString() + ",错误信息:" + mapResult.get("errmsg").toString();
                }
            }
        } catch (IOException e) {
            log.error("解析失败...");
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "发布失败";
    }

    /***
     * 将文章内容中的图片上传到微信服务器
     * @param path 图片网络地址
     * @return
     * @throws Exception
     */
    private Map<String, String> uploadImageLast(String path) throws Exception {
        //上传素材
        //上传素材
        String pathLast = path;
        if (!path.endsWith(".jpg") && !path.endsWith(".png")) {
            pathLast = path.substring(0, path.lastIndexOf(".") + 4);
        }
        String suffix = pathLast.substring(pathLast.lastIndexOf(".") + 1, pathLast.length());
        File fileByUrl = WeiXinUtil.getFileByUrl(pathLast, suffix);
        String result = WeiXinUtil.uploadPermanentMaterial(fileByUrl, "image", null, null);
        Gson gson = new Gson();
        Map<String, String> map = new HashMap<>();
        JSONObject strJson = JSONObject.parseObject(result);
        System.out.println(result);
        map = gson.fromJson(strJson.toString(), map.getClass());
        return map;
    }

3: 群发视频(这个有个比较特殊的点就是,群发视频时上传视频的api地址并不是单单上传永久视频素材的那个api,在上传永久视频素材后会返回一个mediaId,然后根据这个mediaId再进行一次操作,在这个完成后会再得到一个meidaid,这个mediaid才是可以用来群发视频的有效mediaid)

具体可参考:

 /***
     * * 群发视频
     * @param videoPath  视频网络地址
     * @param title 视频标题
     * @param introduction 视频简介
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/sendall", method = RequestMethod.POST)
    public String sendvideoAll(@RequestParam String videoPath,
                               @RequestParam String title,
                               @RequestParam String introduction) throws Exception {
        //获取access_token
        String accessToken = WeiXinUtil.getAccessToken();
        String suffix = videoPath.substring(videoPath.lastIndexOf(".") + 1, videoPath.length());
        File fileByUrl = WeiXinUtil.getFileByUrl(videoPath, suffix);
        String postresult = WeiXinUtil.uploadVideo(fileByUrl, "video", title, introduction);
        Map maps = (Map) JSON.parse(postresult);
        String media1 = maps.get("media_id").toString();
        //通过media_id获取发送media_id
        String url = UPLOADVIDEO + accessToken;
        JSONObject eventTraceInput = new JSONObject();
        eventTraceInput.put("media_id", media1);
        eventTraceInput.put("title", title);
        eventTraceInput.put("description", introduction);
        String result = HttpUtil.sendPost(eventTraceInput, url);
        Map maps2 = (Map) JSON.parse(result);
        String media2 = maps2.get("media_id").toString();
        //根据media_id进行发送
        String url2 = SENDALL + accessToken;
        JSONObject eventTraceInput1 = new JSONObject();
        JSONObject eventTraceInput2 = new JSONObject();
        eventTraceInput2.put("is_to_all", true);
//        eventTraceInput2.put("tag_id","");//如果是全部群发,则这个群发标签不需要设置
        eventTraceInput1.put("filter", eventTraceInput2);
        JSONObject eventTraceInput3 = new JSONObject();
        eventTraceInput3.put("media_id", media2);
        eventTraceInput1.put("mpvideo", eventTraceInput3);
        eventTraceInput1.put("msgtype", "mpvideo");
        String result2 = HttpUtil.sendPost(eventTraceInput1, url2);
        return result2;
    }

4:群发视频、文章删除文章来源地址https://www.toymoban.com/news/detail-612832.html

 /***
     * 删除群发消息
     * @param msgId 消息id  当和文章地址连用时,以消息id为准
     * @param videoUrl 文章地址
     * @return
     * @throws HttpProcessException
     */
    @RequestMapping(value = "/sendall-delete", method = RequestMethod.POST)
    public String sendAllDelete(@RequestParam String msgId, @RequestParam(required = false, defaultValue = "") String videoUrl) throws HttpProcessException {
        //获取access_token
        String accessToken = WeiXinUtil.getAccessToken();
        String url = SENDALLDELETE + accessToken;
        JSONObject eventTraceInput = new JSONObject();
        eventTraceInput.put("msg_id", msgId);
//        eventTraceInput.put("article_idx",1); //要删除的文章在图文消息中的位置
        eventTraceInput.put("url", videoUrl);
        String result = HttpUtil.sendPost(eventTraceInput, url);
        return result;
    }

附WeiXinUtil内容

package com.dahe.wang.medianews.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.arronlong.httpclientutil.HttpClientUtil;
import com.arronlong.httpclientutil.common.HttpConfig;
import com.arronlong.httpclientutil.exception.HttpProcessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

/***
 * * 封装统一的GET/POST请求接口
 */
public class WeiXinUtil {
    private final static Logger logger= LoggerFactory.getLogger(WeiXinUtil.class);

    private static final String APPID = "wx0d1f0bdf5254710b";

    private static final String SECRET = "8af23658e88c12a087d27a531a9a86a9";

   /* private static final String APPID = "wx4d99bf985e140978";

    private static final String SECRET = "8aae44ef46232377f20afc92b4992477";*/

    private static final String TOKENURL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";

    private static final String ADDMATERIAL ="https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=";

    private static final String MEDIAUPLOAD ="https://api.weixin.qq.com/cgi-bin/media/upload?access_token=";

    /**
     * 上传永久素材
     * @param	file
     * @param	type
     * @param	title type为video时需要,其他类型设null
     * @param	introduction type为video时需要,其他类型设null
     * @return	{"media_id":MEDIA_ID,"url":URL}
     */
    public static String uploadPermanentMaterial(File file, String type, String title, String introduction) throws HttpProcessException {

        String access_token = getAccessToken();
        String url = ADDMATERIAL + access_token + "&type=" + type;
        String result = null;
        try {
            URL uploadURL = new URL(url);

            HttpURLConnection conn = (HttpURLConnection) uploadURL.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("Cache-Control", "no-cache");
            String boundary = "-----------------------------" + System.currentTimeMillis();
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);

            OutputStream output = conn.getOutputStream();
            output.write(("--" + boundary + "\r\n").getBytes());
            output.write(String.format("Content-Disposition: form-data; name=\"media\"; filename=\"%s\"\r\n", file.getName()).getBytes());
            output.write("Content-Type: video/mp4 \r\n\r\n".getBytes());

            byte[] data = new byte[1024];
            int len = 0;
            FileInputStream input = new FileInputStream(file);
            while ((len = input.read(data)) > -1) {
                output.write(data, 0, len);
            }

            /*对类型为video的素材进行特殊处理*/
            if ("video".equals(type)) {
                output.write(("--" + boundary + "\r\n").getBytes());
                output.write("Content-Disposition: form-data; name=\"description\";\r\n\r\n".getBytes());
                output.write(String.format("{\"title\":\"%s\", \"introduction\":\"%s\"}", title, introduction).getBytes());
            }

            output.write(("\r\n--" + boundary + "--\r\n\r\n").getBytes());
            output.flush();
            output.close();
            input.close();

            InputStream resp = conn.getInputStream();

            StringBuffer sb = new StringBuffer();

            while ((len = resp.read(data)) > -1)
                sb.append(new String(data, 0, len, "utf-8"));
            resp.close();
            result = sb.toString();
        } catch (IOException e) {
            //....
        }

        return result;
    }

    /**
     * 获取token
     */
    public static String getAccessToken() throws HttpProcessException {
        String url=TOKENURL+"&appid="+APPID+"&secret="+SECRET;
        System.out.println(url);
        String result = HttpClientUtil.get(HttpConfig.custom().url(url));
        JSONObject resultObj = JSON.parseObject(result);
        if (!resultObj.containsKey("access_token")) {
            throw new RuntimeException(result);
        }
        String token = resultObj.getString("access_token");
        return token;
    }

    /***
     * * 根据图片在服务器的地址将图片、视频转成file
     * @param picUrl 图片服务器地址
     * @param suffix 后缀
     * @return
     * @throws Exception
     */
    public static File getFileByUrl(String picUrl, String suffix) throws Exception {
        URL imageUrl = new URL(picUrl);
        HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();
        InputStream inputStream = conn.getInputStream();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, len);
        }
        File file = File.createTempFile("pattern", "." + suffix);
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        fileOutputStream.write(outputStream.toByteArray());

        inputStream.close();
        outputStream.close();
        fileOutputStream.close();
        return file;
    }

    /**
     * 视频预览专用-上传永久视频素材
     * @param	file
     * @param	type
     * @param	title type为video时需要,其他类型设null
     * @param	introduction type为video时需要,其他类型设null
     * @return	{"media_id":MEDIA_ID,"url":URL}
     */
    public static String uploadVideo(File file, String type, String title, String introduction) throws HttpProcessException {

        String access_token = getAccessToken();
        String url = MEDIAUPLOAD + access_token + "&type=" + type;
        String result = null;
        try {
            URL uploadURL = new URL(url);

            HttpURLConnection conn = (HttpURLConnection) uploadURL.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("Cache-Control", "no-cache");
            String boundary = "-----------------------------" + System.currentTimeMillis();
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);

            OutputStream output = conn.getOutputStream();
            output.write(("--" + boundary + "\r\n").getBytes());
            output.write(String.format("Content-Disposition: form-data; name=\"media\"; filename=\"%s\"\r\n", file.getName()).getBytes());
            output.write("Content-Type: video/mp4 \r\n\r\n".getBytes());

            byte[] data = new byte[1024];
            int len = 0;
            FileInputStream input = new FileInputStream(file);
            while ((len = input.read(data)) > -1) {
                output.write(data, 0, len);
            }

            /*对类型为video的素材进行特殊处理*/
            if ("video".equals(type)) {
                output.write(("--" + boundary + "\r\n").getBytes());
                output.write("Content-Disposition: form-data; name=\"description\";\r\n\r\n".getBytes());
                output.write(String.format("{\"title\":\"%s\", \"introduction\":\"%s\"}", title, introduction).getBytes());
            }

            output.write(("\r\n--" + boundary + "--\r\n\r\n").getBytes());
            output.flush();
            output.close();
            input.close();

            InputStream resp = conn.getInputStream();

            StringBuffer sb = new StringBuffer();

            while ((len = resp.read(data)) > -1)
                sb.append(new String(data, 0, len, "utf-8"));
            resp.close();
            result = sb.toString();
        } catch (IOException e) {
            //....
        }

        return result;
    }

//    public static void main(String[] args) throws HttpProcessException {
//        String accessToken = getAccessToken();
//        System.out.println("***************"+accessToken);
//    }

}

到了这里,关于java实现微信公众号图文、视频一键发布的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信公众号 - Java推送小程序订阅消息给用户_java 通过微信公众号发送订阅通知

    不啰嗦,我们直接开始! 本文使用体验版小程序进行调试。 1、登录微信公众平台 点开下面链接,使用微信扫码 微信公众平台 然后选择一个小程序并登录 2、在小程序后台找到Appid、AppSecret、Token、EncodingAESKey等参数 AppSecret忘记了可以自行重置 往下翻,在消息推送这儿能看到

    2024年04月26日
    浏览(47)
  • 微信公众号推送天气教程,自动定时推送【Java版】开发者和小白详细教程

    久违的大更新: 建议先打开,因为GitHub在国内加载很慢。 点击打开 Java版本,教程最近一次更新时间为: 2023-08-23 重大更新: 1: 谚语功能修复。 2: 新增农历生日。 已经部署的伙伴,务必在公众号后台更新新的模块以及applicantion.yml配置文件中的模板ID,新的模板在本教程当中

    2024年01月23日
    浏览(74)
  • Java实现公众号功能、关注、消息推送

    实现公众号事件处理类 实现公众号日志记录处理器 实现公众号用户关注处理器 实现公众号用户取消关注处理器 实现公众号用户发送消息处理器 用户消息事件分类处理Builder 定义处理抽象类 实现处理抽象类–子类–文本消息 实现处理抽象类–子类–图片消息

    2024年02月08日
    浏览(40)
  • 微信公众号模板消息源码实现,打破服务号群发推送次数限制

    公众号服务号每个月只能群发推送四次文章,我们可以使用模板消息为公众号粉丝推送信息 下面是使用golang实现的模板消息发送类库封装,轻松实现模板消息发送 wechat.go 我们的使用方式 推送的效果如图所示,点击模板就能跳转到我们自定义的url上 我在自己客服系统中也是

    2024年02月15日
    浏览(47)
  • spring boot +微信小程序项目,通过微信公众号实现指定用户消息长期推送

    用户登录小程序,后台记录用户的小程序openId和用户唯一的UnionId。然后用户触发公众号事件(关注公众号或者发送指定消息),后台获取到用户公众号的openId,再调用接口通过公众号的openId查询用户的UnionId,再和数据库里的UnionId进行匹配,将用户的公众号openId存入数据库。此

    2024年02月03日
    浏览(57)
  • JAVA 获取微信公众号发布的文章列表内容

    代码业务场景 一、前提操作 二、开始操作 1.获取公众号的开发者id(AppID)和开发者密码(AppSecret),以及设置IP白名单 2.代码操作 总结 最近在给客户开发一款小程序,然后客户还有自己运营的公众号,想要把公众号里面发布的一些内容能够同步到小程序里面进行展示。如下

    2024年02月09日
    浏览(35)
  • 微信公众平台自定义菜单 /事件推送

    用户点击自定义菜单后,微信会把点击事件推送给开发者,请注意,点击菜单弹出子菜单,不会产生上报。 请注意,第3个到第8个的所有事件,仅支持微信iPhone5.4.1以上版本,和Android5.4以上版本的微信用户,旧版本微信用户点击后将没有回应,开发者也不能正常接收到事件推

    2024年02月16日
    浏览(44)
  • 微信公众号推送模板消息给用户

    前置条件: 1.公众号为服务号,而非订阅号 2.认证(300元) 3.进入公众号申请模板推送功能 4.添加模板(注意:推送的消息只能使用微信提供的模板,不可自定义,但也是比较全的) 4.2 获取accessToken时,需要将开发环境的电脑ip添加到微信后台的ip白名单(线上环境亦是如此

    2024年02月12日
    浏览(56)
  • 微信小程序向公众号推送消息模板

    由于微信小程序长期订阅的消息模板全部失效以后,对于小程序的消息推送可以改成往公众号推。 这里将介绍如何使用小程序向公众号推送消息,并且消息可以跳转到小程序 1、微信公众平台注册 服务号 (订阅号是不可以推送的)与小程序,两者都需要认证并且 认证主体是

    2024年02月06日
    浏览(53)
  • uniApp 微信小程序 授权 公众号推送信息

    准本工作  1.首先小程序  更公众号关联起来 2.配置相应的域名(也就是你请求后端接口的公共地址) 3.需要写一个h5 页面 用于跳板 公众号 的授权 公众号如何关联小程序? 打开微信公众号后台,选择「设置 – 公众号设置 」 [关注公众号 -打开开关  ], 步骤一 步骤二  步

    2024年02月10日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包