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'; } } public function call($orderId, $requestId, $agentPhoneNo, $customerPhoneNo, $agentId = '', $agentUm = '', $pushUrl = '') { $logPath = 'call.log'; try { // $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' => $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账号) $pushUrl && $params['pushUrl'] = $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; } } }