最新消息:20210917 已从crifan.com换到crifan.org

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

Flask crifan 6870浏览 0评论

参考:

2. 官方接口 – wechat-python-sdk

wechatpy/app.py at master · jxtech/wechatpy

用代码:

#!/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.exceptions import ParseError
app = Flask(__name__)
app.debug=True
wechatConf = WechatConf(
    token=’sipevents’, 
    appid=’xxx’,
    appsecret=’yyy’,
    # 可选项:normal/compatible/safe,分别对应于 明文/兼容/安全 模式
    encrypt_mode=’safe’,
    # 如果传入此值则必须保证同时传入 token, appid
    encoding_aes_key=’b7Nzzzzzzzzz2cLpt’
)
wechat = WechatBasic(conf=wechatConf)
@app.route("/")
def hello():
    return "Hello SIPEvents!"
@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):
        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+xxxxxxEu4MDYdYa8BXRYk1EtGpW0eDCiF/NLOyQzJsFM1T7jGsxjrKUIcYPmLFbNW8qZEIEDkAhahbVCI=]]></Encrypt>
            # </xml>
            # body_text = request.args.get(‘body’, ”)
            # app.logger.debug(‘body_text=%s’, body_text)
            try:
                wechat.parse_data(requestData)
                app.logger.debug(‘parse post body data OK’)
            except ParseError:
                app.logger.debug(‘parse body failed’)
                return make_response("current not support wechat auth POST")
            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(‘msgContent=%s’, msgContent)
                return make_response(msgContent)
            else :
                respStr = "Not Support type of POST"
                app.logger.debug(‘respStr=%s’, respStr)
                return make_response(respStr)
    else :
        app.logger.debug("wechat check_signature wrong")
        return make_response("wechat auth failed")
if __name__ == ‘__main__’:
    app.run(debug=True)

去在Flask下运行

结果解析body失败:

(SIPEvents) ➜  SIPEvents gunicorn -w 4 -b 127.0.0.1:8080 wechat_auth:app
[2016-08-19 10:17:10 +0000] [29169] [INFO] Starting gunicorn 19.6.0
[2016-08-19 10:17:10 +0000] [29169] [INFO] Listening at: http://127.0.0.1:8080 (29169)
[2016-08-19 10:17:10 +0000] [29169] [INFO] Using worker: sync
[2016-08-19 10:17:10 +0000] [29174] [INFO] Booting worker with pid: 29174
[2016-08-19 10:17:10 +0000] [29175] [INFO] Booting worker with pid: 29175
[2016-08-19 10:17:10 +0000] [29178] [INFO] Booting worker with pid: 29178
[2016-08-19 10:17:10 +0000] [29179] [INFO] Booting worker with pid: 29179

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

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:34]:
signature=3b1370a65463c9cc9fc964f36ae05f6778cd2d18, timestamp=1471573034, nonce=2021984687, echostr=

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

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

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

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

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

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

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

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

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:47]:
requestData=<xml>
    <ToUserName><![CDATA[gh_ac090a9873a8]]></ToUserName>
    <Encrypt><![CDATA[3W7QxxxxxPHu0opmD6YAaw0fOKTcfzs/n4/Zd0ZShsb5Z1+S7qi1P0D1g==]]></Encrypt>
</xml>

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

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

DEBUG in wechat_auth [/usr/share/nginx/html/SIPEvents/wechat_auth.py:60]:
parse body failed

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

看起来像是:

在Flask中,

没搞懂如何获取POST的body内容

好像不是

requestData = request.data

搜:

Flask 获取 微信 Request  body

python – Flask如何获取Post传过来的参数? – SegmentFault

Quickstart — Flask Documentation (0.11)

-》这个之前就看过了。

API — Flask Documentation (0.11)

里面有很多参数:

Incoming Request Data

class flask.Request(environpopulate_request=Trueshallow=False)

The request object used by default in Flask. Remembers the matched endpoint and view arguments.

It is what ends up as request. If you want to replace the request object used you can subclass this and set request_class to your subclass.

The request object is a Request subclass and provides all of the attributes Werkzeug defines plus a few Flask specific ones.

form

MultiDict with the parsed form data from POST or PUT requests. Please keep in mind that file uploads will not end up here, but instead in the filesattribute.

args

MultiDict with the parsed contents of the query string. (The part in the URL after the question mark).

values

CombinedMultiDict with the contents of both form and args.

cookies

dict with the contents of all cookies transmitted with the request.

stream

If the incoming form data was not encoded with a known mimetype the data is stored unmodified in this stream for consumption. Most of the time it is a better idea to use data which will give you that data as a string. The stream only returns the data once.

headers

The incoming request headers as a dictionary like object.

data

Contains the incoming request data as string in case it came with a mimetype Flask does not handle.

files

MultiDict with files uploaded as part of a POST or PUT request. Each file is stored as FileStorage object. It basically behaves like a standard file object you know from Python, with the difference that it also has a save() function that can store the file on the filesystem.

environ

The underlying WSGI environment.

method

The current request method (POSTGET etc.)

path

full_path

script_root

url

base_url

url_root

Provides different ways to look at the current IRI. Imagine your application is listening on the following application root:

http://www.example.com/myapplication

And a user requests the following URI:

http://www.example.com/myapplication/%CF%80/page.html?x=y

In this case the values of the above mentioned attributes would be the following:

path
u’/π/page.html’
full_path
u’/π/page.html?x=y’
script_root
u’/myapplication’
base_url
url
url_root

is_xhr

True if the request was triggered via a JavaScript XMLHttpRequest. This only works with libraries that support the X-Requested-With header and set it to XMLHttpRequest. Libraries that do that are prototype, jQuery and Mochikit and probably some more.

blueprint

The name of the current blueprint

endpoint

The endpoint that matched the request. This in combination with view_argscan be used to reconstruct the same or a modified URL. If an exception happened when matching, this will be None.

get_json(force=Falsesilent=Falsecache=True)

Parses the incoming JSON request data and returns it. By default this function will return None if the mimetype is not application/json but this can be overridden by the force parameter. If parsing fails theon_json_loading_failed() method on the request object will be invoked.

Parameters:
  • force – if set to True the mimetype is ignored.
  • silent – if set to True this method will fail silently and return None.
  • cache – if set to True the parsed JSON data is remembered on the request.

is_json

Indicates if this request is JSON or not. By default a request is considered to include JSON data if the mimetype is application/json or application/*+json.

New in version 0.11.

json

If the mimetype is application/json this will contain the parsed JSON data. Otherwise this will be None.

The get_json() method should be used instead.

max_content_length

Read-only view of the MAX_CONTENT_LENGTH config key.

module

The name of the current module if the request was dispatched to an actual module. This is deprecated functionality, use blueprints instead.

on_json_loading_failed(e)

Called if decoding of the JSON data failed. The return value of this method is used by get_json() when an error occurred. The default implementation just raises a BadRequest exception.

Changed in version 0.10: Removed buggy previous behavior of generating a random JSON response. If you want that behavior back you can trivially add it by subclassing.

New in version 0.8.

routing_exception = None

If matching the URL failed, this is the exception that will be raised / was raised as part of the request handling. This is usually a NotFound exception or something similar.

url_rule = None

The internal URL rule that matched the request. This can be useful to inspect which methods are allowed for the URL from a before/after handler (request.url_rule.methods) etc.

New in version 0.6.

view_args = None

A dict of view arguments that matched the request. If an exception happened when matching, this will be None.

自己去试试:

            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′)])

-》

对于post的data,貌似还是需要自己去从:

requestData=<xml>
    <ToUserName><![CDATA[gh_ac090a9873a8]]></ToUserName>
    <Encrypt><![CDATA[XPWdOuDgWuyo7OkHmyE1+4168B1moD2BX55vjX9m1y2JuwLMOCvFh27iRq6vhDPIiOpLBmnHg3YTTg71qx02euJBLrMC7YjGyh18Qwr4NYt32Wnmdr4igCSg529yZBaqydkuXXZVGc2TawRN9hZ/1JxKR7vNFwB+XwIkPP/9vI45CQZym8cX6BGueOKyX4KIDqwAEa9NdEk35STgdHWrde/hcILi3pLKfLSvMHZ51/jMF1/N91zMvJWlcswII8MMgQ695Nl4TbtjKMia/TpSK4FI3e+N+mrQnfoZNA5W5inO3FaVYgZV593D6x8thOXEyfNOZajStsyImutaiJ3pPcJh08lIBc8J6Y1jGTCuER/ixZKRxYJjq3WAcPB/oR90ERbmggmstG6c3UIW3+mftQM2OaQqF3nWwnM+fxvRsFw=]]></Encrypt>
</xml>

提取对应的加了密的Encrypt原文?

如何获取 微信 Request  body

快速上手 — wechat-python-sdk 0.5.9 文档

作者举例的代码:

# -*- coding: utf-8 -*-
from wechat_sdk import WechatBasic
# 下面这些变量均假设已由 Request 中提取完毕
token = ‘WECHAT_TOKEN’  # 你的微信 Token
signature = ‘f24649c76c3f3d81b23c033da95a7a30cb7629cc’  # Request 中 GET 参数 signature
timestamp = ‘1406799650’  # Request 中 GET 参数 timestamp
nonce = ‘1505845280’  # Request 中 GET 参数 nonce
# 用户的请求内容 (Request 中的 Body)
# 请更改 body_text 的内容来测试下面代码的执行情况
body_text = """
<xml>
<ToUserName><![CDATA[touser]]></ToUserName>
<FromUserName><![CDATA[fromuser]]></FromUserName>
<CreateTime>1405994593</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[wechat]]></Content>
<MsgId>6038700799783131222</MsgId>
</xml>
"""
# 实例化 wechat
wechat = WechatBasic(token=token)
# 对签名进行校验
if wechat.check_signature(signature=signature, timestamp=timestamp, nonce=nonce):
    # 对 XML 数据进行解析 (必要, 否则不可执行 response_text, response_image 等操作)
    wechat.parse_data(body_text)
    # 获得解析结果, message 为 WechatMessage 对象 (wechat_sdk.messages中定义)
    message = wechat.get_message()
    response = None
    if message.type == ‘text’:
        if message.content == ‘wechat’:
            response = wechat.response_text(u’^_^’)
        else:
            response = wechat.response_text(u’文字’)
    elif message.type == ‘image’:
        response = wechat.response_text(u’图片’)
    else:
        response = wechat.response_text(u’未知’)
    # 现在直接将 response 变量内容直接作为 HTTP Response 响应微信服务器即可,此处为了演示返回内容,直接将响应进行输出
    print response

中,body_text,就是我此处的

但是时没有加密的。。。

有很多字段:ToUserName,FromUserName,Content等

而我此处时加了密的:

只有两个字段ToUserName,Encrypt

看来需要自己去解密 解码?

wechat-sdk 0.4.2 : Python Package Index

[GOLANG]获取远程POST来的XML数据(微信公众平台)_葱烧烙饼_新浪博客

看wechat的sdk的源码:

wechat-python-sdk/basic.py at master · doraemonext/wechat-python-sdk

好像当是加密了safe模式时,必须要提供msg_signature,timestamp,nonce

???

那去试试:

[未解决]用Python的微信SDK wechat_sdk中parse_data时出错:ValidateSignatureError

然后加密的方式没有成功。

后来换成明文,可以了:

[已解决]尝试使用明文模式去测试微信的Python版的SDK wechat-sdk

转载请注明:在路上 » [已解决]Flask中如何获取微信POST发送过来的body的数据

发表我的评论
取消评论

表情

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

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
92 queries in 0.193 seconds, using 23.60MB memory