微信小程序接入客服消息后台开发

需求

小程序增加关注公众号功能,点击跳转至客服聊天页面,自动弹窗出现引导语以及公众号二维码;

image.png

实现步骤

1. 小程序前端 相对简单,设置button type即可
点击button会进入到小程序客服聊天页面,这时小程序会
向预先好的服务端接口发送信息,首次发送信息类型为【进入事件】


2. 配置服务器地址以及验证
路径:小程序公众平台 > 小程序管理页面 > 开发 > 开发设置 > 消息推送
首先开启消息推送,接着是配置url以及token等信息
注意,配置url需要进行验证。提交验证后微信会发送get请求
至你填写的服务器域名以及具体接口,需要在接口中校验请求
是否来之微信服务器,将指定数据返回;

image.png

3. 校验接口以及响应信息代码
GET请求仅用于初次配置时验证;
POST请则为每次用户打开微信客服页面,以及用户在客服中聊天中发送的每一条信息都会请求到接口,可进行处理;

接收微信请求时遇到一点小坑,配置后台url信息时如选择JSON格式传输数据,在springMVC中无法获取到消息类型等参数,在request中查看hard以及body中页没有参数,时间紧没来得及深入排查,最终使用XML格式就没有问题……

 /**
     * 处理小程序打开客服请求
     * GET 验证调用者是否为小程序
     * POST 信息接收响应
     *
     * @return
     */
    @ResponseBody
    @RequestMapping("handleCustomerServiceMsg")
    public String handleCustomerServiceMsg(HttpServletRequest request) {
        logger.info("customerService >>>>> 收到小程序客服消息请求 ");

        String resultStr = "success";


        try{
            if("GET".equals(request.getMethod().toUpperCase())){
                CustomerServiceVo customerServiceVo = new CustomerServiceVo();

                String signature = request.getParameter("signature");
                // 时间戳
                String timestamp = request.getParameter("timestamp");
                // 随机数
                String nonce = request.getParameter("nonce");
                // 随机字符串
                String echostr = request.getParameter("echostr");

                customerServiceVo.setSignature(signature);
                customerServiceVo.setTimestamp(timestamp);
                customerServiceVo.setNonce(nonce);
                customerServiceVo.setEchostr(echostr);


                logger.info("customerService >>>>>  {} ",JSONObject.toJSONString(customerServiceVo));

                if(customerServiceVo == null ||
                        StringUtils.isBlank(customerServiceVo.getSignature()) ||
                        StringUtils.isBlank(customerServiceVo.getTimestamp()) ||
                        StringUtils.isBlank(customerServiceVo.getNonce()) ||
                        StringUtils.isBlank(customerServiceVo.getEchostr())
                        ){
                    logger.info("customerService >>>>> error parameter is empty");
                    return resultStr;

                }

                String[] strArray = new String[] { customerServiceToken, customerServiceVo.getTimestamp(), customerServiceVo.getNonce() };
                Arrays.sort(strArray);
                StringBuilder sb = new StringBuilder();
                for (String str : strArray) {
                    sb.append(str);
                }

                //10178941421571798817xcx-1570788125909-a742429ba186d
                String encrypt = SHA1Util.encode(sb.toString());

                //校验成功,原样返回随机字符串
                if (encrypt.equals(customerServiceVo.getSignature())) {
                    return customerServiceVo.getEchostr();
                }

            }else{
                request.setCharacterEncoding("UTF-8");
                Map requestMap = MessageUtil.parseXML(request);
                CustomerServiceVo customerServiceVo = (CustomerServiceVo) Utils.mapToJavaBean(CustomerServiceVo.class, requestMap);

                logger.info("xml参数为{}",JSONObject.toJSONString(customerServiceVo));

                // xml请求解析  处理客服消息
                logger.info("customerService >>>>> 处理客服消息  parameters : {}",JSONObject.toJSONString(customerServiceVo));
                return customerServiceService.acceptMessage(customerServiceVo);

            }

        }catch (Exception e){
            logger.info("{}",e);
        }
        return resultStr;
    }

4. 发送客服消息
上面步骤做好之后已经能接收到客服消息了;接下来我们需要对
收到的客服消息进行处理。我的需求是需要发送一张公众号二维
码图片以及一段文本内容;

小程序发送消息API

customerServiceMessage.send
  注意:小程序对于该接口发送客服消息有限制,必须用户主动发送消息之后才能回复;
  另外发送图片消息,需要mediaID,mediaID必须调用微信API上传素材之后获得,而且三天后失效,需要定时更新!
 /**
     * 处理,回复客服消息
     * @param customerServiceVo
     * @return
     * @throws Exception
     */
    public String acceptMessage(CustomerServiceVo customerServiceVo) throws Exception{
        String resultStr = "success";

        // 消息类型
        String msgType = customerServiceVo.getMsgType();
        String touser = customerServiceVo.getFromUserName();
        //公众帐号  小程序原始码?
        String toUserName = customerServiceVo.getToUserName();


        if(StringUtils.isBlank(msgType) || StringUtils.isBlank(touser)){
            throw new Exception("parameter is error");
        }

        // 除事件之外的类型,都发送关注公众号消息
        if(!"event".equals(msgType)){

            //获取mediaId,mediaId需要先使用微信上传素材接口上传指定图片后获取到mediaId,
            // 且每次上传的素材3天后失效,需要定时更新
            String wxMediaId = (String)redisTemplate.opsForValue().get("WX_MEDIA_ID");

            if(StringUtils.isBlank(wxMediaId)){
                logger.error("wx mediaId fail ");
            }

            //发送二维码图片
            JSONObject imageJson = new JSONObject();
            imageJson.put("touser",touser);
            imageJson.put("msgtype","image");
            Map imageMap = new HashMap();
            imageMap.put("media_id",wxMediaId);
            imageJson.put("image",imageMap);
            wxApiService.sendCustom(imageJson);


            // 文本消息
            JSONObject textJson = new JSONObject();
            Map contentMap = new HashMap<>();
            contentMap.put("content","我是文本消息~");
            textJson.put("touser",touser);
            textJson.put("text",contentMap);
            textJson.put("msgtype","text");
            wxApiService.sendCustom(textJson);

            // 其它类型消息,暂时不作处理
        }else{
            logger.error("客服信息>>>>> 用户发送消息类型为{},暂不作处理",msgType);

        }
        return resultStr;
    }


/**
     * 向微信客服号发送消息
     * @param paramJson
     */
    public boolean sendCustom(JSONObject paramJson) {

        try{
            String access_token = getAccess_token();

            String url = wxSendCustomURL+access_token;

            String result = HttpUtils.postJsonString(url, paramJson);

            JSONObject repoJson = JSONObject.parseObject(result);
            if(repoJson == null || repoJson.get("errcode") == null ){
                logger.info("============微信发送客服接口响应错误{}============",result);
                return false;
            }

            Integer errcode = (Integer)repoJson.get("errcode");
            if(errcode != 0){
                logger.info("=====微信发送客服接口:校验失败:{}======",repoJson.get("errmsg"));
                return false;
            }

        }catch (Exception e){
            logger.info("[发送客服消息失败]:{}",e);
            return false;
        }

        return  true;

    }

5.关于meidaId,采用定时任务上传放在缓存中,三天刷新一次

 /**
     * 上传微信临时素材
     */
    public String uploadWechatTeacherImages() {

        String mediaId = "";

        try{
            //读取resource下图片
            ClassPathResource classPathResource = new ClassPathResource("images/xxxxRcode.png");
            InputStream inputStream = classPathResource.getInputStream();

            //存入临时文件夹
            File file = new File("/opt/zion/image_temp/xxxQRcode.png");
            Utils.inputStreamToFile(inputStream,file);

            //发送图片
            String url = uploadMediaUrl + getAccess_token();
            String result = HttpUtils.uploadMedia(file, url);
            logger.info("upload weixin media result {}",result);

            if(StringUtils.isNotBlank(result)){
                JSONObject resultJson = JSONObject.parseObject(result);
                mediaId = (String)resultJson.get("media_id");
            }

        }catch (Exception e){

            logger.error("上传微信临时素材失败 {}",e);
        }


        return mediaId;
    }


  public static String uploadMedia(File file, String url) {
        try{
            logger.info(">>>>>>>send upload weixin media url {}",url);

            RestTemplate restTemplate = new RestTemplate();
            url += "&type=image";

            HttpHeaders headers = new HttpHeaders();
            MediaType type = MediaType.parseMediaType("multipart/form-data");
            headers.setContentType(type);
            FileSystemResource fileSystemResource = new FileSystemResource(file);
            MultiValueMap form = new LinkedMultiValueMap<>();
            form.add("file", fileSystemResource);
            form.add("filename",file.getName());
            org.springframework.http.HttpEntity> files = new org.springframework.http.HttpEntity<>(form, headers);



            return restTemplate.postForObject(url, files, String.class);

        }catch (Exception e){
            logger.error("send weixin media error {}",e);
            return "fail";
        }

    }

最后,有问题可以私信我~

你可能感兴趣的:(微信小程序接入客服消息后台开发)