A modern, production-ready Smart Vending Machine architecture featuring a Next.js touchscreen interface, a Flask microservice backend, MySQL inventory management, and a Hardware Agent for Raspberry Pi GPIO control. Integrated with Omise for secure Credit Card and PromptPay (QR) payments.
The system is built on a distributed microservices architecture optimized for low-latency hardware interaction and secure payment processing.
graph TD
A[machine-ui - Next.js] -->|API Requests| B[server - Flask API]
B -->|SQL| C[(MySQL DB)]
B -->|HTTPS| D[Omise Gateway]
B -->|HTTP/GPIO| E[hardware-agent - Python]
E -->|Motor Control| F[Physical Vending Hardware]
machine-ui: A high-performance Next.js application designed for 10.1" touchscreens. Handles UI state, Omise tokenization, and real-time polling.server: The central brain. Manages business logic, inventory verification, secure charge execution via Omise, and hardware coordination. Also hosts Socket.IO for real-time job events.db: Persistent storage for products, pricing, machine layouts, and transaction logs.hardware-agent: A lightweight service running on Raspberry Pi to handle GPIO/NFC/LED + connect to server via Socket.IO.admin-ui: Next.js admin dashboard (inventory, machines, orders, alerts).
The entire stack is containerized for seamless deployment.
- Docker & Docker Compose
- Omise Test Keys (Sign up here)
Copy the template and fill in your Omise keys:
cp .env.example .envEdit .env and provide:
NEXT_PUBLIC_OMISE_PUBLIC_KEYOMISE_SECRET_KEY
Run the following command to build and start all services:
docker compose up --build- machine-ui: http://localhost:3000
- admin-ui: http://localhost:3001
- API backend + Socket.IO: http://localhost:8000
- Flasgger (server): http://localhost:8000/apidocs
- Swagger UI (mounted
swagger.yaml): http://localhost:8081 - Hardware agent: http://localhost:5000
Each service prints a startup banner (URLs + key env). If you need even more detail, run:
docker compose up --build --no-log-prefixStandardized configuration for the production-ready stack:
| Variable | Description | Context |
|---|---|---|
NEXT_PUBLIC_OMISE_PUBLIC_KEY |
Omise Public Key for client-side tokenization | Frontend |
OMISE_SECRET_KEY |
Omise Secret Key (KEEP PRIVATE) | Backend |
NEXT_PUBLIC_API_URL |
Backend API Endpoint | Frontend |
AGENT_URL |
URL of the hardware agent | Backend |
DB_HOST / DB_USER ... |
MySQL Database Connection | Backend |
CORS_ORIGINS |
Comma-separated allowed origins (override for LAN/hardware) | Backend |
SERVER_SOCKET_URL |
Socket.IO URL the agent connects to (override for LAN/hardware) | Hardware agent |
To test without physical cards or hardware:
- Auto-Tokenization: Use the "[Test] Simulate Visa Tap" button in the UI. This uses a hardcoded test card (4242...) to generate a real Omise test token.
- PromptPay (QR): Select PromptPay in the UI. A scannable QR code will be generated. You can simulate the payment status update using:
- Webhook: Configure an Omise webhook pointing to your
/api/buy/omise-webhook. - Manual Bypass: POST the
charge_idto/api/buy/mock-payto force a "PAID" status in development.
- Webhook: Configure an Omise webhook pointing to your
- Hardware Trigger: Check the
vending-picontainer logs. You will see[Dispense] Motor Triggeredmessages when the flow completes.
The backend uses Flasgger to provide interactive OpenAPI/Swagger documentation. Navigate to /apidocs on the server to explore the endpoints.
For a dedicated Swagger UI that renders swagger.yaml, open Swagger UI at http://localhost:8081.
Key Endpoints:
GET /api/health: Comprehensive system health check.GET /api/products: Fetch inventory and pricing.POST /api/buy/checkout: Execute a payment (Token or Source).GET /api/buy/status/<charge_id>: Poll for payment completion.
This project is licensed under the MIT License - see the LICENSE file for details.