DEV Community

Cover image for How We Won the Medusa Hackathon: Building the Paystack Plugin
Femi Akinyemi for Medusa

Posted on • Originally published at


How We Won the Medusa Hackathon: Building the Paystack Plugin

This article was written by Femi Akinyemi and Andrew Glago.

Medusa is an open-source composable commerce engine built with Node.js. Medusa enables developers to build scalable and sophisticated commerce setups with low effort and great developer experience.

Paystack allows African businesses to accept payments in local and foreign currencies from multiple local and global payment channels.

As our submission for the Medusa Hackathon, we built Medusa-Payment-Paystack, a plugin that adds Paystack as a payment provider to Medusa ecommerce stores.

With our plugin, African business owners can create ecommerce stores on Medusa and accept payments in local currencies tailored to the 236 million (2022) and counting ecommerce users in Africa.

Experience Working on the Hackathon

Working on the Medusa hackathon was a great experience for both of us. We met on the Medusa Discord server and decided to work together on a submission for the hackathon.

We were both familiar with Paystack, being that they operated in both our countries (Ghana & Nigeria), and decided it would be useful to build a payment plugin integrated with Paystack to enable Medusa store purchases in our local currencies.

We decided on our high-level goals; feature parity with the existing Stripe payment plugin, high code coverage, and a really good developer experience. We then broke those down into measurable tasks we split among each other and worked on in short sprints.

We met regularly to catch up on progress and unblock each other where necessary. We had a great time working together and learned a lot from each other.

Experience developing with Medusa

Our development process began by identifying and getting familiar with the Medusa user flows our payment plugin would be integrated into. These turned out to be the checkout flow and the admin order management system.

Users should be able to pay for items in Medusa stores and store owners should be able to view order payments and issue refunds. Our plugin would take care of everything.

We went to work getting familiar with the APIs Medusa provides developers that would allow our plugin to perform the aforementioned tasks.

The Medusa docs were a godsend for us as first-time users of the platform. There were docs for practically everything we needed and we found the dependency injection mechanism that allowed core Medusa services like the Cart service (we use this in verifying payment amount values) to be used in plugins particularly useful.

After figuring out what needed to be done on Medusa’s end of things we integrated Paystack using the paystack-api package, a Node.js wrapper for the Paystack API, calling the relevant Paystack API endpoints as appropriate.

What are the plugin's features?

When you install and choose Paystack as your payment provider for your Medusa ecommerce store, you are guaranteed the following features:

Connect Medusa to Paystack

Using Medusa-Payment-Paystack, you can effortlessly integrate Paystack with Medusa, add Paystack as a payment provider in a region, and include Paystack in your checkout flow using the provider_id of Paystack. Payments to your Paystack business made from your Medusa store show up on your admin panel automatically. Refunds too.

Verify purchases

In the payment completion callback of your chosen flow, you can call the Medusa Complete Cart method. When you use the reference provided by Medusa-Payment-Paystack, The transaction status is checked, verifies the amount matches the cart total, and marks the cart paid for within Medusa.

Issue refunds

The admin dashboard allows you to refund captured payments made with Paystack.

A refund will occur using Medusa-Payment-Paystack, which marks the order in Medusa as refunded using Paystack.

In addition, all Paystack's checkout flows (popups, redirects, APIs) are made available by the plugin.

How to use the plugin

Adding support for Paystack payments to your Medusa store using the Medusa-Payment-Paystack plugin involves three main steps:

  1. Adding Paystack as a payment provider in your Medusa server
    • This involves installing the plugin from NPM using the command npm install medusa-payment-paystack
    • Adding the plugin to your list of plugins in medusa.config.js
  2. Adding Paystack to the region
    • In the Medusa admin dashboard, choose the regions you want to enable Paystack in and select the Paystack option in Payment Providers.
  3. Integrating into the checkout flow
    • Use the reference the plugin injects into your Payment Session data when initializing the payment with Paystack.
    • Call Medusa’s complete cart method after the user successfully completes payment. The plugin will take it from there, handling reporting the order as paid for in Medusa, verifying amounts, and processing refunds if necessary.

We made a video walking you through these steps you can refer to:


For more detailed steps on setting up the Paystack plugin, you can visit the project’s README for detailed steps.

If you’d also like to dive directly into code, check out medusa-paystack-demo - a demo Medusa store with Paystack configured as a payment provider using medusa-payment-paystack.

Should you have any issues or questions related to Medusa, then feel free to reach out to the Medusa team via Discord.

Top comments (2)

nicklasgellner profile image
Nicklas Gellner

Such as useful plugin and very much sought after in the community

shahednasser profile image
Shahed Nasser

Congrats on winning! 🙌🏻

11 Tips That Make You a Better Typescript Programmer


1 Think in {Set}

Type is an everyday concept to programmers, but it’s surprisingly difficult to define it succinctly. I find it helpful to use Set as a conceptual model instead.

#2 Understand declared type and narrowed type

One extremely powerful typescript feature is automatic type narrowing based on control flow. This means a variable has two types associated with it at any specific point of code location: a declaration type and a narrowed type.

#3 Use discriminated union instead of optional fields


Read the whole post now!