Search by

webrteu / netopia

webrteu

NETOPIA Payments API v2 driver for webrteu/payments (Laravel, Romania)

v1.0.0 2026-11-04 05:09 UTC

This package is auto-updated.

Last update: 2026-11-04 05:10:13 UTC


README

PHP Laravel Licență MIT Packagist

Integrare Laravel pentru NETOPIA Payments API v2 (JSON): plată pe pagina găzduită NETOPIA, IPN verificat prin JWT RS512, status și refund. Implementează Gateway + Refundable din webrteu/payments. Nu folosește fluxul vechi mobilPay cu certificate și nu colectează date de card (fără PCI DSS pe site).

Nu este un pachet oficial NETOPIA.

Cerințe

  • PHP ^8.2 cu ext-openssl, Laravel 12–13
  • cont NETOPIA Payments cu un punct de vânzare (POS) activ
  • webrteu/payments

Instalare

composer require webrteu/netopia
php artisan vendor:publish --tag=netopia-config
php artisan vendor:publish --tag=payments-migrations   # dacă nu ai rulat-o deja
php artisan migrate

Configurare

NETOPIA_SANDBOX=true
NETOPIA_API_KEY=            # panou NETOPIA → Profil → Securitate
NETOPIA_POS_SIGNATURE=      # Punct de vânzare → Setări tehnice (XXXX-XXXX-XXXX-XXXX-XXXX)
NETOPIA_PUBLIC_KEY=         # cheia publică NETOPIA: conținut PEM, PEM în base64 sau cale absolută spre fișier
NETOPIA_CURRENCY=RON
NETOPIA_LANGUAGE=ro
NETOPIA_TIMEOUT=20
NETOPIA_NOTIFY_URL=         # gol = https://site.ro/webhooks/payments/netopia

⚠️ Host-urile secure.sandbox.netopia-payments.com / secure.netopia-payments.com sunt cele din documentația publică. Confirmă-le în panou înainte de producție.

Utilizare

use WeBRTeu\Payments\Data\{CustomerData, PaymentRequestData};
use WeBRTeu\Payments\Facades\Payments;

$redirect = Payments::start('netopia', new PaymentRequestData(
    orderId: "{$order->id}-{$attempt}",   // NETOPIA respinge un orderID refolosit (cod 56)
    amount: 14170,
    description: "Comanda #{$order->id}",
    customer: new CustomerData($order->email, $order->first_name, $order->last_name, $order->phone),
    returnUrl: route('checkout.netopia.return', $order),
), payable: $order);

return $redirect->toResponse();

Alte metode: Payments::gateway('netopia')->status($ntpId) (POST /operation/status) și ->refund($ntpId, $bani) (⚠️ POST /operation/credit, calea se confirmă în spec-ul OpenAPI).

orderID-ul se trimite exact ca PaymentRequestData::$orderId (unic per încercare, conform webrteu/payments), ca IPN-ul să găsească rândul din payments fără traduceri.

Webhook (IPN)

  • URL-ul se trimite automat în fiecare plată (config.notifyUrl): https://site.ro/webhooks/payments/netopia
  • verificare: Verification-token = JWT RS512, semnat cu cheia NETOPIA; iss = "NETOPIA Payments", aud conține POS-ul, sub = base64(sha512(corp brut)), plus exp/iat
  • răspuns: {"errorType":0,"errorCode":null,"errorMessage":""} la acceptare, HTTP 400 cu errorType: 1 la semnătură invalidă (⚠️ semantica exactă errorType se confirmă în docs)
use WeBRTeu\Payments\Events\PaymentStatusChanged;

Event::listen(function (PaymentStatusChanged $event) {
    if ($event->payment->gateway === 'netopia' && $event->to->isSuccessful()) {
        $event->payment->payable?->markAsPaid();
    }
});

Statusuri

Cod PaymentStatus
1, 2, 6, 7, 14, 15, 18 Pending
3, 5 Paid (⚠️ dacă 3 = autorizat și 5 = capturat, 3 devine Authorized)
4, 17 Cancelled
8, 10 Refunded
11, 12, 13, 23 Failed
altele Unknown + log netopia.unknown_status

Comenzi Artisan

payments:reconcile (din core) folosește status() pentru plățile rămase Pending.

Ce nu face pachetul

  • nu colectează date de card (fără instrument în cerere)
  • nu implementează fluxul vechi mobilPay (certificate .cer/.key)
  • nu face retry pe pornirea plății

Testare

composer test
NETOPIA_SANDBOX_API_KEY=... NETOPIA_SANDBOX_POS_SIGNATURE=... vendor/bin/pest --group=sandbox

Testele generează o pereche RSA și semnează JWT-uri ca NETOPIA. Fixture-urile sunt după docs. De înlocuit cu răspunsuri reale.

Changelog

Vezi CHANGELOG.md.

Autor

WeBRTeu

Licență

MIT. Vezi LICENSE.md.