McTaba Labs logo
Software EngineeringThe WhiteboardProjectsEventsMasterclassesWebinarsLearn
Book Call

500+ developers already in the community

Get answers, find accountability partners, and stay ahead

Join Discord →
McTaba Labs logo

Educating 1 million students in tech by 2030.

Programs

  • HighSchool Graduates Launchpad
  • AI & Business Automation
  • Corporate Training
  • McTaba Story & Mission
  • Full-Stack Curriculum
  • Course Pricing & Plans
  • Frequently Asked Questions

Resources

  • Join Discord Community
  • Tech Events in Nairobi
  • Masterclasses
  • Free Resources
  • Learn
  • Campus
  • Africa Tech Talent Report
  • Partner With Us
  • Start a Project
  • Our Work

Contact Us

  • 124 Manyani East Road, Lavington, Nairobi
  • +254727795603
  • Book a Discovery Call

Office Hours:

Mon-Fri: 9am - 2pm EAT

Sat: 10am - 12pm EAT

© 2027 McTaba Labs - A product of Edtech Industries. All rights reserved.

Privacy PolicyTerms of ServiceRefund Policy
  1. Learn
  2. Paystack for African Developers
  3. Using an LLM to Explain Failed Payments to Customers
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 22, 2026

Using an LLM to Explain Failed Payments to Customers

Pattern: 1) Get gateway_response from Paystack (from GET /transaction/verify/:reference or charge.failed webhook). 2) Send gateway_response + channel (card/mobile money/bank transfer) to LLM. 3) Prompt: "Translate this payment failure message into a friendly, actionable explanation for a customer. Tell them what to do next. Do not reveal internal error codes or system details." 4) Return the LLM response to the customer. Always include a next step: try a different card, check balance, contact bank, or try again later. Never show the raw gateway_response to customers.

In this article

  1. 1. Payment Failure Explanation Generator
  2. 2. Common Paystack gateway_response Values
  3. 3. Learn More

Payment Failure Explanation Generator

// Cache for common failure explanations (same input → same output)
var explanationCache = new Map();

async function explainPaymentFailure({ gateway_response, channel, amount_ngn }) {
  var cacheKey = gateway_response + ':' + channel;
  if (explanationCache.has(cacheKey)) {
    return explanationCache.get(cacheKey);
  }

  var channelContext = {
    card: 'This was a card payment.',
    mobile_money: 'This was a mobile money payment (M-Pesa/Airtel Money).',
    bank: 'This was a bank transfer payment.',
    ussd: 'This was a USSD payment.',
  }[channel] || '';

  var prompt = `A customer's payment of NGN ${amount_ngn} failed with this bank message: "${gateway_response}". ${channelContext}

Write a brief, friendly explanation for the customer that:
1. Acknowledges the payment did not go through
2. Explains the likely cause in plain language (no technical jargon)
3. Gives 1-2 specific actions the customer can take
4. Is 2-3 sentences maximum

Do not: mention the bank's internal error message, reveal system details, or use phrases like "error code".
The customer sees this message directly.`;

  var response = await anthropic.messages.create({
    model: 'claude-haiku-4-5-20251001', // fast and cheap — this runs per failed payment
    max_tokens: 150,
    messages: [{ role: 'user', content: prompt }],
  });

  var explanation = response.content[0].text.trim();

  // Cache for 24 hours — same failure message = same explanation
  explanationCache.set(cacheKey, explanation);
  setTimeout(() => explanationCache.delete(cacheKey), 24 * 60 * 60 * 1000);

  return explanation;
}

// Example outputs for common Paystack failures:
// "Do Not Honour" → "Your bank declined this payment. This can happen if your card has a daily transaction limit or if your bank flagged the transaction as unusual. Try using a different card, or contact your bank to authorize the payment."
// "Insufficient Funds" → "Your account did not have enough funds to complete this payment. Please top up your account or use a different card and try again."
// "Invalid Card Number" → "There was an issue with the card number entered. Please double-check your card details and try again, or use a different card."

Common Paystack gateway_response Values

gateway_responseLikely CauseCustomer Action
Insufficient FundsAccount balance too lowTop up account or use different card
Do Not HonourBank declined without reason (fraud suspicion, limit, restriction)Contact bank or use different card
Transaction Not Permitted to CardholderCard restricted for this transaction typeContact bank to lift restriction or use different card
Invalid Card NumberCard number entered incorrectlyCheck card number and re-enter
Expired CardCard past expiry dateUse a different, non-expired card
DeclinedGeneric bank declineContact bank or use different payment method
TimeoutNo response from bank within time limitTry again — likely a temporary network issue

Get weekly developer tips

Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.

No spam. Unsubscribe anytime.

Learn More

See building a payments support chatbot to embed this explanation pattern in a full support workflow.

Sign up for the McTaba newsletter

Key Takeaways

  • ✓gateway_response from Paystack is technical language for developers — translate it before showing to customers.
  • ✓Always include a customer action in the explanation: try different card, check balance, contact bank.
  • ✓Never expose raw Paystack gateway_response codes or internal error details to customers.
  • ✓Vary the explanation by channel — mobile money failures differ from card failures in cause and remedy.
  • ✓Cache common failure translations — the same gateway_response always produces the same explanation.

Frequently Asked Questions

Why not just build a lookup table for failure messages instead of using an LLM?
A lookup table is the right default for the most common failure codes — it is faster, cheaper, and deterministic. Use Claude Haiku or a small model only for failure codes not in your lookup table, or when you need the message to vary by channel (a mobile money failure explanation differs from a card failure explanation). Start with a lookup table for the 10-15 most common codes and use an LLM as fallback for the rest.
Can I show the gateway_response directly to technical customers (developers testing integrations)?
In a developer-facing context (test dashboard, API response for developers), yes — include the raw gateway_response alongside the friendly message. In a customer-facing checkout or payment page, never. The rule is: who is reading the message? End customers see the friendly version. Developers see both.
Should I use Claude Opus or a smaller model for failure explanations?
Use Claude Haiku (claude-haiku-4-5-20251001). Failure explanations are short, formulaic, and do not require complex reasoning. Haiku is fast and cheap — important because this runs on every failed transaction. Opus is for complex reasoning tasks. Save it for contexts where the reasoning complexity justifies the cost: dispute drafting, anomaly analysis, or multi-step agent workflows.

Learn Paystack Integration

KES 2,999

The definitive guide to building payment systems with Paystack — from your first transaction to production-grade payment infrastructure across Africa. 9 modules, 47 lessons. Free preview available.

Start Paystack Course

Not ready? Create Free Account

Keep reading

Paystack AI Agents and the MCP Server: The Complete Guide

A comprehensive guide to building AI agents that interact with Paystack through the Model Context Protocol (MCP) server. Covers connecting the MCP server to Claude Code, querying transactions with natural language, building payment support chatbots, AI-assisted reconciliation, agentic payouts with safety rails, secret key security, human-in-the-loop design, prompt injection risks, and audit trails for AI-initiated financial actions.

Read more

RAG Over Your Payment Documentation and Transaction History

RAG lets an LLM answer questions grounded in your actual Paystack docs and transaction history instead of its training data. "What does this error code mean?" retrieves from your embedded docs. "What happened to transaction X?" retrieves from your transaction store.

Read more

Why You Should Never Give an LLM Your Paystack Secret Key

Your Paystack secret key can initialize transactions, trigger transfers, and access all your transaction data. Giving it to an LLM — even once — creates risks that do not go away when you close the chat window.

Read more

Building a Voice Agent That Collects Payment

A customer calls your number. They say what they want to pay for. The voice agent creates a Paystack payment link and texts it to their phone. No human operator needed. Here is how to build it.

Read more

Verify Paystack Payments in iOS with Swift

After Paystack checkout in iOS, verify the transaction by calling your backend. This guide covers the Swift verification flow using URLSession with async/await, Observable objects for SwiftUI, and error handling.

Read more

Explore related topics

M-Pesa & African Stack

M-Pesa Daraja API tutorials, USSD development, and WhatsApp Business API guides. The African Stack that global bootcamps do not teach.

Learn to Code in Kenya

Everything a Kenyan needs to know before writing their first line of code. Career paths, real costs, hardware requirements, and honest answers about what it takes.

Learning to Code

Roadmaps, language guides, and practical advice for learning to code and launching a programming career.

Breaking Into Tech

Practical, no-nonsense guides for anyone looking to start or change their career in tech. From choosing your first language to acing interviews.

The African Stack: Skills for This Market

The skills that make Kenyan developers hard to replace: M-Pesa, USSD, WhatsApp, fintech, and building for the African market.

Bonaventure Ogeto

Bonaventure Ogeto

Founder, McTaba Labs

Bonaventure is the founder of McTaba Labs, a coding bootcamp in Nairobi, Kenya. He has spent years building products for the African market and mentoring the next generation of developers across the continent.