billing: Enforce the Stripe API version is in sync with billing system.

This commit is contained in:
Vishnu KS 2021-09-07 15:53:27 +00:00 committed by Tim Abbott
parent 6c06858e02
commit 585d98d5a9
3 changed files with 28 additions and 0 deletions

View File

@ -25,6 +25,7 @@ from corporate.lib.stripe import (
DEFAULT_INVOICE_DAYS_UNTIL_DUE, DEFAULT_INVOICE_DAYS_UNTIL_DUE,
MAX_INVOICED_LICENSES, MAX_INVOICED_LICENSES,
MIN_INVOICED_LICENSES, MIN_INVOICED_LICENSES,
STRIPE_API_VERSION,
BillingError, BillingError,
InvalidBillingSchedule, InvalidBillingSchedule,
InvalidTier, InvalidTier,
@ -496,6 +497,7 @@ class StripeTestCase(ZulipTestCase):
"object": "event", "object": "event",
"data": {"object": stripe_session_dict}, "data": {"object": stripe_session_dict},
"type": "checkout.session.completed", "type": "checkout.session.completed",
"api_version": STRIPE_API_VERSION,
} }
response = self.client_post( response = self.client_post(
@ -3846,9 +3848,27 @@ class StripeWebhookEndpointTest(ZulipTestCase):
) )
self.assertEqual(result.status_code, 400) self.assertEqual(result.status_code, 400)
def test_stripe_webhook_endpoint_invalid_api_version(self) -> None:
event_data = {
"id": "stripe_event_id",
"api_version": "1991-02-20",
"type": "event_type",
"data": {"object": {"object": "checkout.session", "id": "stripe_session_id"}},
}
expected_error_message = fr"Mismatch between billing system Stripe API version({STRIPE_API_VERSION}) and Stripe webhook event API version(1991-02-20)."
with self.assertLogs("corporate.stripe", "ERROR") as error_log:
self.client_post(
"/stripe/webhook/",
event_data,
content_type="application/json",
)
self.assertEqual(error_log.output, [f"ERROR:corporate.stripe:{expected_error_message}"])
def test_stripe_webhook_for_session_completed_event(self) -> None: def test_stripe_webhook_for_session_completed_event(self) -> None:
valid_session_event_data = { valid_session_event_data = {
"id": "stripe_event_id", "id": "stripe_event_id",
"api_version": STRIPE_API_VERSION,
"type": "checkout.session.completed", "type": "checkout.session.completed",
"data": {"object": {"object": "checkout.session", "id": "stripe_session_id"}}, "data": {"object": {"object": "checkout.session", "id": "stripe_session_id"}},
} }
@ -3906,6 +3926,7 @@ class StripeWebhookEndpointTest(ZulipTestCase):
valid_session_event_data = { valid_session_event_data = {
"id": stripe_event_id, "id": stripe_event_id,
"type": event_type, "type": event_type,
"api_version": STRIPE_API_VERSION,
"data": {"object": {"object": "payment_intent", "id": stripe_payment_intent_id}}, "data": {"object": {"object": "payment_intent", "id": stripe_payment_intent_id}},
} }

View File

@ -7,6 +7,7 @@ from django.contrib.contenttypes.models import ContentType
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
from corporate.lib.stripe import STRIPE_API_VERSION
from corporate.lib.stripe_event_handler import ( from corporate.lib.stripe_event_handler import (
handle_checkout_session_completed_event, handle_checkout_session_completed_event,
handle_payment_intent_payment_failed_event, handle_payment_intent_payment_failed_event,
@ -42,6 +43,11 @@ def stripe_webhook(request: HttpRequest) -> HttpResponse:
except Exception: except Exception:
return HttpResponse(status=400) return HttpResponse(status=400)
if stripe_event.api_version != STRIPE_API_VERSION:
error_message = f"Mismatch between billing system Stripe API version({STRIPE_API_VERSION}) and Stripe webhook event API version({stripe_event.api_version})."
billing_logger.error(error_message)
return HttpResponse(status=400)
if stripe_event.type not in [ if stripe_event.type not in [
"checkout.session.completed", "checkout.session.completed",
"payment_intent.succeeded", "payment_intent.succeeded",

View File

@ -320,6 +320,7 @@ class EventData:
class Event: class Event:
id: str id: str
api_version: str
type: EventTypes type: EventTypes
data: EventData data: EventData
@staticmethod @staticmethod