### Install pre-commit hooks Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/project/contributing.md Initialize a git repository (required for pre-commit) and install the pre-commit hooks. ```bash git init # A git repo is required to install pre-commit pre-commit install ``` -------------------------------- ### Set up virtual environment with uv Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/project/contributing.md Install uv if not already installed, then set up a virtual environment with 'uv sync'. Commands can be run inside the environment by prefixing with 'uv run'. ```bash uv sync ``` -------------------------------- ### Install dj-stripe with pip Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/installation.md Alternative installation method using pip, the standard Python package installer. ```bash pip install dj-stripe ``` -------------------------------- ### Install dj-stripe with uv Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/installation.md Recommended installation method using the uv package manager. Run this command in your project directory to add dj-stripe as a dependency. ```bash uv add dj-stripe ``` -------------------------------- ### stripe listen --forward-to Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/local_webhook_testing.md Starts the Stripe CLI to listen for webhook events and forward them to a local dj-stripe webhook endpoint. The URL includes a UUID path parameter, supported from v2.7 onwards. ```bash stripe listen --forward-to http://localhost:8000/stripe/webhook/{UUID}/ ``` -------------------------------- ### Get or create a Stripe customer for a subscriber Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/customers.md Use Customer.get_or_create to fetch or create the Stripe customer for a subscriber. The first call creates the customer in Stripe and stores it locally; subsequent calls return the existing record. ```python from djstripe.models import Customer customer, created = Customer.get_or_create(subscriber=request.user) ``` -------------------------------- ### Style Stripe Element container with custom CSS Source: https://github.com/dj-stripe/dj-stripe/blob/main/tests/apps/example/templates/payment_intent.html Styles for the Stripe Elements card input container, including focus, invalid, and webkit autofill states. These styles are not part of the Quickstart guide but show how to customize the Element's appearance. ```css /* * The CSS shown here will not be introduced in the Quickstart guide, but shows * how you can use CSS to style your Element's container. */ .StripeElement { box-sizing: border-box; height: 40px; padding: 10px 12px; border: 1px solid transparent; border-radius: 4px; background-color: white; box-shadow: 0 1px 3px 0 #e6ebf1; -webkit-transition: box-shadow 150ms ease; transition: box-shadow 150ms ease; } .StripeElement--focus { box-shadow: 0 1px 3px 0 #cfd7df; } .StripeElement--invalid { border-color: #fa755a; } .StripeElement--webkit-autofill { background-color: #fefde5 !important; } ``` -------------------------------- ### Add payment method as default using Customer.add_payment_method Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/add_payment_method_to_customer.md Adds a payment method token to a customer and sets it as the default payment method. The example retrieves the first customer from the database and calls add_payment_method with a Stripe payment method identifier (e.g., pm_card_visa). ```python from djstripe.models import Customer customer = ( Customer.objects.first() ) # Get the first customer in the database as an example customer.add_payment_method( "pm_card_visa" ) # Add a payment method to the customer as the default payment method ``` -------------------------------- ### Uninstall jsonfield before installing dj-stripe>=2.2.0 Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/changes/2_x.md Run this command before upgrading to dj-stripe 2.2.0 or later to avoid the ImportError caused by both jsonfield and jsonfield2 using the same import path. It uninstalls jsonfield and installs dj-stripe 2.2.0 or newer. ```bash # ensure jsonfield is uninstalled before we install jsonfield2 pip uninstall jsonfield -y && pip install "dj-stripe>=2.2.0" ``` -------------------------------- ### Add payment method without setting as default using set_default=False Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/add_payment_method_to_customer.md Adds a payment method to a customer without setting it as the default by passing set_default=False. The example retrieves the first customer and calls add_payment_method with a payment method identifier and the set_default parameter. ```python from djstripe.models import Customer customer = ( Customer.objects.first() ) # Get the first customer in the database as an example customer.add_payment_method( "pm_card_visa", set_default=False ) # Add a payment method to the customer without making it the default payment method ``` -------------------------------- ### Uninstall jsonfield2 before upgrading to dj-stripe 2.3.0dev Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/changes/2_x.md Run this before upgrading from dj-stripe 2.2.x to ensure jsonfield2 is uninstalled before installing dj-stripe 2.3.0dev. This prevents the ImportError caused by jsonfield2's module being removed from site-packages. ```bash pip uninstall jsonfield2 -y && pip install "dj-stripe>=2.3.0dev" ``` -------------------------------- ### Get a cookie value for CSRF token Source: https://github.com/dj-stripe/dj-stripe/blob/main/tests/apps/example/templates/payment_intent.html Utility function to retrieve the value of a named cookie, used to get the CSRF token for the POST request. Returns null if the cookie is not present or cannot be parsed. ```javascript function getCookie(name) { if (!document.cookie) { return null; } const xsrfCookies = document.cookie.split(';') .map(c => c.trim()) .filter(c => c.startsWith(name + '=')); if (xsrfCookies.length === 0) { return null; } return decodeURIComponent(xsrfCookies[0].split('=')[1]); } ``` -------------------------------- ### Create PostgreSQL test database Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/project/contributing.md Create the PostgreSQL test database named 'djstripe'. ```bash createdb djstripe ``` -------------------------------- ### Initialize Stripe.js and mount a card Element Source: https://github.com/dj-stripe/dj-stripe/blob/main/tests/apps/example/templates/payment_intent.html Initializes Stripe.js with the public key from the Django template context, creates an Elements instance, styles the card input, and mounts it into the #card-element div. The key and URL are provided by the Django template. ```javascript var stripe = Stripe('{{ STRIPE_PUBLIC_KEY }}'); var elements = stripe.elements(); var style = { base: { color: '#32325d', fontFamily: '"Helvetica Neue", Helvetica, sans-serif', fontSmoothing: 'antialiased', fontSize: '16px', '::placeholder': { color: '#aab7c4' } }, invalid: { color: '#fa755a', iconColor: '#fa755a' } }; var cardElement = elements.create('card', {style: style}); cardElement.mount('#card-element'); ``` -------------------------------- ### Configure Stripe keys and operating mode Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/installation.md Set your Stripe test and live secret keys, enable live mode, and configure the foreign key field. STRIPE_LIVE_MODE must be a real boolean; convert environment variables explicitly. ```python import os STRIPE_TEST_SECRET_KEY = os.environ.get("STRIPE_TEST_SECRET_KEY", "") STRIPE_LIVE_SECRET_KEY = os.environ.get("STRIPE_LIVE_SECRET_KEY", "") STRIPE_LIVE_MODE = False # Change to True in production # Use the Stripe object id (e.g. "sub_...") as the foreign-key target. DJSTRIPE_FOREIGN_KEY_TO_FIELD = "id" ``` -------------------------------- ### Subscribe customer to prices using items dict Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/subscribing_customers.md Shows the recommended way to subscribe a customer to one or more prices using the items dict with Price objects. The first part subscribes to both price_1 and price_2, while the second part subscribes to a single price. For a single price, customer.subscribe(price=price_1) is equivalent. ```python ## Recommended Approach to use items dict with Prices ## This will subscribe customer to both price_1 and price_2 price_1 = Price.objects.get(nickname="one_price") price_2 = Price.objects.get(nickname="two_price") customer = Customer.objects.first() customer.subscribe(items=[{"price": price_1}, {"price": price_2}]) ## This will subscribe customer to price_1 price_1 = Price.objects.get(nickname="one_price") customer = Customer.objects.first() customer.subscribe(items=[{"price": price_1}]) ``` -------------------------------- ### Docker Compose with Stripe CLI for dj-stripe Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/using_with_docker.md Sample docker-compose.yaml for local development with Postgres, a Django app running dj-stripe, and the Stripe CLI sidecar. The Stripe CLI listens for webhook events and forwards them to the Django app's webhook endpoint using the x-djstripe-webhook-secret header. Replace the URL path (stripe/) with your mounted prefix and {uuid} with your webhook endpoint's UUID. Obtain the webhook signing secret from `stripe listen --print-secret`. ```yaml volumes: postgres-data: {} services: db: image: postgres:16 volumes: - postgres-data:/var/lib/postgresql/data environment: - POSTGRES_DB=myproject - POSTGRES_USER=myproject - POSTGRES_PASSWORD=changeme web: build: context: . dockerfile: { PATH_TO_DOCKERFILE } command: python manage.py runserver 0.0.0.0:8000 volumes: - .:/app ports: - "8000:8000" depends_on: - db environment: - STRIPE_TEST_SECRET_KEY=sk_test_****** - DATABASE_URL=postgres://myproject:changeme@db:5432/myproject stripe: image: stripe/stripe-cli:latest command: [ "listen", "-H", "x-djstripe-webhook-secret: whsec_******", "--forward-to", "http://web:8000/stripe/webhook/{uuid}/", ] depends_on: - web environment: - STRIPE_API_KEY=sk_test_****** - STRIPE_DEVICE_NAME=djstripe_docker ``` -------------------------------- ### Run migration for dj-stripe Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/upgrade_dj_stripe.md Run this command after pinning dj-stripe to the next migration-bearing release. It must succeed; if it fails, you likely skipped an intermediate version and should step back and migrate through it first. ```bash python manage.py migrate djstripe ``` -------------------------------- ### Charge a customer with Customer.charge() Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/creating_individual_charges.md Wraps the older Charges API. Takes a Decimal amount in major units and charges the customer's default source. Does not handle authentication challenges such as 3D Secure and can fail where SCA applies. ```python from decimal import Decimal customer.charge(Decimal("10.00"), currency="usd") ``` -------------------------------- ### Run migrations and sync Stripe data Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/installation.md Create the dj-stripe database tables and pull down existing Stripe data. The sync command processes every API key found in settings or the database. ```bash python manage.py migrate python manage.py djstripe_sync_models ``` -------------------------------- ### Create subscription directly with Stripe API and sync Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/subscribing_customers.md When Customer.subscribe() does not expose every needed argument, create the subscription directly with the Stripe API and sync the result back into dj-stripe using Subscription.sync_from_stripe_data(). Requires the Stripe Python library and a valid API key. ```python import stripe from djstripe.models import Subscription stripe_subscription = stripe.Subscription.create( customer=customer.id, items=[{"price": price_1.id}], api_key="sk_test_...", ) subscription = Subscription.sync_from_stripe_data(stripe_subscription) ``` -------------------------------- ### Select test database vendor Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/project/contributing.md Set the DJSTRIPE_TEST_DB_VENDOR environment variable to select sqlite or MySQL as the test database vendor. For postgres and mysql, additional environment variables for host, port, username, and password can be set (see tests/settings.py). ```bash export DJSTRIPE_TEST_DB_VENDOR=sqlite # or: export DJSTRIPE_TEST_DB_VENDOR=mysql ``` -------------------------------- ### Create a PaymentIntent with dj-stripe Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/creating_individual_charges.md Creates a PaymentIntent in Stripe and syncs it. Supports SCA and all payment method types. Keyword arguments are passed through to the Stripe API; dj-stripe model instances are converted to their ids. Collect the payment method in the browser first; the resulting Charge is synced through webhooks or when the intent is synced. ```python from djstripe.models import PaymentIntent intent = PaymentIntent.create( amount=1000, # minor units: 10.00 USD currency="usd", customer=customer, payment_method=customer.default_payment_method, off_session=True, confirm=True, ) ``` -------------------------------- ### Run tests with tox Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/project/contributing.md Run tests with tox to check compatibility with other Python and Django versions. ```bash uv run --group ci tox ``` -------------------------------- ### Create a PaymentMethod on button click and POST to server Source: https://github.com/dj-stripe/dj-stripe/blob/main/tests/apps/example/templates/payment_intent.html Listens for a click on the payment button, creates a PaymentMethod using the card Element and the cardholder name, then sends the payment method ID to the server via a POST request to the Django payment_intent URL. If an error occurs, it displays the error message in the #card-errors element. ```javascript var cardholderName = document.getElementById('cardholder-name'); var cardButton = document.getElementById('card-button'); cardButton.addEventListener('click', function (ev) { stripe.createPaymentMethod('card', cardElement, { billing_details: {name: cardholderName.value} }).then(function (result) { if (result.error) { var errorElement = document.getElementById('card-errors'); errorElement.textContent = result.error.message; } else { fetch("{% url 'djstripe_example:payment_intent' %}", { method: 'POST', headers: { "X-CSRFToken": getCookie("csrftoken"), "Accept": "application/json", "Content-Type": "application/json", "X-Requested-With": "XMLHttpRequest" }, body: JSON.stringify({'payment_method_id': result.paymentMethod.id}) }).then(function (result) { result.json().then(function (json) { handleServerResponse(json); }) }); } }); }); ``` -------------------------------- ### Sync models with custom API keys Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/manually_syncing_with_stripe.md Syncs the named models using the provided API keys. Keys passed with --api-keys are used as given; they do not need to be in the database. ```bash ./manage.py djstripe_sync_models Invoice Subscription --api-keys sk_test_XXX sk_test_YYY ``` -------------------------------- ### Configure DJSTRIPE_SUBSCRIBER_MODEL Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/settings.md Sets the model that Customer objects link to instead of the default AUTH_USER_MODEL. The model must have an email attribute and is specified as an "app_label.ModelName" string. ```python DJSTRIPE_SUBSCRIBER_MODEL = "myapp.Organization" ``` -------------------------------- ### Run tests with pytest Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/project/contributing.md Run the test suite quickly using sqlite and the --reuse-db flag. This command outputs command line and HTML coverage statistics and warns if coverage drops. ```bash DJSTRIPE_TEST_DB_VENDOR=sqlite uv run pytest --reuse-db ``` -------------------------------- ### Add djstripe to INSTALLED_APPS Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/installation.md Add 'djstripe' to your Django project's INSTALLED_APPS setting to enable the app. ```python INSTALLED_APPS = ( ... "djstripe", ... ) ``` -------------------------------- ### Load signal handlers in Django AppConfig.ready() Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/webhooks.md Override the ready() method in your Django AppConfig to import your signal handlers module, ensuring they are loaded at application startup. This is required for the custom handlers to be registered. ```python from django.apps import AppConfig class MyAppConfig(AppConfig): name = "my_app" def ready(self): import my_app.signals # ensure your signals are imported ``` -------------------------------- ### Regenerate test fixtures with manage command Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/project/test_fixtures.md Run this command to create test objects in your Stripe account and regenerate local fixture files. It restores a whitelist of values from existing fixtures to avoid inconsequential changes; disable this with --update-sideeffect-fields. ```bash $ ./manage.py regenerate_test_fixtures ``` -------------------------------- ### Include dj-stripe URLs in urlpatterns Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/installation.md Add the dj-stripe URL configuration to your project's urls.py file, typically under the 'stripe/' path with the namespace 'djstripe'. ```python from django.urls import include, path urlpatterns = [ ... path("stripe/", include("djstripe.urls", namespace="djstripe")), ] ``` -------------------------------- ### Filter subscriptions with with_status() and period_current() Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/changes/3_0_0.md Defines a set of subscription statuses that grant service access and filters the customer's subscriptions to those that are currently in their period. Use this to replace the removed subscription helpers and implement your own access policy. ```python from djstripe.enums import SubscriptionStatus SERVICE_STATUSES = { SubscriptionStatus.trialing, SubscriptionStatus.active, SubscriptionStatus.past_due, } service_subscriptions = customer.subscriptions.with_status( *SERVICE_STATUSES ).period_current() has_access = service_subscriptions.exists() ``` -------------------------------- ### Sync specific models with djstripe_sync_models Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/manually_syncing_with_stripe.md Syncs only the named models (Invoice and Subscription) for every secret key. Note that this may be redundant since related objects are recursively synced. ```bash ./manage.py djstripe_sync_models Invoice Subscription ``` -------------------------------- ### Set DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/settings.md Overrides the default callback (lambda request: request.user) to return the subscriber instance from the request, useful when the subscriber is not the logged-in user. ```python DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK = lambda request: request.user.organization ``` -------------------------------- ### Sync all models with djstripe_sync_models Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/manually_syncing_with_stripe.md Syncs all supported models for every secret key in the database and in your settings. Use this to populate an empty database from an existing Stripe account. ```bash ./manage.py djstripe_sync_models ``` -------------------------------- ### Clone dj-stripe fork Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/project/contributing.md Clone your fork of the dj-stripe repository to your local machine. Replace 'your_name_here' with your GitHub username. ```bash git clone git@github.com:your_name_here/dj-stripe.git ``` -------------------------------- ### Extend subscription with timedelta Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/managing_subscriptions.md Extends a subscription's next billing date by a positive timedelta for out-of-band payment. Warning: extension works by moving trial_end, so Stripe sets the subscription status to trialing until the new date. ```python from datetime import timedelta subscription.extend(timedelta(days=30)) ``` -------------------------------- ### stripe trigger customer.created Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/local_webhook_testing.md Triggers a Stripe event (customer.created) to test the local webhook endpoint. ```bash stripe trigger customer.created ``` -------------------------------- ### Commit and push changes Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/project/contributing.md Commit your changes and push your branch to GitHub before submitting a pull request. ```bash git add . git commit -m "Your detailed description of your changes." git push ``` -------------------------------- ### stripe listen with X-Djstripe-Webhook-Secret header Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/local_webhook_testing.md Passes the webhook secret to dj-stripe via the X-Djstripe-Webhook-Secret header. The secret is obtained by running `stripe listen --print-secret`. Without this header, signature validation fails with HTTP 400 and the message "Failed to verify header". ```bash stripe listen \ --forward-to http://localhost:8000/stripe/webhook/{UUID}/ \ -H "x-djstripe-webhook-secret: $(stripe listen --print-secret)" ``` -------------------------------- ### Subscribe to multiple subscription events with djstripe_receiver Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/webhooks.md Subscribe a single receiver to multiple event types by passing a list of event names to the djstripe_receiver decorator. The handler receives the Event instance as the event keyword argument. ```python @djstripe_receiver( [ "customer.subscription.created", "customer.subscription.updated", "customer.subscription.deleted", ] ) def handle_subscription_change(sender, event, **kwargs): ... ``` -------------------------------- ### Handle charge.succeeded and payment_method.attached with djstripe_receiver Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/webhooks.md Define custom handlers for the charge.succeeded and payment_method.attached webhook events using the djstripe_receiver decorator. Each handler retrieves the Event instance from kwargs, extracts the object ID from event.data, and fetches the corresponding model (Charge or PaymentMethod). Handlers run synchronously inside the webhook request transaction; make them idempotent. ```python from djstripe.event_handlers import djstripe_receiver from djstripe.models import Event, Charge, PaymentMethod @djstripe_receiver("charge.succeeded") def handle_charge_succeeded(sender, **kwargs): event: Event = kwargs.get("event") charge_id = event.data["object"]["id"] charge = Charge.objects.get(id=charge_id) print("Charge succeeded!") print(f"Sender: {sender}") print(f"Event: {event}") print(f"Charge: {charge}") @djstripe_receiver("payment_method.attached") def handle_payment_method_attached(sender, **kwargs): event: Event = kwargs.get("event") payment_method_id = event.data["object"]["id"] payment_method = PaymentMethod.objects.get(id=payment_method_id) print("Payment Method Attached!") print(f"Sender: {sender}") print(f"Event: {event}") print(f"Payment Method: {payment_method}") ``` -------------------------------- ### Define service access based on subscription status Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/customers.md Subscription status does not by itself determine access. Define your policy by explicitly selecting the statuses you accept, then use the composable queryset filters to check access. ```python from djstripe.enums import SubscriptionStatus SERVICE_STATUSES = { SubscriptionStatus.trialing, SubscriptionStatus.active, SubscriptionStatus.past_due, } service_subscriptions = customer.subscriptions.with_status( *SERVICE_STATUSES ).period_current() has_access = service_subscriptions.exists() has_product_access = service_subscriptions.for_product(product).exists() ``` -------------------------------- ### Generate Django migrations Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/project/contributing.md Generate Django migrations if your changes altered the models. ```bash DJSTRIPE_TEST_DB_VENDOR=sqlite uv run ./manage.py makemigrations ``` -------------------------------- ### Custom idempotency key callback Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/idempotency.md Sets a custom callable to generate idempotency keys. The callable must accept (object_type, action, livemode) and return a string. ```python DJSTRIPE_IDEMPOTENCY_KEY_CALLBACK = "myapp.billing.idempotency_key" ``` -------------------------------- ### Handle server response for PaymentIntent confirmation Source: https://github.com/dj-stripe/dj-stripe/blob/main/tests/apps/example/templates/payment_intent.html Handles the server's response after creating or confirming a PaymentIntent. If requires_action is true, uses Stripe.js to handle the required card action and then re-confirms the PaymentIntent with the server. On success, displays a success message. ```javascript function handleServerResponse(response) { if (response.error) { var errorElement = document.getElementById('card-errors'); errorElement.textContent = response.error; } else if (response.requires_action) { stripe.handleCardAction( response.payment_intent_client_secret ).then(function (result) { if (result.error) { var errorElement = document.getElementById('card-errors'); errorElement.textContent = result.error.message; } else { fetch("{% url 'djstripe_example:payment_intent' %}", { method: 'POST', headers: { "X-CSRFToken": getCookie("csrftoken"), "Accept": "application/json", "Content-Type": "application/json", "X-Requested-With": "XMLHttpRequest" }, body: JSON.stringify({payment_intent_id: result.paymentIntent.id}) }).then(function (confirmResult) { confirmResult.json().then(function (json) { handleServerResponse(json) }) }); } }); } else { document.getElementById('success-message').innerHTML = 'Success!!'; } } ``` -------------------------------- ### Configure Stripe API keys in Django settings Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/api_keys.md Define Stripe API keys in Django settings, typically from environment variables. STRIPE_LIVE_MODE switches between the test and live secret keys. A single STRIPE_SECRET_KEY takes precedence over these regardless of STRIPE_LIVE_MODE. ```python STRIPE_TEST_SECRET_KEY = os.environ.get("STRIPE_TEST_SECRET_KEY", "") STRIPE_LIVE_SECRET_KEY = os.environ.get("STRIPE_LIVE_SECRET_KEY", "") # Switches between the test and live secret keys above. STRIPE_LIVE_MODE = False ``` -------------------------------- ### Sync Stripe API data with sync_from_stripe_data Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/manually_syncing_with_stripe.md Syncs data from a Stripe API call into a dj-stripe model using sync_from_stripe_data. Related objects referenced by the data are fetched and synced recursively. If you don't pass api_key, dj-stripe falls back to the secret key from your settings. ```python import stripe from djstripe.models import Product stripe_product = stripe.Product.create( name="Premium plan", api_key="sk_test_...", ) # Returns the dj-stripe Product instance, created or updated from the data. product = Product.sync_from_stripe_data(stripe_product) ``` -------------------------------- ### Change default payment method with stripe.Customer.modify Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/managing_subscriptions.md Changes the default payment method for a customer by modifying the Stripe customer object and syncing the result back to the local database. Requires the Stripe Python library and the djstripe Customer model. ```python import stripe from djstripe.models import Customer stripe_customer = stripe.Customer.modify( customer.id, invoice_settings={"default_payment_method": payment_method.id}, api_key=customer.default_api_key, ) Customer.sync_from_stripe_data(stripe_customer) ``` -------------------------------- ### Reprocess events with djstripe_process_events Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/manually_syncing_with_stripe.md Manually reprocess events with djstripe_process_events. By default processes all events, but options can limit the events processed. Note the Stripe API documents a limitation where events are only guaranteed to be available for 30 days. ```bash # all events ./manage.py djstripe_process_events # failed events (events with pending webhooks or where all webhook delivery attempts failed) ./manage.py djstripe_process_events --failed # filter by event type (all payment_intent events in this example) ./manage.py djstripe_process_events --type payment_intent.* # specific events by ID ./manage.py djstripe_process_events --ids evt_foo evt_bar # more output for debugging processing failures ./manage.py djstripe_process_events -v 2 ``` -------------------------------- ### Cancel subscription with at_period_end Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/managing_subscriptions.md Cancels a subscription immediately by default; passing at_period_end=True keeps it active until the current period ends. Subscriptions scheduled this way are returned by Subscription.objects.scheduled_for_cancellation(). To undo, call subscription.update(cancel_at_period_end=False). ```python subscription.cancel(at_period_end=True) ``` -------------------------------- ### Query customer subscriptions, invoices, and charges via ORM Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/customers.md Stripe data is mirrored into Django models, so you can query a customer's related objects through the ORM. ```python customer.subscriptions.all() customer.invoices.all() customer.charges.all() ``` -------------------------------- ### Update subscription with items and proration_behavior Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/managing_subscriptions.md Updates an active subscription by changing the price or quantity on an existing item with proration behavior, or pauses collection. The subscription object is obtained from the customer's active subscriptions and the update method accepts any argument the Stripe update subscription endpoint takes. ```python subscription = customer.subscriptions.active().first() # Change quantity or price on the existing item subscription.update( items=[{"id": subscription.items.first().id, "price": new_price.id}], proration_behavior="create_prorations", ) # Pause collection subscription.update(pause_collection={"behavior": "void"}) ``` -------------------------------- ### Stripe SDK Order AttributeError Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/changes/2_7_x.md Error message shown when using dj-stripe 2.7.3 with a Stripe SDK version 5.0.0 or higher, due to Stripe dropping support for the Order model. ```python AttributeError: module 'stripe' has no attribute 'Order' ``` -------------------------------- ### Detach payment method with PaymentMethod.detach Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/managing_subscriptions.md Detaches a payment method from a customer. After detachment, the payment method can no longer be charged and is unlinked from the customer locally. ```python payment_method = customer.payment_methods.get(id="pm_...") payment_method.detach() ``` -------------------------------- ### Clear expired idempotency keys Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/usage/idempotency.md Removes expired idempotency key rows from the database. Stripe honors a key for 24 hours, so run this command periodically to clean up stale entries. ```bash python manage.py djstripe_clear_expired_idempotency_keys ``` -------------------------------- ### Fix ImportError by removing both jsonfield packages Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/changes/2_x.md If you already upgraded and hit the ImportError, run this command to remove both jsonfield and jsonfield2, then reinstall dj-stripe 2.2.0 or newer. This resolves the conflict where pip uninstall jsonfield removes jsonfield2's module. ```bash # remove both jsonfield packages before reinstall to fix ImportError: pip uninstall jsonfield jsonfield2 -y && pip install "dj-stripe>=2.2.0" ``` -------------------------------- ### Fix ImportError by removing both jsonfield packages and reinstalling dj-stripe 2.3.0 Source: https://github.com/dj-stripe/dj-stripe/blob/main/docs/changes/2_x.md Run this to fix the ImportError if you have already upgraded and hit 'ImportError: cannot import name JSONField from jsonfield'. It removes both jsonfield packages before reinstalling dj-stripe 2.3.0. ```bash pip uninstall jsonfield jsonfield2 -y && pip install "dj-stripe>=2.3.0" ```