在微信开发过程中,使用的SAE+PYTHON的架构,使用web.py提供web服务,作为微信的后端。前期工作都很顺利,就是在给用户发送模板消息时碰到了一些问题。
首先,由于代码托管在SAE上,无法直接执行发送模板消息的代码,所以只能通过识别用户的输入指令来触发模板消息发送操作,我用的是管理员openid+指令内容来判定是否发消息的指令。
其次,由于用户量较多,大概10000人,模板消息需要发送给所有用户,因此响应的时间肯定超过了5s,此时微信服务器就会重复请求,这样就导致最后模板消息发送了多次(根据我的观察是3-4次)。
我根据微信官方文档http://mp.weixin.qq.com/wiki/14/89b871b5466b19b3efa4ada8e577d45e.html的说明,即微信服务器在将用户的消息发给公众号的开发者服务器地址(开发者中心处配置)后,微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次,如果在调试中,发现用户无法收到响应的消息,可以检查是否消息处理超时。关于重试的消息排重,有msgid的消息推荐使用msgid排重。事件类型消息推荐使用FromUserName + CreateTime 排重。
我对用户的数据库添加了一个msgid字段用来记录用户最近一次消息的msgid,通过比较当前的msgid跟最近一次的msgid是否相同来判断是否重复请求,如果是相同的话就直接return ''给微信服务器,不同的话就执行推送模板消息的操作。按理说这样就可以在第一次请求时发送模板消息而且避免后面重复发送,然而结果却一次都没有发送,很奇怪。我思考是不是必须用异步机制?也就是说先返回一个值给管理员,然后再执行耗时的模板消息推送工作,但web.py貌似不支持?
代码简单列举如下,还望不吝赐教,谢谢
if ('推送' in request and userid=='admin openid '):#如果请求发自管理员而且包含推送字段
if id!=msgid:#判断本次请求的msgid是否跟上次相同,不同才执行下面的操作
cur.execute("update users set msgid='%s'"%id+" where userid='%s'"%userid)
cur.close()
conn.commit()
conn.close()
result=self.push_notice()#推送模板消息,比较耗时
return self.render.reply_text(fromUser,toUser,int(time.time()),result)#return超过了5秒,微信服务器会尝试重复请求
结果是没有上面加粗的排重语句时,模板消息会重复3次,加了之后却1次都没有,很纳闷。