客服消息转发到网页版客服工具

本文详细介绍了如何实现微信小程序点击客服按钮跳转到聊天系统,并通过开发者服务器接收消息推送。步骤包括配置服务器地址、令牌和消息加密密钥,以及验证消息来源。重点讲解了PHP代码实现接收和处理文本、图片、事件等不同类型的消息,特别注意了XML格式和错误处理。此外,还提到了可能出现的问题,如网页版客服接收不到消息,以及解决中文乱码的方法。
摘要由CSDN通过智能技术生成

更多信息可查看网站https://www.lelee.top/

1、首先实现小程序点击客服跳转至聊天系统
2、根据文档可查询消息推送功能、消息推送地址

3、有三种方式可实现微信小程序推送消息功能:
①、开发者服务器接受消息推送
②、云函数接收消息推送
③、云托管服务接收消息推送

根据自己的需求采用不同的实现方法。本文采用的为第一种 开发者服务器接收消息推送
第一步:填写服务器配置

这是我自己配置好的数据参数
URL(服务器地址):是自己服务器上的地址,注意下方系统描述信息
Token(令牌):自己设定,相当于密码盐
EncodingAESKey(消息加密密钥):随机生成就行,主要用于后台加密方式解码使用
消息加密方式:根据自己需求选择、注意下方系统描述信息
数据格式:建议选择xml。所查询的资料均显示json方式存在一定的问题。主要原因返回的头部不符合http标准。
返回json格式header头应该是

Content-Type:application/json,

而微信的选json还是

Content-Type:text/xml

第二步:验证消息是否来自微信服务器,验证方法文档上面已经存在

 第三步:功能实现,参考(https://segmentfault.com/a/1190000013533165
主要代码如下、复制即可实现功能(下面有注意事项):

<?php 
define("TOKEN","你小程序自己设置的Token");//填写自己设置的Token

class wechatAPI{

    const APP_ID = '你自己的appid';
    const APP_SECRET = '你自己的appsecret';
    
    //用于小程序第一步验证返回
    public function isValid(){
        $echoStr = $_GET["echostr"];
        if ($this->checkSignature()) {
            echo $echoStr;
            exit;
        }
    }
    
    public function checkSignature(){
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];
        $token = TOKEN;
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode( $tmpArr );
        $tmpStr = sha1( $tmpStr );
        if( $tmpStr == $signature ){
            return true;
        }else{
            return false;
        }
    }
    
    
    public function send($data){
        $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=".$this->getAccessToken();
        $data = urldecode(json_encode($data));
        $this->curl_post($url,$data);
    }
    
    //xml数据转数组
    public function xml2Array($contents = NULL, $encoding = 'UTF-8', $get_attributes = 1, $priority = 'tag'){
        if (!$contents) 
        {
            return array();
        }
        if (!function_exists('xml_parser_create'))
        {
            return array ();
        }
        $parser = xml_parser_create('');
        xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $encoding);
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
        xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
        xml_parse_into_struct($parser, trim($contents), $xml_values);
        xml_parser_free($parser);
        if (!$xml_values)
            return array(); 
        $xml_array = array ();
        $parents = array ();
        $opened_tags = array ();
        $arr = array ();
        $current = & $xml_array;
        $repeated_tag_index = array (); 
        foreach ($xml_values as $data)
        {
            unset ($attributes, $value);
            extract($data);
            $result = array ();
            $attributes_data = array ();
            if (isset ($value))
            {
                if ($priority == 'tag')
                    $result = trim($value);
                else
                    $result['value'] = trim($value);
            }
            if (isset ($attributes) && $get_attributes) {
                foreach ($attributes as $attr => $val)
                {
                    if ($priority == 'tag')
                        $attributes_data[$attr] = $val;
                    else
                        $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
                }
            }
            if ($type == "open")
            { 
                $parent[$level -1] = & $current;
                if (!is_array($current) || (!in_array($tag, array_keys($current)))) {
                    $current[$tag] = $result;
                    if ($attributes_data)
                        $current[$tag . '_attr'] = $attributes_data;
                    $repeated_tag_index[$tag . '_' . $level] = 1;
                    if (isset($tag) && $tag && isset($current[$tag])) {
                        $current = & $current[$tag];
                    }
                }
                else
                {
                    if (isset ($current[$tag][0]))
                    {
                        $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
                        $repeated_tag_index[$tag . '_' . $level]++;
                    }
                    else
                    { 
                        $current[$tag] = array (
                            $current[$tag],
                            $result
                        ); 
                        $repeated_tag_index[$tag . '_' . $level] = 2;
                        if (isset ($current[$tag . '_attr']))
                        {
                            $current[$tag]['0_attr'] = $current[$tag . '_attr'];
                            unset ($current[$tag . '_attr']);
                        }
                    }
                    $last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1;
                    $current = & $current[$tag][$last_item_index];
                }
            }
            elseif ($type == "complete")
            {
                if (!isset ($current[$tag]))
                {
                    $current[$tag] = $result;
                    $repeated_tag_index[$tag . '_' . $level] = 1;
                    if ($priority == 'tag' && $attributes_data) {
                        $current[$tag . '_attr'] = $attributes_data;
                    }
                }
                else
                {
                    if (isset ($current[$tag][0]) && is_array($current[$tag])) {
                        $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
                        if ($priority == 'tag' && $get_attributes && $attributes_data) {
                            $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
                        }
                        $repeated_tag_index[$tag . '_' . $level]++;
                    }
                    else
                    {
                        $current[$tag] = array (
                            $current[$tag],
                            $result
                        ); 
                        $repeated_tag_index[$tag . '_' . $level] = 1;
                        if ($priority == 'tag' && $get_attributes) {
                            if (isset ($current[$tag . '_attr']) && is_array($current[$tag]))
                            { 
                                $current[$tag]['0_attr'] = $current[$tag . '_attr'];
                                unset ($current[$tag . '_attr']);
                            }
                            if ($attributes_data)
                            {
                                $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
                            }
                        }
                        $repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken
                    }
                }
            }
            elseif ($type == 'close')
            {
                $current = & $parent[$level -1];
            }
        }
        return ($xml_array);
    }



    //获取accesstoken
    public function getAccessToken() {
        $tokenFile = "access_token.txt";
        $data = json_decode(file_get_contents($tokenFile,FILE_USE_INCLUDE_PATH));
        //accesstoken有效期是7200秒,这里用到的文件缓存
        //注意:文件权限问题
        if (!$data->expire_time || $data->expire_time < time()) {
          
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".self::APP_ID."&secret=".self::APP_SECRET;
            
            $res =  json_decode(file_get_contents($url));
            if($res) {
                $arr = array();
                $access_token = $res->access_token;
                $arr['expire_time'] = time() + 7000;
                $arr['access_token'] = $access_token;
                $fp = fopen($tokenFile, "w");
                fwrite($fp, json_encode($arr));
                fclose($fp);
            }
        } else {
            $access_token = $data->access_token;
        }
        
        return $access_token;
    }
    //post发送json数据
    public function curl_post($url,$post_data){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
        $res = curl_exec($ch);
        
        if(!$res){
            throw new Exception('发送消息失败:'.curl_error($ch));
        }
        curl_close($ch);
    }

    

  
};


$wechatObj = new wechatAPI();

//注意:第一步验证时打开,验证完成之后就可以注释了
// $wechatObj->isValid();

if($wechatObj->checkSignature() === true){

    $xmlstring = file_get_contents("php://input");
    $accept_info = $wechatObj->xml2Array($xmlstring)['xml'];
    
    if($accept_info){
        $ToUserName = $accept_info['ToUserName'];
        $FromUserName = $accept_info['FromUserName'];
        $CreateTime = $accept_info['CreateTime'];
        $MsgType = $accept_info['MsgType'];
        //$MsgId = $accept_info['MsgId'];
        // $Encrypt = $accept_info['Encrypt'];
        
        $data = array();
        if($MsgType == 'text'){//接收文本
            
            $Content = $accept_info['Content'];//文本内容
    
            // "touser": "OPENID",
            // "msgtype": "link",
            // "link": {
            //       "title": "Happy Day",
            //       "description": "Is Really A Happy Day",
            //       "url": "URL",
            //       "thumb_url": "THUMB_URL"
            // }
            if($Content === '图文') {
                $data['touser'] = $FromUserName;
                $data['msgtype'] = 'link';
                $data['link']['title'] = urlencode('文章标题');
                $data['link']['description'] = urlencode('好文章要分享');
                $data['link']['url'] = 'https://segmentfault.com';
                $data['link']['thumb_url'] = 'https://static.segmentfault.com/v-5a7c12fe/global/img/logo-b.svg';
                $wechatObj->send($data);exit;
            }
            //else if 可以做好多事
            
        }else if($MsgType === 'image') {//接收图片

        }else if($MsgType === 'event') {//进入客服窗口事件
            $Event = $accept_info['Event'];
            $SessionFrom = $accept_info['SessionFrom'];
            if($Event == 'user_enter_tempsession') {
                $data['touser'] = $FromUserName;
                $data['msgtype'] = 'text';
                $data['text']['content'] = urlencode('您好很高兴为您服务');//urlencode 解决中文乱码问题
                $wechatObj->send($data);exit;
            }
        }
        
        echo '<xml><ToUserName><![CDATA['.$FromUserName.']]></ToUserName><FromUserName><![CDATA['.$ToUserName.']]></FromUserName><CreateTime>'.$CreateTime.'</CreateTime><MsgType><![CDATA[transfer_customer_service]]></MsgType></xml>';
    }

}

 注意事项:
1、最后返回数据的时候,网页版客服总是接受不到推送消息。有可能是xml格式的问题。采用以下方式即可实现

 function xmlSafeStr($str)
    {
        return '<![CDATA['.preg_replace("/[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]/",'',$str).']]>';
    }

    /**
     * 数据XML编码
     * @param mixed $data 数据
     * @return string
     */
    function data_to_xml($data) {
        $xml = '';
        foreach ($data as $key => $val) {
            is_numeric($key) && $key = "item id=\"$key\"";
            $xml    .=  "<$key>";
            $xml    .=  ( is_array($val) || is_object($val)) ? $this->data_to_xml($val)  : $this->xmlSafeStr($val);
            list($key, ) = explode(' ', $key);
            $xml    .=  "</$key>";
        }
        return $xml;
    }

2、微信返回数据类型主要有4中、类型判断依据请查看文档 返回类型
文档介绍了返回不同数据时的数据结构,根据需求进行数据解析。

3、接口转发网页版微信客服文档 转发消息

 需要注意的是:
①、FromUserName 为小程序原始ID CreateTime 为原消息发送时的时间戳
②、消息一旦转发值微信客服,需客服30分钟内无回应时才会继续返回至接口,期间不会转发接口

4、$data'text' = urlencode('您好很高兴为您服务');//urlencode 解决中文乱码问题
urlencode可能会导致微信服务平台返回40003 错误信息。去除urlencode函数,在json_encode数据的时候添加参数 JSON_UNESCAPED_UNICODE 即可避免(php版本在5.4以上)

与君共勉!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值