NetActionCallbackController.cs 6.36 KB
using Microsoft.AspNetCore.Mvc;
using Rcs.Application.Common;
using Rcs.Application.Services.PathFind;
using Rcs.Application.Services.PathFind.Models;

namespace Rcs.Api.Controllers;

/// <summary>
/// 网络动作异步回调API
/// 供第三方系统异步返回网络动作执行结果
/// 固定格式,支持所有动作类型的响应
/// @author zzy
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class NetActionCallbackController : ControllerBase
{
    private readonly ILogger<NetActionCallbackController> _logger;
    private readonly INetActionExecutionService _netActionExecutionService;

    /// <summary>
    /// 构造函数
    /// @author zzy
    /// </summary>
    /// <param name="logger">日志服务</param>
    /// <param name="netActionExecutionService">网络动作执行服务</param>
    public NetActionCallbackController(
        ILogger<NetActionCallbackController> logger,
        INetActionExecutionService netActionExecutionService)
    {
        _logger = logger;
        _netActionExecutionService = netActionExecutionService;
    }

    /// <summary>
    /// 网络动作异步回调接口
    /// 第三方系统执行完网络动作后,通过此接口返回执行结果
    /// </summary>
    /// <param name="request">回调请求</param>
    /// <returns>回调响应</returns>
    /// <remarks>
    /// 回调URL格式: POST /api/net-action/callback
    /// 
    /// 请求示例:
    /// {
    ///     "contextId": "550e8400-e29b-41d4-a716-446655440000:task123:sub456:0:0:action789:abcdef123456",
    ///     "callbackToken": "A1B2C3D4E5F6G7H8",
    ///     "success": true,
    ///     "message": "动作执行成功",
    ///     "businessData": {
    ///         "customField1": "value1",
    ///         "customField2": 123
    ///     },
    ///     "timestamp": "2026-02-06T10:30:00.000Z"
    /// }
    /// 
    /// 响应示例(成功):
    /// {
    ///     "success": true,
    ///     "message": "回调处理成功,已继续发送下一段",
    ///     "action": "Continue"
    /// }
    /// 
    /// 响应示例(失败):
    /// {
    ///     "success": false,
    ///     "message": "回调令牌验证失败",
    ///     "action": "Abort"
    /// }
    /// </remarks>
    [HttpPost("callback")]
    [ProducesResponseType(typeof(NetActionCallbackResponse), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    public async Task<IActionResult> Callback([FromBody] NetActionCallbackRequest request)
    {
        _logger.LogInformation("[网络动作回调] 收到回调请求: ContextId={ContextId}, Success={Success}, Timestamp={Timestamp}",
            request.ContextId, request.Success, request.Timestamp);

        // 验证请求
        if (string.IsNullOrEmpty(request.ContextId))
        {
            return BadRequest(new ApiResponse<object>
            {
                Code = 400,
                Message = "ContextId不能为空",
                Data = null
            });
        }

        if (string.IsNullOrEmpty(request.CallbackToken))
        {
            return BadRequest(new ApiResponse<object>
            {
                Code = 400,
                Message = "CallbackToken不能为空",
                Data = null
            });
        }

        try
        {
            // 处理回调
            var result = await _netActionExecutionService.HandleCallbackAsync(request);

            _logger.LogInformation("[网络动作回调] 处理完成: ContextId={ContextId}, ResultSuccess={ResultSuccess}, Action={Action}",
                request.ContextId, result.Success, result.Action);

            return Ok(result);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "[网络动作回调] 处理异常: ContextId={ContextId}", request.ContextId);

            return StatusCode(500, new NetActionCallbackResponse
            {
                Success = false,
                Message = $"处理异常: {ex.Message}",
                Action = "Retry"
            });
        }
    }

    /// <summary>
    /// 获取网络动作执行状态
    /// 用于第三方系统查询动作执行状态
    /// </summary>
    /// <param name="contextId">上下文ID</param>
    /// <returns>执行状态</returns>
    /// <remarks>
    /// 查询URL格式: GET /api/net-action/status/{contextId}
    /// </remarks>
    [HttpGet("status/{contextId}")]
    [ProducesResponseType(typeof(NetActionExecutionContext), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetStatus(string contextId)
    {
        var context = await _netActionExecutionService.GetExecutionContextAsync(contextId);

        if (context == null)
        {
            return NotFound(new ApiResponse<object>
            {
                Code = 404,
                Message = "执行上下文不存在或已过期",
                Data = null
            });
        }

        return Ok(context);
    }

    /// <summary>
    /// 取消网络动作执行
    /// 用于在特殊情况下取消正在执行的网络动作
    /// </summary>
    /// <param name="contextId">上下文ID</param>
    /// <returns>取消结果</returns>
    /// <remarks>
    /// 取消URL格式: POST /api/net-action/cancel/{contextId}
    /// </remarks>
    [HttpPost("cancel/{contextId}")]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    public async Task<IActionResult> Cancel(string contextId)
    {
        var context = await _netActionExecutionService.GetExecutionContextAsync(contextId);

        if (context == null)
        {
            return NotFound(new ApiResponse<object>
            {
                Code = 404,
                Message = "执行上下文不存在或已过期",
                Data = null
            });
        }

        // 取消网络动作
        var count = await _netActionExecutionService.CancelTaskNetActionsAsync(
            context.RobotId, context.TaskId, context.SubTaskId);

        return Ok(new ApiResponse<object>
        {
            Code = 200,
            Message = $"已取消{count}个网络动作",
            Data = new { CancelledCount = count }
        });
    }
}