GoOn Backend is a fully functional backend system for an Uber-like ride-hailing system. It handles the complete ride lifecycle β from rider requesting a ride to driver accepting, starting, completing, and rating β backed by real geospatial queries, JWT-based authentication, strategy-pattern business logic, and a wallet payment system.
The project is designed following clean architecture principles: thin controllers, interface-driven service layer, repository abstraction, and separate strategy classes for pluggable business rules.
- JWT Access Token (24h expiry) + Refresh Token (6 months, stored in HttpOnly Cookie)
- Role-based access control β
ROLE_ADMIN,ROLE_DRIVER,ROLE_RIDER - Spring Security filter chain with a custom
JwtAuthFilter - Secure password hashing via Spring Security's
PasswordEncoder - Token refresh endpoint reads refresh token from cookie (never exposed in response body)
- Driver locations stored as
Geometry(Point, 4326)using Hibernate Spatial - Two native SQL strategies using PostGIS functions:
- Nearest Driver β
ST_DWithin(10 km radius) +ST_DistanceORDER BY - Top-Rated Driver β
ST_DWithin(15 km radius) + ORDER BYrating DESC
- Nearest Driver β
- Distance calculation via OSRM (Open Source Routing Machine) API for real road distances
RideFareCalculationStrategyinterface with two implementations:- Default Fare β base rate Γ road distance
- Surge Pricing β base rate Γ road distance Γ 2x surge multiplier
RideStrategyManagerselects the correct strategy at runtime based on demand
PaymentStrategyinterface with two implementations:- Cash Payment β marks payment confirmed, adds fare to driver wallet
- Wallet Payment β debits rider wallet, credits driver wallet, logs transactions
PaymentStrategyManagerresolves strategy fromPaymentMethodenum at runtime
- Full state machine:
PENDING β CONFIRMED β ONGOING β ENDED / CANCELLED - OTP-verified ride start (driver submits OTP, rider receives it on booking)
- Atomic
@Transactionaloperations across ride, payment, and driver availability - Paginated ride history for both rider and driver (sorted by
createdTime DESC)
- Rider rates driver; driver rates rider β both stored per ride
- Average rating auto-computed and persisted on
DriverandRiderentities
- Each user has a
Walletwith balance tracking WalletTransactionrecords every debit/credit withTransactionTypeandTransactionMethod- Wallet created automatically on user signup
- Spring Mail (SMTP/Gmail) integration via
EmailSenderService - Sends transactional emails (ride confirmations, onboarding, etc.)
GlobalResponseHandlerwraps every successful response inApiResponse<T>GlobalExceptionHandlermaps exceptions to structuredApiErrorresponses:ResourceNotFoundExceptionβ 404RunTimeConflictExceptionβ 409JwtExceptionβ 401AccessDeniedExceptionβ 403MethodArgumentNotValidExceptionβ 400 with field-level sub-errors
- Swagger / OpenAPI UI auto-generated at
/swagger-ui/index.html
| Layer | Technology |
|---|---|
| Language | PHP |
| Framework | Symfony 8.4 |
| Security | Symfony Security + JJWT 0.12.6 |
| ORM | Symfony + Hibernate 6 |
| Geospatial | Hibernate Spatial + PostGIS |
| Database | MySQL |
| Distance API | OSRM (Open Source Routing Machine) |
| Mapping | ModelMapper 3.2.0 |
| API Docs | SpringDoc OpenAPI (Swagger UI) 2.6.0 |
| Monitoring | () |
| Symfony mail (Gmail SMTP) | |
| Build | build tool |
| Utilities | () |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Client / Postman β
ββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β HTTP
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββ
β JwtAuthFilter (Security Layer) β
β Validates JWT β sets SecurityContext β
ββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββ
β REST Controllers (3) β
β AuthController / DriverController β
β RiderController β
ββββββββββββ¬βββββββββββββββββββββββββββ¬ββββββββββββββββ
β β
ββββββββββββΌβββββββββββ ββββββββββββββΌβββββββββββββββ
β Service Layer β β Strategy Layer β
β AuthService β β DriverMatchingStrategy β
β RideService β β RideFareCalculationStrat. β
β DriverService β β PaymentStrategy β
β RiderService β β (Strategy Pattern) β
β PaymentService β ββββββββββββββββββββββββββββββ
β WalletService β
β RatingService β
β EmailService β
β DistanceService β
ββββββββββββ¬βββββββββββ
β
ββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββ
β Repository Layer (JPA) β
β DriverRepo / RiderRepo / RideRepo / UserRepo β
β WalletRepo / PaymentRepo / RatingRepo β
ββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
β
ββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββ
β MySQL Database + Redis β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
uberApp-Backend/
βββ src/main/java/com/appdefine/uber/uberApp/
β βββ advices/
β β βββ ApiError.java # Error response model
β β βββ ApiResponse.java # Unified response wrapper
β β βββ GlobalExceptionHandler.java # @RestControllerAdvice
β β βββ GlobalResponseHandler.java # Auto-wraps all responses
β β
β βββ configs/
β β βββ MapperConfig.java # ModelMapper bean
β β βββ SecurityConfig.java # JWT filter, CORS, CSRF
β β βββ WebSecurityConfig.java # HTTP security rules
β β
β βββ controllers/
β β βββ AuthController.java # /auth/*
β β βββ DriverController.java # /drivers/* (ROLE_DRIVER)
β β βββ RiderController.java # /riders/* (ROLE_RIDER)
β β
β βββ dto/ # Request/Response DTOs
β βββ entities/ # JPA Entities
β β βββ enums/ # RideStatus, PaymentMethod, Role ...
β β βββ Driver.java
β β βββ Ride.java # Geometry(Point,4326) fields
β β βββ RideRequest.java
β β βββ Rider.java
β β βββ User.java
β β βββ Wallet.java
β β βββ WalletTransaction.java
β β βββ Payment.java
β β βββ Rating.java
β β
β βββ exceptions/
β β βββ ResourceNotFoundException.java
β β βββ RunTimeConflictException.java
β β
β βββ repositories/ # Symfony Data JPA Repositories
β β βββ DriverRepository.java # Native PostGIS spatial queries
β β
β βββ security/
β β βββ JWTService.java # Token generation & validation
β β βββ JwtAuthFilter.java # OncePerRequestFilter
β β
β βββ services/ # Service interfaces
β β βββ impl/ # Service implementations
β β βββ DistanceServiceOSRMImpl.java # OSRM road distance API
β β βββ DriverServiceImpl.java
β β βββ RiderServiceImpl.java
β β βββ RideServiceImpl.java
β β βββ PaymentServiceImpl.java
β β βββ WalletServiceImpl.java
β β βββ RatingServiceImpl.java
β β βββ EmailSenderServiceImpl.java
β β
β βββ strategies/ # Strategy pattern interfaces
β β βββ impl/
β β βββ DriverMatchingNearestDriverStrategy.java
β β βββ DriverMatchingHighestRatedDriverStrategy.java
β β βββ RideFareDefaultFareCalculationStrategy.java
β β βββ RideFareSurgePricingFareCalculationStrategy.java
β β βββ CashPaymentStrategy.java
β β βββ WalletPaymentStrategy.java
β β
β βββ utils/
β βββ GeometryUtil.java # WKT β Point conversion helpers
β
βββ src/main/resources/
β βββ application.properties
β βββ data.sql # Seed data
β
βββ uberApp.postman_collection.json # Ready-to-import Postman collection
βββ pom.xml
All protected endpoints require
Authorization: Bearer <access_token>header.
| Method | Endpoint | Role | Description |
|---|---|---|---|
POST |
/Oauth/signup |
Public | Register a new user |
POST |
/Oauth/login |
Public | Login, returns access token; sets refresh token as HttpOnly cookie |
GET |
/Oauth/refresh-token |
Public | Issue new access token using refresh token cookie |
POST |
/Oauth/onBoardNewDriver/{userId} |
ADMIN |
Promote user to driver with vehicle ID |
| Method | Endpoint | Description |
|---|---|---|
POST |
/drivers/acceptRide/{rideRequestId} |
Accept a pending ride request |
POST |
/drivers/startRide/{rideRequestId} |
Start ride after OTP verification |
POST |
/drivers/endRide/{rideId} |
Complete the ride, trigger payment |
POST |
/drivers/cancelRide/{rideId} |
Cancel a confirmed ride |
POST |
/drivers/rateRider |
Rate the rider after ride completion |
GET |
/drivers/getMyProfile |
Get authenticated driver's profile |
GET |
/drivers/getMyRides?pageOffset=0&pageSize=10 |
Paginated ride history |
| Method | Endpoint | Description |
|---|---|---|
POST |
/riders/requestRide |
Request a new ride with pickup & drop-off location |
POST |
/riders/cancelRide/{rideId} |
Cancel a ride |
POST |
/riders/rateDriver |
Rate the driver after ride |
GET |
/riders/getMyProfile |
Get authenticated rider's profile |
GET |
/riders/getMyRides?pageOffset=0&pageSize=10 |
Paginated ride history |
- PHP 8+
- MySQL 14+ with Redis extension enabled
git clone https://github.com/j-deku/goon-backend-php.git
cd goon-Backend-phpCREATE DATABASE GoOn;
\c goon-backend-php
CREATE EXTENSION postgis;# Database
# JWT
jwt.secretKey=your_strong_secret_key_min_32_chars
# SMTP (Gmail example)
symfony.mail.host=smtp.gmail.com
symfony.mail.port=587
symfony.mail.username=your_email@gmail.com
symfony.mail.password=your_app_password
symfony.mail.properties.mail.smtp.auth=true
symfony.mail.properties.mail.smtp.starttls.enable=true# Build
symfony doctrine:validate
# Run
symfony server:startThe server starts at http://localhost:8080
| Tool | URL |
|---|---|
| Swagger UI | http://localhost:8080/swagger-ui/index.html |
| Actuator Health | http://localhost:8080/actuator/health |
| Postman Collection | Import goOn.postman_collection.json |
POST /Oauth/signup β Create account
POST /Oauth/login β Get access token (+ refresh token in HttpOnly cookie)
Add header: Authorization: Bearer <access_token>
GET /Oauth/refresh β Renew access token using cookie (no body needed)
| Pattern | Where Applied |
|---|---|
| Strategy | Driver matching (Nearest / Highest Rated) |
| Strategy | Fare calculation (Default / Surge Pricing) |
| Strategy | Payment processing (Cash / Wallet) |
| Factory / Manager | RideStrategyManager, PaymentStrategyManager resolve strategies at runtime |
| Repository | Symfony Data with custom native MySQL queries |
| DTO | All controller I/O uses DTOs, never entities directly |
| Global Advice | @RestControllerAdvice for centralized error handling and response wrapping |
./mvnw testA Postman collection with pre-configured requests for all endpoints is included:
GoOn.postman_collection.json
Import it into Postman and set the base_url variable to http://localhost:8080.
- Passwords never stored in plain text β BCrypt hashing via Spring Security
- JWT signed with HMAC-SHA256; validated on every request via
JwtAuthFilter - Refresh token stored in HttpOnly cookie β inaccessible to JavaScript (XSS protection)
- Role-based endpoint guards using
@Securedannotations - Input validation with
@Valid+ field-level error messages in response
Driver locations use the WGS-84 coordinate system (SRID 4326). Example native query:
-- Find 10 nearest available drivers within 10 km
SELECT d.*, ST_Distance(d.current_location, :pickUpLocation) AS distance
FROM driver d
WHERE d.available = true
AND ST_DWithin(d.current_location, :pickUpLocation, 10000)
ORDER BY distance
LIMIT 10;symfony server:start
symfony doctrine:migration
symfony doctrine:validation
modelmapper:3.2.0
sql (runtime)- Google Maps / HERE Maps integration for live routing
- WebSocket β real-time ride status updates
- OTP delivery via SMS (Twilio)
- Push notifications (Firebase FCM)
- Admin dashboard APIs
- Ride fare estimation before booking
- Docker + Docker Compose setup
- CI/CD pipeline (GitHub Actions)
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature - Commit your changes:
git commit -m "feat: add your feature" - Push:
git push origin feature/your-feature - Open a Pull Request
Made with β€οΈ using ExpressJs Β· Symfony 8.4 Β· Redis Β· Messenger