176 lines
5.4 KiB
PHP
176 lines
5.4 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api\V1;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\Sgc\StoreInvoiceRequest;
|
|
use App\Http\Requests\Sgc\StorePaymentRequest;
|
|
use App\Services\Sgc\IntegrationService;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class SgcIntegrationController extends Controller
|
|
{
|
|
private IntegrationService $integrationService;
|
|
|
|
public function __construct(IntegrationService $integrationService)
|
|
{
|
|
$this->integrationService = $integrationService;
|
|
}
|
|
|
|
/**
|
|
* POST /api/v1/integration/sgc/invoices
|
|
* Recebe fatura do SGC
|
|
*/
|
|
public function storeInvoice(StoreInvoiceRequest $request): JsonResponse
|
|
{
|
|
$idempotencyKey = $request->header('X-Idempotency-Key');
|
|
|
|
if (!$idempotencyKey) {
|
|
return response()->json([
|
|
'status' => 'REJECTED',
|
|
'error_code' => 'MISSING_IDEMPOTENCY_KEY',
|
|
'message' => 'Header X-Idempotency-Key é obrigatório',
|
|
], 400);
|
|
}
|
|
|
|
// Verificar assinatura HMAC (em produção)
|
|
// $this->verificarAssinatura($request);
|
|
|
|
$resultado = $this->integrationService->receberFatura(
|
|
$request->validated(),
|
|
$idempotencyKey
|
|
);
|
|
|
|
$statusCode = match($resultado['status']) {
|
|
'ACCEPTED' => 201,
|
|
'DUPLICATE' => 409,
|
|
'REJECTED' => 400,
|
|
default => 500,
|
|
};
|
|
|
|
return response()->json($resultado, $statusCode);
|
|
}
|
|
|
|
/**
|
|
* POST /api/v1/integration/sgc/payments
|
|
* Recebe confirmação de pagamento do SGC
|
|
*/
|
|
public function storePayment(StorePaymentRequest $request): JsonResponse
|
|
{
|
|
$idempotencyKey = $request->header('X-Idempotency-Key');
|
|
|
|
if (!$idempotencyKey) {
|
|
return response()->json([
|
|
'status' => 'REJECTED',
|
|
'error_code' => 'MISSING_IDEMPOTENCY_KEY',
|
|
'message' => 'Header X-Idempotency-Key é obrigatório',
|
|
], 400);
|
|
}
|
|
|
|
$resultado = $this->integrationService->receberPagamento(
|
|
$request->validated(),
|
|
$idempotencyKey
|
|
);
|
|
|
|
$statusCode = match($resultado['status']) {
|
|
'ACCEPTED' => 201,
|
|
'DUPLICATE' => 409,
|
|
'REJECTED' => 400,
|
|
default => 500,
|
|
};
|
|
|
|
return response()->json($resultado, $statusCode);
|
|
}
|
|
|
|
/**
|
|
* GET /api/v1/integration/sgc/invoices/{sgfDocNumber}/status
|
|
* Consulta estado de uma fatura
|
|
*/
|
|
public function getInvoiceStatus(string $sgfDocNumber): JsonResponse
|
|
{
|
|
$fatura = \App\Models\Sgc\Fatura::where('sgf_doc_number', $sgfDocNumber)
|
|
->with(['ordemCompra', 'fornecedor'])
|
|
->first();
|
|
|
|
if (!$fatura) {
|
|
return response()->json([
|
|
'status' => 'NOT_FOUND',
|
|
'message' => 'Fatura não encontrada',
|
|
], 404);
|
|
}
|
|
|
|
// Construir lifecycle
|
|
$lifecycle = [
|
|
['event' => 'RECEBIDA', 'at' => $fatura->created_at],
|
|
];
|
|
|
|
if ($fatura->status_3_way_match !== 'Pendente') {
|
|
$lifecycle[] = [
|
|
'event' => '3WAY_MATCH',
|
|
'at' => $fatura->updated_at,
|
|
'result' => $fatura->status_3_way_match,
|
|
];
|
|
}
|
|
|
|
if ($fatura->status_pagamento === 'Pago') {
|
|
$lifecycle[] = [
|
|
'event' => 'PAGA',
|
|
'at' => $fatura->data_pagamento,
|
|
'reference' => $fatura->numero_comprovativo,
|
|
];
|
|
}
|
|
|
|
return response()->json([
|
|
'sgf_doc_number' => $fatura->sgf_doc_number,
|
|
'current_status' => $fatura->status_pagamento,
|
|
'lifecycle' => $lifecycle,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* GET /api/v1/integration/sgc/stats
|
|
* Estatísticas de integração
|
|
*/
|
|
public function getStats(): JsonResponse
|
|
{
|
|
$stats = [
|
|
'faturas' => [
|
|
'total' => \App\Models\Sgc\Fatura::count(),
|
|
'conformes' => \App\Models\Sgc\Fatura::conformes()->count(),
|
|
'com_excecao' => \App\Models\Sgc\Fatura::comExcecao()->count(),
|
|
'pagas' => \App\Models\Sgc\Fatura::pagas()->count(),
|
|
],
|
|
'ordens_compra' => [
|
|
'total' => \App\Models\Sgc\OrdemCompra::count(),
|
|
'cabimentadas' => \App\Models\Sgc\OrdemCompra::cabimentadas()->count(),
|
|
],
|
|
'integracao' => [
|
|
'aceites' => DB::table('sgc_integration_log')
|
|
->where('status', 'ACCEPTED')->count(),
|
|
'rejeitadas' => DB::table('sgc_integration_log')
|
|
->where('status', 'REJECTED')->count(),
|
|
'duplicadas' => DB::table('sgc_integration_log')
|
|
->where('status', 'DUPLICATE')->count(),
|
|
],
|
|
];
|
|
|
|
return response()->json($stats);
|
|
}
|
|
|
|
/**
|
|
* Verifica assinatura HMAC (em produção)
|
|
*/
|
|
private function verificarAssinatura(Request $request): bool
|
|
{
|
|
$signature = $request->header('X-SGC-Signature');
|
|
$secret = config('services.sgc.webhook_secret');
|
|
|
|
$payload = json_encode($request->all(), JSON_UNESCAPED_SLASHES);
|
|
$expectedSignature = hash_hmac('sha256', $payload, $secret);
|
|
|
|
return hash_equals($expectedSignature, $signature);
|
|
}
|
|
}
|