📦 Marketplace⭐ GitHub
📦

monkeyslegion-stripe

v1.0.5MITApi

by Marouane Amanar

📋 What You'll Learn

This documentation covers everything you need to integrate Stripe payments into your MonkeysLegion application:

  • 🚀 Quick Start: Get up and running in minutes with automated setup

  • 🔧 Configuration: Environment variables, key management, and security setup

  • 🔑 Key Management: Interactive CLI tools for managing Stripe API keys and webhook secrets

  • 📋 Service Registration: Dependency injection setup with MonkeysLegion DI container

  • 💳 Payment Operations: Complete API for payment intents, checkout sessions, subscriptions, and products

  • 🔄 Test/Live Mode: Seamless switching between test and production environments

  • 🪝 Webhook Handling: Secure webhook processing with signature verification and idempotency

  • 📊 Logging: PSR-3 compatible logging with Monolog integration

  • 🛡️ Security: Payload validation, size limits, and secure key storage

Documentation

All usage, configuration, and API references can be found in the official Monkeys Legion Stripe package documentation.

🚀 Quick Start

Bash

composer require monkeyscloud/monkeyslegion-stripe # Install the package
php vendor/bin/ml stripe:install # Publish the configuration file
php vendor/bin/key-helper set # Set up your Stripe keys interactively
php vendor/bin/key-helper validate # Validate your configuration
php vendor/bin/key-helper webhook:test # Test webhook signature verification

Features

  • PSR-Compliant: Built with PSR standards for maximum compatibility

  • Service Container Integration: Automatic dependency injection

  • Configuration Management: Environment-based configuration with merging support

  • HTTP Client Abstraction: PSR-18 HTTP client implementation

  • Key Management: Built-in tools for managing Stripe API keys and webhook secrets

  • Webhook Testing: Comprehensive webhook signature validation testing

  • Environment Awareness: Supports .env.<stage> files for dev, prod, and test environments

Requirements

  • PHP 8.4 or higher

  • MonkeysLegion Core ^1.0

  • MonkeysLegion DI ^1.0 (composer require monkeyscloud/monkeyslegion-di)

  • Stripe PHP SDK ^17.3

Environment Awareness

The package supports environment-specific configurations using .env.<stage> files. By default, the dev environment is used. You can specify the environment using the --stage flag.

Example

Bash

php vendor/bin/key-helper validate # Use the dev environment (default)
php vendor/bin/key-helper --stage=test validate # Use the test environment
php vendor/bin/key-helper --stage=prod validate # Use the production environment

The .env.<stage> file will be used based on the specified stage.

Installation

Install the package via Composer:

Bash

composer require monkeyscloud/monkeyslegion-stripe

Configuration

Publish Configuration File

Publish the configuration file to your project:

Bash

php vendor/monkeyscloud/monkeyslegion-stripe/publish.php

Environment Variables

Configure your Stripe settings using the following environment variables:

Code snippet

# Essential Stripe API keys (managed by key-helper)
STRIPE_SECRET_KEY=sk_test_...            # Main secret key for backend API calls
STRIPE_PUBLISHABLE_KEY=pk_test_...       # Public key for frontend Stripe.js
STRIPE_WEBHOOK_SECRET=whsec_...          # Webhook secret for production/main environment
STRIPE_TEST_KEY=sk_test_...              # Additional test secret key
STRIPE_WEBHOOK_SECRET_TEST=whsec_...     # Webhook secret specifically for test mode

Optional Stripe API configuration (not validated by key-helper)

STRIPE_API_VERSION=2025-04-30 # Stripe API version your code expects STRIPE_CURRENCY=usd # Default currency for transactions STRIPE_CURRENCY_LIMIT=100000 # Maximum transaction amount in cents

Optional webhook configuration

STRIPE_WEBHOOK_TOLERANCE=20 # Time tolerance for webhook signature validation (seconds) STRIPE_WEBHOOK_DEFAULT_TTL=172800 # Default time-to-live for webhook events (seconds) STRIPE_MAX_PAYLOAD_SIZE=131072 # Maximum webhook payload size in bytes (default: 128KB)

Optional idempotency configuration

STRIPE_IDEMPOTENCY_TABLE=stripe_memory # Database table for storing idempotency events

Optional API request configuration

STRIPE_TIMEOUT=60 # Timeout for API requests (seconds) STRIPE_WEBHOOK_RETRIES=3 # Maximum number of retries for failed webhook events

Optional Stripe API endpoint

STRIPE_API_URL=https://api.stripe.com # Stripe API base URL

Note: The key-helper utility validates only the essential Stripe keys. Additional configuration variables can be added manually to your .env files as needed.

Configuration Structure

The configuration file supports the following options:

PHP

return [
    'secret_key'      => getenv('STRIPE_SECRET_KEY') ?: '',
    'publishable_key' => getenv('STRIPE_PUBLISHABLE_KEY') ?: '',
    'webhook_secret'  => getenv('STRIPE_WEBHOOK_SECRET') ?: '',
    'test_key'        => getenv('STRIPE_TEST_KEY') ?: '',
    'api_version'     => getenv('STRIPE_API_VERSION') ?: '2025-04-30',
    'currency'        => getenv('STRIPE_CURRENCY') ?: 'usd',
    'currency_limit'  => (int)(getenv('STRIPE_CURRENCY_LIMIT') ?: 100000),
    'webhook_tolerance' => (int)(getenv('STRIPE_WEBHOOK_TOLERANCE') ?: 20),
    'webhook_default_ttl' => (int)(getenv('STRIPE_WEBHOOK_DEFAULT_TTL') ?: 172800),
    'idempotency_table' => getenv('STRIPE_IDEMPOTENCY_TABLE') ?: 'stripe_memory',
    'timeout'         => (int)(getenv('STRIPE_TIMEOUT') ?: 60),
    'webhook_retries' => (int)(getenv('STRIPE_WEBHOOK_RETRIES') ?: 3),
    'api_url'         => getenv('STRIPE_API_URL') ?: 'https://api.stripe.com',
];

Key Management

The package includes a comprehensive key management utility for generating, validating, and managing Stripe API keys and webhook secrets. All operations are performed through the command line interface.

Key-Helper Features

  • Environment-Aware: Works with .env.dev, .env.prod, .env.test files

  • Secure Key Generation: Uses cryptographically secure random bytes

  • Format Validation: Validates Stripe key formats and structures

  • Interactive Setup: Guided setup for all essential Stripe keys

  • Key Rotation: Safe rotation of existing keys with backup

  • Webhook Testing: Live webhook secret validation with Stripe SDK

  • Batch Operations: Validate all keys at once or individually

Command Reference

Bash

php vendor/bin/key-helper [--stage=dev|prod|test] [COMMAND] [OPTIONS]

Available Commands: generate [KEY_TYPE] # Generate and save a new key (default: STRIPE_SECRET_KEY) set [KEY_NAME] [VALUE] # Set a specific key or enter interactive mode rotate [KEY_TYPE] # Rotate (replace) an existing key with backup validate [KEY_TYPE] # Validate keys (all if no type specified) show [KEY_TYPE] # Display current key value list # List all Stripe/webhook keys in environment webhook:test # Test webhook secret validation with simulated payload

Available Key Types: secret # STRIPE_SECRET_KEY test # STRIPE_TEST_KEY publishable # STRIPE_PUBLISHABLE_KEY webhook # STRIPE_WEBHOOK_SECRET webhook_test # STRIPE_WEBHOOK_SECRET_TEST

Stage Options: --stage=dev # Use .env.dev file (default) --stage=prod # Use .env.prod file --stage=test # Use .env.test file

Environment-Specific Key Management

The --stage flag allows you to manage keys for specific environments (dev, prod, test).

Example

Bash

php vendor/bin/key-helper --stage=test set # Set keys for the test environment
php vendor/bin/key-helper --stage=prod validate # Validate keys for the production environment
php vendor/bin/key-helper --stage=dev generate # Generate a new key for the dev environment

The .env.<stage> file will be updated or validated based on the specified stage.

Default behavior without stage flag: Uses .env.dev file

Generate New Keys

Generate Default Secret Key

Bash

php vendor/bin/key-helper generate # Generates STRIPE_SECRET_KEY (sk_test_* format)

Generate Specific Key Types

Bash

php vendor/bin/key-helper generate webhook # Generate webhook secret placeholder
php vendor/bin/key-helper generate secret # Generate secret key placeholder
php vendor/bin/key-helper generate publishable # Generate publishable key placeholder
php vendor/bin/key-helper generate webhook_test # Generate test webhook secret

Rotate Keys

Rotate Security Keys

Bash

# Rotate secret keys with new generated values
php vendor/bin/key-helper rotate secret
php vendor/bin/key-helper rotate webhook
php vendor/bin/key-helper rotate publishable
php vendor/bin/key-helper rotate webhook_test

Environment-Specific Rotation

Bash

# Rotate production keys
php vendor/bin/key-helper --stage=prod rotate secret
php vendor/bin/key-helper --stage=prod rotate webhook

php vendor/bin/key-helper --stage=test rotate webhook # Rotate test environment keys

Set Keys

Set Individual Keys

Bash

php vendor/bin/key-helper set STRIPE_SECRET_KEY sk_test_your_key_here # Set a specific key value

php vendor/bin/key-helper set STRIPE_WEBHOOK_SECRET whsec_your_secret_here # Set webhook secret

Interactive Setup Mode

Bash

# Enter interactive mode to set all Stripe keys
php vendor/bin/key-helper set

Interactive prompts for:

- STRIPE_PUBLISHABLE_KEY

- STRIPE_SECRET_KEY

- STRIPE_TEST_KEY

- STRIPE_WEBHOOK_SECRET

- STRIPE_WEBHOOK_SECRET_TEST

- STRIPE_API_VERSION

Press Enter to skip any key

Validate Keys

Validate All Keys

Bash

# Validates all Stripe keys and shows comprehensive status

php vendor/bin/key-helper validate

Example output:

✅ STRIPE_SECRET_KEY (secret): VALID

✅ STRIPE_PUBLISHABLE_KEY (publishable): VALID

⚠️ STRIPE_WEBHOOK_SECRET (webhook): NOT SET

✅ STRIPE_WEBHOOK_SECRET_TEST (webhook_test): VALID

Validate Specific Keys

Bash

# Validate individual key types

php vendor/bin/key-helper validate secret php vendor/bin/key-helper validate webhook php vendor/bin/key-helper validate webhook_test

Validate Keys for a Specific Environment

Bash

# Validate keys for the test environment
php vendor/bin/key-helper --stage=test validate

Validate specific key in production

php vendor/bin/key-helper --stage=prod validate secret

Advanced Key Management

Show Current Key Values

Bash

# Display current key values
php vendor/bin/key-helper show secret
php vendor/bin/key-helper show webhook
php vendor/bin/key-helper show webhook_test

Show keys for specific environment

php vendor/bin/key-helper --stage=prod show secret

List All Configuration Keys

Bash

# List all STRIPE and WEBHOOK keys
php vendor/bin/key-helper list

Example output:

STRIPE and WEBHOOK keys found:

STRIPE_SECRET_KEY = sk_test_...

STRIPE_PUBLISHABLE_KEY = pk_test_...

STRIPE_WEBHOOK_SECRET = whsec_...

STRIPE_WEBHOOK_SECRET_TEST = whsec_...

Webhook Secret Testing

Bash

# Test webhook secret validation with simulated Stripe payload

php vendor/bin/key-helper webhook:test

Example output:

Testing webhook secret validation...

✅ Webhook secret validation: VALID

HTTP Status: 200 OK

Process Time: 15.42ms

Event Type: payment_intent.succeeded

Key Validation Features

The key-helper validates different types of keys with specific format requirements:

Supported Validation Types

  • Stripe Secret Keys: sk_test_* or sk_live_* format, minimum 20 characters

  • Stripe Publishable Keys: pk_test_* or pk_live_* format, minimum 20 characters

  • Webhook Secrets: whsec_* format, minimum 7 characters

  • Generated Keys: 64-character hexadecimal strings for app keys

  • Placeholder Validation: Accepts partial keys ending with ... for development

Error Handling

Bash

# Example validation errors:

❌ STRIPE_SECRET_KEY (secret): INVALID

⚠️ STRIPE_WEBHOOK_SECRET (webhook): NOT SET

✅ STRIPE_PUBLISHABLE_KEY (publishable): VALID

Environment File Management

The key-helper safely manages environment files with these features:

File Safety

  • Atomic Operations: All file operations are atomic to prevent corruption

  • Backup on Rotation: Old keys are displayed before replacement

  • Comment Preservation: Comments in .env files are preserved during updates

  • Directory Creation: Automatically creates directories if they don't exist

Multi-Environment Support

  • Stage-Specific Files: Supports .env.dev, .env.prod, .env.test

  • Environment Isolation: Each environment has separate key management

  • Consistent Interface: Same commands work across all environments

Key Generation Security

  • Cryptographically Secure: Uses PHP's random_bytes() for key generation

  • Appropriate Formats: Generates keys in correct Stripe format (sk_test_, pk_test_, whsec_)

  • Configurable Length: Supports different key lengths for different purposes

Service Registration

Registration

(In Your app.php)

register the service provider by: Install DI package via Composer:

Bash

composer require monkeyscloud/monkeyslegion-stripe
use MonkeysLegion\DI\ContainerBuilder;
use MonkeysLegion\Stripe\Provider\StripeServiceProvider;

// Create a new container builder instance
$containerBuilder = new ContainerBuilder();

// Register the Stripe service provider
StripeServiceProvider::register($containerBuilder);

// Build the container
$container = $containerBuilder-&gt;build();

// Globalize it
define('ML_CONTAINER', $container);

// Get Stripe services using class names
$stripeClient = ML_CONTAINER-&gt;get(\Stripe\StripeClient::class);
$stripeGateway = ML_CONTAINER-&gt;get(\MonkeysLegion\Stripe\Client\StripeGateway::class);
$checkoutSession = ML_CONTAINER-&gt;get(\MonkeysLegion\Stripe\Client\CheckoutSession::class);
$subscription = ML_CONTAINER-&gt;get(\MonkeysLegion\Stripe\Client\Subscription::class);
$product = ML_CONTAINER-&gt;get(\MonkeysLegion\Stripe\Client\Product::class);
$setupIntentService = ML_CONTAINER-&gt;get(\MonkeysLegion\Stripe\Client\SetupIntentService::class);
$webhookController = ML_CONTAINER-&gt;get(\MonkeysLegion\Stripe\Webhook\WebhookController::class);</code></pre><h3>Test Mode Management</h3><p>All client services support switching between test and live modes:</p><p>PHP</p><pre class="code-block"><code>// Switch to test mode (default)
$stripeGateway-&gt;setTestMode(true);      // Uses STRIPE_TEST_KEY
$checkoutSession-&gt;setTestMode(true);    // Uses STRIPE_TEST_KEY
$subscription-&gt;setTestMode(true);       // Uses STRIPE_TEST_KEY

// Switch to live mode for production
$stripeGateway-&gt;setTestMode(false);     // Uses STRIPE_SECRET_KEY
$checkoutSession-&gt;setTestMode(false);   // Uses STRIPE_SECRET_KEY
$subscription-&gt;setTestMode(false);      // Uses STRIPE_SECRET_KEY

// You may use this approach if you prefer
$isProduction = ($_ENV['APP_ENV'] ?? 'dev') === 'prod';
$stripeGateway-&gt;setTestMode(!$isProduction);</code></pre><h2>Usage</h2><h3>Payment Intent Operations</h3><p>PHP</p><pre class="code-block"><code>// Get the gateway service
$stripeGateway = $container-&gt;get(\MonkeysLegion\Stripe\Client\StripeGateway::class);

// Create a payment intent
$paymentIntent = $stripeGateway-&gt;createPaymentIntent(
    2000,        // amount in cents
    'usd',       // currency
    true         // enable automatic payment methods
);

// Retrieve a payment intent
$paymentIntent = $stripeGateway-&gt;retrievePaymentIntent('pi_1234567890');

// Confirm a payment intent
$confirmedPayment = $stripeGateway-&gt;confirmPaymentIntent('pi_1234567890', [
    'payment_method' =&gt; 'pm_card_visa'
]);

// Cancel a payment intent
$cancelledPayment = $stripeGateway-&gt;cancelPaymentIntent('pi_1234567890');

// Capture a payment intent (for manual capture)
$capturedPayment = $stripeGateway-&gt;capturePaymentIntent('pi_1234567890');

// Refund a payment intent
$refund = $stripeGateway-&gt;refundPaymentIntent('pi_1234567890', [
    'amount' =&gt; 1000  // partial refund
]);

// Update a payment intent
$updatedPayment = $stripeGateway-&gt;updatePaymentIntent('pi_1234567890', [
    'description' =&gt; 'Updated payment description'
]);

// List payment intents
$paymentIntents = $stripeGateway-&gt;listPaymentIntent([
    'limit' =&gt; 10,
    'customer' =&gt; 'cus_1234567890'
]);

// Search payment intents
$searchResults = $stripeGateway-&gt;searchPaymentIntent([
    'query' =&gt; 'status:\'succeeded\' AND metadata[\'order_id\']:\'12345\''
]);

// Increment authorization
$incrementedPayment = $stripeGateway-&gt;incrementAuthorization('pi_1234567890', 500);

// Check if payment intent is valid
$isValid = $stripeGateway-&gt;isValidPaymentIntent('pi_1234567890');</code></pre><h3>Checkout Session Operations</h3><p>PHP</p><pre class="code-block"><code>// Get the checkout service
$checkoutSession = $container-&gt;get(\MonkeysLegion\Stripe\Client\CheckoutSession::class);

// Create a checkout session
$session = $checkoutSession-&gt;createCheckoutSession([
    'mode' =&gt; 'payment',
    'line_items' =&gt; [
        [
            'price_data' =&gt; [
                'currency' =&gt; 'usd',
                'product_data' =&gt; [
                    'name' =&gt; 'Premium Plan'
                ],
                'unit_amount' =&gt; 2000,
            ],
            'quantity' =&gt; 1,
        ],
    ],
    'success_url' =&gt; '[https://example.com/success?session_id=](https://example.com/success?session_id=){CHECKOUT_SESSION_ID}',
    'cancel_url' =&gt; '[https://example.com/cancel](https://example.com/cancel)',
]);

// Retrieve a checkout session
$session = $checkoutSession-&gt;retrieveCheckoutSession('cs_1234567890');

// List checkout sessions
$sessions = $checkoutSession-&gt;listCheckoutSessions([
    'limit' =&gt; 10
]);

// Expire a checkout session
$expiredSession = $checkoutSession-&gt;expireCheckoutSession('cs_1234567890');

// List line items from a session
$lineItems = $checkoutSession-&gt;listLineItems('cs_1234567890');

// Get checkout URL directly
$checkoutUrl = $checkoutSession-&gt;getCheckoutUrl([
    'mode' =&gt; 'payment',
    'line_items' =&gt; [/* ... */],
    'success_url' =&gt; '[https://example.com/success](https://example.com/success)',
    'cancel_url' =&gt; '[https://example.com/cancel](https://example.com/cancel)',
]);

// Validate checkout session
$isValid = $checkoutSession-&gt;isValidCheckoutSession('cs_1234567890');

// Check if session is expired
$isExpired = $checkoutSession-&gt;isExpiredCheckoutSession('cs_1234567890');</code></pre><h3>Subscription Operations</h3><p>PHP</p><pre class="code-block"><code>// Get the subscription service
$subscription = $container-&gt;get(\MonkeysLegion\Stripe\Client\Subscription::class);

// Create a subscription
$newSubscription = $subscription-&gt;createSubscription(
    'cus_1234567890',  // customer ID
    'price_1234567890', // price ID
    [
        'trial_period_days' =&gt; 7,
        'metadata' =&gt; ['plan' =&gt; 'premium']
    ]
);

// Retrieve a subscription
$subscription = $subscription-&gt;retrieveSubscription('sub_1234567890');

// Update a subscription
$updatedSubscription = $subscription-&gt;updateSubscription('sub_1234567890', [
    'metadata' =&gt; ['updated' =&gt; 'true'],
    'proration_behavior' =&gt; 'create_prorations'
]);

// Cancel a subscription
$cancelledSubscription = $subscription-&gt;cancelSubscription('sub_1234567890', [
    'at_period_end' =&gt; true
]);

// List customer subscriptions
$subscriptions = $subscription-&gt;listSubscriptions('cus_1234567890', [
    'status' =&gt; 'active',
    'limit' =&gt; 10
]);

// Resume a subscription
$resumedSubscription = $subscription-&gt;resumeSubscription('sub_1234567890');

// Search subscriptions
$searchResults = $subscription-&gt;searchSubscriptions([
    'query' =&gt; 'status:\'active\' AND metadata[\'plan\']:\'premium\''
]);</code></pre><h3>Product Operations</h3><p>PHP</p><pre class="code-block"><code>// Get the product service
$product = $container-&gt;get(\MonkeysLegion\Stripe\Client\Product::class);

// Create a product
$newProduct = $product-&gt;createProduct([
    'name' =&gt; 'Premium Software License',
    'description' =&gt; 'Annual software license with premium features',
    'metadata' =&gt; ['category' =&gt; 'software']
]);

// Retrieve a product
$product = $product-&gt;retrieveProduct('prod_1234567890');

// Update a product
$updatedProduct = $product-&gt;updateProduct('prod_1234567890', [
    'name' =&gt; 'Updated Premium License',
    'description' =&gt; 'Updated description'
]);

// Delete a product
$deletedProduct = $product-&gt;deleteProduct('prod_1234567890');

// List products
$products = $product-&gt;listProducts([
    'active' =&gt; true,
    'limit' =&gt; 10
]);

// Search products
$searchResults = $product-&gt;searchProducts(
    'metadata[\'category\']:\'software\'',
    ['limit' =&gt; 20]
);</code></pre><h3>Setup Intent Operations</h3><p>PHP</p><pre class="code-block"><code>// Get the setup intent service
$setupIntentService = $container-&gt;get(\MonkeysLegion\Stripe\Client\SetupIntentService::class);

// Create a setup intent
$setupIntent = $setupIntentService-&gt;createSetupIntent([
    'customer' =&gt; 'cus_1234567890',
    'payment_method_types' =&gt; ['card'],
    'usage' =&gt; 'off_session'
]);

// Retrieve a setup intent
$setupIntent = $setupIntentService-&gt;retrieveSetupIntent('seti_1234567890');

// Confirm a setup intent
$confirmedSetupIntent = $setupIntentService-&gt;confirmSetupIntent('seti_1234567890', [
    'payment_method' =&gt; 'pm_card_visa'
]);

// Cancel a setup intent
$cancelledSetupIntent = $setupIntentService-&gt;cancelSetupIntent('seti_1234567890');

// Update a setup intent
$updatedSetupIntent = $setupIntentService-&gt;updateSetupIntent('seti_1234567890', [
    'metadata' =&gt; ['updated' =&gt; 'true']
]);

// List setup intents
$setupIntents = $setupIntentService-&gt;listSetupIntents([
    'customer' =&gt; 'cus_1234567890',
    'limit' =&gt; 10
]);

// Validate setup intent
$isValid = $setupIntentService-&gt;isValidSetupIntent('seti_1234567890');</code></pre><h2>Webhook Handling</h2><h3>Setting Up Webhooks</h3><ol><li><p><strong>Configure Webhook Secret</strong></p><p>Bash</p><pre class="code-block"><code># Set your webhook secret from Stripe Dashboard
php vendor/bin/key-helper set STRIPE_WEBHOOK_SECRET whsec_your_secret_here

# Verify it's configured correctly
php vendor/bin/key-helper webhook:test</code></pre></li></ol><p>PHP</p><pre class="code-block"><code>// Get the webhook controller
$webhookController = ML_CONTAINER-&gt;get(\MonkeysLegion\Stripe\Webhook\WebhookController::class);

// Handle incoming webhook
$payload = file_get_contents('php://input');
$sigHeader = $_SERVER['HTTP_STRIPE_SIGNATURE'] ?? '';

$result = $webhookController-&gt;handle($payload, $sigHeader, function($event) {
    return ['status' =&gt; 'success', 'event' =&gt; $event['type']];
});

// Complete webhook endpoint example
function handleWebhook() {
    // This should be at your app.php
    $containerBuilder = new ContainerBuilder();
    StripeServiceProvider::register($containerBuilder);
    $container = $containerBuilder-&gt;build();
    define('ML_CONTAINER', $container);
    
    // 
    $webhookController = ML_CONTAINER-&gt;get(\MonkeysLegion\Stripe\Webhook\WebhookController::class);
    
    $payload = file_get_contents('php://input');
    $sigHeader = $_SERVER['HTTP_STRIPE_SIGNATURE'] ?? '';
    
    try {
        $result = $webhookController-&gt;handle($payload, $sigHeader, function ($event) {
            // Your event handling logic here
            return processStripeEvent($event);
        });

        http_response_code(200);
        echo json_encode($result);
    } catch (\Throwable $e) {
        $code = $e-&gt;getCode();

        // Ensure we don't return invalid HTTP codes
        if ($code &lt; 100 || $code &gt;= 600) $code = 500

        http_response_code($code);
        echo json_encode(['error' =&gt; $e-&gt;getMessage()]);
    }
}</code></pre><p>PHP</p><pre class="code-block"><code>// Production mode (APP_ENV=prod):
// - Retries: Rate limits, API connection errors, server errors (5xx)
// - No Retry: Card errors, invalid requests, authentication errors
// - Uses exponential backoff: 60s, 120s, 180s

// Development mode (APP_ENV=dev):
// - No retries for any errors (fail fast for debugging)
// - Immediate error reporting</code></pre><p>This package provides also a robust webhook handling system that securely processes Stripe events while preventing duplicate processing.</p><h3>Environment-Aware Storage</h3><p>The package automatically selects the appropriate storage backend for webhook idempotency based on your <code>APP_ENV</code> environment variable:</p><ul><li><p><strong>Development</strong> (<code>dev</code>, default): <strong>InMemoryStore</strong> - Fast, no persistence needed for development</p></li><li><p><strong>Testing</strong> (<code>test</code>, <code>testing</code>): <strong>SQLiteStore</strong> - Persistent but lightweight SQLite database for testing</p></li><li><p><strong>Production</strong> (<code>prod</code>, <code>production</code>): <strong>MySQLStore</strong> - Robust, scalable MySQL database storage</p></li></ul><p>Code snippet</p><pre class="code-block"><code># Set your environment in .env file
APP_ENV=dev      # Uses InMemoryStore
APP_ENV=test     # Uses SQLiteStore  
APP_ENV=prod     # Uses MySQLStore (requires database configuration)</code></pre><h3>Production Mode Features</h3><p>In production mode (<code>APP_ENV=prod</code>), the webhook system provides additional robustness:</p><ul><li><p><strong>Automatic Retries</strong>: Retries transient errors (rate limits, API connection issues) with exponential backoff</p></li><li><p><strong>MySQL Storage</strong>: Persistent storage for webhook idempotency across server restarts</p></li><li><p><strong>Enhanced Logging</strong>: Detailed error logging and retry attempts</p></li><li><p><strong>Timeout Handling</strong>: Process forking with timeout enforcement (Linux/Unix only)</p></li></ul><h3>Error Handling &amp; Retry Logic</h3><p>The webhook controller implements intelligent error handling based on the environment:</p><h3>Storage Implementation Details</h3><h4>InMemoryStore (Development)</h4><ul><li><p>Pure PHP array storage</p></li><li><p>No persistence between requests</p></li><li><p>Automatic TTL-based cleanup</p></li><li><p>Zero configuration required</p></li></ul><h4>SQLiteStore (Testing)</h4><ul><li><p>Lightweight file-based database</p></li><li><p>Persists across requests</p></li><li><p>Creates database file automatically</p></li><li><p>Default location: system temp directory</p></li></ul><h4>MySQLStore (Production)</h4><ul><li><p>Full database persistence</p></li><li><p>Requires <code>QueryBuilder</code> and <code>Connection</code></p></li><li><p>Uses configurable table name (<code>idempotency_store</code>)</p></li><li><p>Supports clustering and high availability</p></li></ul><h3>Database Schema</h3><p>For production MySQL storage, the following table is required:</p><p>SQL</p><pre class="code-block"><code>CREATE TABLE idempotency_store (
    id INT AUTO_INCREMENT PRIMARY KEY,
    event_id VARCHAR(255) UNIQUE NOT NULL,
    processed_at DATETIME NOT NULL,
    expiry DATETIME NULL,
    data JSON NULL,
    INDEX idx_event_id (event_id),
    INDEX idx_expiry (expiry)
);</code></pre><h3>Configuring Webhook Processing</h3><p>You can customize webhook processing behavior through environment variables:</p><p>Code snippet</p><pre class="code-block"><code># Webhook processing configuration
STRIPE_TIMEOUT=60                    # Timeout for webhook processing (seconds)
STRIPE_WEBHOOK_RETRIES=3             # Maximum retry attempts (production only)
STRIPE_WEBHOOK_TOLERANCE=20          # Signature timestamp tolerance (seconds)
STRIPE_WEBHOOK_DEFAULT_TTL=172800    # Event storage TTL (48 hours in seconds)</code></pre><h3>Configuring Expiration</h3><p>By default, processed events are stored for 48 hours. You can customize this:</p><p>PHP</p><pre class="code-block"><code>// In your app configuration
return [
    'webhook_default_ttl' =&gt; 86400, // 24 hours (in seconds)    // ...other config
];</code></pre><h2>PSR-3 Logger Integration</h2><p>The package includes built-in PSR-3 logger support for comprehensive logging of Stripe operations and webhook processing.</p><h3>Default Logger Behavior</h3><p>By default, the package uses an internal Logger class that supports PSR-3 LoggerInterface. The logging behavior adapts to your environment:</p><ul><li><p><strong>Development</strong> (<code>APP_ENV=dev</code>): Debug level messages</p></li><li><p><strong>Testing</strong> (<code>APP_ENV=test</code>): Notice level messages</p></li><li><p><strong>Production</strong> (<code>APP_ENV=prod</code>): Warning level messages</p></li></ul><h3>Logger Features</h3><ul><li><p><strong>Structured Logging</strong>: Includes context data like request IDs, error codes, and retry counts</p></li><li><p><strong>Environment-Aware</strong>: Automatically adjusts log levels based on APP_ENV</p></li><li><p><strong>Operation Tracking</strong>: Logs all Stripe API calls, webhook processing, and error handling</p></li><li><p><strong>Security</strong>: Sensitive data like API keys are never logged</p></li></ul><h3>Webhook Payload Size Limits</h3><p>For security, webhook payloads are limited to a maximum size to prevent memory exhaustion attacks:</p><ul><li><p><strong>Default Size Limit</strong>: 128KB (131,072 bytes)</p></li><li><p><strong>Environment Variable</strong>: <code>STRIPE_MAX_PAYLOAD_SIZE=131072</code></p></li><li><p><strong>Automatic Validation</strong>: Payloads exceeding the limit are rejected with detailed logging</p></li></ul><p>Code snippet</p><pre class="code-block"><code># Configure webhook payload size limit
STRIPE_MAX_PAYLOAD_SIZE=131072  # 128KB (default)
STRIPE_MAX_PAYLOAD_SIZE=262144  # 256KB (custom)</code></pre><p>The payload validation includes:</p><ul><li><p>Size limit checking</p></li><li><p>JSON format validation</p></li><li><p>Empty payload detection</p></li><li><p>Detailed error logging for debugging</p></li></ul><p></p>

Related Packages