一、本节要点

1.官方文档的media

这个media可以理解为文件,即我们需要以POST方式提交一个文件

2.媒体文件有效期

媒体文件在微信后台保存时间为3天,即3天后media_id失效。

二、代码实现

1.HTTP请求工具类—HttpHelper.java

package com.ray.weixin.gz.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream; import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.util.EntityUtils; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; /**
* HTTP请求封装,建议直接使用sdk的API
*/
public class HttpHelper { /**
* @desc :1.发起GET请求
*
* @param url
* @return JSONObject
* @throws Exception
*/
public static JSONObject doGet(String url) throws Exception { //1.生成一个请求
HttpGet httpGet = new HttpGet(url);
//2.配置请求的属性
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(5000).setConnectTimeout(5000).build();//
httpGet.setConfig(requestConfig); //3.发起请求,获取响应信息
//3.1 创建httpClient
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
try {
//3.2 发起请求,获取响应信息
response = httpClient.execute(httpGet, new BasicHttpContext()); //如果返回结果的code不等于200,说明出错了
if (response.getStatusLine().getStatusCode() != 200) { System.out.println("request url failed, http code=" + response.getStatusLine().getStatusCode()
+ ", url=" + url);
return null;
}
//4.解析请求结果
HttpEntity entity = response.getEntity(); //reponse返回的数据在entity中
if (entity != null) {
String resultStr = EntityUtils.toString(entity, "utf-8"); //将数据转化为string格式
System.out.println("GET请求结果:"+resultStr);
JSONObject result = JSON.parseObject(resultStr); //将String转换为 JSONObject if(result.getInteger("errcode")==null) {
return result;
}else if (0 == result.getInteger("errcode")) {
return result;
}else {
System.out.println("request url=" + url + ",return value=");
System.out.println(resultStr);
int errCode = result.getInteger("errcode");
String errMsg = result.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
}
}
} catch (IOException e) {
System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
e.printStackTrace();
} finally {
if (response != null) try {
response.close(); //释放资源 } catch (IOException e) {
e.printStackTrace();
}
} return null;
} /** 2.发起POST请求
* @desc :
*
* @param url 请求url
* @param data 请求参数(json)
* @return
* @throws Exception JSONObject
*/
public static JSONObject doPost(String url, Object data) throws Exception {
//1.生成一个请求
HttpPost httpPost = new HttpPost(url); //2.配置请求属性
//2.1 设置请求超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(100000).setConnectTimeout(100000).build();
httpPost.setConfig(requestConfig);
//2.2 设置数据传输格式-json
httpPost.addHeader("Content-Type", "application/json");
//2.3 设置请求实体,封装了请求参数
StringEntity requestEntity = new StringEntity(JSON.toJSONString(data), "utf-8");
httpPost.setEntity(requestEntity); //3.发起请求,获取响应信息
//3.1 创建httpClient
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null; try { //3.3 发起请求,获取响应
response = httpClient.execute(httpPost, new BasicHttpContext()); if (response.getStatusLine().getStatusCode() != 200) { System.out.println("request url failed, http code=" + response.getStatusLine().getStatusCode()
+ ", url=" + url);
return null;
} //获取响应内容
HttpEntity entity = response.getEntity();
if (entity != null) {
String resultStr = EntityUtils.toString(entity, "utf-8");
System.out.println("POST请求结果:"+resultStr); //解析响应内容
JSONObject result = JSON.parseObject(resultStr); if(result.getInteger("errcode")==null) {
return result;
}else if (0 == result.getInteger("errcode")) {
return result;
}else {
System.out.println("request url=" + url + ",return value=");
System.out.println(resultStr);
int errCode = result.getInteger("errcode");
String errMsg = result.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
}
}
} catch (IOException e) {
System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
e.printStackTrace();
} finally {
if (response != null) try {
response.close(); //释放资源 } catch (IOException e) {
e.printStackTrace();
}
} return null;
} /**
* @desc : 3.上传文件
*
* @param url 请求url
* @param file 上传的文件
* @return
* @throws Exception JSONObject
*/
public static JSONObject uploadMedia(String url, File file) throws Exception {
HttpPost httpPost = new HttpPost(url);
CloseableHttpResponse response = null;
CloseableHttpClient httpClient = HttpClients.createDefault();
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(5000).setConnectTimeout(5000).build();
httpPost.setConfig(requestConfig); //2.3 设置请求实体,封装了请求参数
HttpEntity requestEntity = MultipartEntityBuilder.create().addPart("media",
new FileBody(file, ContentType.create("multipart/form-data", Consts.UTF_8), file.getName())).build(); //FileEntity requestEntity = new FileEntity(file,ContentType.MULTIPART_FORM_DATA); httpPost.setEntity(requestEntity); try {
response = httpClient.execute(httpPost, new BasicHttpContext()); if (response.getStatusLine().getStatusCode() != 200) { System.out.println("request url failed, http code=" + response.getStatusLine().getStatusCode()
+ ", url=" + url);
return null;
}
HttpEntity entity = response.getEntity();
if (entity != null) {
String resultStr = EntityUtils.toString(entity, "utf-8"); JSONObject result = JSON.parseObject(resultStr);
//上传临时素材成功
if (result.getString("errcode")== null) {
// 成功
//result.remove("errcode");
//result.remove("errmsg");
return result;
} else {
System.out.println("request url=" + url + ",return value=");
System.out.println(resultStr);
int errCode = result.getInteger("errcode");
String errMsg = result.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
}
}
} catch (IOException e) {
System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
e.printStackTrace();
} finally {
if (response != null) try {
response.close(); //释放资源 } catch (IOException e) {
e.printStackTrace();
}
} return null;
} /**
* @desc : 上传PDF
* 见微信电子发票章节
* 9. 向用户提供发票或其它消费凭证PDF
*
* @param url
* @param file
* @return
* @throws Exception
* JSONObject
*/
public static JSONObject uploadPDF(String url, File file) throws Exception {
HttpPost httpPost = new HttpPost(url);
CloseableHttpResponse response = null;
CloseableHttpClient httpClient = HttpClients.createDefault();
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(5000).setConnectTimeout(5000).build();
httpPost.setConfig(requestConfig); //2.3 设置请求实体,封装了请求参数
HttpEntity requestEntity = MultipartEntityBuilder.create().addPart("media",
new FileBody(file, ContentType.create("multipart/form-data", Consts.UTF_8), file.getName())).build(); httpPost.setEntity(requestEntity); try {
response = httpClient.execute(httpPost, new BasicHttpContext()); if (response.getStatusLine().getStatusCode() != 200) { System.out.println("request url failed, http code=" + response.getStatusLine().getStatusCode()
+ ", url=" + url);
return null;
}
HttpEntity entity = response.getEntity();
if (entity != null) {
String resultStr = EntityUtils.toString(entity, "utf-8"); JSONObject result = JSON.parseObject(resultStr);
//上传临时素材成功
if (result.getString("errcode")== null) {
// 成功
//result.remove("errcode");
//result.remove("errmsg");
return result;
} else {
System.out.println("request url=" + url + ",return value=");
System.out.println(resultStr);
int errCode = result.getInteger("errcode");
String errMsg = result.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
}
}
} catch (IOException e) {
System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
e.printStackTrace();
} finally {
if (response != null) try {
response.close(); //释放资源 } catch (IOException e) {
e.printStackTrace();
}
} return null;
}
/**
* @desc : 4.下载文件 -get
*
* @param url 请求url
* @param fileDir 下载路径
* @return
* @throws Exception File
*/
public static File downloadMedia(String url, String fileDir) throws Exception {
//1.生成一个请求
HttpGet httpGet = new HttpGet(url);
//2.配置请求属性
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(100000).setConnectTimeout(100000).build();
httpGet.setConfig(requestConfig); //3.发起请求,获取响应信息
//3.1 创建httpClient
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null; //4.设置本地保存的文件
//File file = new File(fileDir);
File file = null;
try {
//5. 发起请求,获取响应信息
response = httpClient.execute(httpGet, new BasicHttpContext());
System.out.println("HttpStatus.SC_OK:"+HttpStatus.SC_OK);
System.out.println("response.getStatusLine().getStatusCode():"+response.getStatusLine().getStatusCode());
System.out.println("http-header:"+JSON.toJSONString( response.getAllHeaders() ));
System.out.println("http-filename:"+getFileName(response) ); //请求成功
if(HttpStatus.SC_OK==response.getStatusLine().getStatusCode()){ //6.取得请求内容
HttpEntity entity = response.getEntity(); if (entity != null) {
//这里可以得到文件的类型 如image/jpg /zip /tiff 等等 但是发现并不是十分有效,有时明明后缀是.rar但是取到的是null,这点特别说明
System.out.println(entity.getContentType());
//可以判断是否是文件数据流
System.out.println(entity.isStreaming()); //6.1 输出流
//6.1.1获取文件名,拼接文件路径
String fileName=getFileName(response);
fileDir=fileDir+fileName;
file = new File(fileDir);
//6.1.2根据文件路径获取输出流
FileOutputStream output = new FileOutputStream(file); //6.2 输入流:从钉钉服务器返回的文件流,得到网络资源并写入文件
InputStream input = entity.getContent(); //6.3 将数据写入文件:将输入流中的数据写入到输出流
byte b[] = new byte[1024];
int j = 0;
while( (j = input.read(b))!=-1){
output.write(b,0,j);
}
output.flush();
output.close();
}
if (entity != null) {
entity.consumeContent();
}
}
} catch (IOException e) {
System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
e.printStackTrace();
} finally {
if (response != null) try {
response.close(); //释放资源 } catch (IOException e) {
e.printStackTrace();
}
} return file;
} /**
* @desc : 5.下载文件 - post
*
* @param url 请求url
* @param data post请求参数
* @param fileDir 文件下载路径
* @return
* @throws Exception File
*/
public static File downloadMedia(String url, Object data, String fileDir) throws Exception {
//1.生成一个请求
HttpPost httpPost = new HttpPost(url); //2.配置请求属性
//2.1 设置请求超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(100000).setConnectTimeout(100000).build();
httpPost.setConfig(requestConfig);
//2.2 设置数据传输格式-json
httpPost.addHeader("Content-Type", "application/json");
//2.3 设置请求参数
StringEntity requestEntity = new StringEntity(JSON.toJSONString(data), "utf-8");
httpPost.setEntity(requestEntity); //3.发起请求,获取响应信息
//3.1 创建httpClient
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null; //4.设置本地保存的文件
//File file = new File(fileDir);
File file = null;
try {
//5. 发起请求,获取响应信息
response = httpClient.execute(httpPost, new BasicHttpContext());
System.out.println("HttpStatus.SC_OK:"+HttpStatus.SC_OK);
System.out.println("response.getStatusLine().getStatusCode():"+response.getStatusLine().getStatusCode());
System.out.println("http-header:"+JSON.toJSONString( response.getAllHeaders() ));
System.out.println("http-filename:"+getFileName(response) ); //请求成功
if(HttpStatus.SC_OK==response.getStatusLine().getStatusCode()){ //6.取得请求内容
HttpEntity entity = response.getEntity(); if (entity != null) {
//这里可以得到文件的类型 如image/jpg /zip /tiff 等等 但是发现并不是十分有效,有时明明后缀是.rar但是取到的是null,这点特别说明
System.out.println(entity.getContentType());
//可以判断是否是文件数据流
System.out.println(entity.isStreaming()); //6.1 输出流
//6.1.1获取文件名,拼接文件路径
String fileName=getFileName(response);
fileDir=fileDir+fileName;
file = new File(fileDir);
//6.1.2根据文件路径获取输出流
FileOutputStream output = new FileOutputStream(file); //6.2 输入流:从钉钉服务器返回的文件流,得到网络资源并写入文件
InputStream input = entity.getContent(); //6.3 将数据写入文件:将输入流中的数据写入到输出流
byte b[] = new byte[1024];
int j = 0;
while( (j = input.read(b))!=-1){
output.write(b,0,j);
}
output.flush();
output.close();
}
if (entity != null) {
entity.consumeContent();
}
}
} catch (IOException e) {
System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
e.printStackTrace();
} finally {
if (response != null) try {
response.close(); //释放资源 } catch (IOException e) {
e.printStackTrace();
}
} return file;
} /** 5. 获取response header中Content-Disposition中的filename值
* @desc :
*
* @param response 响应
* @return String
*/
public static String getFileName(HttpResponse response) {
Header contentHeader = response.getFirstHeader("Content-Disposition");
String filename = null;
if (contentHeader != null) {
HeaderElement[] values = contentHeader.getElements();
if (values.length == 1) {
NameValuePair param = values[0].getParameterByName("filename");
if (param != null) {
try {
//filename = new String(param.getValue().toString().getBytes(), "utf-8");
//filename=URLDecoder.decode(param.getValue(),"utf-8");
filename = param.getValue();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return filename;
} }

2.Token工具类—AuthHelper.java

package com.ray.weixin.gz.util;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Formatter;
import java.util.UUID; import javax.servlet.http.HttpServletRequest; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import com.alibaba.fastjson.JSONObject;
import com.ray.weixin.gz.config.Env;
import com.ray.weixin.gz.service.invoice.InvoiceService; /**
* 微信公众号 Token、配置工具类
* @desc : AccessToken、Jsticket 、Jsapi
*
* @author: shirayner
* @date : 2017年9月27日 下午5:00:25
*/
public class AuthHelper {
private static final Logger logger = LogManager.getLogger(AuthHelper.class); //1.获取access_token的接口地址,有效期为7200秒
private static final String GET_ACCESSTOKEN_URL="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
//2.获取getJsapiTicket的接口地址,有效期为7200秒
private static final String GET_JSAPITICKET_URL="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi"; //3.通过code换取网页授权access_token
private static final String GET_ACCESSTOKEN_BYCODE_URL="https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code"; /**
* @desc :1.获取access_token
*
* @param appId 第三方用户唯一凭证
* @param appSecret 第三方用户唯一凭证密钥,即appsecret
*
* @return
* access_token 获取到的凭证
* expires_in 凭证有效时间,单位:秒
* @throws Exception String
*/
public static String getAccessToken(String appId,String appSecret) throws Exception {
//1.获取请求url
String url=GET_ACCESSTOKEN_URL.replace("APPID", appId).replace("APPSECRET", appSecret); //2.发起GET请求,获取返回结果
JSONObject jsonObject=HttpHelper.doGet(url);
logger.info("jsonObject:"+jsonObject.toJSONString()); //3.解析结果,获取accessToken
String accessToken="";
if (null != jsonObject) {
//4.错误消息处理
if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {
int errCode = jsonObject.getInteger("errcode");
String errMsg = jsonObject.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
//5.成功获取accessToken
}else {
accessToken=jsonObject.getString("access_token");
}
} return accessToken;
} /**
* @desc :2.获取JsapiTicket
*
* @param accessToken 有效凭证
* @return
* @throws Exception String
*/
public static String getJsapiTicket(String accessToken) throws Exception {
//1.获取请求url
String url=GET_JSAPITICKET_URL.replace("ACCESS_TOKEN", accessToken); //2.发起GET请求,获取返回结果
JSONObject jsonObject=HttpHelper.doGet(url);
logger.info("jsonObject:"+jsonObject.toJSONString()); //3.解析结果,获取accessToken
String jsapiTicket="";
if (null != jsonObject) {
//4.错误消息处理
if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {
int errCode = jsonObject.getInteger("errcode");
String errMsg = jsonObject.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
//5.成功获取jsapiTicket
}else {
jsapiTicket=jsonObject.getString("ticket");
}
} return jsapiTicket;
} /**
* @desc : 3.通过code换取网页授权access_token
*
* @param appId 第三方用户唯一凭证
* @param appSecret 第三方用户唯一凭证密钥,即appsecret
* @param Code code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
*
* @return
* access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
* expires_in access_token接口调用凭证超时时间,单位(秒)
* refresh_token 用户刷新access_token
* openid 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
* scope 用户授权的作用域,使用逗号(,)分隔
*
* @throws Exception String
*/
public static JSONObject getAccessTokenByCode(String appId,String appSecret,String code) throws Exception {
//1.获取请求url
String url=GET_ACCESSTOKEN_BYCODE_URL.replace("APPID", appId).replace("SECRET", appSecret).replace("CODE", code); //2.发起GET请求,获取返回结果
JSONObject jsonObject=HttpHelper.doGet(url);
logger.info("jsonObject:"+jsonObject.toJSONString()); //3.解析结果,获取accessToken
JSONObject returnJsonObject=null;
if (null != jsonObject) {
//4.错误消息处理
if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {
int errCode = jsonObject.getInteger("errcode");
String errMsg = jsonObject.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
//5.成功获取accessToken
}else {
returnJsonObject=jsonObject;
}
} return returnJsonObject;
} /**
* @desc :4.获取前端jsapi需要的配置参数
*
* @param request
* @return String
*/
public static String getJsapiConfig(HttpServletRequest request){ //1.准备好参与签名的字段
//1.1 url
/*
*以http://localhost/test.do?a=b&c=d为例
*request.getRequestURL的结果是http://localhost/test.do
*request.getQueryString的返回值是a=b&c=d
*/
String urlString = request.getRequestURL().toString();
String queryString = request.getQueryString();
String queryStringEncode = null;
String url;
if (queryString != null) {
queryStringEncode = URLDecoder.decode(queryString);
url = urlString + "?" + queryStringEncode;
} else {
url = urlString;
} //1.2 noncestr
String nonceStr=UUID.randomUUID().toString(); //随机数
//1.3 timestamp
long timeStamp = System.currentTimeMillis() / 1000; //时间戳参数 String signedUrl = url; String accessToken = null;
String ticket = null; String signature = null; //签名 try {
//1.4 jsapi_ticket
accessToken=getAccessToken(Env.APP_ID, Env.APP_SECRET);
ticket=getJsapiTicket(accessToken); //2.进行签名,获取signature
signature=getSign(ticket,nonceStr,timeStamp,signedUrl); } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} logger.info("accessToken:"+accessToken);
logger.info("ticket:"+ticket);
logger.info("nonceStr:"+nonceStr);
logger.info("timeStamp:"+timeStamp);
logger.info("signedUrl:"+signedUrl);
logger.info("signature:"+signature);
logger.info("appId:"+Env.APP_ID); String configValue = "{signature:'" + signature + "',nonceStr:'" + nonceStr + "',timeStamp:'"
+ timeStamp + "',appId:'" + Env.APP_ID + "'}";
logger.info("configValue:"+configValue); return configValue;
} /**
* @desc : 4.1 生成签名的函数
*
* @param ticket jsticket
* @param nonceStr 随机串,自己定义
* @param timeStamp 生成签名用的时间戳
* @param url 需要进行免登鉴权的页面地址,也就是执行dd.config的页面地址
* @return
* @throws Exception String
*/ public static String getSign(String jsTicket, String nonceStr, Long timeStamp, String url) throws Exception {
String plainTex = "jsapi_ticket=" + jsTicket + "&noncestr=" + nonceStr + "&timestamp=" + timeStamp + "&url=" + url;
System.out.println(plainTex);
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(plainTex.getBytes("UTF-8"));
return byteToHex(crypt.digest());
} catch (NoSuchAlgorithmException e) {
throw new Exception(e.getMessage());
} catch (UnsupportedEncodingException e) {
throw new Exception(e.getMessage());
}
} /**
* @desc :4.2 将bytes类型的数据转化为16进制类型
*
* @param hash
* @return
* String
*/
private static String byteToHex(byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash) {
formatter.format("%02x", new Object[] { Byte.valueOf(b) });
}
String result = formatter.toString();
formatter.close();
return result;
} /** 5.获取前端所需发票签名参数
*
* @desc :
*(1)将 api_ticket、appid、timestamp、nonceStr、cardType的value值进行字符串的字典序排序。
*(2)再将所有参数字符串拼接成一个字符串进行sha1加密,得到cardSign。
*
* @return String
* timestamp :卡券签名时间戳
nonceStr : 卡券签名随机串
signType : 签名方式,默认'SHA1'
cardSign : 卡券签名
*
*/
public static String getInvoiceConfig(){
//1.准备好签名参数
//1.1 api_ticket 授权页ticket
String apiTicket=null;
try {
String accessToken = AuthHelper.getAccessToken(Env.APP_ID, Env.APP_SECRET);
apiTicket=InvoiceService.getAuthPageTicket(accessToken);
} catch (Exception e) {
logger.info("获取授权页ticket失败");
e.printStackTrace();
} //1.2 appid
String appId=Env.APP_ID; //1.3 timestamp 时间戳
String timeStamp = System.currentTimeMillis() / 1000 +""; //1.4 nonceStr 随机数
String nonceStr=UUID.randomUUID().toString(); //1.5 cardType
String cardType="INVOICE"; //2.获取签名
String cardSign=null;
try { cardSign = AuthHelper.getCardSign(apiTicket, appId, timeStamp, nonceStr, cardType); } catch (Exception e) {
logger.info("获取发票签名失败");
e.printStackTrace();
} String signType="SHA1"; logger.info("apiTicket:"+apiTicket);
logger.info("appId:"+appId);
logger.info("timeStamp:"+timeStamp);
logger.info("nonceStr:"+nonceStr);
logger.info("cardType:"+cardType);
logger.info("cardSign:"+cardSign);
logger.info("signType:"+signType); //3.返回前端所需发票签名参数
JSONObject jsonObject=new JSONObject();
jsonObject.put("timestamp", timeStamp);
jsonObject.put("nonceStr",nonceStr );
jsonObject.put("signType",signType );
jsonObject.put("cardSign", cardSign); String configValue = jsonObject.toJSONString();
logger.info("configValue:"+configValue); return configValue;
} /**
* @desc :5.1获取发票签名
*
* @param apiTicket 授权页ticket,见InvoiceService
* @param appId
* @param timeStamp 时间戳
* @param nonceStr 随机串
* @param cardType 填入INVOICE
* @return
* @throws Exception
* String
*/
public static String getCardSign(String apiTicket, String appId, String timeStamp, String nonceStr,String cardType) throws Exception {
//1.将 api_ticket、appid、timestamp、nonceStr、cardType的value值进行字符串的字典序排序。
//注意:是value值值
String[] array = new String[] { apiTicket, appId, timeStamp, nonceStr,cardType};
StringBuffer sb = new StringBuffer();
// 字符串排序
Arrays.sort(array);
for (int i = 0; i < 5; i++) {
sb.append(array[i]);
}
String plainTex = sb.toString(); //String plainTex = apiTicket+appId+cardType+nonceStr+timeStamp; System.out.println("plainTex:"+plainTex);
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(plainTex.getBytes("UTF-8"));
return byteToHex(crypt.digest());
} catch (NoSuchAlgorithmException e) {
throw new Exception(e.getMessage());
} catch (UnsupportedEncodingException e) {
throw new Exception(e.getMessage());
}
} public static String getSHA1(String apiTicket, String appId, String timeStamp, String nonceStr,String cardType) throws Exception{
System.out.println("getSHA1-----------");
try {
String[] array = new String[] { apiTicket, appId, timeStamp, nonceStr,cardType};
StringBuffer sb = new StringBuffer();
// 字符串排序
Arrays.sort(array);
for (int i = 0; i < 5; i++) {
sb.append(array[i]);
}
String str = sb.toString();
logger.info("str:"+str);
// SHA1签名生成
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(str.getBytes());
byte[] digest = md.digest(); StringBuffer hexstr = new StringBuffer();
String shaHex = "";
for (int i = 0; i < digest.length; i++) {
shaHex = Integer.toHexString(digest[i] & 0xFF);
if (shaHex.length() < 2) {
hexstr.append(0);
}
hexstr.append(shaHex);
}
return hexstr.toString();
} catch (Exception e) {
e.printStackTrace();
throw new Exception("获取发票签名失败");
}
} }

3.素材管理业务类—TempMaterialService.java

package com.ray.weixin.gz.service.tempmaterial;

import java.io.File;
import java.util.HashMap;
import java.util.Map; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ray.weixin.gz.util.HttpHelper; /**@desc : 素材管理
*
* @author: shirayner
* @date : 2017年11月1日 上午10:16:00
*/
public class TempMaterialService {
private static final Logger logger = LogManager.getLogger(TempMaterialService.class); //1.新增临时素材
private static final String UPLOAD_TEMPMATERIAL_URL="https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE";
//2.获取临时素材 ( 即为原“下载多媒体文件”接口 )
private static final String GET_TEMPMATERIAL_URL="https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID"; //3.新增永久素材(上传)——上传永久图片——上传图文消息内的图片获取URL
private static final String UPLOAD_PERMANENT_IMG_URL="https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN";
//4.新增永久素材(上传)——新增其他类型永久素材(image、voice、video、thumb)
private static final String UPLOAD_PERMANENT_MATERIAL_URL="https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type=TYPE";
//5.获取永久素材列表
private static final String LIST_PERMANENT_MATERIAL_URL="https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN";
//6.获取永久素材(下载)
private static final String GET_PERMANENT_MATERIAL_URL="https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=ACCESS_TOKEN";
//7.删除永久素材
private static final String DELETE_PERMANENT_MATERIAL_URL="https://api.weixin.qq.com/cgi-bin/material/del_material?access_token=ACCESS_TOKEN"; /** 1.新增临时素材
*
* @desc :
* 1、临时素材media_id是可复用的。
* 2、媒体文件在微信后台保存时间为3天,即3天后media_id失效。
* 3、上传临时素材的格式、大小限制与公众平台官网一致。
* 图片(image): 2M,支持PNG\JPEG\JPG\GIF格式
* 语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式
* 视频(video):10MB,支持MP4格式
* 缩略图(thumb):64KB,支持JPG格式
*
* @param accessToken 有效凭证
* @param type 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb)
* @param fileDir 要上传文件所在路径
* @return
* @throws Exception JSONObject
*/
public static JSONObject uploadTempMaterial(String accessToken,String type,String fileDir) throws Exception {
//1.创建本地文件
File file=new File(fileDir); //2.拼接请求url
String url = UPLOAD_TEMPMATERIAL_URL.replace("ACCESS_TOKEN", accessToken).replace("TYPE", type); //3.调用接口,发送请求,上传文件到微信服务器
JSONObject jsonObject=HttpHelper.uploadMedia(url, file);
logger.info("JsonObject:"+jsonObject.toJSONString()); //4.解析结果
if (jsonObject != null) {
if (jsonObject.getString("media_id") != null) {
logger.info("上传" + type + "临时素材成功:"+jsonObject.get("media_id"));
return jsonObject; //5.错误消息处理
} else {
logger.error("上传" + type + "临时素材成功失败");
}
}
return null; } /**
* @desc :2.获取临时素材
*
* @param accessToken 调用接口凭证
* @param mediaId 媒体文件ID
* @param fileDir 文件下载路径(文件所在文件夹路径),如 D:/img/download/,会与文件名拼接成文件下载路径
* @return
* @throws Exception File
*/
public static File getTempMaterial(String accessToken,String mediaId,String fileDir) throws Exception {
//1.拼接请求url
String url = GET_TEMPMATERIAL_URL.replace("ACCESS_TOKEN", accessToken).replace("MEDIA_ID", mediaId); //2.调用接口,发送请求,下载文件到本地
File file=HttpHelper.downloadMedia(url, fileDir);
logger.info("fileName:"+file.getName()); return file; } /** 3.新增永久素材——上传永久图片——上传图文消息内的图片获取URL
* @desc :
*
* @param accessToken
* @param fileDir
* @return
* @throws Exception String
*/
public static String uploadPermanentImg(String accessToken,String fileDir) throws Exception {
//1.创建本地文件
File file=new File(fileDir); //2.拼接请求url
String url = UPLOAD_PERMANENT_IMG_URL.replace("ACCESS_TOKEN", accessToken); //3.调用接口,发送请求,上传文件到微信服务器
JSONObject jsonObject=HttpHelper.uploadMedia(url, file);
logger.info("JsonObject:"+jsonObject.toJSONString()); String ImgUrl=null;
//4.解析结果
if (jsonObject != null) {
if (jsonObject.getString("url") != null) { ImgUrl=jsonObject.getString("url"); logger.info("新增永久素材成功:"+ImgUrl); //5.错误消息处理
} else {
logger.info("新增永久素材失败");
}
}
return ImgUrl;
} /**
* @desc : 4.新增永久素材——新增其他类型永久素材(image、voice、thumb)
*
* @param accessToken 调用接口凭证
* @param type 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb)
* @param fileDir 本地图片路径
*
* @return
* media_id 新增的永久素材的media_id
* url 新增的图片素材的图片URL(仅新增图片素材时会返回该字段)
*
* @throws Exception String
*/
public static JSONObject uploadPermanentMaterial(String accessToken,String type,String fileDir) throws Exception {
//1.创建本地文件
File file=new File(fileDir); //2.拼接请求url
String url = UPLOAD_PERMANENT_MATERIAL_URL.replace("ACCESS_TOKEN", accessToken).replace("TYPE", type); //3.调用接口,发送请求,上传文件到微信服务器
JSONObject jsonObject=HttpHelper.uploadMedia(url, file);
logger.info("JsonObject:"+jsonObject.toJSONString()); //4.解析结果
JSONObject returnJsonObject=null;
if (jsonObject != null) {
if (jsonObject.getString("media_id") != null) { logger.info("新增永久素材成功:"+jsonObject.getString("media_id"));
returnJsonObject= jsonObject;
//5.错误消息处理
} else {
int errCode = jsonObject.getInteger("errcode");
String errMsg = jsonObject.getString("errmsg");
logger.error("新增永久素材失败"+" errcode:"+errCode+", errmsg:"+errMsg);
}
}
return returnJsonObject;
} /**
* @desc :5.获取永久素材列表
*
* @param accessToken 调用接口凭证
* @param type 素材的类型,图片(image)、视频(video)、语音 (voice)、图文(news)
* @param offset 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回
* @param count 返回素材的数量,取值在1到20之间
* @return
* @throws Exception JSONObject
*/
public static JSONObject listPermanentMaterial(String accessToken, String type, String offset,String count) throws Exception {
//1.准备好json请求参数
Map<String,String> paramMap=new HashMap<String,String>();
paramMap.put("type", type);
paramMap.put("offset", offset);
paramMap.put("count", count); Object data=JSON.toJSON(paramMap); //2.准备好请求url
String url=LIST_PERMANENT_MATERIAL_URL.replace("ACCESS_TOKEN", accessToken); //3.发起HTTP请求,获取返回结果
JSONObject jsonObject=HttpHelper.doPost(url, data);
logger.info("jsonObject:"+jsonObject.toJSONString()); //4.解析结果
JSONObject returnJsonObject=null;
if (jsonObject != null) { //4.1 错误消息处理
if (jsonObject.getInteger("errcode") != null) {
int errCode = jsonObject.getInteger("errcode");
String errMsg = jsonObject.getString("errmsg");
logger.error("获取永久素材列表失败 "+"errcode:"+errCode+", errmsg:"+errMsg); //4.2 新增成功
} else {
logger.info("获取永久素材列表成功 ");
returnJsonObject= jsonObject;
}
}
return returnJsonObject;
} /**
* @desc :6.获取永久素材
*
* @param accessToken 调用接口凭证
* @param mediaId 媒体文件ID
* @param fileDir 文件下载路径(文件所在文件夹路径),如 D:/img/download/,会与文件名拼接成文件下载路径
* @return
* @throws Exception File
*/
public static File getPermanentMaterial(String accessToken, String mediaId,String fileDir) throws Exception {
//1.准备好json请求参数
Map<String,String> paramMap=new HashMap<String,String>();
paramMap.put("media_id", mediaId); Object data=JSON.toJSON(paramMap); //2.准备好请求url
String url=GET_PERMANENT_MATERIAL_URL.replace("ACCESS_TOKEN", accessToken); //3.调用接口,发送HTTP请求,下载文件到本地
File file=HttpHelper.downloadMedia(url, data,fileDir);
logger.info("fileName:"+file.getName()); return file;
} /**
* @desc :7.删除永久素材
*
* @param accessToken 调用接口凭证
* @param mediaId 媒体文件ID
* @return
*
* @throws Exception JSONObject
*/
public static JSONObject deletePermanentMaterial(String accessToken, String mediaId) throws Exception {
//1.准备好json请求参数
Map<String,String> paramMap=new HashMap<String,String>();
paramMap.put("media_id", mediaId); Object data=JSON.toJSON(paramMap); //2.准备好请求url
String url=DELETE_PERMANENT_MATERIAL_URL.replace("ACCESS_TOKEN", accessToken); //3.发起HTTP请求,获取返回结果
JSONObject jsonObject=HttpHelper.doPost(url, data);
logger.info("jsonObject:"+jsonObject.toJSONString()); //4.解析结果
JSONObject returnJsonObject=null;
if (jsonObject != null) { //4.1 错误消息处理
if (jsonObject.getInteger("errcode") != 0) {
int errCode = jsonObject.getInteger("errcode");
String errMsg = jsonObject.getString("errmsg");
logger.error("删除永久素材失败 "+"errcode:"+errCode+", errmsg:"+errMsg); //4.2 新增成功
} else {
logger.info("删除永久素材成功 ");
returnJsonObject= jsonObject;
}
}
return returnJsonObject;
} }

4.素材管理测试类—TempMaterialServiceTest.java

package com.ray.weixin.gz.service.tempmaterial;

import org.junit.Test;

import com.ray.weixin.gz.config.Env;
import com.ray.weixin.gz.service.tempmaterial.TempMaterialService;
import com.ray.weixin.gz.util.AuthHelper; /**@desc : 素材管理
*
* @author: shirayner
* @date : 2017年11月1日 上午10:30:13
*/
public class TempMaterialServiceTest { /**
* @desc : 1.新增临时素材
*
* @throws Exception void
*/
@Test
public void testUploadTempMaterial() throws Exception {
String accessToken=AuthHelper.getAccessToken(Env.APP_ID, Env.APP_SECRET);
String type="image";
//String fileDir="D:/img/1.jpg"; //5BXY7DI-uz3N-m8HuZP3Lqzy-WrtegzUKW04OcLNlUjMBcyEyCdgorBsotQqpH0r String fileDir="D:/img/2.png"; //bdARqt5NClDYbP_og5NwBRwO4sCIIwF1ZeVQQKTvB1bkn2rL9Yq52Y6S656lTxf1 TempMaterialService.uploadTempMaterial(accessToken, type, fileDir); } /**
* @desc : 2.获取临时素材
*
* @throws Exception void
*/
@Test
public void testGetTempMaterial() throws Exception {
String accessToken=AuthHelper.getAccessToken(Env.APP_ID, Env.APP_SECRET);
// String mediaId="5BXY7DI-uz3N-m8HuZP3Lqzy-WrtegzUKW04OcLNlUjMBcyEyCdgorBsotQqpH0r"; // D:/img/1.jpg
String mediaId="4nPOsc2NL2e5MfRB3ePannbbuRrz0ZKi3udO4sP-6Nf7-SFJXM6D4sOyf1d_Khic"; // D:/img/2.png
String fileDir="D:/img/download/"; TempMaterialService.getTempMaterial(accessToken, mediaId, fileDir); } /**
* @desc : 3.新增永久素材——上传永久图片——上传图文消息内的图片获取URL
*
* @throws Exception void
*/
@Test
public void testUploadPermanentImg() throws Exception {
String accessToken=AuthHelper.getAccessToken(Env.APP_ID, Env.APP_SECRET); //String fileDir="D:/img/1.jpg";
String fileDir="D:/img/2.png"; TempMaterialService.uploadPermanentImg(accessToken, fileDir); } /**
* @desc : 4.新增永久素材——新增其他类型永久素材(image、voice、thumb)
*
* @throws Exception void
*/
@Test
public void testUploadPermanentMaterial() throws Exception {
String accessToken=AuthHelper.getAccessToken(Env.APP_ID, Env.APP_SECRET);
String type="image";
//String fileDir="D:/img/1.jpg";
String fileDir="D:/img/2.png"; TempMaterialService.uploadPermanentMaterial(accessToken, type, fileDir); } /**
* @desc : 5.获取永久素材列表
*
* @throws Exception void
*/
@Test
public void testListPermanentMaterial() throws Exception {
String accessToken=AuthHelper.getAccessToken(Env.APP_ID, Env.APP_SECRET);
String type="image";
String offset="0";
String count="2"; TempMaterialService.listPermanentMaterial(accessToken, type, offset, count); } /**
* @desc :6.获取永久素材
*
* @throws Exception void
*/
@Test
public void testGetPermanentMaterial() throws Exception {
String accessToken=AuthHelper.getAccessToken(Env.APP_ID, Env.APP_SECRET);
String mediaId="NFREZRuTaNgMSgnxT5agYkff8xLCKRjZPMXhS-lT6aE";
String fileDir="D:/img/download/"; TempMaterialService.getPermanentMaterial(accessToken, mediaId, fileDir); } /**
* @desc :7.删除永久素材
*
* @throws Exception void
*/
@Test
public void testDeletePermanentMaterial() throws Exception {
String accessToken=AuthHelper.getAccessToken(Env.APP_ID, Env.APP_SECRET);
String mediaId="NFREZRuTaNgMSgnxT5agYkff8xLCKRjZPMXhS-lT6aE"; TempMaterialService.deletePermanentMaterial(accessToken, mediaId); } }

Java微信公众平台开发_06_素材管理的更多相关文章

  1. Java微信公众平台开发_03_消息管理之被动回复消息

    GitHub源码:https://github.com/shirayner/weixin_gz 一.本节要点 1.回调url 上一节,我们启用服务器配置的时候,填写了一个服务器地址(url),如下图, ...

  2. Java微信公众平台开发_07_JSSDK图片上传

    一.本节要点 1.获取jsapi_ticket //2.获取getJsapiTicket的接口地址,有效期为7200秒 private static final String GET_JSAPITIC ...

  3. Java微信公众平台开发_02_启用服务器配置

    源码将在晚上上传到 github 一.准备阶段 需要准备事项: 1.一个能在公网上访问的项目: 见:[  Java微信公众平台开发_01_本地服务器映射外网  ] 2.一个微信公众平台账号: 去注册: ...

  4. Java微信公众平台开发--番外篇,对GlobalConstants文件的补充

    转自:http://www.cuiyongzhi.com/post/63.html 之前发过一个[微信开发]系列性的文章,也引来了不少朋友观看和点评交流,可能我在写文章时有所疏忽,对部分文件给出的不是 ...

  5. Java微信公众平台开发【番外篇】(七)--公众平台测试帐号的申请

    转自:http://www.cuiyongzhi.com/post/45.html 前面几篇一直都在写一些比较基础接口的使用,在这个过程中一直使用的都是我个人微博认证的一个个人账号,原本准备这篇是写[ ...

  6. Java微信公众平台开发(十二)--微信用户信息的获取

    转自:http://www.cuiyongzhi.com/post/56.html 前面的文章有讲到微信的一系列开发文章,包括token获取.菜单创建等,在这一篇将讲述在微信公众平台开发中如何获取微信 ...

  7. Java微信公众平台开发(一)--接入微信公众平台

    转自:http://www.cuiyongzhi.com/post/38.html (一)接入流程解析 在我们的开发过程中无论如何最好的参考工具当然是我们的官方文档了:http://mp.weixin ...

  8. Java微信公众平台开发(十)--微信用户信息的获取

    前面的文章有讲到微信的一系列开发文章,包括token获取.菜单创建等,在这一篇将讲述在微信公众平台开发中如何获取微信用户的信息,在上一篇我们有说道微信用户和微信公众账号之间的联系可以通过Openid关 ...

  9. Java微信公众平台开发(十六)--微信网页授权(OAuth2.0授权)获取用户基本信息

    转自:http://www.cuiyongzhi.com/post/78.html 好长时间没有写文章了,主要是最近的工作和生活上的事情比较多而且繁琐,其实到现在我依然还是感觉有些迷茫,最后还是决定静 ...

随机推荐

  1. 【框架学习与探究之宿主服务--Topshelf】

    前言 此文欢迎转载,原始链接地址:http://www.cnblogs.com/DjlNet/p/7603819.html 正文 原先也偶然见过这个关键词,当时只是有个大致了解貌似和WinServic ...

  2. linux视频之media媒体框架

    linux视频媒体(kernel层分析)主要包括三个文件: (/drivers/media/media-device.c ,  /drivers/media/media-devnode.c , /dr ...

  3. vue2+webpack使用1--初识默认展示页面

    1 从安装好的展示 vue2+webpack项目开始 2 关键目录及文件 3 关系图 4 类比nodejs项目的理解   // src/main.js import Vue from 'vue' // ...

  4. Hadoop(四)HDFS集群详解

    前言 前面几篇简单介绍了什么是大数据和Hadoop,也说了怎么搭建最简单的伪分布式和全分布式的hadoop集群.接下来这篇我详细的分享一下HDFS. HDFS前言: 设计思想:(分而治之)将大文件.大 ...

  5. Python 开发之路

    强烈推荐地表最强博客:http://www.cnblogs.com/wupeiqi Python开发[第一篇]:目录 Python开发[第二篇]:初识Python Python开发[第三篇]:Pyth ...

  6. This application failed to start because it could not find or load the Qt platform plugin "windows" 的问题原因以及解决方案

    1. 问题原因非常简单,经过各种百度,都没有找到解决方案,在此做一个记录备用. 2.原因就在于,项目目录使用了中文路径,然后出现了这个问题. 3.我是在使用 syncfusion 下的HTML 转PD ...

  7. SAP 动态设置 GUI STATUS 灰色不可用 或者隐藏(转)

    http://blog.sina.com.cn/s/blog_66110f6201017rul.html 有时候需要根据用户的权限或者是操作动态设置gui状态上的某些按钮的可用和不可用.   1.先定 ...

  8. Inno Setup打包注意事项

    Inno Setup是一个开源的,商业的,快捷的脚本打包工具. 具体打包流程根据界面提示就可以搞定,下面讲解几个注意事项 1.在安装包进行安装的过程当中,很多程序都需要修改配置信息,这就要求我们在安装 ...

  9. LINUX 笔记-MOUNT

    mount [-t vfstype] [-o options] device dir -o options: 主要用来描述设备或档案的挂接方式 1)loop:用来把一个文件当成硬盘分区挂上系统 2)r ...

  10. Fastify 系列教程三 (验证、序列化和生命周期)

    Fastify 系列教程: Fastify 系列教程一 (路由和日志) Fastify 系列教程二 (中间件.钩子函数和装饰器) Fastify 系列教程三 (验证.序列化和生命周期) 验证 Fast ...