How to Add Stripe Checkout to a Custom PHP Website (No Plugins)
Stripe is the cleanest payment API available. No monthly SaaS fees, no WooCommerce overhead, no Shopify transaction cuts. This is the exact implementation used on BuiltToWinWeb client stores — PHP, Stripe SDK, webhooks, and email confirmations.
Why Native PHP + Stripe Beats Every Page Builder
Shopify charges 0.5–2% per transaction on top of Stripe's own fee. WooCommerce adds 14+ plugin dependencies that slow your checkout page LCP to 3.8s. A custom PHP integration ships a checkout that loads in under 0.6s and keeps every penny of margin.
- Zero platform transaction fees — only Stripe's 2.9% + 30¢
- Checkout page Lighthouse score: 98 vs Shopify's typical 61
- Full webhook control — custom fulfillment, inventory, email
- No recurring subscription cost for the ecommerce platform
- Own your code, host anywhere, migrate freely
Step 1 — Install the Stripe PHP SDK
Composer is the cleanest approach. If your host doesn't support Composer, download the SDK zip and drop it in your project root.
composer require stripe/stripe-php
Then load it at the top of your checkout script:
require_once __DIR__ . '/vendor/autoload.php';
\Stripe\Stripe::setApiKey(getenv('STRIPE_SECRET_KEY'));
Step 2 — Create a Checkout Session (Server Side)
Never put your secret key in the browser. Create a server-side endpoint that the frontend POSTs to:
<?php
require_once __DIR__ . '/vendor/autoload.php';
\Stripe\Stripe::setApiKey(getenv('STRIPE_SECRET_KEY'));
$session = \Stripe\Checkout\Session::create([
'payment_method_types' => ['card'],
'line_items' => [[
'price_data' => [
'currency' => 'usd',
'unit_amount' => 175000, // $1,750 in cents
'product_data' => ['name' => 'Business Pro Website'],
],
'quantity' => 1,
]],
'mode' => 'payment',
'success_url' => 'https://yoursite.com/success?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => 'https://yoursite.com/pricing',
]);
header('Content-Type: application/json');
echo json_encode(['url' => $session->url]);
Step 3 — Redirect the User from the Frontend
A simple fetch call on your pricing page button:
document.getElementById('buy-btn').addEventListener('click', async () => {
const res = await fetch('/create-checkout-session.php', { method: 'POST' });
const data = await res.json();
window.location.href = data.url;
});
Step 4 — Handle Webhooks (Fulfillment)
Stripe sends a POST to your webhook endpoint when payment succeeds. This is where you trigger email, update inventory, and record the order — NOT on the success page (which users can skip).
<?php
$payload = file_get_contents('php://input');
$sig = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$secret = getenv('STRIPE_WEBHOOK_SECRET');
try {
$event = \Stripe\Webhook::constructEvent($payload, $sig, $secret);
} catch (\Exception $e) {
http_response_code(400); exit;
}
if ($event->type === 'checkout.session.completed') {
$session = $event->data->object;
fulfill_order($session); // your custom function
}
http_response_code(200);
Register your webhook URL in the Stripe dashboard under Developers → Webhooks. Use the CLI locally: `stripe listen --forward-to localhost/webhook.php`.
Step 5 — Send a Confirmation Email via PHPMailer
Inside your `fulfill_order()` function, pull the customer email from the session and fire PHPMailer:
function fulfill_order($session) {
$email = $session->customer_details->email;
$name = $session->customer_details->name;
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
$mail->isSMTP();
$mail->Host = 'smtp.yourhost.com';
$mail->Username = getenv('SMTP_USER');
$mail->Password = getenv('SMTP_PASS');
$mail->setFrom('hello@yoursite.com', 'Your Business');
$mail->addAddress($email, $name);
$mail->Subject = 'Payment Received — Thank You!';
$mail->Body = "Hi $name, your order is confirmed.";
$mail->send();
}
Platform Comparison — Custom PHP vs Shopify vs WooCommerce
Real Business Impact
On a \$50,000/month ecommerce store, Stripe's 2.9% + 30¢ is unavoidable. But Shopify's additional 0.5–2% platform fee costs \$250–\$1,000 per month extra. Custom PHP eliminates that.
- Shopify Advanced (\$399/mo) + 0.5% fee on \$50k = \$649/mo platform cost
- Custom PHP + Stripe = \$0/mo platform cost (just Stripe's standard fees)
- Breakeven on a \$5,600 custom build: under 9 months
- Checkout pages load 3× faster = measurably lower cart abandonment
The math is simple: if you process more than \$15,000/month, a custom PHP store pays for itself in under a year.
Security Checklist
- Store keys in environment variables — never hardcode in PHP files
- Always verify Stripe webhook signatures with `constructEvent()`
- Use HTTPS everywhere — Stripe requires it
- Idempotency: check if the order already exists before fulfilling (replay protection)
- Rate-limit your `/create-checkout-session.php` endpoint (10 req/hr per IP)
Frequently Asked Questions
Do I need Composer to use Stripe with PHP?
Composer is recommended but not required. You can download the Stripe PHP SDK as a zip file and include it manually with require_once. Composer just makes updates easier.
Is it safe to process payments without a platform like Shopify?
Yes. Stripe is PCI-DSS Level 1 certified. Your server never handles raw card numbers — Stripe's JS tokenizes them client-side. Your PHP only receives a session ID.
How do I test Stripe without charging real cards?
Use Stripe test mode with key prefix sk_test_. Use test card 4242 4242 4242 4242 with any future expiry and any 3-digit CVC. Switch to live keys when ready to go live.
Can I add subscriptions with this approach?
Yes. Change the Checkout Session mode from "payment" to "subscription" and pass a recurring price ID instead of price_data. Stripe handles billing cycles automatically.
Want a Custom Stripe Store Built for You?
BuiltToWinWeb builds custom PHP ecommerce stores with native Stripe integration, Lighthouse 98+ scores, and zero monthly platform fees. Flat one-time fee — you own the code forever.
Stores typically ship in 3–4 weeks. Reply within 24 hours guaranteed.
Benchmark data from controlled tests on identical Hostinger VPS hosting. WooCommerce plugin count measured on default WooCommerce 8.x install with Storefront theme.