微信公众号开发被动回复用户消息,回复内容Content使用了"\n"换行符还是没有换行

时间:2024-02-24 13:22:52

使用语言和框架:本人后端开发使用的Python的DRF(Django REST framework)框架

 

需求:在微信公众号开发时,需要实现自动回复,即被关注回复、收到消息回复、关键词回复

 

发现问题:按照微信公众号的开发文档,在写完逻辑代码后,测试时发现:Content回复的消息内容,使用"\n",预期效果应该是文字内容有换行效果,微信的文档也说明了换行可以使用"\n"换行符,但是实际测试的效果是没有换行。这个问题纠结了一天,最后发现是我响应给微信服务器的数据类型错误了。

 

问题分析过程:微信公众号文档里的原话(当用户发送消息给公众号时(或某些特定的用户操作引发的事件推送时),会产生一个POST请求,开发者可以在响应包(Get)中返回特定XML结构,来对该消息进行响应(现支持回复文本、图片、图文、语音、视频、音乐)。严格来说,发送被动响应消息其实并不是一种接口,而是对微信服务器发过来消息的一次回复。)

文档已经说得很明白,在接收到微信的Post请求后,处理完具体的业务逻辑后,要对微信服务器作响应回复,如果需要特定的回复则返回特定XML结构,如果不作任何处理推荐方式直接回复success

 

根本原因:因为使用的是DRF框架,自然而然的在响应的时候使用了rest_framework.response.Response,但其实响应给微信服务器的是一个响应体数据,而我使用Response响应给微信服务器的是响应对象

 

解决方案:使用django.http.HttpResponse响应返回数据

代码演示:

# 使用的是类视图APIView
def post(self, request):
    """接收微信Post数据,并处理"""
    data = request.body.decode("utf-8")
    doc = xmltodict.parse(data)  # 解析xml数据
    to_user = doc["xml"]["ToUserName"]  # 开发者微信号
    from_user = doc["xml"]["FromUserName"]  # 发送方帐号(一个OpenID)

    if doc["xml"]["MsgType"] == "text":  # 文本消息处理
        dict = {
            "ToUserName" = from_user
            "FromUserName" = to_user
            "CreateTime" = int(time.time())
            "Content" = "欢迎关注公众号!\n新人好礼等你来拿"
        }
        # 返回回复文本消息特定XML结构
        xml_form = """
        <xml>
        <ToUserName><![CDATA[{ToUserName}]]></ToUserName>
        <FromUserName><![CDATA[{FromUserName}]]></FromUserName>
        <CreateTime>{CreateTime}</CreateTime>
        <MsgType><![CDATA[text]]></MsgType>
        <Content><![CDATA[{Content}]]></Content>
        </xml>
        """
        # 根据判断是否返回回复文本消息还是不作任何处理
        if ....:
            # 回复文本消息
            return HttpResponse(xml_form.format(**dict))
        else:
            # 不作任何处理
            return HttpResponse("success")

 

django.http.HttpResponse和rest_framework.response.Response的区别:

1、HttpResponse

可以使用django.http.HttpResponse来构造响应对象,HttpResponse对象由开发人员创建,适用于返回图片,视频,音频等二进制文件

 

格式:HttpResponse(content=响应体, content_type=响应体数据MIME类型, status=状态码)

MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型:

text/html html
text/plain 普通文本
application/json json


响应头设置: 可以直接将HttpResponse对象当做字典进行响应头键值对的设置

response = HttpResponse(\'响应内容\')
response[\'Itcast\'] = \'Python\' # 自定义响应头Itcast, 值为Python

 

2、Response

REST framework提供的一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。

 

格式:Response(data, status=None, headers=None, content_type=None)

参数说明:

data: 字典类型,为响应准备的序列化处理后的数据;
status: 状态码,默认200;
headers: 用于存放响应头信息的字典;
content_type: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。

 

补充:JsonResponse对象是HttpResponse 的常用子类

帮助我们将数据转换为json字符串,再返回给客户端,会设置响应头 Content-Type 为 application/json

from django.http import JsonResponse

def resp(request):
      return JsonResponse({\'city\': \'beijing\', \'subject\': \'python\'})


当包含的内容中包含中文时,会返回该中文对应的编码,例如:

def resp(request):

      # 最终看到的效果是: {"name": "\u5f20\u4e09"}
     response = JsonResponse({"name":"张三"})
     return response
解决:JsonResponse(data, json_dumps_params={\'ensure_ascii\':False})

JsonResponse可以接收非字典数据,需要指定 safe=False