How To Send Message To Viber Bot With Python?
I have following HTTPS server:
from flask import Flask, request, Response
from viberbot import Api
from viberbot.api.bot_configuration import BotConfiguration
from viberbot.api.messages import VideoMessage
from viberbot.api.messages.text_message import TextMessage
import logging
from viberbot.api.viber_requests import ViberConversationStartedRequest
from viberbot.api.viber_requests import ViberFailedRequest
from viberbot.api.viber_requests import ViberMessageRequest
from viberbot.api.viber_requests import ViberSubscribedRequest
from viberbot.api.viber_requests import ViberUnsubscribedRequest
logger = logging.getLogger(__name__)
app = Flask(__name__)
viber = Api(BotConfiguration(
name='PythonSampleBot',
avatar='http://www.clker.com/cliparts/3/m/v/Y/E/V/small-red-apple-hi.png',
auth_token='xxx-xxx-xxx'
))
@app.route('/', methods=['POST'])
def incoming():
logger.debug("received request. post data: {0}".format(request.get_data()))
# every viber message is signed, you can verify the signature using this method
if not viber.verify_signature(request.get_data(), request.headers.get('X-Viber-Content-Signature')):
return Response(status=403)
# this library supplies a simple way to receive a request object
viber_request = viber.parse_request(request.get_data())
if isinstance(viber_request, ViberMessageRequest):
message = viber_request.message
# lets echo back
viber.send_messages(viber_request.sender.id, [
message
])
elif isinstance(viber_request, ViberSubscribedRequest):
viber.send_messages(viber_request.get_user.id, [
TextMessage(text="thanks for subscribing!")
])
elif isinstance(viber_request, ViberFailedRequest):
logger.warn(
"client failed receiving message. failure: {0}".format(viber_request))
return Response(status=200)
def set_webhook(viber_bot):
viber_bot.set_webhook('https://xxx.xxx.xxx.xxx:4443')
logging.info("Web hook has been set")
if __name__ == "__main__":
context = ('certificate.pem', 'key.pem')
app.run(host='0.0.0.0', port=4443, debug=True, ssl_context=context)
and trying to send message:
import json
import requests
webhook_url = 'https://xxx.xxx.xxx.xxx:4443'
data = {
"receiver": "xxx-xxx-xxx",
"type": "text",
"text": "Hello world!"
}
response = requests.post(
webhook_url, data=json.dumps(data),
headers={'Content-Type': 'application/json'},
verify='E:\\Docs\\learn_py\\viberbot\\certificate.pem'
)
if response.status_code != 200:
raise ValueError(
'Request returned an error %s, the response is:\n%s'
% (response.status_code, response.text)
)
I'm getting 403 error
ValueError: Request returned an error 403, the response is:
UPDATE:
The 403 comes from:
if not viber.verify_signature(request.get_data(), request.headers.get('X-Viber-Content-Signature')):
return Response(status=403)
Answer
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.
Related Questions
- → What are the pluses/minuses of different ways to configure GPIOs on the Beaglebone Black?
- → Django, code inside <script> tag doesn't work in a template
- → React - Django webpack config with dynamic 'output'
- → GAE Python app - Does URL matter for SEO?
- → Put a Rendered Django Template in Json along with some other items
- → session disappears when request is sent from fetch
- → Python Shopify API output formatted datetime string in django template
- → Can't turn off Javascript using Selenium
- → WebDriver click() vs JavaScript click()
- → Shopify app: adding a new shipping address via webhook
- → Shopify + Python library: how to create new shipping address
- → shopify python api: how do add new assets to published theme?
- → Access 'HTTP_X_SHOPIFY_SHOP_API_CALL_LIMIT' with Python Shopify Module