1. 程式人生 > >微信小程式---客服訊息介面呼叫,拿來即用

微信小程式---客服訊息介面呼叫,拿來即用

  • <button open-type="contact" class='contactService' session-from="{{'https://https://mp.weixin.qq.com/debug/wxadoc/introduction/image/x11.png'}}" hover-class="none">聯絡客服獲取二維碼</button> 
  • 當用戶在客服會話傳送訊息(或進行某些特定的使用者操作引發的事件推送時),微信伺服器會將訊息(或事件)的資料包(JSON或者XML格式)POST請求開發者填寫的URL。開發者收到請求後可以使用傳送客服訊息介面進行非同步回覆。

  • 微信伺服器在將使用者的訊息發給小程式的開發者伺服器地址(開發設定處配置)後,微信伺服器在五秒內收不到響應會斷掉連線,並且重新發起請求,總共重試三次,如果在除錯中,發現使用者無法收到響應的訊息,可以檢查是否訊息處理超時。關於重試的訊息排重,有msgid的訊息推薦使用msgid排重。事件型別訊息推薦使用FromUserName + CreateTime 排重。

  • 伺服器收到請求必須做出下述回覆,這樣微信伺服器才不會對此作任何處理,並且不會發起重試,否則,將出現嚴重的錯誤提示。詳見下面說明:

    1、直接回復success(推薦方式)
    2、直接回復空串(指位元組長度為0的空字串,而不是結構體中content欄位的內容為空)
    
  • 一旦遇到以下情況,微信都會在小程式會話中,向用戶下發系統提示“該小程式客服暫時無法提供服務,請稍後再試”:

    1、開發者在5秒內未回覆任何內容
    2、開發者回覆了異常資料
    
  • 訊息推送配置

  • 填寫伺服器配置

  • 驗證訊息的確來自微信伺服器

  • 開發者提交資訊後,微信伺服器將傳送GET請求到填寫的伺服器地址URL上,GET請求攜帶引數如下表所示:

    點選提交認證的時候,需要呼叫到如下方法,進行校驗,校驗通過,代表配置成功
  • //例項化物件
        $vyuanCustom = new vyuanCustomAPI();
        //注意:第一步驗證時開啟,驗證完成之後就可以註釋了
        $vyuanCustom->isValid();
  • 詳細程式碼解析

<?php
    //伺服器配置介面地址 
    define("TOKEN", "vyuan");       //定義token
    define("WXPAY_APPID", '***********');     //替換為自己的APPID
    define("WXPAY_APPSECRET", '******************'); //替換為自己的APPSECRET

    class vyuanCustomAPI{        
        //用於小程式後臺第一步驗證返回,驗證成功後便可註釋
        public function isValid(){
            $echoStr = $_GET["echostr"];
            if ($this->checkSignature()) {
                echo $echoStr;
                exit;
            }
        }
        
        //官方提供的驗證demo
        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;
                    }
                }

                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]++; 
                        }
                    }
                }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=".WXPAY_APPID."&secret=".WXPAY_APPSECRET;
                
                $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);
        }  
        
        //進入客服視窗,如果需要主動發起客服訊息型別為圖片,則需要獲取media_id
        public function getMedia_id($imageurl){
             $foldername = date('Y-m-d',time()); //定義資料夾目錄
             $path = __DIR__.'/static/image/Code/'.$foldername.'/'; //伺服器存放目錄
             if(!is_dir($path)){
                 mkdir($path,0777,true);
             }else{
                 chmod($path,0777);
             }

             //下載二維碼到本地
             $imageInfo = $this -> getImage($imageurl,$path);
             $imageurl = $imageInfo['save_path'];
                    
             $post_url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token={$this->getAccessToken()}&type=image";
             $ch = curl_init();
             curl_setopt($ch, CURLOPT_URL, $post_url);
             curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
             curl_setopt($ch, CURLOPT_POST, 1);
             curl_setopt($ch, CURLOPT_POSTFIELDS, ['media'=>'@'.$imageurl]);
             $res = curl_exec($ch);
             $a = json_decode($res);

             $media_id = $a->media_id;
            return $media_id;
        }

        //下載二維碼
        public function getImage($url,$save_dir,$filename='',$type=0){
            if(trim($url)==''){
                return array('file_name'=>'','save_path'=>'','error'=>1);
            }
            if(trim($filename)==''){//儲存檔名
                $ext=strrchr($url,'.');
                if($ext!='.gif'&&$ext!='.jpg'){
                    return array('file_name'=>'','save_path'=>'','error'=>3);
                }
                $filename=time().$ext;
            }
            //獲取遠端檔案所採用的方法
            if($type){
                $ch=curl_init();
                $timeout=5;
                curl_setopt($ch,CURLOPT_URL,$url);
                curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
                curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
                $img=curl_exec($ch);
                curl_close($ch);
            }else{
                ob_start();
                readfile($url);
                $img=ob_get_contents();
                ob_end_clean();
            }
    
            //下載檔案
            [email protected]($save_dir.$filename,'a');
            fwrite($fp2,$img);
            fclose($fp2);
            unset($img,$url);
            return array('file_name'=>$filename,'save_path'=>$save_dir.$filename,'error'=>0);
          }
    };
    
    //例項化物件
    $vyuanCustom = new vyuanCustomAPI();
    //注意:第一步驗證時開啟,驗證完成之後就可以註釋了
    $vyuanCustom->isValid();

    if($vyuanCustom->checkSignature() === true){
        $xmlstring = file_get_contents("php://input");
        $accept_info = $vyuanCustom->xml2Array($xmlstring)['xml'];
        
        if($accept_info){
            $ToUserName = $accept_info['ToUserName'];
            $FromUserName = $accept_info['FromUserName'];
            $CreateTime = $accept_info['CreateTime'];
            $MsgType = $accept_info['MsgType'];

            $data = array();
            if($MsgType == 'text'){//接收文字
                $Content = $accept_info['Content'];//文字內容
                $data['touser'] = $FromUserName;
                
                if($Content === '圖文') {
                    $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';
                }else if($Content === '1'){
                    $data['msgtype'] = 'image';
                    $data['image']['media_id'] = 'q3oQpLPWOIB50tCKdR510qeNIGEQd9A0Ku7DJJmsTsXVeQZqq0sUMK2gbUyJZsYn';
                    $data['image']['picurl'] = 'this is image';
                }else if($Content === '2'){
                    $data['msgtype'] = 'text';
                    $data['text']['content'] = urlencode('你好');//urlencode 解決中文亂碼問題
                    
                }else{
                    $data['msgtype'] = 'text';
                    $data['text']['content'] = urlencode('對不起,我不知道您在說什麼....');//urlencode 解決中文亂碼問題
                }
                
                $vyuanCustom->send($data);exit;
                
            }else if($MsgType === 'image') {//接收圖片
                

            }else if($MsgType === 'event') {//進入客服視窗事件
                $Event = $accept_info['Event'];
                $SessionFrom = $accept_info['SessionFrom'];  //得到開發者在客服會話按鈕設定的session-from屬性

                $media_id = $vyuanCustom -> getMedia_id($SessionFrom);

                if($Event == 'user_enter_tempsession') {
                    $data['touser'] = $FromUserName;

                    if(!$media_id){
                        //紅娘二維碼不為空,傳送二維碼
                        $data['msgtype'] = 'image';
                        $data['image']['media_id'] = $media_id;
                        //$data['image']['media_id'] = 'D6SA5xGFDlrxspT2LovHD2gbMHrUjhcji7B6WUXZ2lG7rhWi4K8ExT0_6FF4uvJY';
                        $data['image']['picurl'] = 'this is image';
                    }else{
                        //紅娘二維碼為空,則傳送文字
                        $data['msgtype'] = 'text';
                        $data['text']['content'] = urlencode('您好,請回復1獲取我的微信');//urlencode 解決中文亂碼問題
                    }
                    
                    $vyuanCustom->send($data);exit;
                }
            }
            
            echo '<xml><ToUserName><![CDATA['.$FromUserName.']]></ToUserName><FromUserName><![CDATA['.$ToUserName.']]></FromUserName><CreateTime>'.$CreateTime.'</CreateTime><MsgType><![CDATA[transfer_customer_service]]></MsgType></xml>';
        }
    }
     

相關推薦

程式---訊息介面呼叫

<button open-type="contact" class='contactService' session-from="{{'https://https://mp.weixin.qq.com/debug/wxadoc/introduction/imag

程式訊息實時通知之最佳實踐

我們做微信小程式開發的都知道,只要在小程式頁面中新增如下程式碼即可進入小程式的客服會話介面:  <button open-type="contact" >聯絡我們</button>  微信小程式客服會話介面如下圖所示: 但是,客戶給我們小程式發的訊息,微信伺服器並不會通知小程式管

【最佳實踐】程式訊息實時通知如何快速低成本實現?

我們做微信小程式開發的都知道,只要在小程式頁面中新增如下程式碼即可進入小程式的客服會話介面: <button open-type="contact" >聯絡我們</button> 微信小程式客服會話介面如下圖所示:

程式訊息授權給第三方Udesk

微信小程式客服訊息可能授權給第三方Udesk 一、必須是微信認證過的微信小程式 登入微信小程式後臺-設定-基本設定 連結:https://mp.weixin.qq.com/ 下面有一欄:微信認證(看是否認證) 二、以管理員身份登入Udesk後臺 1、地址:http://ud

程式訊息之解決方案

小程式自公開發布起就有訊息推送功能,但由於張小龍對於微信小程式的定義為極簡的生活方式,所以為了避免小程式傳送過多的推送訊息騷擾使用者對於小程式訊息推送制定了許多的規則和限制。 一、小程式客服訊息的意義: 為豐富小程式的服務能力,提高服務質量,微信為小程式提供客服訊息能

技術白之記錄程式功能

程式做到上線,必不可缺的便是使使用者在使用你製作的程式時,能夠反饋回一些建議,這就需要客服的功能了。 客服功能,官方微信上有提供專門的元件,如下: 客服訊息會話入口有兩個: 1、小程式內:開發者在小程式內新增客服訊息按鈕元件,使用者可在小程式內喚起客服會話頁面,給小程式發訊息; 2、已使

程式 按鈕

例如這個: <view> <image src='/img/img/servicewx.png' class='card-img'> <button open-type="contact" class='card-i

手把手教你實現程式會話聊天智慧程式

如果你是一個經常需要接待使用者的小程式,可能已經給小程式添加了一個簡單的客服功能按鈕,讓使用者更主動和你互動! 客服人員可以直接使用微信公眾平臺網頁版客服工具進行客服訊息回覆。或者使用更智慧的第三方小程式客服,來實現更多多維度的操作! 比如多達 15 中的自動回覆,以及多

Thinkphp5程式獲取使用者資訊介面呼叫筆記

首先在官網下載示例程式碼, 選php的, 這裡有個坑  官方的php檔案,編碼是UTF-8+的, 所以要把檔案改為UTF-8 然後在Thinkphp5 extend資料夾下建立Wxxcx名稱空間,把官方的幾個類檔案放進去(這裡要注意資料夾名, 名稱空間名, 類名的, 大小

程序系統手機版五大功能介紹

分享 嚴重 體驗 多用戶 模板消息 mobile 可以登錄 移動 targe 很多朋友小程序上線後,客服消息這塊一直沒得到解決。小程序客服消息只能在PC端回復,是讓眾多小程序運營商及商家頭疼的問題,因為一個再牛逼的客服,也不可能隨時隨地都抱著電腦,這就導致很多用戶的留言不

使用程序消息上的一些註意事項!程序消息按鈕接入及消息接收

綁定 可謂 分享圖片 src 介紹 分享 組件 處理 工具 本文分為四部分,為大家介紹一下,小程序客服消息上的一些解決方案 1.增加小程序客服按鈕 2.實現客服會話(綁定客服人員,消息推送配置) 3.如何實現小程序客服智能消息(自動回復等) 4.用手機回復小程序客服消息(模

程式開發--豆瓣圖書介面

由於微信小程式訪問豆瓣圖書介面的API被關閉, 所有從小程式端發起的訪問請求都會被拒絕, 403,禁止通訊。 其餘的資訊介面大都是http的,微信小程式中不允許訪問http, 我們通過中繼伺服器爬取並解析資料實現了一個可以在小程式中實現的圖書資訊查詢介面。 通過圖書的isbn 號碼查詢關於該圖書的各

程式上,幫助中心介面實現類似手風琴案例

小程式wxml程式碼如下:  <block wx:for="{{arrdata}}" wx:key=""> <view class="centent_title" @tap="open_that" data-index="{{index}}">

程式支付統一下單介面

微信小程式——支付 1.通過code獲取openId code:使用者登入憑證(有效期五分鐘)。開發者需要在開發者伺服器後臺呼叫 api,使用 code 換取 openid 和 session_key 等資訊 openid: 使用者唯一標識 session_key: 會

程式-公告滾動訊息通知

寫在前面:    這次我主要想總結一下微信小程式實現上下滾動訊息提醒,主要是利用swiper元件來實現,swiper元件在小程式中是滑塊檢視容器。   我們通過vertical屬性(預設為false,實現預設左右滾動)設定為true來實現上下滾動。   (需要注意的是:只要

程式訊息

/** * 傳送客服訊息介面 */ public function actionCustomService() { $data = file_get_contents('php://input'); $data =

程式摸版訊息測試

目的:實現訊息摸版的下發。 結果:測試成功 步驟: 1.小程式不校驗域名請求OpenId(個人開發者不行) 2.介面弄個表單 <view> <form name='pushMsgFm' report-submit bindsubmit='orderSi

程式發模板訊息給使用者

第一步:index.wxml,其程式碼如下所示 <!--index.wxml--> <form bindsubmit='formSubmit' report-submit='true'> <view class="container"

程式登入Java後臺介面(詳解,附示例程式碼)

首先看一下官方文件 我們先對官方給的時序圖進行簡單的分析 1.當小程式呼叫wx.login()時,會獲得一個code(臨時登入憑證),然後我們需要用wx.request()將code傳送到自己的伺服器. 2.在伺服器的介面中,呼叫登入憑證校檢介面,將appid(

程式——傳送模板訊息

步驟一:獲取模板ID 1、通過模版訊息管理介面獲取模版ID(詳見模版訊息管理) 2、在微信公眾平臺手動配置獲取模版ID     登入 https://mp.weixin.qq.com  獲取模板,如果沒有合