Payload Signature
For your security, OpenPay signs every webhook request sent to your endpoints. The signature is included in the request's signature-digest
header, and it follows the format
t=TIMESTAMP,SIGNATURE_VERSION=SIGNATURE[,SIGNATURE_VERSION=SIGNATURE_2,SIGNATURE_VERSION=SIGNATURE_3,...]
-
TIMESTAMP
is an integer representing the POSIX timestamp (seconds since epoch) of the event creation. -
SIGNATURE_VERSION
isv1
right now, but this could change in the future. -
SIGNATURE
is an HMAC SHA256 digest of the stringTIMESTAMP.DATA
-
DATA
is the value of thedata
key in the payload.
-
-
There is one signature for every available secret, but you should only need to verify at least one.
Getting the secretCopied!
The signatures are generated using automatically-generated secret keys. You can obtain the secret used to sign payloads for your webhook from the Dashboard.
-
On the Developers page (where you created your webhook), click on the webhook that you want to get the secret for.
-
On the webhook’s details page, click the three dots to the right of the webhook name. Select Show Secret from the menu that appears.
-
You can now copy the secret to clipboard.
If you need to get the secret programmatically (using something like cURL), do the following:
-
Obtain an OpenPay API token with the
ADMIN
role. (Webhook secrets can only be accessed using tokens of this role.) -
Access the webhook secret from the API:
curl -X GET \
-H 'Authorization: Bearer SECRET_KEY' \
https://connto.getopenpay.com/webhook-endpoints/webhook_endpoint_XXXXXXXXXXX/reveal_secret
# JSON response:
# {
# "id": "webhook_endpoint_XXXXXXXXXXX",
# // ...
# "secret": "whsec_XXXXXXXXXXXXXXXX"
# }
Verifying a signatureCopied!
To verify a signature, you will need to generate your own signature using the same data as above and compare the two digests.
from getopenpay.client import ApiKeys, OpenPayClient
from getopenpay.utils.webhook_utils import InvalidSignatureError
client = OpenPayClient(ApiKeys(...))
secret_key = 'whsec_XXXXXXXXXXXXXXXX'
event_data = "{\"id\": \"event_dev_abcdefg12345678\", \"object\": \"event\", ...}"
signature_digest = request.headers.get('signature-digest', None)
try:
client.webhook_utils.validate_payload(
event_data=event_data,
signature_digest=signature_digest,
secret=secret_key
)
except InvalidSignatureError: # or ValueError
# ...
import hmac
from hashlib import sha256
secret_key = 'whsec_XXXXXXXXXXXXXXXX'
content = f'{TIMESTAMP}.{DATA}'
signature = hmac.new(
secret_key.encode('utf-8'),
content.encode('utf-8'),
digestmod=sha256
).hexdigest()
expected_signature = request.headers.get('signature-digest')
is_valid = hmac.compare_digest(signature, expected_signature)