Skip to content

canovack/stripe-api-sample

Repository files navigation

Stripe PHP Payment Example

Author: Abbas Can Ovacık

A Stripe PaymentIntents integration example using PHP 8.2, Apache, and Docker. Covers the full payment flow — card input, billing details, 3D Secure authentication, webhook handling, and CSRF protection. Intended as a learning reference.

Features

  • Stripe Elements for secure card input
  • Billing address and contact information collection
  • Payment processing via Stripe PaymentIntents API
  • 3D Secure (3DS) redirect and completion handling
  • CSRF protection on payment endpoint
  • Stripe webhook support (payment_intent.succeeded, payment_intent.payment_failed)
  • File-based request logging (logs/app-YYYY-MM-DD.log)
  • SweetAlert2 for user-friendly success/error notifications
  • Phone number input masking with Inputmask
  • ISO 3166-1 country code dropdown (required by Stripe)
  • Dockerized PHP 8.2 + Apache environment

Project Structure

stripe-api-sample/
├── public/                 # Apache document root
│   ├── card-payment.html   # Payment form UI
│   ├── payment.js          # Stripe Elements handler, form submission
│   ├── payment.css         # Payment form styles
│   ├── create.php          # POST — creates and confirms a PaymentIntent
│   ├── complete.html       # Post-payment result page
│   ├── complete.js         # Fetches payment status, renders result
│   ├── complete.css        # Result page styles
│   ├── complete.php        # GET  — checks status via ?payment_intent=
│   ├── status.php          # POST — checks status from request body
│   ├── public_key.php      # GET  — returns Stripe publishable key
│   ├── csrf.php            # GET  — issues a session CSRF token
│   └── webhook.php         # POST — handles Stripe webhook events
├── src/
│   └── Logger.php          # File logger (writes to logs/)
├── logs/                   # Runtime logs — git-ignored, .gitkeep present
├── secrets.php             # .env loader + Stripe key provider
├── .env                    # Environment variables — NOT tracked in git
├── .env.example            # Environment variables template
├── composer.json           # PHP dependencies (Stripe PHP SDK)
├── Dockerfile              # PHP 8.2 + Apache
└── docker-compose.yml      # Development environment

Setup

1. Configure environment

cp .env.example .env

Fill in your Stripe test keys from the Stripe Dashboard:

STRIPE_SECRET_KEY=sk_test_...
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...   # see Webhook Setup below
APP_URL=http://localhost:8080

2. Install dependencies

docker compose run --rm composer install

3. Start the application

docker compose up -d

Open http://localhost:8080/card-payment.html.

Webhook Setup (Local)

Install the Stripe CLI, then:

stripe login
stripe listen --forward-to localhost:8080/webhook.php

Copy the whsec_... secret shown in the output into your .env, then restart:

docker compose restart

Test with:

stripe trigger payment_intent.succeeded

Successful events appear in logs/app-YYYY-MM-DD.log.

Testing

Use these Stripe test cards (any future expiry, any CVC):

Scenario Card Number
Successful payment 4242 4242 4242 4242
Card declined 4000 0000 0000 0002
Insufficient funds 4000 0000 0000 9995
3D Secure required 4000 0025 0000 3155

Monitor logs in real time:

tail -f logs/app-$(date +%Y-%m-%d).log

Error Handling

Exception Client message Logged
CardException (card declined, insufficient funds, etc.) Stripe's user-facing message Yes (INFO)
InvalidRequestException "Invalid payment request." Yes (ERROR)
AuthenticationException "Payment service error." Yes (ERROR)
Any other \Throwable "An unexpected error occurred." Yes (ERROR)

Internal error details are never exposed to the client.

Security Notes

  • CSRF tokens are issued via csrf.php and validated in create.php on every payment request.
  • payment_intent_id inputs are validated against /^pi_[a-zA-Z0-9_]+$/ before being sent to Stripe.
  • Webhook requests are verified using \Stripe\Webhook::constructEvent().
  • logs/ is git-ignored and sits outside the Apache document root (public/).
  • This project is for educational and testing purposes — not production-ready without additional hardening (authentication, database, rate limiting).

Technologies & Libraries

License

MIT License — see LICENSE for details.

Copyright (c) 2026–present Abbas Can Ovacık

About

Stripe PaymentIntents example using PHP, Docker, and Stripe.js

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors