Created
July 5, 2017 02:10
-
-
Save henryyang42/f313a2d9f9fbbe0ee7a09bffb92650b1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import hashlib | |
import time | |
import xmltodict | |
from flask import Flask, request | |
app = Flask(__name__) | |
WECHAT_TOKEN = "wechat_token" | |
# Check if the message XML is valid, this simple bot handles TEXT messages only! | |
# To learn more about the supported types of messages and how to implement them, see: | |
# Common Messages: http://admin.wechat.com/wiki/index.php?title=Common_Messages | |
# Event Messages: http://admin.wechat.com/wiki/index.php?title=Event-based_Messages | |
# Speech Recognition Messages: | |
# http://admin.wechat.com/wiki/index.php?title=Speech_Recognition_Messages | |
def validate_message(message): | |
return ( | |
message is not None and | |
message['xml'] != None and | |
message['xml']['MsgType'] != None and | |
message['xml']['MsgType'] == 'text' and | |
message['xml']['Content'] != None | |
) | |
# Format the reply according to the WeChat XML format for synchronous replies, | |
# see: http://admin.wechat.com/wiki/index.php?title=Callback_Messages | |
def format_message(original_message, content): | |
return ( | |
"<xml>" | |
"<ToUserName><![CDATA[%s]]></ToUserName>" | |
"<FromUserName><![CDATA[%s]]></FromUserName>" | |
"<CreateTime>%s</CreateTime>" | |
"<MsgType><![CDATA[text]]></MsgType>" | |
"<Content><![CDATA[%s]]></Content>" | |
"</xml>" | |
) % ( | |
# From and To must be inverted in replies ;) | |
original_message['xml']['FromUserName'], | |
original_message['xml']['ToUserName'], # Same as above! | |
time.gmtime(), | |
content | |
) | |
def verify_backend(request): | |
# Get the parameters from the query string | |
signature = request.args.get('signature') | |
timestamp = request.args.get('timestamp') | |
nonce = request.args.get('nonce') | |
echostr = request.args.get('echostr') | |
# Compute the signature (note that the shared token is used too) | |
verification_elements = [WECHAT_TOKEN, timestamp, nonce] | |
verification_elements.sort() | |
verification_string = "".join(verification_elements) | |
verification_string = hashlib.sha1( | |
verification_string.encode('utf-8')).hexdigest() | |
# If the signature is correct, output the same "echostr" provided by | |
# the WeChat server as a parameter | |
if signature == verification_string: | |
return echostr | |
else: | |
return "" | |
@app.route('/wechat', methods=['GET', 'POST']) | |
def echo_server(): | |
error = None | |
if request.method == 'GET': | |
# The WeChat server will issue a GET request in order to verify the chatbot backend server upon configuration. | |
return verify_backend(request) | |
elif request.method == 'POST': | |
# Messages will be POSTed from the WeChat server to the chatbot backend server, | |
# see: http://admin.wechat.com/wiki/index.php?title=Common_Messages | |
message = xmltodict.parse(request.data) | |
# If the message is valid, echo it back to the user or send an error message. | |
# Some kind of response, even an empty one, is *REQUIRED* by WeChat | |
# within the mandatory timeout limit of 5 seconds. | |
# Otherwise, the user will see an error in the app. | |
if validate_message(message): | |
reply = "You typed: %s" % (message['xml']['Content']) | |
return format_message(message, reply) | |
else: | |
return "Message was sent in a wrong format." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment