1.需求:根据不同的发送位置做不同的处理。所以自定义了发送位置事件。eventKey为publish。可能用到多个发送位置作不同处理。
2.问题:用户发送位置时,后台收到一个带有eventKey的location_select事件,和location事件(没有eventKey)。
我需要处理完location_select(带eventKey为publish)的事件后,回复消息。
3.结果:用户不收到消息。
4.发现:location事件回复真正消息,用户能收到;location事件回复""且location_select事件回复真正消息,用户收不到。
5.猜测:因为腾讯同时向我发出了两条请求,会不会排重原因location事件回复覆盖掉location_select事件。
<FromUserName><![CDATA[oUqtYx0]]></FromUserName>
<CreateTime>1742716069</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[location_select]]></Event>
<EventKey><![CDATA[push_car_in]]></EventKey>
<SendLocationInfo><Location_X><![CDATA[XX.203168701311291]]></Location_X>
<Location_Y><![CDATA[XX.52965488217018]]></Location_Y>
<Scale><![CDATA[15]]></Scale>
<Label><![CDATA[]]></Label>
<Poiname><![CDATA[XXXXX]]></Poiname>
</SendLocationInfo>
</xml>)]
<FromUserName><![CDATA[oZqtYx0]]></FromUserName>
<CreateTime>1742716068</CreateTime>
<MsgType><![CDATA[location]]></MsgType>
<Location_X>XX.203169</Location_X>
<Location_Y>XX.529655</Location_Y>
<Scale>15</Scale>
<Label><![CDATA[]]></Label>
<MsgId>2494XX7XX</MsgId>
</xml>)]
1. 问题原因:
当用户通过自定义菜单选择位置时,微信服务器会同时发送两个事件:
location_select事件(带有EventKey)
location事件(不带EventKey)
由于这两个事件几乎同时到达,可能会造成消息覆盖
2. 解决方案:
建议采用以下方式处理:
def handle_wechat_event(request):
# 解析XML数据
msg_type = xml_data.find('MsgType').text
if msg_type == 'event':
event_type = xml_data.find('Event').text
if event_type == 'location_select':
# 获取EventKey
event_key = xml_data.find('EventKey').text
# 获取位置信息
location_x = xml_data.find('.//Location_X').text
location_y = xml_data.find('.//Location_Y').text
# 处理location_select事件,但不立即回复
process_location_select(event_key, location_x, location_y)
return '' # 返回空字符串
elif event_type == 'location':
# 在location事件中进行实际的消息回复
location_x = xml_data.find('Location_X').text
location_y = xml_data.find('Location_Y').text
# 获取之前处理的结果并回复
reply_content = get_processed_reply(location_x, location_y)
return format_reply(reply_content)
在location_select事件中只进行数据处理,不回复消息(返回空字符串)
在location事件中进行实际的消息回复
可以使用缓存(如Redis)在两个事件之间传递数据
4. 示例实现:
import redis
# 初始化Redis连接
redis_client = redis.Redis(host='localhost', port=6379, db=0)
def process_location_select(event_key, location_x, location_y):
# 将处理结果存入Redis,设置过期时间为60秒
key = f"location_{location_x}_{location_y}"
result = process_by_event_key(event_key, location_x, location_y)
redis_client.setex(key, 60, result)
def get_processed_reply(location_x, location_y):
# 从Redis获取之前的处理结果
key = f"location_{location_x}_{location_y}"
result = redis_client.get(key)
return result if result else "默认回复消息"
确保location_x和location_y的精度处理,可能需要进行四舍五入
设置合适的缓存过期时间
考虑并发情况下的处理
这样处理可以确保用户能收到正确的回复消息,同时避免消息覆盖的问题。