微信公众号开发
一、准备工作
在微信开发平台申请一个测试账号(优先选择这个),如果可以使用认证过的订阅号最好,不过我们在开发阶段很多功能都是测试用的,申请一个测试账号完全够用
个人的订阅号是不可以申请认证的,所以很多微信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)
具体可参考:文章来源:https://www.toymoban.com/news/detail-612832.html
/***
* * 群发视频
* @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模板网!