All Skills

PayFast payment gateway integration specialist for FastAPI and Node.js. Use when debugging PayFast signature validation, ITN webhooks, sandbox-to-production migration, or implementing onsite/offsite/recurring billing. Covers MD5 signature generation, webhook security, PCI-DSS compliance, and production deployment checklists.

m
$npx skills add mkelam/PDFLab --skill payfast-integration

PayFast Integration Specialist

Production-grade PayFast integration with systematic debugging workflows for FastAPI and Node.js applications.

Diagnostic Interview

Before jumping to solutions, gather these critical details:

Error Context:

  • Exact error message (include stack trace if available)
  • When does it occur? (payment submission, ITN callback, signature validation)
  • Environment: sandbox or production

Integration Details:

  • Integration type: onsite, offsite, or recurring billing
  • Framework: FastAPI or Node.js (which version?)
  • Recent changes: code updates, PayFast dashboard settings, server migrations

Configuration Status:

  • merchant_id and merchant_key verified against PayFast dashboard
  • Passphrase set (required for recurring billing and signatures)
  • Return/cancel/notify URLs publicly accessible (not localhost)

Top 3 Failure Modes

1. MD5 Signature Mismatch

Symptoms:

  • "Generated signature does not match" error
  • Payment form rejected
  • ITN validation fails

⚠️ CRITICAL: PayFast Signature Requirements (NON-NEGOTIABLE)

Production Lesson Learned (Nov 5, 2025): PayFast signature mismatch caused 100% payment failure in production. Issue: empty passphrase was being included in signature generation when production mode doesn't use passphrases.

Mandatory Signature Generation Steps:

  1. ✅ Sort keys alphabetically (a-z) - EXACT alphabetical order required
  2. ✅ URL encode values - Spaces as +, not %20
  3. ✅ Exclude empty values - Do NOT include parameters with empty strings
  4. ❌ NO passphrase in production mode - Only use passphrase in sandbox if configured
  5. ✅ MD5 hash the parameter string - Use lowercase output

Before vs After (Real Production Issue):

// ❌ WRONG: Including empty passphrase in production
const signature = generateSignature(paymentData, PAYFAST_CONFIG.passphrase);
// passphrase = "" gets included → signature mismatch

// ✅ CORRECT: No passphrase parameter in production
const signature = generateSignature(paymentData);
// Only actual payment parameters → signature valid

Root Causes & Fixes:

IssueDetectionSolutionReal Production Impact
Empty passphrase includedCheck if empty passphrase in signature paramsExclude passphrase entirely in production modeFIXED Nov 5 - 100% payment failure
Wrong parameter orderCompare param order to PayFast docsParameters MUST be alphabetically sorted (a-z)Critical - always fails
Trailing spaces in merchant_keyCopy merchant_key, check lengthTrim whitespace when storing credentialsCommon copy-paste error
Empty fields includedCheck for blank value="" fieldsExclude empty parameters from signature stringCauses intermittent failures
Uppercase MD5 hashCheck hash output casingUse .toLowerCase() on hashAlways fails validation
URL encoding inconsistentSpecial chars in item descriptionsSpaces as +, special chars URL encodedFails with special characters

Mandatory Pre-Integration Testing:

# Step 1: Generate signature manually
 Create parameter string with exact alphabetical order
 Exclude empty values
 Do NOT include passphrase in production
 MD5 hash and convert to lowercase

# Step 2: Test with PayFast signature validator
 Use PayFast's signature validation endpoint
□ Send test payment with known signature
□ Verify "Signature valid" response

# Step 3: Test with real payment amounts
□ Test with minimum amount (R5.00)
□ Test with decimal amounts (R85.50)
□ Test with large amounts (R1850.00)

# Step 4: Verify parameter ordering
□ Print parameter string before hashing
□ Confirm alphabetical order visually
□ Compare with PayFast documentation example

Signature Validation Endpoint (for testing):

# Test your signature generation
curl -X POST https://www.payfast.co.za/eng/query/validate \
  -d "merchant_id=YOUR_ID" \
  -d "signature=YOUR_GENERATED_SIGNATURE" \
  -d "amount=85.00"

Verification Script: See scripts/validate_signature.py for standalone signature validator.

Real Production Test Results (Nov 5, 2025):

=== Before Fix ===
Generated Signature: a1b2c3d4e5f6 (with empty passphrase)
PayFast Expected: c857dc1297ea380cd431307f75d42bea
Result: ❌ Signature mismatch - 100% payment failure

=== After Fix ===
Generated Signature: c857dc1297ea380cd431307f75d42bea (no passphrase)
PayFast Expected: c857dc1297ea380cd431307f75d42bea
Result: ✅ Signatures match - payments working

2. ITN (Instant Transaction Notification) Webhook Failures

Symptoms:

  • Payment succeeds but order not updated
  • "ITN not received" in PayFast logs
  • 307 redirect or non-200 response
  • Empty req.body in webhook handler

Root Causes & Fixes:

IssueDetectionSolution
Not returning 200 OKCheck webhook logs for status codeWebhook MUST return 200 before any async processing
notify_url redirects (307)Test URL with curlUse exact URL (no trailing slash mismatch), ensure HTTPS
localhost URLCheck if notify_url uses localhostUse ngrok/tunneling for dev or deploy to accessible server
Body parsing middleware missingCheck if req.body populatedFastAPI: use Form(...), Node.js: express.urlencoded()
Source IP not from PayFastLog incoming IP in webhookVerify IP in PayFast ranges (see Security Checks below)
Signature validation failingLog received vs computed signatureApply same signature logic as payment submission

Advisory Security Checks: Consider implementing these ITN validations:

  • Verify source IP belongs to PayFast (range: 197.97.145.144/28)
  • Validate signature matches received data
  • Confirm payment amount matches order total
  • Check payment status is COMPLETE before fulfilling order

Testing Script: See scripts/test_itn_endpoint.py to simulate PayFast ITN callbacks.

3. Configuration & Environment Issues

Symptoms:

  • Works in sandbox, fails in production
  • "Invalid merchant_id or merchant_key"
  • Recurring billing signature errors

Root Causes & Fixes:

IssueDetectionSolution
Sandbox creds in productionCheck if merchant_id is 10000100 (sandbox)Switch to live merchant_id and merchant_key from PayFast dashboard
merchant_id vs merchant_key swappedDouble-check credential assignmentmerchant_id is numeric, merchant_key is alphanumeric
Passphrase not setCheck PayFast dashboard SettingsRequired for recurring billing; set in Integration > Security
Recurring billing not enabledTest subscription paymentEnable in PayFast dashboard Settings > Integrations
CURL disabled on serverTest: curl --versionContact hosting provider to enable CURL/outbound requests
Firewall blocks PayFast IPsCheck server firewall logsWhitelist PayFast IP ranges

Systematic Debugging Workflow

Step 1: Isolate Failure Point

  • Client-side? Check browser console for JS errors, form submission logs
  • Server-side? Check application logs for exceptions in payment initiation
  • Gateway? Check PayFast dashboard transaction logs for rejection reason
  • Webhook? Check ITN logs for delivery failures or 5xx errors

Step 2: Verify Configuration Run this checklist:

□ merchant_id matches PayFast dashboard (case-sensitive)
□ merchant_key matches PayFast dashboard (no spaces)
□ Passphrase set in PayFast dashboard if using signatures
□ Environment matches credentials (sandbox vs production)
□ notify_url publicly accessible (test with curl)
□ return_url and cancel_url use HTTPS

Step 3: Test Signature Generation Use scripts/validate_signature.py to:

  • Generate reference signature from sample data
  • Compare with your application's signature output
  • Identify parameter ordering or encoding issues

Step 4: Test Webhook Reception Use scripts/test_itn_endpoint.py to:

  • Send mock ITN payload to your endpoint
  • Verify 200 response returned immediately
  • Check if order status updates correctly

Step 5: Check Logs Systematically

  • Application logs: Exceptions, signature mismatches, validation errors
  • PayFast ITN logs: Dashboard > Integrations > View ITN Log
  • Server access logs: Confirm ITN POST requests arriving
  • Network traces: Use browser DevTools or Wireshark for API calls

Framework-Specific Patterns

FastAPI: See references/fastapi-patterns.md for:

  • Pydantic models for payment requests
  • Async webhook handlers
  • Signature validation middleware
  • Type-safe configuration management

Node.js: See references/nodejs-patterns.md for:

  • Express route setup
  • Body parsing middleware
  • Signature generation utilities
  • Error handling patterns

Sandbox-to-Production Migration

Repeatable Workflow:

Step 1: Export Sandbox Configuration

# Document current working sandbox setup
 merchant_id (sandbox): __________
 merchant_key (sandbox): __________
 Passphrase (if set): __________
 Test transaction IDs: __________
 Working notify_url pattern: __________

Step 2: Update PayFast Dashboard (Production)

  • Navigate to Settings > Integration
  • Set passphrase (copy from sandbox if consistent)
  • Configure notify_url with production domain
  • Enable recurring billing if needed
  • Save and note new production credentials

Step 3: Update Application Configuration

 Update merchant_id to production value
 Update merchant_key to production value
 Change API endpoint: sandbox.payfast.co.za payfast.co.za
 Update notify_url to production domain
 Verify HTTPS certificate valid on all URLs

Step 4: Validation Checklist

 Run scripts/validate_signature.py with production creds
 Test small transaction (minimum amount)
 Verify ITN callback received and processed
 Check order status updates correctly
 Confirm email notifications sent (if enabled)
 Test edge cases: cancelled payment, failed payment

Step 5: Monitoring Setup Consider implementing:

  • Alert on ITN failures (non-200 responses)
  • Log signature mismatches for analysis
  • Track transaction completion rate
  • Monitor webhook response times
  • Set up PayFast dashboard email notifications

Security Best Practices

Advisory Recommendations:

PCI-DSS Compliance:

  • Never log full card numbers or CVV codes
  • Use HTTPS for all payment-related endpoints
  • Implement rate limiting on payment submission endpoints
  • Store credentials in environment variables, not code

Signature Validation:

  • Always validate ITN signatures before processing
  • Use timing-safe comparison for signature checks
  • Regenerate signature server-side; never trust client values

Webhook Security:

  • Consider source IP validation (PayFast IPs only)
  • Implement idempotency checks to prevent duplicate processing
  • Return 200 immediately, process async to avoid timeouts
  • Log all ITN payloads for audit trail

Data Handling:

  • Validate amount precision (2 decimal places for ZAR)
  • Check currency matches expected value (ZAR)
  • Sanitize user input in item descriptions
  • Use database transactions for order state updates

Code Snippet Guidelines

When providing code examples:

  • Include inline comments explaining PayFast-specific requirements
  • Flag security risks explicitly (e.g., exposed keys, weak validation)
  • Show error handling for network failures and signature mismatches
  • Demonstrate idempotent webhook processing patterns
  • Provide both sync and async examples where applicable

Production Resilience

Recommended Monitoring:

  • Webhook delivery success rate (target: >99%)
  • Average ITN processing time (target: <500ms)
  • Signature validation failure rate (investigate if >1%)
  • Payment-to-order completion rate (identify drop-offs)

Alerting Triggers:

  • Webhook returning non-200 status
  • Repeated signature mismatches from same user
  • ITN not received within 5 minutes of payment
  • Unusual spike in failed transactions