@enomshop/paystack
v1.38.0
Published
A starter for Medusa plugins.
Maintainers
Readme
Medusa Paystack Payment Plugin (v2)
A powerful, multi-currency Paystack payment integration designed specifically for Medusa v2. This plugin supports standard checkouts, partial installments, STK push for Mobile Money, and a comprehensive admin widget for manual payments.
Features
- Multi-Account Support: Manage multiple Paystack accounts natively using Medusa's provider identifiers (e.g.,
paystack_kenya,paystack_nigeria) mapped directly to separate webhooks. - Multi-Currency & Subunit Parsing: Gracefully translates precise amounts. Safely converts KES (e.g.
40000.00→4000000) and bypasses conversion for zero-decimal currencies like XOF and UGX. - Partial Payments & Installments: Allows customers to pay orders off dynamically using installments via storefront API endpoints.
- Admin Manual Payments: Beautiful admin UI injected into the Order details page to record out-of-band partial or full payments (cash/bank transfer).
- Admin STK Push: Send direct mobile money payment prompts (M-Pesa) to customers from the Admin Dashboard for remaining order balances.
- Auto-Capture: Fully Paid orders and installments are captured instantly.
- Failsafe Cron Job: Automatically syncs pending payment statuses every 30 minutes in case of network failures.
Prerequisites
- Medusa v2 Backend installed.
- Paystack Account with a Secret Key.
Installation
- Install the package inside your Medusa project (using npm or yarn).
npm install medusa-payment-paystack-v2
# or
yarn add medusa-payment-paystack-v2- Make sure you install the required peer dependency if not present:
npm install axiosConfiguration & Implementation
- Configure the Plugin
Update your
medusa-config.jsto register the plugin in yourpaymentmodule. You can register multiple providers for different accounts by assigning them uniqueids.
Important Note on Provider IDs in Medusa V2: Medusa dynamically creates the final provider ID by concatenating your config id with the plugin's internal identifier (paystack). So if you use id: "apple_4all", the final provider ID will be apple_4all_paystack.
module.exports = defineConfig({
// ...
modules: [
{
resolve: "@medusajs/payment",
options: {
providers: [
{
resolve: "@enomshop/paystack",
id: "apple_4all", // Resulting ID: apple_4all_paystack
options: {
secret_key: process.env.PAYSTACK_SECRET_KEY_KE,
}
},
{
resolve: "@enomshop/paystack",
id: "urbandevicecare", // Resulting ID: urbandevicecare_paystack
options: {
secret_key: process.env.PAYSTACK_SECRET_KEY_NG,
}
}
],
},
},
]
})- Webhooks Setup In your Paystack dashboard, set your webhook URL for each region appropriately. Medusa natively routes webhooks based on the provider ID:
- For Kenya:
https://your-domain.com/hooks/payment/paystack_kenya - For Nigeria:
https://your-domain.com/hooks/payment/paystack_nigeria
- Storefront Dynamic Provider Routing (Multi-Website) If you are running multiple storefronts connected to the same Medusa backend (e.g. Website A and Website B) in the same Region, you can force each website to exclusively use its own Paystack account without code changes!
Note: Medusa automatically prefixes all custom payment provider IDs with pp_ when exposing them via the API. Your storefront must match this prefix. Also remember that the base ID is {config_id}_paystack!
In your FreshJS Storefront .env for Apple-4All:
# Format: "provider_id:Display Name"
PAYMENT_PROVIDERS="pp_apple_4all_paystack:Paystack,pp_system_default:Pay on Delivery"In your FreshJS Storefront .env for Urban Device Care:
PAYMENT_PROVIDERS="pp_urbandevicecare_paystack:Paystack,pp_system_default:Pay on Delivery"The storefront will automatically ignore the other region-wide providers and dynamically bind to the correct backend instance!
- Storefront Usage (FreshJS)
We've included an example FreshJS Preact Island component under
storefront/components/PaystackCheckout.tsx. Use it to generate the inline popup securely:
import { PaystackCheckout } from "./components/PaystackCheckout";
// When standard checkout reaches payment, or during partial installments,
// render the component with the access_code generated by the backend:
<PaystackCheckout
accessCode={paymentSession.data.paystackTxAccessCode}
autoTrigger={true}
onSuccess={(transaction) => console.log(transaction)}
/>- Verify Cron Job Configuration
Ensure that the Medusa server has Redis running to execute the verification cron job (
verify-pending-paystack.ts), which automatically cleans up dropped connections every 30 minutes.
TODO
- [ ] Add extensive end-to-end testing for Webhook signature parsing.
- [ ] Add Support for Split Payments directly routing to Paystack Subaccounts.
- [ ] Implement robust refund synchronization if refunds occur from the Paystack Dashboard directly.
- [ ] Support custom UI localization for the Admin Widget.
Changelog
v1.0.0
- Initial Release:
- Complete Medusa v2 compatibility.
- Multi-account logic utilizing native config injection.
- Paystack Subunit currency helper added.
- Custom Admin UI widget deployed for STK Push and Manual payment records.
- Failsafe Cron Job implemented.
