def validate(self, api_key=None): """ The original contents of the Event message must be confirmed by refetching it and comparing the fetched data with the original data. This function makes an API call to Stripe to redownload the Event data and returns whether or not it matches the WebhookEventTrigger data. """ local_data = self.json_body if "id" not in local_data or "livemode" not in local_data: return False if self.is_test_event: logger.info("Test webhook received: {}".format(local_data)) return False if djstripe_settings.WEBHOOK_VALIDATION is None: # validation disabled return True elif ( djstripe_settings.WEBHOOK_VALIDATION == "verify_signature" and djstripe_settings.WEBHOOK_SECRET ): # HTTP headers are case-insensitive, but we store them as a dict. headers = CaseInsensitiveMapping(self.headers) try: stripe.WebhookSignature.verify_header( self.body, headers.get("stripe-signature"), djstripe_settings.WEBHOOK_SECRET, djstripe_settings.WEBHOOK_TOLERANCE, ) except stripe.error.SignatureVerificationError: return False else: return True livemode = local_data["livemode"] api_key = api_key or djstripe_settings.get_default_api_key(livemode) # Retrieve the event using the api_version specified in itself with stripe_temporary_api_version(local_data["api_version"], validate=False): remote_data = Event.stripe_class.retrieve( id=local_data["id"], api_key=api_key ) return local_data["data"] == remote_data["data"]
def validate( self, api_key: str = None, secret: str = djstripe_settings.WEBHOOK_SECRET, tolerance: int = djstripe_settings.WEBHOOK_TOLERANCE, validation_method=djstripe_settings.WEBHOOK_VALIDATION, ): """ The original contents of the Event message must be confirmed by refetching it and comparing the fetched data with the original data. This function makes an API call to Stripe to redownload the Event data and returns whether or not it matches the WebhookEventTrigger data. """ local_data = self.json_body if "id" not in local_data or "livemode" not in local_data: logger.error( '"id" not in json body or "livemode" not in json body(%s)', local_data) return False if self.is_test_event: logger.info( "Test webhook received and discarded: {}".format(local_data)) return False if validation_method is None: # validation disabled warnings.warn("WEBHOOK VALIDATION is disabled.") return True elif validation_method == "verify_signature": if not secret: raise ValueError( "Cannot verify event signature without a secret") # HTTP headers are case-insensitive, but we store them as a dict. headers = CaseInsensitiveMapping(self.headers) signature = headers.get("stripe-signature") local_cli_signing_secret = headers.get("x-djstripe-webhook-secret") try: # check if the x-djstripe-webhook-secret Custom Header exists if local_cli_signing_secret: # Set Endpoint Signing Secret to the output of Stripe CLI # for signature verification secret = local_cli_signing_secret stripe.WebhookSignature.verify_header(self.body, signature, secret, tolerance) except stripe.error.SignatureVerificationError: logger.exception("Failed to verify header") return False else: return True livemode = local_data["livemode"] api_key = api_key or djstripe_settings.get_default_api_key(livemode) # Retrieve the event using the api_version specified in itself with stripe_temporary_api_version(local_data["api_version"], validate=False): remote_data = Event.stripe_class.retrieve(id=local_data["id"], api_key=api_key) return local_data["data"] == remote_data["data"]