Skip to content

Latest commit

 

History

History
178 lines (137 loc) · 5.67 KB

File metadata and controls

178 lines (137 loc) · 5.67 KB

Fashion Marketplace Demo

Full-stack fashion marketplace demo: Laravel 13 REST API + Next.js 15 storefront with Stripe Checkout, FedEx sandbox shipping, printable labels, and an admin panel for orders, customers, and multi-currency settlement.

Architecture

flowchart LR
  subgraph client [Next.js 15]
    Store[Storefront]
    Admin[Admin UI]
  end

  subgraph api [Laravel API :8088]
    Orders[OrderService]
    PayGW[PaymentGateway]
    ShipGW[ShippingCarrier]
    Events[OrderPaid event]
  end

  subgraph external [External]
    StripeAPI[Stripe]
    FedExAPI[FedEx Sandbox]
  end

  Store -->|REST JSON| Orders
  Admin -->|Bearer token| Orders
  Orders --> PayGW
  Orders --> ShipGW
  PayGW -->|fulfillment| Events
  Events --> ShipGW
  PayGW --> StripeAPI
  ShipGW --> FedExAPI
Loading

See ARCHITECTURE.md for contracts, DTOs, and FedEx module layout.

Layer Stack URL
Frontend Next.js 15 (App Router) http://localhost:3001
API Laravel 13 REST http://localhost:8088/api
Database MySQL 8.4 localhost:3308
frontend/     Next.js storefront + admin
app/          Laravel API (services, controllers, models)
routes/api.php
docker-compose.yml
tests/        PHPUnit feature + unit tests

Quick start (Docker)

cp .env.example .env
# Optional: add Stripe + FedEx sandbox credentials
docker compose up --build

Open:

Admin credentials (demo only):

  • Email: admin@marketplace.demo
  • Password: password

Demo flow

  1. Browse designs → add to cart (single currency per checkout)
  2. Checkout → enter US ship-to address → Calculate FedEx shipping
  3. Pay with Stripe test card 4242 4242 4242 4242 (or demo mode without keys)
  4. Success page confirms payment; FedEx label generated when paid
  5. Admin → orders → view customer Stripe payload, settlement, print FedEx PDF label

FedEx integration

Uses the FedEx sandbox when credentials are set:

Step Endpoint
OAuth POST https://apis-sandbox.fedex.com/oauth/token
Rates POST /rate/v1/rates/quotes
Labels POST /ship/v1/shipments → official PDF (PAPER_4X6)

Responses include source and fallback_reason when zone-based demo rates are used instead of live API data.

Label sources stored on each shipment:

label_source Meaning
fedex_sandbox_pdf Official FedEx sandbox PDF
fedex_sandbox_pdf_retry PDF using FedEx test address after invalid ship-to
html_fallback Printable HTML when Ship API fails
html_no_credentials HTML when FedEx keys are absent

Environment variables

APP_DEMO_MODE=true          # Enables POST /orders/{order}/complete-demo locally

STRIPE_KEY=pk_test_...
STRIPE_SECRET=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...

FEDEX_CLIENT_ID=...
FEDEX_CLIENT_SECRET=...
FEDEX_ACCOUNT_NUMBER=...
FEDEX_BASE_URL=https://apis-sandbox.fedex.com
FEDEX_TOKEN_URL=https://apis-sandbox.fedex.com/oauth/token
FEDEX_ORIGIN_LINE1="350 5th Ave"
FEDEX_ORIGIN_CITY="New York"
FEDEX_ORIGIN_STATE=NY
FEDEX_ORIGIN_POSTAL_CODE=10001

ADMIN_EMAIL=admin@marketplace.demo
ADMIN_PASSWORD=password
ADMIN_TOKEN=demo-admin-token

Stripe webhooks (local):

stripe listen --forward-to localhost:8088/api/webhooks/stripe

Key API routes

Method Path Description
GET /api/products Catalog
POST /api/shipping/quote FedEx rates (sandbox or zone fallback)
POST /api/checkout Create order + Stripe session
POST /api/checkout/confirm Confirm paid Stripe session
GET /api/orders/{orderNumber} Order details (access token or signature required)
POST /api/orders/{order}/complete-demo Demo payment completion (APP_DEMO_MODE only)
POST /api/webhooks/stripe Stripe payment webhook (signature required when configured)
GET /api/labels/{id} FedEx label PDF/HTML (signed URL required)
POST /api/admin/login Admin bearer token
GET /api/admin/orders Orders list
POST /api/admin/orders/{id}/label?force=1 Generate/regenerate FedEx label

Security model (demo vs production)

Control Implementation
Order PII access_token or signed URL required
Label download Laravel signed URLs (30-day expiry)
Demo payment bypass Gated by APP_DEMO_MODE
Stripe webhooks Signature verification required when STRIPE_SECRET is set
Admin API Bearer token + rate limiting
Checkout Server-side shipping re-quote prevents price tampering

Known demo limitations

  • Admin auth uses a static bearer token (not Sanctum) — acceptable for local demo only.
  • Invalid international or malformed addresses may be retried with a FedEx sandbox test address (Seattle) to produce a valid PDF.
  • HTML label fallback exists when FedEx Ship API rejects a shipment.
  • Settlement FX rates are hardcoded in SettlementService (documented for demo).

Tests & CI

composer lint          # Laravel Pint (code style)
composer test          # Pest test suite
composer test:coverage # Pest + PCOV (fails below 70% app coverage)
cd frontend && npm run lint

GitHub Actions runs Pint, Pest with ≥70% PHP coverage, frontend typecheck, and production build on push/PR.

Settlement note

Paid orders store charge currency totals plus a converted settlement amount in SETTLEMENT_CURRENCY (default USD). The admin settlements screen highlights multi-currency payout inconsistencies — the core business problem this demo targets.