blob: 657fc688fc3f25c3c6664f298654fd1397d5e3a2 [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,
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()
Tang Cheng1a07ce72012-12-20 14:02:50 +0800203 if isinstance(funcdata, unicode):
204 request_token['funcdata'] = funcdata
205 elif isinstance(funcdata, str):
Tang Chengd36592e2012-12-20 14:24:27 +0800206 request_token['funcdata'] = funcdata.decode('gbk', 'ignore')
Tang Cheng53ca4872012-11-05 14:00:43 +0800207 return json.dumps(request_token, ensure_ascii=False)