Files
alfa-bank-sdk/RELEASE_NOTES.md
Anatoliy Poloz 29645b7a5f feat(retries): never repeat non-idempotent or verdict requests
Saloon retries whenever an exception is thrown (handleRetry defaults to true)
and both connectors set tries = 3, so POST /payoffs, PATCH /payoffs/{id}/accept
and SBP QrcReversalRequest were sent to the bank up to three times while the
caller believed it had made a single request. For payouts a repeated POST is a
duplicate-payment risk, not a harmless retry.

HasSafeRetries replaces the HasTries default at the connector level (Saloon
retries only when the per-send callable, the request and the connector all
allow it):
- a deterministic bank verdict (4xx/5xx) is never retried;
- an explicit deny-list covers money operations;
- an explicit allow-list keeps retries for read-only SBP operations, since that
  API uses POST even for reads (GetQrcReversalDataRequest stays denied: the bank
  matches the following reversal against it, EBD 44 / I14044);
- by default only GET/HEAD/OPTIONS are retried.

Every decision is logged through the connector's PSR-3 logger as
'[alfa-sdk][retry]', so physical request count per operation is countable via
X-Request-ID.

Tests: tests/Feature/RetryPolicyTest.php (23 tests), including an assertion on
the real retry loop that a failing non-idempotent POST is sent exactly once,
while a read-only GET still uses all configured attempts.
2026-09-29 10:44:18 +03:00

4.1 KiB

Alfa Bank SDK - Release Notes v1.1.0

⚠️ Behaviour change: safe retries

Saloon retries a request whenever an exception is thrown (handleRetry returns true by default) and both SDK connectors set tries = 3. As a result, non-idempotent operations (POST /payoffs, PATCH /payoffs/{id}/accept, SBP QrcReversal) were sent to the bank up to three times while the calling code believed it had made a single request. For payouts a repeated POST is a duplicate-payment risk, not a harmless retry — the SDK now stops this at the connector level, because Saloon only retries when the per-send callable, the request and the connector all allow it.

The new trait Apoloz\AlfaBank\Traits\HasSafeRetries replaces the default with an explicit policy:

  1. A deterministic bank verdict (4xx/5xx) is never retried.
  2. An explicit deny-list of money operations is never retried.
  3. An explicit allow-list keeps retries for read-only SBP operations (that API uses POST for reads).
  4. By default only read-only HTTP methods (GET/HEAD/OPTIONS) are retried.

Every decision is reported through the connector's PSR-3 logger ([alfa-sdk][retry]), which makes the number of physical requests countable per operation via the X-Request-ID header.

🐞 Fixes

  • Restored the missing HasStringBody and CmsSigner imports in Sbp\Requests\DigitalRuble\CashLink\* requests: the classes failed with a fatal error when loaded.

🧪 Tests

  • Added tests/Feature/RetryPolicyTest.php (23 tests): money operations and bank verdicts are never repeated, read-only operations keep their retries, and the real Saloon retry loop is asserted (a failing non-idempotent POST reaches the wire exactly once).

Alfa Bank SDK - Release Notes v1.0.0

🚀 Overview

The Alfa Bank SDK is a production-ready, enterprise-grade library for integrating with Alfa Bank's API (BaaS & SBP). It is built on top of Saloon v3 and Spatie Laravel Data, ensuring strict typing, robustness, and idiomatic Laravel integration.

✨ Key Features

1. Unified API Access

  • BaaS (Bank-as-a-Service): Full coverage of Accounts, Payments, Cards, Statements, and Salary projects.
  • SBP (Faster Payments): Dedicated connector for C2B/B2C/B2B payouts with automated body signing (JCS/RSA-SHA256).
  • Security: Native support for mTLS (GOST/RSA), detached CMS/PKCS#7 signatures, and JWS transport security.

2. Architecture & Quality

  • DTO-Driven: 100% of requests and responses are mapped to Data Transfer Objects. No more raw arrays.
  • Saloon Power: Middleware for error handling, automatic retries, and timeouts.
  • Pagination: Smart AlfaOffsetPaginator handling various response formats automatically.
  • Testing: 63 automated tests verifying every module.

3. Laravel Integration

  • Zero-Config: Auto-discovery via Service Provider.
  • Facades: AlfaBank:: and Sbp:: for static access.
  • Config: Publishable config/alfa-bank.php.
  • Webhooks: Route macro Route::alfaWebhooks() and event dispatching.

🛠️ Installation

composer require apoloz/alfa-bank-sdk

📖 Usage Examples

Create a Payment

use AlfaBank;
use Apoloz\AlfaBank\Requests\Payments\CreatePaymentRequest;
use Apoloz\AlfaBank\Data\Payments\PaymentData;

$data = new PaymentData(
    amount: 100.50,
    payeeAccount: '40702...',
    // ...
);

$response = AlfaBank::send(new CreatePaymentRequest($data));
echo $response->id; // "EXT-123"

Iterate Transactions (Pagination)

use Apoloz\AlfaBank\Requests\Statement\GetTransactionsRequest;

$paginator = AlfaBank::paginate(new GetTransactionsRequest('40702...'));

foreach ($paginator as $transaction) {
    echo $transaction->amount;
}

SBP Payout

use Sbp;
use Apoloz\AlfaBank\Sbp\Requests\Payouts\CreatePayoutRequest;

// The SDK handles body signing automatically
Sbp::send(new CreatePayoutRequest($payoutData));

✅ Verification Status

  • Tests Passed: 63/63
  • Static Analysis: PHPStan Level 5 (0 errors)
  • Integration Test: Verified in Laravel 12 environment via alfa-bank-app.

Ready for deployment.