medusa-payment-yoco
v1.2.0
Published
An awesome Yoco payment provider for Medusa v2 - Accept card payments in South Africa
Maintainers
Readme
medusa-payment-yoco
A payment provider for Medusa v2 that makes it easy to accept card payments in South Africa. With just a few lines of code, you can enable your customers to pay with Visa, Mastercard, American Express, and Instant EFT.
The package handles the Yoco Checkout API flow, and provides a simple and consistent integration with Medusa's payment system. It also handles webhooks for payment confirmation, making it easy to integrate with your existing store.

Features
- ✅ Accept payments via Yoco's secure hosted checkout
- ✅ Webhook support for real-time payment updates
- ✅ Full and partial refund support
- ✅ Test & Live mode support
- ✅ Configurable redirect URLs for success, cancel, and failure
- ✅ Idempotency keys to prevent duplicate charges
- ✅ Production-grade error handling with detailed error codes
- ✅ Input validation with Zod
- ✅ TypeScript support with full type definitions
- ✅ Debug logging
- ✅ Comprehensive test coverage
Compatibility
This package is compatible with Medusa v2.0.0 and above.
How to use this cute package
Install the package
using yarn
yarn add medusa-payment-yocousing npm
npm install medusa-payment-yocoAdd it to your Medusa config
// medusa-config.ts
import { defineConfig } from "@medusajs/framework/utils"
export default defineConfig({
projectConfig: {
// your config...
},
modules: [
{
resolve: "@medusajs/medusa/payment",
options: {
providers: [
{
resolve: "medusa-payment-yoco",
id: "yoco",
options: {
secretKey: process.env.YOCO_SECRET_KEY,
debug: true,
// Optional: Configure redirect URLs after payment
successUrl: process.env.YOCO_SUCCESS_URL,
cancelUrl: process.env.YOCO_CANCEL_URL,
failureUrl: process.env.YOCO_FAILURE_URL,
},
},
],
},
},
],
})Add your Yoco keys to .env
# Get these from Yoco Business Portal > Selling Online > Payment Gateway
YOCO_SECRET_KEY=sk_test_xxxxxxxxxxxx
# Optional: Redirect URLs after payment (recommended for production)
YOCO_SUCCESS_URL=https://your-store.com/checkout/success
YOCO_CANCEL_URL=https://your-store.com/checkout/cancel
YOCO_FAILURE_URL=https://your-store.com/checkout/failureEnable Yoco in your region
- Go to Medusa Admin → Settings → Regions
- Select your South Africa region
- Add Yoco as a payment provider
- Save
Cool stuff girly-pop 💅🏾 You're ready to accept payments 🎉

Storefront Integration
Initialize payment with Yoco
// Select Yoco as payment provider
await medusa.store.cart.initiatePaymentSession(cartId, {
provider_id: "pp_yoco_yoco",
})Redirect to Yoco checkout
const { cart } = await medusa.store.cart.retrieve(cartId)
const paymentSession = cart.payment_collection?.payment_sessions?.find(
(ps) => ps.provider_id === "pp_yoco_yoco"
)
// Redirect customer to Yoco's secure payment page
window.location.href = paymentSession?.data?.redirectUrlComplete the order after payment
// On your return page
const { type, order } = await medusa.store.cart.complete(cartId)
if (type === "order") {
// Success! 🎉
router.push(`/order/${order.id}`)
}Configuration Options
| Option | Type | Required | Description |
| ------------ | --------- | -------- | ---------------------------------------------------------------------------- |
| secretKey | string | ✅ | Your Yoco secret key (sk_test_... or sk_live_...) |
| debug | boolean | ❌ | Enable debug logging (default: false) |
| successUrl | string | ❌ | URL to redirect to after successful payment |
| cancelUrl | string | ❌ | URL to redirect to after cancelled payment |
| failureUrl | string | ❌ | URL to redirect to after failed payment |
Redirect URLs
When configured, Yoco will automatically redirect customers back to your store after completing, cancelling, or failing a payment. This provides a better user experience by seamlessly bringing customers back to your checkout flow.
Example redirect URLs:
- Success:
https://your-store.com/checkout/success?session_id={session_id} - Cancel:
https://your-store.com/checkout/cancel?session_id={session_id} - Failure:
https://your-store.com/checkout/failure?session_id={session_id}
You can access the session ID from the URL query parameter to complete the order or handle errors appropriately.
Webhook Setup (Production)
For production, set up webhooks in your Yoco Business Portal:
- Go to Selling Online → Payment Gateway → Webhooks
- Add webhook URL:
https://your-domain.com/hooks/payment/yoco_yoco - Select events:
payment.succeeded,payment.failed
Test Cards
| Card Number | Result | | ------------------- | -------- | | 4000 0000 0000 0000 | ✅ Success | | 4000 0000 0000 0002 | ❌ Declined |
Use any future expiry date and any CVV.
Yoco Fees
No monthly fees - only pay when you get paid! 💰
- Local Cards: 2.6% - 2.95%
- International/AMEX: 3.05% - 3.5%
- Instant EFT: 2%
See Yoco Pricing for details.
TypeScript Support
Full TypeScript support with exported types:
import type { YocoOptions } from "medusa-payment-yoco"Production Best Practices
Idempotency
The package automatically handles idempotency for checkout creation and refunds using unique keys. This prevents duplicate charges if a network timeout causes a retry.
Error Handling
The package provides detailed error codes for better error handling in your storefront:
import { YocoPaymentError, YocoErrorCode } from "medusa-payment-yoco"
try {
// Payment logic
} catch (error) {
if (error instanceof YocoPaymentError) {
switch (error.code) {
case YocoErrorCode.CARD_DECLINED:
// Show user-friendly message
break
case YocoErrorCode.INSUFFICIENT_FUNDS:
// Handle insufficient funds
break
// ... handle other error codes
}
}
}Available error codes:
CARD_DECLINED- Card was declinedINSUFFICIENT_FUNDS- Insufficient fundsINVALID_CARD- Invalid card detailsEXPIRED_CARD- Card has expiredINVALID_CVV- Invalid CVV codeFRAUD_DETECTED- Transaction flagged as fraudulentLIMIT_EXCEEDED- Transaction limit exceededNETWORK_ERROR- Network communication errorAPI_ERROR- General API error
Partial Refunds
The package supports partial refunds. Simply specify the amount when calling refund:
// Refund R50.00 (5000 cents)
await paymentService.refundPayment({
payment_id: "payment_123",
amount: 5000,
// ...
})Logging
Enable debug logging in production with caution:
{
secretKey: process.env.YOCO_SECRET_KEY,
debug: process.env.NODE_ENV === "development", // Only in development
}Troubleshooting
Payment session not created?
- Check your secret key is correct (must start with
sk_test_orsk_live_) - Ensure Yoco is enabled in your region
- Enable
debug: trueto see detailed logs - Check that redirect URLs are valid HTTPS URLs
Webhooks not working?
- Webhook URL must be publicly accessible
- URL format:
https://your-domain.com/hooks/payment/yoco_yoco - Check webhook is enabled in Yoco dashboard
- Verify webhook events are selected:
payment.succeeded,payment.failed
Configuration validation errors?
- The package uses Zod for configuration validation
- Check the error message for specific validation failures
- Ensure all URLs use HTTPS protocol
Links
License
MIT
