springcloud_k8s_panzhihuazhihuishequ/applets/src/main/java/com/panzhihua/applets/api/WxMessagePushApi.java
New file @@ -0,0 +1,153 @@ package com.panzhihua.applets.api; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.panzhihua.common.utlis.StringUtils; import com.panzhihua.common.utlis.WxUtil; import com.panzhihua.common.utlis.WxXCXTempSend; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; @Slf4j @RestController @RequestMapping("/wx/push/") public class WxMessagePushApi { private String token = "01A9CB2234D7CBD0AC61B75EB1263805"; private String url = "www.taobao.com";//图文跳转地址 private String thumbUrl = "https://www.psciio.com//idcard/f986ba3ae7a241d9bce5cb568adec7da.jpg";//图片地址 @Resource private WxXCXTempSend wxXCXTempSend; /** * 微信接口配置信息认证接口<br> * 需要正确响应微信发送的Token验证。 加密/校验流程如下:<br> * 1. 将token、timestamp、nonce三个参数进行字典序排序<br> * 2. 将三个参数字符串拼接成一个字符串进行sha1加密<br> * 3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信 */ @RequestMapping("/cgi") public void cgi(HttpServletRequest request, HttpServletResponse response) { boolean isGet = request.getMethod().toLowerCase().equals("get"); // 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 try { if (isGet) { String signature = request.getParameter("signature"); // 时间戳 String timestamp = request.getParameter("timestamp"); // 随机数 String nonce = request.getParameter("nonce"); // 随机字符串 String echostr = request.getParameter("echostr"); log.info("signature = "+signature+" , timestamp = "+timestamp+ " , nonce = "+nonce+ " , echostr = "+echostr); String[] strArray = new String[] { token, timestamp, nonce }; Arrays.sort(strArray); StringBuilder sb = new StringBuilder(); for (String str : strArray) { sb.append(str); } // SHA1签名生成 MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(sb.toString().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); } if (hexstr.toString().equals(signature)) { response.getOutputStream().write(echostr.getBytes()); } }else{ // 进入POST聊天处理 // 将请求、响应的编码均设置为UTF-8(防止中文乱码) request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); // 接收消息并返回消息 String result = acceptMessage(request, response); // 响应消息 PrintWriter out = response.getWriter(); out.print(result); out.close(); } } catch (Exception ex) { log.error("微信帐号接口配置失败!", ex); ex.printStackTrace(); } } /** * 接受到微信接口数据 * @param request * @param response * @return */ private String acceptMessage(HttpServletRequest request, HttpServletResponse response) { // {CreateTime=1548042266, Event=user_enter_tempsession, ToUserName=gh_e6198220cbff, // FromUserName=oZvme4q2Oi7Dz3FChXc43kqw28, MsgType=event, SessionFrom=wxapp} String respMessage = ""; String inputLine = ""; String notityXml = ""; try { //接收数据 while((inputLine = request.getReader().readLine()) != null){ notityXml += inputLine; } // xml请求解析 JSONObject requestJson = JSON.parseObject(notityXml); log.info(">>>>>>>>>>>>>"+requestJson.toString()); // 发送方帐号(open_id) String fromUserName = requestJson.get("FromUserName").toString(); // 公众帐号 String toUserName = requestJson.get("ToUserName").toString(); // 消息类型 String msgType = requestJson.get("MsgType").toString(); // String Event = requestJson.get("Event").toString(); //SCAN 为扫描信息 VIEW 公众号底部点击事件 log.info("fromUserName = "+fromUserName+" , ToUserName = "+toUserName+ " , msgType = "+msgType); String access_token = wxXCXTempSend.getAccessToken();//获取access_token //公众号关注事件消息 if(msgType.equals("event")){ // log.info("公众号被关注事件.........."); if(StringUtils.isNotEmpty(access_token)){ WxUtil.sendKfLinkMessage(fromUserName,url,thumbUrl,access_token); //把封装好的信息推送给用户 } }else if(msgType.equals("text")){ // log.info("公众号接受文字.........."); if(StringUtils.isNotEmpty(access_token)){ WxUtil.sendKfLinkMessage(fromUserName,url,thumbUrl,access_token); } }else if(msgType.equals("image")){ // log.info("公众号接受图片.........."); WxUtil.sendKfLinkMessage(fromUserName,url,thumbUrl,access_token); } } catch (Exception e) { e.printStackTrace(); } return respMessage; } } springcloud_k8s_panzhihuazhihuishequ/common/pom.xml
@@ -124,6 +124,13 @@ <artifactId>json</artifactId> <version>20160810</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec --> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.9</version> </dependency> </dependencies> springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/constants/SecurityConstants.java
@@ -11,6 +11,7 @@ public static final String ROLE_ALL="springsecurity:role:all";//平台所有权限存储在redis public static final String ROLE_USER="springsecurity:role:";//某个用户的具体权限 public static final String ROLE_APPLETS="applets";//小程序用户通用角色 public static final String APPLETS_ACCESS_TOKEN ="APPLETS_ACCESS_TOKEN";//小程序获取的access_token } springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/utlis/HttpClientUtil.java
@@ -7,8 +7,10 @@ import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicHeader; import org.apache.http.util.EntityUtils; import org.springframework.util.ObjectUtils; @@ -20,6 +22,9 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.Iterator; import java.util.List; import java.util.Map; /** * @program: springcloud_k8s_panzhihuazhihuishequ @@ -131,4 +136,117 @@ } /** * http请求工具类,get请求 * * @param url * @param params * @param resonseCharSet * @return * @throws Exception */ public static String httpGet(String url, Map<String, Object> params, String... resonseCharSet) throws Exception { DefaultHttpClient defaultHttpClient = null; BufferedReader bufferedReader = null; try { defaultHttpClient = new DefaultHttpClient(); if (params != null) { StringBuilder stringBuilder = new StringBuilder(); Iterator<String> iterator = params.keySet().iterator(); String key; while (iterator.hasNext()) { key = iterator.next(); Object val = params.get(key); if (val instanceof List) { List v = (List) val; for (Object o : v) { stringBuilder.append(key).append("=").append(o.toString()).append("&"); } } else { stringBuilder.append(key).append("=").append(val.toString()).append("&"); } } stringBuilder.deleteCharAt(stringBuilder.length() - 1); url = url + "?" + stringBuilder.toString(); log.info("url:{}", url); } HttpGet httpGet = new HttpGet(url); httpGet.setHeader("Content-Type", "application/json;charset=ut-8"); HttpResponse httpResponse = defaultHttpClient.execute(httpGet); if (httpResponse.getStatusLine().getStatusCode() != 200) { String errorLog = "请求失败,errorCode:" + httpResponse.getStatusLine().getStatusCode(); log.info(errorLog); throw new Exception(url + errorLog); } //读取返回信息 String charSet = "utf-8"; if (resonseCharSet != null && resonseCharSet.length > 0) charSet = resonseCharSet[0]; String output; bufferedReader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent(), charSet)); StringBuilder dataBuilder = new StringBuilder(); while ((output = bufferedReader.readLine()) != null) { dataBuilder.append(output); } return dataBuilder.toString(); } catch (IOException e) { e.printStackTrace(); throw e; } finally { if (defaultHttpClient != null) defaultHttpClient.getConnectionManager().shutdown(); if (bufferedReader != null) bufferedReader.close(); } } /** * http请求工具类,post请求 * * @param url url * @param param 参数值 仅支持String * @return * @throws Exception */ public static String httpPost(String url, String param) throws Exception { DefaultHttpClient defaultHttpClient = null; BufferedReader bufferedReader = null; try { defaultHttpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(url); httpPost.setHeader("Content-Type", "application/json;charset=ut-8"); if (StringUtils.isNotBlank(param)) { log.info("参数值:{}", param); HttpEntity httpEntity = new StringEntity(param, "utf-8"); httpPost.setEntity(httpEntity); } HttpResponse httpResponse = defaultHttpClient.execute(httpPost); if (httpResponse.getStatusLine().getStatusCode() != 200) { String errorLog = "请求失败,errorCode:" + httpResponse.getStatusLine().getStatusCode(); log.info(errorLog); throw new Exception(url + errorLog); } //读取返回信息 String output; bufferedReader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent(), "utf-8")); StringBuilder stringBuilder = new StringBuilder(); while ((output = bufferedReader.readLine()) != null) { stringBuilder.append(output); } return stringBuilder.toString(); } catch (IOException e) { e.printStackTrace(); throw e; } finally { if (defaultHttpClient != null) defaultHttpClient.getConnectionManager().shutdown(); if (bufferedReader != null) bufferedReader.close(); } } } springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/utlis/WxUtil.java
New file @@ -0,0 +1,26 @@ package com.panzhihua.common.utlis; import com.alibaba.fastjson.JSON; import java.util.HashMap; import java.util.Map; public class WxUtil { //客服消息推送地址 public final static String kf_url = "https://api.weixin.qq.com/cgi-bin/message/custom/send"; public static String sendKfLinkMessage(String openid,String url,String thumbUrl,String access_token)throws Exception{ Map<String,Object> map_content = new HashMap<>(); map_content.put("title","社区福利一分购"); map_content.put("description","点击参与社区一分钱抢购活动"); map_content.put("url",url);//跳转地址 map_content.put("thumb_url",thumbUrl);//图片地址 Map<String,Object> map = new HashMap<>(); map.put("touser",openid); map.put("msgtype","link"); map.put("link",map_content); String content = JSON.toJSONString(map); return HttpClientUtil.httpPost(kf_url+"?access_token="+access_token,content); } } springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/utlis/WxXCXTempSend.java
New file @@ -0,0 +1,89 @@ package com.panzhihua.common.utlis; import com.alibaba.fastjson.JSON; import com.panzhihua.common.constants.SecurityConstants; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Component; import java.io.IOException; import java.util.Map; import java.util.concurrent.TimeUnit; @Slf4j @Component public class WxXCXTempSend { private static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential"; public static final String APP_ID = "wx0cef797390444b75"; private static final String APP_SECRET = "c7ea9aaa7e391a487e8a5b9ba61045d1"; @Autowired private StringRedisTemplate redisTemplate; /** * 获取小程序token,(ps:0=token获取失败) * * @return */ 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); } }else{ accessToken = getAppAccessToken(); valueOperations.set(SecurityConstants.APPLETS_ACCESS_TOKEN, accessToken,110, TimeUnit.MINUTES); } return accessToken; } private String getAppAccessToken() 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 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); } } springcloud_k8s_panzhihuazhihuishequ/zuul/src/main/java/com/panzhihua/zuul/filters/JWTAuthenticationTokenFilter.java
@@ -77,8 +77,9 @@ boolean refreshToken = requestURI.contains("refreshToken"); boolean logout = requestURI.contains("logout"); boolean wxPay = requestURI.contains("wxNotify"); boolean wxCgi = requestURI.contains("cgi"); SafeboxRequestWrapper safeboxRequestWrapper = new SafeboxRequestWrapper(request); if (login||doc||css||js||ui||swagger||ico||docs||error||refreshToken||useragreement||wxPay) { if (login||doc||css||js||ui||swagger||ico||docs||error||refreshToken||useragreement||wxPay||wxCgi) { //什么也不做 } else { // 获取请求头中JWT的Token springcloud_k8s_panzhihuazhihuishequ/zuul/src/main/java/com/panzhihua/zuul/filters/SercuritFilter.java
@@ -76,9 +76,10 @@ boolean docs = !requestUrl.contains("docs"); boolean login = !requestUrl.contains("login"); boolean wxNotify = !requestUrl.contains("wxNotify"); boolean wxCgi = !requestUrl.contains("cgi"); boolean refreshToken = !requestUrl.contains("refreshToken"); boolean useragreement = !requestUrl.contains("useragreement"); if (contains&&docs&&login&&refreshToken&&useragreement&&wxNotify) { if (contains&&docs&&login&&refreshToken&&useragreement&&wxNotify&&wxCgi) { configAttributes.add(new SecurityConfig(SecurityConstants.ROLE_APPLETS)); } return configAttributes;