PHP 微信公众号之客服完整讲解
//获取access_token private static function get_access_token($app_id) { $getAuthorizerInfo = wx_auth::getAuthorizerInfo($app_id); $access_token = wx_auth::getAuthorizerAccessToken($app_id, $getAuthorizerInfo[\'authorization_info\'][\'authorizer_refresh_token\']); return $access_token; } //客服回复用户信息 public static function reply_customer($open_id, $content) { $app_id = WxUser::getWxUserInfoByOpenId($open_id)[\'app_id\']; $data = \'{"touser":"\' . $open_id . \'","msgtype":"text","text":{"content":"\' . $content . \'"}}\'; $access_token = self::get_access_token($app_id); $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" . $access_token; $result = wx_tools::postCurl($url, $data); return json_decode($result, true); } //获取所有客服账号 public static function get_customer_account_list($app_id) { $access_token = self::get_access_token($app_id); $url = "https://api.weixin.qq.com/cgi-bin/customservice/getkflist?access_token=" . $access_token; $result = wx_tools::getCurl($url); return json_decode($result, true); } //邀请微信号到客服 public static function invite_customer_account($kf_account, $invite_wx, $app_id) { $access_token = self::get_access_token($app_id); $data = \'{"kf_account":"\' . $kf_account . \'","invite_wx":"\' . $invite_wx . \'"}\'; $url = "https://api.weixin.qq.com/customservice/kfaccount/inviteworker?access_token=" . $access_token; $result = wx_tools::postCurl($url, $data); return json_decode($result, true); } //添加客服账号 public static function add_customer_account($kf_account, $nickname, $password, $app_id) { $access_token = self::get_access_token($app_id); $data = \'{"kf_account":"\' . $kf_account . \'","nickname":"\' . $nickname . \'","text":"\' . $password . \'"}\'; $url = "https://api.weixin.qq.com/customservice/kfaccount/add?access_token=" . $access_token; $result = wx_tools::postCurl($url, $data); return json_decode($result, true); } //设置微信头像 public static function upload_head_img($app_id, $kf_account, $file) { $access_token = self::get_access_token($app_id); $url = \'https://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?access_token=\' . $access_token . \'&kf_account=\' . $kf_account; $tmp_name = $file[\'tmp_name\']; $type = $file[\'type\']; $path = $file[\'name\']; $result = wx_tools::curl_post_file($url, $tmp_name, $type, $path); return $result; } //修改客服账号 public static function modify_customer_account($kf_account, $nickname, $password, $app_id) { $access_token = self::get_access_token($app_id); $data = \'{"kf_account":"\' . $kf_account . \'","nickname":"\' . $nickname . \'","text":"\' . $password . \'"}\'; $url = "https://api.weixin.qq.com/customservice/kfaccount/update?access_token=" . $access_token; $result = wx_tools::postCurl($url, $data); return json_decode($result, true); } //删除客服帐号 public static function remove_customer_account($kf_account, $app_id) { $access_token = self::get_access_token($app_id); $data = \'{"kf_account":"\' . $kf_account . \'"}\'; $url = "https://api.weixin.qq.com/customservice/kfaccount/del?access_token=" . $access_token; $result = wx_tools::postCurl($url, $data); return json_decode($result, true); } //获取用户与客服之间的聊天记录 public static function get_customer_service_chat_record($starttime, $endtime, $msgid, $number, $app_id) { $access_token = self::get_access_token($app_id); $data = \'{"starttime":"\' . $starttime . \'","endtime":"\' . $endtime . \'","msgid":"\' . $msgid . \'","number":"\' . $number . \'"}\'; $url = "https://api.weixin.qq.com/customservice/msgrecord/getmsglist?access_token=" . $access_token; $result = wx_tools::postCurl($url, $data); return json_decode($result, true); }
我自己的wx_tools 文件
/** * 以post方式提交xml到对应的接口url * @param string $url 提交地址 * @param string $param 需要post的xml数据 * @param bool $file 是否上传文件 * @param bool|array $cert 是否需要证书,默认不需要 如果是数组代表有证书地址 请按以下格式 array(\'cert\' => \'cert.pem\', \'key\' => \'key.pem\', \'rootca\' => \'rootca.pem\'); * @param int $second * @return mixed */ public static function postCurl($url, $param, $file = false, $cert = false, $second = 30) { $curl = curl_init(); //设置超时 curl_setopt($curl, CURLOPT_TIMEOUT, $second); if (stripos($url, "https://") !== FALSE) { curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($curl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1 } if (PHP_VERSION_ID >= 50500 && class_exists(\'\CURLFile\')) { $is_file = true; } else { $is_file = false; if (defined(\'CURLOPT_SAFE_UPLOAD\')) { curl_setopt($curl, CURLOPT_SAFE_UPLOAD, false); } } if (is_string($param)) { $str_post = $param; } elseif ($file) { if ($is_file) { foreach ($param as $key => $val) { if (substr($val, 0, 1) == \'@\') { $param[$key] = new \CURLFile(realpath(substr($val, 1))); } } } $str_post = $param; } else { $post = array(); foreach ($param as $key => $val) { $post[] = $key . "=" . urlencode($val); } $str_post = join("&", $post); } //设置证书 todo 未验证 if (is_array($cert)) { //请确保您的libcurl版本是否支持双向认证,版本高于7.20.1 使用证书:cert 与 key 分别属于两个.pem文件 curl_setopt($curl, CURLOPT_SSLKEYTYPE, \'PEM\'); curl_setopt($curl, CURLOPT_SSLCERT, $cert[\'cert\']); curl_setopt($curl, CURLOPT_SSLKEYTYPE, \'PEM\'); curl_setopt($curl, CURLOPT_SSLKEY, $cert[\'key\']); //红包使用 if (empty($cert[\'rootca\'])) { curl_setopt($curl, CURLOPT_SSLKEYTYPE, \'PEM\'); curl_setopt($curl, CURLOPT_CAINFO, $cert[\'rootca\']); } } curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $str_post); $content = curl_exec($curl); $status = curl_getinfo($curl); if (intval($status["http_code"]) == 200) { curl_close($curl); // ApiLog::setMessage(\Yii::$app->session->get(\'request_base_api_log_id\'),[\'url\' => $url, \'message\'=> $content], 1); return $content; } else { $error = curl_errno($curl); curl_close($curl); // $this->err_code = $error; // $this->err_msg = $this->curl_error[$error]; // ApiLog::setMessage(\Yii::$app->session->get(\'request_base_api_log_id\'),[\'url\' => $url, \'message\'=> $content], 0); return false; } } /** * CURL GET 请求 * @param $url * @return bool|mixed */ public static function getCurl($url) { $curl = curl_init(); if (stripos($url, "https://") !== FALSE) { curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($curl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1 } curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $content = curl_exec($curl); $status = curl_getinfo($curl); if (intval($status["http_code"]) == 200) { curl_close($curl); // ApiLog::setMessage(\Yii::$app->session->get(\'request_base_api_log_id\'),[\'url\' => $url, \'message\'=> $content], 1); return $content; } else { $error = curl_errno($curl); curl_close($curl); file_put_contents(\'../web/logs/notify/error\' . date(\'YmdHi\') . \'.txt\', $error); // ApiLog::setMessage(\Yii::$app->session->get(\'request_base_api_log_id\'),[\'url\' => $url, \'message\'=> $content], 0); // $this->err_code = $error; // $this->err_msg = $this->curl_error[$error]; return false; } } /** * 微信api不支持中文转义的json结构 * @param $arr * @return string */ public static function jsonEncode($arr) { if (count($arr) == 0) return "[]"; $parts = array(); $is_list = false; //Find out if the given array is a numerical array $keys = array_keys($arr); $max_length = count($arr) - 1; if (($keys [0] === 0) && ($keys [$max_length] === $max_length)) { //See if the first key is 0 and last key is length - 1 $is_list = true; for ($i = 0; $i < count($keys); $i++) { //See if each key correspondes to its position if ($i != $keys [$i]) { //A key fails at position check. $is_list = false; //It is an associative array. break; } } } foreach ($arr as $key => $value) { if (is_array($value)) { //Custom handling for arrays if ($is_list) $parts [] = self::jsonEncode($value); /* :RECURSION: */ else $parts [] = \'"\' . $key . \'":\' . self::jsonEncode($value); /* :RECURSION: */ } else { $str = \'\'; if (!$is_list) $str = \'"\' . $key . \'":\'; //Custom handling for multiple data types if (!is_string($value) && is_numeric($value) && $value < 2000000000) $str .= $value; //Numbers elseif ($value === false) $str .= \'false\'; //The booleans elseif ($value === true) $str .= \'true\'; else $str .= \'"\' . addslashes($value) . \'"\'; //All other things // :TODO: Is there any more datatype we should be in the lookout for? (Object?) $parts [] = $str; } } $json = implode(\',\', $parts); if ($is_list) return \'[\' . $json . \']\'; //Return numerical JSON return \'{\' . $json . \'}\'; //Return associative JSON } /** * 数据解析 * @param $data * @return bool|mixed */ public static function parseData($data) { $data = json_decode($data, true); return $data; } /** * 使用curl 文件上传 版本大于5.5 * @param $url * @param $tmp_name * @param $type * @param $path * @return int|mixed */ public static function curl_post_file($url, $tmp_name, $type, $path) { $curl = curl_init(); curl_setopt($curl, CURLOPT_SAFE_UPLOAD, true); $data = [\'file\' => new \CURLFile($tmp_name, $type, $path)]; curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_USERAGENT, "TEST"); $result = curl_exec($curl); $status = curl_getinfo($curl); if (intval($status["http_code"]) == 200) { curl_close($curl); return $result; } $error = curl_errno($curl); curl_close($curl); return $error; }