updates
This commit is contained in:
96
Backend/venv/lib/python3.12/site-packages/stripe/_webhook.py
Normal file
96
Backend/venv/lib/python3.12/site-packages/stripe/_webhook.py
Normal file
@@ -0,0 +1,96 @@
|
||||
import hmac
|
||||
import json
|
||||
import time
|
||||
from collections import OrderedDict
|
||||
from hashlib import sha256
|
||||
|
||||
# Used for global variables
|
||||
import stripe # noqa: IMP101
|
||||
from stripe._event import Event
|
||||
from stripe._util import secure_compare
|
||||
from stripe._error import SignatureVerificationError
|
||||
from stripe._api_requestor import _APIRequestor
|
||||
|
||||
|
||||
class Webhook(object):
|
||||
DEFAULT_TOLERANCE = 300
|
||||
|
||||
@staticmethod
|
||||
def construct_event(
|
||||
payload, sig_header, secret, tolerance=DEFAULT_TOLERANCE, api_key=None
|
||||
):
|
||||
if hasattr(payload, "decode"):
|
||||
payload = payload.decode("utf-8")
|
||||
|
||||
WebhookSignature.verify_header(payload, sig_header, secret, tolerance)
|
||||
|
||||
data = json.loads(payload, object_pairs_hook=OrderedDict)
|
||||
event = Event._construct_from(
|
||||
values=data,
|
||||
requestor=_APIRequestor._global_with_options(
|
||||
api_key=api_key or stripe.api_key
|
||||
),
|
||||
api_mode="V1",
|
||||
)
|
||||
|
||||
return event
|
||||
|
||||
|
||||
class WebhookSignature(object):
|
||||
EXPECTED_SCHEME = "v1"
|
||||
|
||||
@staticmethod
|
||||
def _compute_signature(payload, secret):
|
||||
mac = hmac.new(
|
||||
secret.encode("utf-8"),
|
||||
msg=payload.encode("utf-8"),
|
||||
digestmod=sha256,
|
||||
)
|
||||
return mac.hexdigest()
|
||||
|
||||
@staticmethod
|
||||
def _get_timestamp_and_signatures(header, scheme):
|
||||
list_items = [i.split("=", 2) for i in header.split(",")]
|
||||
timestamp = int([i[1] for i in list_items if i[0] == "t"][0])
|
||||
signatures = [i[1] for i in list_items if i[0] == scheme]
|
||||
return timestamp, signatures
|
||||
|
||||
@classmethod
|
||||
def verify_header(cls, payload, header, secret, tolerance=None):
|
||||
try:
|
||||
timestamp, signatures = cls._get_timestamp_and_signatures(
|
||||
header, cls.EXPECTED_SCHEME
|
||||
)
|
||||
except Exception:
|
||||
raise SignatureVerificationError(
|
||||
"Unable to extract timestamp and signatures from header",
|
||||
header,
|
||||
payload,
|
||||
)
|
||||
|
||||
if not signatures:
|
||||
raise SignatureVerificationError(
|
||||
"No signatures found with expected scheme "
|
||||
"%s" % cls.EXPECTED_SCHEME,
|
||||
header,
|
||||
payload,
|
||||
)
|
||||
|
||||
signed_payload = "%d.%s" % (timestamp, payload)
|
||||
expected_sig = cls._compute_signature(signed_payload, secret)
|
||||
if not any(secure_compare(expected_sig, s) for s in signatures):
|
||||
raise SignatureVerificationError(
|
||||
"No signatures found matching the expected signature for "
|
||||
"payload",
|
||||
header,
|
||||
payload,
|
||||
)
|
||||
|
||||
if tolerance and timestamp < time.time() - tolerance:
|
||||
raise SignatureVerificationError(
|
||||
"Timestamp outside the tolerance zone (%d)" % timestamp,
|
||||
header,
|
||||
payload,
|
||||
)
|
||||
|
||||
return True
|
||||
Reference in New Issue
Block a user