diff --git a/stripe_checkout/settings/base.py b/stripe_checkout/settings/base.py index 798ff849cc3e700f73d5bf6918cd4b1ef22cc3cc..10bf54f2e047202171b4ee9a9ca2ea0b9f7fa2e9 100644 --- a/stripe_checkout/settings/base.py +++ b/stripe_checkout/settings/base.py @@ -136,3 +136,5 @@ LOGGING = { "level": "INFO", }, } + +STRIPE_WEBHOOK_ALLOWED_IPS = ["*"] diff --git a/stripe_checkout/settings/prod.py b/stripe_checkout/settings/prod.py index d4f7007b270d61ed96881ab80b7650ed0de2d819..6edf70c831cfbfaa7276a1904e6723c48394f38d 100644 --- a/stripe_checkout/settings/prod.py +++ b/stripe_checkout/settings/prod.py @@ -30,3 +30,18 @@ STATIC_URL = os.getenv("STATIC_URL", "/static/") # noqa: F405 STATIC_ROOT = os.getenv("STATIC_ROOT", "staticfiles/") # noqa: F405 SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True + +STRIPE_WEBHOOK_ALLOWED_IPS = [ + "3.18.12.63", + "3.130.192.231", + "13.235.14.237", + "13.235.122.149", + "18.211.135.69", + "35.154.171.200", + "52.15.183.38", + "54.88.130.119", + "54.88.130.237", + "54.187.174.169", + "54.187.205.235", + "54.187.216.72", +] diff --git a/stripe_checkout/stripe_checkout/visit_views.py b/stripe_checkout/stripe_checkout/visit_views.py index 01824d72f4630ea8550e434e5e6014c96769e6bb..463e715864f494348820b9e444483e308f83a0d8 100644 --- a/stripe_checkout/stripe_checkout/visit_views.py +++ b/stripe_checkout/stripe_checkout/visit_views.py @@ -1,16 +1,17 @@ import logging from typing import Union + +import requests from django import forms from django.http import Http404, HttpResponse from django.shortcuts import redirect, render -from django.views.decorators.http import require_POST, require_http_methods, require_GET from django.views.decorators.csrf import csrf_exempt -import requests +from django.views.decorators.http import require_GET, require_http_methods, require_POST -from stripe_checkout.stripe_checkout.shopping_cart import ShoppingCart - -from .models import Event, ExchangeRate from . import stripe +from .models import Event, ExchangeRate +from .shopping_cart import ShoppingCart +from .utils import whitelist_ips from .visit import VisitorAPI logger = logging.getLogger(__name__) @@ -67,7 +68,7 @@ def create_invoice(visitor, data): customer, purchase_order=data["purchase_order"], vat_number=data["vat_number"], - gbp_exchange_rate=exchange_rate + gbp_exchange_rate=exchange_rate, ) @@ -88,6 +89,7 @@ def checkout_success(request, visitor_id): @csrf_exempt @require_POST +@whitelist_ips(by_setting="STRIPE_WEBHOOK_ALLOWED_IPS") def stripe_event(request): try: event = stripe.read_event(request.body, request.headers.get("Stripe-Signature")) diff --git a/test/test_visit.py b/test/test_visit.py index 7767f5583aab0f6a661ea17d485c67dab98ad04f..535a93d969f115157e260432a486b8d9cd7ee308 100644 --- a/test/test_visit.py +++ b/test/test_visit.py @@ -43,7 +43,7 @@ def test_exchange_rate(client, default_exchange_rate, visitor_id): call_args = stripe.Invoice.create.call_args[1] assert call_args["custom_fields"][0] == { "name": "GBP VAT Rate", - "value": "GBP 1.60 (0.8000)" , + "value": "GBP 1.60 (0.8000)", } @@ -62,3 +62,23 @@ def test_event_webhook(client): ) assert rv.status_code == 200 assert Event.objects.exists() + + +@responses.activate +@pytest.mark.django_db +def test_event_webhook_disallowed_when_not_whitelisted(client, settings): + settings.STRIPE_WEBHOOK_ALLOWED_IPS = ["1.1.1.1"] + with patch( + "stripe.Webhook.construct_event", side_effect=lambda b, *_: json.loads(b) + ): + rv = client.post( + "/stripe-event-webhook/", + json.dumps( + { + "type": "invoice.paid", + "data": {"object": {"id": "stripe-invoice"}}, + } + ), + content_type="application/json", + ) + assert rv.status_code == 403