noith/tbank

Framework-agnostic T-Bank (Tinkoff) Acquiring API v2 client

Maintainers

Package info

gitlab.com/noith-payment/tbank

Issues

pkg:composer/noith/tbank

Statistics

Installs: 5

Dependents: 1

Suggesters: 0

Stars: 0

1.1.0 2026-06-27 13:20 UTC

This package is auto-updated.

Last update: 2026-06-27 10:21:49 UTC


README

Framework-agnostic HTTP client for the T-Bank (Tinkoff) Acquiring API v2.

The package contains only the transport-facing layer: typed request objects, typed response DTOs, token signing/verification, response mapping, receipt DTOs, and a small TbankClient wrapper over noith/api-requester.

Requirements

PHP^8.3
ext-mbstring*
noith/api-requester^1.0

Installation

composer require noith/tbank

Creating a Client

use Noith\TBank\TbankClient;

$tbank = new TbankClient(
    terminalKey: 'your-terminal',
    secretKey: 'your-secret',
    apiUrl: 'https://securepay.tinkoff.ru/v2',
    cashboxUrl: 'https://securepay.tinkoff.ru/cashbox',
);

SendClosingReceipt uses the cashbox API. If you call that endpoint, pass the cashbox URL explicitly when it differs from the default:

$tbank = new TbankClient(
    terminalKey: 'your-terminal',
    secretKey: 'your-secret',
    cashboxUrl: 'https://securepay.tinkoff.ru/cashbox',
);

Usage

use Noith\TBank\Requests\ConfirmRequest;
use Noith\TBank\Requests\GetQrRequest;
use Noith\TBank\Requests\InitRequest;

$init = $tbank->send(new InitRequest(
    orderId: 'order-1',
    amount: 150000,
    description: 'Order #1',
    notificationUrl: 'https://example.com/tbank/webhook',
    successUrl: 'https://example.com/paid',
    failUrl: 'https://example.com/failed',
));

$paymentUrl = $init->paymentUrl;

$qr = $tbank->send(new GetQrRequest($init->paymentId));

$confirmed = $tbank->send(new ConfirmRequest($init->paymentId));

Available requests:

EndpointRequestResponse
InitInitRequestInitResponse
FinishAuthorizeFinishAuthorizeRequestFinishAuthorizeResponse
ConfirmConfirmRequestConfirmResponse
CancelCancelRequestCancelResponse
ChargeChargeRequestChargeResponse
ChargeQrChargeQrRequestChargeQrResponse
GetStateGetStateRequestGetStateResponse
CheckOrderCheckOrderRequestCheckOrderResponse
ResendResendRequestResendResponse
SendClosingReceiptSendClosingReceiptRequestSendClosingReceiptResponse
GetQrGetQrRequestGetQrResponse
SbpPayTestSbpPayTestRequestSbpPayTestResponse
AddCustomerAddCustomerRequestAddCustomerResponse
GetCustomerGetCustomerRequestGetCustomerResponse
RemoveCustomerRemoveCustomerRequestRemoveCustomerResponse
GetCardListGetCardListRequestCardResponse[]
RemoveCardRemoveCardRequestRemoveCardResponse

Two-stage payments use TbankPayType (O one-stage / T two-stage) on InitRequest, then send() a ConfirmRequest or CancelRequest for the authorized amount.

Request options with a closed T-Bank value set are typed as enums. For example, SBP bank-list device type is strict while device OS stays a free string because T-Bank does not publish a closed OS list:

use Noith\TBank\DTO\TbankQrBankListDevice;
use Noith\TBank\Enums\TbankQrBankListDeviceType;
use Noith\TBank\Enums\TbankQrBankListScenarioType;
use Noith\TBank\Requests\GetQrBankListRequest;

$banks = $tbank->send(new GetQrBankListRequest(
    device: new TbankQrBankListDevice(
        type: TbankQrBankListDeviceType::MOBILE,
        os: 'iOS',
    ),
    scenarioType: TbankQrBankListScenarioType::SUBSCRIPTION,
));

Receipts

Use Noith\TBank\DTO\Receipt DTOs when an endpoint accepts a T-Bank Receipt payload: InitRequest, ConfirmRequest, CancelRequest, and SendClosingReceiptRequest. Pick the DTO variant that matches the fiscal data format configured for the terminal.

use Noith\TBank\DTO\Receipt\TbankReceiptFfd105;
use Noith\TBank\DTO\Receipt\TbankReceiptItemFfd105;
use Noith\TBank\Enums\Taxation;
use Noith\TBank\Enums\VatRate;
use Noith\TBank\Requests\InitRequest;

$receipt = new TbankReceiptFfd105(
    taxation: Taxation::OSN,
    email: 'buyer@example.com',
    items: [
        new TbankReceiptItemFfd105(
            name: 'Subscription',
            price: 150000,
            quantity: 1,
            amount: 150000,
            tax: VatRate::VAT22,
        ),
    ],
);

$request = new InitRequest(
    orderId: 'order-1',
    amount: 150000,
    receipt: $receipt,
);

For FFD 1.2, receipt items additionally require MeasurementUnit, PaymentMethod, and the FFD 1.2 PaymentObject enum:

use Noith\TBank\DTO\Receipt\TbankReceiptFfd12;
use Noith\TBank\DTO\Receipt\TbankReceiptItemFfd12;
use Noith\TBank\Enums\PaymentMethod;
use Noith\TBank\Enums\PaymentObjectFfd12;
use Noith\TBank\Enums\Taxation;
use Noith\TBank\Enums\VatRate;

$receipt = new TbankReceiptFfd12(
    taxation: Taxation::OSN,
    email: 'buyer@example.com',
    items: [
        new TbankReceiptItemFfd12(
            name: 'Subscription',
            price: 150000,
            quantity: 1,
            amount: 150000,
            tax: VatRate::VAT22,
            measurementUnit: 'шт',
            paymentMethod: PaymentMethod::FULL_PAYMENT,
            paymentObject: PaymentObjectFfd12::SERVICE,
        ),
    ],
);

Webhooks

This package does not register routes or process webhook side effects. It only provides signature verification and typed notification DTOs.

Use TbankNotificationFactory::fromVerifiedArray() for the whole incoming webhook flow: verify the token first, then map the payload to a concrete DTO by NotificationType. Payment notifications are treated as NotificationPayment when NotificationType is absent, matching T-Bank docs.

use Noith\TBank\Auth\TbankTokenAuthenticator;
use Noith\TBank\Exceptions\InvalidNotificationSignatureException;
use Noith\TBank\Notifications\TbankAddCardNotification;
use Noith\TBank\Notifications\TbankNotificationFactory;
use Noith\TBank\Notifications\TbankPaymentNotification;
use Noith\TBank\Notifications\TbankQrNotification;

try {
    $notification = TbankNotificationFactory::fromVerifiedArray(
        payload: $payload,
        authenticator: new TbankTokenAuthenticator(
            terminalKey: 'your-terminal',
            secretKey: 'your-secret',
        ),
    );
} catch (InvalidNotificationSignatureException) {
    // Reject invalid notification.
    return;
}

match (true) {
    $notification instanceof TbankPaymentNotification => $notification->status,
    $notification instanceof TbankAddCardNotification => $notification->status,
    $notification instanceof TbankQrNotification => $notification->status,
    default => null,
};

When you already have a TbankClient instance and want to reuse its verifier, verify first and then parse:

use Noith\TBank\Notifications\TbankNotificationFactory;

if (!$tbank->verify($payload)) {
    // Reject invalid notification.
    return;
}

$notification = TbankNotificationFactory::fromArray($payload);

Notification DTOs keep the raw payload for logging or repeated signature checks:

$raw = $notification->payload();

Concrete notification classes:

Notification typeDTOTyped status
NotificationPayment or missing NotificationTypeTbankPaymentNotificationTbankPaymentStatus
NotificationAddCardTbankAddCardNotificationTbankCardBindingStatus
NotificationFiscalizationTbankFiscalizationNotificationraw string, because fiscalization statuses are not modeled as a closed list
NotificationQrTbankQrNotificationTbankAccountQrStatus

Errors

T-Bank usually returns logical API errors as HTTP 200 responses with Success=false or a non-zero ErrorCode. TbankResponseMapper converts these responses into TbankApiException.

Testing

composer test