Question | Answer |
---|---|
Time Spent for design and implementation | 2 hours, 47 minutes |
Technologies | Java17, Spring Boot, PostgreSQL, Hibernate |
Features | 1. Store Card. 2. Retrieve Cards information by merchant and userId 3. Process payment. 4. Retrieve payments using user and merchant 5. Pull latest payment status updates |
Run | Docker, Docker Compose, or manual DB creation with app running. |
Mock Bank | Bank is mocked through another API running locally. |
Main Missing Components | 1. Authorization and Authentication roles 2. Data Encryption of Card information.3. Request Validatoin 4. Unit and Integration tests. 5. Async communication to allow bank updates coming from the banks. 6. Delete/Update endpoint to update/delete cards. 7. Error handling of different cases in the endpoints. 8. Generate a unique API key for each merchant. 7. Use UUIDs instead of sequential IDs to prevent malicious reverse engineering |
This is the design I would implement in real life to make sure that the updated payment status is accessible from the merchant easily.
For the sake of simplicity, There is no queue integration in the current implementation. However, there is a simple mocked response that is being sent through a mockBank API which is requested through a Callable
This is a payment gateway that helps to collect money for merchants, store cards information, and keep track of payments history.
- Store card information.
- Retrieve card information.
- Process a payment through the gateway.
- Retrieve payments.
- Just run
docker-compose up
, and it will spin up the app service and the postgres service. - The service will be running on
http://localhost:8080/
- Create the database:
sudo docker run --name payments -p 5432:5432 -e POSTGRES_USER=test -e POSTGRES_PASSWORD=test -d postgres
Output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
32e7a0f07ba8 postgres "docker-entrypoint.s…" 6 minutes ago Up 6 minutes 0.0.0.0:5432->5432/tcp payments
- Run the service through running
PaymentGatewayApplication
- Get the stored cards for a specific user in a specific merchant:
GET http://localhost:8080/api/card/merchant/{merchantId}/user/{userId}
Return:
[
{
"cardId":652,
"userId":"123",
"merchantId":"1234",
"displayCardNumber":"**** **** **** 8765",
"createdAt":1675531493858,
"updatedAt":1675531493859
}
]
- Add a card for a specific user in a specific merchant:
POST http://localhost:8080/api/card/merchant/{merchantId}/user/{userId}
Request Body:
{
"cardNumber": "1234 5678 4321 8765",
"displayName": "Addy",
"expMonth": 1,
"expYear": 25,
"cvv": 123
}
Return:
{
"cardId": 702,
"userId": "123",
"merchantId": "1234",
"displayCardNumber": "**** **** **** 8765",
"createdAt": 1675540931248,
"updatedAt": 1675540931248
}
- Get the payment history for a specific user in a specific merchant:
GET http://localhost:8080/api/payment/merchant/{merchantId}/user/{userId}
Return:
[
{
"paymentId":652,
"cardId":503,
"merchantId":"1234",
"userId":"123",
"paymentStatus":"PROCESSING",
"createdAt":1675534050928,
"updatedAt":1675534055027
},
{
"paymentId":752,
"cardId":652,
"merchantId":"1234",
"userId":"123",
"paymentStatus":"SUCCESSFUL",
"createdAt":1675538891083,
"updatedAt":1675538905975
}
]
- Make a payment for a specific user in a specific merchant using a specific payment card:
POST http://localhost:8080/api/payment/merchant/{merchantId}/user/{userId}
Request Body:
{
"cardId": 652,
"amount": 550.89,
"currency": "USD"
}
Return:
{
"paymentId": 802,
"cardId": 652,
"merchantId": "1234",
"userId": "123",
"paymentStatus": "PROCESSING",
"createdAt": 1675541283655,
"updatedAt": 1675541283655
}
- Get the payment status
GET http://localhost:8080/api/payment/merchant/{merchantId}/user/{userId}/payment/{paymentId}
Return:
{
"paymentId":752,
"cardId":652,
"merchantId":"1234",
"userId":"123",
"paymentStatus":"SUCCESSFUL",
"createdAt":1675538891083,
"updatedAt":1675538905975
}
The mock bank API has two endpoints.
- Process a payment
POST http://localhost:8080/mockBank/processPayment
- Get updated payment status
GET http://localhost:8080/mockBank/paymentStatus/merchant/{merchantId}/user/{userId}/payment/{paymentId}
View Sequence Diagram on LucidChart