创作灵感
好奇心驱使着我扫了图中的二维码(已打码),发现是引导关注公众号的,我一点关注后,会话界面就出来了这个 预测 2020 会发生在被扫码者身上的几件事 的小游戏的链接:
我继续点击这个链接,然后就生成了属于我自己的预测图:
然后我又可以分享出去,让我的朋友圈好友去扫,他们又分享,这样一传十、一传百,不知不觉又被隔了一波韭菜:
创作效果
作为一个技术人,不仅要有对割韭菜有敏锐的嗅觉,还要懂得如何技术割韭菜,于是乎,昨晚调研一晚上,确定技术栈及与了解公众号开发的诸多限制后,今天倒腾了了一上午,我利用了我的微信公众小号,部署应用上线。
可以在扫一扫下面这个二维码体验~,一人独立完成,时间有限,UI 丑勿喷。
(ps~,未关注者点击关注,已关注者发送 海报 两字,即可获得你的专属预测海报,服务器性能差,代码尚待优化,图片传输流量较大,故需 1-3 秒时间获得为你制作的海报,请谅解)
创作笔法
微信公众号的两种开发模式
你可能会有一个疑惑?我为什么要用小号做测试呢?其实微信公众号开发分两种模式:
编辑模式:主要针对非编程人员及信息发布类公众帐号使用。开启该模式后,可以方便地通过界面配置“自定义菜单”和“自动回复的消息”。 开发模式:主要针对具备开发能力的人使用。开启该模式后,能够使用微信公众平台开放的接口,通过编程方式实现自定义菜单的创建、用户消息的接收/处理/响应。这种模式更加灵活,建议有开发能力的公司或个人都采用该模式。
简单来说,就是不用写代码直接在微信公众号网页上配置自定义菜单或者自动回复,这叫编辑模式;需要写代码实现自动回复或者更高级的逻辑,这叫开发模式;并且这两种模式是互斥的,就是说,一旦开启了开发模式,编辑模式就失效了,之前配置的自定义菜单和自动回复全部失效,这对我现在这个公众号是不可接受的,因为在编辑模式里配置太多了,迁移到开发者模式一来多耗了时间成本,二来还不稳定,所以我想起了我尘封已久的小号。
创作原料
在正式开发前,你需要有以下“纸”或者“笔”:
一台服务器(最好 location 华中华南华北华东华西)
一个最好存案好的域名
服务器接入微信公众号
然后呢,其实在微信公众号开发过程中,微信公众号后台就像是一台代理服务器,微信公众号消息先由微信公众号后台处理,再转发给我们自己的服务器处理,这过程就必须要遵循微信公众号的开发规范了;那么,怎么让微信公众号和我们自己的服务器对接呢?接入微信公众平台开发,开发者需要依照如下步骤完成:
填写服务器配置:填写 URL(只支持 80(http) 和 443(https) 端口,开发者文档说是服务器域名,准确来说不是你的服务器域名,而是你服务器上处理微信公众号转发消息的根路由)、Token(可随便填) 和 EncodingAESKey(可自动生成),这两个参数只在接入时可能有用,是为了平安性起见而采用 sha1 加密的几个参数之二,无需过多关心,这一步主要是注意 URL 的正确性。
验证服务器地址的有效性:点一下验证按钮即可,网页上会出现 Token 验证成功或者失败的提示。
依据接口文档实现业务逻辑:这个就是我们大展身手写代码的部分了。
应用逻辑
有个坑需要填一下,个人微信公众号不能够获取用户的基本信息:昵称和头像等等
需要认证才能获得这个权限,但是认证需要 take money,但是我满脸都写着穷
PIL 库的安装姿势是 pip install pillow 而不是 pip install PIL
然后应用服务器采用的是 Flask 框架(Flask 是应用框架,nginx 是 web 服务器,他们都属于软件,Flask 自带的生产环境服务器不足以支持实际应用,需要 uwsgi 应用服务器,nginx 直接处理静态资源请求,逻辑请求转发给 uwsgi ;阿里云服务器是虚拟化的 PC,包含软件和硬件;有关服务器具体知识可以参考我之前发过的一篇文章:扫码考勤小程序正式上线)
回到主题,假设我们的根路由是
https://doamin/wechat/
我们可以给这个路由绑定一个视图函数,my_view(),并同时开启处理 post 请求开关(默认只处理 get),我们所有的逻辑都可以由这一个视图函数实现,接入公众号开发时 Token 验证公众号是通过 get 方式请求到我们的服务器的,验证通过后的转发消息都是通过 post 方式,那么,我们就可以通过请求方式区分是验证还是转发了。
if request.method == 'GET':
signature = request.args['signature']
timestamp = request.args['timestamp']
echostr = request.args['echostr']
nonce = request.args['nonce']
token = '好想爱这个世界'
tempList = [token, timestamp, nonce]
# 字典序排序
tempList.sort()
# 转成字符串
tempStr = ''.join(tempList)
# sha1 加密
tempStr = hashlib.sha1(tempStr.encode('utf-8')).hexdigest()
if tempStr == signature:
print('token verify succes')
return echostr
else:
#可以发现,前面的验证代码其实无关紧要,只要返回了 echostr ,就算验证成功
return echostr
elif request.method == 'POST':
print('在这里写业务逻辑')
我们还需要在自己的服务器上调用微信的接口,好比海报制作完成后,通过微信转发给用户,不能直接返回图片的二进制数据,事实上这是微信公众号做的,我们需要上传该海报至微信公众号素材库,获得这个海报的 id,然后封装成 xml 数据返回给微信公众号(吐槽一下还没有升级到 json 交换数据),这样用户就收到我们的海报了。
那么问题来了,上传该海报至微信公众号素材库,在公众号文章编辑界面呆久了,我还以为要手动上传,还好找到了接口 1,我们可以在服务器上调用这个接口 1,为了防止滥用这个接口 1, 必须提供 access_token , 但是 access_token 哪里来呢?需要通过调用另一个接口 2,接口 2 需要提供 AppId 和 AppSecret 参数,如果不自己修改,这两个是长期有效的,可以直接获取。
接口 1:POST https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
接口 2:GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
还有一个坑就是,这个 access_token 有效期只有 2 个小时,所以我们需要不断更新它,所以需要给我们的 Flask 引入循环任务配置
# 定时任务配置
class Config(object): # 创建配置
# 任务列表
JOBS = [
{
'id': '1',
'func': '__main__:refreshToken', # 定时执行的方法名
'trigger': 'interval', # interval表示循环任务
'hours': 2, # 每两个小时的执行一次
}
]
app.config.from_object(Config()) # 为实例化的flask引入配置
坑暂时填了这么多,欢迎大噶品鉴。最后防止大家忘记海报入口,再放一次图,仅生产环境级部署,不接受任何压测,需要优惠购买阿里云服务器请点击原文链接。