阿里云+python+flask+ngnix零基础从零开始搭建微信公众号进行后台AI开发全套教程

您所在的位置:网站首页 云时政微信公众号 阿里云+python+flask+ngnix零基础从零开始搭建微信公众号进行后台AI开发全套教程

阿里云+python+flask+ngnix零基础从零开始搭建微信公众号进行后台AI开发全套教程

2024-07-16 02:10| 来源: 网络整理| 查看: 265

目录 一、微信公众号开发基础1.1 与公众号的消息会话1.2 与公众号内的网页交互1.2 搭建开发者环境1.2.1 配置nginx环境1.2.2 云服务器与微信服务器建立连接1.2.2.1 token与access_token1.2.2.2 建立连接 二、微信公众号部署AI对话机器人三. 公众号回复其他类型消息3.1 接口的概念3.2 使用接口进行开发3.2.1 实现元宵节猜灯谜 四.参考文献

一、微信公众号开发基础 1.1 与公众号的消息会话

在部署好一个微信公众号时,用户通过微信客户端向公众号发送文本消息并请求返回,这一过程实际上分为四个阶段: 1.用户向微信服务器发出请求 2.微信服务器向云服务器转发请求 3.云服务器接收请求并返回给云服务器响应消息 4.微信服务器再返回给用户回复消息 在这里插入图片描述

1.2 与公众号内的网页交互

公众号的网页交互与消息会话刚好不同,它基于以下四个过程: 1.用户向网页服务器发出请求 2.网页服务器向微信服务器转发请求寻求用户信息 3.微信服务器接收请求并返回给网页服务器用户信息 4.网页服务器再返回给用户网页资源

1.2 搭建开发者环境

开发者环境是指我们开发微信公众号的环境,与云服务器的运行环境相对应。微信官方为开发者提供了开发者文档,里面规定了开发微信公众号所使用的端口号(只能用80(http)和443(https)这两个,实际上微信公众号只支持80端口)。 按照开发者文档,我们首先需要在开发者环境下搭建开发环境:

1.2.1 配置nginx环境

nginx作为高性能的HTTP和反向代理web服务器,负责将每个用户账号从80端口跑到固定的端口,如从8001开始,8002,8003…以此类推。注意运行在哪个端口,微信服务器配置的URL对应的就是wechatXXXX。 首先在云服务器上安装nginx:

sudo apt-get install nginx

接下来在云服务器上打开/etc/nginx/sites-available, 使用vim编辑该目录下的default文件:

sudo vim /etc/nginx/sites-available/default

找到文件中的server部分,将

location / { XXXXX }

这一部分内容改为:

location /wechat8000 { proxy_pass_header Server; proxy_set_header Host $http_host; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_pass http://127.0.0.1:8000; }

修改后的default文件(去掉部分注释):

## # You should look at the following URL's in order to grasp a solid understanding # of Nginx configuration files in order to fully unleash the power of Nginx. # https://www.nginx.com/resources/wiki/start/ # https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/ # https://wiki.debian.org/Nginx/DirectoryStructure # # In most cases, administrators will remove this file from sites-enabled/ and # leave it as reference inside of sites-available where it will continue to be # updated by the nginx packaging team. # # This file will automatically load configuration files provided by other # applications, such as Drupal or Wordpress. These applications will be made # available underneath a path with that package name, such as /drupal8. # # Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. ## # Default server configuration # server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name _; location /wechat8000 {undefined proxy_pass_header Server; proxy_set_header Host $http_host; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_pass http://127.0.0.1:8000; } } # Virtual Host configuration for example.com # # You can move that to a different file under sites-available/ and symlink that # to sites-enabled/ to enable it. # #server { # listen 80; # listen [::]:80; # # server_name example.com; # # root /var/www/example.com; # index index.html; # # location / { # try_files $uri $uri/ =404; # } #} 1.2.2 云服务器与微信服务器建立连接 1.2.2.1 token与access_token

这是两个东西。 1.Token可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性,完全是云服务器与微信服务器建立连接时的验证工具,可以无限次使用。

2.access_token的意义在于拿到用户在第三方平台的唯一的标识,这样就可以用于获取用户的nickname,头像,邮箱等其他信息。

3.为了保证微信服务器与云服务器连接的安全,微信官方规定每2个小时(7200s)需要刷新一次access_token,同时为了防止因为开发者程序的bug导致微信服务器资源耗尽,规定单个微信公众号每日获取access_token的上限为2000次,对于运行正常的公众号完全可以24h无限制与用户进行消息交互。 4.access_token分为两个种类,一种是普通的access_token,另一种是网页授权access_token。多个不同的进程独立的去获取这种普通access_token,就会导致有些接口没办法正常地调用相关的微信接口,因此最好使用中控服务器专门负责刷新access_token。

1.2.2.2 建立连接

综前所述,我们需要在后端服务器上实现一个/wechat80XX的视图,基于这个视图就可以实现微信服务器和后端云服务器的通信:

接下来向服务器上传一个wechat.py文件,用于向微信服务器建立连接。上传方式可以是ftp,也可以是ssh远程传输(效果一样)。 wechat.py(记得修改token、填写APPID和APPSECRET):

# coding:utf-8 from flask import Flask, request, abort, render_template import hashlib import xmltodict import time import urllib.request as urllib2 import json # 微信的token令牌 WECHAT_TOKEN = '你的token' WECHAT_APPID = '你的APPID' WECHAT_APPSECRET = '你的APPSECRET' app = Flask(__name__) @app.route("/wechat8000", methods=["GET", "POST"]) def wechat(): """对接微信公众号服务器""" # 接收微信服务器发送的参数 signature = request.args.get("signature") timestamp = request.args.get("timestamp") nonce = request.args.get("nonce") # 校验参数 if not all([signature, timestamp, nonce]): abort(400) # 按照微信的流程进行计算签名 li = [WECHAT_TOKEN, timestamp, nonce] # 排序 li.sort() # 拼接字符串 tmp_str = "".join(li) # 进行sha1加密,得到正确的签名值 sign = hashlib.sha1(tmp_str.encode("utf-8")).hexdigest() # 将自己计算的签名值与请求的签名参数进行对比,如果相同,则证明请求来自微信 if signature != sign: # 表示请求不是微信发的 abort(403) else: # 表示是微信发送的请求 if requesthod == "GET": # 表示是第一次接入微信服务器的验证 echostr = request.args.get("echostr") if not echostr: abort(400) return echostr elif requesthod == "POST": # 表示是微信服务器转发消息过来 xml_str = request.data if not xml_str: abort(400) # 对xml字符串进行解析 xml_dict = xmltodict.parse(xml_str) xml_dict = xml_dict["xml"] # 提取消息类型 msg_type = xml_dict.get("MsgType") if msg_type == "text": # 表示发送的是文本消息 # 构造返回值,经由微信服务器回复给用户的消息内容 resp_dict = { "xml": { "ToUserName": xml_dict.get("FromUserName"), "FromUserName": xml_dict.get("ToUserName"), "CreateTime": int(time.time()), "MsgType": "text", "Content": xml_dict.get("Content") } } else: resp_dict = { "xml": { "ToUserName": xml_dict.get("FromUserName"), "FromUserName": xml_dict.get("ToUserName"), "CreateTime": int(time.time()), "MsgType": "text", "Content": "i love u" } } # 将字典转换成xml字符串 resp_xml_str = xmltodict.unparse(resp_dict) # 返回消息数据给微信服务器 return resp_xml_str @app.route('/wechat8000/index') def index(): """让用户通过微信访问的网页页面视图""" # 从微信服务器中拿取用户的资料数据 # 1. 拿取code参数 code = request.args.get("code") if not code: return "缺失code参数" # 2. 向微信服务器发送http请求,获取access_token url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code" \ % (WECHAT_APPID, WECHAT_APPSECRET, code) # 使用urllib2的urlopen方法发送请求 # 如果只传网址url参数,则默认使用http的get请求方式 response = urllib2.urlopen(url) # 获取响应体数据,微信返回的json数据 json_str = response.read() resp_dict = json.loads(json_str) # 提取access_token if "errcode" in resp_dict: return "获取access_token失败" access_token = resp_dict.get("access_token") open_id = resp_dict.get("openid") # 3. 向微信服务器发送http请求,获取用户的资料数据 url = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN" \ % (access_token, open_id) response = urllib2.urlopen(url) # 读取微信传回的json的响应体数据 user_json_str = response.read() user_dict_data = json.loads(user_json_str) if "errcode" in user_dict_data: return "获取用户信息失败" else: # 将用户的资料数据填充到页面 return render_template("index.html", user=user_dict_data) if __name__ == '__main__': app.run(port=8000, debug=True)

通过xftp软件向服务器上传修改后的wechat.py文件: 在这里插入图片描述

云服务器上需要同步基于python的flask,这是一个轻量级web框架,先在服务器上安装flask:

pip install flask

查看端口号8000的开放情况(使用阿里云的朋友记得在阿里云的安全组配置上面开放80端口和8000端口的使用):

netstat -apn | grep 8000

进入虚拟环境:

conda activate paddle_env

前面编写写的GET和POST方法向微信服务器请求access_token,运行wechat.py文件,与微信服务器建立连接,获取accexx_token:

在这里插入图片描述

在URL输入框里的IP后面不用添加端口号,因为一方面微信公众号http协议只支持80端口,另一方面我们先让微信服务器把消息转发到云服务器的nginix上,然后再交给服务器,注意URL一定要填http而不是https,否则不成功: 在这里插入图片描述

提交后显示成功,然后点击启用:

在这里插入图片描述

二、微信公众号部署AI对话机器人

服务器运行AI部署代码:

import paddlenlp import utils from utils import select_sum from utils import post_process_sum from flask import Flask, request, abort, render_template import hashlib import xmltodict import time import urllib.request as urllib2 import json # 微信的token令牌 WECHAT_TOKEN = '你的token' WECHAT_APPID = '你的APPID' WECHAT_APPSECRET = '你的SECRET' model = paddlenlp.transformers.UNIMOLMHeadModel.from_pretrained('data126898') tokenizer = paddlenlp.transformers.UNIMOTokenizer.from_pretrained('unimo-text-1.0') model.eval() num_return_sequences = 8 app = Flask(__name__) @app.route("/wechat8000", methods=["GET", "POST"]) def wechat(): """对接微信公众号服务器""" # 接收微信服务器发送的参数 signature = request.args.get("signature") timestamp = request.args.get("timestamp") nonce = request.args.get("nonce") # 校验参数 if not all([signature, timestamp, nonce]): abort(400) # 按照微信的流程进行计算签名 li = [WECHAT_TOKEN, timestamp, nonce] # 排序 li.sort() # 拼接字符串 tmp_str = "".join(li) # 进行sha1加密,得到正确的签名值 sign = hashlib.sha1(tmp_str.encode("utf-8")).hexdigest() # 将自己计算的签名值与请求的签名参数进行对比,如果相同,则证明请求来自微信 if signature != sign: # 表示请求不是微信发的 abort(403) else: # 表示是微信发送的请求 if requesthod == "GET": # 表示是第一次接入微信服务器的验证 echostr = request.args.get("echostr") if not echostr: abort(400) return echostr elif requesthod == "POST": # 表示是微信服务器转发消息过来 xml_str = request.data if not xml_str: abort(400) # 对xml字符串进行解析 xml_dict = xmltodict.parse(xml_str) xml_dict = xml_dict["xml"] # 提取消息类型 msg_type = xml_dict.get("MsgType") if msg_type == "text": # 表示发送的是文本消息 # 构造返回值,经由微信服务器回复给用户的消息内容 source_text = xml_dict.get("Content") # 由于训练时间较长,这里我们直接读训练好的模型 inputs = source_text inputs_ids = tokenizer.gen_encode(inputs, return_tensors=True, add_start_token_for_decoding=True, return_position_ids=True) # 调用生成api并指定解码策略为beam_search outputs, scores = model.generate(**inputs_ids, decode_strategy='beam_search', num_beams=8, num_return_sequences=num_return_sequences) # 调用生成api并指定解码策略为Sampling,不同策略的效果不同哦。 r = '' for i in range(num_return_sequences): r = r+'{} 上联: {} 下联:{}'.format(i, inputs, ''.join(post_process_sum(outputs[i].numpy(), tokenizer)[1]))+'\n' resp_dict = { "xml": { "ToUserName": xml_dict.get("FromUserName"), "FromUserName": xml_dict.get("ToUserName"), "CreateTime": int(time.time()), "MsgType": "text", "Content": r } } else: resp_dict = { "xml": { "ToUserName": xml_dict.get("FromUserName"), "FromUserName": xml_dict.get("ToUserName"), "CreateTime": int(time.time()), "MsgType": "text", "Content": "i love u" } } # 将字典转换成xml字符串 resp_xml_str = xmltodict.unparse(resp_dict) resp_xml_str = resp_xml_str+"我爱你" # 返回消息数据给微信服务器 return resp_xml_str @app.route('/wechat8000/index') def index(): """让用户通过微信访问的网页页面视图""" # 从微信服务器中拿取用户的资料数据 # 1. 拿取code参数 code = request.args.get("code") if not code: return "缺失code参数" # 2. 向微信服务器发送http请求,获取access_token url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code" \ % (WECHAT_APPID, WECHAT_APPSECRET, code) # 使用urllib2的urlopen方法发送请求 # 如果只传网址url参数,则默认使用http的get请求方式 response = urllib2.urlopen(url) # 获取响应体数据,微信返回的json数据 json_str = response.read() resp_dict = json.loads(json_str) # 提取access_token if "errcode" in resp_dict: return "获取access_token失败" access_token = resp_dict.get("access_token") open_id = resp_dict.get("openid") # 3. 向微信服务器发送http请求,获取用户的资料数据 url = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN" \ % (access_token, open_id) response = urllib2.urlopen(url) # 读取微信传回的json的响应体数据 user_json_str = response.read() user_dict_data = json.loads(user_json_str) if "errcode" in user_dict_data: return "获取用户信息失败" else: # 将用户的资料数据填充到页面 return render_template("index.html", user=user_dict_data) if __name__ == '__main__': app.run(port=8000, debug=True)

服务器运行结果: 在这里插入图片描述 公众号效果: 在这里插入图片描述

三. 公众号回复其他类型消息 3.1 接口的概念

接口是指微信服务器提供的供开发者可以直接使用的API(Application program Interface,应用程序接口),开发者在使用接口时需要定义和接口相同名字的函数,这被视为双方达成的一致协议。 相关接口的使用次数都是有上限的,目的为了防止公众号的程序错误而引发微信服务器负载异常,默认情况下,每个公众号调用接口都不能超过一定限制。

3.2 使用接口进行开发

根据微信开发者文档的规定,要想使用微信提供的接口,必须先获得有效的access_token。

3.2.1 实现元宵节猜灯谜

将程序挂在服务器上:

nohup python -u main_test.py > test.out 2>&1 &

上述命令关键词含义:

其中 0、1、2分别代表如下含义: 0 – stdin (standard input) 1 – stdout (standard output) 2 – stderr (standard error) nohup python -u main.py > test.out 2>&1 & nohup+最后面的& 是让命令在后台执行 >out.log 是将信息输出到out.log日志中 2>&1 是将标准错误信息转变成标准输出,这样就可以将错误信息输出到out.log 日志里面来。

这样即使是关闭Xshell等ssh连接软件也可以继续提供服务了。

四.参考文献

https://blog.csdn.net/mrbcy/article/details/64533496



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3