blob: 29cd25f13deac8c01d633170da65eac3887af88d [file] [log] [blame]
Tang Cheng53ca4872012-11-05 14:00:43 +08001# -*- coding: utf-8
2"""
3一卡通webservice 请求 session 封装
4"""
5import urllib
6from datetime import datetime
7from tornado.httpclient import HTTPClient, HTTPRequest, HTTPError
8import json
9import traceback
10
11
12class 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
28class 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, "&timestamp=",
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
165class 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,
Cheng Tang05eec9b2013-07-09 09:33:37 +0800179 request_timeout=timeout,
Cheng Tange6e19a82013-05-09 11:45:37 +0800180 body=self._pack_body(request, timeout))
Tang Cheng53ca4872012-11-05 14:00:43 +0800181 http_resp = client.fetch(http_request)
182 except HTTPError, ex:
183 http_resp = ex.response
184 except:
185 traceback.print_exc()
186 return False
187
188 if not http_resp:
189 return False
190 self.status_code = http_resp.code
191 if http_resp.code != 200:
192 self.error_msg = '%d : %s' % (self.status_code, http_resp.body)
193 self.error_msg = self.error_msg.decode('utf-8', 'ignore')
194 else:
195 try:
196 response.unserialize(http_resp.body)
197 return True
198 except:
199 return False
200
Cheng Tange6e19a82013-05-09 11:45:37 +0800201 def _pack_body(self, request, timeout):
Tang Cheng53ca4872012-11-05 14:00:43 +0800202 funcdata = request.serialize()
203 request_token = self.session.gen_request_token()
Tang Cheng1a07ce72012-12-20 14:02:50 +0800204 if isinstance(funcdata, unicode):
205 request_token['funcdata'] = funcdata
206 elif isinstance(funcdata, str):
Tang Chengd36592e2012-12-20 14:24:27 +0800207 request_token['funcdata'] = funcdata.decode('gbk', 'ignore')
Cheng Tangb64f40c2013-07-16 13:40:36 +0800208 request_token['timeout'] = int(round(timeout, 0))
Tang Cheng53ca4872012-11-05 14:00:43 +0800209 return json.dumps(request_token, ensure_ascii=False)