Signals

The subscriptions package dispatches custom Django signals for every major lifecycle event. Connect to these signals to add custom behavior without modifying the package.

Connecting to Signals

# your_app/signals.py
from subscriptions.signals import subscription_activated, payment_success

def on_subscription_activated(sender, instance, **kwargs):
    """Called when a subscription becomes active."""
    print(f"Subscription activated: {instance.user} - {instance.plan.name}")

def on_payment_success(sender, instance, **kwargs):
    """Called when a payment is successfully settled."""
    print(f"Payment settled: {instance.order_id} - {instance.gross_amount}")

subscription_activated.connect(on_subscription_activated)
payment_success.connect(on_payment_success)

Or using the @receiver decorator:

from django.dispatch import receiver
from subscriptions.signals import subscription_created

@receiver(subscription_created)
def handle_new_subscription(sender, instance, **kwargs):
    """Send welcome email when subscription is created."""
    send_welcome_email(instance.user)

Signal Reference

Subscription Lifecycle

Signal

Sent When

instance Type

subscription_created

New subscription saved

Subscription

subscription_activated

Status changes to active

Subscription

subscription_cancelled

Status changes to cancelled

Subscription

subscription_paused

Status changes to paused

Subscription

subscription_resumed

(dispatched via subscription_activated)

Subscription

subscription_expired

Status changes to expired

Subscription

subscription_renewed

(dispatched manually when renewing)

Subscription

subscription_plan_changed

(available for custom use)

Subscription

Payment Lifecycle

Signal

Sent When

instance Type

payment_created

New payment saved

Payment

payment_success

Payment is settled (is_paid=True)

Payment

payment_failed

Status is deny, cancel, expire, or failure

Payment

payment_refunded

Status is refund or partial_refund

Payment

Invoice Lifecycle

Signal

Sent When

instance Type

invoice_created

New invoice saved

Invoice

invoice_paid

Status changes to paid

Invoice

invoice_overdue

Status changes to overdue

Invoice

invoice_voided

Status changes to void

Invoice

Webhook

Signal

Sent When

instance Type

webhook_received

New webhook log created

WebhookLog

webhook_processed

Webhook log status becomes processed

WebhookLog

Wallet

Signal

Sent When

instance Type

topup_completed

Top-up status changes to success

TopUp

wallet_credited

Wallet transaction created with positive amount

WalletTransaction

wallet_debited

Wallet transaction created with negative amount

WalletTransaction

How Signals Are Dispatched

Signals are dispatched via post_save handlers registered in subscriptions/signals.py:

  • Subscription: On post_save, checks if status is in update_fields and dispatches the corresponding signal

  • Payment: On post_save, checks is_paid or failure states

  • Invoice: On post_save, checks status for paid, overdue, void

  • WebhookLog: On post_save, dispatches webhook_received on create and webhook_processed on status update

  • TopUp: On post_save, dispatches topup_completed when status is success

  • WalletTransaction: On post_save, dispatches wallet_credited or wallet_debited based on amount sign

Example Use Cases

Send Slack notification on payment failure

@receiver(payment_failed)
def notify_slack_on_failure(sender, instance, **kwargs):
    slack_webhook(f"Payment failed: {instance.order_id} ({instance.gross_amount} {instance.currency})")

Log subscription changes to analytics

@receiver(subscription_activated)
def track_activation(sender, instance, **kwargs):
    analytics.track(instance.user.id, "subscription_activated", {
        "plan": instance.plan.name,
        "payment_type": instance.payment_type,
    })

Auto-provision resources on activation

@receiver(subscription_activated)
def provision_resources(sender, instance, **kwargs):
    features = instance.plan.features
    create_user_workspace(instance.user, max_projects=features.get("max_projects", 1))