The Payment Gateway project simulates a payment processing system that allows merchants to process payments and retrieve payment details. This solution includes a payment gateway service, a mock bank simulator, and integrated Swagger documentation for API exploration.
The Payment Gateway project simulates a payment processing system that allows merchants to process payments and retrieve payment details. This solution includes a payment gateway service and a mock bank simulator.
payment_gateway/
├── README.md
├── main.go
├── bank_simulator/
│ ├── bank_simulator.go
├── config/
│ ├── config.yaml
├── controllers/
│ └── payment_controller.go
├── middleware/
│ └── validation.go
├── models/
│ └── payment.go
├── repository/
│ └── payment_repository.go
├── router/
│ └── router.go
├── services/
│ ├── payment_service.go
│ └── payment_service_test.go
├── utils/
│ ├── logger.go
│ └── uuid_generator.go
├── .env
├── config.yaml
├── go.mod
├── go.sum
└── payments.db
main.go
: Entry point for the application. Initializes the database, service, and router, and starts the server.bank_simulator/
: Directory containing files related to the bank simulator.
bank_simulator.go
: Simulates the acquiring bank, mocking payment processing responses.config/config.yaml
: Configuration file for the application settings.controllers/payment_controller.go
: Handles HTTP requests for processing and retrieving payments.middleware/validation.go
: Middleware for validating payment requests.models/payment.go
: Defines data models for payments and payment requests.repository/payment_repository.go
: Interfaces and implementation for payment data storage and retrieval.router/router.go
: Sets up the HTTP routes and handlers.services/payment_service.go
: Contains business logic for processing payments and interacting with the bank simulator.services/payment_service_test.go
: Contains test cases for the payment service.utils/logger.go
: Configures and provides a logger using Uber's Zap.utils/uuid_generator.go
: Utility for generating UUIDs based on card number and amount..env
: Environment variable configuration file.config.yaml
: Configuration settings for the application.Processing Payments:
/process_payment
with payment details.Retrieving Payments:
/retrieve_payment/:id
with the payment ID./simulate_bank
that mimics the behavior of an acquiring bank.Clone the Repository:
git clone https://github.com/leyantong/payment_gateway.git
cd payment_gateway
Install Dependencies:
go mod tidy
Create .env
File:
Create a .env
file in the root directory with the following content:
BANK_SIMULATOR_URL=http://localhost:8081/simulate_bank
PORT=:8080
Run the Bank Simulator:
Navigate to the bank_simulator/
directory and start the simulator:
go run bank_simulator.go
Run the Payment Gateway:
go run main.go
Access Swagger UI: Open a browser and go to:
http://localhost:8080/swagger/index.html
Run Tests:
go test ./...
cURL is a command-line tool for transferring data using various network protocols. It is commonly used for making HTTP requests, which can be useful for testing and interacting with APIs. Below is a guide on how to use cURL to send requests to the payment gateway and retrieve data.
To process a payment, you need to send a POST request with the payment details to the /process_payment
endpoint.
Example cURL Command:
curl -X POST http://localhost:8080/process_payment \
-H "Content-Type: application/json" \
-d '{
"card_number": "4242424242424242",
"expiry_month": "12",
"expiry_year": "2024",
"cvv": "123",
"amount": 11,
"currency": "SD"
}'
Explanation:
-X POST
: Specifies the request method as POST.http://localhost:8080/process_payment
: The URL of the payment processing endpoint.-H "Content-Type: application/json"
: Sets the Content-Type
header to application/json
, indicating that the request body contains JSON data.-d '{...}'
: The -d
flag sends the specified data in the request body. The data is in JSON format and includes the payment details.To retrieve the details of a specific payment, you need to send a GET request to the /retrieve_payment/:id
endpoint, where :id
is the unique identifier of the payment.
Example cURL Command:
curl -X GET http://localhost:8080/retrieve_payment/your-payment-id
Explanation:
-X GET
: Specifies the request method as GET.http://localhost:8080/retrieve_payment/your-payment-id
: The URL of the payment retrieval endpoint, with your-payment-id
replaced by the actual payment ID.Processing a Payment:
curl -X POST http://localhost:8080/process_payment \ -H "Content-Type: application/json" -d '{ "card_number": "4242424242424242", "expiry_month": "12", "expiry_year": "2024", "cvv": "123", "amount": 11, "currency": "SD" }'
**Expected Response:**
```json
{
"Status": "APPROVED",
"PaymentID": "80f8ec93-6ff8-5dcc-9e83-1c438a658d86"
}
Retrieving Payment Details:
curl -X GET http://localhost:8080/retrieve_payment/80f8ec93-6ff8-5dcc-9e83-1c438a658d86
Expected Response:
{
"ID": "80f8ec93-6ff8-5dcc-9e83-1c438a658d86",
"CardNumber": "4242",
"ExpiryMonth": "12",
"ExpiryYear": "2024",
"Amount": 100.00,
"Currency": "USD",
"Status": "APPROVED"
}
The model represents the data layer of the application. It defines the structure of the data and the relationships between different data elements. In this application, the models
package contains the Payment
struct, which represents a payment entity.
In the context of a web API, the view is represented by the responses sent back to the client. The Gin framework handles the serialization of responses to JSON format. The controllers
package contains functions that handle the HTTP requests and send appropriate responses.
The controller acts as an intermediary between the model and the view. It handles incoming HTTP requests, processes them (e.g., by interacting with the database or calling external services), and sends back the HTTP responses. In this application, the controllers
package contains the logic for processing payments and retrieving payment information.
Gin is a high-performance HTTP web framework written in Go. It was chosen for the following reasons:
To prevent duplicate payments, a cache mechanism is used. The cache stores recent payment requests and checks for duplicates before processing a new payment. The cache is implemented as a map where the key is a combination of payment details (card number, expiry date, amount, etc.) and the value is the timestamp of the payment request.
Locks are used to ensure thread safety when accessing shared resources like the cache. In this application, a sync.Mutex
is used to protect the cache from concurrent access issues. The mutex is locked before accessing the cache and unlocked after the access is complete. This ensures that only one goroutine can access the cache at a time, preventing race conditions and ensuring data integrity.
.env
file is used to configure necessary environment variables. The application assumes this file is properly set up.Database: Switch to a more scalable database solution like PostgreSQL or MySQL for production use to handle larger datasets and provide better performance and reliability.
Error Handling: Improve error handling to provide more detailed and user-friendly error messages. This includes catching and logging errors effectively, and returning clear, actionable messages to the end users.
Configuration Management: Use a more advanced configuration management tool to handle environment-specific settings. Tools like Viper or Consul can provide more flexibility and manage configurations for different deployment environments.
Security: Implement additional security measures such as:
Logging: Enhance logging to capture more detailed information and use centralized logging solutions for better monitoring and analysis. Tools like ELK stack (Elasticsearch, Logstash, Kibana) or Splunk can be used for this purpose.
CI/CD Pipeline: Implement a continuous integration and continuous deployment pipeline using tools like GitHub Actions or Jenkins to automate testing and deployment. This ensures that the code is always in a deployable state and reduces the risk of introducing errors in production.
End-to-End Testing for Load Testing: Implement end-to-end tests that simulate real-world usage and perform load testing to ensure the system can handle high traffic and large volumes of transactions.
Swagger API Documentation: Add Swagger for interactive API documentation. This will make it easier for developers to explore and test the API endpoints directly from the documentation.
Code Duplication: Ensure that there's no duplicated code across services and controllers to improve maintainability. Refactor common logic into reusable functions or services.
Hardcoded Values: Move all hardcoded values to configuration files to enhance flexibility and adaptability to different environments. This makes it easier to manage environment-specific settings without changing the codebase.
Testing: Expand the test coverage to include more edge cases and integrate with a CI tool for automated testing. Consider adding end-to-end tests and load testing to ensure the system can handle high traffic and perform reliably under stress.
Documentation: Enhance the documentation to include more detailed explanations of the codebase, especially for new developers. Ensure that API endpoints are well-documented, and consider adding Swagger for interactive API documentation in the future.
Scalability: Evaluate the system's scalability and refactor the code where necessary to handle a larger volume of transactions. This may include optimizing database queries, improving caching mechanisms, and using load balancers to distribute traffic evenly across servers.
Monitoring and Metrics: Integrate monitoring and metrics collection to track system performance and identify bottlenecks. Tools like Prometheus and Grafana can be used to monitor application health, track key performance indicators, and set up alerts for potential issues.