Skip to content

Settings

STRIPE_API_VERSION (='2020-08-27')

The API version used to communicate with the Stripe API is configurable, and defaults to the latest version that has been tested as working. Using a value other than the default is allowed, as a string in the format of YYYY-MM-DD.

For example, you can specify "2020-03-02" to use that API version:

STRIPE_API_VERSION = "2020-03-02"

However you do so at your own risk, as using a value other than the default might result in incompatibilities between Stripe and this library, especially if Stripe has labelled the differences between API versions as "Major". Even small differences such as a new enumeration value might cause issues.

For this reason it is best to assume that only the default version is supported.

For more information on API versioning, see the stripe documentation.

See also API Versions.

DJSTRIPE_FOREIGN_KEY_TO_FIELD

(Introduced in 2.4.0)

DJSTRIPE_FOREIGN_KEY_TO_FIELD is a setting introduced in dj-stripe version 2.4.0. You are required to set it in 2.4.0: It does not have a default value. In 3.0.0, the default will be "id", and we recommend setting it to "id" for new installations. Older installations should set it to "djstripe_id". Explanation below.

In dj-stripe 2.3 and before, foreign keys for Stripe models were set to point to the foreign model's djstripe_id field, a numeric integer generated by the local database. This new setting allows dj-stripe users to change it to use the "id" field, which is the upstream, non-numeric Stripe identifier.

When using the Stripe identifier as a foreign key, synchronization between Stripe and dj-stripe can be made far more efficient and robust. Furthermore, it removes the per-installation instability of a critical value. The plan is to get rid of djstripe_id altogether for the 3.0 release (we may retain the field itself until 4.0, but it will no longer be a primary key).

How to migrate older installations from "djstripe_id" to "id"?

Such a migration path has not been designed at the moment. Currently if you want to switch an older installation to "id", the easiest way is to wipe the djstripe db and sync again from scratch. This is obviously not ideal, and we will design a proper migration path before 3.0.

DJSTRIPE_IDEMPOTENCY_KEY_CALLBACK (=djstripe.settings.djstripe_settings._get_idempotency_key)

A function which will return an idempotency key for a particular object_type and action pair. By default, this is set to a function which will create a djstripe.IdempotencyKey object and return its uuid. You may want to customize this if you want to give your idempotency keys a different lifecycle than they normally would get.

The function takes the following signature:

def get_idempotency_key(object_type: str, action: str, livemode: bool):
    return "<idempotency key>"

The function MUST return a string suitably random for the object_type/action pair, and usable in the Stripe Idempotency-Key HTTP header. For more information, see the stripe documentation.

DJSTRIPE_SUBSCRIBER_CUSTOMER_KEY (="djstripe_subscriber")

Every Customer object created in Stripe is tagged with metadata This setting controls what the name of the key in Stripe should be. The key name must be a string no more than 40 characters long.

You may set this to None or "" to disable that behaviour altogether. This is probably not something you want to do, though.

DJSTRIPE_SUBSCRIBER_MODEL (=settings.AUTH_USER_MODEL)

If the AUTH_USER_MODEL doesn't represent the object your application's subscription holder, you may define a subscriber model to use here. It should be a string in the form of 'app.model'.

Note

DJSTRIPE_SUBSCRIBER_MODEL must have an email field. If your existing model has no email field, add an email property that defines an email address to use.

Example Model:

class Organization(models.Model):
    name = CharField(max_length=200, unique=True)
    admin = ForeignKey(settings.AUTH_USER_MODEL, on_delete=CASCADE)

    @property
    def email(self):
        return self.admin.email

DJSTRIPE_SUBSCRIBER_MODEL_MIGRATION_DEPENDENCY (="__first__")

If the model referenced in DJSTRIPE_SUBSCRIBER_MODEL is not created in the __first__ migration of an app you can specify the migration name to depend on here. For example: "0003_here_the_subscriber_model_was_added"

DJSTRIPE_WEBHOOK_URL (=r"^webhook/$")

Warning

This setting is deprecated and will be removed in dj-stripe 2.9.

This is where you can tell Stripe to send webhook responses. You can set this to what you want to prevent unnecessary hijinks from unfriendly people.

As this is embedded in the URLConf, this must be a resolvable regular expression.

DJSTRIPE_WEBHOOK_SECRET (="")

If this is set to a non-empty value, webhook signatures will be verified.

Learn more about webhook signature verification.

DJSTRIPE_WEBHOOK_VALIDATION= (="verify_signature")

This setting controls which type of validation is done on webhooks. Value can be "verify_signature" for signature verification (recommended default), "retrieve_event" for event retrieval (makes an extra HTTP request), or None for no validation at all.

DJSTRIPE_WEBHOOK_TOLERANCE (=300)

Controls the milliseconds tolerance which wards against replay attacks. Leave this to its default value unless you know what you're doing.

DJSTRIPE_WEBHOOK_EVENT_CALLBACK (=None)

Webhook event callbacks allow an application to take control of what happens when an event from Stripe is received. It must be a callable or importable string to a callable that takes an event object.

One suggestion is to put the event onto a task queue (such as celery) for asynchronous processing.

Examples:

# callbacks.py
def webhook_event_callback(event, api_key):
    """ Dispatches the event to celery for processing. """
    from . import tasks
    # Ansychronous hand-off to celery so that we can continue immediately
    tasks.process_webhook_event.s(event.pk, api_key).apply_async()
# tasks.py
from djstripe.models import WebhookEventTrigger
from stripe.error import StripeError

@shared_task(bind=True)
def process_webhook_event(self, pk, api_key):
    """ Processes events from Stripe asynchronously. """
    logger.info(f"Processing Stripe event: {pk}")
    try:
        # get the event
        obj = WebhookEventTrigger.objects.get(pk=pk)
        # process the event.
        # internally, this creates a Stripe WebhookEvent Object and invokes the respective Webhooks
        try:
            event = obj.process(save=False, api_key=api_key)
            # only save the event if webhook process was successfuly, otherwise it won't retry
            event.save()
        except StripeError as exc:
            # Mark the event as not processed
            obj.processed = False
            obj.save()
            logger.error(f"Failed to process Stripe event: {pk}. Retrying in 60 seconds.")
            raise self.retry(exc=exc, countdown=60)  # retry after 60 seconds
    except WebhookEventTrigger.DoesNotExist as exc:
        # This can happen in case the celery task got executed before the actual model got saved to the DB
        raise self.retry(exc=exc, countdown=10)  # retry after 10 seconds

    return event.type or "Stripe Event Processed"
# settings.py
DJSTRIPE_WEBHOOK_EVENT_CALLBACK = 'callbacks.webhook_event_callback'

STRIPE_API_HOST (= unset)

If set, this sets the base API host for Stripe. You may want to set this to, for example, "http://localhost:12111" if you are running stripe-mock.

If this is set in production (DEBUG=False), a warning will be raised on manage.py check.

Source Code

dj-stripe settings

Attributes

djstripe.settings.djstripe_settings = DjstripeSettings() module-attribute

Classes

djstripe.settings.DjstripeSettings

Container for Dj-stripe settings

:return: Initialised settings for Dj-stripe. :rtype: object

Source code in djstripe/settings.py
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
class DjstripeSettings:
    """Container for Dj-stripe settings

    :return: Initialised settings for Dj-stripe.
    :rtype: object

    """

    DEFAULT_STRIPE_API_VERSION = "2020-08-27"

    ZERO_DECIMAL_CURRENCIES = {
        "bif",
        "clp",
        "djf",
        "gnf",
        "jpy",
        "kmf",
        "krw",
        "mga",
        "pyg",
        "rwf",
        "vnd",
        "vuv",
        "xaf",
        "xof",
        "xpf",
    }

    def __init__(self):
        # Set STRIPE_API_HOST if you want to use a different Stripe API server
        # Example: https://github.com/stripe/stripe-mock
        if hasattr(settings, "STRIPE_API_HOST"):
            stripe.api_base = getattr(settings, "STRIPE_API_HOST")

    # generic setter and deleter methods to ensure object patching works
    def __setattr__(self, name, value):
        self.__dict__[name] = value

    def __delattr__(self, name):
        del self.__dict__[name]

    @property
    def subscriber_request_callback(self):
        return self.get_callback_function(
            "DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK",
            default=(lambda request: request.user),
        )

    @property
    def get_idempotency_key(self):
        return self.get_callback_function(
            "DJSTRIPE_IDEMPOTENCY_KEY_CALLBACK", self._get_idempotency_key
        )

    @property
    def DJSTRIPE_WEBHOOK_URL(self):
        return getattr(settings, "DJSTRIPE_WEBHOOK_URL", r"^webhook/$")

    @property
    def WEBHOOK_TOLERANCE(self):
        return getattr(
            settings, "DJSTRIPE_WEBHOOK_TOLERANCE", stripe.Webhook.DEFAULT_TOLERANCE
        )

    @property
    def WEBHOOK_VALIDATION(self):
        return getattr(settings, "DJSTRIPE_WEBHOOK_VALIDATION", "verify_signature")

    @property
    def WEBHOOK_SECRET(self):
        return getattr(settings, "DJSTRIPE_WEBHOOK_SECRET", "")

    # Webhook event callbacks allow an application to take control of what happens
    # when an event from Stripe is received.  One suggestion is to put the event
    # onto a task queue (such as celery) for asynchronous processing.
    @property
    def WEBHOOK_EVENT_CALLBACK(self):
        return self.get_callback_function("DJSTRIPE_WEBHOOK_EVENT_CALLBACK")

    @property
    def SUBSCRIBER_CUSTOMER_KEY(self):
        return getattr(
            settings, "DJSTRIPE_SUBSCRIBER_CUSTOMER_KEY", "djstripe_subscriber"
        )

    @property
    def TEST_API_KEY(self):
        return getattr(settings, "STRIPE_TEST_SECRET_KEY", "")

    @property
    def LIVE_API_KEY(self):
        return getattr(settings, "STRIPE_LIVE_SECRET_KEY", "")

    # Determines whether we are in live mode or test mode
    @property
    def STRIPE_LIVE_MODE(self):
        return getattr(settings, "STRIPE_LIVE_MODE", False)

    @property
    def STRIPE_SECRET_KEY(self):
        # Default secret key
        if hasattr(settings, "STRIPE_SECRET_KEY"):
            STRIPE_SECRET_KEY = settings.STRIPE_SECRET_KEY
        else:
            STRIPE_SECRET_KEY = (
                self.LIVE_API_KEY if self.STRIPE_LIVE_MODE else self.TEST_API_KEY
            )
        return STRIPE_SECRET_KEY

    @property
    def STRIPE_PUBLIC_KEY(self):
        # Default public key
        if hasattr(settings, "STRIPE_PUBLIC_KEY"):
            STRIPE_PUBLIC_KEY = settings.STRIPE_PUBLIC_KEY
        elif self.STRIPE_LIVE_MODE:
            STRIPE_PUBLIC_KEY = getattr(settings, "STRIPE_LIVE_PUBLIC_KEY", "")
        else:
            STRIPE_PUBLIC_KEY = getattr(settings, "STRIPE_TEST_PUBLIC_KEY", "")
        return STRIPE_PUBLIC_KEY

    @property
    def STRIPE_API_VERSION(self) -> str:
        """
        Get the desired API version to use for Stripe requests.
        """
        version = getattr(settings, "STRIPE_API_VERSION", stripe.api_version)
        return version or self.DEFAULT_STRIPE_API_VERSION

    def get_callback_function(self, setting_name, default=None):
        """
        Resolve a callback function based on a setting name.

        If the setting value isn't set, default is returned.  If the setting value
        is already a callable function, that value is used - If the setting value
        is a string, an attempt is made to import it.  Anything else will result in
        a failed import causing ImportError to be raised.

        :param setting_name: The name of the setting to resolve a callback from.
        :type setting_name: string (``str``/``unicode``)
        :param default: The default to return if setting isn't populated.
        :type default: ``bool``
        :returns: The resolved callback function (if any).
        :type: ``callable``
        """
        func = getattr(settings, setting_name, None)
        if not func:
            return default

        if callable(func):
            return func

        if isinstance(func, str):
            func = import_string(func)

        if not callable(func):
            raise ImproperlyConfigured(f"{setting_name} must be callable.")

        return func

    def _get_idempotency_key(self, object_type, action, livemode) -> str:
        from .models import IdempotencyKey

        action = f"{object_type}:{action}"
        idempotency_key, _created = IdempotencyKey.objects.get_or_create(
            action=action, livemode=livemode
        )
        return str(idempotency_key.uuid)

    def get_default_api_key(self, livemode) -> str:
        """
        Returns the default API key for a value of `livemode`.
        """
        if livemode is None:
            # Livemode is unknown. Use the default secret key.
            return self.STRIPE_SECRET_KEY
        elif livemode:
            # Livemode is true, use the live secret key
            return self.LIVE_API_KEY or self.STRIPE_SECRET_KEY
        else:
            # Livemode is false, use the test secret key
            return self.TEST_API_KEY or self.STRIPE_SECRET_KEY

    def get_subscriber_model_string(self) -> str:
        """Get the configured subscriber model as a module path string."""
        return getattr(settings, "DJSTRIPE_SUBSCRIBER_MODEL", settings.AUTH_USER_MODEL)  # type: ignore

    def get_subscriber_model(self):
        """
        Attempt to pull settings.DJSTRIPE_SUBSCRIBER_MODEL.

        Users have the option of specifying a custom subscriber model via the
        DJSTRIPE_SUBSCRIBER_MODEL setting.

        This methods falls back to AUTH_USER_MODEL if DJSTRIPE_SUBSCRIBER_MODEL is not set.

        Returns the subscriber model that is active in this project.
        """
        model_name = self.get_subscriber_model_string()

        # Attempt a Django 1.7 app lookup
        try:
            subscriber_model = django_apps.get_model(model_name)
        except ValueError:
            raise ImproperlyConfigured(
                "DJSTRIPE_SUBSCRIBER_MODEL must be of the form 'app_label.model_name'."
            )
        except LookupError:
            raise ImproperlyConfigured(
                f"DJSTRIPE_SUBSCRIBER_MODEL refers to model '{model_name}' "
                "that has not been installed."
            )

        if (
            "email"
            not in [field_.name for field_ in subscriber_model._meta.get_fields()]
        ) and not hasattr(subscriber_model, "email"):
            raise ImproperlyConfigured(
                "DJSTRIPE_SUBSCRIBER_MODEL must have an email attribute."
            )

        if model_name != settings.AUTH_USER_MODEL:
            # Custom user model detected. Make sure the callback is configured.
            func = self.get_callback_function(
                "DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK"
            )
            if not func:
                raise ImproperlyConfigured(
                    "DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK must be implemented "
                    "if a DJSTRIPE_SUBSCRIBER_MODEL is defined."
                )

        return subscriber_model

Attributes

djstripe.settings.DjstripeSettings.DEFAULT_STRIPE_API_VERSION = '2020-08-27' class-attribute instance-attribute
djstripe.settings.DjstripeSettings.DJSTRIPE_WEBHOOK_URL property
djstripe.settings.DjstripeSettings.LIVE_API_KEY property
djstripe.settings.DjstripeSettings.STRIPE_API_VERSION: str property

Get the desired API version to use for Stripe requests.

djstripe.settings.DjstripeSettings.STRIPE_LIVE_MODE property
djstripe.settings.DjstripeSettings.STRIPE_PUBLIC_KEY property
djstripe.settings.DjstripeSettings.STRIPE_SECRET_KEY property
djstripe.settings.DjstripeSettings.SUBSCRIBER_CUSTOMER_KEY property
djstripe.settings.DjstripeSettings.TEST_API_KEY property
djstripe.settings.DjstripeSettings.WEBHOOK_EVENT_CALLBACK property
djstripe.settings.DjstripeSettings.WEBHOOK_SECRET property
djstripe.settings.DjstripeSettings.WEBHOOK_TOLERANCE property
djstripe.settings.DjstripeSettings.WEBHOOK_VALIDATION property
djstripe.settings.DjstripeSettings.ZERO_DECIMAL_CURRENCIES = {'bif', 'clp', 'djf', 'gnf', 'jpy', 'kmf', 'krw', 'mga', 'pyg', 'rwf', 'vnd', 'vuv', 'xaf', 'xof', 'xpf'} class-attribute instance-attribute
djstripe.settings.DjstripeSettings.get_idempotency_key property
djstripe.settings.DjstripeSettings.subscriber_request_callback property

Functions

djstripe.settings.DjstripeSettings.__delattr__(name)
Source code in djstripe/settings.py
49
50
def __delattr__(self, name):
    del self.__dict__[name]
djstripe.settings.DjstripeSettings.__init__()
Source code in djstripe/settings.py
39
40
41
42
43
def __init__(self):
    # Set STRIPE_API_HOST if you want to use a different Stripe API server
    # Example: https://github.com/stripe/stripe-mock
    if hasattr(settings, "STRIPE_API_HOST"):
        stripe.api_base = getattr(settings, "STRIPE_API_HOST")
djstripe.settings.DjstripeSettings.__setattr__(name, value)
Source code in djstripe/settings.py
46
47
def __setattr__(self, name, value):
    self.__dict__[name] = value
djstripe.settings.DjstripeSettings.get_callback_function(setting_name, default=None)

Resolve a callback function based on a setting name.

If the setting value isn't set, default is returned. If the setting value is already a callable function, that value is used - If the setting value is a string, an attempt is made to import it. Anything else will result in a failed import causing ImportError to be raised.

:param setting_name: The name of the setting to resolve a callback from. :type setting_name: string (str/unicode) :param default: The default to return if setting isn't populated. :type default: bool :returns: The resolved callback function (if any). :type: callable

Source code in djstripe/settings.py
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
def get_callback_function(self, setting_name, default=None):
    """
    Resolve a callback function based on a setting name.

    If the setting value isn't set, default is returned.  If the setting value
    is already a callable function, that value is used - If the setting value
    is a string, an attempt is made to import it.  Anything else will result in
    a failed import causing ImportError to be raised.

    :param setting_name: The name of the setting to resolve a callback from.
    :type setting_name: string (``str``/``unicode``)
    :param default: The default to return if setting isn't populated.
    :type default: ``bool``
    :returns: The resolved callback function (if any).
    :type: ``callable``
    """
    func = getattr(settings, setting_name, None)
    if not func:
        return default

    if callable(func):
        return func

    if isinstance(func, str):
        func = import_string(func)

    if not callable(func):
        raise ImproperlyConfigured(f"{setting_name} must be callable.")

    return func
djstripe.settings.DjstripeSettings.get_default_api_key(livemode)

Returns the default API key for a value of livemode.

Source code in djstripe/settings.py
179
180
181
182
183
184
185
186
187
188
189
190
191
def get_default_api_key(self, livemode) -> str:
    """
    Returns the default API key for a value of `livemode`.
    """
    if livemode is None:
        # Livemode is unknown. Use the default secret key.
        return self.STRIPE_SECRET_KEY
    elif livemode:
        # Livemode is true, use the live secret key
        return self.LIVE_API_KEY or self.STRIPE_SECRET_KEY
    else:
        # Livemode is false, use the test secret key
        return self.TEST_API_KEY or self.STRIPE_SECRET_KEY
djstripe.settings.DjstripeSettings.get_subscriber_model()

Attempt to pull settings.DJSTRIPE_SUBSCRIBER_MODEL.

Users have the option of specifying a custom subscriber model via the DJSTRIPE_SUBSCRIBER_MODEL setting.

This methods falls back to AUTH_USER_MODEL if DJSTRIPE_SUBSCRIBER_MODEL is not set.

Returns the subscriber model that is active in this project.

Source code in djstripe/settings.py
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
def get_subscriber_model(self):
    """
    Attempt to pull settings.DJSTRIPE_SUBSCRIBER_MODEL.

    Users have the option of specifying a custom subscriber model via the
    DJSTRIPE_SUBSCRIBER_MODEL setting.

    This methods falls back to AUTH_USER_MODEL if DJSTRIPE_SUBSCRIBER_MODEL is not set.

    Returns the subscriber model that is active in this project.
    """
    model_name = self.get_subscriber_model_string()

    # Attempt a Django 1.7 app lookup
    try:
        subscriber_model = django_apps.get_model(model_name)
    except ValueError:
        raise ImproperlyConfigured(
            "DJSTRIPE_SUBSCRIBER_MODEL must be of the form 'app_label.model_name'."
        )
    except LookupError:
        raise ImproperlyConfigured(
            f"DJSTRIPE_SUBSCRIBER_MODEL refers to model '{model_name}' "
            "that has not been installed."
        )

    if (
        "email"
        not in [field_.name for field_ in subscriber_model._meta.get_fields()]
    ) and not hasattr(subscriber_model, "email"):
        raise ImproperlyConfigured(
            "DJSTRIPE_SUBSCRIBER_MODEL must have an email attribute."
        )

    if model_name != settings.AUTH_USER_MODEL:
        # Custom user model detected. Make sure the callback is configured.
        func = self.get_callback_function(
            "DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK"
        )
        if not func:
            raise ImproperlyConfigured(
                "DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK must be implemented "
                "if a DJSTRIPE_SUBSCRIBER_MODEL is defined."
            )

    return subscriber_model
djstripe.settings.DjstripeSettings.get_subscriber_model_string()

Get the configured subscriber model as a module path string.

Source code in djstripe/settings.py
193
194
195
def get_subscriber_model_string(self) -> str:
    """Get the configured subscriber model as a module path string."""
    return getattr(settings, "DJSTRIPE_SUBSCRIBER_MODEL", settings.AUTH_USER_MODEL)  # type: ignore

selection: filters: - "!^[^]"