Files
2025-09-15 15:06:02 +08:00

226 lines
9.3 KiB
PHP

<?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 = 'http://61.144.161.163:28098/crm-api/'; //正式接口地址
protected $aesKey = 'Crm0123456Abcdef'; //AES秘钥
protected $iv = 'Crm0123456Abcdef';
protected $belongPool = 16;
protected $useName = 'HAOCHEBU';
protected $password = 'nxoBq2cp@xYC#UZ*5N';
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->useName = 'carhome';
$this->password = 'Yzy@95511';
}
$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];
}
}
}