PHPackages                             dalpras/payment-bank-transfer - 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. dalpras/payment-bank-transfer

ActiveLibrary[Payment Processing](/categories/payments)

dalpras/payment-bank-transfer
=============================

Manual bank transfer connector for dalpras/payment-core.

v0.5.0(2mo ago)02MITPHPPHP ^8.2

Since Apr 27Pushed 1mo agoCompare

[ Source](https://github.com/dalpras/payment-bank-transfer)[ Packagist](https://packagist.org/packages/dalpras/payment-bank-transfer)[ RSS](/packages/dalpras-payment-bank-transfer/feed)WikiDiscussions main Synced 2w ago

READMEChangelogDependencies (3)Versions (4)Used By (0)

dalpras/payment-bank-transfer
=============================

[](#dalpraspayment-bank-transfer)

Manual bank transfer connector for `dalpras/payment-core`.

This package implements a provider for offline/manual bank transfers. It creates normalized checkout instructions containing beneficiary, IBAN/BIC, payment reference, amount and expiration. It does **not** contact a payment gateway, does **not** verify settlement automatically, and does **not** send emails directly.

Side effects such as email, ERP calls, CRM updates, outbox writes or queue messages are intentionally decoupled behind a small event dispatcher contract.

Status
------

[](#status)

Skeleton package, consistent with the current `dalpras/payment-core` and provider-connector split.

Included:

- `BankTransferProvider` implementing `DalPraS\Payment\Contract\PaymentProviderInterface`
- `BankTransferConfig`
- bank transfer instructions DTO
- optional event dispatcher interface
- null dispatcher
- reference generator interface
- unsupported-operation exception
- minimal PHPUnit structure

Not included:

- SMTP, SendGrid, Mailgun, Symfony Mailer or Laminas Mail integrations
- ERP / CRM clients
- bank account reconciliation APIs
- automatic settlement confirmation
- framework controllers

Installation
------------

[](#installation)

```
composer require dalpras/payment-bank-transfer
```

Basic usage
-----------

[](#basic-usage)

```
use DalPraS\Payment\BankTransfer\Config\BankTransferConfig;
use DalPraS\Payment\BankTransfer\Provider\BankTransferProvider;

$config = new BankTransferConfig(
    beneficiaryName: 'My Store Srl',
    iban: 'IT60X0542811101000000123456',
    bic: 'BCITITMM',
    bankName: 'Example Bank',
    expiresAfterDays: 7,
);

$provider = new BankTransferProvider($config);

$response = $provider->createCheckout($checkoutRequest);

// $response->redirectRequired === false
// $response->status === PaymentStatus::PendingCustomerAction
// $response->raw['instructions'] contains the bank transfer instructions
```

Decoupled callbacks / side effects
----------------------------------

[](#decoupled-callbacks--side-effects)

The package exposes `BankTransferEventDispatcherInterface`. Your application can implement it to send email, enqueue jobs, call services, or write to an outbox.

```
use DalPraS\Payment\BankTransfer\Contract\BankTransferEventDispatcherInterface;
use DalPraS\Payment\BankTransfer\Dto\BankTransferEvent;
use DalPraS\Payment\BankTransfer\Enum\BankTransferEventType;

final class AppBankTransferEventDispatcher implements BankTransferEventDispatcherInterface
{
    public function dispatch(BankTransferEvent $event): void
    {
        if ($event->type === BankTransferEventType::CustomerActionRequired) {
            // Create an email job, write to outbox, call ERP, etc.
            // Do not put provider-specific code into the package.
        }
    }
}
```

Then inject it:

```
$provider = new BankTransferProvider(
    config: $config,
    eventDispatcher: new AppBankTransferEventDispatcher(),
);
```

For production, prefer an outbox implementation so side effects happen after your application has persisted the payment state.

Core mapping
------------

[](#core-mapping)

### `createCheckout()`

[](#createcheckout)

Creates manual bank transfer instructions and returns:

- `PaymentStatus::PendingCustomerAction`
- `redirectRequired = false`
- no redirect URL
- `providerPaymentId` equal to the generated bank transfer reference
- raw payload containing `instructions`

### `completeCheckout()`

[](#completecheckout)

No external provider completion exists. The payment remains pending until the merchant confirms settlement.

### `authorize()`

[](#authorize)

Unsupported. Manual bank transfer cannot authorize funds.

### `capture()`

[](#capture)

Used as the manual “mark paid / confirmed” operation. Returns `PaymentStatus::Captured` by default.

### `cancel()`

[](#cancel)

Marks the manual bank transfer as cancelled.

### `refund()`

[](#refund)

Marks the refund as manually processed. No bank API call is made.

### `sync()`

[](#sync)

Returns the manual state requested through metadata, or `pending_customer_action` by default.

### Webhooks

[](#webhooks)

Manual bank transfer has no provider webhook. `parseWebhook()` returns an unsupported event, and `verifyWebhook()` returns an unverified result.

Events
------

[](#events)

The provider can dispatch:

- `checkout_created`
- `customer_action_required`
- `payment_confirmed`
- `payment_cancelled`
- `refund_marked`
- `payment_synced`

Events are neutral DTOs. They do not depend on mailers, queues, frameworks, ERPs, or CRMs.

Recommended production pattern
------------------------------

[](#recommended-production-pattern)

For robust side effects:

1. call `PaymentManager` / provider operation
2. persist payment + operation result
3. write a payment event to an outbox
4. process the outbox asynchronously in your application
5. send email / invoke external services from the application layer

This keeps the connector reusable and provider-focused.

Package layout
--------------

[](#package-layout)

- `src/Config/BankTransferConfig.php`
- `src/Provider/BankTransferProvider.php`
- `src/Dto/BankTransferInstructions.php`
- `src/Dto/BankTransferEvent.php`
- `src/Contract/BankTransferEventDispatcherInterface.php`
- `src/Contract/BankTransferReferenceGeneratorInterface.php`
- `src/Support/*`
- `src/Exception/*`

License
-------

[](#license)

MIT

Compatibility with payment-core metadata persistence
----------------------------------------------------

[](#compatibility-with-payment-core-metadata-persistence)

This package is compatible with the payment-core metadata lifecycle introduced for redirect and multi-step providers.

Even though a manual bank transfer has no external gateway operation id, the provider still returns normalized metadata so `PaymentManager` can persist and reuse the payment reference consistently across requests.

### Metadata returned by `createCheckout()`

[](#metadata-returned-by-createcheckout)

`createCheckout()` returns `CheckoutResponse::$metadata` with generic keys used by core and bank-transfer-specific keys used by applications:

```
[
    'provider' => 'bank_transfer',
    'provider_payment_id' => 'PAYMENT-REFERENCE',
    'order_id' => 'MERCHANT-REFERENCE',
    'payment_reference' => 'PAYMENT-REFERENCE',
    'manual' => true,
    'bank_transfer_reference' => 'PAYMENT-REFERENCE',
    'bank_transfer_iban' => 'IT...',
    'bank_transfer_bic' => '...',
    'bank_transfer_beneficiary_name' => 'My Store Srl',
    'bank_transfer_amount' => '100.00',
    'bank_transfer_currency' => 'EUR',
    'bank_transfer_expires_at' => '2026-01-01T12:00:00+00:00',
]
```

Applications that persist provider metadata on their order entity should merge this metadata after checkout creation/completion, just like they do for Nexi and PayPal.

### Completion

[](#completion)

`completeCheckout()` keeps the payment in `PendingCustomerAction`. There is no external provider to verify. The merchant must later confirm settlement manually, usually by calling `capture()` through `PaymentManager`.

### Manual confirmation

[](#manual-confirmation)

Use `capture()` to mark the bank transfer as paid:

```
$result = $paymentManager->capture(new CaptureRequest(
    providerCode: 'bank_transfer',
    paymentReference: $paymentReference,
    providerPaymentId: null,
    idempotencyKey: $paymentReference . ':bank-transfer-confirm',
    metadata: [
        'description' => 'Bank transfer received',
    ],
));
```

If the payment repository is backed by Redis/Symfony Cache, `PaymentManager` will reuse the stored `provider_payment_id` / `bank_transfer_reference` automatically.

### Manual cancellation

[](#manual-cancellation)

Use `cancel()` to mark the pending transfer as cancelled:

```
$result = $paymentManager->cancel(new CancelRequest(
    providerCode: 'bank_transfer',
    paymentReference: $paymentReference,
    providerPaymentId: null,
    idempotencyKey: $paymentReference . ':bank-transfer-cancel',
    metadata: [
        'description' => 'Customer cancelled before transfer was received',
    ],
));
```

### Manual refund

[](#manual-refund)

Use `refund()` to mark an already captured transfer as manually refunded:

```
$result = $paymentManager->refund(new RefundRequest(
    providerCode: 'bank_transfer',
    paymentReference: $paymentReference,
    providerPaymentId: null,
    idempotencyKey: $paymentReference . ':bank-transfer-refund:' . $refundId,
    metadata: [
        'amount_minor' => '5000',
        'currency' => 'EUR',
        'description' => 'Manual refund executed by accounting',
    ],
));
```

### Persistence recommendation

[](#persistence-recommendation)

Use the same production setup as Nexi and PayPal:

- `PaymentRepositoryInterface` wired to `CachePaymentRepository` or `RedisPaymentRepository`
- `IdempotencyStoreInterface` wired to `CacheIdempotencyStore` or `RedisIdempotencyStore`
- durable order-level metadata persisted in your application entity, for example `OrderEntity::paymentMetadata`

The cache/Redis repository is temporary flow state. Your order table remains the long-term source for accounting, customer service, refunds and debugging.

###  Health Score

35

—

LowBetter than 77% of packages

Maintenance90

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity38

Early-stage or recently created project

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

Every ~12 days

Total

3

Last Release

65d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/f4ad7c52ee1f0a8936e8bb6bcc95f15d4f55ce63233a0fa629da25bba024bd97?d=identicon)[dalpras](/maintainers/dalpras)

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/dalpras-payment-bank-transfer/health.svg)

```
[![Health](https://phpackages.com/badges/dalpras-payment-bank-transfer/health.svg)](https://phpackages.com/packages/dalpras-payment-bank-transfer)
```

###  Alternatives

[aws/aws-sdk-php

AWS SDK for PHP - Use Amazon Web Services in your PHP project

6.2k543.5M2.7k](/packages/aws-aws-sdk-php)[symfony/symfony

The Symfony PHP framework

31.4k87.2M2.2k](/packages/symfony-symfony)[guzzlehttp/psr7

PSR-7 message implementation that also provides common utility methods

7.9k1.1B4.1k](/packages/guzzlehttp-psr7)[neuron-core/neuron-ai

The PHP Agentic Framework.

2.0k656.1k46](/packages/neuron-core-neuron-ai)[tempest/framework

The PHP framework that gets out of your way.

2.2k34.4k16](/packages/tempest-framework)[telnyx/telnyx-php

Official Telnyx PHP SDK — APIs for Voice, SMS, MMS, WhatsApp, Fax, SIP Trunking, Wireless IoT, Call Control, and more. Build global communications on Telnyx's private carrier-grade network.

36789.4k2](/packages/telnyx-telnyx-php)

PHPackages © 2026

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