blob: 418c671ac31dfcce25fe083c85afe2fc794608f7 [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
Cheng Tang06013602014-04-18 21:12:55 +0800107 if isinstance(key, unicode):
108 key = key.encode('utf-8')
Tang Cheng53ca4872012-11-05 14:00:43 +0800109 h = hmac.new(key, digestmod=hashlib.sha1)
110 h.update(data)
111 return (h.hexdigest(), 'HMAC')
112
113 def _get_session_key(self, timeout):
114 timestamp = self.nonce()
115 sign, sign_meth = self._sign_data(self.appsecret,
116 self.access_token + timestamp)
117 r = (self.service_url, '/authservice/getauth/', self.appid,
118 '?access_token=', self.access_token, '&term_id=', self.termid,
119 "&sign_method=", sign_meth, "&sign=", sign, "&timestamp=",
120 timestamp, "&v=1")
121 url = ''.join(r)
122
123 http_client = HTTPClient()
124 try:
125 response = http_client.fetch(url, connect_timeout=timeout,
126 request_timeout=timeout)
127 try:
128 result = json.loads(response.body)
129 self.session_key = result.get('session_key', None)
130 if not self.session_key:
131 raise SWWebserviceError(501, u"系统返回值正确")
132 return True
133 except:
134 raise SWWebserviceError(500, u"无法解析返回值")
135 except HTTPError, ex:
136 self.status_code = ex.response.code
137 self.error_msg = ex.response.body
138 return False
139
140 def nonce(self):
141 return datetime.now().strftime('%Y%m%d%H%M%S')
142
143 def gen_request_token(self):
144 """
145 生成请求 token
146 """
147 timestamp = self.nonce()
148 token = ''.join((self.appid, self.termid,
149 self.session_key, timestamp))
150 sign, sign_meth = self._sign_data(self.appsecret, token)
151 # params = urllib.urlencode(dict(app_id=appinfo.get('appid'),
152 # term_id=appinfo.get('termid'),
153 # sign_method="HMAC",
154 # timestamp=timestamp,
155 # sign=sign))
156 return dict(timestamp=timestamp, sign=sign,
157 app_id=self.appid, term_id=self.termid,
158 sign_method=sign_meth)
159
160 def request_token_urlencode(self, token):
161 """
162 将 gen_request_token 返回的数据编码成请求url
163 """
164 return urllib.urlencode(token)
165
166
167class SWRequest(object):
168 def __init__(self, session):
169 self.session = session
170 self.service_url = self.session.service_url + '/ecardservice/ecardapi'
171 self.error_msg = None
172
173 def request(self, request, response, timeout=10.0):
174 if not self.session.is_logon():
175 raise SWWebserviceError(u"session无效")
176 client = HTTPClient()
177 try:
178 http_request = HTTPRequest(url=self.service_url, method='POST',
179 headers={'Content-Type': 'application/json'},
180 connect_timeout=timeout,
Cheng Tang05eec9b2013-07-09 09:33:37 +0800181 request_timeout=timeout,
Cheng Tange6e19a82013-05-09 11:45:37 +0800182 body=self._pack_body(request, timeout))
Tang Cheng53ca4872012-11-05 14:00:43 +0800183 http_resp = client.fetch(http_request)
184 except HTTPError, ex:
185 http_resp = ex.response
Cheng Tang06013602014-04-18 21:12:55 +0800186 print u"Error<{0}>".format(http_resp)
187 except BaseException:
Tang Cheng53ca4872012-11-05 14:00:43 +0800188 traceback.print_exc()
189 return False
190
191 if not http_resp:
Cheng Tang06013602014-04-18 21:12:55 +0800192 print u"Response is empty"
Tang Cheng53ca4872012-11-05 14:00:43 +0800193 return False
194 self.status_code = http_resp.code
195 if http_resp.code != 200:
196 self.error_msg = '%d : %s' % (self.status_code, http_resp.body)
197 self.error_msg = self.error_msg.decode('utf-8', 'ignore')
198 else:
199 try:
200 response.unserialize(http_resp.body)
201 return True
Cheng Tang06013602014-04-18 21:12:55 +0800202 except BaseException as e:
203 print u"Decode Error<{0}>".format(e)
Tang Cheng53ca4872012-11-05 14:00:43 +0800204 return False
205
Cheng Tange6e19a82013-05-09 11:45:37 +0800206 def _pack_body(self, request, timeout):
Tang Cheng53ca4872012-11-05 14:00:43 +0800207 funcdata = request.serialize()
208 request_token = self.session.gen_request_token()
Tang Cheng1a07ce72012-12-20 14:02:50 +0800209 if isinstance(funcdata, unicode):
210 request_token['funcdata'] = funcdata
211 elif isinstance(funcdata, str):
Tang Chengd36592e2012-12-20 14:24:27 +0800212 request_token['funcdata'] = funcdata.decode('gbk', 'ignore')
Cheng Tangb64f40c2013-07-16 13:40:36 +0800213 request_token['timeout'] = int(round(timeout, 0))
Tang Cheng53ca4872012-11-05 14:00:43 +0800214 return json.dumps(request_token, ensure_ascii=False)