python处理微信公众平台请求

#!/usr/bin/env python
#coding:utf8
# Author          : tuxpy
# Email           : q8886888@qq.com
# Last modified   : 2014-09-03 22:50:13
# Filename        : weixin.py
# Description     : 
from config import render,kv_db
import os
import urllib2,json
import lxml
from lxml import etree
import time
import hashlib
import web



__all__ = ["WeixinInterface"]


class Public():
    def _do_clear(self):
        in_where = kv_db.get(self.fromUser + "_where")
        if not in_where:  # 如果当前在首页,则不需要清除相应记录
            return None
        if in_where.startswith("pc_"): # 在故障报修下的子菜单,就只清理下面的东西就行
            kd_list = ["_content","_name","_phone","_where","_room","_when"]
        if in_where.startswith("search_"):
            kd_list = ["_where"]  # 如果在搜索模式下,就只有清空当前位置信息,返回首页就行。
          
        if in_where.startswith("login_"):
            kd_list = ["_where","_user","_pwd", "_is_login"]
        
        for item in kd_list:
            kv_db.delete(self.fromUser + item)

    def do_help(self):
    	self._do_clear()
        help_mess=[
                u'***输入以下指令.前的"符号"***',
                u'"1.技术人员"——获取技术人员联系方式',
                u'"2.最新公告"——获取协会的最近活动信息',
                u'"3.电脑报修"——电脑出问题了?把问题提交给我们吧',
                u'"4.搜索问题"——来我们的已解决故障的数据库中查找答案吧',
                u'"#.退出当前模式,并显示帮助菜单"'
                ]
        if kv_db.get(self.fromUser + "_is_login"):
            help_mess.extend([
                              u'"bug.查看故障"——查看随机一个待解决故障',
                              u'"logout.退出登录"——注销当前账号'
                             ])
        
        return '\n'.join(help_mess)

  
class obj_pc(Public):
    def __init__(self,line,fromUser):
        self.line = line
        self.fromUser = fromUser
        
    def do_pc_(self):
    	kv_db.set(self.fromUser + "_where", "pc_content")  # 改动当前位置,使用kd来判断当前位置
    
        return u'请输入您遇到的电脑问题,至少要10个字哦~暂时不支持加图片。回复"#"退出故障提交模式'    
  
    def do_pc_content(self):
    	from submit import check_content
        
        if check_content(self.line):
            kv_db.set(self.fromUser + "_where", "pc_name")
            kv_db.set(self.fromUser + "_content", self.line)
        else:
            return u"您输入的故障信息不能少于10个字哦~~请重新输入"
        return u"请输入您的名字"    
    
    def do_pc_name(self):
        from submit import check_name
        if check_name(self.line):
            kv_db.set(self.fromUser + "_where", "pc_phone")
            kv_db.set(self.fromUser + "_name", self.line)
        else:
            return u"您输入的姓名不要太长,或太短哦"
        return u"请输入您的联系方式"
        
    
    def do_pc_phone(self):
        from submit import check_phone
        
        if check_phone(self.line):
            kv_db.set(self.fromUser + "_where", "pc_room")
            kv_db.set(self.fromUser + "_phone", self.line)
        else:
            return u"您输入的联系方式错误,请输入11位长号,或6位长号"
     
        return u"您的寝室号?"
        
    def do_pc_room(self):
        kv_db.set(self.fromUser + "_where", "pc_when")
        kv_db.set(self.fromUser + "_room", self.line)
        
        return u"希望我们什么时候过去修?或者说你什么时候有空?"
    
    def do_pc_when(self):
        kv_db.set(self.fromUser + "_where", "pc_end")  # 定位
        kv_db.set(self.fromUser + "_when", self.line)  # 存值
        
        return self.__do_pc_data() # 到这信息都输入完毕,确定提交了
            
    
    def do_pc_end(self):
        if self.line.lower() != 'y':
            self._do_clear()
            return  u"取消提交"
        else:
            if self.__do_pc_submit():
                self._do_clear()
                return u"提交成功"
            else:
                return u"提交失败,是否重试?"
    

    
    def __do_pc_data(self):  # 对提交问题的最后一个确定
        data = [
                u"故障: " + kv_db.get(self.fromUser + "_content"),
                u"姓名: " + kv_db.get(self.fromUser + "_name"),
                u"联系方式: " + kv_db.get(self.fromUser + "_phone"),
                u"寝室号: " + kv_db.get(self.fromUser + "_room"),
                u"维修时间: " + kv_db.get(self.fromUser + "_when"),
                u"确定提交(回复'y'表示确定)?",
                ]
        return '\n'.join(data)
    
    
    
    
            
    def __do_pc_submit(self):
        class Data():  # 为了和writeDb接口匹配
            Content = kv_db.get(self.fromUser + "_content")
            Name = kv_db.get(self.fromUser + "_name")
            Phone = kv_db.get(self.fromUser + "_phone")
            Room = kv_db.get(self.fromUser + "_room")
            Time = kv_db.get(self.fromUser + "_when")

        from submit import sendSubmit
        data = Data()
        try:
            sendSubmit().writeDb(data)
            return True
        except:
            return False
        

    
class obj_search(Public):
    def __init__(self,line,fromUser):
        self.line = line
        self.fromUser = fromUser
        
   
    def do_search_(self):
        kv_db.set(self.fromUser + "_where", "search_content")  # 改动当前位置,使用kd来判断当前位置
        return u'请输入您的故障,2~30字\n(尽可以输得简单直白一点,不要拖泥带水。\
        <a href="http://xxxxxxxxxxxx/help#search">使用帮助</a>)\n回复"#"退出搜索模式'
    
    def do_search_content(self):
        if not (2 <= len(self.line) <= 30):
            return u"问题字数请控制在2~30"
        else:
            request = [u"问题: %s" % self.line,
                       u'答案: <a href="http://xxxxxxxxxx/sendKw?Kw=%s">点击查看</a>' % self.line,
                       u'回复"#"退出搜索模式',
                      ]
            return '\n'.join(request)

  
class obj_login(Public):
    def __init__(self,line,fromUser):
        self.line = line
        self.fromUser = fromUser
        
    def do_login_(self):
        kv_db.set(self.fromUser + "_where", "login_user")
        return u"请输入用户名"
    def do_login_user(self):
        kv_db.set(self.fromUser + "_where", "login_pwd")
        kv_db.set(self.fromUser + "_user", self.line) 
        return u"请输入密码"
    
    def do_login_pwd(self):
        import hashlib
        pwd = hashlib.md5(self.line).hexdigest()
        kv_db.set(self.fromUser + "_pwd", pwd)
        
        if check_login(self.fromUser):
            kv_db.delete(self.fromUser + "_where")
            kv_db.set(self.fromUser + "_is_login", True)
            return u"登录成功"
        else:
            self._do_clear()
            return u"登录失败"
    
def check_login(fromUser):
    fromUser_user = kv_db.get(fromUser + '_user')
    fromUser_pwd = kv_db.get(fromUser + '_pwd')
   
    if fromUser_user and fromUser_pwd:
        try:
            from config import get_isLoginOk
            uid = get_isLoginOk(fromUser_user, fromUser_pwd) # 用户uid
            return True
        except:
            return False
    else:
        return False

class CommandHandler(Public):
    def handle(self, line, fromUser):
        self.fromUser = fromUser
     
        cmd_list={ # 数字指令与文字指令对应的函数
            u'1':"list", u'技术人员':"list",
            u'2':"mess", u'最新公告':"mess",
            u'3':"pc_", u'电脑报修':"pc_",
            u'4':"search_", u'搜索问题':"search_", # 最后带_表示有子菜单
            u'login':"login_",
            u'logout':"logout",
            u'bug':"bug",

            u'#':"help",
                }
        in_where = kv_db.get(self.fromUser + "_where") # 获取当前所在位置。如果是首页,则是None
        
        if in_where and line.strip() != '#':  # 如果不在首页,则以当前所在位置,调用相应的函数。函数名是do_当前位置。
           # self.line = line
            command = in_where

        else:
            command = cmd_list.get(line.strip(),'help')  # 如果指令不存在,则使用help,只在首页有效果
        
 
        
        if command.startswith("pc_"):
            obj = obj_pc(line,fromUser)
        elif command.startswith("search_"):
            obj = obj_search(line,fromUser)
        elif command.startswith("login_"):
            obj = obj_login(line, fromUser)
        else:
            obj = self
        
        
        func = getattr(obj, 'do_' + command, None)
        try:
            request = func()
        except TypeError:
            request = self.do_help()

        return request
   	

    def do_list(self):
        from config import get_listDb
        listDb = map(lambda x: ' '.join(x[1:]), get_listDb())
        return "\n".join(listDb)
        
    
    def do_mess(self):
        from config import get_mess
        mess = get_mess()
        return mess
    
    def do_logout(self):
    
        kv_db.set(self.fromUser + "_where", "login_")
        self._do_clear()
        return u"账号已退出"
        
    
    # 下面开始与bug有关..........................................
    def do_bug(self):
        if check_login(self.fromUser):  # 同时具有查看是否登录成功效果
            no, bugs_list = self.__get_bugs_list()
            bugs_list_request = self.__get_bugs_request(bugs_list)
            
            return u"共有%s个问题\n%s" % (no,'\n'.join(bugs_list_request))
        else:
            return u"请输入正确的用户凭证\nlogin——登录\nlogout——退出登录"
        
    # 返回未解决问题的数量和未解决问题的列表,每个元素是 个tuple,里面是相关信息    
    def __get_bugs_list(self):
        from config import get_bugsList
        import random
        bugslist =  get_bugsList()
        bugs_list = []
        if bugslist.no > 0:
            bug = random.choice(bugslist.nolist)
            bugs_list.append((bug.PostTime,bug.Content,bug.Name,
                              bug.Phone,bug.Room,bug.Time))
            
        return bugslist.no,bugs_list
        
    def __get_bugs_request(self,bugs_list):
        bugs_list_temp = [
                          u"提交时间: %s",
                          u"故障内容: %s",
                          u"姓名: %s",
                          u"联系方式: %s",
                          u"寝室: %s",
                          u"维修时间: %s",
                          ]
        bugs_list_request = []
        for bug in bugs_list:
            bugs_list_request.append('\n'.join([temp % value for temp,
                                                value in zip(bugs_list_temp,bug)]))
            
        return bugs_list_request
    #................................................................


class WeixinInterface:
    def __init__(self):
        self.handler=CommandHandler()

    def GET(self):
        data = web.input()
        signature=data.signature
        timestamp=data.timestamp
        nonce=data.nonce
        echostr=data.echostr
        #自己的token
        token="xxxxxxxxxxxxxxxx"
        #字典序排序
        list=[token,timestamp,nonce]
        list.sort()
        sha1=hashlib.sha1()
        map(sha1.update,list)
        hashcode=sha1.hexdigest()
        #sha1加密算法        
 
        #如果是来自微信的请求,则回复echostr
        if hashcode == signature:
            return echostr

    def POST(self):        
        str_xml = web.data() 
        xml = etree.fromstring(str_xml)
        msgType=xml.find("MsgType").text
        fromUser=xml.find("FromUserName").text
        toUser=xml.find("ToUserName").text
        
        if msgType == "event":
            mscontent = xml.find("Event").text
            if mscontent == "subscribe":
                content = u"#"
 
        if msgType == "text":
            content = xml.find("Content").text# 当msgType是event是无法找到Content的,所以这行代码,不能放在前面,要不会500
        return render.reply_text(fromUser,toUser,int(time.time()),u"%s"%self.handler.handle(content,fromUser))


一部分代码,还好的设计整个网站的时候,接口都留出来了,直接拿来调用下就行了.初学web开发,写得有点乱。。

实现的功能有:查看我们社团的最新公告,查看维修电脑的技术人员,提交电脑故障,技术人员可以登录账号,登录后,可以查看用户提交的问题。类似短信营业厅的使用方式


转载于:https://my.oschina.net/tuxpy/blog/310687

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值