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.
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
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:
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
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:
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:
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.
When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.