DEV Community

Caleb Nkunze
Caleb Nkunze

Posted on • Originally published at blog.devgenius.io on

NodeJS Gateway — Part 4: Controllers Take the Stage!

NodeJS Gateway — Part 4: Controllers Take the Stage!


Photo by Isis França on Unsplash

In our previous posts, we’ve built a solid foundation for our payment gateway using JavaScript and NodeJS. We set up the gateway itself, established communication with MongoDB, and even created routes and middleware to handle requests. Now, it’s time to introduce the superstars of the show — controllers!

Imagine controllers as the conductors of our payment gateway orchestra. They receive instructions from the routes, interpret them, and delegate tasks to other parts of the system like models and services. In essence, they handle the business logic of our application, keeping the routes clean and focused on traffic management.

So, what can controllers do? Let’s take a look:

  • Process payment requests: When a user initiates a payment through the “collect” endpoint, the controller receives the request, validates the data, and calls the appropriate service to process the transaction. It could involve communicating with payment providers, updating databases, and sending confirmation messages.
  • Manage user accounts: Controllers handle user registration, login, and other account-related actions. They interact with the user model to store and retrieve data, ensuring secure authentication and authorization.
  • Orchestrate complex workflows: Payment gateways often involve intricate processes with multiple steps. Controllers act as the glue, coordinating the flow of data between different components and ensuring everything runs smoothly.
  • Handle errors gracefully: When something goes wrong, controllers catch the errors, log them appropriately, and provide informative responses to the users or APIs making the request.

Here’s an example of how a controller might handle the “collect” request:


export async function collect(data:any, res:any){
    // Validate type and amount from request body
    const { type, amount } = data;
    if (!type || !amount) {
        return res.status(400).json({
        error: "Missing required fields",
        });
    }

    // Process payment based on type
    try {
        if (type === "mobile_money") {
            // Call a controller or service that handles mobile money payments
            // Send confirmation message and status
            res.status(200).json({
                message: "Mobile Money Payment initiated successfully",
                status: "pending",
            });
        } else if (type === "card_payment") {
            // Call a controller or service that handles card payments
            // Send confirmation message and status
            res.status(200).json({
                message: "Card Payment initiated successfully",
                status: "pending",
            });
        } else {
            return res.status(400).json({
                error: "Invalid payment type",
            });
        }
    } catch (error) {
        // Handle and log errors
        console.error(error);
        res.status(500).json({
            error: "Internal server error",
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

As you can see, the controller takes care of the entire payment flow, from validation to service calls and response generation. When we run our previous collect route we get the response as shown below.


Response from collect route handled by the collect controller

Using controllers brings several benefits:

  • Improved code organization: Code is divided into clear, reusable modules, making it easier to understand, maintain, and test.
  • Reduced redundancy: Logic is centralized in controllers, preventing duplication across routes and other components.
  • Enhanced flexibility: New features and functionalities can be easily implemented by adding new controllers or modifying existing ones.

By leveraging the power of controllers, you can build a robust and scalable payment gateway that can handle complex transactions with ease. Stay tuned for the next part, where we’ll dive deeper into specific controller implementations and explore how they interact with other parts of the system!

Next we will look at services to further handle our controller functionalities, then we will also look at practices that we can use to make our code better including logging methods, migrations, setup and handling scripts among others. And in case if you want to view the code you can always check it below.

Until the next blog, happy coding.

GitHub - Cank256/payie: A payment solution project


AWS Q Developer image

Your AI Code Assistant

Implement features, document your code, or refactor your projects.
Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

Top comments (0)

👋 Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay