huanghongfa
2021-04-23 ec382a737f59877abe9fce022a9124a7897e5dd5
小程序新增客服功能
5个文件已修改
3个文件已添加
400 ■■■■■ 已修改文件
springcloud_k8s_panzhihuazhihuishequ/applets/src/main/java/com/panzhihua/applets/api/WxMessagePushApi.java 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/pom.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/constants/SecurityConstants.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/utlis/HttpClientUtil.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/utlis/WxUtil.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/utlis/WxXCXTempSend.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/zuul/src/main/java/com/panzhihua/zuul/filters/JWTAuthenticationTokenFilter.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/zuul/src/main/java/com/panzhihua/zuul/filters/SercuritFilter.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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;