Tang Cheng | 53ca487 | 2012-11-05 14:00:43 +0800 | [diff] [blame] | 1 | # -*- coding: utf-8
|
| 2 | """
|
| 3 | 一卡通webservice 请求 session 封装
|
| 4 | """
|
| 5 | import urllib
|
| 6 | from datetime import datetime
|
| 7 | from tornado.httpclient import HTTPClient, HTTPRequest, HTTPError
|
| 8 | import json
|
| 9 | import traceback
|
| 10 |
|
| 11 |
|
| 12 | class SWWebserviceError(BaseException):
|
| 13 | def __init__(self, code, msg):
|
| 14 | self.code = code
|
| 15 | self.msg = msg
|
| 16 |
|
| 17 | def __str__(self):
|
| 18 | try:
|
| 19 | msg = self.msg.encode('utf-8', 'ignore')
|
| 20 | except:
|
| 21 | msg = self.msg.encode('gbk', 'ignore')
|
| 22 | return "%d : %s" % (self.code, msg)
|
| 23 |
|
| 24 | def __unicode__(self):
|
| 25 | return u"%d: %s" % (self.code, self.msg)
|
| 26 |
|
| 27 |
|
| 28 | class SWWebserviceSession(object):
|
| 29 | """
|
| 30 | webservice session object
|
| 31 | example
|
| 32 |
|
| 33 | session = SWWebserviceSession('http://localhost:8080/yktapi/services',
|
| 34 | '123213','3334df334223',1)
|
| 35 |
|
| 36 | try:
|
| 37 | if not session.auth():
|
| 38 | print u"签到失败"
|
| 39 | except SWWebserviceError, ex:
|
| 40 | print "Error : %d , %s" % (ex.code, ex.msg)
|
| 41 |
|
| 42 | """
|
| 43 | def __init__(self, service_url, appid, appsecret, termid):
|
| 44 | self.service_url = service_url
|
| 45 | self.appid = appid
|
| 46 | self.appsecret = appsecret
|
| 47 | if isinstance(termid, int):
|
| 48 | self.termid = str(termid)
|
| 49 | elif isinstance(termid, float):
|
| 50 | self.termid = str(termid)
|
| 51 | else:
|
| 52 | self.termid = termid
|
| 53 | self.access_token = None
|
| 54 | self.session_key = None
|
| 55 | self.error_msg = None
|
| 56 | self.status_code = None
|
| 57 |
|
| 58 | def auth(self, timeout=10):
|
| 59 | """
|
| 60 | 签到
|
| 61 | """
|
| 62 | if not self._get_access_token(timeout):
|
| 63 | return False
|
| 64 | if not self._get_session_key(timeout):
|
| 65 | return False
|
| 66 | return True
|
| 67 |
|
| 68 | def logoff(self):
|
| 69 | """
|
| 70 | 签退
|
| 71 | """
|
| 72 | self.access_token = None
|
| 73 | self.session_key = None
|
| 74 |
|
| 75 | def is_logon(self):
|
| 76 | """
|
| 77 | 是否签到成功
|
| 78 | """
|
| 79 | return self.session_key != None
|
| 80 |
|
| 81 | def _get_access_token(self, timeout):
|
| 82 | url = ''.join((self.service_url, '/authservice/getauth/',
|
| 83 | self.appid, '/getaccesstoken?term_id=', self.termid))
|
| 84 | http_client = HTTPClient()
|
| 85 | try:
|
| 86 | response = http_client.fetch(url, connect_timeout=timeout,
|
| 87 | request_timeout=timeout)
|
| 88 | try:
|
| 89 | result = json.loads(response.body)
|
| 90 | self.access_token = result.get('access_token', None)
|
| 91 | if not self.access_token:
|
| 92 | raise SWWebserviceError(501, u"系统返回值正确")
|
| 93 | return True
|
| 94 | except:
|
| 95 | raise SWWebserviceError(500, u"无法解析返回值")
|
| 96 | except HTTPError, ex:
|
| 97 | if not ex.response:
|
| 98 | self.error_msg = u"检查与服务器的连接"
|
| 99 | return False
|
| 100 | self.status_code = ex.response.code
|
| 101 | self.error_msg = ex.response.body
|
| 102 | return False
|
| 103 |
|
| 104 | def _sign_data(self, key, data):
|
| 105 | import hmac
|
| 106 | import hashlib
|
| 107 | h = hmac.new(key, digestmod=hashlib.sha1)
|
| 108 | h.update(data)
|
| 109 | return (h.hexdigest(), 'HMAC')
|
| 110 |
|
| 111 | def _get_session_key(self, timeout):
|
| 112 | timestamp = self.nonce()
|
| 113 | sign, sign_meth = self._sign_data(self.appsecret,
|
| 114 | self.access_token + timestamp)
|
| 115 | r = (self.service_url, '/authservice/getauth/', self.appid,
|
| 116 | '?access_token=', self.access_token, '&term_id=', self.termid,
|
| 117 | "&sign_method=", sign_meth, "&sign=", sign, "×tamp=",
|
| 118 | timestamp, "&v=1")
|
| 119 | url = ''.join(r)
|
| 120 |
|
| 121 | http_client = HTTPClient()
|
| 122 | try:
|
| 123 | response = http_client.fetch(url, connect_timeout=timeout,
|
| 124 | request_timeout=timeout)
|
| 125 | try:
|
| 126 | result = json.loads(response.body)
|
| 127 | self.session_key = result.get('session_key', None)
|
| 128 | if not self.session_key:
|
| 129 | raise SWWebserviceError(501, u"系统返回值正确")
|
| 130 | return True
|
| 131 | except:
|
| 132 | raise SWWebserviceError(500, u"无法解析返回值")
|
| 133 | except HTTPError, ex:
|
| 134 | self.status_code = ex.response.code
|
| 135 | self.error_msg = ex.response.body
|
| 136 | return False
|
| 137 |
|
| 138 | def nonce(self):
|
| 139 | return datetime.now().strftime('%Y%m%d%H%M%S')
|
| 140 |
|
| 141 | def gen_request_token(self):
|
| 142 | """
|
| 143 | 生成请求 token
|
| 144 | """
|
| 145 | timestamp = self.nonce()
|
| 146 | token = ''.join((self.appid, self.termid,
|
| 147 | self.session_key, timestamp))
|
| 148 | sign, sign_meth = self._sign_data(self.appsecret, token)
|
| 149 | # params = urllib.urlencode(dict(app_id=appinfo.get('appid'),
|
| 150 | # term_id=appinfo.get('termid'),
|
| 151 | # sign_method="HMAC",
|
| 152 | # timestamp=timestamp,
|
| 153 | # sign=sign))
|
| 154 | return dict(timestamp=timestamp, sign=sign,
|
| 155 | app_id=self.appid, term_id=self.termid,
|
| 156 | sign_method=sign_meth)
|
| 157 |
|
| 158 | def request_token_urlencode(self, token):
|
| 159 | """
|
| 160 | 将 gen_request_token 返回的数据编码成请求url
|
| 161 | """
|
| 162 | return urllib.urlencode(token)
|
| 163 |
|
| 164 |
|
| 165 | class SWRequest(object):
|
| 166 | def __init__(self, session):
|
| 167 | self.session = session
|
| 168 | self.service_url = self.session.service_url + '/ecardservice/ecardapi'
|
| 169 | self.error_msg = None
|
| 170 |
|
| 171 | def request(self, request, response, timeout=10.0):
|
| 172 | if not self.session.is_logon():
|
| 173 | raise SWWebserviceError(u"session无效")
|
| 174 | client = HTTPClient()
|
| 175 | try:
|
| 176 | http_request = HTTPRequest(url=self.service_url, method='POST',
|
| 177 | headers={'Content-Type': 'application/json'},
|
| 178 | connect_timeout=timeout,
|
| 179 | body=self._pack_body(request))
|
| 180 | http_resp = client.fetch(http_request)
|
| 181 | except HTTPError, ex:
|
| 182 | http_resp = ex.response
|
| 183 | except:
|
| 184 | traceback.print_exc()
|
| 185 | return False
|
| 186 |
|
| 187 | if not http_resp:
|
| 188 | return False
|
| 189 | self.status_code = http_resp.code
|
| 190 | if http_resp.code != 200:
|
| 191 | self.error_msg = '%d : %s' % (self.status_code, http_resp.body)
|
| 192 | self.error_msg = self.error_msg.decode('utf-8', 'ignore')
|
| 193 | else:
|
| 194 | try:
|
| 195 | response.unserialize(http_resp.body)
|
| 196 | return True
|
| 197 | except:
|
| 198 | return False
|
| 199 |
|
| 200 | def _pack_body(self, request):
|
| 201 | funcdata = request.serialize()
|
| 202 | request_token = self.session.gen_request_token()
|
| 203 | request_token['funcdata'] = funcdata.decode('utf-8', 'ignore')
|
| 204 | return json.dumps(request_token, ensure_ascii=False)
|