小程序消息推送及客服(JAVA后台)

小程序客服及消息推送开发(后台JAVA)

最近公司在做小程序,涉及到客服及消息推送,简单的记录下开发过程及心得

客服

小程序自带的有客服功能只需要开启就行了.

小程序消息推送及客服(JAVA后台)_第1张图片
选择开启后即可使用.

消息推送

首先在开发 开发设置中配置消息推送

小程序消息推送及客服(JAVA后台)_第2张图片
URL: 服务器 设置自己服务器的路径.
Token(令牌): 自己设置,后面再自己的URL需对应.
EncodingAESkey(消息加密秘钥):涉及到加密解密,自己设置,推荐使用随机生成.
消息加密方式: 我这里选择的是明文模式.
数据格式: XML 和 JSON 都行,我选择的是JSON(听说JSON有问题,不过目前没遇到).

配置完后点击保存配置,此时微信端会发送一个GET请求到之前配置的URL路径中进行校检.废话不说直接贴代码

 // 与接口配置信息中的Token要一致
 private static String WECHAT_TOKEN = "ZIJIESHANYAO";
@RequestMapping("/checkToken")
    public void get(HttpServletRequest request, HttpServletResponse response) throws Exception {

        boolean isGet = request.getMethod().toLowerCase().equals("get");
        PrintWriter print;
        if (isGet) {
            // 微信加密签名
            String signature = request.getParameter("signature");
            // 时间戳
            String timestamp = request.getParameter("timestamp");
            // 随机数
            String nonce = request.getParameter("nonce");
            // 随机字符串
            String echostr = request.getParameter("echostr");
            // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
            if (signature != null && checkSignature(signature, timestamp, nonce)) {
                System.out.println("111111111");
                System.out.println("jiaoyanchenggong");
                try {
                    print = response.getWriter();
                    print.write(echostr);
                    print.flush();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {

            }
        } else {

        }
    }
     /**
     * 验证签名
     *
     * @param signature
     * @param timestamp
     * @param nonce
     * @return
     */
    public static boolean checkSignature(String signature, String timestamp, String nonce) {
        String[] arr = new String[]{WECHAT_TOKEN, timestamp, nonce};
        // 将token、timestamp、nonce三个参数进行字典序排序
        // Arrays.sort(arr);
        sort(arr);
        StringBuilder content = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            content.append(arr[i]);
        }
        MessageDigest md = null;
        String tmpStr = null;

        try {
            md = MessageDigest.getInstance("SHA-1");
            // 将三个参数字符串拼接成一个字符串进行sha1加密
            byte[] digest = md.digest(content.toString().getBytes());
            tmpStr = byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        content = null;
        // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信
        return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param byteArray
     * @return
     */
    private static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

    /**
     * 将字节转换为十六进制字符串
     *
     * @param mByte
     * @return
     */
    private static String byteToHexStr(byte mByte) {
        char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];
        String s = new String(tempArr);
        return s;
    }

    public static void sort(String a[]) {
        for (int i = 0; i < a.length - 1; i++) {
            for (int j = i + 1; j < a.length; j++) {
                if (a[j].compareTo(a[i]) < 0) {
                    String temp = a[i];
                    a[i] = a[j];
                    a[j] = temp;
                }
            }
        }
    }

校检成功后就可以选择模板进行设置发送消息了,至于如何设置选择模板,这里不多说,直接看下就知道了,下面说下消息推送的具体实现.
第一步 : 获取模板 ID 自己去选择适合自己的模板 https://mp.weixin.qq.com
第二步 : 获取form_id ,前端设置按钮,点击按钮提交表单可以获取 formId(对于后台,直接去找前端要就行了).
第三步 : 调用接口具体的实现.

/*
     * 微信小程序推送单个用户
     * */
    @RequestMapping(value = "/Phsu", method = RequestMethod.POST)
    @ResponseBody
    public String pushOneUser(String openid, String formid, Long orderId) {
        //获取access_token
        String access_token = getAccess_token(Global.appId, Global.secret);//这里是自己小程序的appId和secretKey
        String url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send" +
                "?access_token=" + access_token;

  		//拼接推送的模版
         WxMssVo wxMssVo = new WxMssVo();
         wxMssVo.setTouser(openid);//用户openid
         wxMssVo.setTemplate_id("DkA9fB-xmODJLVf1JvRtWdxr5-iTGETOfV5_6Nuk8NU");//模版id
         wxMssVo.setForm_id(formid);//formid

         Map<String, TemplateDataVo> m = new HashMap<>();

         if (order.getStatus().equals(20)) {
                List<OrderProduct> orderProducts = order.getOrderProducts();
                String ProductName = null;
                for (OrderProduct orderProduct : orderProducts) {
                    ProductName = orderProduct.getName();
                }
                TemplateDataVo keyword1 = new TemplateDataVo();
                keyword1.setValue(ProductName);//商品名称
                m.put("keyword1", keyword1);
                wxMssVo.setData(m);
                System.out.println(keyword1.getValue() + ":name");

                TemplateDataVo keyword2 = new TemplateDataVo();
                keyword2.setValue(order.getOrderSn() + "");//订单编号
                m.put("keyword2", keyword2);
                wxMssVo.setData(m);
                System.out.println(keyword2.getValue() + ":bianhao");

                TemplateDataVo keyword3 = new TemplateDataVo();
                keyword3.setValue(order.getTotalPrice() + "");//订单金额
                m.put("keyword3", keyword3);
                wxMssVo.setData(m);
                System.out.println(keyword3.getValue() + ":jine");

                TemplateDataVo keyword4 = new TemplateDataVo();
                keyword4.setValue(order.getPoyTime() + "");//支付时间
                m.put("keyword4", keyword4);
                wxMssVo.setData(m);
                System.out.println(keyword4.getValue() + ":time");
            }
            ResponseEntity<String> responseEntity =
                    restTemplate.postForEntity(url, wxMssVo, String.class);

            System.out.println(responseEntity.getBody() + "wancheng");
            //发送成功
            return responseEntity.getBody()
    }
/*
     * 获取access_token
     * appid和appsecret到小程序后台获取,当然也可以让小程序开发人员给你传过来
     * */
    public String getAccess_token(String appid, String appsecret) {
        //获取access_token
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" +
                "&appid=" + appid + "&secret=" + appsecret;
        String json = restTemplate.getForObject(url, String.class);
        AccessToken accessToken = new Gson().fromJson(json, AccessToken.class);
        return accessToken.getAccess_token();
    }

至此消息推送完成.
小程序消息推送及客服(JAVA后台)_第3张图片

但是随后发现之前配置的客服不能使用了

小程序消息推送及客服(JAVA后台)_第4张图片
看下文档, https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/customer-message/trans.html 发现
如果配置了消息推送,所有用户发给小程序的消息都会被转发到已填写的服务器地址中,此时我们需要处理的是将微信转发到后台的消息取出返回给客服,并将客服消息返回给用户.
官网上有对各种消息的具体格式.https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/customer-message/receive.html
下面我只处理文本形式.
当微信将消息推送到后台,会推送到之前配置的URL 地址,以POST请求的方式.

/**
     * 接收微信后台发来的用户消息
     * @return
     */
    @RequestMapping(value = "/checkToken", method = RequestMethod.POST)
    @ResponseBody
    public String receiveMessage(@RequestBody Map<String, Object> msg) {
     
        //获取token
        String access_token = getAccess_token(Global.appId, Global.secret);
        System.out.println("access_token:--------" + access_token);

        //用户openId
        String fromUserName = msg.get("FromUserName").toString();
        String createTime = msg.get("CreateTime").toString();
        String toUserName = msg.get("ToUserName").toString();
        String msgType = msg.get("MsgType").toString();
        if (msgType.equals("text")) { //收到的是文本消息,并将消息返回给客服
            HashMap<String, Object> resultMap = new HashMap<>();
            resultMap.put("ToUserName", fromUserName);
            resultMap.put("FromUserName", toUserName);
            resultMap.put("CreateTime", Long.parseLong(createTime));
            resultMap.put("MsgType", "transfer_customer_service");
            String json = JSON.toJSONString(resultMap);
            com.alibaba.fastjson.JSONObject result = com.alibaba.fastjson.JSONObject.parseObject(json);
            return result.toString();
        }
        //客服方面,也回复一个文本消息
        JSONObject text = new JSONObject();
        text.element("content", msg.get("MsgType"));
        JSONObject json = new JSONObject();
        json.element("touser", toUserName);
        json.element("text", text);
        json.element("msgtype", "text");
        //发送aip
        sendMsToCustomer(access_token, json);
        return "success";
    }
 /**
     * 用户发送消息给客服
     *
     * @param json 消息的参数
     */
    private void sendMsToCustomer(String access_token, JSONObject json) {

        RestTemplate restTemplate = new RestTemplate();

        //access_token
        String result = restTemplate.postForEntity("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" +
                        access_token, json, String.class).getBody();
    }

小程序消息推送及客服(JAVA后台)_第5张图片
至此,消息推送及客服全部完成.

总结

其实整体流程还是比较简单的,只是开启消息推送的有点坑之外其他的还好说,做之前多看几遍文档熟悉,新人第一次写博客如有错误请指正,共同学习.

你可能感兴趣的:(小程序消息推送及客服(JAVA后台))