You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
flyapps/fir_ser/api/utils/ali/yun/basic.py

226 lines
5.4 KiB

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Date: 2018/9/18
import hmac
import base64
import inspect
import logging
from urllib.parse import quote
from .. import BaseAli
from ..yun import api
from ..yun.api.base import BaseAliYunAPI
from ..tools import get_uuid
from ..tools import get_iso_8061_date
logger = logging.getLogger(__name__)
QUERY_STRING = None
def _get_signature(string_to_sign, secret, signer=hmac):
"""获取签名
"""
secret = "{}&".format(secret)
hmb = signer.new(secret.encode("utf-8"), string_to_sign.encode("utf-8"), "sha1").digest()
return quote(base64.standard_b64encode(hmb).decode("ascii"), safe="~")
def __pop_standard_urlencode(query):
ret = ""
for item in query:
if not item[1]:
continue
ret += quote(item[0], safe="~") + "=" + quote(item[1], safe="~") + "&"
return ret
def _compose_sign_string(query_params):
"""组成签名字符串
"""
sorted_parameters = sorted(query_params.items(), key=lambda url_params: url_params[0])
string_to_sign = __pop_standard_urlencode(sorted_parameters)
query_string = string_to_sign[:-1]
global QUERY_STRING
QUERY_STRING = query_string
tosign = "GET&%2F&" + quote(query_string, safe="~")
return tosign
def _is_api_endpoint(instance):
return issubclass(instance.__class__, BaseAliYunAPI)
class AliYunClient(BaseAli):
VERSION = "" # 每个接口都需要版本号
API_BASE_URL = "" # 阿里云api网关地址均从使用的接口定义
# 点播api
vod = api.AliYunVod()
# 短信api
sms = api.AliYunSms()
def __new__(cls, *args, **kwargs):
"""注册接口
"""
self = super(AliYunClient, cls).__new__(cls)
api_endpoints = inspect.getmembers(self, _is_api_endpoint)
for name, api_ins in api_endpoints:
api_cls = type(api_ins)
api_ins = api_cls(self)
setattr(self, name, api_ins)
return self
def __init__(self, app_id, secret, timeout=None, auto_retry=False):
super(AliYunClient, self).__init__(
timeout, auto_retry
)
self.app_id = app_id
self.secret = secret
def request(self, method, action, **kwargs):
"""构造请求用户授权的url
Parameters
----------
method : string
请求类型
action : string
API的命名,固定值,如发送短信API的值为:SendSms
kwargs : dict
请求参数
Returns
-------
dict
"""
query_string = ""
api_base_url = kwargs.pop("api_base_url", self.API_BASE_URL)
# 获取请求参数
if isinstance(kwargs.get("data", {}), dict):
data = kwargs["data"]
data["Action"] = action
# 封装公有请求参数
# 接口版本号
if "Version" not in data:
data["Version"] = kwargs.pop("version", self.VERSION)
# 时间戳
data["Timestamp"] = get_iso_8061_date()
# 签名算法名称
data["SignatureMethod"] = "HMAC-SHA1"
# 签名版本
data["SignatureVersion"] = "1.0"
# 随机码
data["SignatureNonce"] = get_uuid()
# access key
data["AccessKeyId"] = self.app_id
# 接口响应类型均为 `JSON`
data["Format"] = "JSON"
# 计算签名
string_to_sign = _compose_sign_string(data)
signature = _get_signature(string_to_sign, self.secret)
query_string = '?{}{}'.format(QUERY_STRING, "&" + "Signature=" + signature)
# 结果解析器, 如果需要定制可单独定制
result_processor = kwargs.pop("result_processor", None)
url = "{}{}".format(api_base_url, query_string)
res = self._http.request(
method=method,
url=url,
**kwargs
)
# res.raise_for_status()
return self._handle_result(res, method, url, result_processor, **kwargs)
def _handle_result(self, res, method=None, url=None,
result_processor=None, **kwargs):
"""结果解析
Parameters
----------
res : request instance
响应对象 response
method : string
请求方法
url : string
请求的 `url`
result_processor: func OR None
结果处理器
kwargs: dict
更多参数
Returns
-------
dict
"""
if not isinstance(res, dict):
result = res.json()
else:
result = res
if not isinstance(result, dict):
return result
if "Code" in result:
code = result.get("Code")
if code != "OK":
logger.error("AliApi {} 调用异常, Code {} Errmsg {}".format(
url, code, result.get("Message")
))
if code in []:
self.request(method, url, **kwargs)
return result if not result_processor else result_processor(result)
def get(self, url, **kwargs):
return self.request(
method="get",
action=url,
**kwargs
)
def post(self, url, **kwargs):
return self.request(
method="post",
action=url,
**kwargs
)