Docs

Stripe

First-class Stripe integration package for the MonkeysLegion PHP framework, providing PSR-compliant HTTP clients and service container integration.

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

1 Quick Start

# Install the package
composer require monkeyscloud/monkeyslegion-stripe

# Publish the configuration file
php vendor/bin/ml stripe:install

# Set up your Stripe keys interactively
php vendor/bin/key-helper set

# Validate your configuration
php vendor/bin/key-helper validate

# Test webhook signature verification
php vendor/bin/key-helper webhook:test

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

Installation

composer require monkeyscloud/monkeyslegion-stripe

2 Configuration

Environment Variables

# Essential Stripe API keys
STRIPE_SECRET_KEY=sk_test_...
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_TEST_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET_TEST=whsec_...

# Optional configuration
STRIPE_API_VERSION=2025-04-30
STRIPE_CURRENCY=usd
STRIPE_CURRENCY_LIMIT=100000
STRIPE_WEBHOOK_TOLERANCE=20
STRIPE_WEBHOOK_DEFAULT_TTL=172800
STRIPE_MAX_PAYLOAD_SIZE=131072
STRIPE_IDEMPOTENCY_TABLE=stripe_memory
STRIPE_TIMEOUT=60
STRIPE_WEBHOOK_RETRIES=3
STRIPE_API_URL=https://api.stripe.com

3 Key Management

Environment-Aware Commands

# Default (dev environment)
php vendor/bin/key-helper validate

# Test environment
php vendor/bin/key-helper --stage=test validate

# Production environment  
php vendor/bin/key-helper --stage=prod validate

Generate Keys

# Generate default secret key
php vendor/bin/key-helper generate

# Generate specific key types
php vendor/bin/key-helper generate webhook
php vendor/bin/key-helper generate secret
php vendor/bin/key-helper generate publishable
php vendor/bin/key-helper generate webhook_test

Set Keys

# Set individual keys
php vendor/bin/key-helper set STRIPE_SECRET_KEY sk_test_your_key_here
php vendor/bin/key-helper set STRIPE_WEBHOOK_SECRET whsec_your_secret_here

# Interactive setup (recommended for first time)
php vendor/bin/key-helper set

Validate Keys

# Validate all keys
php vendor/bin/key-helper validate

# Validate specific keys
php vendor/bin/key-helper validate secret
php vendor/bin/key-helper validate webhook
php vendor/bin/key-helper validate webhook_test

Rotate Keys

# Rotate security keys
php vendor/bin/key-helper rotate secret
php vendor/bin/key-helper rotate webhook

# Environment-specific rotation
php vendor/bin/key-helper --stage=prod rotate secret
php vendor/bin/key-helper --stage=test rotate webhook

Advanced Key Operations

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

# List all configuration keys
php vendor/bin/key-helper list

# Test webhook secret validation
php vendor/bin/key-helper webhook:test

4 Service Registration

<?php

use MonkeysLegion\DI\ContainerBuilder;
use MonkeysLegion\Stripe\Provider\StripeServiceProvider;

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

// Register Stripe services
StripeServiceProvider::register($containerBuilder);

// Build container
$container = $containerBuilder->build();

// Globalize container or however you want
define('ML_CONTAINER', $container);

// Access Stripe services
$stripeClient = ML_CONTAINER->get(\Stripe\StripeClient::class);
$stripeGateway = ML_CONTAINER->get(\MonkeysLegion\Stripe\Client\StripeGateway::class);
$checkoutSession = ML_CONTAINER->get(\MonkeysLegion\Stripe\Client\CheckoutSession::class);
$subscription = ML_CONTAINER->get(\MonkeysLegion\Stripe\Client\Subscription::class);
$product = ML_CONTAINER->get(\MonkeysLegion\Stripe\Client\Product::class);
$setupIntentService = ML_CONTAINER->get(\MonkeysLegion\Stripe\Client\SetupIntentService::class);
$webhookController = ML_CONTAINER->get(\MonkeysLegion\Stripe\Webhook\WebhookController::class);

5 Test Mode Management

<?php

// Switch to test mode (default)
$stripeGateway->setTestMode(true);
$checkoutSession->setTestMode(true);
$subscription->setTestMode(true);

// Switch to live mode for production
$stripeGateway->setTestMode(false);
$checkoutSession->setTestMode(false); 
$subscription->setTestMode(false);

// Auto-detect based on environment
$isProduction = ($_ENV['APP_ENV'] ?? 'dev') === 'prod';
$stripeGateway->setTestMode(!$isProduction);

6 Payment Operations

Payment Intent Operations

<?php

$stripeGateway = ML_CONTAINER->get(\MonkeysLegion\Stripe\Client\StripeGateway::class);

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

// Retrieve payment intent
$paymentIntent = $stripeGateway->retrievePaymentIntent('pi_1234567890');

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

// Cancel payment intent
$cancelledPayment = $stripeGateway->cancelPaymentIntent('pi_1234567890');

// Capture payment intent
$capturedPayment = $stripeGateway->capturePaymentIntent('pi_1234567890');

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

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

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

// Validate payment intent
$isValid = $stripeGateway->isValidPaymentIntent('pi_1234567890');

Checkout Session Operations

<?php

$checkoutSession = ML_CONTAINER->get(\MonkeysLegion\Stripe\Client\CheckoutSession::class);

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

// Retrieve checkout session
$session = $checkoutSession->retrieveCheckoutSession('cs_1234567890');

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

// Expire checkout session
$expiredSession = $checkoutSession->expireCheckoutSession('cs_1234567890');

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

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

Subscription Operations

<?php

$subscription = ML_CONTAINER->get(\MonkeysLegion\Stripe\Client\Subscription::class);

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

// Retrieve subscription
$subscription = $subscription->retrieveSubscription('sub_1234567890');

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

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

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

// Resume subscription
$resumedSubscription = $subscription->resumeSubscription('sub_1234567890');

Product Operations

<?php

$product = ML_CONTAINER->get(\MonkeysLegion\Stripe\Client\Product::class);

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

// Retrieve product
$product = $product->retrieveProduct('prod_1234567890');

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

// Delete product
$deletedProduct = $product->deleteProduct('prod_1234567890');

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

// Search products
$searchResults = $product->searchProducts(
    'metadata[\'category\']:\'software\'',
    ['limit' => 20]
);

Setup Intent Operations

<?php

$setupIntentService = ML_CONTAINER->get(\MonkeysLegion\Stripe\Client\SetupIntentService::class);

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

// Retrieve setup intent
$setupIntent = $setupIntentService->retrieveSetupIntent('seti_1234567890');

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

// Cancel setup intent
$cancelledSetupIntent = $setupIntentService->cancelSetupIntent('seti_1234567890');

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

// Validate setup intent
$isValid = $setupIntentService->isValidSetupIntent('seti_1234567890');

7 Webhook Handling

Complete Webhook Endpoint

<?php

use MonkeysLegion\DI\ContainerBuilder;
use MonkeysLegion\Stripe\Provider\StripeServiceProvider;

function handleWebhook() {
    // Initialize container
    $containerBuilder = new ContainerBuilder();
    StripeServiceProvider::register($containerBuilder);
    $container = $containerBuilder->build();
    define('ML_CONTAINER', $container);
    
    // Get webhook controller
    $webhookController = ML_CONTAINER->get(\MonkeysLegion\Stripe\Webhook\WebhookController::class);
    
    $payload = file_get_contents('php://input');
    $sigHeader = $_SERVER['HTTP_STRIPE_SIGNATURE'] ?? '';
    
    try {
        $result = $webhookController->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->getCode();
        if ($code < 100 || $code >= 600) $code = 500;

        http_response_code($code);
        echo json_encode(['error' => $e->getMessage()]);
    }
}

// Example event processor
function processStripeEvent($event) {
    switch ($event['type']) {
        case 'payment_intent.succeeded':
            return handlePaymentSuccess($event['data']['object']);
        case 'payment_intent.payment_failed':
            return handlePaymentFailure($event['data']['object']);
        case 'customer.subscription.created':
            return handleSubscriptionCreated($event['data']['object']);
        default:
            return ['status' => 'ignored', 'event_type' => $event['type']];
    }
}

Environment-Aware Storage

The package automatically selects storage based on APP_ENV:

# Development - InMemoryStore (no persistence)
APP_ENV=dev

# Testing - SQLiteStore (file-based persistence)  
APP_ENV=test

# Production - MySQLStore (database persistence)
APP_ENV=prod

Production Database Schema

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)
);

Error Handling & Retry Logic

<?php

// 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

8 Logging & Security

Payload Size Limits

# Configure webhook payload size limit (default: 128KB)
STRIPE_MAX_PAYLOAD_SIZE=131072
STRIPE_MAX_PAYLOAD_SIZE=262144  # 256KB custom limit

Webhook Configuration

# Webhook processing settings
STRIPE_TIMEOUT=60
STRIPE_WEBHOOK_RETRIES=3
STRIPE_WEBHOOK_TOLERANCE=20
STRIPE_WEBHOOK_DEFAULT_TTL=172800

Security Features

  • Payload Validation: Automatic size and format validation

  • Signature Verification: Secure webhook signature checking

  • Idempotency: Prevents duplicate event processing

  • Environment Isolation: Separate keys for test/production

  • Secure Key Storage: Environment-based key management

  • Automatic Retry Logic: Handles transient failures gracefully

License

MIT © 2025 MonkeysCloud