Changelog
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[1.2.0] - 2025-07-15
Removed
WEBHOOK_SECRETsetting — Paystack signs webhooks with your API secret key (sk_...), so a separate webhook secret was redundant. Webhook verification now readsPAYSTACK['SECRET_KEY']directly. Remove anyWEBHOOK_SECRETentries from your settings.djpaystack.W001system check — The warning for a missingWEBHOOK_SECREThas been removed since the setting no longer exists.
Added
paystack_listenmanagement command — Start a Cloudflare Quick Tunnel to receive live Paystack webhooks on localhost. Detects or guides installation ofcloudflared, streams the tunnel URL, and prints the webhook URL to register in the Paystack dashboard. Accepts--host,--port, and--webhook-pathoptions.paystack_webhook_eventmanagement command — Send a signed webhook event to your local dev server for testing. Includes sample payloads for 11 common event types (charge.success,transfer.success,subscription.create, etc.). Supports--reference,--amount,--email,--data(custom JSON), and--listto display all supported events.Documentation: Cloudflare Tunnel guide (
docs/advanced/cloudflare_tunnel.rst) — Install instructions for Linux, macOS, and Windows; manual tunnel usage;paystack_listencommand reference.Documentation: Webhook Security deep-dive (
docs/advanced/webhook_security.rst) — HMAC SHA-512 verification flow, whySECRET_KEYis used (not a separate secret), IP whitelisting, event deduplication, and production best practices.Documentation: Local Webhook Testing guide (
docs/advanced/local_webhook_testing.rst) — End-to-end workflow combiningpaystack_listen,paystack_webhook_event,WebhookTester, and DjangoTestCaseexamples.
Changed
Webhook handler —
verify_signature()readspaystack_settings.SECRET_KEYinstead of the removedWEBHOOK_SECRET.test_webhookcommand — UsesSECRET_KEYfor HMAC signing.start_webhook_tunnelcommand — Instructions updated to referenceSECRET_KEY.list_webhook_eventscommand — Fixed bug referencing non-existentDISPUTE_CREATE/DISPUTE_REMIND/DISPUTE_RESOLVEenum members; corrected toCHARGE_DISPUTE_CREATE/CHARGE_DISPUTE_REMIND/CHARGE_DISPUTE_RESOLVE.WebhookTesterdev utility — Renamedwebhook_secretparameter tosecret_keyfor consistency.Documentation overhaul — Rewrote
signals.rst(correct signal names),testing.rst(correctPaystackClientusage),webhooks.rst(removedWEBHOOK_SECRETexamples),configuration.rst,webhooks.rst,installation.rst,README.md, andINSTALLATION.mdto remove allWEBHOOK_SECRETreferences.
[1.1.0] - 2025-06-20
Security
Fixed webhook signature bypass —
verify_signature()now returnsFalse(instead ofTrue) whenWEBHOOK_SECRETis not configured, preventing unsigned payloads from being accepted.Fixed
naira_to_kobofloating-point precision — Changed fromint(naira * 100)toint(Decimal(str(naira)) * 100)to prevent rounding errors on real currency amounts.Webhook IP verification —
_get_client_ip()now correctly resolves client IPs fromX-Forwarded-Forheaders and the IP whitelist check is actually invoked.
Added
Charge API — Added
bank_transfer,eft, andqrparameters toChargeAPI.create()for Pay with Transfer, EFT (South Africa / Ozow), and QR code (scan-to-pay) payment channels.Transaction API — Added
splitparameter (dict) toTransactionAPI.initialize()for on-the-fly dynamic split configuration; addedsplit_codeandcallback_urltocharge_authorization().Dedicated Account API — Added
DedicatedAccountAPI.assign()for single-step Dedicated Virtual Account creation; fixedsplit()to acceptaccount_numberinstead ofcustomer; addeddateparameter torequery().Refund API — Added
RefundAPI.retry()for retrying refunds stuck inrefund.needs-attentionstatus.Webhook events — Added
BANK_TRANSFER_REJECTED,REFUND_PROCESSING,REFUND_NEEDS_ATTENTION,DIRECT_DEBIT_AUTHORIZATION_CREATED, andDIRECT_DEBIT_AUTHORIZATION_ACTIVEevents to theWebhookEventenum.Context manager —
PaystackClientnow supportswithstatements (__enter__/__exit__) for automatic session cleanup.System checks — Django system checks now raise
E001for a missingSECRET_KEYandW001for a missingWEBHOOK_SECRET.PaystackCallbackView— A class-based callback view (djpaystack.views) to handle Paystack redirect callbacks.New tests — Added
test_middleware.py,test_decorators.py,test_settings.py,test_admin.py,test_views.py, andtest_webhook_security.py— test suite grew from 27 to 64 tests.
Changed
Direct Debit API — Complete rewrite replacing fabricated
/mandate/endpoints with the correct Paystack endpoints:initialize_authorization,verify_authorization,activation_charge, andbulk_activation_charge.Dispute webhook events — Renamed
DISPUTE_CREATE/DISPUTE_RESOLVEtoCHARGE_DISPUTE_CREATE/CHARGE_DISPUTE_RESOLVEto match Paystack’s actualcharge.dispute.*event names.Logging — Replaced f-string logging calls with lazy
%sformatting throughout the codebase (client.py,middleware.py,handlers.py,decorators.py).Removed
python-decoupledependency — The package no longer requirespython-decouple; useos.environor any config loader of your choice.
Removed
Deprecated
default_app_config— Removed fromdjpaystack/__init__.py(unnecessary since Django 3.2+).setup.cfg— Consolidated all metadata intopyproject.tomlas the single source of truth.Redundant database indexes — Migration
0002_remove_redundant_indexesremoves duplicate indexes that were already covered byunique=Trueanddb_index=True.
Fixed
Webhook handler deduplication — Switched from
set()toOrderedDictfor processed-event tracking to ensure FIFO eviction and deterministic behaviour.Admin test configuration — Added
django.contrib.admin,sessions, andmessagesto testINSTALLED_APPSso admin tests run correctly.
[1.0.0] - 2024-02-13
Added
✨ Complete Paystack API integration with all endpoints
✨ Django models for transactions, customers, plans, products, and more
✨ Webhook support with automatic verification and signal dispatch
✨ Comprehensive configuration system with environment variable support
✨ Signal support for payment events (success, failed, verified, etc.)
✨ Type hints throughout the codebase for better IDE support
✨ Extensive error handling with custom exception classes
✨ Automatic retry mechanism with exponential backoff
✨ Request/response logging for debugging
✨ Pagination support for list endpoints
✨ Caching support for frequently accessed data
✨ Async-ready design for future async support
✨ Comprehensive test suite with high coverage
✨ Full API documentation with examples
✨ Support for Django 3.2 through Django 6.0
✨ Support for Python 3.8 through Python 3.12
Supported Services
Transactions - Create, verify, and manage transactions
Customers - Create and manage customer records
Plans - Create and manage subscription plans
Subscriptions - Manage customer subscriptions
Transfers - Handle fund transfers to bank accounts
Refunds - Process and manage refunds
Disputes - Manage transaction disputes
Settlements - Track settlement information
Splits - Configure payment splits between accounts
Subaccounts - Manage subaccounts
Products - Create and manage products
Payment Requests - Generate payment request links
Verification - Bank and account verification
Direct Debit - Direct debit authorization
Terminal - Terminal operations
Apple Pay - Apple Pay integration
Virtual Terminal - Virtual terminal operations
Pages - Create and manage pages
Bulk Charges - Batch charge operations
Integration - Integration-related operations
Miscellaneous - Other utility endpoints
Features
🔐 Secure webhook signature verification
🔄 Automatic transaction verification
📊 Comprehensive transaction tracking
🏪 Multi-merchant support via subaccounts
💳 Multiple payment methods support
📱 Apple Pay integration
💰 Payment splits and routing
🔗 Linked bank accounts for payouts
📧 Email-based customer identification
🏦 Bank account verification
📱 Phone number verification
🗂️ Flexible metadata storage
🔍 Advanced filtering and pagination
📝 Comprehensive logging
Documentation
📚 Full API documentation
🎓 Quick start guide
📖 Configuration guide
🔧 Integration examples
🧪 Testing guide
🔐 Security best practices
Support
For issues or feature requests, please visit GitHub Issues.
License
This project is licensed under the MIT License - see the LICENSE file for details.