使用flask搭建微信公众号:实现签到功能
终于到了实战阶段。用微信公众号实现一个简单的签到功能。
前情提要:
程序逻辑如下图

发起签到
生成"随机数.txt"文件,并将随机数返回作为签到码,将签到码返回给发起签到的用户
def gensign():
sign_number=random.randint(1000,9999)
f = open(str(sign_number)+'.txt','w')
f.close()
return str(sign_number)
签到
用户发送"签到 签到码 用户名"给公众号(各项之间用一个空格分开)。服务器接收到信息后将用户名写入签到文件中,并返回是否签到成功
def sign(sign_number,username):
if(os.path.exists(sign_number+'.txt')):
with open(sign_number+'.txt','a') as f:
f.write(username+'\n')
return "签到成功"
elif(os.path.exists(sign_number)):
return "已超出签到时间"
else:
return "签到失败"
关闭签到
关闭签到是为了给签到设定期限,由用户选择何时关闭签到。我这里的关闭签到就是把后缀名的txt给删掉。发送"关闭 签到码"给公众号(各项之间用一个空格分开)。即可关闭签到
def closesign(sign_number):
if(os.path.exists(sign_number+'.txt')):
os.rename(sign_number+'.txt',str(sign_number))
查看签到
发送"查看 签到码"给公众号(各项之间用一个空格分开)即可查看某个签到的签到情况。这里发送的是签到码,所以只有在关闭签到后才能查看(当然,发带.txt的也能)。就是把读取某个签到文件的内容返回给查看签到的用户即可。
所有代码
from flask import Flask,request
import hashlib
import xmltodict
import time
import random
import os def gensign():
sign_number=random.randint(1000,9999)
f = open(str(sign_number)+'.txt','w')
f.close()
return str(sign_number) def closesign(sign_number):
if(os.path.exists(sign_number+'.txt')):
os.rename(sign_number+'.txt',str(sign_number)) def sign(sign_number,username):
if(os.path.exists(sign_number+'.txt')):
with open(sign_number+'.txt','a') as f:
f.write(username+'\n')
return "签到成功"
elif(os.path.exists(sign_number)):
return "已超出签到时间"
else:
return "签到失败" app = Flask(__name__) @app.route('/wx', methods=["GET", "POST"])
def getinput():
if (request.method == "GET"):
# 表示是第一次接入微信服务器的验证
signature=request.args.get('signature')
timestamp=request.args.get('timestamp')
nonce=request.args.get('nonce')
token = "maluguang"
list = [token, timestamp, nonce]
list.sort()
sha1 = hashlib.sha1()
sha1.update(list[0].encode('utf-8'))
sha1.update(list[1].encode('utf-8'))
sha1.update(list[2].encode('utf-8'))
hashcode = sha1.hexdigest()
echostr = request.args.get("echostr")
if hashcode == signature:
return echostr
else:
return ""
elif request.method == "POST":
# 表示微信服务器转发消息过来
xml_str = request.data
if not xml_str:
return""
# 对xml字符串进行解析
xml_dict = xmltodict.parse(xml_str)
xml_dict = xml_dict.get("xml") # 提取消息类型
msg_type = xml_dict.get("MsgType")
if msg_type == "text":
# 表示发送的是文本消息
# 构造返回值,经由微信服务器回复给用户的消息内容
userinput=xml_dict.get("Content")
if(userinput=='发起签到'):
sign_number=gensign()
resp_dict = {
"xml": {
"ToUserName": xml_dict.get("FromUserName"),
"FromUserName": xml_dict.get("ToUserName"),
"CreateTime": int(time.time()),
"MsgType": "text",
"Content": "您的签到码为" +sign_number
}
}
# 将字典转换为xml字符串
resp_xml_str = xmltodict.unparse(resp_dict)
# 返回消息数据给微信服务器
return resp_xml_str
else:
userinput=xml_dict.get("Content")
if("关闭" in userinput):
try:
msglist=userinput.split(" ")
sign_number=msglist[1]
closesign(sign_number)
resp_dict = {
"xml": {
"ToUserName": xml_dict.get("FromUserName"),
"FromUserName": xml_dict.get("ToUserName"),
"CreateTime": int(time.time()),
"MsgType": "text",
"Content": "成功关闭签到" +sign_number
}
}
# 将字典转换为xml字符串
resp_xml_str = xmltodict.unparse(resp_dict)
# 返回消息数据给微信服务器
return resp_xml_str
except:
return "success"
if("签到" in userinput):
try:
msglist=userinput.split(' ')
sign_number=msglist[1]
username=msglist[2]
return_msg=sign(sign_number,username)
resp_dict = {
"xml": {
"ToUserName": xml_dict.get("FromUserName"),
"FromUserName": xml_dict.get("ToUserName"),
"CreateTime": int(time.time()),
"MsgType": "text",
"Content": username+return_msg+sign_number
}
}
# 将字典转换为xml字符串
resp_xml_str = xmltodict.unparse(resp_dict)
# 返回消息数据给微信服务器
return resp_xml_str
except:
return "success"
if("查看" in userinput):
try:
msglist=userinput.split(' ')
sign_number=msglist[1]
if(os.path.exists(sign_number)):
with open(sign_number,'r') as f:
data=f.read();
else:
data='打开签到文件失败'
resp_dict = {
"xml": {
"ToUserName": xml_dict.get("FromUserName"),
"FromUserName": xml_dict.get("ToUserName"),
"CreateTime": int(time.time()),
"MsgType": "text",
"Content": sign_number+'签到情况为\n'+data
}
}
# 将字典转换为xml字符串
resp_xml_str = xmltodict.unparse(resp_dict)
# 返回消息数据给微信服务器
return resp_xml_str
except:
return "success"
else:
resp_dict = {
"xml": {
"ToUserName": xml_dict.get("FromUserName"),
"FromUserName": xml_dict.get("ToUserName"),
"CreateTime": int(time.time()),
"MsgType": "text",
"Content": "Dear I Love you so much"
}
}
resp_xml_str = xmltodict.unparse(resp_dict)
# 返回消息数据给微信服务器
return resp_xml_str if __name__ == '__main__':
app.run(port='')
运行截图

一些漏洞和缺陷
1.【大漏洞】没有对签到的控制验证权限,任何人只要发送正确的命令都可以操控签到,关闭签到,查看签到等。可能会有人趁此捣乱。其实应该是只有发起签到的人有权力操纵的
2.每次都会写返回的xml的同样的东西,应该可以省略然后只改不一样的部分的。后面再看看
3.代码很丑,一堆if可能效率还很低
4.异常处理也没有管那么多。可能会有意料之外的错误
5.发送的消息未经token验证,这个是懒得写,反正又不是投入生产环境的
6.生成的随机数可能会重复而产生问题
7.一个微信号可以一直签到,可以替任何人签到,没有进行微信号和签到人的绑定来确定签到的唯一性
应该还有很多问题,暂时就想到这么多了。不过就算一堆问题也不重要,重要的是这个prototype已经做出来了,后面要是用就可以在这基础上进行更改了。不过我也不是为了用它才写这个的,就是想学学微信公众号的开发,写点东西练练手。
写完了,快乐呀。哈哈
使用flask搭建微信公众号:实现签到功能的更多相关文章
- 使用flask搭建微信公众号:完成token的验证
上一篇文章讨论了官方给的例子验证token失败的解决方法:微信公众号token验证失败 想了一下,还是决定不适用web.py这个框架.因为搜了一下他的中文文档不多,学起来可能会有点麻烦.而且看着他没有 ...
- 使用flask搭建微信公众号:接收与回复消息
token验证的意义 在看了别人的代码之后对token加密有了些理解了.但又觉得很鸡肋.第一次验证服务器的时候我在那弄了半天的验证其实不写也可以验证成功,只要直接返回echostr这个字段就行了.微信 ...
- C#开发微信门户及应用(37)--微信公众号标签管理功能
微信公众号,仿照企业号的思路,增加了标签管理的功能,对关注的粉丝可以设置标签管理,实现更加方便的分组管理功能.开发者可以使用用户标签管理的相关接口,实现对公众号的标签进行创建.查询.修改.删除等操作, ...
- 微信开发(3):微信公众号发现金红包功能开发,利用第三方SDK实现(转)
最近需求是 用户兑换微信红包,需要一些验证,加密,以及证书: 工欲善其事必先利其器 感谢前辈的微信SDK 已经维护三年了,还在维护中! 官方文档走一波 文档还是一如既往的 坑人啊,写的很简单,对简单明 ...
- 在新浪SAE上搭建微信公众号的python应用
微信公众平台的开发者文档https://www.w3cschool.cn/weixinkaifawendang/ python,flask,SAE(新浪云),搭建开发微信公众账号http://www. ...
- flask开发微信公众号
1.进入微信公众号首页,进行注册登录 https://mp.weixin.qq.com/ 2.进入个人首页,进行公众号设置 可参照 公众号文档 进行开发 开发前 先阅读 接口权限列表 3.配置服务器 ...
- 使用python django快速搭建微信公众号后台
前言 使用python语言,django web框架,以及wechatpy,快速完成微信公众号后台服务的简易搭建,做记录于此. wechatpy是一个python的微信公众平台sdk,封装了被动消息和 ...
- ngrok逆向代理服务器搭建微信公众号本地开发环境
一条命令解决的外网访问内网问题 本地WEB外网访问.本地开发微信.TCP端口转发 平台登陆地址:http://www.ngrok.cc/login 新版本上线启动方式更简单使用视频教程 在路由器上面的 ...
- Flask接通微信公众号
import hashlib import xml.etree.ElementTree as ET from flask import Flask, request import time app = ...
随机推荐
- 将SpringCloud Eureka 服务注册与发现部署到docker
一.前言 最近在学习docker,顺便把之前学习的spring cloud 部署到Docker 中.至于什么是SpringCloud的服务注册与发现,什么是docker,我这里就不作赘述了.可以先去学 ...
- JVM知识点总览-高级Java工程师面试必备
jvm 总体梳理 jvm体系总体分四大块: 类的加载机制 jvm内存结构 GC算法 垃圾回收 GC分析 命令调优 当然这些知识点在之前的文章中都有详细的介绍,这里只做主干的梳理 这里画了一个思维导图, ...
- netty自定义解码器
在socket传输通信中容易丢包问题,什么半包问题,这些都是很正常的问题,处理方法就是定义自己的编解码规则了,让每次接收按定义好的规则为一个完整包作为数据源即可. 下面个例子就是netty自定义的一个 ...
- JS中,JSON 和 对象互转,数组和字符串的转换?
JSON 与 J对象转化 要实现从对象转换为 JSON 字符串,使用 JSON.stringify() 方法: 如下: var json = JSON.stringify({a: 'Hello', b ...
- RabbitMQ之消息模式
目的: 消息如何保证100%的投递 幂等性概念 Confirm确认消息 Return返回消息 自定义消费者 前言: 想必知道消息中间件RabbitMQ的小伙伴,对于引入中间件的好处可以起到抗高并发,削 ...
- K8s-yaml的使用及命令
YAML配置文件管理对象 对象管理: # 创建deployment资源 kubectl create -f nginx-deployment.yaml # 查看deployment kubectl g ...
- Equalizing Two Strings CodeForces - 1256F (思维)
大意: 给定两个串$s,t$, 每次操作任选长度$len$, 分别翻转$s,t$中一个长$len$的子串, 可以进行任意次操作, 求判断能否使$s$和$t$相同. 字符出现次数不一样显然无解, 否则若 ...
- ansible debugger 模块
在搞TF(tungstenfabric)时遇到了一些错误,TF通过ansible playbook 来部署的.通常情况下遇到错误都是通过ansibale xxxx –vvv 来详细输出一下.出错的类型 ...
- 4.将验证添加到 ASP.NET Core Razor 页面
向 Movie 模型添加了验证逻辑. 每当用户创建或编辑电影时,都会强制执行验证规则. 1.打开Movie.cs文件.DataAnnotations命名空间提供了一组内置的验证属性,这些属性以声明方式 ...
- docker build 错误 /usr/share/dotnet/sdk/2.1.801/Microsoft.Common.CurrentVersion.targets(2106,5): warning MSB3245: Could not resolve this reference
docker dotnet Restore 的时候报错, 一度怀疑是linux的dotnet core sdk没有装好, 卸了装, 装了卸, 试了好几遍还是无效(Microsoft.Common.Cu ...