How to send message to Viber bot with Python?

Edited due to update. You are getting an error on verify_signature.

The definition of verify_signature:

def verify_signature(self, request_data, signature):
    return signature == self._calculate_message_signature(request_data)

You are sending there a request.headers.get('X-Viber-Content-Signature') as a `signature. So the solution for you is to check the result of __calculate_message_signature(request_data)

requiest_data = request.get_data() in your case.

The definition of _calculate_message_signature is:

    def _calculate_message_signature(self, message):
        return hmac.new(
            bytes(self._bot_configuration.auth_token.encode('ascii')),
            msg=message,
            digestmod=hashlib.sha256)\
.hexdigest()

I would check your auth_token which is used in self._bot_configuration.auth_token.encode('ascii'). Does it include non-ascii characters? If yes then you have the reason. (as example)

Try to compare the result of:

hmac.new(bytes(self._bot_configuration.auth_token.encode('ascii')),
                msg=request.get_data(),
                digestmod=hashlib.sha256).hexdigest()

to:

request.headers.get('X-Viber-Content-Signature') which is different and that is why you are getting forbidden message.


You are getting the 403 error for 2 reasons. To simulate a webhook request from Viber, you must send the X-Viber-Content-Signature header. Also this value must be a SHA256 hash computed using the auth token and the webhook payload as described in their API docs under Callbacks.

I believe you have 2 choices here. If you want to just verify that your code receives the webhook properly, you can just comment out the verify_signature() lines temporarily. Validation of webhook requests is not required by Viber (or any webhook source). Typically a developer would assume that a library like the one provided by Viber tests their code properly, so usually there is no need to test their functionality again. You could also consider mocking the function, as that is very simple in this case.

If you really want to test Viber's signature validation, then you will need to implement the 2 reasons I mentioned first. Here's basically what you need to do in your test webhook sending code. Note that I only included the new code you need below, please merge into your other test code.

import json
import hmac
import hashlib

# Compute SHA256 hex digest signature using auth token and payload.
auth_token = 'xxx-xxx-xxx'
signature = hmac.new(
    key=auth_token.encode('ascii'),
    msg=data.encode('ascii'),
    digestmod=hashlib.sha256
).hexdigest()

# Send test webhook request with computed signature in header.
response = requests.post(
    webhook_url,
    data=json.dumps(data),
    headers={
        'X-Viber-Content-Signature': signature,
        'Content-Type': 'application/json'
    },
    verify='E:\\Docs\\learn_py\\viberbot\\certificate.pem'
)

Note that @tukan pointed out the _calculate_message_signature() function in the viber-bot-python repo, which shows how the signature is computed.