/stripe-guides

How to use Stripe API with PHP?

Learn how to integrate Stripe API with PHP in this step-by-step tutorial covering setup, payment forms, subscriptions, webhooks, error handling, and security best practices.

Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

Book a free consultation

How to use Stripe API with PHP?

How to Use Stripe API with PHP: A Comprehensive Tutorial

 

Introduction

 

This tutorial will guide you through integrating Stripe payment processing into your PHP application. Stripe provides robust APIs for handling online payments securely. We'll cover everything from setup to implementing common payment scenarios.

 

Step 1: Set Up Your Stripe Account

 

Before writing any code, you need to create and configure your Stripe account:

  1. Sign up for a Stripe account at https://dashboard.stripe.com/register
  2. Verify your email address and complete the required account information
  3. Navigate to the Developers section in your Stripe Dashboard
  4. Locate your API keys (both publishable and secret keys)

Note: Stripe provides both test and live keys. Always use test keys during development.

 

Step 2: Install the Stripe PHP Library

 

There are two ways to install the Stripe PHP library:

Option A: Install via Composer (Recommended)


composer require stripe/stripe-php

Option B: Manual Installation

  1. Download the latest release from GitHub
  2. Extract the files to your project directory
  3. Include the init.php file in your project

require\_once('/path/to/stripe-php/init.php');

 

Step 3: Set Up Your PHP Environment

 

Create a basic configuration file to store your Stripe API keys:


Create an initialization file to load the Stripe library and set your API key:


 

Step 4: Create a Simple Payment Form

 

Create an HTML form to collect payment information:





    
    
    Stripe Payment Form
    
    


    

 

Step 5: Process the Payment on the Server

 

Create a PHP script to handle the form submission and process the payment:


 $email,
            'name' => $name,
            'source' => $token,
        ]);
        
        // Create a charge
        $charge = \Stripe\Charge::create([
            'customer' => $customer->id,
            'amount' => $amount,
            'currency' => 'usd',
            'description' => 'Payment for product/service',
        ]);
        
        // Payment successful
        echo "Payment successful! Charge ID: " . $charge->id;
        
        // You might want to store payment details in your database here
        
    } catch (\Stripe\Exception\CardException $e) {
        // Card was declined
        echo "Error: " . $e->getError()->message;
    } catch (\Exception $e) {
        // Another error occurred
        echo "Error: " . $e->getMessage();
    }
} else {
    // Not a POST request
    header('Location: index.php');
    exit;
}

 

Step 6: Implementing Stripe Checkout (Alternative Approach)

 

Stripe Checkout provides a pre-built, hosted payment page. Here's how to implement it:


 ['card'],
    'line\_items' => [[
        'price\_data' => [
            'currency' => 'usd',
            'product\_data' => [
                'name' => 'Product Name',
            ],
            'unit\_amount' => 2000, // $20.00 in cents
        ],
        'quantity' => 1,
    ]],
    'mode' => 'payment',
    'success_url' => 'https://yourdomain.com/success.php?session_id={CHECKOUT_SESSION_ID}',
    'cancel\_url' => 'https://yourdomain.com/cancel.php',
]);
?>




    
    
    Stripe Checkout
    


    

Checkout with Stripe

 

Step 7: Handling Webhook Events

 

Webhooks allow Stripe to notify your application when events happen in your account:


type) {
        case 'payment\_intent.succeeded':
            $paymentIntent = $event->data->object;
            // Handle successful payment
            handleSuccessfulPayment($paymentIntent);
            break;
            
        case 'payment_intent.payment_failed':
            $paymentIntent = $event->data->object;
            // Handle failed payment
            handleFailedPayment($paymentIntent);
            break;
            
        case 'charge.refunded':
            $charge = $event->data->object;
            // Handle refunded charge
            handleRefundedCharge($charge);
            break;
            
        // Add more event types as needed
        
        default:
            // Unexpected event type
            http_response_code(400);
            exit();
    }
    
    // Return a success response to Stripe
    http_response_code(200);
    echo json\_encode(['status' => 'success']);
    
} catch(\UnexpectedValueException $e) {
    // Invalid payload
    http_response_code(400);
    exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
    // Invalid signature
    http_response_code(400);
    exit();
} catch (\Exception $e) {
    // Other error
    http_response_code(500);
    echo json\_encode(['error' => $e->getMessage()]);
    exit();
}

// Helper functions for handling different events
function handleSuccessfulPayment($paymentIntent) {
    // Update database, send confirmation email, etc.
    // Example: 
    // $paymentId = $paymentIntent->id;
    // $amount = $paymentIntent->amount / 100; // Convert from cents
    // $customerId = $paymentIntent->customer;
    
    // You would typically add code here to:
    // 1. Update your database with payment status
    // 2. Fulfill orders or provide access to purchased content
    // 3. Send confirmation emails to customers
}

function handleFailedPayment($paymentIntent) {
    // Log failure, notify customer, etc.
}

function handleRefundedCharge($charge) {
    // Update refund status in your database, etc.
}

 

Step 8: Creating Subscription Plans

 

For recurring billing, you can create subscription plans:


 'Premium Subscription',
    'description' => 'Monthly subscription to premium features',
]);

// Create a price (plan) for the product
$price = \Stripe\Price::create([
    'product' => $product->id,
    'unit\_amount' => 1999, // $19.99 in cents
    'currency' => 'usd',
    'recurring' => [
        'interval' => 'month', // month, year, week, or day
    ],
]);

// Store the price ID in your database for later use
echo "Product created: " . $product->id . "
"; echo "Price created: " . $price->id . "
"; // Now you can use this price ID to create subscriptions

 

Step 9: Creating a Customer Subscription

 

Once you have a price ID, you can create subscriptions for customers:


 '[email protected]',
    'name' => 'John Doe',
    'payment_method' => 'pm_card\_visa', // This would come from your payment form
]);

// Attach the payment method to the customer
\Stripe\PaymentMethod::attach(
    'pm_card_visa', // This would come from your payment form
    ['customer' => $customer->id]
);

// Set the default payment method for the customer
\Stripe\Customer::update($customer->id, [
    'invoice\_settings' => [
        'default_payment_method' => 'pm_card_visa', // This would come from your payment form
    ],
]);

// Create the subscription
$subscription = \Stripe\Subscription::create([
    'customer' => $customer->id,
    'items' => [
        ['price' => $priceId],
    ],
    'expand' => ['latest_invoice.payment_intent'],
]);

// Check if payment needs additional authentication
if ($subscription->status === 'active') {
    // Subscription is active
    echo "Subscription created successfully. Subscription ID: " . $subscription->id;
} elseif ($subscription->latest_invoice->payment_intent->status === 'requires\_action') {
    // Additional action required (like 3D Secure)
    echo json\_encode([
        'subscription\_id' => $subscription->id,
        'client_secret' => $subscription->latest_invoice->payment_intent->client_secret,
    ]);
}

 

Step 10: Error Handling and Security Best Practices

 

Implement robust error handling and follow security best practices:


 2000,
        'currency' => 'usd',
        'source' => 'tok\_visa', // obtained with Stripe.js
        'description' => 'Test Charge',
    ]);
    
    // Process successful charge
    return [
        'success' => true,
        'charge\_id' => $charge->id
    ];
    
} catch (\Stripe\Exception\CardException $e) {
    // Card declined
    return [
        'success' => false,
        'error' => $e->getError()->message,
        'code' => $e->getError()->code,
        'type' => 'card\_error'
    ];
    
} catch (\Stripe\Exception\RateLimitException $e) {
    // Too many requests made to the API too quickly
    logError('rate_limit_error', $e);
    return ['success' => false, 'error' => 'Rate limit exceeded'];
    
} catch (\Stripe\Exception\InvalidRequestException $e) {
    // Invalid parameters were supplied to Stripe's API
    logError('invalid_request_error', $e);
    return ['success' => false, 'error' => 'Invalid request'];
    
} catch (\Stripe\Exception\AuthenticationException $e) {
    // Authentication with Stripe's API failed
    logError('authentication\_error', $e);
    return ['success' => false, 'error' => 'Authentication failed'];
    
} catch (\Stripe\Exception\ApiConnectionException $e) {
    // Network communication with Stripe failed
    logError('api_connection_error', $e);
    return ['success' => false, 'error' => 'Network error'];
    
} catch (\Stripe\Exception\ApiErrorException $e) {
    // Generic API error
    logError('api\_error', $e);
    return ['success' => false, 'error' => 'API error'];
    
} catch (\Exception $e) {
    // Something else happened, unrelated to Stripe
    logError('general\_error', $e);
    return ['success' => false, 'error' => 'An error occurred'];
}

// Helper function to log errors
function logError($type, $exception) {
    // Log to file or database
    error\_log("Stripe {$type}: " . $exception->getMessage());
    
    // For critical errors, you might want to send notifications
    if (in_array($type, ['authentication_error', 'api\_error'])) {
        // sendAdminNotification($type, $exception->getMessage());
    }
}

 

Security Best Practices:

  1. Never log or display full card details
  2. Always use HTTPS for your payment pages
  3. Keep your API keys secure and never expose them in client-side code
  4. Validate all input data before sending to Stripe
  5. Implement proper error handling as shown above
  6. Use Stripe's test mode and test cards during development
  7. Regularly update the Stripe PHP library to get the latest security patches

 

Step 11: Testing Your Integration

 

Stripe provides test cards for simulating different scenarios:


// Test card numbers
// 4242 4242 4242 4242 - Successful payment
// 4000 0000 0000 0002 - Card declined
// 4000 0000 0000 3220 - 3D Secure authentication required

// Test with PHP
try {
    $charge = \Stripe\Charge::create([
        'amount' => 2000,
        'currency' => 'usd',
        'source' => 'tok\_visa', // This is a test token
        'description' => 'Test charge',
    ]);
    
    echo "Test successful! Charge ID: " . $charge->id;
} catch (\Exception $e) {
    echo "Test failed: " . $e->getMessage();
}

 

Step 12: Going Live

 

When you're ready to accept real payments:

  1. Complete your Stripe account setup (business details, bank account, etc.)
  2. Update your configuration to use live API keys instead of test keys
  3. Set up proper SSL/TLS on your website
  4. Perform thorough testing with test cards before switching to live mode
  5. Implement proper monitoring and logging

 

Conclusion

 

You now have a comprehensive understanding of how to integrate Stripe payments into your PHP application. The Stripe API offers many more features beyond what we've covered here, including invoicing, disputes handling, reporting, and more. Always refer to the official Stripe documentation for the most up-to-date information.

Remember to always follow best security practices when handling payments, and consider consulting with a security expert before deploying payment processing in production.

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Book a Free Consultation

Client trust and success are our top priorities

When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.

Rapid Dev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with. They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

CPO, Praction - Arkady Sokolov

May 2, 2023

Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost. He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Co-Founder, Arc - Donald Muir

Dec 27, 2022

Rapid Dev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space. They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Co-CEO, Grantify - Mat Westergreen-Thorne

Oct 15, 2022

Rapid Dev is an excellent developer for no-code and low-code solutions.
We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Co-Founder, Church Real Estate Marketplace - Emmanuel Brown

May 1, 2024 

Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 
This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Production Manager, Media Production Company - Samantha Fekete

Sep 23, 2022