From 4651bae2eff3f138545942ea30e3e9812650db7d Mon Sep 17 00:00:00 2001 From: lcc <805383944@qq.com> Date: Fri, 15 Aug 2025 13:58:48 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B9=B3=E5=AE=89=E5=A4=96=E5=91=BC=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/controllers/Common.php | 107 ++++++--- admin/controllers/receiver/Clues.php | 20 +- admin/controllers/receiver/Customer.php | 22 +- admin/controllers/sys/site/Callconfig.php | 90 +++++++ admin/views/receiver/clues/edit.php | 7 + admin/views/receiver/customer/get.php | 7 + admin/views/sys/site/callConfig/edit.php | 44 ++++ .../admin/controllers/api/receiver/Clues.php | 18 +- .../controllers/api/receiver/Customer.php | 20 +- agent/admin/controllers/pingan/call/Log.php | 78 ++++++ .../controllers/pingan/receiver/Clues.php | 37 ++- .../controllers/pingan/receiver/Customer.php | 20 +- .../controllers/pingan/user/UserInfo.php | 23 +- agent/admin/libraries/api/CallPhone.php | 92 +++++++ api/controllers/plan/CallBack.php | 128 ++++++++++ api/controllers/plan/Plan.php | 2 + api/controllers/wxapp/licheb/Customerlogs.php | 14 +- api/controllers/wxapp/licheb/Xz.php | 110 ++++++--- common/libraries/carHome/CallOut.php | 32 ++- common/libraries/carHome/CallOutWechat.php | 224 ++++++++++++++++++ .../models/receiver/Receiver_call_model.php | 20 ++ .../receiver/Receiver_call_wechat_model.php | 25 ++ .../receiver/Receiver_clue_oplogs_model.php | 43 +++- .../Receiver_customer_oplogs_model.php | 36 +++ common/models/sys/Sys_config_model.php | 8 +- 25 files changed, 1043 insertions(+), 184 deletions(-) create mode 100644 admin/controllers/sys/site/Callconfig.php create mode 100644 admin/views/sys/site/callConfig/edit.php create mode 100644 agent/admin/controllers/pingan/call/Log.php create mode 100644 agent/admin/libraries/api/CallPhone.php create mode 100644 common/libraries/carHome/CallOutWechat.php create mode 100644 common/models/receiver/Receiver_call_model.php create mode 100644 common/models/receiver/Receiver_call_wechat_model.php diff --git a/admin/controllers/Common.php b/admin/controllers/Common.php index 2857aad3..fe44fb7b 100644 --- a/admin/controllers/Common.php +++ b/admin/controllers/Common.php @@ -839,6 +839,9 @@ class Common extends CI_Controller */ public function bind_mobile() { + $this->load->helper('order'); + $this->load->model('receiver/receiver_call_wechat_model', 'callWechat'); + $this->load->library('carHome/callOutWechat'); $this->load->model('sys/sys_admin_model'); $this->load->model('sys/sys_yx_mobiles_model'); $params = $this->input->get(); @@ -851,57 +854,89 @@ class Common extends CI_Controller if ($type == 'clues') { $this->load->model('receiver/receiver_clues_model', 'mdClues'); $re = $this->mdClues->get(array('id' => $id)); + $orderId = $re['sid']; + $cfId = $re['id']; + $cfType = Receiver_call_wechat_model::CF_TYPE_CLUE; } else if ($type == 'customer') { $this->load->model('receiver/receiver_customers_model', 'mdCustomers'); $re = $this->mdCustomers->get(array('id' => $id)); + $orderId = $re['cid']; + $cfId = $re['id']; + $cfType = Receiver_call_wechat_model::CF_TYPE_CUSTOMERS; + } else { + return $this->show_json(SYS_CODE_FAIL, '参数错误!'); } if (!$re['mobile']) { return $this->show_json(SYS_CODE_FAIL, '手机不存在!'); } + $user = $this->sys_admin_model->get(['id' => $this->uid]); + $user_mobile = $user['mobile']; + if (!$user_mobile) { + return $this->show_json(SYS_CODE_FAIL, '管理员未设置手机号'); + } $mobile = $re['mobile']; + $callOutWechat = new CallOutWechat(); + $cityId = $re['city_id'] ?: 350200; + $requestId = create_order_no($cityId, 'licheb'); + $req = $callOutWechat->outBind($requestId, $orderId, $user_mobile, $mobile); + if (!$req->isSuccess()) { + return $this->show_json(SYS_CODE_FAIL, $req->getMessage()); + } + //添加记录 + $add_data = [ + 'reqId' => $requestId, + 'cfId' => $cfId, + 'cfUid' => $this->uid, + 'cfType' => $cfType, + 'cfPlatform' => Receiver_call_wechat_model::CF_PLATFORM_ADMIN, + 'createTime' => time() + ]; + $req = $this->callWechat->add($add_data); + if (!is_numeric($req)) { + return $this->show_json(SYS_CODE_FAIL, $req->getMessage()); + } + //绑定手机号 + return $this->show_json(SYS_CODE_SUCCESS, '提交成功,请耐心等待'); // $cache = &load_cache('redis'); // $xz_admin_phone = $cache->get('xz_admin_phone'); // $middleNumber = ''; // if ($xz_admin_phone) { // $middleNumber = $xz_admin_phone['admins'][$this->uid]; // } - $yxMobiles = $this->sys_yx_mobiles_model->get(['admin_id' => $this->uid, 'status' => 1]); - $middleNumber = $yxMobiles['mobile'] ?: ''; - if (!$middleNumber) { - return $this->show_json(SYS_CODE_FAIL, '还未分配号码不可使用'); - } - $this->load->helper('order'); - require_once COMMPATH . 'third_party/Ycall/Ycall.php'; - $seq_id = create_order_no(); - $ycall = new Ycall(); - $maxBindingTime = 30;//绑定时间 - $result = $ycall->AXbind($middleNumber, $mobile, '', $maxBindingTime, ''); + // 平安双呼 + +// $yxMobiles = $this->sys_yx_mobiles_model->get(['admin_id' => $this->uid, 'status' => 1]); +// $middleNumber = $yxMobiles['mobile'] ?: ''; +// if (!$middleNumber) { +// return $this->show_json(SYS_CODE_FAIL, '还未分配号码不可使用'); +// } +// require_once COMMPATH . 'third_party/Ycall/Ycall.php'; +// $seq_id = create_order_no(); +// $ycall = new Ycall(); +// $maxBindingTime = 30;//绑定时间 +// $result = $ycall->AXbind($middleNumber, $mobile, '', $maxBindingTime, ''); //改AXB模式 开始 -// $this->load->model('sys/sys_admin_model'); -// $user = $this->sys_admin_model->get(['id'=>$this->uid]); -// $user_mobile = $user['mobile']; -// if(!$user_mobile) return $this->show_json(SYS_CODE_FAIL, '管理员未设置手机号'); // $result = $ycall->ABXbind($user_mobile, $mobile, $seq_id, $maxBindingTime); //改AXB模式 结束 - if ($result['result'] != '000000') { //绑定失败 - debug_log("xz_result:" . json_encode($result, JSON_UNESCAPED_UNICODE)); - return $this->show_json(SYS_CODE_FAIL, $result['message']); - } - $this->data['middlenumber'] = $result['middleNumber']; - $add_data = [ - 'call_id' => $seq_id, - 'bind_id' => $result['bindId'], - 'display_number' => $result['middleNumber'], - 'cf_id' => $id, - 'cf_uid' => $this->uid, - 'cf_title' => $type, - 'cf_platform' => 'admin', - 'c_time' => time() - ]; - $this->mdReceiverYx->add($add_data); - $this->data['mobile_sub'] = mobile_asterisk($mobile); - $this->data['id'] = $id; - $this->show_view('common/bind_mobile'); +// if ($result['result'] != '000000') { //绑定失败 +// debug_log("xz_result:" . json_encode($result, JSON_UNESCAPED_UNICODE)); +// return $this->show_json(SYS_CODE_FAIL, $result['message']); +// } +// $this->data['middlenumber'] = $result['middleNumber']; +// $add_data = [ +// 'call_id' => $seq_id, +// 'bind_id' => $result['bindId'], +// 'display_number' => $result['middleNumber'], +// 'cf_id' => $id, +// 'cf_uid' => $this->uid, +// 'cf_title' => $type, +// 'cf_platform' => 'admin', +// 'c_time' => time() +// ]; +// $this->mdReceiverYx->add($add_data); +// $this->data['mobile_sub'] = mobile_asterisk($mobile); +// $this->data['id'] = $id; +// $this->show_view('common/bind_mobile'); } /** @@ -1197,8 +1232,8 @@ class Common extends CI_Controller 'status' => App_paic_users_model::STATUS_NORMAL ]; $rows = $this->app_paic_users_model->select($where, 'id desc', 0, 0, 'id,name,mobile'); - foreach ($rows as $k => $v){ - $rows[$k]['name'] = $v['name'] . " (".substr($v['mobile'], -4).")"; + foreach ($rows as $k => $v) { + $rows[$k]['name'] = $v['name'] . " (" . substr($v['mobile'], -4) . ")"; } $this->data = $rows; return $this->show_json(SYS_CODE_SUCCESS); diff --git a/admin/controllers/receiver/Clues.php b/admin/controllers/receiver/Clues.php index 985e0632..862f8a14 100644 --- a/admin/controllers/receiver/Clues.php +++ b/admin/controllers/receiver/Clues.php @@ -17,7 +17,7 @@ class Clues extends HD_Controller $this->load->model('receiver/receiver_clues_cfrom_model', 'clues_cfrom_model'); $this->load->model('receiver/receiver_customers_model', 'customers_model'); $this->load->model('receiver/receiver_clue_oplogs_model', 'mdOplogs'); - $this->load->model('receiver/receiver_yx_model', 'mdReceiverXz'); +// $this->load->model('receiver/receiver_yx_model', 'mdReceiverXz'); // $this->load->model('app/licheb/app_licheb_users_model'); $this->load->model("biz/biz_model"); // $this->load->model('auto/auto_brand_model', 'mdAutoBrand'); @@ -309,15 +309,15 @@ class Clues extends HD_Controller $setValue['log'] = $value['log']; $setValue['type_name'] = $this->mdOplogs->typeAry()[$value['type']]; $setValue['c_time'] = date('Y-m-d H:i', $value['c_time']); - $rec_url = $rec_text = ''; - if ($value['type'] == 2) {//拨打电话 - $rec_text = '未接通'; - $row = $this->mdReceiverXz->get(array('id' => $value['log'])); - if ($row['duration']) { - $rec_url = $row['rec_url'] ? build_qiniu_image_url($row['rec_url'], 0, 0, 'video') : ''; - $rec_text = '录音文件未生成'; - } - } + list($rec_url,$rec_text) = $this->mdOplogs->getRecordUrl($value['id']); +// if ($value['type'] == 2) {//拨打电话 +// $rec_text = '未接通'; +// $row = $this->mdReceiverXz->get(array('id' => $value['log'])); +// if ($row['duration']) { +// $rec_url = $row['rec_url'] ? build_qiniu_image_url($row['rec_url'], 0, 0, 'video') : ''; +// $rec_text = '录音文件未生成'; +// } +// } $setValue['rec_url'] = $rec_url; $setValue['rec_text'] = $rec_text; $logsList[] = $setValue; diff --git a/admin/controllers/receiver/Customer.php b/admin/controllers/receiver/Customer.php index a435d16b..3451f05a 100644 --- a/admin/controllers/receiver/Customer.php +++ b/admin/controllers/receiver/Customer.php @@ -572,8 +572,8 @@ class Customer extends HD_Controller } if ($this->admin_biz_str) { $where["biz_id in ($this->admin_biz_str)"] = null; - }else{ - $this->belong && $where["biz_id in(select id from lc_biz where province_id=".$this->limit_province_id.")"] = null; + } else { + $this->belong && $where["biz_id in(select id from lc_biz where province_id=" . $this->limit_province_id . ")"] = null; } return $where; } @@ -676,23 +676,7 @@ class Customer extends HD_Controller //操作日志 $logs = array(); foreach ($rows_log as $key => $value) { - $rec_text = $rec_url = ''; - if ($value['type'] == 2) { - $record = ''; - if ($value['sub_type'] == Receiver_customer_oplogs_model::SUB_TYPE_XZ) { - $rec_row = $this->receiver_xz_model->get(['id' => $value['log']], 'rec_url,duration'); - $rec_row['rec_url'] && $record = $rec_row['rec_url']; - } else { - $rec_row = $this->receiver_yx_model->get(['id' => $value['log']], 'rec_url,duration'); - $rec_row['rec_url'] && $record = get_yx_video($rec_row['rec_url']); - } - if ($rec_row['duration']) { - $record && $rec_url = $record; - !$rec_row['rec_url'] && $rec_text = '录音暂未生成'; - } else { - $rec_text = '未接通'; - } - } + list($rec_url, $rec_text) = $this->customer_oplogs_model->getRecordUrl($value['id']); $imgs = []; if ($value['imgs']) { $json_imgs = json_decode($value['imgs'], true); diff --git a/admin/controllers/sys/site/Callconfig.php b/admin/controllers/sys/site/Callconfig.php new file mode 100644 index 00000000..ee09b99c --- /dev/null +++ b/admin/controllers/sys/site/Callconfig.php @@ -0,0 +1,90 @@ +load->model('sys/sys_config_model', 'confModel'); + } + + public function index() + { + return $this->get(); + } + + public function lists() + { + } + + public function get() + { + $row = $this->confModel->get(array('k' => Sys_config_model::CALL_CONFIG_KEY)); + if (!$row) { + $addData = array( + 'k' => Sys_config_model::CALL_CONFIG_KEY, + 'v' => json_encode([], JSON_UNESCAPED_UNICODE), + 'c_time' => time(), + ); + $id = $this->confModel->add($addData); + if (!is_numeric($id)) { + $this->show_json(SYS_CODE_FAIL, '添加失败'); + } + $row = $addData; + $row['id'] = $id; + } + $this->data['id'] = $row['id']; + $this->data['row'] = json_decode($row['v'], true); + $this->data['_title'] = '外呼配置'; + $this->show_view('sys/site/callConfig/edit', true); + } + + public function add() + { + } + + public function edit() + { + $input = $this->input->post(); + $row = $this->confModel->get(array('id' => $input['id'])); + if (!$row) { + return $this->show_json(SYS_CODE_FAIL, '提交错误'); + } + $callTime = intval($input['callTime']); + $callbackTime = intval($input['callbackTime']); + if (!$callTime || $callbackTime <= 0) { + return $this->show_json(SYS_CODE_FAIL, '请输入正确的外呼绑定时长'); + } + if (!$callbackTime || $callbackTime <= 0) { + return $this->show_json(SYS_CODE_FAIL, '请输入正确的回拨绑定时长'); + } + $jsonData = json_decode($row['v'], true); + $jsonData['callBackPhoneNo'] = $input['callBackPhoneNo'] ?: ''; + $jsonData['callTime'] = $callTime; + $jsonData['callbackTime'] = $callbackTime; + $re = $this->confModel->update(array('v' => json_encode($jsonData, JSON_UNESCAPED_UNICODE)), array('id' => $input['id'])); + if ($re) { + return $this->show_json(SYS_CODE_SUCCESS, '编辑成功'); + } else { + return $this->show_json(SYS_CODE_FAIL, '编辑失败'); + } + } + + public function del() + { + + } + + public function batch() + { + + } + + public function export() + { + + } + +} diff --git a/admin/views/receiver/clues/edit.php b/admin/views/receiver/clues/edit.php index 3a61d5ad..836cf2fd 100644 --- a/admin/views/receiver/clues/edit.php +++ b/admin/views/receiver/clues/edit.php @@ -201,9 +201,16 @@
保存 + + + 拨打 +
diff --git a/admin/views/receiver/customer/get.php b/admin/views/receiver/customer/get.php index 3a837b28..0dcce61b 100644 --- a/admin/views/receiver/customer/get.php +++ b/admin/views/receiver/customer/get.php @@ -44,12 +44,19 @@ 客户姓名:{{info.name}} 客户电话:{{info.mobile}} + + 拨打 + + 归属门店:{{info.biz}} diff --git a/admin/views/sys/site/callConfig/edit.php b/admin/views/sys/site/callConfig/edit.php new file mode 100644 index 00000000..921ca97f --- /dev/null +++ b/admin/views/sys/site/callConfig/edit.php @@ -0,0 +1,44 @@ +
+
+
+ +
+ +
+ +
+ + 客户回拨到号码,为空则回到坐席号码 + +
+
+ +
+
+ + 分钟 +
+
+
+
+ +
+
+ + 分钟 +
+
+
+
+ +
+
+
+
+ diff --git a/agent/admin/controllers/api/receiver/Clues.php b/agent/admin/controllers/api/receiver/Clues.php index b6c7f828..195afcff 100644 --- a/agent/admin/controllers/api/receiver/Clues.php +++ b/agent/admin/controllers/api/receiver/Clues.php @@ -14,13 +14,17 @@ class Clues extends BaseController $this->load->model('auto/auto_brand_model'); $this->load->model('auto/auto_series_model'); $this->load->model('receiver/receiver_clue_oplogs_model', 'mdOplogs'); - $this->load->model('receiver/receiver_yx_model', 'mdReceiverXz'); + $this->load->model('receiver/receiver_yx_model'); + $this->load->model('receiver/receiver_xz_model'); + $this->load->model('receiver/receiver_call_wechat_model'); $this->clues_model->set_db('ssdb'); $this->clues_cfrom_model->set_db('ssdb'); $this->auto_brand_model->set_db('ssdb'); $this->auto_series_model->set_db('ssdb'); $this->mdOplogs->set_db('ssdb'); - $this->mdReceiverXz->set_db('ssdb'); + $this->receiver_yx_model->set_db('ssdb'); + $this->receiver_xz_model->set_db('ssdb'); + $this->receiver_call_wechat_model->set_db('ssdb'); } public function page_get() @@ -124,15 +128,7 @@ class Clues extends BaseController $setValue['log'] = $value['log']; $setValue['type_name'] = $this->mdOplogs->typeAry()[$value['type']]; $setValue['c_time'] = date('Y-m-d H:i', $value['c_time']); - $rec_url = $rec_text = ''; - if ($value['type'] == 2) {//拨打电话 - $rec_text = '未接通'; - $row = $this->mdReceiverXz->get(array('id' => $value['log'])); - if ($row['duration']) { - $rec_url = $row['rec_url'] ? build_qiniu_image_url($row['rec_url'], 0, 0, 'video') : ''; - $rec_text = '录音文件未生成'; - } - } + list($rec_url, $rec_text) = $this->mdOplogs->getRecordUrl($value['id']); $setValue['rec_url'] = $rec_url; $setValue['rec_text'] = $rec_text; $list[] = $setValue; diff --git a/agent/admin/controllers/api/receiver/Customer.php b/agent/admin/controllers/api/receiver/Customer.php index a87101bf..4159dbc3 100644 --- a/agent/admin/controllers/api/receiver/Customer.php +++ b/agent/admin/controllers/api/receiver/Customer.php @@ -16,6 +16,7 @@ class Customer extends BaseController $this->load->model('area_model'); $this->load->model('receiver/receiver_yx_model'); $this->load->model('receiver/receiver_xz_model'); + $this->load->model('receiver/receiver_call_wechat_model'); $this->load->model('receiver/receiver_clues_cfrom_model', 'clues_cfrom_model'); $this->customers_model->set_db('ssdb'); $this->customer_oplogs_model->set_db('ssdb'); @@ -25,6 +26,7 @@ class Customer extends BaseController $this->area_model->set_db('ssdb'); $this->receiver_yx_model->set_db('ssdb'); $this->receiver_xz_model->set_db('ssdb'); + $this->receiver_call_wechat_model->set_db('ssdb'); $this->clues_cfrom_model->set_db('ssdb'); } @@ -165,23 +167,7 @@ class Customer extends BaseController $list = []; $rows_log = $this->customer_oplogs_model->select($where, 'id desc', $page, $limit); foreach ($rows_log as $key => $value) { - $rec_text = $rec_url = ''; - if ($value['type'] == 2) { - $record = ''; - if ($value['sub_type'] == Receiver_customer_oplogs_model::SUB_TYPE_XZ) { - $rec_row = $this->receiver_xz_model->get(['id' => $value['log']], 'rec_url,duration'); - $rec_row['rec_url'] && $record = $rec_row['rec_url']; - } else { - $rec_row = $this->receiver_yx_model->get(['id' => $value['log']], 'rec_url,duration'); - $rec_row['rec_url'] && $record = get_yx_video($rec_row['rec_url']); - } - if ($rec_row['duration']) { - $record && $rec_url = $record; - !$rec_row['rec_url'] && $rec_text = '录音暂未生成'; - } else { - $rec_text = '未接通'; - } - } + list($rec_url, $rec_text) = $this->customer_oplogs_model->getRecordUrl($value['id']); $imgs = []; if ($value['imgs']) { $json_imgs = json_decode($value['imgs'], true); diff --git a/agent/admin/controllers/pingan/call/Log.php b/agent/admin/controllers/pingan/call/Log.php new file mode 100644 index 00000000..15ff8f7b --- /dev/null +++ b/agent/admin/controllers/pingan/call/Log.php @@ -0,0 +1,78 @@ +load->model('receiver/receiver_call_model', 'callModel'); + $this->load->model('receiver/receiver_clues_model', 'cluesModel'); + $this->cluesModel->set_db('ssdb'); + $this->callModel->set_db('ssdb'); + } + + public function page_get() + { + $params = $this->input_param(); + $page = $params['page'] ?: 1; + $limit = $params['limit'] ?: 10; + $sort_order = 'id desc'; + $where = $this->buildWhere(); + $count = $this->callModel->count($where); + $list = []; + if ($count) { + $rows = $this->callModel->select($where, $sort_order, $page, $limit); + foreach ($rows as $v) { + $temp = $v; + $temp['customerPhoneNo'] = mobile_asterisk($v['customerPhoneNo']); + $temp['finishTypeCn'] = Receiver_call_model::finishTypeList[$v['finishType']] ?: ''; + $temp['callTypeCn'] = Receiver_call_model::callTypeList[$v['callType']] ?: ''; + $temp['hangupTypeCn'] = Receiver_call_model::hangupTypeList[$v['hangupType']] ?: ''; + $list[] = $temp; + } + } + $data = ['list' => $list, 'count' => $count]; + $this->return_response_list($data); + } + + /** + * 搜索条件 + * @return void + */ + public function search_get() + { + $data = []; + $data['finishTypeList'] = Receiver_call_model::finishTypeList;; + $data['callTypeList'] = Receiver_call_model::callTypeList; + $data['hangupTypeList'] = Receiver_call_model::hangupTypeList; + $this->return_response_list($data); + } + + private function buildWhere() + { + $params = $this->input_param(); + $where = [ + 'cfUid' => $_SESSION['id'] + ]; + $params['orderId'] && $where["orderId like '%{$params['orderId']}%'"] = null; + $params['agentId'] && $where['agentId'] = $params['agentId']; + $params['voiceId'] && $where['voiceId'] = $params['voiceId']; + $params['customerPhoneNo'] && $where['customerPhoneNo'] = $params['customerPhoneNo']; + strlen($params['finishType']) && $where['finishType'] = $params['finishType']; + strlen($params['callType']) && $where['callType'] = $params['callType']; + strlen($params['hangupType']) && $where['hangupType'] = $params['hangupType']; + if ($params['startTime'][0] && $params['startTime'][1]) { + $where['startTime >='] = $params['startTime'][0] . ' 00:00:00'; + $where['startTime <='] = $params['startTime'][1] . ' 23:59:59'; + } + if ($params['endTime'][0] && $params['endTime'][1]) { + $where['endTime >='] = $params['endTime'][0] . ' 00:00:00'; + $where['endTime <='] = $params['endTime'][1] . ' 23:59:59'; + } + return $where; + } +} + diff --git a/agent/admin/controllers/pingan/receiver/Clues.php b/agent/admin/controllers/pingan/receiver/Clues.php index ef6ba8c6..5a08abc8 100644 --- a/agent/admin/controllers/pingan/receiver/Clues.php +++ b/agent/admin/controllers/pingan/receiver/Clues.php @@ -17,16 +17,21 @@ class Clues extends BaseController $this->load->model('auto/auto_brand_model'); $this->load->model('auto/auto_series_model'); $this->load->model('receiver/receiver_clue_oplogs_model', 'mdOplogs'); - $this->load->model('receiver/receiver_yx_model', 'mdReceiverXz'); + $this->load->model('receiver/receiver_yx_model'); + $this->load->model('receiver/receiver_xz_model'); + $this->load->model('receiver/receiver_call_wechat_model'); $this->load->model('receiver/receiver_enroll_model'); $this->clues_model->set_db('ssdb'); $this->clues_cfrom_model->set_db('ssdb'); $this->auto_brand_model->set_db('ssdb'); $this->auto_series_model->set_db('ssdb'); $this->mdOplogs->set_db('ssdb'); - $this->mdReceiverXz->set_db('ssdb'); + $this->receiver_yx_model->set_db('ssdb'); + $this->receiver_xz_model->set_db('ssdb'); + $this->receiver_call_wechat_model->set_db('ssdb'); $this->mdOplogs->set_db('ssdb'); $this->receiver_enroll_model->set_db('ssdb'); + $this->load->library('api/callPhone'); } public function page_get() @@ -149,15 +154,7 @@ class Clues extends BaseController $setValue['log'] = $value['log']; $setValue['type_name'] = $this->mdOplogs->typeAry()[$value['type']]; $setValue['c_time'] = date('Y-m-d H:i', $value['c_time']); - $rec_url = $rec_text = ''; - if ($value['type'] == 2) {//拨打电话 - $rec_text = '未接通'; - $row = $this->mdReceiverXz->get(array('id' => $value['log'])); - if ($row['duration']) { - $rec_url = $row['rec_url'] ? build_qiniu_image_url($row['rec_url'], 0, 0, 'video') : ''; - $rec_text = '录音文件未生成'; - } - } + list($rec_url, $rec_text) = $this->mdOplogs->getRecordUrl($value['id']); $setValue['rec_url'] = $rec_url; $setValue['rec_text'] = $rec_text; $list[] = $setValue; @@ -381,5 +378,23 @@ class Clues extends BaseController } $this->return_response(); } + + /** + * 拨打电话 + * @return void + */ + public function call_post() + { + $params = $this->input_param(); + if (!$params['id']) { + $this->return_json('参数错误!'); + } + $callPhone = new CallPhone(); + $result = $callPhone->Call(Receiver_call_model::CF_TYPE_CLUE, $params['id'], $_SESSION['id'], $_SESSION['username'], $_SESSION['userCode']); + if (!$result->isSuccess()) { + $this->return_json($result->getMessage()); + } + $this->return_response(); + } } diff --git a/agent/admin/controllers/pingan/receiver/Customer.php b/agent/admin/controllers/pingan/receiver/Customer.php index bb8c14b1..66b7d023 100644 --- a/agent/admin/controllers/pingan/receiver/Customer.php +++ b/agent/admin/controllers/pingan/receiver/Customer.php @@ -18,6 +18,7 @@ class Customer extends BaseController $this->load->model('area_model'); $this->load->model('receiver/receiver_yx_model'); $this->load->model('receiver/receiver_xz_model'); + $this->load->model('receiver/receiver_call_wechat_model'); $this->load->model('receiver/receiver_clues_cfrom_model', 'clues_cfrom_model'); $this->load->model('receiver/receiver_clues_model', 'clues_model'); $this->load->model('receiver/order/receiver_orders_model'); @@ -30,6 +31,7 @@ class Customer extends BaseController $this->area_model->set_db('ssdb'); $this->receiver_yx_model->set_db('ssdb'); $this->receiver_xz_model->set_db('ssdb'); + $this->receiver_call_wechat_model->set_db('ssdb'); $this->clues_cfrom_model->set_db('ssdb'); $this->clues_model->set_db('ssdb'); } @@ -246,23 +248,7 @@ class Customer extends BaseController $list = []; $rows_log = $this->customer_oplogs_model->select($where, 'id desc', $page, $limit); foreach ($rows_log as $key => $value) { - $rec_text = $rec_url = ''; - if ($value['type'] == 2) { - $record = ''; - if ($value['sub_type'] == Receiver_customer_oplogs_model::SUB_TYPE_XZ) { - $rec_row = $this->receiver_xz_model->get(['id' => $value['log']], 'rec_url,duration'); - $rec_row['rec_url'] && $record = $rec_row['rec_url']; - } else { - $rec_row = $this->receiver_yx_model->get(['id' => $value['log']], 'rec_url,duration'); - $rec_row['rec_url'] && $record = get_yx_video($rec_row['rec_url']); - } - if ($rec_row['duration']) { - $record && $rec_url = $record; - !$rec_row['rec_url'] && $rec_text = '录音暂未生成'; - } else { - $rec_text = '未接通'; - } - } + list($rec_url, $rec_text) = $this->customer_oplogs_model->getRecordUrl($value['id']); $imgs = []; if ($value['imgs']) { $json_imgs = json_decode($value['imgs'], true); diff --git a/agent/admin/controllers/pingan/user/UserInfo.php b/agent/admin/controllers/pingan/user/UserInfo.php index 59bbf68e..a63f1835 100644 --- a/agent/admin/controllers/pingan/user/UserInfo.php +++ b/agent/admin/controllers/pingan/user/UserInfo.php @@ -32,7 +32,9 @@ class UserInfo extends BaseController 'bankCardNum' => $row['bankCardNum'] ?: '', 'bankName' => $row['bankName'] ?: '', 'cardA' => $row['cardA'] ? changeImg(explode(',', $row['cardA'])) : [], - 'cardB' => $row['cardB'] ? changeImg(explode(',', $row['cardB'])) : [] + 'cardB' => $row['cardB'] ? changeImg(explode(',', $row['cardB'])) : [], + 'mobile' => $row['mobile'], + 'cti' => $row['cti'] ]; $this->return_response($data); } @@ -56,4 +58,23 @@ class UserInfo extends BaseController } $this->return_response(); } + + /** + * 修改手机号 + * @return void + */ + public function mobile_put() + { + $userId = $_SESSION['id']; + $params = $this->input_param(); + $upData = [ + 'mobile' => $params['mobile'] ?: '', + 'cti' => $params['cti'] ?: '' + ]; + $res = $this->userData->update($upData, ['userId' => $userId]); + if (!$res) { + $this->return_json("更新失败"); + } + $this->return_response(); + } } \ No newline at end of file diff --git a/agent/admin/libraries/api/CallPhone.php b/agent/admin/libraries/api/CallPhone.php new file mode 100644 index 00000000..ca60f5f3 --- /dev/null +++ b/agent/admin/libraries/api/CallPhone.php @@ -0,0 +1,92 @@ +ci = &get_instance(); + $this->ci->load->model('agent/pingan/pingan_users_data_model', 'userData'); + $this->ci->load->model('receiver/receiver_clues_model', 'clues_model'); + $this->ci->load->model('receiver/receiver_clue_oplogs_model', 'mdOplogs'); + $this->ci->load->model('receiver/receiver_call_model', 'callModel'); + $this->ci->clues_model->set_db('ssdb'); + $this->ci->mdOplogs->set_db('ssdb'); + $this->ci->callModel->set_db('ssdb'); + $this->ci->load->library('carHome/CallOut'); + } + + /** + * @param $cfType int 类型 1线索 + * @param $cfId int 来源id + * @param $cfUid int 用户id + * @param $cfName string 操作用户名 + * @return MyResponse + */ + public function Call($cfType, $cfId, $cfUid, $cfName, $userCode) + { + $this->ci->callModel->db->trans_begin(); + try { + $userData = $this->ci->userData->get(['userId' => $cfUid]); + if (!$userData['mobile']) { + throw new Exception('请先配置分机号'); + } + $agentPhoneNo = $userData['mobile']; + $agentId = $userData['cti']; + $agentUm = $userCode; + $cityId = 350200; + if ($cfType == Receiver_call_model::CF_TYPE_CLUE) { + $clues = $this->ci->clues_model->get(['id' => $cfId]); + if (!$clues) { + throw new Exception('线索不存在'); + } + $orderId = $clues['sid']; + $customerPhoneNo = $clues['mobile']; + $clues['city_id'] && $cityId = $clues['city_id']; + } else { + throw new Exception('来源类型错误'); + } + $requestId = create_order_no($cityId, 'pingan'); + $callOut = new CallOut(); + $callReq = $callOut->call($orderId, $requestId, $agentPhoneNo, $customerPhoneNo, $agentId, $agentUm); + if (!$callReq->isSuccess()) { + throw new Exception($callReq->getMessage()); + } + $callData = [ + 'reqId' => $requestId, + 'orderId' => $orderId, + 'customerPhoneNo' => $customerPhoneNo, + 'agentPhoneNo' => $agentPhoneNo, + 'apiResult' => json_encode($callReq->getData(), JSON_UNESCAPED_UNICODE), + 'cfUid' => $cfUid, + 'cfId' => $cfId, + 'cfType' => $cfType, + 'cfPlatform' => Receiver_call_model::CF_PLATFORM_AGENT_PINGAN, + 'createTime' => time(), + ]; + $callLogId = $this->ci->callModel->add($callData); + if (!is_numeric($callLogId)) { + throw new Exception('添加通话记录失败'); + } + if ($cfType == Receiver_call_model::CF_TYPE_CLUE) { + $optLogId = $this->ci->mdOplogs->add([ + 'clue_id' => $cfId, + 'pingan_user_id' => $cfUid, + 'uname' => $cfName, + 'type' => Receiver_clue_oplogs_model::OP_TYPE_AUTO_CALL, + 'log' => '', + 'c_time' => time() + ]); + if (!is_numeric($optLogId)) { + throw new Exception('添加操作日志失败'); + } + } + $this->ci->callModel->db->trans_commit(); + return new MyRESPONSE(EXIT_SUCCESS, '提交成功'); + } catch (Exception $e) { + $this->ci->callModel->db->trans_rollback(); + return new MyResponse(EXIT_ERROR, "参数错误"); + } + } +} \ No newline at end of file diff --git a/api/controllers/plan/CallBack.php b/api/controllers/plan/CallBack.php index 60660032..edcd9ecb 100644 --- a/api/controllers/plan/CallBack.php +++ b/api/controllers/plan/CallBack.php @@ -198,6 +198,134 @@ class CallBack extends CI_Controller echo "do_num:{$do_num},success_num:{$success_num},failed_num:{$failed_num}"; } + /** + * 拨打电话回调(sadmin后台和小程序) + * @return void + */ + public function app() + { + $logPath = "callBackApp.log"; + //接收json 数据 + $post = $this->input->post(); + debug_log("post: " . json_encode($post, JSON_UNESCAPED_UNICODE), $logPath, $this->logDir); + $json = file_get_contents('php://input'); + debug_log("json: " . $json, $logPath, $this->logDir); + $data = $json ? json_decode($json, true) : []; + try { + //处理业务逻辑 + if (!$data || !$data['requestId']) { + throw new Exception('参数错误'); + } + $row = $this->callWechat->get(['reqId' => $data['requestId']]); + if (!$row) { + throw new Exception('拨号记录不存在'); + } + $callData = $data['calldata']; + $upData = [ + 'orderId' => $callData['orderId'] ?: '', + 'sessionId' => $callData['sessionId'] ?: '', + 'agentId' => $callData['agentId'] ?: '', + 'agentPhoneNo' => $callData['agentPhoneNo'] ?: '', + 'customerPhoneNo' => $callData['customerPhoneNo'] ?: '', + 'agentDispNo' => $callData['agentDispNo'] ?: '', + 'customerDispNo' => $callData['customerDispNo'] ?: '', + 'voiceId' => $callData['voiceId'] ?: '', + 'finishType' => $callData['finishType'], + 'callType' => $callData['callType'], + 'hangupType' => $callData['hangupType'], + 'recordpath' => $callData['recordpath'] ?: '', + 'status' => Receiver_call_wechat_model::STATUS_FINISH, + 'apiResult' => $json + ]; + $callData['agentRingTime'] && $upData['agentRingTime'] = $callData['agentRingTime']; + $callData['agentAnswerTime'] && $upData['agentAnswerTime'] = $callData['agentAnswerTime']; + $callData['userRingTime'] && $upData['userRingTime'] = $callData['userRingTime']; + $callData['userAnswerTime'] && $upData['userAnswerTime'] = $callData['userAnswerTime']; + $callData['endTime'] && $upData['endTime'] = $callData['endTime']; + if ($callData['endTime'] && $callData['agentAnswerTime']) { + $upData['telDuration'] = strtotime($callData['endTime']) - strtotime($callData['agentAnswerTime']); + } + if ($callData['endTime'] && $callData['userAnswerTime']) { + $upData['telDuration'] = strtotime($callData['endTime']) - strtotime($callData['userAnswerTime']); + } + $this->callWechat->update($upData, ['id' => $row['id']]); + if ($row['cfId'] && $row['cfPlatform'] == Receiver_call_wechat_model::CF_PLATFORM_WX_APP) { //理车宝 + $user = $this->app_user_model->get(['id' => $row['cfUid']]); + $cust = $this->customers_model->get(['id' => $row['cfId']]); + $this->load->library('receiver/customers_entity'); + $visit = 1; + $this->customers_entity->add_log_visit($cust['id'], $row['cfUid'], $user['uname'], $row['id'], 2, $visit, [], 'wxapp', Receiver_customer_oplogs_model::SUB_TYPE_AUTO_CALL_OUT_WECHAT); + } elseif ($row['cfId'] && $row['cfPlatform'] == Receiver_call_wechat_model::CF_PLATFORM_ADMIN) { //后台 + $admin_id = $row['cfUid']; + $admin = $this->sys_admin_model->get(['id' => $admin_id]); + $addData = array( + 'uid' => $admin_id, + 'uname' => $admin['username'] ? $admin['username'] : '', + 'type' => 2,//类型 0 普通 1短信 2电话 + 'sub_type' => Receiver_customer_oplogs_model::SUB_TYPE_AUTO_CALL_OUT_WECHAT, + 'log' => $row['id'], + 'c_time' => time() + ); + if ($row['cfType'] == Receiver_call_wechat_model::CF_TYPE_CLUE) {//线索拨打电话回调 + $this->load->model('receiver/receiver_clue_oplogs_model', 'mdOplogs'); + $addData['clue_id'] = $row['cfId']; + } else if ($row['cfType'] == Receiver_call_wechat_model::CF_TYPE_CUSTOMERS) {//客户拨打电话回调 + $this->load->model('receiver/receiver_customer_oplogs_model', 'mdOplogs'); + $addData['customer_id'] = $row['cfId']; + $addData['cf_platform'] = Receiver_call_wechat_model::CF_PLATFORM_ADMIN; + } + $this->mdOplogs->add($addData); + } + } catch (Exception $e) { + debug_log("错误信息: " . $e->getMessage(), $logPath, $this->logDir); + } + $data = ['code' => 200, 'msg' => '成功', 'data' => []]; + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($data, JSON_UNESCAPED_UNICODE)); + } + + // 下载录音文件 + public function downVideo() + { + $logPath = "downVideo.log"; + $where = array( + "recordUrl" => "", + "voiceId <> ''" => null + ); + $count = $this->callWechat->count($where); + $failed_num = $success_num = $do_num = 0; + if ($count) { + $rows = $this->callWechat->select($where, 'id asc', 1, 20, 'id,voiceId,reqId'); + $callOutWechat = new CallOutWechat(); + foreach ($rows as $key => $val) { + try { + debug_log("下载录音文件: " . $val['id'], $logPath, $this->logDir); + $req = $callOutWechat->getAudio($val['voiceId']); + if (!$req->getData()) { + throw new Exception('获取录音文件失败'); + } + $videoData = $req->getData(); + $qiniu = new Qiniu(['type' => 'video']); + $filename = $qiniu->getFileName($val['reqId'], 'mp3', 'call_out_wechat_video_'); + $q_res = $qiniu->save($filename, $videoData); + if (!$q_res || !$q_res['url']) { + throw new Exception('文件上传七牛失败'); + } + $recUrl = $q_res['url']; + $this->callWechat->update(['recordUrl' => $recUrl], ['id' => $val['id']]); + debug_log("录音文件保存成功: " . $recUrl, $logPath, $this->logDir); + $success_num++; + } catch (Exception $e) { + debug_log("错误信息: " . $e->getMessage(), $logPath, $this->logDir); + $failed_num++; + } + $do_num++; + } + } + echo "do_num:{$do_num},success_num:{$success_num},failed_num:{$failed_num}"; + } + public function test() { $logPath = "test.log"; diff --git a/api/controllers/plan/Plan.php b/api/controllers/plan/Plan.php index 851d5505..ebf236ae 100644 --- a/api/controllers/plan/Plan.php +++ b/api/controllers/plan/Plan.php @@ -43,6 +43,8 @@ class Plan extends CI_Controller $plan[] = array('url' => base_url(array('plan', 'report', 'index')), 'interval' => 20); //门店日报 + $plan[] = array('url' => base_url(array('plan', 'callBack', 'downVideo')), 'interval' => 1); //外呼下载录音文件 + $this->plan = $plan; } diff --git a/api/controllers/wxapp/licheb/Customerlogs.php b/api/controllers/wxapp/licheb/Customerlogs.php index ff411cd4..d9e05a07 100644 --- a/api/controllers/wxapp/licheb/Customerlogs.php +++ b/api/controllers/wxapp/licheb/Customerlogs.php @@ -55,16 +55,10 @@ class Customerlogs extends Wxapp } if ($val['type'] == 2) { $content = '拨打电话'; - if ($val['sub_type'] == Receiver_customer_oplogs_model::SUB_TYPE_XZ) { - $rec_row = $this->receiver_xz_model->get(['id' => $val['log']], 'rec_url,duration'); - $rec_row['rec_url'] && $record = $rec_row['rec_url']; - $rec_row['duration'] && $second = intval($rec_row['duration'] / 1000); - } else { - $rec_row = $this->receiver_yx_model->get(['id' => $val['log']], 'rec_url,duration'); - $rec_row['rec_url'] && $record = get_yx_video($rec_row['rec_url']); - $rec_row['duration'] && $second = intval($rec_row['duration']); - } - !$rec_row['duration'] && $content .= '(未接通)'; + list($rec_url, $rec_text, $duration) = $this->customer_oplogs_model->getRecordUrl($val['id']); + $rec_url && $record = $rec_url; + $duration && $second = intval($duration); + !$duration && $content .= '(未接通)'; } $comments = []; $res = $this->mdComments->select(['pid' => $val['id'], 'status' => 1, 'type' => 0], 'id asc', 0, 0 diff --git a/api/controllers/wxapp/licheb/Xz.php b/api/controllers/wxapp/licheb/Xz.php index 002e42d6..afd97e6c 100644 --- a/api/controllers/wxapp/licheb/Xz.php +++ b/api/controllers/wxapp/licheb/Xz.php @@ -23,13 +23,17 @@ class Xz extends Wxapp $this->load->model('receiver/receiver_customers_model', 'customers_model'); $this->load->model('receiver/receiver_xz_model'); + $this->load->library('carHome/callOutWechat'); + $this->load->model('sys/sys_config_model', 'confModel'); + $this->load->model('receiver/receiver_call_wechat_model', 'callWechat'); $this->log_file = 'call.log'; } protected function get() { - throw new Hd_Exception('系统调整,暂停服务', API_CODE_FAIL); - return; + //平安外呼 +// throw new Hd_Exception('系统调整,暂停服务', API_CODE_FAIL); +// return; $id = $this->input_param('id'); $type = intval($this->input_param('type')); !$type && $type = 0; @@ -47,42 +51,74 @@ class Xz extends Wxapp if ($json && $json['hdy'] && $json['hdy']['tel']) { $user_mobile = $json['hdy']['tel']; } - $redis = &load_cache('redis'); - $cache_key = "XZ_LICHEB_MOBILEA_{$user_mobile}_MOBILEB_{$customer_mobile}_{$admin_id}"; - $call_mobile = $redis->get($cache_key); - if (!$call_mobile) { - $this->config->load('xcall'); - $params = [ - 'app_id' => $this->config->item('app_id'), - 'app_key' => $this->config->item('app_key'), - ]; - $seq_id = create_order_no(); - $xcall = new Xcall($params); - $maxBindingTime = 10;//绑定时间 - $result = $xcall->ABXbind($user_mobile, $customer_mobile, $seq_id, $maxBindingTime); - if (!$result['code']) { //绑定失败 - debug_log("xz_failed_bind:customer_mobile【{$customer_mobile}】", $this->log_file); - debug_log("xz_result:" . json_encode($result, JSON_UNESCAPED_UNICODE), $this->log_file); - throw new Hd_Exception($result['msg'], API_CODE_FAIL); - } else { - $this->data['middlenumber'] = $result['data']['virtualMobile']; - $add_data = [ - 'call_id' => $seq_id, - 'display_number' => $result['data']['virtualMobile'], - 'biz_id' => $row['biz_id'], - 'cf_id' => $cus_id, - 'cf_uid' => $admin_id, - 'cf_title' => $cf_title, - 'cf_platform' => 'api', - 'json_data' => json_encode(['uname' => $session['uname']], JSON_UNESCAPED_UNICODE), - 'c_time' => time() - ]; - $this->receiver_xz_model->add($add_data); - $call_mobile = $result['data']['virtualMobile']; - $redis->save($cache_key, $call_mobile, $maxBindingTime * 60); - } + //平安外呼 + $cityId = $row['city_id'] ?: 350200; + $requestId = create_order_no($cityId, 'licheb'); + //获取绑定配置信息 + $configRow = $this->confModel->get(array('k' => Sys_config_model::CALL_CONFIG_KEY)); + $jsonData = $configRow['v'] ? json_decode($configRow['v'], true) : []; + $callBackPhoneNo = $jsonData['callBackPhoneNo'] ?: ''; + $callTime = $jsonData['callTime'] ?: 2; + $callbackTime = $jsonData['callbackTime'] ?: 60; + $callOutWechat = new CallOutWechat(); + $req = $callOutWechat->bind($requestId, $row['cid'], $user_mobile, $customer_mobile, $callBackPhoneNo, $callTime, $callbackTime); + if (!$req->isSuccess()) { + throw new Hd_Exception($req->getMessage(), API_CODE_FAIL); } - $data['mobile'] = $call_mobile; + $data['mobile'] = $req->getData()['x']; + if (!$data['mobile']) { + throw new Hd_Exception('获取虚拟号码失败', API_CODE_FAIL); + } + //添加记录 + $add_data = [ + 'reqId' => $requestId, + 'cfId' => $cus_id, + 'cfUid' => $admin_id, + 'cfType' => Receiver_call_wechat_model::CF_TYPE_CUSTOMERS, + 'cfPlatform' => Receiver_call_wechat_model::CF_PLATFORM_WX_APP, + 'createTime' => time() + ]; + $req = $this->callWechat->add($add_data); + if (!is_numeric($req)) { + throw new Hd_Exception('保存记录失败', API_CODE_FAIL); + } + return $data; +// $redis = &load_cache('redis'); +// $cache_key = "XZ_LICHEB_MOBILEA_{$user_mobile}_MOBILEB_{$customer_mobile}_{$admin_id}"; +// $call_mobile = $redis->get($cache_key); +// if (!$call_mobile) { +// $this->config->load('xcall'); +// $params = [ +// 'app_id' => $this->config->item('app_id'), +// 'app_key' => $this->config->item('app_key'), +// ]; +// $seq_id = create_order_no(); +// $xcall = new Xcall($params); +// $maxBindingTime = 10;//绑定时间 +// $result = $xcall->ABXbind($user_mobile, $customer_mobile, $seq_id, $maxBindingTime); +// if (!$result['code']) { //绑定失败 +// debug_log("xz_failed_bind:customer_mobile【{$customer_mobile}】", $this->log_file); +// debug_log("xz_result:" . json_encode($result, JSON_UNESCAPED_UNICODE), $this->log_file); +// throw new Hd_Exception($result['msg'], API_CODE_FAIL); +// } else { +// $this->data['middlenumber'] = $result['data']['virtualMobile']; +// $add_data = [ +// 'call_id' => $seq_id, +// 'display_number' => $result['data']['virtualMobile'], +// 'biz_id' => $row['biz_id'], +// 'cf_id' => $cus_id, +// 'cf_uid' => $admin_id, +// 'cf_title' => $cf_title, +// 'cf_platform' => 'api', +// 'json_data' => json_encode(['uname' => $session['uname']], JSON_UNESCAPED_UNICODE), +// 'c_time' => time() +// ]; +// $this->receiver_xz_model->add($add_data); +// $call_mobile = $result['data']['virtualMobile']; +// $redis->save($cache_key, $call_mobile, $maxBindingTime * 60); +// } +// } +// $data['mobile'] = $call_mobile; return $data; } diff --git a/common/libraries/carHome/CallOut.php b/common/libraries/carHome/CallOut.php index dfe2af60..f275baa2 100644 --- a/common/libraries/carHome/CallOut.php +++ b/common/libraries/carHome/CallOut.php @@ -23,6 +23,7 @@ class CallOut // 测试环境: // 汽车之家外呼接口(互联网主线): http://202.105.128.251:18081/bas_car_home_ping_tai/car/v1/call // 汽车之家外呼接口(互联网备线): http://218.18.234.155:18081/bas_car_home_ping_tai/car/v1/call + private $logDir = 'carHome'; public function __construct() { @@ -34,30 +35,41 @@ class CallOut } } - public function call() + public function call($orderId, $requestId, $agentPhoneNo, $customerPhoneNo, $agentId = '', $agentUm = '', $pushUrl = '') { + $logPath = 'call.log'; try { - $agentPhoneNo = '18350451617'; - $customerPhoneNo = '13365081602'; +// $agentPhoneNo = '18350451617'; +// $customerPhoneNo = '13365081602'; + debug_log("加密前手机号:" . json_encode(['agentPhoneNo' => $agentPhoneNo, 'customerPhoneNo' => $customerPhoneNo]), $logPath, $this->logDir); $enAgentPhoneNo = $this->aesEcbPkcs5Encrypt($agentPhoneNo, $this->aesKey); $enCustomerPhoneNo = $this->aesEcbPkcs5Encrypt($customerPhoneNo, $this->aesKey); $params = [ - 'orderId' => md5(time()), //必选 String 订单号 + 'orderId' => $orderId, //必选 String 订单号 'agentPhoneNo' => $enAgentPhoneNo, //必选 String 坐席分机。坐席分机如采用AES加密,汽车之家系统传加密后的号码 'customerPhoneNo' => $enCustomerPhoneNo, //必选 String 客户手机号码。加密规则与坐席分机一致 -// 'agentId' => '', //备选 String 坐席工号(汽车之家上报开通的中兴平台唯一cti号码) -// 'agentUm' => '', //备选 String 坐席Um(汽车之家人员um账号) 'displayedPhoneNo' => '0', //必选 String 外显号码(传“0”和空值均为云中继外显) ]; + $agentId && $params['agentId'] = $agentId; //备选 String 坐席工号(汽车之家上报开通的中兴平台唯一cti号码) + $agentUm && $params['agentUm'] = $agentUm; //备选 String 坐席Um(汽车之家人员um账号) + $pushUrl && $params['pushUrl'] = $pushUrl; //如果有传此字段,那么推送话单数据,就推到这里 $reqParams = [ 'ctiType' => $this->ctiType, - 'requestId' => time(), + 'requestId' => $requestId, 'para' => $params ]; - $req = $this->send($this->baseUrl, $reqParams, self::METHOD_POST); - print_r($req); + debug_log("请求参数:" . json_encode($reqParams, JSON_UNESCAPED_UNICODE), $logPath, $this->logDir); + list($req, $header, $httpStatus) = $this->send($this->baseUrl, $reqParams, self::METHOD_POST); + debug_log("响应状态码:" . $httpStatus, $logPath, $this->logDir); + debug_log("响应结果:" . $req, $logPath, $this->logDir); + $reqArr = json_decode($req, true); + if (isset($reqArr['code']) && intval($reqArr['code']) == 200) { + return new Myresponse(EXIT_SUCCESS, '操作成功', $reqArr); + } else { + throw new Exception($reqArr['msg']); + } } catch (\Exception $e) { - + return new MyResponse(EXIT_ERROR, $e->getMessage()); } } diff --git a/common/libraries/carHome/CallOutWechat.php b/common/libraries/carHome/CallOutWechat.php new file mode 100644 index 00000000..0c73a200 --- /dev/null +++ b/common/libraries/carHome/CallOutWechat.php @@ -0,0 +1,224 @@ +ci = &get_instance(); + if (!is_product()) { //测试环境 + $this->baseUrl = 'http://61.144.161.163:18098/crm-api/'; + $this->belongPool = 2; + } + $this->ci->load->library('myResponse'); + $this->redis = &load_cache(); + } + + /** + * 获取token + * @return MyResponse + */ + public function getToken() + { + try { + $cKey = "AUTO_OUT_CALL_TOKEN"; + $token = $this->redis->get($cKey); + if (!$token) { + $url = $this->baseUrl . self::LOGIN_URL; + $enPassword = $this->encryption($this->password); + $data = [ + 'username' => $this->useName, + 'password' => $enPassword, + ]; + list($req, $code) = $this->send($url, $data, self::METHOD_POST, false); + if (!$code || $code != 200) { + throw new Exception($req); + } + $reqData = json_decode($req, true); + if ($reqData['code'] != self::SUCCESS_CODE) { + throw new Exception($req['msg'] ?: '获取token失败'); + } + $expires = (int)($reqData['expires'] / 1000); + $timeOut = $expires - time(); + $token = $reqData['token']; + $this->redis->save($cKey, $token, $timeOut); + } + return new MyRESPONSE(EXIT_SUCCESS, '提交成功', ['token' => $token]); + } catch (Exception $e) { + return new MyResponse(EXIT_ERROR, $e->getMessage()); + } + } + + public function outBind($requestId, $orderId, $agentPhoneNo, $customerPhoneNo, $callBackPhoneNo = '', $callbackTime = 5) + { + try { + $url = $this->baseUrl . self::OUT_BOUND_URL; + $enAgentPhoneNo = $this->encryption($agentPhoneNo); + $enCustomerPhoneNo = $this->encryption($customerPhoneNo); + $reqData = [ + 'requestId' => $requestId, + 'para' => [ + //订单号(通话唯一标识,外呼结果回传) + 'orderId' => $orderId, + //agentPhoneNo 为坐席分机,可传坐席接听手机号码或者固话。坐席分机如采用 AES 加密,调用系统传加密后的号码 + 'agentPhoneNo' => $enAgentPhoneNo, + //回呼号码,客户回拨到号码,为空则回到坐席号码,加密规则与坐席分机一致 + 'callBackPhoneNo' => $callBackPhoneNo, + //客户号码,加密规则与坐席分机一致 + 'customerPhoneNo' => $enCustomerPhoneNo, + //坐席工号(无坐席可以为空) + 'agentId' => '', + //外显类型(根据号码情况传) 0:云中继,固话外显 1:手机号外显 + 'displayedPhoneNo' => '0', + //int 平台分配 + 'belongPool' => $this->belongPool, + //int 回拨绑定时长(分钟) + 'callbackTime' => $callbackTime, + ] + ]; + list($req, $code) = $this->send($url, $reqData, self::METHOD_POST); + if ($code != 200) { + throw new Exception($req); + } + $reqData = json_decode($req, true); + if ($reqData['code'] != self::SUCCESS_CODE) { + throw new Exception($req['msg'] ?: '绑定失败'); + } + return new MyRESPONSE(EXIT_SUCCESS, '提交成功'); + } catch (Exception $e) { + return new MyResponse(EXIT_ERROR, $e->getMessage()); + } + } + + /** + * 单呼绑定 + * @return MyResponse + */ + public function bind($requestId, $orderId, $agentPhoneNo, $customerPhoneNo, $callBackPhoneNo = '', $callTime = 5, $callbackTime = 5) + { + try { + $url = $this->baseUrl . self::BIND_URL; + $enAgentPhoneNo = $this->encryption($agentPhoneNo); + $enCustomerPhoneNo = $this->encryption($customerPhoneNo); + $reqData = [ + 'requestId' => $requestId, + 'para' => [ + //订单号(通话唯一标识,外呼结果回传) + 'orderId' => $orderId, + //agentPhoneNo 为坐席分机,可传坐席接听手机号码或者固话。坐席分机如采用 AES 加密,调用系统传加密后的号码 + 'agentPhoneNo' => $enAgentPhoneNo, + //回呼号码,客户回拨到号码,为空则回到坐席号码,加密规则与坐席分机一致 + 'callBackPhoneNo' => $callBackPhoneNo, + //客户号码,加密规则与坐席分机一致 + 'customerPhoneNo' => $enCustomerPhoneNo, + //坐席工号(无坐席可以为空) + 'agentId' => '', + //外显类型(根据号码情况传) 0:云中继,固话外显 1:手机号外显 + 'displayedPhoneNo' => '0', + //int 平台分配 + 'belongPool' => $this->belongPool, + //int 外呼绑定时长(分钟) + 'callTime' => $callTime, + //int 回拨绑定时长(分钟) + 'callbackTime' => $callbackTime, + ] + ]; + list($req, $code) = $this->send($url, $reqData, self::METHOD_POST); + if ($code != 200) { + throw new Exception($req); + } + $reqData = json_decode($req, true); + if ($reqData['code'] != self::SUCCESS_CODE) { + throw new Exception($req['msg'] ?: '绑定失败'); + } + return new MyRESPONSE(EXIT_SUCCESS, '提交成功', $reqData['data']); + } catch (Exception $e) { + return new MyResponse(EXIT_ERROR, $e->getMessage()); + } + } + + public function getAudio($recKeyStr) + { + try { + $url = $this->baseUrl . sprintf(self::GET_AUDIO_URL, $recKeyStr); + list($req, $code) = $this->send($url, [], self::METHOD_GET, true, false); + return new MyRESPONSE(EXIT_SUCCESS, '提交成功', $req); + } catch (Exception $e) { + var_dump($e); + return new MyResponse(EXIT_ERROR, $e->getMessage()); + } + } + + /** + * 加密 + * + * @param string $data + * @return string + */ + public function encryption($data) + { + $encrypted = openssl_encrypt($data, 'AES-128-CBC', $this->aesKey, OPENSSL_RAW_DATA, $this->iv); + // 转换为16进制表示 + return bin2hex($encrypted); + } + + + public function send($url, $data = [], $type = self::METHOD_GET, $needToken = true, $saveLog = true) + { + $logPath = "callOutWechatSend.log"; + try { + $headers = [ + 'Content-Type' => 'application/json' + ]; + if ($needToken) { + $tokenReq = $this->getToken(); + if (!$tokenReq->isSuccess()) { + throw new Exception($tokenReq->getMessage()); + } + $headers['Authorization'] = 'Bearer ' . $tokenReq->getData()['token']; + } + $options = [ + 'headers' => $headers, + ]; + if ($data) { + $options['json'] = $data; + } + $client = new Client(); + debug_log("请求地址: {$url}", $logPath, $this->logDir); + debug_log("请求参数:" . json_encode($data, JSON_UNESCAPED_UNICODE), $logPath, $this->logDir); + $response = $client->request($type, $url, $options); + $responseContent = $response->getBody()->getContents(); + if ($saveLog) { + debug_log("返回结果:" . $responseContent, $logPath, $this->logDir); + } + return [$responseContent, $response->getStatusCode()]; + } catch (Exception $e) { + debug_log($e->getMessage(), $logPath, $this->logDir); + return [$e->getMessage(), 0]; + } + } +} \ No newline at end of file diff --git a/common/models/receiver/Receiver_call_model.php b/common/models/receiver/Receiver_call_model.php new file mode 100644 index 00000000..d78d163b --- /dev/null +++ b/common/models/receiver/Receiver_call_model.php @@ -0,0 +1,20 @@ + '通话未完成', 1 => '通话完成', 2 => '通话失败']; + const callTypeList = [0 => '呼入', 1 => '呼出']; + const hangupTypeList = [0 => '客户挂断', 1 => '坐席挂断']; + + + public function __construct() + { + parent::__construct($this->table_name, 'default'); + } +} diff --git a/common/models/receiver/Receiver_call_wechat_model.php b/common/models/receiver/Receiver_call_wechat_model.php new file mode 100644 index 00000000..3ff39c24 --- /dev/null +++ b/common/models/receiver/Receiver_call_wechat_model.php @@ -0,0 +1,25 @@ + '通话未完成', 1 => '通话完成', 2 => '通话失败']; + const callTypeList = [0 => '呼入', 1 => '呼出']; + const hangupTypeList = [0 => '客户挂断', 1 => '坐席挂断']; + //状态 0 未拨打 1 已拨打 + const STATUS_WAIT = 0; + const STATUS_FINISH = 1; + + + public function __construct() + { + parent::__construct($this->table_name, 'default'); + } +} diff --git a/common/models/receiver/Receiver_clue_oplogs_model.php b/common/models/receiver/Receiver_clue_oplogs_model.php index f2d00d03..9305ad9d 100644 --- a/common/models/receiver/Receiver_clue_oplogs_model.php +++ b/common/models/receiver/Receiver_clue_oplogs_model.php @@ -6,11 +6,14 @@ * Time: 13:47 */ -defined('BASEPATH') OR exit('No direct script access allowed'); +defined('BASEPATH') or exit('No direct script access allowed'); class Receiver_clue_oplogs_model extends HD_Model { private $table_name = 'lc_receiver_clue_oplogs'; + const OP_TYPE_AUTO_CALL = 4; //汽车之家外呼 + const SUB_TYPE_XZ = 'xz'; + const SUB_TYPE_AUTO_CALL_OUT_WECHAT = 'call_out_wechat'; //平安外呼 小程序和sadmin后台 public function __construct() { @@ -25,7 +28,43 @@ class Receiver_clue_oplogs_model extends HD_Model */ public function typeAry() { - return array(0 => '小记', 1 => '发短信', 2 => '拨打电话', 3 => '新增', 9 => '系统'); + //4 汽车之家外呼拨打拨打电话 + return array(0 => '小记', 1 => '发短信', 2 => '拨打电话', 3 => '新增', 4 => '拨打电话', 9 => '系统'); } + /** + * 获取录音文件 + * @param $id + * @return array + */ + public function getRecordUrl($id) + { + $this->load->model('receiver/receiver_yx_model'); + $this->load->model('receiver/receiver_xz_model'); + $this->load->model('receiver/receiver_call_wechat_model'); + $row = $this->get(['id' => $id]); + $duration = $rec_text = $rec_url = ''; + if ($row['type'] == 2) { + $record = ''; + if ($row['sub_type'] == self::SUB_TYPE_XZ) { + $rec_row = $this->receiver_xz_model->get(['id' => $row['log']], 'rec_url,duration'); + $rec_row['rec_url'] && $record = $rec_row['rec_url']; + $rec_row['duration'] = intval($rec_row['duration'] / 1000); + } elseif ($row['sub_type'] == self::SUB_TYPE_AUTO_CALL_OUT_WECHAT) { + $rec_row = $this->receiver_call_wechat_model->get(['id' => $row['log']], 'recordUrl as rec_url,telDuration as duration'); + $rec_row['rec_url'] && $record = $rec_row['rec_url']; + } else { + $rec_row = $this->receiver_yx_model->get(['id' => $row['log']], 'rec_url,duration'); + $rec_row['rec_url'] && $record = get_yx_video($rec_row['rec_url']); + } + $duration = $rec_row['duration']; + if ($rec_row['duration']) { + $record && $rec_url = $record; + !$rec_row['rec_url'] && $rec_text = '录音暂未生成'; + } else { + $rec_text = '未接通'; + } + } + return [$rec_url, $rec_text, $duration]; + } } diff --git a/common/models/receiver/Receiver_customer_oplogs_model.php b/common/models/receiver/Receiver_customer_oplogs_model.php index 6931cae7..f5660db6 100644 --- a/common/models/receiver/Receiver_customer_oplogs_model.php +++ b/common/models/receiver/Receiver_customer_oplogs_model.php @@ -13,6 +13,7 @@ class Receiver_customer_oplogs_model extends HD_Model private $table_name = 'lc_receiver_customer_oplogs'; const SUB_TYPE_XZ = 'xz'; + const SUB_TYPE_AUTO_CALL_OUT_WECHAT = 'call_out_wechat'; //平安外呼 小程序和sadmin后台 public function __construct() { @@ -37,4 +38,39 @@ class Receiver_customer_oplogs_model extends HD_Model } } + /** + * 获取录音文件 + * @param $id + * @return array + */ + public function getRecordUrl($id) + { + $this->load->model('receiver/receiver_yx_model'); + $this->load->model('receiver/receiver_xz_model'); + $this->load->model('receiver/receiver_call_wechat_model'); + $row = $this->get(['id' => $id]); + $duration = $rec_text = $rec_url = ''; + if ($row['type'] == 2) { + $record = ''; + if ($row['sub_type'] == self::SUB_TYPE_XZ) { + $rec_row = $this->receiver_xz_model->get(['id' => $row['log']], 'rec_url,duration'); + $rec_row['rec_url'] && $record = $rec_row['rec_url']; + $rec_row['duration'] = intval($rec_row['duration'] / 1000); + } elseif ($row['sub_type'] == self::SUB_TYPE_AUTO_CALL_OUT_WECHAT) { + $rec_row = $this->receiver_call_wechat_model->get(['id' => $row['log']], 'recordUrl as rec_url,telDuration as duration'); + $rec_row['rec_url'] && $record = $rec_row['rec_url']; + } else { + $rec_row = $this->receiver_yx_model->get(['id' => $row['log']], 'rec_url,duration'); + $rec_row['rec_url'] && $record = get_yx_video($rec_row['rec_url']); + } + $duration = $rec_row['duration']; + if ($rec_row['duration']) { + $record && $rec_url = $record; + !$rec_row['rec_url'] && $rec_text = '录音暂未生成'; + } else { + $rec_text = '未接通'; + } + } + return [$rec_url, $rec_text, $duration]; + } } diff --git a/common/models/sys/Sys_config_model.php b/common/models/sys/Sys_config_model.php index 8555b10a..b229aa8f 100644 --- a/common/models/sys/Sys_config_model.php +++ b/common/models/sys/Sys_config_model.php @@ -5,13 +5,15 @@ * Date: 2018/11/5 * Time: 13:47 */ - -defined('BASEPATH') OR exit('No direct script access allowed'); - + +defined('BASEPATH') or exit('No direct script access allowed'); + class Sys_config_model extends HD_Model { private $table_name = 'lc_sys_config'; + const CALL_CONFIG_KEY = 'callConfig'; // 呼叫配置 + public function __construct() { parent::__construct($this->table_name, 'default');