| | |
| | | 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.springframework.beans.factory.annotation.Autowired; |
| | | 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 java.io.IOException; |
| | | 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 { |
| | | 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; |
| | | |
| | | public static final String APP_ID = "wx0cef797390444b75"; |
| | | private static final String APP_SECRET = "c7ea9aaa7e391a487e8a5b9ba61045d1"; |
| | | private static WxXCXTempSend wxXCXTempSend; |
| | | |
| | | @Autowired |
| | | private StringRedisTemplate redisTemplate; |
| | | /** |
| | | * 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获取失败) |
| | |
| | | */ |
| | | public String getAccessToken() throws Exception { |
| | | String accessToken = ""; |
| | | Boolean aBoolean = redisTemplate.hasKey(SecurityConstants.APPLETS_ACCESS_TOKEN); |
| | | ValueOperations<String, String> valueOperations = redisTemplate.opsForValue(); |
| | | if(aBoolean){ |
| | | Long expire = redisTemplate.boundHashOps(SecurityConstants.APPLETS_ACCESS_TOKEN).getExpire(); |
| | | if(expire <= 0){ |
| | | redisTemplate.delete(SecurityConstants.APPLETS_ACCESS_TOKEN);//如果过期则删除 |
| | | accessToken = getAppAccessToken(); |
| | | valueOperations.set(SecurityConstants.APPLETS_ACCESS_TOKEN, accessToken,110, TimeUnit.MINUTES); |
| | | }else{ |
| | | accessToken = valueOperations.get(SecurityConstants.APPLETS_ACCESS_TOKEN); |
| | | 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); |
| | | } |
| | | }else{ |
| | | accessToken = getAppAccessToken(); |
| | | valueOperations.set(SecurityConstants.APPLETS_ACCESS_TOKEN, accessToken,110, TimeUnit.MINUTES); |
| | | } |
| | | return accessToken; |
| | | } |
| | | |
| | | private String getAppAccessToken() throws Exception{ |
| | | public String getAppAccessToken(String appId, String appSecret) 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; |
| | | 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); |
| | | if(resultMap.containsKey("access_token")) { |
| | | 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) { |
| | |
| | | return accessToken; |
| | | } |
| | | |
| | | public static void main(String[] args) throws Exception { |
| | | // String accessToken = "0"; |
| | | // try { |
| | | // //此处APP_ID APP_SECRET 在微信小程序后端可见 |
| | | // String accessTokenUrl = String.format(TEMP_URL, APP_ID, 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(); |
| | | // } |
| | | // System.out.println(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; |
| | | |
| | | } |
| | | |
| | | } |