Skip to content

Tojan-Naiem/Advanced-Vending-Machine

Repository files navigation

🍦 Advanced Vending Machine System

A comprehensive ASP.NET Core Web API for managing an intelligent ice cream vending machine with state machine architecture, payment processing, and real-time tracking.

πŸ“‹ Table of Contents

✨ Features

  • State Machine Architecture: Manages vending machine states (Idle, Item Selection, Payment, Dispensing)
  • Payment Processing: Integrated with Stripe for secure payments
  • Product Management: Full CRUD operations for ice cream products
  • Transaction Tracking: Complete audit trail of all transactions
  • QR Code Scanning: Initiates purchase flow via QR scan
  • Email Notifications: Automated confirmation emails after purchase
  • Redis Caching: Optimized product data retrieval
  • JWT Authentication: Secure API access with role-based authorization
  • Image Upload: Product image management
  • State History: Complete log of all state transitions

πŸ›  Tech Stack

Backend

  • .NET 9.0
  • ASP.NET Core Web API
  • Entity Framework Core 9.0
  • SQL Server

Libraries & Frameworks

  • Mapster - Object mapping
  • Stripe.NET - Payment processing
  • StackExchange.Redis - Caching
  • ASP.NET Core Identity - Authentication & Authorization
  • JWT Bearer - Token-based authentication

Design Patterns

  • State Machine Pattern
  • Observer Pattern
  • Repository Pattern
  • Dependency Injection

πŸ— Project Architecture

Advanced-Vending-Machine/
β”œβ”€β”€ VendingMachine.PL/          # Presentation Layer (API Controllers)
β”œβ”€β”€ VendingMachine.BLL/         # Business Logic Layer
β”‚   β”œβ”€β”€ Service/                # Business services
β”‚   └── StateMachine/           # State machine implementation
└── VendingMachine.DAL/         # Data Access Layer
    β”œβ”€β”€ Data/                   # DbContext
    β”œβ”€β”€ Model/                  # Entity models
    β”œβ”€β”€ Repository/             # Data repositories
    β”œβ”€β”€ DTO/                    # Data Transfer Objects
    β”œβ”€β”€ Enums/                  # Enumerations
    └── Migrations/             # EF Core migrations

πŸ“¦ Prerequisites

πŸš€ Installation

1. Clone the Repository

git clone https://github.com/yourusername/advanced-vending-machine.git
cd advanced-vending-machine

2. Restore Dependencies

dotnet restore

3. Install Entity Framework Tools

dotnet tool install --global dotnet-ef

βš™οΈ Configuration

1. Create appsettings.json

Create appsettings.json in the VendingMachine.PL directory:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DefaultConnection": "Server=.;Database=VendingMachineDB;Trusted_Connection=True;TrustServerCertificate=True;",
    "Redis": "localhost:6379"
  },
  "Jwt": {
    "SecretKey": "YourSuperSecretKeyHereMustBeLongEnough123456789"
  },
  "Stripe": {
    "SecretKey": "sk_test_your_stripe_secret_key"
  },
  "SmtpSettings": {
    "Host": "smtp.gmail.com",
    "Port": 587,
    "EnableSsl": true,
    "Email": "your-email@gmail.com",
    "Password": "your-app-password"
  }
}

2. Configure Stripe

  1. Sign up at Stripe
  2. Get your API keys from the Dashboard
  3. Add your secret key to appsettings.json

3. Configure Email (Optional)

For Gmail:

  1. Enable 2-factor authentication
  2. Generate an app-specific password
  3. Add credentials to appsettings.json

4. Configure Redis (Optional)

If not using Redis, you can comment out the Redis configuration in Program.cs.

πŸ—„οΈ Database Setup

1. Update Connection String

Edit the connection string in appsettings.json to match your SQL Server instance:

"DefaultConnection": "Server=YOUR_SERVER;Database=VendingMachineDB;Trusted_Connection=True;TrustServerCertificate=True;"

2. Apply Migrations

cd VendingMachine.PL
dotnet ef database update

3. Seeded Data

The application automatically seeds:

Products:

  • Vanilla Ice Cream - $5.00
  • Chocolate Ice Cream - $5.50
  • Strawberry Ice Cream - $6.00
  • Mint Ice Cream - $5.75
  • Cookie Dough Ice Cream - $6.50

Users:

Email Password Role
Lama@gmail.com La@000 Admin
nemeh@gmail.com Ly@000 Admin
layal@gmail.com na@000 Customer

πŸƒ Running the Application

Development

cd VendingMachine.PL
dotnet run

The API will be available at:

  • HTTPS: https://localhost:7259
  • HTTP: http://localhost:5038

Production Build

dotnet publish -c Release -o ./publish

πŸ“š API Documentation

Base URL

https://localhost:7259/api/v1

Authentication

Login

POST /Accounts/Login
Content-Type: application/json

{
  "email": "Lama@gmail.com",
  "password": "La@000"
}

Response:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Confirm Email

GET /Accounts/ConfirmEmail?token={token}&userId={userId}

Products

Get All Products

GET /Products

Get Product by ID

GET /Products/{id}

Create Product (Admin Only)

POST /Products
Authorization: Bearer {token}
Content-Type: multipart/form-data

Name: Vanilla Ice Cream
Price: 5.0
Quantity: 50
MainImage: [file]

Update Product (Admin Only)

PATCH /Products/{id}
Authorization: Bearer {token}
Content-Type: multipart/form-data

Name: Updated Name
Price: 6.0
Quantity: 40
MainImage: [file]

Toggle Product Status (Admin Only)

PATCH /Products/{id}/toggle-status
Authorization: Bearer {token}

Delete Product (Admin Only)

DELETE /Products/{id}
Authorization: Bearer {token}

Transactions

Create Transaction

POST /Transactions
Authorization: Bearer {token}
Content-Type: application/json

{
  "productId": 1
}

Get Transaction

GET /Transactions/{id}
Authorization: Bearer {token}

Delete Transaction

DELETE /Transactions/{id}
Authorization: Bearer {token}

Checkout

Process Payment

POST /CheckOut/payment
Authorization: Bearer {token}
Content-Type: application/json

{
  "transactionId": 1
}

Response:

{
  "success": true,
  "message": "Payment session created successfully",
  "url": "https://checkout.stripe.com/...",
  "paymentId": "cs_test_..."
}

Payment Success (Webhook)

GET /CheckOut/success/{session_id}/{transactionId}

Payment Cancel (Webhook)

GET /CheckOut/cancel

QR Scan

Scan QR Code

POST /Scan/scan-qr
Content-Type: application/json

{
  "qrCode": "VEND-12345"
}

Vending Machine State

Trigger Event

POST /vending/trigger?evt=QR_Scanned

Available Events:

  • QR_Scanned
  • Item_Selected
  • Payment_Initiated
  • Payment_Confirmed
  • Payment_Failed
  • Dispense_Complete
  • Reset
  • Error_Occurred

Get Current State

GET /vending/state

Response:

{
  "state": "Idle"
}

Get State History

GET /vending/history

Response:

{
  "state": [
    {
      "id": 1,
      "stateBefore": "Idle",
      "stateAfter": "ItemSelection",
      "eventTriggered": "QR_Scanned",
      "timestamp": "2025-12-14T10:00:00"
    }
  ]
}

πŸ”„ State Machine Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    State Transitions                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Idle 
  └─[QR_Scanned]──> ItemSelection
                      └─[Item_Selected]──> PaymentPending
                                             └─[Payment_Initiated]──> PaymentProcessing
                                                                       β”œβ”€[Payment_Confirmed]──> ProductDispensing
                                                                       β”‚                          └─[Dispense_Complete]──> Idle
                                                                       └─[Payment_Failed]──> ItemSelection

[Error_Occurred] from any state ──> Error ──> Idle

States Description

State Description
Idle Machine waiting for customer interaction
ItemSelection Customer browsing and selecting products
PaymentPending Waiting for payment initiation
PaymentProcessing Processing payment through Stripe
ProductDispensing Dispensing the selected product
Error Error state for handling failures

πŸ§ͺ Testing

Using Postman/Thunder Client

  1. Import the API endpoints
  2. Login to get JWT token
  3. Add token to Authorization header
  4. Test endpoints

Example Test Flow

# 1. Login
POST /api/v1/Accounts/Login
{
  "email": "Lama@gmail.com",
  "password": "La@000"
}

# 2. Get Products
GET /api/v1/Products

# 3. Create Transaction
POST /api/v1/Transactions
{
  "productId": 1
}

# 4. Process Payment
POST /api/v1/CheckOut/payment
{
  "transactionId": 1
}

πŸ” Security

  • JWT Bearer token authentication
  • Role-based authorization (Admin/Customer)
  • Password hashing with ASP.NET Identity
  • Email confirmation required
  • Account lockout after failed login attempts
  • HTTPS enforcement
  • SQL injection protection via EF Core

πŸ“ Common Issues & Solutions

Issue: Database connection fails

Solution: Verify SQL Server is running and connection string is correct

Issue: Redis connection error

Solution: Comment out Redis configuration or install Redis locally

Issue: Email not sending

Solution: Check SMTP settings and ensure app password is used for Gmail

Issue: Stripe payment fails

Solution: Verify Stripe API key is correct and in test mode

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License.

πŸ™ Acknowledgments

  • Stripe for payment processing
  • Redis for caching solutions
  • Microsoft for .NET and Entity Framework
  • The open-source community

Built with ❀️ using .NET 9.0

About

A comprehensive ASP.NET Core Web API for managing an intelligent ice cream vending machine with state machine architecture, payment processing, and real-time tracking.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages