145 lines
6.4 KiB
PHP
145 lines
6.4 KiB
PHP
<?php
|
||
defined('BASEPATH') or exit('No direct script access allowed');
|
||
|
||
use GuzzleHttp\Client;
|
||
use GuzzleHttp\Exception\GuzzleException;
|
||
|
||
/**
|
||
* 汽车之家外呼接口
|
||
*/
|
||
class CallOut
|
||
{
|
||
const METHOD_GET = 'GET';
|
||
const METHOD_POST = 'POST';
|
||
|
||
protected $baseUrl = 'http://202.105.128.251:18082/bas_car_home_ping_tai/car/v1/call'; //正式接口地址
|
||
protected $aesKey = 'AmUFhqX2IOI48BwdgAXVsQgvncCD0f5X'; //AES秘钥
|
||
protected $ctiType = 'QCZJ'; //平台类型,固定QCZJ
|
||
protected $ci;
|
||
protected $client;
|
||
// 生产环境:
|
||
// 汽车之家外呼接口(互联网主线): http://202.105.128.251:18082/bas_car_home_ping_tai/car/v1/call
|
||
// 汽车之家外呼接口(互联网备线): http://218.18.234.155:18082/bas_car_home_ping_tai/car/v1/call
|
||
// 测试环境:
|
||
// 汽车之家外呼接口(互联网主线): 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';
|
||
private $pushUrl;
|
||
|
||
public function __construct()
|
||
{
|
||
$this->ci = &get_instance();
|
||
$this->client = new Client();
|
||
if (!is_product()) { //测试环境
|
||
$this->baseUrl = 'http://202.105.128.251:18081/bas_car_home_ping_tai/car/v1/call';
|
||
$this->aesKey = 'JKCDlCxTvwNumLQVAMQltfpuOSCSa6J9';
|
||
}
|
||
$this->pushUrl = http_host_com() . "plan/callBack";
|
||
}
|
||
|
||
public function call($orderId, $requestId, $agentPhoneNo, $customerPhoneNo, $agentId = '', $agentUm = '', $pushUrl = '')
|
||
{
|
||
$logPath = 'call.log';
|
||
try {
|
||
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' => $orderId, //必选 String 订单号
|
||
'agentPhoneNo' => $enAgentPhoneNo, //必选 String 坐席分机。坐席分机如采用AES加密,汽车之家系统传加密后的号码
|
||
'customerPhoneNo' => $enCustomerPhoneNo, //必选 String 客户手机号码。加密规则与坐席分机一致
|
||
'displayedPhoneNo' => '0', //必选 String 外显号码(传“0”和空值均为云中继外显)
|
||
];
|
||
$agentId && $params['agentId'] = $agentId; //备选 String 坐席工号(汽车之家上报开通的中兴平台唯一cti号码)
|
||
$agentUm && $params['agentUm'] = $agentUm; //备选 String 坐席Um(汽车之家人员um账号)
|
||
if (!$pushUrl) {
|
||
$params['pushUrl'] = $this->pushUrl; //如果有传此字段,那么推送话单数据,就推到这里
|
||
}
|
||
$reqParams = [
|
||
'ctiType' => $this->ctiType,
|
||
'requestId' => $requestId,
|
||
'para' => $params
|
||
];
|
||
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());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* AES-ECB模式加密,使用PKCS5Padding填充
|
||
* @param string $data 待加密的数据
|
||
* @param string $key 加密密钥(16/24/32字节,对应AES-128/192/256)
|
||
* @return string 加密后的base64字符串
|
||
*/
|
||
function aesEcbPkcs5Encrypt($data, $key)
|
||
{
|
||
// 检查密钥长度
|
||
$keyLength = strlen($key);
|
||
if (!in_array($keyLength, [16, 24, 32])) {
|
||
throw new InvalidArgumentException("密钥长度必须是16、24或32字节");
|
||
}
|
||
|
||
// 根据密钥长度确定AES模式
|
||
$cipher = 'AES-' . ($keyLength * 8) . '-ECB';
|
||
|
||
// 执行加密,OPENSSL_RAW_DATA表示输出原始二进制,默认使用PKCS5填充
|
||
$encrypted = openssl_encrypt($data, $cipher, $key, OPENSSL_RAW_DATA, '');
|
||
|
||
// 返回base64编码结果(也可根据需要改为bin2hex输出16进制)
|
||
return bin2hex($encrypted);
|
||
}
|
||
|
||
/**
|
||
* AES-ECB模式解密,对应HEX格式的加密数据
|
||
* @param string $hexData 加密后的十六进制字符串
|
||
* @param string $key 解密密钥(与加密密钥相同)
|
||
* @return string 解密后的原始数据
|
||
*/
|
||
function aesEcbPkcs5DecryptFromHex($hexData, $key)
|
||
{
|
||
$keyLength = strlen($key);
|
||
if (!in_array($keyLength, [16, 24, 32])) {
|
||
throw new InvalidArgumentException("密钥长度必须是16、24或32字节");
|
||
}
|
||
|
||
$cipher = 'AES-' . ($keyLength * 8) . '-ECB';
|
||
|
||
// 先将十六进制转回二进制,再解密
|
||
$decrypted = openssl_decrypt(hex2bin($hexData), $cipher, $key, OPENSSL_RAW_DATA, '');
|
||
return $decrypted;
|
||
}
|
||
|
||
public function send($url, $data = [], $type = self::METHOD_GET)
|
||
{
|
||
try {
|
||
$options = [
|
||
'headers' => [
|
||
'Content-Type' => 'application/json'
|
||
],
|
||
];
|
||
if ($data) {
|
||
$options['json'] = $data;
|
||
}
|
||
$response = $this->client->request($type, $url, $options);
|
||
// $response = $this->client->post($url, [
|
||
// 'form_params' => $data,
|
||
// // 可选:设置超时时间
|
||
// 'timeout' => 5.0,
|
||
// ]);
|
||
return [$response->getBody()->getContents(), $options, $response->getStatusCode()];
|
||
} catch (Exception $e) {
|
||
debug_log($e->getMessage() . ' URL: ' . $url . ' Data: ' . json_encode($data));
|
||
throw $e;
|
||
}
|
||
}
|
||
} |