平安外呼系统
This commit is contained in:
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
defined('BASEPATH') or exit('No direct script access allowed');
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
|
||||
/**
|
||||
* 汽车之家外呼接口(小程序)
|
||||
*/
|
||||
class CallOutWechat
|
||||
{
|
||||
const METHOD_GET = 'GET';
|
||||
const METHOD_POST = 'POST';
|
||||
|
||||
protected $baseUrl = ''; //正式接口地址
|
||||
protected $aesKey = 'Crm0123456Abcdef'; //AES秘钥
|
||||
protected $iv = 'Crm0123456Abcdef';
|
||||
protected $belongPool;
|
||||
protected $useName = 'carhome';
|
||||
protected $password = 'Yzy@95511';
|
||||
protected $ci;
|
||||
protected $redis;
|
||||
private $logDir = 'carHome';
|
||||
const LOGIN_URL = 'login'; //登录接口
|
||||
const OUT_BOUND_URL = 'call/v1.0/outbound'; //双呼接口
|
||||
const BIND_URL = 'call/v1.0/bind'; //单呼接口
|
||||
const GET_AUDIO_URL = 'call/v1.0/getAudio?reckeystr=%s'; //获取音频接口
|
||||
const SUCCESS_CODE = 200;//接口成功返回码
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->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];
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user