微信公众号接python/django服务器验证token问题

微信公众号,想要接python/django的服务器,卡在了第一步,验证token上,按照文档,获取signature 、timestamp 、nonce 后,验证是否一致,一致的话返回echostr,

def test(request):

    signature = request.GET.get("signature","")
    timestamp = request.GET.get("timestamp","")
    nonce = request.GET.get("nonce","")
    echostr=request.GET.get("echostr","")
    result={}
    result['signature']=signature
    result['timestamp']=timestamp
    result['nonce']=nonce
    result['echostr']=echostr
    tmpArr = [TOKEN, timestamp, nonce]
    tmpArr.sort()
    tmpStr = "".join(tmpArr) 
    tmpStr = hashlib.sha1(tmpStr.encode()).hexdigest() 
    if tmpStr == signature: 
        return echostr

    else: 
        return False

测试结果反馈
AttributeError: 'bool' object has no attribute 'get'

后来一步一步排查,发现,只要把最后return 改成return httpresponse或者return jsonresponse,他就可以正常反馈结果(用本地服务在浏览器直接输入请求连接做测试),但这样一来,在微信公众号的认证token中又没法认证,因为返回的是httpresponse/jsonresponse

怎么解决?

    if tmpStr == signature: 
        return httpresponse(echostr)


    else: 
        return httpresponse(echostr)

该答案引用ChatGPT的部分内容:您可以尝试在返回 HttpResponse 或 JsonResponse 前,先将它们的实例化对象存储在变量中,并将该变量的值传递给后续的 if 和 else 语句,例如:

from django.http import HttpResponse, JsonResponse

def test(request):
    signature = request.GET.get("signature","")
    timestamp = request.GET.get("timestamp","")
    nonce = request.GET.get("nonce","")
    echostr = request.GET.get("echostr","")

    tmpArr = [TOKEN, timestamp, nonce]
    tmpArr.sort()
    tmpStr = "".join(tmpArr) 
    tmpStr = hashlib.sha1(tmpStr.encode()).hexdigest() 

    if tmpStr == signature: 
        response = HttpResponse(echostr)
    else: 
        response = HttpResponse(False)
    
    return response

在上面的代码中,我们先实例化了 HttpResponse 对象并将其存储在 response 变量中。然后,我们将 response 变量传递给后续的 if 和 else 语句,以便根据条件进行相应的操作。

请注意,在此示例中,我们使用 HttpResponse 对象将 echostr 或 False 返回给微信公众号。如果您需要返回 JSON 格式的数据,请使用 JsonResponse 替换 HttpResponse。

希望这可以帮助您解决问题。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
您遇到的问题是因为在第一次验证微信公众号时,需要返回的是一个echostr字符串,而您将返回值设为了False

在您的代码中,可以将最后的return语句修改为以下形式:

return HttpResponse(echostr, content_type="text/plain")

这样就可以返回echostr字符串了。同时,注意需要导入HttpResponse类。

完整代码如下:

from django.http import HttpResponse

def test(request):

    signature = request.GET.get("signature","")
    timestamp = request.GET.get("timestamp","")
    nonce = request.GET.get("nonce","")
    echostr = request.GET.get("echostr","")
    tmpArr = [TOKEN, timestamp, nonce]
    tmpArr.sort()
    tmpStr = "".join(tmpArr) 
    tmpStr = hashlib.sha1(tmpStr.encode()).hexdigest() 
    if tmpStr == signature: 
        return HttpResponse(echostr, content_type="text/plain")
    else: 
        return HttpResponse("", content_type="text/plain")

此外,对于接收到的signaturetimestampnonce参数,建议也进行类型和合法性检查,以避免错误。
如果我的回答解决了您的问题,请采纳!

可以参考如下代码:

# -*- coding: cp936 -*-
#python 27
#xiaodeng



#获取微信access_token
#办法一:将该url直接填写到浏览器地址中可以获得access_token
url='https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wxc0f4d0ed1cb2f4e1&secret=c4d72d33cacf8c94845ac906ad60eed6'


#办法二
import urllib
url='https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential'#grant_type为固定值
data={'appid':'wxc0f4d0ed1cb2f4e1',
      'secret':'c4d72d33cacf8c94845ac906ad60eed6'}

data=urllib.urlencode(data)
html=urllib.urlopen(url,data)#<addinfourl at 34758208 whose fp = <socket._fileobject object at 0x0212F570>>
html= html.read()
print html
'''
{"access_token":"Isd_tm3QE8Kateyxjz_WEEXuerBZ0gnO6XwyjirZXY1umVIDqebi6GK2Zv2fv1hI7sXQfHXeaOa2A4XrOITwS5LnczFRXf4BbSnMdSRLKiwBQYgADASHP",
"expires_in":7200}  #expires_in,定义access_token有效时间,单位为秒
'''

引用chatGPT作答,问题在于,在签名验证成功后,该函数应该返回一个包含 echostr 值的普通字符串,但是你的代码中,你返回的是 httpresponse 或者 jsonresponse 对象,这些对象与预期的返回类型不兼容。

为了解决这个问题,你应该修改代码,返回一个普通字符串而不是一个HTTP响应对象。以下是一个例子:

from django.http import HttpResponse

def test(request):
    signature = request.GET.get("signature", "")
    timestamp = request.GET.get("timestamp", "")
    nonce = request.GET.get("nonce", "")
    echostr = request.GET.get("echostr", "")
    
    tmpArr = [TOKEN, timestamp, nonce]
    tmpArr.sort()
    tmpStr = "".join(tmpArr) 
    tmpStr = hashlib.sha1(tmpStr.encode()).hexdigest() 
    
    if tmpStr == signature: 
        return HttpResponse(echostr)
    else: 
        return HttpResponse("签名验证失败。")

在这个修改后的代码中,当签名验证成功时,该函数返回一个包含 echostr 值的 HttpResponse 对象。如果验证失败,则返回一个包含错误消息的 HttpResponse 对象。

请确保你的微信公众号服务器的URL已经正确配置,指向你Django应用程序中的 test 视图函数。

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^