当前位置:   article > 正文

java实现微信公众号图文、视频一键发布_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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
所有涉及到的微信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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
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;
    }

 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
(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;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
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;
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
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;


}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

一键发布:

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;
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180

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;
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

4:群发视频、文章删除

 /***
     * 删除群发消息
     * @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;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

附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);
//    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/70785
推荐阅读
相关标签
  

闽ICP备14008679号