最新消息:20190717 VPS服务器:Vultr新加坡,WordPress主题:大前端D8,统一介绍入口:关于

[记录]用Python版微信SDK wechat-sdk去给微信公众号创建菜单

Python crifan 1549浏览 0评论

之前已经:

[已解决]Flask中如何获取微信POST发送过来的body的数据

了,然后现在去尝试创建菜单

自定义菜单创建接口 – 微信公众平台开发者文档

然后用代码:

@app.route(‘/create_menu’, methods=[‘GET’, ‘POST’])
def create_menu():
    menu_info = {
        ‘button’: [
            {
                ‘type’: ‘click’,
                ‘name’: ‘今日歌曲’,
                ‘key’: ‘GET_TODAY_EVENTS’
            },
            {
                ‘type’: ‘view’,
                ‘name’: ‘我的活动’,
                ‘url’: ‘http://hd.webonn.com/’
            }
        ]
    }
    app.logger.debug(‘menu_info=%s’, menu_info)
    menuResp = wechat.create_menu(menu_info)
    app.logger.debug(‘menuResp=%s’, menuResp)
    return menuResp

去访问:

http://hd.webonn.com/create_menu

显示出错:

但是log显示是OK的:

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:60]:
menu_info={‘button’: [{‘type’: ‘click’, ‘name’: ‘\xe4\xbb\x8a\xe6\x97\xa5\xe6\xad\x8c\xe6\x9b\xb2’, ‘key’: ‘GET_TODAY_EVENTS’}, {‘url’: ‘http://hd.webonn.com/’, ‘type’: ‘view’, ‘name’: ‘\xe6\x88\x91\xe7\x9a\x84\xe6\xb4\xbb\xe5\x8a\xa8’}]}

<div–<——————————————————————————

<div–<——————————————————————————

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:62]:
menuResp={u’errcode’: 0, u’errmsg’: u’ok’}

再去写:

@app.route(‘/get_menu’, methods=[‘GET’])
def get_menu():
    respDict = wechat.get_menu()
    app.logger.debug(‘respDict=%s’, respDict)
    menuJson = respDict[‘menu’]
    app.logger.debug(‘menuJson=%s’, menuJson)
    return app.make_response(menuJson)

http://hd.webonn.com/get_menu

log:

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:47]:
respDict={u’menu’: {u’button’: [{u’type’: u’click’, u’name’: u’\u4eca\u65e5\u6b4c\u66f2′, u’key’: u’GET_TODAY_EVENTS’, u’sub_button’: []}, {u’url’: u’http://hd.webonn.com/’, u’type’: u’view’, u’name’: u’\u6211\u7684\u6d3b\u52a8′, u’sub_button’: []}]}}

<div–<——————————————————————————

<div–<——————————————————————————

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:49]:
menuJson={u’button’: [{u’type’: u’click’, u’name’: u’\u4eca\u65e5\u6b4c\u66f2′, u’key’: u’GET_TODAY_EVENTS’, u’sub_button’: []}, {u’url’: u’http://hd.webonn.com/’, u’type’: u’view’, u’name’: u’\u6211\u7684\u6d3b\u52a8′, u’sub_button’: []}]}

<div–<——————————————————————————

[2016-08-20 14:57:22 +0000] [12253] [ERROR] Error handling request /get_menu
Traceback (most recent call last):
  File "/root/Envs/SIPEvents/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 135, in handle
    self.handle_request(listener, req, client, addr)
  File "/root/Envs/SIPEvents/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 176, in handle_request
    respiter = self.wsgi(environ, resp.start_response)
  File "/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py", line 2000, in __call__
    return self.wsgi_app(environ, start_response)
  File "/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py", line 1991, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py", line 1567, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py", line 1988, in wsgi_app
    response = self.full_dispatch_request()
  File "/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py", line 1641, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py", line 1544, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py", line 1639, in full_dispatch_request
    rv = self.dispatch_request()
  File "/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py", line 1625, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/usr/share/nginx/html/SIPEvents/wechat_auth.py", line 50, in get_menu
    return app.make_response(menuJson)
  File "/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py", line 1746, in make_response
    rv = self.response_class.force_type(rv, request.environ)
  File "/root/Envs/SIPEvents/lib/python2.7/site-packages/werkzeug/wrappers.py", line 847, in force_type
    response = BaseResponse(*_run_wsgi_app(response, environ))
  File "/root/Envs/SIPEvents/lib/python2.7/site-packages/werkzeug/wrappers.py", line 57, in _run_wsgi_app
    return _run_wsgi_app(*args)
  File "/root/Envs/SIPEvents/lib/python2.7/site-packages/werkzeug/test.py", line 871, in run_wsgi_app
    app_rv = app(environ, start_response)
TypeError: ‘dict’ object is not callable

 换成:

import json
@app.route(‘/get_menu’, methods=[‘GET’])
def get_menu():
    respDict = wechat.get_menu()
    app.logger.debug(‘respDict=%s’, respDict)
    menuJson = respDict[‘menu’]
    app.logger.debug(‘menuJson=%s’, menuJson)
    menuJsonStr = json.dumps(menuJson, indent=2)
    app.logger.debug(‘menuJsonStr=%s’, menuJsonStr)
    return app.make_response(menuJsonStr)

效果:

log:

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:49]:
respDict={u’menu’: {u’button’: [{u’type’: u’click’, u’name’: u’\u4eca\u65e5\u6b4c\u66f2′, u’key’: u’GET_TODAY_EVENTS’, u’sub_button’: []}, {u’url’: u’http://hd.webonn.com/’, u’type’: u’view’, u’name’: u’\u6211\u7684\u6d3b\u52a8′, u’sub_button’: []}]}}

<div–<——————————————————————————

<div–<——————————————————————————

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:51]:
menuJson={u’button’: [{u’type’: u’click’, u’name’: u’\u4eca\u65e5\u6b4c\u66f2′, u’key’: u’GET_TODAY_EVENTS’, u’sub_button’: []}, {u’url’: u’http://hd.webonn.com/’, u’type’: u’view’, u’name’: u’\u6211\u7684\u6d3b\u52a8′, u’sub_button’: []}]}

<div–<——————————————————————————

<div–<——————————————————————————

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:53]:
menuJsonStr={
  "button": [
    {
      "type": "click", 
      "name": "\u4eca\u65e5\u6b4c\u66f2", 
      "key": "GET_TODAY_EVENTS", 
      "sub_button": []
    }, 
    {
      "url": "http://hd.webonn.com/", 
      "type": "view", 
      "name": "\u6211\u7684\u6d3b\u52a8", 
      "sub_button": []
    }
  ]
}

然后去关注了微信公众号的用户端,看看效果:

微信公众号的底部已经出现了对应的菜单了。

-》后来把 今日歌曲 换成了 今日活动

然后对于,点击:

今日活动

则,由于暂时不支持具体的逻辑处理,返回:

Not Support type of POST

效果:

log是:

(SIPEvents) ➜  SIPEvents gunicorn -w 4 -b 127.0.0.1:8080 wechat_auth:app
[2016-08-20 15:17:23 +0000] [12596] [INFO] Starting gunicorn 19.6.0
[2016-08-20 15:17:23 +0000] [12596] [INFO] Listening at: http://127.0.0.1:8080 (12596)
[2016-08-20 15:17:23 +0000] [12596] [INFO] Using worker: sync
[2016-08-20 15:17:23 +0000] [12601] [INFO] Booting worker with pid: 12601
[2016-08-20 15:17:23 +0000] [12602] [INFO] Booting worker with pid: 12602
[2016-08-20 15:17:23 +0000] [12607] [INFO] Booting worker with pid: 12607
[2016-08-20 15:17:23 +0000] [12608] [INFO] Booting worker with pid: 12608

<div–<——————————————————————————

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:101]:
signature=5e4ba18d9314cd247ac8a225458634e298095db8, timestamp=1471677448, nonce=345938065, echostr=

<div–<——————————————————————————

tmp_list= [‘sipevents’, u’1471677448′, u’345938065′]
after sort: tmp_list= [u’1471677448′, u’345938065′, ‘sipevents’]
tmp_str= 1471677448345938065sipevents
tmp_str_encoded= 1471677448345938065sipevents
tmp_str_sha1= <sha1 HASH object @ 0x7f0a2bc0c210>
tmp_str_hexdigest= 5e4ba18d9314cd247ac8a225458634e298095db8
signature= 5e4ba18d9314cd247ac8a225458634e298095db8
signature OK

<div–<——————————————————————————

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:105]:
wechat check_signature OK

<div–<——————————————————————————

<div–<——————————————————————————

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:113]:
requestMethod=POST

<div–<——————————————————————————

<div–<——————————————————————————

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:116]:
requestData=<xml><ToUserName><![CDATA[gh_ac090a9873a8]]></ToUserName>
<FromUserName><![CDATA[oswjmv4X0cCXcfkIwjoDfCkeTVVY]]></FromUserName>
<CreateTime>1471677448</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[CLICK]]></Event>
<EventKey><![CDATA[GET_TODAY_EVENTS]]></EventKey>
</xml>

<div–<——————————————————————————

<div–<——————————————————————————

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:123]:
requestArgs=ImmutableMultiDict([(‘nonce’, u’345938065′), (‘timestamp’, u’1471677448′), (‘signature’, u’5e4ba18d9314cd247ac8a225458634e298095db8′), (‘openid’, u’oswjmv4X0cCXcfkIwjoDfCkeTVVY’)])

<div–<——————————————————————————

data= <xml><ToUserName><![CDATA[gh_ac090a9873a8]]></ToUserName>
<FromUserName><![CDATA[oswjmv4X0cCXcfkIwjoDfCkeTVVY]]></FromUserName>
<CreateTime>1471677448</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[CLICK]]></Event>
<EventKey><![CDATA[GET_TODAY_EVENTS]]></EventKey>
</xml>
self.conf.encrypt_mode= normal

<div–<——————————————————————————

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:135]:
parse post body data OK

<div–<——————————————————————————

<div–<——————————————————————————

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:148]:
messageId=0, messageTarget=gh_ac090a9873a8, messageSource=oswjmv4X0cCXcfkIwjoDfCkeTVVY, messageTime=1471677448, messageType=click, messageRaw=<xml><ToUserName><![CDATA[gh_ac090a9873a8]]></ToUserName>
<FromUserName><![CDATA[oswjmv4X0cCXcfkIwjoDfCkeTVVY]]></FromUserName>
<CreateTime>1471677448</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[CLICK]]></Event>
<EventKey><![CDATA[GET_TODAY_EVENTS]]></EventKey>
</xml>

<div–<——————————————————————————

<div–<——————————————————————————

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:158]:
respStr=Not Support type of POST

<div–<——————————————————————————

text response= 
    <xml>
    <ToUserName><![CDATA[oswjmv4X0cCXcfkIwjoDfCkeTVVY]]></ToUserName>
    <FromUserName><![CDATA[gh_ac090a9873a8]]></FromUserName>
    <CreateTime>1471677448</CreateTime>
    <MsgType><![CDATA[text]]></MsgType>
    <Content><![CDATA[Not Support type of POST]]></Content>
    </xml>

点击:

我的活动

则跳转到页面:

http://hd.webonn.com/

最后,稍微整理一下,完整的代码为:

#!/usr/bin/python
# -*- coding: UTF-8 -*-  
from flask import Flask, g, request, make_response
from wechat_sdk import WechatConf
from wechat_sdk import WechatBasic
# from wechat_sdk import WechatBaseCrypto
# from wechat_sdk.lib.crypto.crypto import WechatBaseCrypto
# from wechat_sdk.lib.crypto import WechatBaseCrypto
from wechat_sdk.exceptions import ParseError
from wechat_sdk.messages import (
    TextMessage,
    ImageMessage,
    VoiceMessage,
    VideoMessage,
    ShortVideoMessage,
    LinkMessage,
    LocationMessage,
    EventMessage,
    UnknownMessage
)
import json
app = Flask(__name__)
app.debug=True
wechatConf = WechatConf(
    token=’yyyy’, 
    appid=’gggg’,
    appsecret=’lll’,
    # 可选项:normal/compatible/safe,分别对应于 明文/兼容/安全 模式
    #encrypt_mode=’safe’,
    encrypt_mode=’normal’,
    # 如果传入此值则必须保证同时传入 token, appid
    encoding_aes_key=’b7NCPES6jQOsoooooEoSf2cLpt’
)
wechat = WechatBasic(conf=wechatConf)
# wechat = WechatBaseCrypto(conf=wechatConf)
@app.route("/")
def hello():
    return "欢迎来到金鸡日历!"
def jsonToStr(jsonDict, indent=2):
    return json.dumps(jsonDict, indent=2)
@app.route(‘/get_menu’, methods=[‘GET’])
def get_menu():
    respDict = wechat.get_menu()
    app.logger.debug(‘respDict=%s’, respDict)
    menuJson = respDict[‘menu’]
    app.logger.debug(‘menuJson=%s’, menuJson)
    menuJsonStr = jsonToStr(menuJson)
    app.logger.debug(‘menuJsonStr=%s’, menuJsonStr)
    return app.make_response(menuJsonStr)
@app.route(‘/create_menu’, methods=[‘GET’, ‘POST’])
def create_menu():
    menu_info = {
        ‘button’: [
            {
                ‘type’: ‘click’,
                ‘name’: ‘今日活动’,
                ‘key’: ‘GET_TODAY_EVENTS’
            },
            {
                ‘type’: ‘view’,
                ‘name’: ‘我的活动’,
                ‘url’: ‘http://hd.webonn.com/’
            }
        ]
    }
    app.logger.debug(‘menu_info=%s’, menu_info)
    respDict = wechat.create_menu(menu_info)
    app.logger.debug(‘respDict=%s’, respDict)
    menuJsonStr = jsonToStr(menu_info)
    app.logger.debug(‘menuJsonStr=%s’, menuJsonStr)
    if respDict[‘errcode’] == 0 :
        createdMenuOkStr = "create ok for menu: %s" % (menuJsonStr)
        app.logger.debug(‘createdMenuOkStr=%s’, createdMenuOkStr)
        return app.make_response(createdMenuOkStr)
    else:
        failCreateMenuStr = "Fail to create menu: %s" % (menuJsonStr)
        app.logger.debug(‘failCreateMenuStr=%s’, failCreateMenuStr)
        failCreateMenuStr += ", reason: %s" % (respDict[‘errmsg’])
        app.logger.debug(‘failCreateMenuStr=%s’, failCreateMenuStr)
        return app.make_response(failCreateMenuStr)
@app.route(‘/wechat_auth’, methods=[‘GET’, ‘POST’])
def wechat_auth():
    signature = request.args.get(‘signature’, ”)
    timestamp = request.args.get(‘timestamp’, ”)
    nonce = request.args.get(‘nonce’, ”)
    echostr = request.args.get(‘echostr’, ”)
    app.logger.debug(‘signature=%s, timestamp=%s, nonce=%s, echostr=%s’, signature, timestamp, nonce, echostr)
    if wechat.check_signature(signature, timestamp, nonce):
    # if wechat.check_signature(signature, timestamp, nonce, echostr):
        app.logger.debug("wechat check_signature OK")
        if request.method == ‘GET’ :
            respStr = echostr
            app.logger.debug(‘respStr=%s’, respStr)
            return make_response(respStr)
        else :
            # for POST
            requestMethod = request.method
            app.logger.debug(‘requestMethod=%s’, requestMethod)
            # requestMethod=POST
            requestData = request.data
            app.logger.debug(‘requestData=%s’, requestData)
            # <xml>
            #     <ToUserName><![CDATA[gh_ac090a9873a8]]></ToUserName>
            #     <Encrypt><![CDATA[6PBVvYed+IuFgEa4BuDeOaNwM3KLqv6uoWqQcSCY+SidbN2VBjWL+N88kp0GU2BvLXyzlvbGGOxvJnFIDRQCDAgBUBhk3YQMWJmR+bB3D5phuVEIFo1MoknxB4xsIi3wVQunlyljyFl43TCwCxIvBVxXeHsKSzYOxhFGL+2ZmelLp46WJRaNrrh8yLl2eK1pRCR09QAoNZISLUszfzlr4N9t4nnl8ZuQpYqEdWt4bH8xsqTRPd91TG6hSio/o46G9Ow2QA16j7l4q9HXV2fZEIdlSJma4Jepl7N9jBDwrjd4zi4MXwsJpQ0KBI3Q1LBojlipt8wk1xzuVzmyidkHzvDtfIa22ZTvEu4MDYdYa8BXRYk1EtGpW0eDCiF/NLOyQzJsFM1T7jGsxjrKUIcYPmLFbNW8qZEIEDkAhahbVCI=]]></Encrypt>
            # </xml>
            requestArgs = request.args
            app.logger.debug(‘requestArgs=%s’, requestArgs)
            # requestArgs=ImmutableMultiDict([(‘nonce’, u’1438950245′), (‘openid’, u’oswjmv4X0cCXcfkIwjoDfCkeTVVY’), (‘signature’, u’cb962992182efd9f94f09560b893b20106408e49′), (‘timestamp’, u’1471573757′), (‘encrypt_type’, u’aes’), (‘msg_signature’, u’dc3336e6f85053f3563802f4e7b5398e3930d017′)])
            try:
                # decryptedReqData = wechat.conf.crypto.decrypt_message(requestData, signature, timestamp, nonce)
                # app.logger.debug(‘decryptedReqData=%s’, decryptedReqData)
                # app.logger.debug(‘decrypt post body data OK’)
                # wechat.parse_data(decryptedReqData)
                #wechat.parse_data(decryptedReqData, signature, timestamp, nonce)
                #wechat.parse_data(requestData, signature, timestamp, nonce)
                wechat.parse_data(requestData)
                app.logger.debug(‘parse post body data OK’)
            except ParseError:
                respStr = "parse post body failed"
                app.logger.debug(respStr)
                return wechat.response_text(respStr)
            messageId = wechat.message.id          # 对应于 XML 中的 MsgId
            messageTarget = wechat.message.target  # 对应于 XML 中的 ToUserName
            messageSource = wechat.message.source  # 对应于 XML 中的 FromUserName
            messageTime = wechat.message.time      # 对应于 XML 中的 CreateTime
            messageType = wechat.message.type      # 对应于 XML 中的 MsgType
            messageRaw = wechat.message.raw        # 原始 XML 文本,方便进行其他分析
            app.logger.debug(‘messageId=%s, messageTarget=%s, messageSource=%s, messageTime=%s, messageType=%s, messageRaw=%s’, messageId, messageTarget, messageSource, messageTime, messageType, messageRaw)
            if isinstance(wechat.message, TextMessage) :
                msgContent = wechat.message.content
                app.logger.debug(‘type(msgContent)=%s, msgContent=%s’, type(msgContent), msgContent)
                resonseTextContent = wechat.response_text(msgContent)
                app.logger.debug(‘resonseTextContent=%s’, resonseTextContent)
                return app.make_response(resonseTextContent)
            else :
                respStr = "Not Support type of POST"
                app.logger.debug(‘respStr=%s’, respStr)
                return wechat.response_text(respStr)
    else :
        app.logger.debug("wechat check_signature wrong")
        return wechat.response_text("wechat auth failed")
if __name__ == ‘__main__’:
    app.run(debug=True)

转载请注明:在路上 » [记录]用Python版微信SDK wechat-sdk去给微信公众号创建菜单

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
58 queries in 0.145 seconds, using 18.92MB memory