Security-first PHP + MySQL ecommerce platform for modern storefront and admin operations.
Storefront + Admin Panel • COD + Stripe • CSRF + CAPTCHA + Rate Limiting • Audit Logging
Commerza is a PHP + MySQL ecommerce platform with a customer storefront and an operations-focused admin panel.
This README is the canonical engineering guide for setup, security posture, feature boundaries, and production operations.
Last updated: 2026-04-20
Commerza is production-oriented and launch-ready for Apache/PHP hosting with:
- Clean-route storefront and restricted admin/backend surfaces
- Prepared-statement-first data access across user-facing mutation/query paths
- Layered controls for CSRF, CAPTCHA, rate limiting, idempotency, and audit logging
- Hardened checkout path with stock locking, payment verification, and coupon validation
- Documented operations model for backups, security gates, and cron-based automation
- Storefront + admin panel in one repository with shared security bootstrap
- Payment flows: COD + Stripe card with server-side verification and risk controls
- Anti-abuse controls: request throttling, captcha hardening, blacklist checks
- Security monitoring: admin security events plus CI security gate checks
- Launch docs included: README, SECURITY.md, robots.txt, sitemap.xml, llms.txt
- Backend: PHP (mysqli prepared statements), Apache, MySQL
- DB migration bridge: PDO helper available for incremental endpoint migration
- Frontend: Server-rendered PHP templates, Bootstrap, jQuery, modular CSS/JS assets
- Deployment shape: XAMPP-compatible (local) and Apache hosting (production)
- Shared bootstrap: backend/core/data.php
- admin/: admin frontend UI plus admin backend split into auth/ and api//
- backend/: shared helpers, storefront APIs, cron/report scripts, schema
- frontend/: storefront static assets (css, js, images, videos)
- root *.php pages: storefront and auth/public entrypoints
- infra/docs files: .htaccess, robots.txt, sitemap.xml, llms.txt, SECURITY.md
Current repository inventory (verified snapshot on 2026-04-20):
- Root-level PHP pages (
*.phpat repository root): 24 - Admin frontend PHP pages (
admin/frontend/*.php): 6 - Combined storefront/admin entry pages: 30
- Admin backend PHP APIs (
admin/backend/api/**/*.php): 9 - Shared backend PHP files (
backend/**/*.phpexcludingbackend/api/**): 30 - Total tracked PHP files (
git ls-files '*.php'): 80 - Total tracked files in repository tree (
git ls-files): 339
Quick re-check commands:
git ls-files | Measure-Object | Select-Object -ExpandProperty Count
git ls-files "*.php" | Measure-Object | Select-Object -ExpandProperty Count
(Get-ChildItem -Path . -Filter *.php -File).Count
(Get-ChildItem -Path .\admin\frontend -Filter *.php -File).Count
(Get-ChildItem -Path .\admin\backend\api -Recurse -Filter *.php -File).Count
(Get-ChildItem -Path .\backend -Recurse -Filter *.php -File | Where-Object { $_.FullName -notmatch '\\backend\\api\\' } | Measure-Object).CountPublic storefront routes are clean-route pages such as /, /products, /about, /contact, /shipping, /returns, and policy pages.
Restricted or sensitive surfaces include:
- /admin/*
- /backend/*
- account and transaction flows (/account, /cart, /order-tracking, /invoice)
- auth and recovery flows (/login, /signup, /forgot-password, /reset-password)
Commerza features a native dual-theme system that adapts to user preference or system settings:
- Dark Mode (Main): A high-contrast OrangeRed + Black aesthetic designed for reduced eye strain and a modern "engineering" feel.
- Light Mode (Default): A clean NavyBlue + White professional interface optimized for readability in high-light environments.
- Browse catalog and category pages
- Search and suggestions
- Cart, wishlist, compare
- Coupon-aware checkout (COD + Stripe)
- Account profile management
- Password reset and account safety controls
- Order tracking and invoice views
- Product reviews (eligibility based on delivered/completed/received orders)
- Dashboard with KPI cards and recent-order visibility
- Sub-admin (mini admin) lifecycle: create, email-verify, edit, suspend/reactivate, resend verification, and soft delete
- Immediate session revocation on sub-admin suspend/delete (and sensitive identity/password updates)
- Role presets plus custom access model for sub-admins
- Product sections and product CRUD
- Product trash archive and restore workflows
- Orders table, status updates, and refund moderation
- Coupons management and campaign tooling
- Customer directory and blacklist controls
- Per-sub-admin hidden-tab controls with runtime tab gating in the admin UI
- Account blacklist notice visibility toggle for account.php warning banner
- Reviews moderation and review tooling
- Website settings, social links, slider/ticker controls
- Security event monitoring
- Email center and recipient management
Checkout currently supports Cash on Delivery (COD) and Stripe card payments.
- Supported method in checkout UI:
- Cash on Delivery (COD)
- Stripe (Card)
- Stripe card flow:
- Client-side Stripe SDK (
https://js.stripe.com/v3/) for card capture and confirmation - Server-side PaymentIntent creation and verification in
cart.php - Required environment keys:
STRIPE_PUBLISHABLE_KEY,STRIPE_SECRET_KEY
- Client-side Stripe SDK (
- Order placement still enforces CSRF, idempotency, CAPTCHA, stock locking, and coupon checks.
- High-value COD policy:
- COD OTP threshold is configurable via
COMMERZA_COD_OTP_THRESHOLD(default15000) - Optional COD hard limit via
COMMERZA_COD_HIGH_VALUE_HARD_LIMIT(default0, disabled) - When threshold applies, checkout requires a 6-digit email OTP before order creation
- COD OTP threshold is configurable via
Commerza's production DB safety posture uses the following baseline:
- Request-facing queries use prepared statements (
prepare+bind_param) for user input - String-concatenated SQL is limited to internal schema/setup flows and controlled constants
- IDs from request context are cast to strict integer types before query usage
- Dynamic enum-like inputs (action/status/mode/field) are validated against allowlists
- Critical write paths use transactions, row-locking, and idempotency controls
Operational note:
- The project is not fully PDO-only yet; active runtime data access is mysqli prepared-statement based
- PDO connection support exists in
backend/core/data.phpfor controlled migration of new/updated modules
Password security is centralized in backend/security/security_helpers.php.
- Primary hash algorithm: Argon2id (when PASSWORD_ARGON2ID is available)
- Fallback hash algorithm: bcrypt with cost 12
- Emergency fallback in hashing: PASSWORD_DEFAULT if primary hashing fails
- Verify path: password_verify
- Rehash path: password_needs_rehash against current algorithm/options
Password policy baseline:
- Length: 10 to 64
- Requires uppercase, lowercase, number, special character
- No whitespace
Admin and sub-admin verification code policy:
- Verification and recovery codes are 6-digit OTP values
- Code expiry is 15 minutes
- Codes are one-time use and cleared after successful verification or password reset
Account username changes are lock-protected.
- Lock duration: 90 days after each successful username change
- Enforcement: server-side during profile update (not only UI)
- Data source: users.username_changed_at
CAPTCHA is centralized in backend/security/security_helpers.php and uses a layered hybrid model.
Layered checks:
- Honeypot field and submit-time checks
- reCAPTCHA v3 verification
- reCAPTCHA v2 verification
- Built-in fallback challenge when needed
reCAPTCHA and honeypot runtime behavior:
- Honeypot field (
commerza_contact_website) is embedded in CAPTCHA widget HTML and must remain empty; non-empty submissions are rejected server-side before token verification. - reCAPTCHA v3 is used as the primary automatic verification path when v3 keys are configured.
- reCAPTCHA v2 checkbox is rendered when v2 is configured and v3 is not active for that flow.
- Backup challenge remains available for network/key failures and low-confidence/failed automated verification conditions.
Current v3 hardening details:
- Default minimum score is stricter (0.65 default, floor 0.55)
- Action must match server-expected context
- Hostname must match request host
- challenge_ts freshness is validated
- Invalid token length and invalid score payloads are rejected
Fallback challenge hardening details:
- Randomized knowledge plus arithmetic challenge generation
- Answer normalization (case/spacing/symbol tolerance within strict bounds)
- Hashed answer verification per nonce and context
- Minimum solve-time guard
- Attempt tracking with lockout after repeated failures
CSP nonce generation details:
- Nonce source: cryptographically secure
random_bytes(16) - Encoding: base64url (typically ~22 characters)
- Lifecycle: generated per HTTP request (changes on each refresh)
- Helper:
commerza_csp_nonce_attr()for nonce-tagged inline blocks where needed
OAuth login supports both providers through backend/auth/oauth.php (via public oauth.php entrypoint).
Supported providers:
- Google OAuth
- Facebook OAuth
Configuration sources:
- Environment variables (COMMERZA_* and provider aliases)
- site_settings fallback keys
Security properties:
- Provider allowlist validation
- State/nonce validation with expiry handling
- Provider token exchange + profile fetch validation
- Active customer blacklist check on OAuth completion (email/phone)
- Safe error redirection back to auth flows
Email behavior is centralized in backend/mailer/mailer.php plus notification helpers.
SMTP routing strategy:
- Primary route: sender_net_primary (configurable host/port/auth/encryption)
- Secondary route: gmail_fallback (configurable fallback transport)
- Duplicate route suppression when primary and secondary point to same host/account
Sender/logo handling:
- Sender identity resolved from configured SMTP sender or support fallback
- Email logo prefers PNG for compatibility
- If only WebP exists and GD supports conversion, PNG is generated automatically
Automation scripts include:
- backend/jobs/send_engagement_reminders.php
- backend/jobs/monthly_profit_report.php
- backend/jobs/weekly_analytics_report.php
Commerza uses layered caching and response optimization.
Application cache layers:
- Runtime in-process cache
- APCu cache (when available)
- Redis cache (when available)
Cache helper file:
- backend/cache/cache_helpers.php
Important cache environment keys:
- COMMERZA_CACHE_ENABLED
- COMMERZA_CACHE_NAMESPACE
- COMMERZA_REDIS_HOST
- COMMERZA_REDIS_PORT
- COMMERZA_REDIS_DB
- COMMERZA_REDIS_PASSWORD
- COMMERZA_REDIS_TIMEOUT
- COMMERZA_SITE_SETTINGS_CACHE_TTL
Delivery optimizations:
- Static asset cache headers from .htaccess
- Shared HTML normalization and asset-loading optimizations in backend/core/data.php
- Fragment cache support for expensive render sections
Upload paths are validated and scanned.
Controls include:
- MIME and extension checks
- Parser-based validation/transformation for images
- Malware signature checks
- Optional ClamAV scan command integration
- Fail-open or fail-closed behavior configurable by environment
Related environment keys:
- COMMERZA_UPLOAD_SCAN_ENABLED
- COMMERZA_UPLOAD_SCAN_FAIL_CLOSED
- COMMERZA_CLAMSCAN_PATH
Commerza supports server-side Cloudinary uploads for admin media targets (images and videos).
Enable via environment:
- COMMERZA_CLOUDINARY_ENABLED=1
- COMMERZA_CLOUDINARY_CLOUD_NAME
- COMMERZA_CLOUDINARY_API_KEY
- COMMERZA_CLOUDINARY_API_SECRET
- COMMERZA_CLOUDINARY_UPLOAD_PRESET_IMAGE
- COMMERZA_CLOUDINARY_UPLOAD_PRESET_VIDEO
Optional tuning keys:
- COMMERZA_CLOUDINARY_FOLDER
- COMMERZA_CLOUDINARY_IMAGE_TRANSFORMATION
- COMMERZA_CLOUDINARY_VIDEO_TRANSFORMATION
- COMMERZA_CLOUDINARY_TIMEOUT
Maintenance command to provision presets then bulk-upload existing frontend assets:
php scripts/maintenance/cloudinary_sync.php
Useful flags:
--dry-run--skip-presets--skip-upload--skip-db--skip-sql
Cleanup command to remove stale Cloudinary assets that are no longer referenced by DB rows or the local asset map:
- Preview only:
php scripts/maintenance/cloudinary_cleanup.php - Apply delete:
php scripts/maintenance/cloudinary_cleanup.php --apply - Restrict scope:
php scripts/maintenance/cloudinary_cleanup.php --prefix=commerza/products - Process in chunks:
php scripts/maintenance/cloudinary_cleanup.php --apply --limit=25
Notes:
- The cleanup script now batch-deletes resources by type to reduce API operations.
- Placeholder resources with Cloudinary backups are purged using backup
version_idswhen detected. - If Cloudinary API rate limits are hit, the script exits early and can be resumed later with the same command.
Critical flows include transactional locking and anti-race protections.
Examples:
- Checkout stock protection:
- Transactional order placement
- SELECT ... FOR UPDATE stock lock before decrement
- Conditional stock update guard
- Checkout idempotency key consumption to block duplicate submissions
- Refund status update flow includes row-level lock semantics in admin orders API
- Username change lock window enforcement (90 days)
Storefront product feeds now exclude archived/deleted entries.
- products API excludes products with deleted_at (when column exists)
- products API excludes products present in product_trash (when table exists)
- Result: trashed products do not appear on user-facing product/search payloads
Review eligibility is verified server-side.
- Accepted order statuses for eligibility: delivered, completed, received
- Primary product linkage is by
product_id; temporary compatibility fallback to product-name matching exists for historic rows - Refund-linked restrictions remain enforced where refund tables exist
Customer blacklist enforcement scope (server-side):
- Blacklisted contacts are blocked from cart add/update quantity
- Blacklisted contacts are blocked from wishlist add operations
- Blacklisted users are blocked from submitting reviews
- Blacklisted users are blocked from placing checkout orders
- Blacklisted users are blocked from creating refund requests
- OAuth sign-in/signup completion blocks blacklisted contacts and re-registration attempts
- Account blacklist warning banner visibility is controlled by site setting
account_blacklist_notice_visible
Use this severity model when extending or reviewing features.
- Level 1 (baseline): input validation, output escaping, prepared statements
- Level 2 (sensitive forms/APIs): CSRF, rate limit, CAPTCHA, audit logging
- Level 3 (critical money/data paths): transaction boundaries, row locks, idempotency, explicit permission checks
- Put project in C:/xampp/htdocs/commerza
- Import backend/database/commerza.sql into database commerza
- Configure .env values
- Start Apache and MySQL from XAMPP
- Open http://localhost/commerza/
PHP lint examples:
- C:/xampp/php/php.exe -l backend/security/security_helpers.php
- C:/xampp/php/php.exe -l cart.php
- C:/xampp/php/php.exe -l admin/backend/api/commerce/orders_api.php
Automation examples:
- C:/xampp/php/php.exe C:/xampp/htdocs/commerza/backend/jobs/send_engagement_reminders.php 180
- C:/xampp/php/php.exe C:/xampp/htdocs/commerza/backend/jobs/monthly_profit_report.php
- C:/xampp/php/php.exe C:/xampp/htdocs/commerza/backend/jobs/weekly_analytics_report.php
Backup/restore verification:
- powershell -ExecutionPolicy Bypass -File scripts/maintenance/backup_restore_test.ps1 -MySqlBinPath "C:/xampp/mysql/bin"
- Verify clean-route canonical behavior
- Validate CAPTCHA flows in signup/login/reset/checkout (admin 2FA verification is code-only)
- Validate OAuth login for Google and Facebook
- Validate SMTP primary and fallback delivery
- Validate checkout, coupon, stock, and order status workflows
- Validate admin KPI cards and core operations tabs
- Validate sub-admin lifecycle (invite, verify, permission/hidden-tabs, suspend/reactivate, delete)
- Validate blacklist restrictions across cart/wishlist/review/refund/checkout/OAuth and account notice toggle behavior
- Run PHP lint on touched files
- SECURITY.md: security policy and disclosure channel
- llms.txt: LLM-safe discovery guidance
- instructions.md: integration requirements reference
- scripts/maintenance/BACKUP_RESTORE_TESTS.md: backup and restore runbook
- scripts/maintenance/backup_restore_test.ps1: automated backup/restore verification script
Environment guidance:
- Keep local secrets in
.envand never commit them. - Production should use server-managed secrets (not repo files).
- Set
COMMERZA_CAPTCHA_BYPASS_LOCAL=0for real validation tests. - Set
COMMERZA_OAUTH_STRICT_SSL=1on production HTTPS deployments.
Admin test keys used by security automation:
COMMERZA_ADMIN_TEST_2FA_CODE: only for scripted authenticated abuse tests.COMMERZA_ADMIN_TEST_SESSION_ID: only for scripted authenticated abuse tests.
These values do not auto-login your normal browser sessions. They are consumed by scripts/security/admin_e2e_abuse_tests.ps1 and CI jobs when present.
Workflow file: .github/workflows/security-gate.yml
- Static security gate runs on every push/PR/workflow dispatch.
- Dynamic probes run only when
SECURITY_BASE_URLsecret is configured. - Authenticated admin abuse checks require one of:
COMMERZA_ADMIN_TEST_SESSION_ID, orCOMMERZA_ADMIN_TEST_EMAIL+COMMERZA_ADMIN_TEST_PASSWORD+COMMERZA_ADMIN_TEST_2FA_CODE
Set and verify the following before go-live:
- Configure
COMMERZA_ADMIN_RESET_KEYto a strong non-default secret (minimum 16 chars). - Ensure production
.envvalues are managed outside source control. - Confirm HTTPS is enforced and secure cookies are active.
- Run syntax lint on all deployment-touched PHP files.
- Run security smoke tests (
scripts/security/security_smoke_tests.ps1). - Validate admin auth recovery flows with real reset key configuration.
- Verify robots/sitemap/llms files are aligned with production domain.
DigitalOcean launch profile for commerza.ahmershah.dev:
COMMERZA_APP_URL=https://commerza.ahmershah.devCOMMERZA_GOOGLE_REDIRECT_URI=https://commerza.ahmershah.dev/oauth.php?provider=googleCOMMERZA_FACEBOOK_REDIRECT_URI=https://commerza.ahmershah.dev/oauth.php?provider=facebookCOMMERZA_CAPTCHA_ENABLED=1,COMMERZA_CAPTCHA_REQUIRED=1,COMMERZA_CAPTCHA_PROVIDER=recaptcha- Configure both reCAPTCHA v2 and v3 keys for
commerza.ahmershah.dev - Use one DB transport mode:
- TCP:
COMMERZA_DB_HOST,COMMERZA_DB_PORT,COMMERZA_DB_USER,COMMERZA_DB_PASS,COMMERZA_DB_NAME - Socket:
COMMERZA_DB_SOCKET,COMMERZA_DB_USER,COMMERZA_DB_PASS,COMMERZA_DB_NAME
- TCP:
Runtime behavior note:
backend/core/data.phpnow supports optionalCOMMERZA_DB_PORTandCOMMERZA_DB_SOCKETfor both mysqli and PDO helper connections.
Security hardening note:
- Legacy predictable admin reset-key fallback is intentionally disabled.
- If no valid reset key is configured, admin reset-key-dependent flows will reject requests by design.
Commerza is distributed under the Commerza Attribution License in license.txt.
This is a permissive, MIT-like license with one additional requirement: clear author credit must be preserved.
Minimum credit requirements for redistribution or public deployment:
- Keep the copyright and license notice.
- Include author credit: Syed Ahmer Shah.
- Include project credit: Commerza.
- Include project link: https://github.com/ahmershahdev/commerza
- For websites/SaaS/products, show credit in at least one user-visible location (for example footer, about page, credits page, or documentation page).