PATH:
home
/
cardxfeb
/
public_html
/
app
/
Http
/
Controllers
/
Webhooks
/
Editing: 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]); } }
SAVE
CANCEL