Files
shop-platform/src/addon/aikefu/api/controller/Kefu.php

314 lines
10 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace addon\aikefu\api\controller;
use addon\aikefu\model\Config as KefuConfigModel;
use addon\aikefu\model\Conversation as KefuConversationModel;
use addon\aikefu\model\Message as KefuMessageModel;
use app\api\controller\BaseApi;
class Kefu extends BaseApi
{
/**
* 封装curl请求方法
* @param string $url 请求URL
* @param string $method 请求方法
* @param array $data 请求数据
* @param array $headers 请求头
* @return string 响应内容
*/
private function curlRequest($url, $method = 'GET', $data = [], $headers = [])
{
$ch = curl_init();
// 设置URL
curl_setopt($ch, CURLOPT_URL, $url);
// 设置请求方法
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
// 设置POST数据
if ($method === 'POST' && !empty($data)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, is_array($data) ? json_encode($data) : $data);
}
// 设置请求头
if (!empty($headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
// 设置返回值
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
// 执行请求
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// 关闭连接
curl_close($ch);
if ($response === false) {
throw new \Exception('Curl请求失败');
}
if ($httpCode >= 400) {
throw new \Exception('HTTP请求失败状态码' . $httpCode);
}
return $response;
}
/**
* 为事件调用初始化属性
* @param array $data 事件数据
*/
public function initializeForEvent($data)
{
if (!empty($data['site_id'])) {
$this->site_id = $data['site_id'] ?? 0;
}
if (!empty($data['member_id'])) {
$this->member_id = $data['member_id'] ?? 0;
}
if (!empty($data['token'])) {
$this->token = $data['token'] ?? '';
}
$this->params = [
'message' => $data['message'] ?? '',
'user_id' => $data['user_id'] ?? '',
'conversation_id' => $data['conversation_id'] ?? '',
'stream' => $data['stream'] ?? false,
];
}
/**
* 智能客服聊天接口
* @return \think\response\Json
*/
public function chat()
{
// 获取请求参数
$message = $this->params['message'] ?? '';
$user_id = $this->params['user_id'] ?? $this->member_id;
$conversation_id = $this->params['conversation_id'] ?? '';
$stream = $this->params['stream'] ?? false;
// 验证参数
if (empty($message)) {
return $this->response($this->error('请输入消息内容'));
}
try {
// 获取智能客服配置
$kefu_config_model = new KefuConfigModel();
$config_info = $kefu_config_model->getConfig($this->site_id)['data']['value'] ?? [];
if (empty($config_info) || $config_info['status'] != 1) {
return $this->response($this->error('智能客服暂未启用'));
}
$config = $config_info;
$apiKey = $config['api_key'];
$baseUrl = $config['base_url'];
$chatEndpoint = $config['chat_endpoint'];
// 构建请求数据
$requestData = [
'inputs' => [],
'query' => $message,
'response_mode' => $stream ? 'streaming' : 'blocking',
'user' => $user_id,
];
// 如果有会话ID添加到请求中
if (!empty($conversation_id)) {
$requestData['conversation_id'] = $conversation_id;
}
// 构建请求头
$headers = [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
];
// 发送请求到Dify API
$url = $baseUrl . $chatEndpoint;
$response = $this->curlRequest($url, 'POST', $requestData, $headers);
// 解析响应
$result = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
return $this->response($this->error('解析响应失败'));
}
// 保存消息记录
$kefu_message_model = new KefuMessageModel();
$kefu_conversation_model = new KefuConversationModel();
// 保存用户消息
$kefu_message_model->addMessage([
'site_id' => $this->site_id,
'user_id' => $user_id,
'conversation_id' => $result['conversation_id'] ?? $conversation_id,
'message_id' => $result['message_id'] ?? '',
'role' => 'user',
'content' => $message,
]);
// 保存机器人回复
$kefu_message_model->addMessage([
'site_id' => $this->site_id,
'user_id' => $user_id,
'conversation_id' => $result['conversation_id'] ?? $conversation_id,
'message_id' => $result['id'] ?? '',
'role' => 'assistant',
'content' => $result['answer'] ?? '',
]);
// 更新会话状态或创建新会话
$conversation_info = $kefu_conversation_model->getConversationInfo([
['site_id', '=', $this->site_id],
['conversation_id', '=', $result['conversation_id'] ?? $conversation_id],
]);
if (empty($conversation_info['data'])) {
// 创建新会话
$kefu_conversation_model->addConversation([
'site_id' => $this->site_id,
'user_id' => $user_id,
'conversation_id' => $result['conversation_id'] ?? '',
'name' => '智能客服会话',
]);
} else {
// 更新会话状态
$kefu_conversation_model->updateConversation([
'status' => 1,
], [
['id', '=', $conversation_info['data']['id']],
]);
}
// 返回成功响应
return $this->response($this->success([
'conversation_id' => $result['conversation_id'] ?? '',
'reply' => $result['answer'] ?? '',
'message_id' => $result['message_id'] ?? '',
'finish_reason' => $result['finish_reason'] ?? '',
'usage' => $result['usage'] ?? [],
]));
} catch (\Exception $e) {
return $this->response($this->error('请求失败:' . $e->getMessage()));
}
}
/**
* 获取会话历史
* @return \think\response\Json
*/
public function getHistory()
{
// 获取请求参数
$conversation_id = $this->params['conversation_id'] ?? '';
$user_id = $this->params['user_id'] ?? $this->member_id;
$limit = $this->params['limit'] ?? 20;
$offset = $this->params['offset'] ?? 0;
// 验证参数
if (empty($conversation_id)) {
return $this->response($this->error('会话ID不能为空'));
}
try {
// 获取会话历史记录
$kefu_message_model = new KefuMessageModel();
$message_list = $kefu_message_model->getMessageList([
['site_id', '=', $this->site_id],
['user_id', '=', $user_id],
['conversation_id', '=', $conversation_id],
], 'id, role, content, create_time', 'create_time asc', $limit, $offset);
// 返回成功响应
return $this->response($this->success([
'messages' => $message_list['data'] ?? [],
'total' => $message_list['total'] ?? 0,
'limit' => $limit,
'offset' => $offset,
]));
} catch (\Exception $e) {
return $this->response($this->error('请求失败:' . $e->getMessage()));
}
}
/**
* 创建新会话
* @return \think\response\Json
*/
public function createConversation()
{
// 获取请求参数
$user_id = $this->params['user_id'] ?? $this->member_id;
try {
// 获取智能客服配置
$kefu_config_model = new KefuConfigModel();
$config_info = $kefu_config_model->getConfig($this->site_id)['data']['value'] ?? [];
if (empty($config_info) || $config_info['status'] != 1) {
return $this->response($this->error('智能客服暂未启用'));
}
$config = $config_info;
$apiKey = $config['api_key'];
$baseUrl = $config['base_url'];
// 构建请求数据
$requestData = [
'name' => '智能客服会话',
'user' => $user_id,
];
// 构建请求头
$headers = [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
];
// 发送请求到Dify API
$url = $baseUrl . '/conversations';
$response = $this->curlRequest($url, 'POST', $requestData, $headers);
// 解析响应
$result = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
return $this->response($this->error('解析响应失败'));
}
// 保存会话记录
$kefu_conversation_model = new KefuConversationModel();
$kefu_conversation_model->addConversation([
'site_id' => $this->site_id,
'user_id' => $user_id,
'conversation_id' => $result['id'] ?? '',
'name' => $result['name'] ?? '智能客服会话',
]);
// 返回成功响应
return $this->response($this->success([
'conversation_id' => $result['id'] ?? '',
'name' => $result['name'] ?? '',
'created_at' => $result['created_at'] ?? '',
]));
} catch (\Exception $e) {
return $this->response($this->error('请求失败:' . $e->getMessage()));
}
}
}