package com.panzhihua.common.utlis;
|
|
import cn.hutool.core.util.StrUtil;
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONObject;
|
import com.panzhihua.common.constants.SecurityConstants;
|
import com.panzhihua.common.controller.BaseController;
|
import com.panzhihua.common.redis.RedisUtils;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.fileupload.FileItem;
|
import org.apache.commons.fileupload.FileItemFactory;
|
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
|
import org.apache.http.entity.ContentType;
|
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.data.redis.core.ValueOperations;
|
import org.springframework.stereotype.Component;
|
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.commons.CommonsMultipartFile;
|
|
import javax.annotation.PostConstruct;
|
import javax.annotation.Resource;
|
import javax.servlet.http.HttpServletRequest;
|
import java.io.*;
|
import java.net.HttpURLConnection;
|
import java.net.URL;
|
import java.nio.charset.StandardCharsets;
|
import java.text.MessageFormat;
|
import java.text.SimpleDateFormat;
|
import java.util.Date;
|
import java.util.Map;
|
import java.util.concurrent.TimeUnit;
|
|
@Slf4j
|
@Component
|
public class WxXCXTempSend extends BaseController {
|
|
public static final String APP_ID = "wx118de8a734d269f0";
|
private static final String APP_SECRET = "0264342daefde5cd70a6adada09ee5b1";
|
private static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";
|
private static String APP_IMAGE_URL = "https://www.psciio.com//idcard/8fa82cfba258498eab2fa818220fb592.jpg";
|
private static String APP_IMAGE_NAME = "5.jpg";
|
private static String WX_CALL_BACK = "https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=";
|
//2小时
|
private static final Long EXPIRE_TIME = 2L;
|
@Resource
|
private RedisTemplate redisTemplate;
|
@Resource
|
private StringRedisTemplate stringRedisTemplate;
|
@Resource
|
private RedisUtils redisUtils;
|
|
private static WxXCXTempSend wxXCXTempSend;
|
|
/**
|
* url转变为 MultipartFile对象
|
*
|
* @param url
|
* @param fileName
|
* @return
|
* @throws Exception
|
*/
|
private static MultipartFile createFileItem(String url, String fileName) throws Exception {
|
FileItem item = null;
|
try {
|
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
conn.setReadTimeout(30000);
|
conn.setConnectTimeout(30000);
|
// 设置应用程序要从网络连接读取数据
|
conn.setDoInput(true);
|
conn.setRequestMethod("GET");
|
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
InputStream is = conn.getInputStream();
|
|
FileItemFactory factory = new DiskFileItemFactory(16, null);
|
String textFieldName = "uploadfile";
|
item =
|
factory.createItem(textFieldName, ContentType.APPLICATION_OCTET_STREAM.toString(), false, fileName);
|
OutputStream os = item.getOutputStream();
|
|
int bytesRead = 0;
|
byte[] buffer = new byte[8192];
|
while ((bytesRead = is.read(buffer, 0, 8192)) != -1) {
|
os.write(buffer, 0, bytesRead);
|
}
|
os.close();
|
is.close();
|
}
|
} catch (IOException e) {
|
throw new RuntimeException("文件下载失败", e);
|
}
|
|
return new CommonsMultipartFile(item);
|
}
|
|
/**
|
* 获取小程序token,(ps:0=token获取失败)
|
*
|
* @return
|
*/
|
public String getAccessToken() throws Exception {
|
String accessToken = "";
|
String appId = this.getAppId();
|
accessToken = wxXCXTempSend.stringRedisTemplate.boundValueOps("access_token:access_token:" + appId).get();
|
return accessToken;
|
}
|
|
|
public String getAccessToken(String appId) throws Exception {
|
String accessToken = "";
|
accessToken = wxXCXTempSend.stringRedisTemplate.boundValueOps("access_token:access_token:" + appId).get();
|
return accessToken;
|
}
|
|
private String validAccessToken(String accessToken, String appId, String appSecret) throws Exception {
|
if (StrUtil.isEmpty(accessToken)) {
|
//重新获取并设置到缓存 该方法暂时只用在花城
|
accessToken = getAppAccessToken(appId, appSecret);
|
wxXCXTempSend.stringRedisTemplate.opsForValue().set("access_token:access_token:" + appId, accessToken, EXPIRE_TIME, TimeUnit.HOURS);
|
} else {
|
String accessTokenUrl = WX_CALL_BACK + accessToken;
|
String result = HttpClientUtil.httpGet(accessTokenUrl, null, null);
|
Map<String, Object> resultMap = JSON.parseObject(result, Map.class);
|
//如果Access_token过期也重新获取
|
if (resultMap.containsKey("errcode")) {
|
accessToken = getAppAccessToken(appId, appSecret);
|
wxXCXTempSend.stringRedisTemplate.opsForValue().set("access_token:access_token:" + appId, accessToken, EXPIRE_TIME, TimeUnit.HOURS);
|
}
|
}
|
return accessToken;
|
}
|
|
public String getAppAccessToken(String appId, String appSecret) throws Exception {
|
String accessToken = "0";
|
try {
|
log.info("获取微信token参数:appid=" + appId + ",appSecret=" + appSecret);
|
String accessTokenUrl = ACCESS_TOKEN_URL + "&appid=" + appId + "&secret=" + appSecret;
|
String result = HttpClientUtil.httpGet(accessTokenUrl, null, null);
|
Map<String, Object> resultMap = JSON.parseObject(result, Map.class);
|
StringRedisTemplate redisTemplate = wxXCXTempSend.stringRedisTemplate;
|
if (resultMap.containsKey("access_token")) {
|
accessToken = resultMap.get("access_token").toString();
|
redisTemplate.opsForValue().set("access_token:access_token:" + appId, accessToken);
|
}
|
HttpServletRequest request = ServletUtils.getRequest();
|
String requestURI = request.getRequestURI();
|
//加上时间戳
|
String datetime = new SimpleDateFormat("yyyyMMdd").format(new Date());
|
//这里是 Redis key的前缀,如: sys:tabieId:表名 如果不需要去掉表名也可以
|
String key = MessageFormat.format("{0}:{1}:{2}", "access_token_request_incr",datetime,requestURI);
|
//查询 key 是否存在, 不存在返回 1 ,存在的话则自增加1
|
redisTemplate.opsForValue().increment(key, 1);
|
|
} catch (IOException ioe) {
|
log.error("小程序http请求异常");
|
ioe.printStackTrace();
|
}
|
return accessToken;
|
}
|
|
public String getWsAccessToken() throws Exception {
|
String accessToken = "0";
|
try {
|
// log.info("获取微信token参数:appid=" + APP_ID + ",appSecret=" + APP_SECRET);
|
String accessTokenUrl = ACCESS_TOKEN_URL + "&appid=wx98d62711dfbd8425" + "&secret=97a2a10b990c2774ed279724337b5337";
|
String result = HttpClientUtil.httpGet(accessTokenUrl, null, null);
|
Map<String, Object> resultMap = JSON.parseObject(result, Map.class);
|
if (resultMap.containsKey("access_token")) {
|
accessToken = resultMap.get("access_token").toString();
|
}
|
} catch (IOException ioe) {
|
log.error("小程序http请求异常");
|
ioe.printStackTrace();
|
}
|
return accessToken;
|
}
|
|
/**
|
* 获取西区社区通微信token
|
*
|
* @return 西区社区通微信token
|
* @throws Exception 异常
|
*/
|
public String getXQAppAccessToken() throws Exception {
|
String accessToken = "0";
|
try {
|
// 此处APP_ID APP_SECRET 在微信小程序后端可见
|
// String accessTokenUrl = String.format(TEMP_URL, APP_ID, APP_SECRET);
|
String accessTokenUrl = ACCESS_TOKEN_URL + "&appid=" + APP_ID + "&secret=" + APP_SECRET;
|
String result = HttpClientUtil.httpGet(accessTokenUrl, null, null);
|
Map<String, Object> resultMap = JSON.parseObject(result, Map.class);
|
if (resultMap.containsKey("access_token")) {
|
accessToken = resultMap.get("access_token").toString();
|
}
|
} catch (IOException ioe) {
|
log.error("小程序http请求异常");
|
ioe.printStackTrace();
|
}
|
return accessToken;
|
}
|
|
public String getMediaId(String accessToken) {
|
String mediaId = "";
|
Boolean aBoolean = redisTemplate.hasKey(SecurityConstants.APPLETS_ACCESS_MEDIA_ID);
|
ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
|
if (aBoolean) {
|
Long expireTime = Long.parseLong(valueOperations.get(SecurityConstants.APPLETS_ACCESS_MEDIA_ID_TIME));
|
if (expireTime <= System.currentTimeMillis()) {
|
redisTemplate.delete(SecurityConstants.APPLETS_ACCESS_MEDIA_ID);// 如果过期则删除
|
redisTemplate.delete(SecurityConstants.APPLETS_ACCESS_MEDIA_ID_TIME);// 如果过期则删除
|
mediaId = getAppMediaId(accessToken);
|
valueOperations.set(SecurityConstants.APPLETS_ACCESS_MEDIA_ID, mediaId);
|
valueOperations.set(SecurityConstants.APPLETS_ACCESS_MEDIA_ID_TIME,
|
System.currentTimeMillis() + 259000000 + "");
|
} else {
|
mediaId = valueOperations.get(SecurityConstants.APPLETS_ACCESS_MEDIA_ID);
|
}
|
} else {
|
mediaId = getAppMediaId(accessToken);
|
valueOperations.set(SecurityConstants.APPLETS_ACCESS_MEDIA_ID, mediaId);
|
valueOperations.set(SecurityConstants.APPLETS_ACCESS_MEDIA_ID_TIME,
|
System.currentTimeMillis() + 259000000 + "");
|
}
|
return mediaId;
|
}
|
|
private String getAppMediaId(String accessToken) {
|
String appMediaId = "";
|
try {
|
MultipartFile file = createFileItem(APP_IMAGE_URL, APP_IMAGE_NAME);
|
appMediaId = uploadFile(file, accessToken);
|
} catch (Exception e) {
|
log.error("上传临时图片素材失败,错误原因:" + e.getMessage());
|
}
|
return appMediaId;
|
}
|
|
/**
|
* 微信小程序临时素材上传
|
*
|
* @param file
|
* @return
|
* @throws Exception
|
* @author yixiu
|
*/
|
public String uploadFile(MultipartFile file, String access_token) throws Exception {
|
String url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=" + access_token + "&type=image";
|
String result = null;
|
String fileName = file.getOriginalFilename();
|
URL urlObj = new URL(url);
|
HttpURLConnection con = (HttpURLConnection) urlObj.openConnection();
|
con.setRequestMethod("POST");
|
con.setDoInput(true);
|
con.setDoOutput(true);
|
con.setUseCaches(false);
|
// 设置请求头信息
|
con.setRequestProperty("Connection", "Keep-Alive");
|
con.setRequestProperty("Charset", "UTF-8");
|
// 设置边界
|
String BOUNDARY = "----------" + System.currentTimeMillis();
|
con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
|
// 请求正文信息
|
// 第一部分:
|
StringBuilder sb = new StringBuilder();
|
sb.append("--"); // 必须多两道线
|
sb.append(BOUNDARY);
|
sb.append("\r\n");
|
sb.append("Content-Disposition: form-data;name=\"media\";filename=\"" + fileName + "\"\r\n");
|
sb.append("Content-Type:application/octet-stream\r\n\r\n");
|
byte[] head = sb.toString().getBytes(StandardCharsets.UTF_8);
|
// 获得输出流
|
OutputStream out = new DataOutputStream(con.getOutputStream());
|
// 输出表头
|
out.write(head);
|
// 文件正文部分
|
// 把文件已流文件的方式 推入到url中
|
DataInputStream in = new DataInputStream(file.getInputStream());
|
int bytes = 0;
|
byte[] bufferOut = new byte[1024];
|
while ((bytes = in.read(bufferOut)) != -1) {
|
out.write(bufferOut, 0, bytes);
|
}
|
in.close();
|
// 结尾部分
|
byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes(StandardCharsets.UTF_8);// 定义最后数据分隔线
|
out.write(foot);
|
out.flush();
|
out.close();
|
StringBuffer buffer = new StringBuffer();
|
BufferedReader reader = null;
|
try {
|
// 定义BufferedReader输入流来读取URL的响应
|
reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
String line = null;
|
while ((line = reader.readLine()) != null) {
|
buffer.append(line);
|
}
|
if (result == null) {
|
result = buffer.toString();
|
}
|
} catch (IOException e) {
|
System.out.println("发送POST请求出现异常! {}");
|
e.printStackTrace();
|
throw new IOException("数据读取异常");
|
} finally {
|
if (reader != null) {
|
reader.close();
|
}
|
}
|
// 获取到返回HTTP结果
|
Map<String, Object> map = JSONObject.parseObject(result, Map.class);
|
if (map.containsKey("media_id")) {
|
return map.get("media_id").toString();
|
}
|
System.out.println("小程序上传临时素材出错,返回信息为: " + result);
|
return null;
|
}
|
|
@PostConstruct
|
public void init() {
|
wxXCXTempSend = this;
|
wxXCXTempSend.redisTemplate = this.redisTemplate;
|
wxXCXTempSend.stringRedisTemplate = this.stringRedisTemplate;
|
wxXCXTempSend.redisUtils = this.redisUtils;
|
|
}
|
|
}
|