HOME


Mini Shell 1.0
DIR: /home/cardxfeb/public_html/app/Http/Controllers/Webhooks/
Upload File :
Current File : //home/cardxfeb/public_html/app/Http/Controllers/Webhooks/MultibancoPagamentoController.php
<?php

namespace App\Http\Controllers\Webhooks;

use App\Http\Controllers\Controller;
use App\Models\Vcard;
use App\Models\MultibancoReference;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

/**
 * IfthenPay Multibanco controller for Portugal payments.
 *
 * Flow:
 * 1. POST /pagamento/multibanco/{vcard}  generate reference, store in DB, show to user
 * 2. POST /webhooks/portugal               IfthenPay notifies payment confirmed
 *
 * IfthenPay API docs: https://ifthenpay.com/docs/
 */
class MultibancoPagamentoController extends Controller
{
    private string $entityKey;
    private string $subEntityKey;
    private string $antiPhishing;

    public function __construct()
    {
        $this->entityKey    = config('services.ifthen.entity_key', '');
        $this->subEntityKey = config('services.ifthen.sub_entity_key', '');
        $this->antiPhishing = config('services.ifthen.anti_phishing', '');
    }

    /**
     * Generate a Multibanco reference for a VCard payment
     * POST /pagamento/multibanco/{vcard}
     */
    public function generate(Request $request, Vcard $vcard): JsonResponse
    {
        if ($vcard->user_id !== auth()->id()) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        $region   = config('app.region', 'PT');
        $amount   = $region === 'PT' ? 7.00 : 40.00; // Setup 5 + 1 month 2
        $orderId  = 'vcard_' . $vcard->id . '_' . time();

        // Check if already has pending reference
        $existing = MultibancoReference::where('vcard_id', $vcard->id)
            ->where('status', 'pending')
            ->first();

        if ($existing) {
            return response()->json([
                'status'    => 'existing',
                'entity'    => $existing->entity,
                'reference' => $existing->reference,
                'amount'    => $existing->amount,
                'expires_at'=> $existing->expires_at,
            ]);
        }

        // Generate reference via IfthenPay API
        try {
            $response = Http::post('https://ifthenpay.com/api/multibanco/reference/init', [
                'mbKey'     => $this->entityKey,
                'orderId'   => $orderId,
                'amount'    => number_format($amount, 2, '.', ''),
                'expiryDays'=> 3,
            ]);

            if (!$response->ok()) {
                Log::error('[Multibanco] IfthenPay API error: ' . $response->status());
                return response()->json(['error' => 'Gateway error'], 502);
            }

            $data = $response->json();

            // Store reference in database
            $ref = MultibancoReference::create([
                'vcard_id'   => $vcard->id,
                'order_id'   => $orderId,
                'entity'     => $data['Entity'] ?? '11249',
                'reference'  => $data['Reference'] ?? '',
                'amount'     => $amount,
                'status'     => 'pending',
                'expires_at' => now()->addDays(3),
            ]);

            Log::info("[Multibanco] Reference generated: {$ref->entity}/{$ref->reference} for vcard#{$vcard->id}");

            return response()->json([
                'status'    => 'created',
                'entity'    => $ref->entity,
                'reference' => $ref->reference,
                'amount'    => $ref->amount,
                'expires_at'=> $ref->expires_at->format('d/m/Y'),
                'message'   => 'Utilize o ATM ou homebanking para efectuar o pagamento',
            ]);

        } catch (\Exception $e) {
            Log::error('[Multibanco] Exception: ' . $e->getMessage());
            return response()->json(['error' => 'Internal error'], 500);
        }
    }

    /**
     * IfthenPay Webhook  payment confirmed
     * POST /webhooks/portugal
     */
    public function webhook(Request $request): JsonResponse
    {
        // Anti-phishing key validation
        $receivedKey = $request->input('chave')
                    ?? $request->input('anti_phishing_key')
                    ?? $request->header('x-ifthen-key');

        if ($this->antiPhishing && $receivedKey !== $this->antiPhishing) {
            Log::warning('[PortugalWebhook] Invalid anti-phishing key');
            return response()->json(['error' => 'Unauthorized'], 401);
        }

        $entity    = $request->input('entidade') ?? $request->input('entity');
        $reference = $request->input('referencia') ?? $request->input('reference');
        $amount    = (float)($request->input('valor') ?? $request->input('amount') ?? 0);

        Log::info("[PortugalWebhook] Payment received: {$entity}/{$reference} amount={$amount}");

        $ref = MultibancoReference::where('reference', $reference)
            ->where('entity', $entity)
            ->where('status', 'pending')
            ->first();

        if (!$ref) {
            Log::warning("[PortugalWebhook] Reference not found: {$entity}/{$reference}");
            return response()->json(['status' => 'reference_not_found']);
        }

        // Validate amount (tolerance 1 cent)
        if (abs($amount - $ref->amount) > 0.01) {
            Log::warning("[PortugalWebhook] Amount mismatch: expected {$ref->amount}, got {$amount}");
        }

        // Mark reference as paid
        $ref->update(['status' => 'paid', 'paid_at' => now()]);

        // Activate VCard
        $vcard = Vcard::withTrashed()->find($ref->vcard_id);
        if ($vcard) {
            $vcard->update([
                'status'           => 'active',
                'payment_deadline' => null,
                'nfc_status'       => 'pending',
                'nfc_requested_at' => now(),
            ]);

            if ($vcard->trashed()) {
                $vcard->restore();
            }

            Log::info("[PortugalWebhook] VCard#{$vcard->id} ACTIVATED via Multibanco");
        }

        return response()->json(['status' => 'ok', 'vcard_id' => $ref->vcard_id]);
    }
}