A PHP component/library.

v0.0.3 2023-12-06 16:04 UTC

This package is auto-updated.

Last update: 2024-05-06 17:13:23 UTC


README

An XPay (Nexi) implementation.

Usage

Currently implemented functionality: Pagamento semplice

1) Extend class AbstractPaymentService

  • implement createCancelUrl, createNotificationUrl, createReturnUrl;
final class PaymentService extends AbstractPaymentService implements PaymentServiceInterface
{
    protected function createCancelUrl(string $orderId): string
    {
        ...
    }

    protected function createNotificationUrl(string $orderId): string
    {
        ...
    }

    protected function createReturnUrl(string $orderId): string
    {
        ...
    }
}

2) Extend class AbstractRequestInputService

  • optionally implement your own validation rules;
final class RequestInputService extends AbstractRequestInputService implements RequestInputServiceInterface
{
    public const KEY_LANGUAGE = 'lang';
    
    public const KEY_ORDER_ID = 'orderId';
    
    protected function getValidationRule(string $key): string
    {
        return match ($key) {
            self::KEY_ORDER_ID => '/^[a-f0-9]{42}$/',
            default => parent::getValidationRule($key),
        };
    }
    
    protected function validateInput(string $key, string $value): bool
    {
        if ($key === self::KEY_LANGUAGE) {
            return $this->validateLanguageCode($value);
        }

        return parent::validateInput($key, $value);
    }
}

4) Payment request

<!doctype html>
<html>
    <head>
        ...
    </head>
    <body>
        <form id="payment_form" method="POST" action="<?=$paymentService->getApiUrl()?>">
            <?php
            foreach (
                $paymentService->createPaymentRequestParameters(
                    $languageCode,
                    $orderId,
                    $orderInformation->total,
                ) as $key => $value
            ) { ?>
                <input type="hidden" name="<?=$key?>" value="<?=$value?>" />
            <?php } ?>
            <button type="submit" class="btn btn-primary">
                <?=$languageCode === 'it' ? 'Acquista ora' : 'Buy now'?>
            </button>
        </form>
        <script>
            document.getElementById('payment_form').submit();
        </script>
    </body>
</html>

5) Return page

// Validate order (get info from storage)
...

/**
 * Special situation: "mac" can be missing from the request.
 * Eg. try to pay already paid transaction.
 * In that situation we don't want to have a transaction error, however we also can not trust the request.
 * Simply do not process transaction.
 */
$processTransaction = true;
try {
    // Try to get mac
    $requestInputService->getValidatedString(RequestInput::MAC);
} catch (OutOfBoundsException) {
    $processTransaction = false;
}

if ($processTransaction) {
    // Validate transaction. Uses input data (_GET or _POST).
    $paymentService->validateTransaction();

    // Store transaction result.
    ...
}

// Redirect back to website.
...

Development

# Lint
composer check:lint && \
# Code style
composer check:phpcs && \
# PHPStan
composer check:phpstan && \
# Phan
composer check:phan && \
# PHPMD
composer check:phpmd && \
# Psalm
composer check:psalm