PHPackages                             djweb/payments - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Payment Processing](/categories/payments)
4. /
5. djweb/payments

ActiveLibrary[Payment Processing](/categories/payments)

djweb/payments
==============

Payment and invoice integration package for Stripe and iFirma

1.0.0(8mo ago)00MITPHPPHP ^8.4

Since Sep 19Pushed 6mo agoCompare

[ Source](https://github.com/DJWeb-Damian-Jozwiak/PaymentGateway)[ Packagist](https://packagist.org/packages/djweb/payments)[ RSS](/packages/djweb-payments/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (12)Versions (2)Used By (0)

DjWeb Payments 💳
================

[](#djweb-payments-)

[![PHP Version](https://camo.githubusercontent.com/9a8e6e769aa0c5ab5134f912a6a5060ad12f805ba61f54084fd1daffddc262be/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e342b2d3738374342352e737667)](https://php.net)[![Tests](https://camo.githubusercontent.com/584522dd24b2bb5d92b04ae9398bf619864731660d8e01f6f6051104868d07b1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74657374732d3237362532307061737365642d627269676874677265656e2e737667)](./tests)[![Coverage](https://camo.githubusercontent.com/0ce7842672fb7fb8a1160d1eef337b4a2b756a1db8e43384e5a795a0596de0b1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f7665726167652d3932253235253230636c61737365732d627269676874677265656e2e737667)](./tests)[![PHPStan](https://camo.githubusercontent.com/1bc07920f0d36e55c17e1d38b1caa132cc605f51a82b388c962870b9a747b898/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c253230392d627269676874677265656e2e737667)](https://phpstan.org)[![PHPInsights](https://camo.githubusercontent.com/f1a75929caa90a91ca6e71cca19e202675dec77748fc25ba1f59e0dbefe9dafc/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f504850496e736967687473436f64652d39372532352d627269676874677265656e2e737667)](https://phpinsights.com)[![PHPInsights](https://camo.githubusercontent.com/fa0ed7f5bc1db8bf195c05bc2554c693a8815e9dcb6360fcb1094aafbe165e01/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f504850496e736967687473436f6d706c65786974792d3130302532352d627269676874677265656e2e737667)](https://phpinsights.com)[![PHPInsights](https://camo.githubusercontent.com/59ca58d263482508e16986a947397c99a7439e3528b3f241c5be86f9bdf45c4f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f504850496e7369676874734172636869746563747572652d3130302532352d627269676874677265656e2e737667)](https://phpinsights.com)[![License](https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667)](LICENSE)

Modern, secure and flexible payment system for PHP applications. Supports Stripe, invoice generation via IFirma and EU VAT data validation.

✨ Features
----------

[](#-features)

- 🔒 **Security** - VAT validation, type checking, sensitive data protection
- 💰 **Stripe Payments** - Full Stripe PaymentIntents support with webhooks
- 📄 **IFirma Invoices** - Automatic invoice generation with various VAT strategies
- 🌍 **EU Support** - VAT number validation, tax rates, regional requirements
- 🧪 **High Quality** - 92% test coverage, PHPStan level 8, PHPInsights A+
- 🚀 **Modern PHP** - Uses latest PHP 8.4 features (property hooks, readonly classes)

📦 Installation
--------------

[](#-installation)

```
composer require djweb/payments
```

🚀 Quick Start
-------------

[](#-quick-start)

### Stripe Payments

[](#stripe-payments)

```
use DjWeb\Payments\Services\Payment\Stripe\StripePaymentGateway;
use DjWeb\Payments\DTOs\PaymentRequest;
use DjWeb\Payments\DTOs\CustomerData;
use DjWeb\Payments\DTOs\AddressData;
use DjWeb\Payments\ValueObjects\Money;
use DjWeb\Payments\ValueObjects\VatNumber;

// Gateway configuration
$stripe = new StripePaymentGateway(
    secretKey: 'sk_test_...',
    webhookSecret: 'whsec_...'
);

// Customer data
$customer = new CustomerData(
    email: 'customer@example.com',
    firstName: 'John',
    lastName: 'Doe',
    address: new AddressData(
        street: '123 Example Street',
        city: 'Warsaw',
        postalCode: '00-001',
        country: 'PL'
    ),
    companyName: 'Example Company Ltd.',
    vatNumber: new VatNumber('PL', '5260001246')
);

// Payment request
$request = new PaymentRequest(
    amount: new Money(299.99, 'PLN'),
    customer: $customer,
    description: 'Premium Product Purchase'
);

// Create PaymentIntent
$intent = $stripe->createPaymentIntent($request);

// Process payment
$result = $stripe->processPayment($intent);

if ($result->success) {
    echo "Payment successful: {$result->transactionId}";
}
```

### IFirma Invoice Generation

[](#ifirma-invoice-generation)

```
use DjWeb\Payments\Services\Invoice\IFirma\IFirmaInvoiceService;
use DjWeb\Payments\DTOs\InvoiceData;

$invoiceService = new IFirmaInvoiceService(
    username: 'your_username',
    invoiceKey: 'your_invoice_key',
    apiUrl: 'https://www.ifirma.pl/iapi'
);

$invoiceData = new InvoiceData(
    customer: $customer,
    amount: new Money(299.99, 'PLN'),
    originalAmount: new Money(299.99, 'PLN'),
    productName: 'Premium Product'
);

$invoiceResult = $invoiceService->createInvoice($invoiceData);

if ($invoiceResult->success) {
    echo "Invoice created: {$invoiceResult->invoiceNumber}";
    echo "PDF: {$invoiceResult->pdfUrl}";
}
```

### Working with Discounts

[](#working-with-discounts)

```
use DjWeb\Payments\DTOs\DiscountData;

$discount = new DiscountData(
    code: 'SAVE20',
    percentage: 20.0,
    maxUsages: 100,
    currentUsages: 15,
    validUntil: new DateTimeImmutable('2024-12-31')
);

if ($discount->isValid) {
    $originalAmount = 299.99;
    $discountAmount = $discount->calculateDiscountAmount($originalAmount);
    $finalAmount = $discount->calculateFinalAmount($originalAmount);

    echo "Discount: {$discountAmount} PLN";
    echo "Total: {$finalAmount} PLN";
}
```

### VAT and Country Validation

[](#vat-and-country-validation)

```
use DjWeb\Payments\ValueObjects\VatNumber;
use DjWeb\Payments\ValueObjects\Country;

// Create and validate VAT number
$vatNumber = new VatNumber('PL', '526-000-12-46');
echo $vatNumber; // PL5260001246

// Check EU country
$country = new Country('PL');
echo $country->name; // Poland
echo $country->getVatRate(); // 0.23 (23%)
echo $country->isEu ? 'EU' : 'Non-EU'; // EU

// Check state/province requirements
if ($country->requiresStateProvince()) {
    // Required for US, CA, AU, BR, MX, IN, MY, AR
}
```

### Stripe Webhook Handling

[](#stripe-webhook-handling)

```
use DjWeb\Payments\DTOs\WebhookEvent;

// Webhook signature verification
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_STRIPE_SIGNATURE'];

try {
    $isValid = $stripe->verifyWebhookSignature($payload, $signature);

    if ($isValid) {
        $eventData = json_decode($payload, true);

        $event = new WebhookEvent(
            id: $eventData['id'],
            type: $eventData['type'],
            data: $eventData['data'],
            source: 'stripe',
            createdAt: new DateTimeImmutable()
        );

        // Handle different event types
        if ($event->isPaymentEvent) {
            // payment_intent.succeeded, payment_intent.payment_failed, etc.
            handlePaymentEvent($event);
        } elseif ($event->isInvoiceEvent) {
            // invoice.payment_succeeded, invoice.payment_failed, etc.
            handleInvoiceEvent($event);
        }
    }
} catch (Exception $e) {
    http_response_code(400);
    exit('Webhook error: ' . $e->getMessage());
}
```

🏗️ Architecture
---------------

[](#️-architecture)

### Design Patterns

[](#design-patterns)

- **Strategy Pattern** - Different invoicing strategies (domestic, EU B2B, export, OSS)
- **Factory Pattern** - Automatic strategy selection based on customer data
- **Value Objects** - Safe representations of money, countries, VAT numbers
- **DTOs** - Data transfer with validation and transformation

### Project Structure

[](#project-structure)

```
src/
├── Contracts/          # Interfaces
│   ├── Arrayable.php
│   ├── InvoiceServiceContract.php
│   ├── PaymentGatewayContract.php
│   └── WebhookHandlerContract.php
├── DTOs/              # Data Transfer Objects
│   ├── AddressData.php
│   ├── CustomerData.php
│   ├── DiscountData.php
│   ├── InvoiceData.php
│   ├── PaymentIntent.php
│   ├── PaymentRequest.php
│   ├── PaymentResult.php
│   └── WebhookEvent.php
├── Exceptions/        # Business Exceptions
│   ├── InvoiceError.php
│   └── PaymentError.php
├── Services/
│   ├── Invoice/       # Invoice Services
│   │   └── IFirma/   # IFirma Implementation
│   ├── Payment/       # Payment Gateways
│   │   └── Stripe/   # Stripe Implementation
│   └── Validators/    # VAT Validators
└── ValueObjects/      # Value Objects
    ├── Country.php
    ├── Money.php
    └── VatNumber.php

```

🧪 Code Quality
--------------

[](#-code-quality)

The project maintains the highest code quality through:

### Test Coverage

[](#test-coverage)

- **92% class coverage** (23/25)
- **91% method coverage** (74/81)
- **89% line coverage** (389/438)
- **276 tests**, **1007 assertions**

### Quality Control Tools

[](#quality-control-tools)

```
# All tests
vendor/bin/phpunit

# With code coverage
XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html coverage

# Static analysis PHPStan (level 9)
vendor/bin/phpstan analyse

# Quality analysis PHPInsights
vendor/bin/phpinsights analyse

# Code standards check
vendor/bin/phpcs
```

📝 Invoice Strategies
--------------------

[](#-invoice-strategies)

The system automatically selects the appropriate strategy based on customer data:

StrategyConditionsVATIFirma Endpoint**Domestic**Polish customer, PLN23%`/fakturakraj.json`**Currency**Polish customer, EUR/USD23%`/fakturawaluta.json`**EU B2B**EU customer with valid VAT0% (reverse charge)`/fakturaeksportuslugue.json`**OSS**EU consumerCustomer's country VAT`/fakturaoss.json`**Export**Non-EU customer0%`/fakturaeksportuslug.json`### Custom Strategy Example

[](#custom-strategy-example)

```
use DjWeb\Payments\Services\Invoice\IFirma\Strategies\InvoiceStrategyContract;

class CustomInvoiceStrategy implements InvoiceStrategyContract
{
    public function shouldApply(CustomerData $customer): bool
    {
        return $customer->address->country->code === 'US'
            && $customer->companyName !== null;
    }

    public function getEndpoint(): string
    {
        return '/custom-us-b2b.json';
    }

    public function prepareInvoiceData(InvoiceData $data): array
    {
        return [
            'NabywcaNazwa' => $data->customer->companyName,
            'NabywcaAdres' => $data->customer->address->street,
            'StawkaVat' => 0, // No VAT for export
            // ... more fields
        ];
    }
}
```

🌍 Supported Countries and Currencies
------------------------------------

[](#-supported-countries-and-currencies)

### EU Countries with Automatic VAT Rates

[](#eu-countries-with-automatic-vat-rates)

All 27 EU countries with automatic VAT rates:

CountryCodeVAT RateRequires State/Province🇵🇱 PolandPL23%❌🇩🇪 GermanyDE19%❌🇫🇷 FranceFR20%❌🇺🇸 USAUS0%✅🇨🇦 CanadaCA0%✅### Currencies

[](#currencies)

- **EUR**, **USD**, **PLN**, **GBP** - full support
- **JPY**, **KRW** - no decimal places
- Support for 100+ currencies via Stripe

```
// Automatic conversion to Stripe units
$money = new Money(99.99, 'PLN');
echo $money->toSmallestUnit(); // 9999 (grosze)

$yen = new Money(1000, 'JPY');
echo $yen->toSmallestUnit(); // 1000 (no conversion)
```

🔒 Security
----------

[](#-security)

### Built-in Protections

[](#built-in-protections)

- **Input validation** - All DTOs validate data at construction
- **Sensitive data protection** - `#[SensitiveParameter]` attribute for API keys
- **Safe Value Objects** - Immutable objects with validation
- **VAT validation** - Automatic checksum validation for Polish NIPs
- **Webhook verification** - Stripe signature checking

### Error Handling Example

[](#error-handling-example)

```
use DjWeb\Payments\Exceptions\PaymentError;
use DjWeb\Payments\Exceptions\InvoiceError;

try {
    $intent = $stripe->createPaymentIntent($request);
} catch (PaymentError $e) {
    // Safe logging with context
    logger()->error('Payment failed', [
        'message' => $e->getMessage(),
        'context' => $e->context, // Additional context data
        'customer_id' => $request->customer->email
    ]);
}

// Error factories for different scenarios
throw PaymentError::invalidAmount(-100);
throw PaymentError::unsupportedCurrency('XYZ');
throw PaymentError::gatewayError('Stripe', 'Card declined');

throw InvoiceError::invalidCustomerData('vatNumber');
throw InvoiceError::unsupportedCountry('XX');
throw InvoiceError::apiError('IFirma', 'Connection timeout');
```

🔧 Configuration
---------------

[](#-configuration)

### Environment Variables

[](#environment-variables)

```
# Stripe
STRIPE_SECRET_KEY=sk_test_51234567890...
STRIPE_WEBHOOK_SECRET=whsec_1234567890...

# IFirma
IFIRMA_USERNAME=your_username
IFIRMA_INVOICE_KEY=123456789abcdef
IFIRMA_API_URL=https://www.ifirma.pl/iapi

# Optional
APP_ENV=production
LOG_LEVEL=info
```

### Dependency Injection (Laravel/Symfony)

[](#dependency-injection-laravelsymfony)

```
// Laravel Service Provider
use DjWeb\Payments\Contracts\PaymentGatewayContract;
use DjWeb\Payments\Contracts\InvoiceServiceContract;

$this->app->bind(PaymentGatewayContract::class, function () {
    return new StripePaymentGateway(
        secretKey: config('services.stripe.secret'),
        webhookSecret: config('services.stripe.webhook_secret')
    );
});

$this->app->bind(InvoiceServiceContract::class, function () {
    return new IFirmaInvoiceService(
        username: config('services.ifirma.username'),
        invoiceKey: config('services.ifirma.invoice_key'),
        apiUrl: config('services.ifirma.api_url', 'https://www.ifirma.pl/iapi')
    );
});
```

📊 Quality Metrics
-----------------

[](#-quality-metrics)

MetricValueStatus**Class Coverage**92% (23/25)✅ Excellent**Method Coverage**91% (74/81)✅ Excellent**Line Coverage**89% (389/438)✅ Very Good**PHPStan**Level 8/9✅ Perfect**PHPInsights Code**97%✅ Excellent**PHPInsights Complexity**100%✅ Excellent**PHPInsights Architecture**100%✅ Excellent**PHPInsights Style**98%✅ Excellent**Tests**276 passed✅ All Green📄 License
---------

[](#-license)

MIT License. See [LICENSE](LICENSE) for details.

🆘 Support
---------

[](#-support)

- 📧 **Email**:
- 🐛 **Issues**: [GitHub Issues](https://github.com/djweb/payments/issues)
- 📖 **Documentation**: [GitHub Wiki](https://github.com/djweb/payments/wiki)
- 💬 **Discussions**: [GitHub Discussions](https://github.com/djweb/payments/discussions)

---

\*\*Created with ❤️ by [DjWeb](https://djweb.pl) \*\*

*Modern PHP solutions for future businesses*

###  Health Score

33

—

LowBetter than 75% of packages

Maintenance65

Regular maintenance activity

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

242d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/41979fa3adf74e308157185e30a99c93795d8bb8c33f35dbcef030cb3c9865c2?d=identicon)[damek24](/maintainers/damek24)

---

Top Contributors

[![damek24](https://avatars.githubusercontent.com/u/11960180?v=4)](https://github.com/damek24 "damek24 (7 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/djweb-payments/health.svg)

```
[![Health](https://phpackages.com/badges/djweb-payments/health.svg)](https://phpackages.com/packages/djweb-payments)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[neuron-core/neuron-ai

The PHP Agentic Framework.

1.8k245.3k21](/packages/neuron-core-neuron-ai)[theodo-group/llphant

LLPhant is a library to help you build Generative AI applications.

1.5k311.5k5](/packages/theodo-group-llphant)[tempest/framework

The PHP framework that gets out of your way.

2.1k23.1k9](/packages/tempest-framework)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)[dnetix/redirection

Library to connect with PlacetoPay Checkout service

17123.3k2](/packages/dnetix-redirection)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
