diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/README.md b/README.md index 6d3cca3..7048ce7 100644 --- a/README.md +++ b/README.md @@ -51,3 +51,29 @@ api.dosomething() abelzhu@tencent.com # + +# 关于使用 +设置环境变量 +```shell +export WX_TOKEN="xxxx" +export WX_EncodingAESKey="xxxx" +export WX_CORPID="xxxx" + +vim ~/.pip/pip.conf +[global] +index-url = http://mirrors.aliyun.com/pypi/simple/ +[install] +trusted-host = http://mirrors.aliyun.com/pypi/simple/ + +cd weworkapi_python +python3 -m venv .venv +source .venv/bin/activate +pip3 install flask pycryptodome + +cd callback +python3 app.py + +``` + + + diff --git a/callback/app.py b/callback/app.py new file mode 100644 index 0000000..ab77a31 --- /dev/null +++ b/callback/app.py @@ -0,0 +1,92 @@ +# -*- encoding:utf-8 -*- +from flask import abort, request +from flask import Flask +from xml.dom.minidom import parseString +import _thread +import time +import os +import sys + +from WXBizMsgCrypt3 import WXBizMsgCrypt + +app = Flask(__name__) + +# 对应步骤4中接受消息回调模式中的URL,如域名是'www.example.com' 那么在步骤4中填入的url就为"http://www.example.com/hook_path" +@app.route('/hook_path', methods=['GET', 'POST']) +def douban(): + if request.method == 'GET': + echo_str = signature(request, 0) + return (echo_str) + elif request.method == 'POST': + echo_str = signature2(request, 0) + return (echo_str) + +@app.route('/echo', methods=['GET', 'POST']) +def echo(): + return "echo hello world" + + +# export WX_TOKEN="xxxx" +# export WX_EncodingAESKey="xxxx" +# export WX_CORPID="xxxx" +qy_api = [ + WXBizMsgCrypt(os.getenv('WX_TOKEN'), os.getenv('WX_EncodingAESKey'), os.getenv('WX_CORPID')), +] # 对应接受消息回调模式中的token,EncodingAESKey 和 企业信息中的企业id + + +# 开启消息接受模式时验证接口连通性 +def signature(request, i): + msg_signature = request.args.get('msg_signature', '') + timestamp = request.args.get('timestamp', '') + nonce = request.args.get('nonce', '') + echo_str = request.args.get('echostr', '') + ret, sEchoStr = qy_api[i].VerifyURL(msg_signature, timestamp, nonce, echo_str) + if (ret != 0): + print("ERR: VerifyURL ret: " + str(ret)) + return ("failed") + else: + return (sEchoStr) + + +# 实际接受消息 +def signature2(request, i): + msg_signature = request.args.get('msg_signature', '') + timestamp = request.args.get('timestamp', '') + nonce = request.args.get('nonce', '') + data = request.data.decode('utf-8') + ret, sMsg = qy_api[i].DecryptMsg(data, msg_signature, timestamp, nonce) + if (ret != 0): + print("ERR: DecryptMsg ret: " + str(ret)) + return ("failed") + else: + with open("/var/log/qywx.log", 'a+') as f: # 消息接收日志 + doc = parseString(sMsg) + collection = doc.documentElement + name_xml = collection.getElementsByTagName("FromUserName") + msg_xml = collection.getElementsByTagName("Content") + type_xml = collection.getElementsByTagName("MsgType") + pic_xml = collection.getElementsByTagName("PicUrl") + msg = "" + name = "" + msg_type = type_xml[0].childNodes[0].data + if msg_type == "text": # 文本消息 + name = name_xml[0].childNodes[0].data # 发送者id + msg = msg_xml[0].childNodes[0].data # 发送的消息内容 + f.write(time.strftime('[%Y-%m-%d %H:%M:%S]') + "[ch%d] %s:%s\n" % (i, name, msg)) + _thread.start_new_thread(os.system, ( + "python3 command.py '%s' '%s' '%d' '%d'" % (name, msg, i, 0),)) # 此处将消息进行外部业务处理 + + elif msg_type == "image": # 图片消息 + name = name_xml[0].childNodes[0].data + pic_url = pic_xml[0].childNodes[0].data + f.write(time.strftime('[%Y-%m-%d %H:%M:%S]') + "[ch%d] %s:图片消息\n" % (i, name)) + _thread.start_new_thread(os.system, ( + "python3 command.py '%s' '%s' '%d' '%d'" % (name, pic_url, i, 1),)) # 此处将消息进行外部业务处理 + + f.close() + + return ("ok") + + +if __name__ == '__main__': + app.run("0.0.0.0", 8888) # 本地监听端口,可自定义 \ No newline at end of file