PYTHON SDK
v2.0.3
coolsms.py
이 파일의 문서화 페이지로 가기
1 # vi:set sw=4 ts=4 expandtab:
2 # -*- coding: utf8 -*-
3 
4 import sys
5 import hmac
6 import mimetypes
7 import uuid
8 import json
9 import time
10 import platform
11 
12 from hashlib import md5
13 from sdk.exceptions import CoolsmsException
14 from sdk.exceptions import CoolsmsSDKException
15 from sdk.exceptions import CoolsmsSystemException
16 from sdk.exceptions import CoolsmsServerException
17 
18 # sys.version_info.major is available in python version 2.7
19 # use sys.version_info[0] for python 2.6
20 if sys.version_info[0] == 2:
21  from httplib import HTTPSConnection
22  from httplib import HTTPConnection
23  from urllib import urlencode
24 else:
25  from http.client import HTTPSConnection
26  from http.client import HTTPConnection
27  from urllib.parse import urlencode
28 
29 ## @mainpage PYTHON SDK
30 # @section intro 소개
31 # - 소개 : Coolsms REST API SDK FOR PYTHON
32 # - 버전 : 2.0.3
33 # - 설명 : Coolsms REST API 를 이용 보다 빠르고 안전하게 문자메시지를 보낼 수 있는 PYTHON으로 만들어진 SDK 입니다.
34 # @section CreateInfo 작성 정보
35 # - 작성자 : Nurigo
36 # - 작성일 : 2016/08/09
37 # @section common 기타 정보
38 # - 저작권 GPL v2
39 # - Copyright (C) 2008-2016 NURIGO
40 # - http://www.coolsms.co.kr
41 
42 ## @class Coolsms
43 # @brief Gateway access url : https://api.coolsms.co.kr/{api type}/{verson}/{resource name}
44 class Coolsms:
45  # SDK Version
46  sdk_version = "2.0.3"
47 
48  # API Version
49  api_version = "2"
50 
51  # SMS Gateway address
52  host = 'api.coolsms.co.kr'
53 
54  # use secure channel as default
55  port = 443
56 
57  # API Key
58  api_key = None
59 
60  # API Secret
61  api_secret = None
62 
63  # API Name
64  api_name = "sms"
65 
66  # error handle
67  error_string = None
68 
69  # if True. use http connection
70  use_http_connection = False
71 
72  ## @brief initialize
73  # @param string api_key [required]
74  # @param string api_secret [required]
75  def __init__(self, api_key, api_secret):
76  self.api_key = api_key
77  self.api_secret = api_secret
78 
79  ## @brief get signature
80  # @return string timestamp, string salt, string signature
81  def __get_signature__(self):
82  salt = str(uuid.uuid1())
83  timestamp = str(int(time.time()))
84  data = timestamp + salt
85  return timestamp, salt, hmac.new(self.api_secret.encode(), data.encode(), md5)
86 
87  ## @brief http GET method request
88  # @param string resource [required]
89  # @param dictionary params [optional]
90  # @return JSONObject
91  def request_get(self, resource, params=dict()):
92  return self.request(resource, params)
93 
94  ## @brief http POST method request
95  # @param string resource [required]
96  # @param dictionary params [optional]
97  # @return JSONObject
98  def request_post(self, resource, params=dict()):
99  return self.request(resource, params, "POST")
100 
101  ## @brief http POST & GET method request process
102  # @param string resource [required]
103  # @param dictionary params [required]
104  # @param string method [optional] [default:"GET"]
105  # @return JSONObject
106  def request(self, resource, params, method="GET"):
107  params = self.set_base_params(params)
108  params_str = urlencode(params)
109  headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain",
110  "User-Agent": "sms-python"}
111  try:
112  # use_http_connection 이 True 라면 http 통신을 한다
113  if self.use_http_connection == True:
114  conn = HTTPConnection(self.host)
115  else:
116  conn = HTTPSConnection(self.host, self.port)
117 
118  # request method 에 따라 다르게 요청
119  if method == "GET":
120  conn.request("GET", "/%s/%s/%s?" % (self.api_name, self.api_version, resource) + params_str, None, headers)
121  else:
122  conn.request("POST", "/%s/%s/%s" % (self.api_name, self.api_version, resource), params_str, headers)
123 
124  response = conn.getresponse()
125  data = response.read().decode()
126  conn.close()
127  except Exception as e:
128  conn.close()
129  raise CoolsmsSystemException(e, 399)
130 
131  # https status code is not 200, raise Exception
132  if response.status != 200:
133  error_msg = response.reason
134  if data:
135  error_msg = data
136 
137  raise CoolsmsServerException(error_msg, response.status)
138 
139  obj = None
140  if data:
141  obj = json.loads(data)
142 
143  return obj
144 
145  ## @brief http POST method multipart form request
146  # @param string resource [required]
147  # @param dictionary params [optional]
148  # @param dictionary files [optional]
149  # @return JSONObject
150  def request_post_multipart(self, resource, params, files):
151  host = self.host + ':' + str(self.port)
152  selector = "/%s/%s/%s" % (self.api_name, self.api_version, resource)
153 
154  params = self.set_base_params(params)
155 
156  content_type, body = self.encode_multipart_formdata(params, files)
157 
158  try:
159  # use_http_connection 이 True 라면 http 통신을 한다
160  if self.use_http_connection == True:
161  conn = HTTPConnection(self.host)
162  else:
163  conn = HTTPSConnection(self.host, self.port)
164 
165  conn.putrequest('POST', selector)
166  conn.putheader('Content-type', content_type)
167  conn.putheader('Content-length', str(len(body)))
168  conn.putheader('User-Agent', 'sms-python')
169  conn.endheaders()
170  conn.send(body)
171  response = conn.getresponse()
172  data = response.read().decode()
173  conn.close()
174  except Exception as e:
175  conn.close()
176  raise CoolsmsSystemException(e, 399)
177 
178  # https status code is not 200, raise Exception
179  if response.status != 200:
180  error_msg = response.reason
181  if data:
182  error_msg = data
183 
184  raise CoolsmsServerException(error_msg, response.status)
185 
186  # response data parsing
187  obj = None
188  if data:
189  obj = json.loads(data)
190 
191  return obj
192 
193  ## @brief format multipart form
194  # @param dictionary params [required]
195  # @param dictionary files [required]
196  # @return string content_type, string body
197  def encode_multipart_formdata(self, params, files):
198  boundary = str(uuid.uuid1())
199  crlf = '\r\n'
200 
201  l = []
202  for key, value in params.items():
203  l.append('--' + boundary)
204  l.append('Content-Disposition: form-data; name="%s"' % key)
205  l.append('')
206  l.append(value)
207 
208  for key, value in files.items():
209  l.append('--' + boundary)
210  l.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, value['filename']))
211  l.append('Content-Type: %s' % self.get_content_type(value['filename']))
212  l.append('')
213  l.append(str(value['content']))
214 
215  l.append('--' + boundary + '--')
216  l.append('')
217  body = crlf.join(l).encode('utf-8')
218 
219  content_type = 'multipart/form-data; boundary=%s' % boundary
220 
221  return content_type, body
222 
223  ## @brief get content type
224  # @param string filesname [required]
225  # @return string content_type
226  def get_content_type(self, filename):
227  return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
228 
229  ## @brief set base parameter
230  # @param dictionary params [required]
231  # @return dictionary params
232  def set_base_params(self, params):
233  timestamp, salt, signature = self.__get_signature__()
234  base_params = {'api_key': self.api_key, 'timestamp': timestamp, 'salt': salt,
235  'signature': signature.hexdigest()}
236  params.update(base_params)
237  return params
238 
239  ## @brief check send data
240  # @param dictionary params [required]
241  # @return dictionary params
242  def check_send_data(self, params):
243  # require fields check
244  if all (k in params for k in ("to", "from", "text")) == False:
245  raise CoolsmsSDKException("parameter 'to', 'from', 'text' are required", 201)
246 
247  for key, val in params.items():
248  # ptyhon 2 version 에서 unicode 문제 해결
249  if key == "text" and sys.version_info[0] == 2:
250  text = val
251  t_temp = text.decode('utf-8')
252  text = t_temp.encode('utf-8')
253  text = unicode(text, encoding='utf-8')
254  params['text'] = text
255 
256  # convert list to a comma seperated string
257  if key == "to" and val == list:
258  params['to'] = ','.join(to)
259 
260  # message type check
261  if key == "type" and val.lower() not in ['sms', 'lms', 'mms', 'ata', 'cta']:
262  raise CoolsmsSDKException("message type is not supported", 201)
263 
264  return params
265 
266  ## @brief set api name and api version
267  # @param string api_name [required] 'sms', 'senderid', 'image'
268  # @param integer api_version [required]
269  def set_api_config(self, api_name, api_version):
270  self.api_name = api_name;
271  self.api_version = api_version;
272 
273  ## @brief use http connection
275  self.use_http_connection = True
def encode_multipart_formdata(self, params, files)
format multipart form
Definition: coolsms.py:197
def request_post_multipart(self, resource, params, files)
http POST method multipart form request
Definition: coolsms.py:150
def request_get(self, resource, params=dict())
http GET method request
Definition: coolsms.py:91
string api_version
Definition: coolsms.py:49
def __init__(self, api_key, api_secret)
initialize
Definition: coolsms.py:75
def set_base_params(self, params)
set base parameter
Definition: coolsms.py:232
bool use_http_connection
Definition: coolsms.py:70
def request_post(self, resource, params=dict())
http POST method request
Definition: coolsms.py:98
def get_content_type(self, filename)
get content type
Definition: coolsms.py:226
def __get_signature__(self)
get signature
Definition: coolsms.py:81
def request(self, resource, params, method="GET")
http POST & GET method request process
Definition: coolsms.py:106
Gateway access url : https://api.coolsms.co.kr/{api type}/{verson}/{resource name}.
Definition: coolsms.py:44
def check_send_data(self, params)
check send data
Definition: coolsms.py:242
def set_api_config(self, api_name, api_version)
set api name and api version
Definition: coolsms.py:269