Download the PHP package birkof/netopia-mobilpay-bundle without Composer
On this page you can find all versions of the php package birkof/netopia-mobilpay-bundle. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download birkof/netopia-mobilpay-bundle
More information about birkof/netopia-mobilpay-bundle
Files in birkof/netopia-mobilpay-bundle
Package netopia-mobilpay-bundle
Short Description Seamless integration of Netopia MobilPay Payment Gateway into your Symfony application
License MIT
Informations about the package netopia-mobilpay-bundle
Netopia MobilPay Bundle — Architecture Overview
A thin, typed Symfony integration layer over the birkof/netopia-mobilpay low-level SDK. It wires the SDK into the Symfony service container and exposes two responsibilities of the Netopia (MobilPay) card-payment protocol:
- Outbound — build an RSA‑encrypted payment request to redirect a customer to the gateway.
- Inbound — decrypt and authenticate the gateway's IPN (Instant Payment Notification) callback and produce the
<crc>acknowledgement it expects.
The bundle holds no state, no persistence, and no HTTP controllers. It builds request objects and parses notifications; the consuming application owns routing, fulfilment, and storage.
Source of truth for this document: the files under
src/(14 PHP files, ~1090 LOC),composer.json,phpunit.xml.dist, and.github/workflows/ci.yml. Usage examples live insrc/Resources/doc/index.md.
Requirements
From composer.json:
| Dependency | Constraint | Role |
|---|---|---|
php |
^8.3 |
runtime |
birkof/netopia-mobilpay |
^4.0 |
low-level Netopia SDK (Mobilpay\…): crypto + XML protocol |
symfony/routing |
^4.4 \|\| ^5.0 \|\| ^6.0 |
generates the absolute confirm/return URLs |
symfony/yaml |
^4.4 \|\| ^5.0 \|\| ^6.0 |
loads Resources/config/services.yaml |
symfony/monolog-bundle |
^3.7 |
provides the logger service injected into both services |
phpunit/phpunit (dev) |
^11.5 |
test suite |
Autoload (PSR‑4): birkof\NetopiaMobilPay\ → src/.
Installation
1. Require the package
2. Register the bundle
With Symfony Flex this is automatic. Otherwise add it to config/bundles.php:
3. Configure the gateway
signature is required — the bundle fails to boot without it. payment_url,
public_cert and private_key are optional (defaults: sandbox URL, null, null).
Both public_cert and private_key accept either a file path (resolved relative to
%kernel.project_dir%) or the inline PEM content.
4. Define the confirm and return routes
The bundle generates absolute URLs from two route names it expects you to define
(NetopiaMobilPayConfiguration::CONFIRM_URL / ::RETURN_URL). These names are mandatory —
missing them breaks URL generation at container build time:
Usage
Both entry points are autowired by their interface:
Start a payment (outbound)
createCreditCardPaymentObject() validates the input, builds and RSA‑seals the request,
and returns the SDK request object exposing the sealed env_key / data (and cipher / iv
for block ciphers). Render an auto‑submitting form that POSTs them to the gateway URL.
PCI note: leave the
creditCardargument empty and let the gateway's hosted page collect the card details. Passing a raw PAN/CVV through your server places the whole application in PCI‑DSS SAQ‑D scope.
Handle the confirmation (inbound IPN)
Netopia POSTs the encrypted notification to your netopia_mobilpay_confirm_url route.
Decrypt it, verify the amount/order yourself, then acknowledge with <crc>:
IpnResult predicates: isConfirmed(), isPaid(), isPending(), isCanceled(), isError().
See src/Resources/doc/index.md for the full integration guide.
Architecture at a glance
The SDK does the cryptography and XML; this bundle adapts it to Symfony DI and gives the inbound side a typed, vendor‑agnostic result.
Components
Grouped by directory under src/:
Bundle + DI
| File | Responsibility |
|---|---|
NetopiaMobilPayBundle.php |
The bundle. const ALIAS = 'netopia_mobilpay', const VERSION = '1.4.0'; returns NetopiaMobilPayExtension from getContainerExtension(). |
DependencyInjection/Configuration.php |
Config tree (getConfigTreeBuilder): nodes payment_url, public_cert, private_key, signature. signature is isRequired()->cannotBeEmpty() — a missing signature fails config processing rather than booting with a placeholder. |
DependencyInjection/NetopiaMobilPayExtension.php |
Loads services.yaml, processes config, and registers the service graph (below). inflateServicesInConfig() turns any @service‑prefixed config string into a Reference. Secrets are passed to the configuration object only via method calls — they are never written to container parameters (which Symfony would dump to the compiled‑container cache in cleartext). |
Service graph built by the extension:
Resources/config/services.yaml aliases each interface to its service for autowiring:
NetopiaMobilPayServiceInterface → netopia_mobilpay.payment,
NetopiaMobilPayIpnHandlerInterface → netopia_mobilpay.ipn_handler.
Configuration value object
Configuration/NetopiaMobilPayConfiguration.php — runtime holder for the gateway settings, built once and shared by both services.
- Reads
public_cert/private_keyas either a file path (resolved under%kernel.project_dir%) or the literal PEM content (setPublicCert/setPrivateKeyfall back to the raw value when it is not a readable file). - In its constructor it generates the absolute confirm and return URLs via the router from two route names it expects the application to define:
netopia_mobilpay_confirm_url(const CONFIRM_URL)netopia_mobilpay_return_url(const RETURN_URL)
resolvePaymentUrl(bool $useTokenEndpoint)derives the per‑request endpoint from an immutable base URL: the base for a normal payment,base + '/card4'for a token payment. The base is never mutated, so repeated/token calls cannot accumulate/card4or leak across requests on long‑running workers.- Currency constants:
CURRENCY_RON,CURRENCY_EUR,CURRENCY_USD.
Outbound — payment request building
Service/NetopiaMobilPayServiceInterface.php + NetopiaMobilPayService.php.
createCreditCardPaymentObject($orderId, $amount, $currency, $details, $billingAddress, $shippingAddress, $creditCard, $extraParameters):- validates
orderId(non‑empty),amount(positive numeric) andcurrency(one of theCURRENCY_*constants) before the try/catch, so a specific input error is not masked; - builds a
Mobilpay\Payment\Request\Card—signature,confirmUrl,returnUrl, aMobilpay\Payment\Invoice(currency/amount/details), optional billing/shippingMobilpay\Payment\Address, optionalMobilpay\Payment\Instrument\Card, and tokenextraParameters; - resolves the payment URL for the request;
- calls
->encrypt($publicCert)(RSA envelope) and returns the request object.
- validates
createSmsPaymentObject($orderId, $serviceId)— the SMS‑payment equivalent.composeAddressObject()sets only the fields the SDK'sAddressactually serializes (type,firstName,lastName,address,email,mobilePhone).composeCreditCardObject()builds a raw‑PANCardInstrument. Its docblock warns that this server‑side card path places the application in PCI‑DSS SAQ‑D scope; the hosted payment page (leave$creditCardempty) is the recommended flow.
The returned request object exposes the sealed env_key / data; the application renders an auto‑submitting HTML form POSTing them to getPaymentUrl().
Inbound — IPN handling (src/Notification/)
| File | Responsibility |
|---|---|
IpnAction.php |
Backed enum IpnAction: string of gateway actions (confirmed, confirmed_pending, paid_pending, paid, canceled, credit) plus an Unknown fallback. fromValue(?string) maps unrecognized/null to Unknown (forward‑compatible — never throws on a new action). |
IpnResult.php |
final readonly DTO — an immutable, vendor‑agnostic view of a decrypted notification. fromNotify(Notify) maps the SDK object (money kept as string, errorCode cast to int). Predicates: isError(), isConfirmed(), isPaid(), isPending(), isCanceled(). |
NetopiaMobilPayIpnHandlerInterface.php / NetopiaMobilPayIpnHandler.php |
decrypt(string $envKey, string $encData, ?string $cipher = null, ?string $iv = null): IpnResult opens the envelope via RequestAbstract::factoryFromEncrypted() using the configured private key, then returns IpnResult::fromNotify(). confirmResponse() / errorResponse($message, $errorType, $errorCode) build the <crc> reply with DOMDocument (values XML‑escaped). Constants ERROR_TYPE_TEMPORARY = 1 (gateway retries) and ERROR_TYPE_PERMANENT = 2. Decrypt failures log only the error code (never the vendor message, key material, or ciphertext) and surface a generic NetopiaMobilPayException. |
Errors
Exception/NetopiaMobilPayException.php — the single extends \Exception type thrown by the bundle (invalid input, failed encryption, failed/empty/garbage IPN payload).
All src/ classes declare declare(strict_types=1).
Request / response flows
Outbound (start a payment):
Inbound (gateway confirmation / IPN):
Security model
- Authenticity is the RSA envelope. Netopia seals the IPN against your public certificate; only the holder of the matching private key can
openssl_openit. A successfuldecrypt()therefore authenticates the sender — there is no separate signature on the callback. - The bundle cannot verify the amount/order. It proves the message came from Netopia; it does not know what you expected. The consumer must cross‑check
IpnResult::$purchaseIdagainst a real, unfulfilled order and confirmIpnResult::$processedAmountbefore fulfilling. This boundary is documented insrc/Resources/doc/index.md. - Secrets stay out of the compiled container. The extension passes
private_key/signatureto the configuration object via method calls, not container parameters. - No card data by default. The hosted‑page flow keeps PAN/CVV off your server; the raw‑card path is documented as PCI SAQ‑D scope.
Project layout
Configuration reference
Defined in config/packages/netopia_mobilpay.yaml (see src/Resources/doc/index.md for full examples):
| Key | Required | Default | Notes |
|---|---|---|---|
signature |
yes | — | merchant signature; processing fails if absent |
payment_url |
no | http://sandboxsecure.mobilpay.ro |
gateway base URL (set the production URL in prod) |
public_cert |
no | null |
file path or inline PEM; used to seal outbound requests |
private_key |
no | null |
file path or inline PEM; used to open inbound IPNs |
The application must also define two routes the configuration generates URLs for: netopia_mobilpay_confirm_url (server‑to‑server IPN) and netopia_mobilpay_return_url (browser return).
Inject by interface:
Testing & CI
- PHPUnit 11 (
phpunit.xml.dist): bootstrapsvendor/autoload.php, runs thetests/suite, declaressrc/as the coverage source, and is strict —failOnWarning="true",failOnRisky="true". Run withvendor/bin/phpunit(orcomposer test). - Current suite: 33 tests / 134 assertions, mirroring
src/(config tree, DI wiring, value object, outbound service, IPN enum/DTO/handler). The IPN handler test performs a realopenssl_seal→decryptround‑trip with a generated key pair. - CI (
.github/workflows/ci.yml): on push tomainand on pull requests; matrix PHP 8.3 and 8.4 (extensionsopenssl, mbstring, dom); steps:composer validate --strict, install,vendor/bin/phpunit, and a non‑blockingcomposer audit.
License
MIT — see LICENSE.md.
All versions of netopia-mobilpay-bundle with dependencies
birkof/netopia-mobilpay Version ^4.0
symfony/monolog-bundle Version ^3.7
symfony/routing Version ^4.4 || ^5.0 || ^6.0
symfony/yaml Version ^4.4 || ^5.0 || ^6.0