sms_client.py 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. #! usr/bin/python
  2. # coding=utf-8
  3. # Copyright 2014 Baidu, Inc.
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
  6. # except in compliance with the License. You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software distributed under the
  11. # License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  12. # either express or implied. See the License for the specific language governing permissions
  13. # and limitations under the License.
  14. """
  15. This module provides a client class for SMS.
  16. """
  17. import copy
  18. import json
  19. import logging
  20. import uuid
  21. import http.client
  22. import baidubce.services.sms.model as model
  23. from baidubce import utils
  24. from baidubce.auth import bce_v1_signer
  25. from baidubce.bce_base_client import BceBaseClient
  26. from baidubce.bce_client_configuration import BceClientConfiguration
  27. from baidubce.exception import BceClientError
  28. from baidubce.exception import BceServerError
  29. from baidubce.http import bce_http_client
  30. from baidubce.http import http_headers
  31. from baidubce.http import http_methods
  32. from baidubce.services import sms
  33. from baidubce.utils import required
  34. _logger = logging.getLogger(__name__)
  35. def _parse_result(http_response, response):
  36. if http_response.status / 100 == http.client.CONTINUE / 100:
  37. raise BceClientError('Can not handle 1xx http status code')
  38. bse = None
  39. body = http_response.read()
  40. if body:
  41. d = json.loads(body)
  42. if 'message' in d and 'code' in d and 'requestId' in d:
  43. r_code = d['code']
  44. # 1000 means success
  45. if r_code != '1000':
  46. bse = BceServerError(d['message'],
  47. code=d['code'],
  48. request_id=d['requestId'])
  49. else:
  50. response.__dict__.update(
  51. json.loads(body, object_hook=utils.dict_to_python_object).__dict__)
  52. http_response.close()
  53. return True
  54. elif http_response.status / 100 == http.client.OK / 100:
  55. response.__dict__.update(
  56. json.loads(body, object_hook=utils.dict_to_python_object).__dict__)
  57. http_response.close()
  58. return True
  59. elif http_response.status / 100 == http.client.OK / 100:
  60. return True
  61. if bse is None:
  62. bse = BceServerError(http_response.reason, request_id=response.metadata.bce_request_id)
  63. bse.status_code = http_response.status
  64. raise bse
  65. class SmsClient(BceBaseClient):
  66. """
  67. Sms sdk client
  68. """
  69. def __init__(self, config=None):
  70. if config is not None:
  71. self._check_config_type(config)
  72. BceBaseClient.__init__(self, config)
  73. @required(config=BceClientConfiguration)
  74. def _check_config_type(self, config):
  75. return True
  76. @required(signature_id=str, template_id=str, type=str, mobile=str, content_var_dict=dict)
  77. def send_message(self, signature_id, template_id, mobile, content_var_dict, config=None, custom=None,
  78. user_ext_id=None, merchant_url_id=None):
  79. """
  80. Send message
  81. :param signature_id: The unique code identifying message signature, can be obtained from cloud.baidu.com
  82. :type signature_id: string or unicode
  83. :param template_id: The unique code identifying message content template, can be obtained from cloud.baidu.com
  84. :type template_id: string or unicode
  85. :param mobile: The target mobile, use "," as separators if you have multiple targets.
  86. :type mobile: string or unicode
  87. :param content_var_dict: A map like "{"template param name": "template param content"}
  88. :type content_var_dict: dict
  89. :param config: None
  90. :type config: BceClientConfiguration
  91. :param custom: The user-defined param
  92. :type custom: string or unicode
  93. :param user_ext_id: The user-defined channel code
  94. :type user_ext_id: string or unicode
  95. :param merchant_url_id: The id of callback url specified by user
  96. :type merchant_url_id: string or unicode
  97. :return: Object
  98. {
  99. "request_id": "5e6dacd5-8815-4183-8255-4ff079bf24e6",
  100. "code": "1000",
  101. "message": "成功",
  102. "data": [
  103. {
  104. "code": "1000",
  105. "message": "成功",
  106. "mobile": "13800138000",
  107. "message_id": "e325ea68-02c1-47ad-8844-c7b93cafaeba_13800138000"
  108. }
  109. ]
  110. }
  111. """
  112. data = {
  113. 'signatureId': signature_id,
  114. 'template': template_id,
  115. 'mobile': mobile,
  116. 'contentVar': content_var_dict,
  117. 'custom': custom,
  118. 'userExtId': user_ext_id,
  119. 'merchantUrlId': merchant_url_id
  120. }
  121. return self._send_request(http_methods.POST, 'sendSms', body=json.dumps(data), config=config, api_version=1)
  122. @required(content=str, content_type=str, country_type=str)
  123. def create_signature(self, content, content_type, description=None, country_type="DOMESTIC",
  124. signature_file_base_64=None, signature_file_format=None, config=None):
  125. """
  126. Create signature
  127. :param content: Signature content, only Chinese and English characters and numbers are allowed.
  128. :type content: string or unicode
  129. :param content_type: Signature type, one of "Enterprise, MobileApp, Web, WeChatPublic, Brand, Else"
  130. :type content_type: string or unicode
  131. :param description: Description of the signature
  132. :type description: string or unicode
  133. :param country_type: The country or region in which the template can be used. Default value is "DOMESTIC".
  134. The value of countryType could be DOMESTIC or INTERNATIONAL or GLOBAL.
  135. DOMESTIC: the template can only be used in Mainland China.
  136. INTERNATIONAL: the template can only be used out of Mainland China.
  137. GLOBAL: the template can only be used all over the world.
  138. :type country_type: string or unicode
  139. :param signature_file_base_64: The base64 encoding string of the signature certificate picture
  140. :type signature_file_base_64: string or unicode
  141. :param signature_file_format: The format of the signature certificate picture, only one of JPG, PNG,
  142. JPEG allowed.
  143. :type signature_file_format: string or unicode
  144. :param config: None
  145. :type config: BceClientConfiguration
  146. :return: Object
  147. {
  148. "signature_id": "sms-sign-WWejWQ54455",
  149. "status": "SUBMITTED"
  150. }
  151. """
  152. data = {
  153. "content": content,
  154. "contentType": content_type,
  155. "countryType": country_type
  156. }
  157. if description:
  158. data["description"] = description
  159. if signature_file_base_64:
  160. data["signatureFileBase64"] = signature_file_base_64
  161. if signature_file_format:
  162. data["signatureFileFormat"] = signature_file_format
  163. return model.CreateSignatureResponse(self._send_request(http_methods.POST, 'signatureApply',
  164. params={"clientToken": uuid.uuid4()},
  165. body=json.dumps(data), config=config, api_version=2))
  166. @required(content=str, content_type=str, country_type=str, signature_id=str)
  167. def update_signature(self, content, content_type, country_type, signature_id, description=None,
  168. signature_file_base_64=None, signature_file_format=None, config=None):
  169. """
  170. Update signature
  171. :param content: Signature content
  172. :type content: string or unicode
  173. :param content_type: Signature type, one of "Enterprise, MobileApp, Web, WeChatPublic, Brand, Else"
  174. :type content_type: string or unicode
  175. :param signature_id: The unique code identifying the signature
  176. :type signature_id: string or unicode
  177. :param description: Description of the signature
  178. :type description: string or unicode
  179. :param country_type: The country or region in which the template can be used.
  180. The value of countryType could be DOMESTIC or INTERNATIONAL or GLOBAL.
  181. DOMESTIC: the template can only be used in Mainland China.
  182. INTERNATIONAL: the template can only be used out of Mainland China.
  183. GLOBAL: the template can only be used all over the world.
  184. :type country_type: string or unicode
  185. :param signature_file_base_64: The base64 encoding string of the signature certificate picture
  186. :type signature_file_base_64: string or unicode
  187. :param signature_file_format: The format of the signature certificate picture, only one of JPG, PNG,
  188. JPEG allowed.
  189. :type signature_file_format: string or unicode
  190. :param config: None
  191. :type config: BceClientConfiguration
  192. :return: Object
  193. {
  194. "content": "Baidu",
  195. "content_type": "Enterprise",
  196. "description": "test sdk",
  197. "country_type": "DOMESTIC",
  198. "signature_file_base64": "test-string-base64encoded",
  199. "signature_file_format": "png"
  200. }
  201. """
  202. data = {
  203. "content": content,
  204. "contentType": content_type,
  205. "countryType": country_type
  206. }
  207. if description:
  208. data["description"] = description
  209. if signature_file_base_64:
  210. data["signatureFileBase64"] = signature_file_base_64
  211. if signature_file_format:
  212. data["signatureFileFormat"] = signature_file_format
  213. return self._send_request(http_methods.PUT, 'signatureApply', key=signature_id,
  214. body=json.dumps(data), config=config, api_version=2)
  215. @required(signature_id=str)
  216. def get_signature_detail(self, signature_id, config=None):
  217. """
  218. Get signature detail
  219. :param signature_id: The unique code identifying the signature
  220. :type signature_id: string or unicode
  221. :param config: None
  222. :type config: BceClientConfiguration
  223. :return: Object
  224. {
  225. "signature_id": "sms-sign-WWejWQ54455",
  226. "user_id": "bbede3f8c42e4113b6971fd09a57f494",
  227. "content": "Baidu",
  228. "content_type": "MobileApp",
  229. "description": "test sdk",
  230. "review": "",
  231. "status": "SUBMITTED",
  232. "country_type": "GLOBAL",
  233. }
  234. """
  235. return model.GetSignatureResponse(self._send_request(http_methods.GET, 'signatureApply', key=signature_id,
  236. config=config, api_version=2))
  237. @required(signature_id=str)
  238. def delete_signature(self, signature_id, config=None):
  239. """
  240. Delete signature
  241. :param signature_id: The unique code identifying the signature
  242. :type signature_id: string or unicode
  243. :param config: None
  244. :type config: BceClientConfiguration
  245. :return:
  246. """
  247. return self._send_request(http_methods.DELETE, 'signatureApply', key=signature_id, config=config, api_version=2)
  248. @required(name=str, content=str, sms_type=str, country_type=str, description=str)
  249. def create_template(self, name, content, sms_type, country_type, description, config=None):
  250. """
  251. Create template with specific name and content
  252. :param name: Template name
  253. :type name: string or unicode
  254. :param content: Template content like 'this is ${APP}, your code is ${VID}'
  255. :type content: string or unicode
  256. :param sms_type: Business type of the template content, can be obtained from cloud.baidu.com
  257. :type sms_type: string or unicode
  258. :param country_type: The country or region in which the template can be used.
  259. The value of countryType could be DOMESTIC or INTERNATIONAL or GLOBAL.
  260. DOMESTIC: the template can only be used in Mainland China.
  261. INTERNATIONAL: the template can only be used out of Mainland China.
  262. GLOBAL: the template can only be used all over the world.
  263. :type country_type: string or unicode
  264. :param description: Description of the template
  265. :type description: string or unicode
  266. :param config: None
  267. :type config: BceClientConfiguration
  268. :return: Object
  269. {
  270. "template_id": "sms-tmpl-wHoJXL09355",
  271. "status": "SUBMITTED",
  272. }
  273. :rtype: baidubce.bce_response.BceResponse
  274. """
  275. data = {'name': name,
  276. 'content': content,
  277. 'smsType': sms_type,
  278. 'countryType': country_type,
  279. 'description': description}
  280. return model.CreateTemplateResponse(self._send_request(http_methods.POST, 'template',
  281. params={"clientToken": uuid.uuid4()},
  282. body=json.dumps(data), config=config, api_version=2))
  283. @required(template_id=str, name=str, content=str, sms_type=str, country_type=str)
  284. def update_template(self, template_id, name, content, sms_type, country_type, description=None, config=None):
  285. """
  286. Update template when audition failed.
  287. :param template_id: The unique code identifying the template
  288. :type template_id: string or unicode
  289. :param name: the name of template
  290. :type name: string or unicode
  291. :param content: the content of template,such as 'this is ${APP}, your code is ${VID}'
  292. :type content: string or unicode
  293. :param sms_type: The business type of the template content, can be obtained from cloud.baidu.com
  294. :type sms_type: string or unicode
  295. :param country_type: The country or region in which the template can be used.
  296. The value of countryType could be DOMESTIC or INTERNATIONAL or GLOBAL.
  297. DOMESTIC: the template can only be used in Mainland China.
  298. INTERNATIONAL: the template can only be used out of Mainland China.
  299. GLOBAL: the template can only be used all over the world.
  300. :type country_type: string or unicode
  301. :param description: Description of the template
  302. :type description: string or unicode
  303. :param config: None
  304. :type config: BceClientConfiguration
  305. :return:
  306. """
  307. data = {'name': name,
  308. 'content': content,
  309. 'smsType': sms_type,
  310. 'countryType': country_type}
  311. if description:
  312. data["description"] = description
  313. return self._send_request(http_method=http_methods.PUT, function_name='template', key=template_id,
  314. body=json.dumps(data), config=config, api_version=2)
  315. @required(template_id=str)
  316. def get_template_detail(self, template_id, config=None):
  317. """
  318. Get template detail
  319. :param template_id: The ID of message template
  320. :type template_id: string or unicode
  321. :param config: None
  322. :type config: BceClientConfiguration
  323. :return:
  324. {
  325. "template_id": "sms-tmpl-wHoJXL09355",
  326. "user_id": "bbede3f8c42e4113b6971fd09a57f494",
  327. "name": "TemplateNameTest",
  328. "content": "${code}",
  329. "sms_type": "CommonNotice",
  330. "description": "test modify",
  331. "review": "通过",
  332. "status": "APPROVED",
  333. "country_type": "INTERNATIONAL",
  334. }
  335. """
  336. return model.GetTemplateResponse(self._send_request(http_methods.GET, function_name='template', key=template_id,
  337. config=config, api_version=2))
  338. @required(template_id=str)
  339. def delete_template(self, template_id, config=None):
  340. """
  341. Delete template
  342. :param template_id: The ID of message template
  343. :type template_id: string or unicode
  344. :param config: None
  345. :type config: BceClientConfiguration
  346. :return:
  347. """
  348. return self._send_request(http_method=http_methods.DELETE, function_name='template', key=template_id,
  349. config=config, api_version=2)
  350. def query_quota_rate(self, config=None):
  351. """
  352. Query quota and rate-limit detail
  353. :param config: None
  354. :type config: BceClientConfiguration
  355. :return:
  356. {
  357. "quota_oer_day": 100,
  358. "quota_per_month": 1000,
  359. "quota_remain_today": 100,
  360. "quota_remain_this_month": 1000,
  361. "apply_check_status": "PASS",
  362. "check_reply": "",
  363. "apply_quota_per_day": 10,
  364. "apply_quota_per_month": 10,
  365. "rate_limit_per_mobile_per_sign_by_minute": 5,
  366. "rate_limit_per_mobile_per_sign_by_hour": 10,
  367. "rate_limit_per_mobile_per_sign_by_day": 50,
  368. "rate_limit_white_list": true
  369. }
  370. """
  371. return model.QueryQuotaResponse(self._send_request(http_methods.GET, function_name="quota",
  372. params={"userQuery": ""}, config=config, api_version=2))
  373. @required(quota_per_day=int, quota_per_month=int, rate_limit_per_mobile_per_sign_by_minute=int,
  374. rate_limit_per_mobile_per_sign_by_hour=int, rate_limit_per_mobile_per_sign_by_day=int)
  375. def update_quota_rate(self, quota_per_day, quota_per_month, rate_limit_per_mobile_per_sign_by_minute,
  376. rate_limit_per_mobile_per_sign_by_hour, rate_limit_per_mobile_per_sign_by_day, config=None):
  377. """
  378. :param quota_per_day: Upper bound of the response-success request counts in one natural day.
  379. :type quota_per_day: int
  380. :param quota_per_month: Upper bound of the response-success request counts in one natural month.
  381. :type quota_per_month: int
  382. :param rate_limit_per_mobile_per_sign_by_minute: The limit with same mobile and signature in one minute
  383. :type rate_limit_per_mobile_per_sign_by_minute: int
  384. :param rate_limit_per_mobile_per_sign_by_hour: Hourly limit with same mobile and signature
  385. :type rate_limit_per_mobile_per_sign_by_hour: int
  386. :param rate_limit_per_mobile_per_sign_by_day: Daily rate limit with same mobile and signature
  387. :type rate_limit_per_mobile_per_sign_by_day: int
  388. :param config: None
  389. :type config: BceClientConfiguration
  390. :return:
  391. """
  392. data = {
  393. "quotaPerDay": quota_per_day,
  394. "quotaPerMonth": quota_per_month,
  395. "rateLimitPerMobilePerSignByMinute": rate_limit_per_mobile_per_sign_by_minute,
  396. "rateLimitPerMobilePerSignByHour": rate_limit_per_mobile_per_sign_by_hour,
  397. "rateLimitPerMobilePerSignByDay": rate_limit_per_mobile_per_sign_by_day
  398. }
  399. return self._send_request(http_methods.PUT, function_name="quota", body=json.dumps(data),
  400. config=config, api_version=2)
  401. @staticmethod
  402. def _get_path_v3(config, function_name=None, key=None):
  403. return utils.append_uri(sms.URL_PREFIX_V3, function_name, key)
  404. @staticmethod
  405. def _get_path_v3_2(config, function_name=None, key=None):
  406. return utils.append_uri(sms.URL_PREFIX_V3_2, function_name, key)
  407. @staticmethod
  408. def _bce_sms_sign(credentials, http_method, path, headers, params,
  409. timestamp=0, expiration_in_seconds=1800,
  410. headers_to_sign=None):
  411. headers_to_sign_list = [b"host",
  412. b"content-md5",
  413. b"content-length",
  414. b"content-type"]
  415. if headers_to_sign is None or len(headers_to_sign) == 0:
  416. headers_to_sign = []
  417. for k in headers:
  418. k_lower = k.strip().lower()
  419. if k_lower.startswith(http_headers.BCE_PREFIX) or k_lower in headers_to_sign_list:
  420. headers_to_sign.append(k_lower)
  421. headers_to_sign.sort()
  422. else:
  423. for k in headers:
  424. k_lower = k.strip().lower()
  425. if k_lower.startswith(http_headers.BCE_PREFIX):
  426. headers_to_sign.append(k_lower)
  427. headers_to_sign.sort()
  428. return bce_v1_signer.sign(credentials,
  429. http_method,
  430. path,
  431. headers,
  432. params,
  433. timestamp,
  434. expiration_in_seconds,
  435. headers_to_sign)
  436. def _merge_config(self, config):
  437. if config is None:
  438. return self.config
  439. else:
  440. self._check_config_type(config)
  441. new_config = copy.copy(self.config)
  442. new_config.merge_non_none_values(config)
  443. return new_config
  444. def _send_request(self, http_method, function_name=None, key=None, body=None, headers=None, params=None,
  445. config=None, body_parser=None, api_version=1):
  446. config = self._merge_config(config)
  447. path = {1: SmsClient._get_path_v3,
  448. 2: SmsClient._get_path_v3_2,
  449. }[api_version](config, function_name, key)
  450. if body_parser is None:
  451. body_parser = _parse_result
  452. if headers is None:
  453. headers = {b'Accept': b'*/*', b'Content-Type': b'application/json;charset=utf-8'}
  454. return bce_http_client.send_request(config, SmsClient._bce_sms_sign, [body_parser], http_method, path, body,
  455. headers, params)
  456. @required(type=str, phone=str)
  457. def create_mobile_black(self, type, phone, country_type, sms_type=None, signature_id_str=None, config=None):
  458. """
  459. :param type: The value of type could be MerchantBlack or SignatureBlack
  460. :type type: str
  461. :param country_type: The value of countryType could be DOMESTIC or INTERNATIONAL
  462. :type country_type: str
  463. :param sms_type: Mobile of black, Support multiple mobile phone numbers, up to 200 maximum, separated by comma.
  464. :type sms_type: str
  465. :param signature_id_str: When the value of "type" is "SignatureBlack", this field is required.
  466. :type signature_id_str: str
  467. :param phone: When the value of "type" is "SignatureBlack", this field is required.
  468. :type phone: str
  469. :param config: None
  470. :type config: BceClientConfiguration
  471. """
  472. data = {
  473. "type": type,
  474. "phone": phone,
  475. "countryType": country_type
  476. }
  477. if sms_type:
  478. data["smsType"] = sms_type
  479. if signature_id_str:
  480. data["signatureIdStr"] = signature_id_str
  481. return self._send_request(http_methods.POST, function_name="blacklist", body=json.dumps(data),
  482. config=config, api_version=2)
  483. def get_mobile_black(self, phone=None, country_type=None, sms_type=None, signature_id_str=None, start_time=None,
  484. end_time=None, page_no=None, page_size=None, config=None):
  485. """
  486. Get mobile black
  487. :param phone: Support multiple mobile phone numbers, up to 200 maximum, separated by comma.
  488. :type phone: str
  489. :param country_type: The value of countryType could be DOMESTIC or INTERNATIONAL
  490. :type country_type: str
  491. :param sms_type: smsType
  492. :type sms_type: str
  493. :param signature_id_str: signatureIdStr
  494. :type signature_id_str: str
  495. :param start_time: format is yyyy-MM-dd
  496. :type start_time: str
  497. :param end_time: format is yyyy-MM-dd
  498. :type end_time: str
  499. :param page_no: The current page number
  500. :type page_no: int
  501. :param page_size: The current page size, range from 1 to 99999
  502. :type page_size: int
  503. :param config: None
  504. :type config: BceClientConfiguration
  505. :return: Object
  506. {
  507. "blacklists": [
  508. {
  509. "phone": "17611111111",
  510. "type": "SignatureBlack",
  511. "smsType": "CommonNotice",
  512. "signatureIdStr": "1234",
  513. "updateDate": "2023-07-14 14:23:41"
  514. }
  515. ],
  516. "totalCount": 1,
  517. "pageNo": 1,
  518. "pageSize": 100
  519. }
  520. """
  521. req_params = {}
  522. if phone:
  523. req_params["phone"] = phone
  524. if country_type:
  525. req_params["countryType"] = country_type
  526. if sms_type:
  527. req_params["smsType"] = sms_type
  528. if signature_id_str:
  529. req_params["signatureIdStr"] = signature_id_str
  530. if start_time:
  531. req_params["startTime"] = start_time
  532. if end_time:
  533. req_params["endTime"] = end_time
  534. if page_no:
  535. req_params["pageNo"] = page_no
  536. if page_size:
  537. req_params["pageSize"] = page_size
  538. return model.GetMobileBlackResponse(self._send_request(http_methods.GET, function_name="blacklist",
  539. params=req_params, config=config, api_version=2))
  540. @required(phones=str)
  541. def delete_mobile_black(self, phones, config=None):
  542. """
  543. Delete mobile_black
  544. :param phones: Support multiple mobile phone numbers, up to 200 maximum, separated by comma.
  545. :type phones: string
  546. :param config: None
  547. :type config: BceClientConfiguration
  548. :return:
  549. """
  550. req_params = {
  551. "phones": phones
  552. }
  553. return self._send_request(http_method=http_methods.DELETE, function_name='blacklist/delete', params=req_params,
  554. config=config, api_version=2)
  555. @required(start_time=str, end_time=str)
  556. def list_statistics(self, start_time, end_time, sms_type='all', country_type='domestic',
  557. signature_id=None, template_code=None, config=None):
  558. """
  559. Get messages statistics list
  560. :param start_time: The start of time condition, format: yyyy-MM-dd
  561. :type start_time: str
  562. :param end_time: The end of time condition, format: yyyy-MM-dd
  563. :type end_time: str
  564. :param sms_type: Queried message type, "all" as default
  565. :type sms_type: str
  566. :param signature_id: Queried signature id
  567. :type signature_id: str
  568. :param template_code: Queried template code, for instance: "sms-tmpl-xxxxxxxx"
  569. :type template_code: str
  570. :param country_type: Queried country type, available values: "domestic", "international"
  571. :type country_type: str
  572. :param config: None
  573. :type config: BceClientConfiguration
  574. :return: Object:
  575. {
  576. "statisticsResults": [
  577. {
  578. "datetime": "合计",
  579. "countryAlpha2Code": "",
  580. "submitLongCount": "10",
  581. "submitCount": "100",
  582. "deliverSuccessCount": "99",
  583. "deliverSuccessLongCount": "10",
  584. "deliverFailureCount": "1",
  585. "unknownCount": "0",
  586. "deliverSuccessProportion": "0.99",
  587. "deliverFailureProportion": "0.01",
  588. "notExistCount": "0",
  589. "signatureOrTemplateCount": "0",
  590. "abnormalCount": "0",
  591. "overclockingCount": "0",
  592. "otherErrorCount": "0",
  593. "blacklistCount": "0",
  594. "routeErrorCount": "0",
  595. "issueFailureCount": "0",
  596. "parameterErrorCount": "0",
  597. "illegalWordCount": "0",
  598. "anomalyCount": "1",
  599. "unknownErrorCount": "0",
  600. "receiptProportion": "1.0",
  601. "unknownProportion": "0",
  602. "responseSuccessCount": "100",
  603. "responseTimeoutCount": "0",
  604. "responseSuccessProportion": "1.0"
  605. },
  606. {
  607. "datetime": "2023-10-30",
  608. "countryAlpha2Code": "",
  609. "submitLongCount": "10",
  610. "submitCount": "100",
  611. "deliverSuccessCount": "99",
  612. "deliverSuccessLongCount": "10",
  613. "deliverFailureCount": "1",
  614. "unknownCount": "0",
  615. "deliverSuccessProportion": "0.99",
  616. "deliverFailureProportion": "0.01",
  617. "notExistCount": "0",
  618. "signatureOrTemplateCount": "0",
  619. "abnormalCount": "0",
  620. "overclockingCount": "0",
  621. "otherErrorCount": "0",
  622. "blacklistCount": "0",
  623. "routeErrorCount": "0",
  624. "issueFailureCount": "0",
  625. "parameterErrorCount": "0",
  626. "illegalWordCount": "0",
  627. "anomalyCount": "1",
  628. "unknownErrorCount": "0",
  629. "receiptProportion": "1.0",
  630. "unknownProportion": "0",
  631. "responseSuccessCount": "100",
  632. "responseTimeoutCount": "0",
  633. "responseSuccessProportion": "1.0"
  634. },
  635. ]
  636. }
  637. """
  638. req_params = {
  639. "startTime": start_time + " 00:00:00",
  640. "endTime": end_time + " 23:59:59",
  641. "smsType": sms_type,
  642. "dimension": "day"
  643. }
  644. if country_type:
  645. req_params["countryType"] = country_type
  646. if signature_id:
  647. req_params["signatureId"] = signature_id
  648. if template_code:
  649. req_params["templateCode"] = template_code
  650. return model.ListStatisticsResponse(self._send_request(http_method=http_methods.GET, function_name='summary',
  651. params=req_params, config=config, api_version=2))
  652. @required(user_id=str)
  653. def get_prepaid_packages(self, user_id, country_type=None, package_status=None,
  654. page_no=1, page_size=10, config=None):
  655. """
  656. Get merchant's prepaid_packages list
  657. :param user_id: Queried user id
  658. :type user_id: str
  659. :param country_type: Queried country type, available values: "domestic", "international", "global"
  660. :type country_type: str
  661. :param package_status: Queried package status, available values: "RUNNING", "EXPIRED", "USED_UP", "DESTROYED"
  662. :type package_status: str
  663. :param page_no: Queried page no, optional, need more than 0
  664. :type page_no: int
  665. :param page_size: Queried page size, optional, need more than 0
  666. :type page_size: int
  667. :param config: None
  668. :type config: BceClientConfiguration
  669. :return: Object:
  670. {
  671. "prepaidPackages": [
  672. {
  673. "packageId": "c983db8fdc1853fc78cdaf598458394c",
  674. "name": "国内普通短信包",
  675. "countryType": "DOMESTIC",
  676. "capacity": 5000.00,
  677. "remainingCapacity": 0.00,
  678. "packageStatus": "EXPIRED",
  679. "purchaseDate": "2022-01-07T08:53:52.000+00:00",
  680. "expiryDate": "2022-01-07T09:05:52.000+00:00"
  681. },
  682. {
  683. "packageId": "96c566bcb26a3dc0794e0e34dcad4edc",
  684. "name": "国内普通短信包",
  685. "countryType": "DOMESTIC",
  686. "capacity": 5000.00,
  687. "remainingCapacity": 0.00,
  688. "packageStatus": "EXPIRED",
  689. "purchaseDate": "2022-01-07T08:42:52.000+00:00",
  690. "expiryDate": "2022-01-07T08:54:52.000+00:00"
  691. },
  692. ]
  693. "totalCount":185
  694. }
  695. """
  696. req_params = {
  697. }
  698. if country_type:
  699. req_params["countryType"] = country_type
  700. if package_status:
  701. req_params["packageStatus"] = package_status
  702. if page_no > 0:
  703. req_params["pageNo"] = page_no
  704. if page_size > 0:
  705. req_params["pageSize"] = page_size
  706. return model.GetPrepaidPackageResponse(self._send_request(http_method=http_methods.GET,
  707. function_name='prepay/' + user_id,
  708. params=req_params, config=config,
  709. api_version=2))