What gets generated
Webhook handler with signature verification
# app/blueprints/paystack_webhook_bp.py
import hmac, hashlib
@paystack_webhook_bp.route("/webhooks/paystack", methods=["POST"])
def handle_webhook():
signature = request.headers.get("X-Paystack-Signature", "")
body = request.data
expected = hmac.new(
current_app.config["PAYSTACK_SECRET_KEY"].encode(),
body,
hashlib.sha512
).hexdigest()
if not hmac.compare_digest(signature, expected):
return jsonify({"error": "invalid signature"}), 400
event = request.get_json()
if WebhookEvent.query.filter_by(provider_event_id=event.get("data", {}).get("reference")).first():
return jsonify({"status": "already_processed"}), 200
handler = WEBHOOK_HANDLERS.get(event["event"])
if handler:
handler(event)
return jsonify({"status": "ok"}), 200
Subscription billing
Paystack's subscription model differs from Stripe's. Generated code handles charge.success, subscription.create, subscription.disable, invoice.create, invoice.payment_failed. The plan-enforcement middleware reads the workspace's current subscription and gates premium features accordingly.
Split payments (for marketplace use cases)
When you generate a marketplace, Archiet wires Paystack's subaccount + split mechanism. Vendors register a subaccount; orders containing their products route a percentage to that subaccount automatically.
Multi-currency
NGN, GHS, ZAR, KES are all supported as first-class. Amounts stored in minor units (kobo for NGN, pesewas for GHS), never floats. Currency is locked at order placement, conversions logged.
Refund flow
Paystack's refund API requires the original transaction reference; generated code stores it on the payment record and exposes a refund route gated by role. Partial refunds supported.
What ships in docs/
docs/decisions/ADR-0009-payment-provider-paystack.md— when Paystack is the right call (African market presence) vs Stripe (global), with rejected alternativesdocs/compliance/cbn-compliance-notes.md— when targeting Nigerian customers, the CBN data-residency considerationsdocs/decisions/ADR-0014-webhook-signature-verification.md— Paystack's HMAC-SHA512 vs Stripe's HMAC-SHA256
Environment variables generated
PAYSTACK_PUBLIC_KEY=pk_test_...
PAYSTACK_SECRET_KEY=sk_test_...
PAYSTACK_WEBHOOK_SECRET=...
PAYSTACK_PLAN_CODE_BUILDER=PLN_...
PAYSTACK_PLAN_CODE_PRO=PLN_...
Paystack documentation references
Internal links
- Stripe integration for the global counterpart
- Flutterwave integration for additional African market coverage
- Marketplace use case
CTA
Try it — free plan, no credit card. archiet.com.
Generate a codebase targeting African markets with Paystack wired, look at the webhook + split-payment shape, decide if it's the architecture you'd ship.