PHP code example of grazulex / laravel-api-idempotency

1. Go to this page and download the library: Download grazulex/laravel-api-idempotency library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

grazulex / laravel-api-idempotency example snippets


// routes/api.php
Route::post('/payments', [PaymentController::class, 'store'])
    ->middleware('idempotent');

Route::post('/orders', [OrderController::class, 'store'])
    ->middleware('idempotent:

// Custom TTL (seconds)
->middleware('idempotent:ttl=172800')  // 48 hours

// Require key (returns 400 if missing)
->middleware('idempotent:

use Grazulex\ApiIdempotency\Attributes\Idempotent;
use Grazulex\ApiIdempotency\Attributes\IdempotentExcept;

#[Idempotent]
class PaymentController extends Controller
{
    public function store(Request $request) { /* ... */ }

    #[IdempotentExcept]
    public function index() { /* ... */ } // Excluded
}

use Grazulex\ApiIdempotency\Facades\Idempotency;

// Check if already processed
if ($cached = Idempotency::get($key)) {
    return $cached->toResponse();
}

// Store manually
Idempotency::store($key, response()->json($data, 201));

// Skip caching (e.g., for validation errors)
Idempotency::skip();

use Grazulex\ApiIdempotency\Support\IdempotencyKey;

// Generate unique key
$key = IdempotencyKey::generate();         // "idem_01HQ3K4M..."
$key = IdempotencyKey::generate('pay');    // "pay_01HQ3K4M..."

// Deterministic key from data
$key = IdempotencyKey::fromData([
    'user_id' => 123,
    'action' => 'create_payment',
]);

use Grazulex\ApiIdempotency\Events\IdempotentRequestProcessed;
use Grazulex\ApiIdempotency\Events\IdempotentRequestReplayed;
use Grazulex\ApiIdempotency\Events\IdempotentConflictDetected;
use Grazulex\ApiIdempotency\Events\IdempotentPayloadMismatch;

// config/api-idempotency.php
return [
    'enabled' => env('API_IDEMPOTENCY_ENABLED', true),
    'header' => env('API_IDEMPOTENCY_HEADER', 'Idempotency-Key'),

    'key' => [
        'EMPOTENCY_DRIVER', 'cache'),

    'drivers' => [
        'cache' => [
            'store' => 'default',
            'prefix' => 'idempotency:',
        ],
        'redis' => [
            'connection' => 'default',
            'prefix' => 'idempotency:',
        ],
        'database' => [
            'connection' => null,
            'table' => 'idempotency_keys',
        ],
        'dynamodb' => [
            'table' => 'idempotency_keys',
            'region' => 'eu-west-1',
        ],
    ],

    'ttl' => env('API_IDEMPOTENCY_TTL', 86400), // 24 hours

    'conflict' => [
        'strategy' => 'wait', // or 'reject'
        'wait_timeout' => 10,
        'retry_interval' => 100,
    ],

    'fingerprint' => [
        'enabled' => true,
        'algorithm' => 'sha256',
        '

use Grazulex\ApiIdempotency\Facades\Idempotency;

public function test_idempotency(): void
{
    Idempotency::fake();

    // Your test code...

    Idempotency::assertStored('expected_key');
    Idempotency::assertReplayed('expected_key');
    Idempotency::assertStoredCount(5);
}

public function test_payment_is_idempotent(): void
{
    $key = 'test_key_' . uniqid();
    $payload = ['amount' => 9999];

    $response1 = $this->postJson('/api/payments', $payload, [
        'Idempotency-Key' => $key,
    ]);

    $response1->assertStatus(201)
        ->assertHeader('X-Idempotent-Replayed', 'false');

    $response2 = $this->postJson('/api/payments', $payload, [
        'Idempotency-Key' => $key,
    ]);

    $response2->assertStatus(201)
        ->assertHeader('X-Idempotent-Replayed', 'true')
        ->assertJson($response1->json());
}
bash
php artisan vendor:publish --tag="api-idempotency-config"
bash
php artisan vendor:publish --tag="api-idempotency-migrations"
php artisan migrate
bash
curl -X POST https://api.example.com/payments \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pay_abc123_unique_key" \
  -d '{"amount": 9999, "currency": "EUR"}'
http
HTTP/1.1 201 Created
Idempotency-Key: pay_abc123_unique_key
X-Idempotent-Replayed: true
X-Original-Request-Time: 2025-01-15T10:30:00+00:00
bash
# View statistics
php artisan idempotency:stats

# Cleanup expired keys
php artisan idempotency:cleanup

# Remove specific key
php artisan idempotency:forget pay_abc123

# List recent keys
php artisan idempotency:list --limit=20