parent
d9b0d3718c
commit
9f21a2f51e
@ -1,46 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/8/2 |
|
||||||
|
|
||||||
""" |
|
||||||
阿里巴巴旗下相关服务 |
|
||||||
|
|
||||||
蚂蚁金服 |
|
||||||
|
|
||||||
阿里云 |
|
||||||
|
|
||||||
因阿里云权限访问控制, 可能每种服务都会映射到一个访问key和秘钥(当然也可以用最大权限) |
|
||||||
|
|
||||||
""" |
|
||||||
|
|
||||||
import logging |
|
||||||
import requests |
|
||||||
|
|
||||||
logger = logging.getLogger(__name__) |
|
||||||
|
|
||||||
|
|
||||||
class BaseAli(object): |
|
||||||
API_BASE_URL = "" |
|
||||||
|
|
||||||
_http = requests.session() |
|
||||||
|
|
||||||
def __init__(self, timeout, auto_retry=False): |
|
||||||
self.timeout = timeout |
|
||||||
self.auto_retry = auto_retry |
|
||||||
|
|
||||||
def request(self, *args, **kwargs): |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
def get(self, url, **kwargs): |
|
||||||
return self.request( |
|
||||||
method="get", |
|
||||||
url_or_endpoint=url, |
|
||||||
**kwargs |
|
||||||
) |
|
||||||
|
|
||||||
def post(self, url, **kwargs): |
|
||||||
return self.request( |
|
||||||
method="post", |
|
||||||
url_or_endpoint=url, |
|
||||||
**kwargs |
|
||||||
) |
|
@ -1,58 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/8/2 |
|
||||||
|
|
||||||
""" |
|
||||||
阿里 api 调用出口 |
|
||||||
|
|
||||||
封装更易用的api |
|
||||||
""" |
|
||||||
|
|
||||||
from django.conf import settings |
|
||||||
from django.utils.functional import LazyObject |
|
||||||
|
|
||||||
from .pay.basic import AliPay |
|
||||||
from .yun.basic import AliYunClient |
|
||||||
|
|
||||||
|
|
||||||
class AliApi(object): |
|
||||||
# 默认的支付配置 |
|
||||||
DEFAULT_ALI_PAY_CONFIG = settings.THIRD_PART_CONFIG["ALI_PAY"]["default"] |
|
||||||
# 指定的支付配置(业务拓展) |
|
||||||
SPECIFIC_ALI_PAY_CONFIG = settings.THIRD_PART_CONFIG["ALI_PAY"].get("pay") or DEFAULT_ALI_PAY_CONFIG |
|
||||||
# 注册云配置 |
|
||||||
ALI_YUN_CONFIG = settings.THIRD_PART_CONFIG["ALI_YUN"] |
|
||||||
|
|
||||||
def __init__(self, ): |
|
||||||
# 支付类业务 |
|
||||||
self.pay = AliPay( |
|
||||||
app_id=self.SPECIFIC_ALI_PAY_CONFIG["app_id"], |
|
||||||
app_private_key_path=self.SPECIFIC_ALI_PAY_CONFIG["app_private_key_path"], |
|
||||||
ali_public_key_path=self.SPECIFIC_ALI_PAY_CONFIG["alipay_public_key_path"], |
|
||||||
notify_url=self.SPECIFIC_ALI_PAY_CONFIG["callback_url"], |
|
||||||
return_url=self.SPECIFIC_ALI_PAY_CONFIG["callback_url"], |
|
||||||
debug=self.SPECIFIC_ALI_PAY_CONFIG["debug"] |
|
||||||
) |
|
||||||
# 转账类业务 |
|
||||||
self.transfer = AliPay( |
|
||||||
app_id=self.DEFAULT_ALI_PAY_CONFIG["app_id"], |
|
||||||
app_private_key_path=self.DEFAULT_ALI_PAY_CONFIG["app_private_key_path"], |
|
||||||
ali_public_key_path=self.DEFAULT_ALI_PAY_CONFIG["alipay_public_key_path"], |
|
||||||
notify_url=self.SPECIFIC_ALI_PAY_CONFIG["callback_url"], |
|
||||||
return_url=self.SPECIFIC_ALI_PAY_CONFIG["callback_url"], |
|
||||||
debug=self.DEFAULT_ALI_PAY_CONFIG["debug"] |
|
||||||
) |
|
||||||
# 阿里云业务 |
|
||||||
self.yun = AliYunClient( |
|
||||||
app_id=self.ALI_YUN_CONFIG.get("ACCESS_KEY"), |
|
||||||
secret=self.ALI_YUN_CONFIG.get("SECRET") |
|
||||||
) |
|
||||||
|
|
||||||
|
|
||||||
class DefaultApi(LazyObject): |
|
||||||
|
|
||||||
def _setup(self): |
|
||||||
self._wrapped = AliApi() |
|
||||||
|
|
||||||
|
|
||||||
ali_api = DefaultApi() |
|
@ -1,3 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/8/2 |
|
@ -1,3 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/8/2 |
|
@ -1,13 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/8/2 |
|
||||||
|
|
||||||
""" |
|
||||||
实名认证相关接口实现, 实名认证三步走 |
|
||||||
|
|
||||||
认证初始化 > 开始认证 > 认证查询 |
|
||||||
""" |
|
||||||
|
|
||||||
|
|
||||||
class AliCertification(object): |
|
||||||
pass |
|
@ -1,3 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/8/2 |
|
@ -1,3 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/8/2 |
|
@ -1,10 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/8/2 |
|
||||||
|
|
||||||
|
|
||||||
from .page import AliPage |
|
||||||
from .wap import AliWap |
|
||||||
from .app import AliApp |
|
||||||
from .transfer import AliTransfer |
|
||||||
from .order import AliOrder |
|
@ -1,82 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/8/2 |
|
||||||
|
|
||||||
|
|
||||||
""" |
|
||||||
App支付 |
|
||||||
""" |
|
||||||
|
|
||||||
import logging |
|
||||||
|
|
||||||
from .base import BaseAliPayAPI |
|
||||||
|
|
||||||
logger = logging.getLogger(__name__) |
|
||||||
|
|
||||||
|
|
||||||
class AliApp(BaseAliPayAPI): |
|
||||||
|
|
||||||
def direct(self, subject, out_trade_no, total_amount, notify_url=None, return_url=None, **kwargs): |
|
||||||
"""App快速下单接口 |
|
||||||
|
|
||||||
文档DOC地址: https://docs.open.alipay.com/203/105288/ |
|
||||||
|
|
||||||
Parameters |
|
||||||
---------- |
|
||||||
|
|
||||||
subject : string |
|
||||||
订单标题 |
|
||||||
|
|
||||||
out_trade_no : string |
|
||||||
商户订单号唯一凭证 |
|
||||||
|
|
||||||
total_amount : string or float or int |
|
||||||
支付金额,单位元,精确到分 |
|
||||||
|
|
||||||
notify_url: string |
|
||||||
|
|
||||||
支付宝服务器主动通知商户服务器里指定的页面http/https路径 |
|
||||||
|
|
||||||
example: http://www.alipay.com/pay |
|
||||||
|
|
||||||
return_url: string |
|
||||||
|
|
||||||
同步返回地址,HTTP/HTTPS开头字符串 |
|
||||||
|
|
||||||
kwargs : dict |
|
||||||
以下均为可选参数 |
|
||||||
|
|
||||||
body : string |
|
||||||
订单描述 |
|
||||||
|
|
||||||
goods_detail : json |
|
||||||
订单包含的商品列表信息,Json格式: {"show_url":"https://或http://打头的商品的展示地址"} |
|
||||||
在支付时,可点击商品名称跳转到该地址 |
|
||||||
|
|
||||||
passback_params : string |
|
||||||
公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。 |
|
||||||
支付宝只会在异步通知时将该参数原样返回。 |
|
||||||
本参数必须进行UrlEncode之后才可以发送给支付宝 |
|
||||||
|
|
||||||
goods_type : int |
|
||||||
商品主类型:0; 虚拟类商品,1; 实物类商品(默认) |
|
||||||
|
|
||||||
extend_params : |
|
||||||
业务扩张参数(主要用于接入花呗分期) |
|
||||||
|
|
||||||
Returns |
|
||||||
------- |
|
||||||
dict |
|
||||||
""" |
|
||||||
|
|
||||||
biz_content = { |
|
||||||
"subject": subject, |
|
||||||
"out_trade_no": out_trade_no, |
|
||||||
"total_amount": total_amount, |
|
||||||
"product_code": "QUICK_MSECURITY_PAY", # 销售产品码,目前仅支持这个类型 |
|
||||||
# "qr_pay_mode":4 |
|
||||||
} |
|
||||||
|
|
||||||
biz_content.update(**kwargs) |
|
||||||
|
|
||||||
return self._generate_url("alipay.trade.app.pay", biz_content, notify_url, return_url) |
|
@ -1,31 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/8/2 |
|
||||||
|
|
||||||
|
|
||||||
class BaseAliPayAPI(object): |
|
||||||
""" |
|
||||||
|
|
||||||
支付宝支付API基类 |
|
||||||
|
|
||||||
""" |
|
||||||
|
|
||||||
def __init__(self, client=None): |
|
||||||
self._client = client |
|
||||||
|
|
||||||
def _get(self, url, **kwargs): |
|
||||||
if hasattr(self, "API_BASE_URL"): |
|
||||||
kwargs['api_base_url'] = getattr(self, "API_BASE_URL") |
|
||||||
return self._client.get(url, **kwargs) |
|
||||||
|
|
||||||
def _post(self, url, **kwargs): |
|
||||||
if hasattr(self, "API_BASE_URL"): |
|
||||||
kwargs['api_base_url'] = getattr(self, "API_BASE_URL") |
|
||||||
return self._client.post(url, **kwargs) |
|
||||||
|
|
||||||
def _generate_url(self, method, *args, **kwargs): |
|
||||||
return self._client.generate_url(method, *args, **kwargs) |
|
||||||
|
|
||||||
@property |
|
||||||
def app_id(self): |
|
||||||
return self._client.app_id |
|
@ -1,44 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/8/2 |
|
||||||
|
|
||||||
""" |
|
||||||
统一收单相关服务 |
|
||||||
""" |
|
||||||
|
|
||||||
import logging |
|
||||||
|
|
||||||
from .base import BaseAliPayAPI |
|
||||||
|
|
||||||
logger = logging.getLogger(__name__) |
|
||||||
|
|
||||||
|
|
||||||
class AliOrder(BaseAliPayAPI): |
|
||||||
|
|
||||||
def query(self, out_biz_no=None, trade_no=None, **kwargs): |
|
||||||
"""统一收单线下交易查询. |
|
||||||
|
|
||||||
Parameters |
|
||||||
---------- |
|
||||||
out_biz_no : string |
|
||||||
订单支付时传入的商户订单号,和支付宝交易号不能同时为空。 |
|
||||||
trade_no,out_trade_no如果同时存在优先取trade_no |
|
||||||
|
|
||||||
trade_no : string |
|
||||||
支付宝交易号,和商户订单号不能同时为空 |
|
||||||
|
|
||||||
Returns |
|
||||||
------- |
|
||||||
dict |
|
||||||
""" |
|
||||||
|
|
||||||
biz_content = { |
|
||||||
"out_biz_no": out_biz_no, |
|
||||||
"trade_no": trade_no |
|
||||||
} |
|
||||||
|
|
||||||
biz_content.update(kwargs) |
|
||||||
|
|
||||||
url = self._generate_url("alipay.trade.query", biz_content) |
|
||||||
|
|
||||||
return self._get(url) |
|
@ -1,81 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/8/2 |
|
||||||
|
|
||||||
""" |
|
||||||
PC支付场景 |
|
||||||
""" |
|
||||||
|
|
||||||
import logging |
|
||||||
|
|
||||||
from .base import BaseAliPayAPI |
|
||||||
|
|
||||||
logger = logging.getLogger(__name__) |
|
||||||
|
|
||||||
|
|
||||||
class AliPage(BaseAliPayAPI): |
|
||||||
|
|
||||||
def direct(self, subject, out_trade_no, total_amount, notify_url=None, return_url=None, **kwargs): |
|
||||||
"""PC快速下单接口 |
|
||||||
|
|
||||||
文档DOC地址: https://docs.open.alipay.com/270/alipay.trade.page.pay |
|
||||||
|
|
||||||
Parameters |
|
||||||
---------- |
|
||||||
|
|
||||||
subject : string |
|
||||||
订单标题 |
|
||||||
|
|
||||||
out_trade_no : string |
|
||||||
商户订单号唯一凭证 |
|
||||||
|
|
||||||
total_amount : string or float or int |
|
||||||
支付金额,单位元,精确到分 |
|
||||||
|
|
||||||
notify_url: string |
|
||||||
|
|
||||||
支付宝服务器主动通知商户服务器里指定的页面http/https路径 |
|
||||||
|
|
||||||
example: http://www.alipay.com/pay |
|
||||||
|
|
||||||
return_url: string |
|
||||||
|
|
||||||
同步返回地址,HTTP/HTTPS开头字符串 |
|
||||||
|
|
||||||
kwargs : dict |
|
||||||
以下均为可选参数 |
|
||||||
|
|
||||||
body : string |
|
||||||
订单描述 |
|
||||||
|
|
||||||
goods_detail : json |
|
||||||
订单包含的商品列表信息,Json格式: {"show_url":"https://或http://打头的商品的展示地址"} |
|
||||||
在支付时,可点击商品名称跳转到该地址 |
|
||||||
|
|
||||||
passback_params : string |
|
||||||
公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。 |
|
||||||
支付宝只会在异步通知时将该参数原样返回。 |
|
||||||
本参数必须进行UrlEncode之后才可以发送给支付宝 |
|
||||||
|
|
||||||
goods_type : int |
|
||||||
商品主类型:0; 虚拟类商品,1; 实物类商品(默认) |
|
||||||
|
|
||||||
extend_params : |
|
||||||
业务扩张参数(主要用于接入花呗分期) |
|
||||||
|
|
||||||
Returns |
|
||||||
------- |
|
||||||
dict |
|
||||||
""" |
|
||||||
|
|
||||||
biz_content = { |
|
||||||
"subject": subject, |
|
||||||
"out_trade_no": out_trade_no, |
|
||||||
"total_amount": total_amount, |
|
||||||
"product_code": "FAST_INSTANT_TRADE_PAY", # 销售产品码,目前仅支持这个类型 |
|
||||||
# "qr_pay_mode":4 |
|
||||||
} |
|
||||||
|
|
||||||
biz_content.update(**kwargs) |
|
||||||
|
|
||||||
return self._generate_url("alipay.trade.page.pay", biz_content, notify_url, return_url) |
|
@ -1,100 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/8/2 |
|
||||||
|
|
||||||
""" |
|
||||||
转账支付 `api` |
|
||||||
""" |
|
||||||
|
|
||||||
import logging |
|
||||||
|
|
||||||
from .base import BaseAliPayAPI |
|
||||||
|
|
||||||
logger = logging.getLogger(__name__) |
|
||||||
|
|
||||||
|
|
||||||
class AliTransfer(BaseAliPayAPI): |
|
||||||
|
|
||||||
def transfer(self, out_biz_no, payee_account, amount, payee_real_name, is_verify=True, **kwargs): |
|
||||||
"""转账接口 |
|
||||||
|
|
||||||
在构建完成数据结构体之前进行验证码校验 |
|
||||||
|
|
||||||
该方法加入了 业务代码, 业务若有变动, 请根据实际需求进行更改 |
|
||||||
|
|
||||||
Parameters |
|
||||||
---------- |
|
||||||
out_biz_no : string |
|
||||||
商户转账唯一凭证 |
|
||||||
|
|
||||||
payee_account : string |
|
||||||
收款方账户 |
|
||||||
|
|
||||||
amount : string or int or float |
|
||||||
转账金额(单位: 元, 保留俩位小数, 最小转帐金额 0.1元) |
|
||||||
|
|
||||||
payee_real_name: string |
|
||||||
收款方真实姓名 |
|
||||||
|
|
||||||
is_verify: bool, default: True |
|
||||||
是否进行验证码校验 |
|
||||||
|
|
||||||
kwargs : dict |
|
||||||
以下均为可选参数 |
|
||||||
|
|
||||||
payer_show_name : string |
|
||||||
付款方姓名 |
|
||||||
|
|
||||||
remark : string |
|
||||||
转账备注(支持200个英文/100个汉字)。当付款方为企业账户,且转账金额达到(大于等于)50000元,remark不能为空。 |
|
||||||
收款方可见,会展示在收款用户的收支详情中。 |
|
||||||
|
|
||||||
Returns |
|
||||||
------- |
|
||||||
dict |
|
||||||
""" |
|
||||||
|
|
||||||
# 如果需要校验, 获取验证码进行校验, 校验不通过直接响应校验不通过 |
|
||||||
if is_verify: |
|
||||||
kwargs.pop("verify_code", None) |
|
||||||
|
|
||||||
biz_content = { |
|
||||||
"out_biz_no": out_biz_no, |
|
||||||
"payee_account": payee_account, |
|
||||||
"payee_type": "ALIPAY_LOGONID", # 收款方账户类型 |
|
||||||
"amount": amount, |
|
||||||
"payee_real_name": payee_real_name |
|
||||||
} |
|
||||||
|
|
||||||
biz_content.update(**kwargs) |
|
||||||
|
|
||||||
url = self._generate_url("alipay.fund.trans.toaccount.transfer", biz_content) |
|
||||||
|
|
||||||
return self._get(url) |
|
||||||
|
|
||||||
def query(self, out_biz_no, order_id, **kwargs): |
|
||||||
"""转账交易查询接口. |
|
||||||
|
|
||||||
Parameters |
|
||||||
---------- |
|
||||||
out_biz_no : string |
|
||||||
商户转账唯一凭证 |
|
||||||
|
|
||||||
order_id : string |
|
||||||
支付宝商户转账唯一凭证 |
|
||||||
|
|
||||||
Returns |
|
||||||
------- |
|
||||||
dict |
|
||||||
""" |
|
||||||
|
|
||||||
biz_content = { |
|
||||||
"out_biz_no": out_biz_no, |
|
||||||
"order_id": order_id |
|
||||||
} |
|
||||||
|
|
||||||
biz_content.update(kwargs) |
|
||||||
|
|
||||||
url = self._generate_url("alipay.fund.trans.order.query", biz_content) |
|
||||||
|
|
||||||
return self._get(url) |
|
@ -1,81 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/8/2 |
|
||||||
|
|
||||||
""" |
|
||||||
手机网站支付 |
|
||||||
""" |
|
||||||
|
|
||||||
import logging |
|
||||||
|
|
||||||
from .base import BaseAliPayAPI |
|
||||||
|
|
||||||
logger = logging.getLogger(__name__) |
|
||||||
|
|
||||||
|
|
||||||
class AliWap(BaseAliPayAPI): |
|
||||||
|
|
||||||
def direct(self, subject, out_trade_no, total_amount, notify_url=None, return_url=None, **kwargs): |
|
||||||
"""WAP快速下单接口 |
|
||||||
|
|
||||||
文档DOC地址: https://docs.open.alipay.com/203/105288/ |
|
||||||
|
|
||||||
Parameters |
|
||||||
---------- |
|
||||||
|
|
||||||
subject : string |
|
||||||
订单标题 |
|
||||||
|
|
||||||
out_trade_no : string |
|
||||||
商户订单号唯一凭证 |
|
||||||
|
|
||||||
total_amount : string or float or int |
|
||||||
支付金额,单位元,精确到分 |
|
||||||
|
|
||||||
notify_url: string |
|
||||||
|
|
||||||
支付宝服务器主动通知商户服务器里指定的页面http/https路径 |
|
||||||
|
|
||||||
example: http://www.alipay.com/pay |
|
||||||
|
|
||||||
return_url: string |
|
||||||
|
|
||||||
同步返回地址,HTTP/HTTPS开头字符串 |
|
||||||
|
|
||||||
kwargs : dict |
|
||||||
以下均为可选参数 |
|
||||||
|
|
||||||
body : string |
|
||||||
订单描述 |
|
||||||
|
|
||||||
goods_detail : json |
|
||||||
订单包含的商品列表信息,Json格式: {"show_url":"https://或http://打头的商品的展示地址"} |
|
||||||
在支付时,可点击商品名称跳转到该地址 |
|
||||||
|
|
||||||
passback_params : string |
|
||||||
公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。 |
|
||||||
支付宝只会在异步通知时将该参数原样返回。 |
|
||||||
本参数必须进行UrlEncode之后才可以发送给支付宝 |
|
||||||
|
|
||||||
goods_type : int |
|
||||||
商品主类型:0; 虚拟类商品,1; 实物类商品(默认) |
|
||||||
|
|
||||||
extend_params : |
|
||||||
业务扩张参数(主要用于接入花呗分期) |
|
||||||
|
|
||||||
Returns |
|
||||||
------- |
|
||||||
dict |
|
||||||
""" |
|
||||||
|
|
||||||
biz_content = { |
|
||||||
"subject": subject, |
|
||||||
"out_trade_no": out_trade_no, |
|
||||||
"total_amount": total_amount, |
|
||||||
"product_code": "QUICK_WAP_WAY", # 销售产品码,目前仅支持这个类型 |
|
||||||
# "qr_pay_mode":4 |
|
||||||
} |
|
||||||
|
|
||||||
biz_content.update(**kwargs) |
|
||||||
|
|
||||||
return self._generate_url("alipay.trade.wap.pay", biz_content, notify_url, return_url) |
|
@ -1,198 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/8/2 |
|
||||||
|
|
||||||
import json |
|
||||||
import inspect |
|
||||||
|
|
||||||
from urllib.parse import quote_plus |
|
||||||
|
|
||||||
from Crypto.PublicKey import RSA |
|
||||||
|
|
||||||
from django.utils.timezone import now |
|
||||||
|
|
||||||
from .. import BaseAli |
|
||||||
from ..tools import calculate_signature |
|
||||||
from .api.base import BaseAliPayAPI |
|
||||||
from . import api |
|
||||||
|
|
||||||
|
|
||||||
def _is_api_endpoint(instance): |
|
||||||
return issubclass(instance.__class__, BaseAliPayAPI) |
|
||||||
|
|
||||||
|
|
||||||
class AliPay(BaseAli): |
|
||||||
# 在构造函数中初始化 |
|
||||||
API_BASE_URL = "" |
|
||||||
|
|
||||||
# PC支付 |
|
||||||
pc = api.AliPage() |
|
||||||
# Wap支付 |
|
||||||
wap = api.AliWap() |
|
||||||
# App支付 |
|
||||||
app = api.AliApp() |
|
||||||
# 转账 |
|
||||||
transfer = api.AliTransfer() |
|
||||||
# 统一收单相关 |
|
||||||
order = api.AliOrder() |
|
||||||
|
|
||||||
def __init__( |
|
||||||
self, app_id, app_private_key_path, ali_public_key_path, |
|
||||||
notify_url, return_url, debug, |
|
||||||
): |
|
||||||
|
|
||||||
# 如果是调试模式,则用调试api |
|
||||||
if debug: |
|
||||||
setattr(self, "API_BASE_URL", "https://openapi.alipaydev.com/gateway.do") |
|
||||||
else: |
|
||||||
setattr(self, "API_BASE_URL", "https://openapi.alipay.com/gateway.do") |
|
||||||
|
|
||||||
# 暂时用不到父类方法参数(设置默认值) |
|
||||||
super(AliPay, self).__init__(timeout=3, auto_retry=True) |
|
||||||
|
|
||||||
self.app_id = app_id |
|
||||||
self.notify_url = notify_url |
|
||||||
self.return_url = return_url |
|
||||||
|
|
||||||
# 加载应用的私钥 |
|
||||||
with open(app_private_key_path) as fp: |
|
||||||
self.app_private_key = RSA.importKey(fp.read()) |
|
||||||
|
|
||||||
# 加载支付宝公钥 |
|
||||||
with open(ali_public_key_path) as fp: |
|
||||||
self.ali_public_key = RSA.importKey(fp.read()) |
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs): |
|
||||||
self = super(AliPay, 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 request(self, method, url_or_endpoint, **kwargs): |
|
||||||
if not url_or_endpoint.startswith(('http://', 'https://')): |
|
||||||
api_base_url = kwargs.pop('api_base_url', self.API_BASE_URL) |
|
||||||
url = '{base}{endpoint}'.format( |
|
||||||
base=api_base_url, |
|
||||||
endpoint=url_or_endpoint |
|
||||||
) |
|
||||||
else: |
|
||||||
url = url_or_endpoint |
|
||||||
|
|
||||||
res = self._http.request( |
|
||||||
method=method, |
|
||||||
url=url, |
|
||||||
**kwargs |
|
||||||
) |
|
||||||
|
|
||||||
res.raise_for_status() |
|
||||||
|
|
||||||
return self._handle_result(res) |
|
||||||
|
|
||||||
def _handle_result(self, res): |
|
||||||
"""解析请求结果并校验签名 |
|
||||||
|
|
||||||
""" |
|
||||||
return res.json() |
|
||||||
|
|
||||||
def get_url_params(self, data): |
|
||||||
data.pop("sign", None) |
|
||||||
# 排序后[(k, v), ...] |
|
||||||
ordered_items = sorted( |
|
||||||
((k, v if not isinstance(v, dict) else json.dumps(v, separators=(',', ':'))) |
|
||||||
for k, v in data.items()) |
|
||||||
) |
|
||||||
# 拼接成待签名的字符串 |
|
||||||
unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in ordered_items) |
|
||||||
# 对上一步得到的字符串进行签名 |
|
||||||
sign = calculate_signature(unsigned_string.encode("utf-8"), self.app_private_key) |
|
||||||
# 处理URL |
|
||||||
quoted_string = "&".join("{0}={1}".format(k, quote_plus(v)) for k, v in ordered_items) |
|
||||||
# 添加签名,获得最终的订单信息字符串 |
|
||||||
signed_string = quoted_string + "&sign=" + quote_plus(sign) |
|
||||||
return signed_string |
|
||||||
|
|
||||||
def build_body(self, method, biz_content, notify_url=None, return_url=None): |
|
||||||
"""构建请求体 |
|
||||||
|
|
||||||
公有请求体 + 业务请求体 |
|
||||||
|
|
||||||
Parameters |
|
||||||
---------- |
|
||||||
method : string |
|
||||||
请求API |
|
||||||
|
|
||||||
biz_content: dict |
|
||||||
业务参数 |
|
||||||
|
|
||||||
notify_url: string, default: None |
|
||||||
异步通知地址 |
|
||||||
|
|
||||||
return_url: string, default: None |
|
||||||
同步地址 |
|
||||||
|
|
||||||
Returns |
|
||||||
------- |
|
||||||
请求参数: dict |
|
||||||
""" |
|
||||||
data = { |
|
||||||
"app_id": self.app_id, |
|
||||||
"method": method, |
|
||||||
"charset": "utf-8", |
|
||||||
"sign_type": "RSA2", |
|
||||||
"timestamp": now().strftime("%Y-%m-%d %H:%M:%S"), |
|
||||||
"version": "1.0", |
|
||||||
"biz_content": biz_content |
|
||||||
} |
|
||||||
|
|
||||||
# 同步回调 |
|
||||||
if notify_url is not None: |
|
||||||
data["notify_url"] = notify_url |
|
||||||
|
|
||||||
# 异步回调 |
|
||||||
if return_url is not None: |
|
||||||
data["return_url"] = return_url |
|
||||||
|
|
||||||
return data |
|
||||||
|
|
||||||
def generate_url(self, method, biz_content, notify_url=None, return_url=None): |
|
||||||
"""构建请求体. |
|
||||||
公有请求体 + 业务请求体 |
|
||||||
|
|
||||||
Parameters |
|
||||||
---------- |
|
||||||
method : string |
|
||||||
|
|
||||||
请求API |
|
||||||
|
|
||||||
biz_content: dict |
|
||||||
|
|
||||||
业务参数 |
|
||||||
|
|
||||||
notify_url: string, default: None |
|
||||||
|
|
||||||
异步通知 `url` |
|
||||||
|
|
||||||
return_url: string, default: None |
|
||||||
|
|
||||||
同步通知 `url` |
|
||||||
|
|
||||||
|
|
||||||
Returns |
|
||||||
------- |
|
||||||
string |
|
||||||
""" |
|
||||||
|
|
||||||
if notify_url is None: |
|
||||||
notify_url = self.notify_url |
|
||||||
|
|
||||||
if return_url is None: |
|
||||||
return_url = self.return_url |
|
||||||
|
|
||||||
body = self.build_body(method, biz_content, notify_url, return_url) |
|
||||||
|
|
||||||
params = self.get_url_params(body) |
|
||||||
|
|
||||||
return "{}?{}".format(self.API_BASE_URL, params) |
|
@ -1,69 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/8/2 |
|
||||||
|
|
||||||
import json |
|
||||||
import time |
|
||||||
import uuid |
|
||||||
|
|
||||||
from Crypto.Signature import PKCS1_v1_5 |
|
||||||
from Crypto.Hash import SHA256 |
|
||||||
|
|
||||||
from base64 import encodebytes |
|
||||||
from base64 import decodebytes |
|
||||||
|
|
||||||
|
|
||||||
def format_params(params): |
|
||||||
"""格式化参数 |
|
||||||
|
|
||||||
""" |
|
||||||
return sorted( |
|
||||||
((k, v if not isinstance(v, dict) else json.dumps(v, separators=(',', ':'))) for k, v in params.items()) |
|
||||||
) |
|
||||||
|
|
||||||
|
|
||||||
def verify_signature(params, api_key): |
|
||||||
"""验证签名 |
|
||||||
|
|
||||||
""" |
|
||||||
|
|
||||||
sign = params.pop("sign", "") |
|
||||||
|
|
||||||
if "sign_type" in params: |
|
||||||
params.pop("sign_type") |
|
||||||
|
|
||||||
# 针对字符串进行排序 |
|
||||||
ordered_items = format_params(params) |
|
||||||
message = "&".join(u"{}={}".format(k, v) for k, v in ordered_items) |
|
||||||
# 验签 |
|
||||||
signer = PKCS1_v1_5.new(api_key) |
|
||||||
digest = SHA256.new() |
|
||||||
digest.update(message.encode("utf8")) |
|
||||||
if signer.verify(digest, decodebytes(sign.encode("utf8"))): |
|
||||||
return True |
|
||||||
return False |
|
||||||
|
|
||||||
|
|
||||||
def calculate_signature(params, api_key): |
|
||||||
"""计算签名 |
|
||||||
|
|
||||||
""" |
|
||||||
signer = PKCS1_v1_5.new(api_key) |
|
||||||
signature = signer.sign(SHA256.new(params)) |
|
||||||
# base64 编码,转换为unicode表示并移除回车 |
|
||||||
sign = encodebytes(signature).decode("utf8").replace("\n", "") |
|
||||||
return sign |
|
||||||
|
|
||||||
|
|
||||||
def get_uuid(): |
|
||||||
"""获取 `UUID` |
|
||||||
|
|
||||||
""" |
|
||||||
return str(uuid.uuid4()) |
|
||||||
|
|
||||||
|
|
||||||
def get_iso_8061_date(): |
|
||||||
"""获取 `iso` 标准时间 |
|
||||||
|
|
||||||
""" |
|
||||||
return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) |
|
@ -1,12 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/9/18 |
|
||||||
|
|
||||||
""" |
|
||||||
阿里云相关服务, 目前提供支持: |
|
||||||
|
|
||||||
点播服务 |
|
||||||
|
|
||||||
短信服务 |
|
||||||
|
|
||||||
""" |
|
@ -1,7 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/9/18 |
|
||||||
|
|
||||||
|
|
||||||
from .vod import AliYunVod |
|
||||||
from .sms import AliYunSms |
|
@ -1,41 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/9/18 |
|
||||||
|
|
||||||
|
|
||||||
class BaseAliYunAPI(object): |
|
||||||
""" |
|
||||||
|
|
||||||
阿里云服务API基类 |
|
||||||
|
|
||||||
""" |
|
||||||
|
|
||||||
def __init__(self, client=None): |
|
||||||
self._client = client |
|
||||||
|
|
||||||
def _get(self, action, **kwargs): |
|
||||||
if hasattr(self, "API_BASE_URL"): |
|
||||||
kwargs['api_base_url'] = getattr(self, "API_BASE_URL") |
|
||||||
|
|
||||||
if hasattr(self, "VERSION"): |
|
||||||
kwargs["version"] = getattr(self, "VERSION") |
|
||||||
|
|
||||||
return self._client.get(action, **kwargs) |
|
||||||
|
|
||||||
def _post(self, action, **kwargs): |
|
||||||
|
|
||||||
if hasattr(self, "API_BASE_URL"): |
|
||||||
kwargs['api_base_url'] = getattr(self, "API_BASE_URL") |
|
||||||
|
|
||||||
if hasattr(self, "VERSION"): |
|
||||||
kwargs["version"] = getattr(self, "VERSION") |
|
||||||
|
|
||||||
return self._client.post(action, **kwargs) |
|
||||||
|
|
||||||
@property |
|
||||||
def app_id(self): |
|
||||||
return self._client.app_id |
|
||||||
|
|
||||||
@property |
|
||||||
def secret_key(self): |
|
||||||
return self._client.secret_key |
|
@ -1,144 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/9/18 |
|
||||||
|
|
||||||
""" |
|
||||||
短信服务 |
|
||||||
""" |
|
||||||
|
|
||||||
from .base import BaseAliYunAPI |
|
||||||
|
|
||||||
|
|
||||||
class AliYunSms(BaseAliYunAPI): |
|
||||||
VERSION = "2017-05-25" |
|
||||||
|
|
||||||
API_BASE_URL = "http://dysmsapi.aliyuncs.com/" |
|
||||||
|
|
||||||
def send(self, phone_numbers, sign_name, template_code, template_param, **kwargs): |
|
||||||
"""发送短信 |
|
||||||
|
|
||||||
详情参见: |
|
||||||
https://help.aliyun.com/document_detail/55284.html?spm=5176.8195934.1001856.3.a36a4183xdfqaD |
|
||||||
|
|
||||||
Parameters |
|
||||||
---------- |
|
||||||
phone_numbers : string |
|
||||||
短信接收号码,支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码. |
|
||||||
发送国际/港澳台消息时,接收号码格式为00+国际区号+号码,如“0085200000000” |
|
||||||
|
|
||||||
sign_name: string |
|
||||||
短信签名 |
|
||||||
|
|
||||||
template_code: string |
|
||||||
短信模板ID,发送国际/港澳台消息时,请使用国际/港澳台短信模版 |
|
||||||
|
|
||||||
template_param: json |
|
||||||
短信模板变量替换JSON串,友情提示:如果JSON中需要带换行符,请参照标准的JSON协议 |
|
||||||
|
|
||||||
kwargs: dict |
|
||||||
可选字段: |
|
||||||
|
|
||||||
SmsUpExtendCode |
|
||||||
上行短信扩展码,无特殊需要此字段的用户请忽略此字段 |
|
||||||
|
|
||||||
OutId |
|
||||||
外部流水扩展字段 |
|
||||||
|
|
||||||
Returns |
|
||||||
------- |
|
||||||
dict |
|
||||||
""" |
|
||||||
|
|
||||||
data = { |
|
||||||
"PhoneNumbers": phone_numbers, |
|
||||||
"SignName": sign_name, |
|
||||||
"TemplateCode": template_code, |
|
||||||
"TemplateParam": template_param |
|
||||||
} |
|
||||||
|
|
||||||
data.update(**kwargs) |
|
||||||
|
|
||||||
return self._get(action="SendSms", data=data) |
|
||||||
|
|
||||||
def send_batch( |
|
||||||
self, |
|
||||||
phone_number_json, |
|
||||||
sign_name_json, |
|
||||||
template_code, |
|
||||||
template_param_json, |
|
||||||
sms_upextend_code_json=None, |
|
||||||
): |
|
||||||
"""短信批量发送 |
|
||||||
|
|
||||||
详情参见: |
|
||||||
https://help.aliyun.com/document_detail/66041.html?spm=a2c4g.11186623.6.565.290415e8yJ7E0N |
|
||||||
|
|
||||||
Parameters |
|
||||||
---------- |
|
||||||
phone_number_json : string |
|
||||||
短信接收号码,JSON格式,批量上限为100个手机号码, |
|
||||||
批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式 |
|
||||||
|
|
||||||
sign_name_json: string |
|
||||||
短信签名,JSON格式 |
|
||||||
|
|
||||||
template_code: int |
|
||||||
短信模板ID |
|
||||||
|
|
||||||
template_param_json: int |
|
||||||
短信模板变量替换JSON串,友情提示:如果JSON中需要带换行符,请参照标准的JSON协议。 |
|
||||||
|
|
||||||
sms_upextend_code_json: string |
|
||||||
上行短信扩展码,JSON格式,无特殊需要此字段的用户请忽略此字段 |
|
||||||
|
|
||||||
""" |
|
||||||
data = { |
|
||||||
"PhoneNumberJson": phone_number_json, |
|
||||||
"SignNameJson": sign_name_json, |
|
||||||
"TemplateCode": template_code, |
|
||||||
"TemplateParamJson": template_param_json |
|
||||||
} |
|
||||||
|
|
||||||
if sms_upextend_code_json is not None: |
|
||||||
data["SmsUpExtendCodeJson"] = sms_upextend_code_json |
|
||||||
|
|
||||||
return self._get(action="SendBatchSms", data=data) |
|
||||||
|
|
||||||
def query(self, phone_number, send_date, page_size, current_page, biz_id=None): |
|
||||||
"""短信查询 |
|
||||||
|
|
||||||
详情参见: |
|
||||||
https://help.aliyun.com/document_detail/55289.html?spm=a2c4g.11186623.6.563.56d7577756pHT4 |
|
||||||
|
|
||||||
Parameters |
|
||||||
---------- |
|
||||||
phone_number : string |
|
||||||
短信接收号码,如果需要查询国际短信,号码前需要带上对应国家的区号,区号的获取详见国际短信支持国家信息查询API接口 |
|
||||||
|
|
||||||
send_date: string |
|
||||||
短信发送日期格式yyyyMMdd,支持最近30天记录查询 |
|
||||||
|
|
||||||
page_size: int |
|
||||||
页大小Max=50 |
|
||||||
|
|
||||||
current_page: int |
|
||||||
当前页码 |
|
||||||
|
|
||||||
biz_id: string OR None |
|
||||||
可选, 发送流水号,从调用发送接口返回值中获取 |
|
||||||
|
|
||||||
Returns |
|
||||||
------- |
|
||||||
dict |
|
||||||
""" |
|
||||||
data = { |
|
||||||
"PhoneNumber": phone_number, |
|
||||||
"SendDate": send_date, |
|
||||||
"PageSize": page_size, |
|
||||||
"CurrentPage": current_page |
|
||||||
} |
|
||||||
|
|
||||||
if biz_id is not None: |
|
||||||
data["BizId"] = biz_id |
|
||||||
|
|
||||||
return self._get(action="QuerySendDetails", data=data) |
|
@ -1,212 +0,0 @@ |
|||||||
#! /usr/bin/env python |
|
||||||
# -*- coding: utf-8 -*- |
|
||||||
# Date: 2018/9/18 |
|
||||||
|
|
||||||
""" |
|
||||||
点播服务 |
|
||||||
""" |
|
||||||
|
|
||||||
from .base import BaseAliYunAPI |
|
||||||
|
|
||||||
|
|
||||||
class AliYunVod(BaseAliYunAPI): |
|
||||||
VERSION = "2017-03-21" |
|
||||||
|
|
||||||
API_BASE_URL = "http://vod.cn-shanghai.aliyuncs.com/" |
|
||||||
|
|
||||||
def get_play_auth(self, video_id, timeout): |
|
||||||
"""获取播放 `auth` |
|
||||||
|
|
||||||
Parameters |
|
||||||
---------- |
|
||||||
video_id : string |
|
||||||
|
|
||||||
视频 `vid` |
|
||||||
|
|
||||||
timeout: string |
|
||||||
|
|
||||||
获取到的播放 `key` 的有效时间 |
|
||||||
|
|
||||||
Returns |
|
||||||
------- |
|
||||||
dict |
|
||||||
""" |
|
||||||
|
|
||||||
data = { |
|
||||||
"VideoId": video_id, |
|
||||||
"AuthInfoTimeout": timeout |
|
||||||
} |
|
||||||
|
|
||||||
return self._get(action="GetVideoPlayAuth", data=data) |
|
||||||
|
|
||||||
def get_play_info( |
|
||||||
self, video_id, formats=None, timeout=None, stream_type=None, definition=None, |
|
||||||
result_type=None, output_type=None, |
|
||||||
): |
|
||||||
"""获取播放 `auth` |
|
||||||
|
|
||||||
Parameters |
|
||||||
---------- |
|
||||||
video_id : string |
|
||||||
|
|
||||||
视频 `vid` |
|
||||||
|
|
||||||
formats: string |
|
||||||
视频流格式,多个用逗号分隔。支持格式:mp4 m3u8 mp3 |
|
||||||
默认获取所有格式的流 |
|
||||||
|
|
||||||
timeout: string |
|
||||||
播放地址过期时间,单位:秒。 |
|
||||||
最小值为1(未指定时,以URL鉴权中用户设置的默认有效时长为准),最大值无限制。 |
|
||||||
只有开启了 URL鉴权 才会生效。 |
|
||||||
|
|
||||||
stream_type: string |
|
||||||
视频流类型,多个用逗号分隔。支持类型:video audio |
|
||||||
默认获取所有类型的流。 |
|
||||||
|
|
||||||
definition: string |
|
||||||
视频流清晰度,多个用逗号分隔。取值范围:FD(流畅)LD(标清)SD(高清)HD(超清)OD(原画)2K(2K)4K(4K) |
|
||||||
默认获取所有清晰度的流。 |
|
||||||
|
|
||||||
result_type: string |
|
||||||
返回数据类型。取值范围 : |
|
||||||
Single(每种清晰度和格式只返回一路最新转码完成的流) |
|
||||||
Multiple(每种清晰度和格式返回所有转码完成的流) |
|
||||||
默认为Single类型。 |
|
||||||
|
|
||||||
output_type: string |
|
||||||
输出地址类型。取值范围 : |
|
||||||
oss(回源地址) |
|
||||||
cdn(加速地址) |
|
||||||
默认为cdn类型。注意:仅支持播放格式为mp4的oss地址 |
|
||||||
|
|
||||||
Returns |
|
||||||
------- |
|
||||||
dict |
|
||||||
""" |
|
||||||
|
|
||||||
data = { |
|
||||||
"VideoId": video_id, |
|
||||||
"Formats": formats, |
|
||||||
"AuthTimeout": timeout, |
|
||||||
"StreamType": stream_type, |
|
||||||
"Definition": definition, |
|
||||||
"ResultType": result_type, |
|
||||||
"OutputType": output_type |
|
||||||
} |
|
||||||
|
|
||||||
return self._get(action="GetPlayInfo", data=data) |
|
||||||
|
|
||||||
def query_flow_data( |
|
||||||
self, domain_name=None, start_time=None, end_time=None, time_merge=None, interval=None, |
|
||||||
location_name_en=None, isp_name_en=None, |
|
||||||
): |
|
||||||
"""查询流量数据 |
|
||||||
|
|
||||||
获取加速域名的网络流量监控数据,单位:byte。 |
|
||||||
不指定StartTime和EndTime时,默认读取过去24小时的数据。也可以按指定的起止时间查询。 |
|
||||||
|
|
||||||
注意: |
|
||||||
支持域名批量查询,多个域名用半角逗号分隔。 |
|
||||||
最多可获取近90天的数据。 |
|
||||||
|
|
||||||
Parameters |
|
||||||
---------- |
|
||||||
domain_name : string |
|
||||||
要查询的域名。若为空,则默认返回所有加速域名的合并数据。支持批量查询,多个域名用半角逗号分隔。 |
|
||||||
|
|
||||||
start_time: string |
|
||||||
获取数据起始时间点。日期格式按照ISO8601表示法,使用UTC时间。 |
|
||||||
若为空,则默认读取最近24小时的数据。 |
|
||||||
|
|
||||||
end_time: string |
|
||||||
结束时间。需大于起始时间,日期格式按照ISO8601表示法,使用UTC时间。格式为:YYYY-MM-DDThh:mmZ。 |
|
||||||
|
|
||||||
time_merge: string |
|
||||||
时间合并。取值范围: |
|
||||||
on:默认值。每条记录的时间间隔会根据时间跨度进行合并。 |
|
||||||
off:返回5分钟粒度数据,最大时间跨度为31天。 |
|
||||||
|
|
||||||
interval: string |
|
||||||
查询数据的时间粒度。单位:秒,取值范围:300 3600 14400 28800 86400 |
|
||||||
默认值:300 |
|
||||||
|
|
||||||
location_name_en: string |
|
||||||
区域英文名。默认为所有区域。 |
|
||||||
|
|
||||||
isp_name_en: string |
|
||||||
运营商英文名。默认为所有运营商。 |
|
||||||
|
|
||||||
Returns |
|
||||||
------- |
|
||||||
dict |
|
||||||
""" |
|
||||||
|
|
||||||
data = { |
|
||||||
"DomainName": domain_name, |
|
||||||
"StartTime": start_time, |
|
||||||
"EndTime": end_time, |
|
||||||
"TimeMerge": time_merge, |
|
||||||
"Interval": interval, |
|
||||||
"LocationNameEn": location_name_en, |
|
||||||
"IspNameEn": isp_name_en |
|
||||||
} |
|
||||||
|
|
||||||
return self._get(action="DescribeDomainFlowData", data=data) |
|
||||||
|
|
||||||
def query_bps_data( |
|
||||||
self, domain_name=None, start_time=None, end_time=None, time_merge=None, interval=None, |
|
||||||
location_name_en=None, isp_name_en=None, |
|
||||||
): |
|
||||||
"""查询网络带宽 |
|
||||||
|
|
||||||
获取加速域名的网络带宽监控数据,单位:bit/second。 |
|
||||||
不指定StartTime和EndTime时,默认读取过去24小时的数据。也可以按指定的起止时间查询。 |
|
||||||
|
|
||||||
注意: |
|
||||||
支持域名批量查询,多个域名用半角逗号分隔。 |
|
||||||
最多可获取近90天的数据。 |
|
||||||
|
|
||||||
Parameters |
|
||||||
---------- |
|
||||||
domain_name : string |
|
||||||
要查询的域名。若为空,则默认返回所有加速域名的合并数据。支持批量查询,多个域名用半角逗号分隔。 |
|
||||||
|
|
||||||
start_time: string |
|
||||||
获取数据起始时间点。日期格式按照ISO8601表示法,使用UTC时间。 |
|
||||||
若为空,则默认读取最近24小时的数据。 |
|
||||||
|
|
||||||
end_time: string |
|
||||||
结束时间。需大于起始时间,日期格式按照ISO8601表示法,使用UTC时间。格式为:YYYY-MM-DDThh:mmZ。 |
|
||||||
|
|
||||||
time_merge: string |
|
||||||
时间合并。取值范围: |
|
||||||
on:默认值。每条记录的时间间隔会根据时间跨度进行合并。 |
|
||||||
off:返回5分钟粒度数据,最大时间跨度为31天。 |
|
||||||
|
|
||||||
interval: string |
|
||||||
查询数据的时间粒度。单位:秒,取值范围:300 3600 14400 28800 86400 |
|
||||||
默认值:300 |
|
||||||
|
|
||||||
location_name_en: string |
|
||||||
区域英文名。默认为所有区域。 |
|
||||||
|
|
||||||
isp_name_en: string |
|
||||||
运营商英文名。默认为所有运营商。 |
|
||||||
|
|
||||||
Returns |
|
||||||
------- |
|
||||||
dict |
|
||||||
""" |
|
||||||
|
|
||||||
data = { |
|
||||||
"DomainName": domain_name, |
|
||||||
"StartTime": start_time, |
|
||||||
"EndTime": end_time, |
|
||||||
"TimeMerge": time_merge, |
|
||||||
"Interval": interval, |
|
||||||
"LocationNameEn": location_name_en, |
|
||||||
"IspNameEn": isp_name_en |
|
||||||
} |
|
||||||
|
|
||||||
return self._get(action="DescribeDomainBpsData", data=data) |
|
@ -1,224 +0,0 @@ |
|||||||
#! /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 |
|
||||||
) |
|
@ -1,73 +0,0 @@ |
|||||||
#!/usr/bin/env python |
|
||||||
# -*- coding:utf-8 -*- |
|
||||||
# project: 12月 |
|
||||||
# author: NinEveN |
|
||||||
# date: 2019/12/19 |
|
||||||
|
|
||||||
import re |
|
||||||
import os |
|
||||||
import zipfile |
|
||||||
# from biplist import * |
|
||||||
from androguard.core.bytecodes import apk |
|
||||||
import plistlib |
|
||||||
|
|
||||||
|
|
||||||
def get_android_data(package_file): |
|
||||||
try: |
|
||||||
apkobj = apk.APK(package_file) |
|
||||||
except Exception as err: |
|
||||||
print(err) |
|
||||||
else: |
|
||||||
if apkobj.is_valid_APK(): |
|
||||||
versioncode = apkobj.get_androidversion_code() |
|
||||||
bundle_id = apkobj.get_package() |
|
||||||
labelname = apkobj.get_app_name() |
|
||||||
versioname = apkobj.get_androidversion_name() |
|
||||||
sdk_version = apkobj.get_target_sdk_version() |
|
||||||
return labelname, bundle_id, versioncode, versioname, sdk_version |
|
||||||
|
|
||||||
|
|
||||||
def get_ios_data(ios_file): |
|
||||||
if zipfile.is_zipfile(ios_file): |
|
||||||
ipaobj = zipfile.ZipFile(ios_file) |
|
||||||
info_path = get_ios_info_path(ipaobj) |
|
||||||
if info_path: |
|
||||||
plist_data = ipaobj.read(info_path) |
|
||||||
print(plist_data) |
|
||||||
if b"ProvisionedDevices" in plist_data: |
|
||||||
print("adhoc") |
|
||||||
else: |
|
||||||
print("inhouse") |
|
||||||
|
|
||||||
|
|
||||||
def get_ios_info_path(ipaobj): |
|
||||||
infopath_re = re.compile(r'.*.app/embedded.mobileprovision') |
|
||||||
for i in ipaobj.namelist(): |
|
||||||
m = infopath_re.match(i) |
|
||||||
if m is not None: |
|
||||||
return m.group() |
|
||||||
|
|
||||||
|
|
||||||
def get_ios_icon_path(ipaobj): |
|
||||||
infopath_re = re.compile(r'Payload/[^/]*.app/AppIcon[^/]*[^(ipad)].png') |
|
||||||
for i in ipaobj.namelist(): |
|
||||||
m = infopath_re.match(i) |
|
||||||
if m is not None: |
|
||||||
return m.group() |
|
||||||
|
|
||||||
|
|
||||||
def get_package_size(package_path): |
|
||||||
fsize = os.path.getsize(package_path) |
|
||||||
fsize = fsize / float(1024 * 1024) |
|
||||||
return round(fsize, 2) |
|
||||||
|
|
||||||
|
|
||||||
# a=get_ios_data("/root/v1.1.8/Riot.ipa") |
|
||||||
# print(a) |
|
||||||
|
|
||||||
ipaobj = zipfile.ZipFile("M:\\Breeze.ipa") |
|
||||||
info_path = get_ios_icon_path(ipaobj) |
|
||||||
print(info_path) |
|
||||||
|
|
||||||
with open('111222.png', 'wb') as f: |
|
||||||
f.write(ipaobj.read(info_path)) |
|
@ -1,48 +0,0 @@ |
|||||||
from django.conf import settings |
|
||||||
from api.utils.geetest import GeeTestLib |
|
||||||
|
|
||||||
|
|
||||||
def verify(verify_data, uid=None, extend_params=None): |
|
||||||
"""第三方滑动验证码校验. |
|
||||||
|
|
||||||
选用第三方的验证组件, 根据参数进行校验 |
|
||||||
根据布尔值辨别是否校验通过 |
|
||||||
|
|
||||||
Parameters |
|
||||||
---------- |
|
||||||
|
|
||||||
verify_data : dict |
|
||||||
请求数据 |
|
||||||
|
|
||||||
uid: string, default: None |
|
||||||
用户UID, 如果存在就免受滑动验证码的限制 |
|
||||||
|
|
||||||
extend_params : dict |
|
||||||
预留的扩展参数 |
|
||||||
|
|
||||||
Returns |
|
||||||
------- |
|
||||||
True OR False |
|
||||||
""" |
|
||||||
captcha_config = settings.GEE_TEST |
|
||||||
if captcha_config.get("verify_status"): |
|
||||||
|
|
||||||
status = True |
|
||||||
|
|
||||||
if uid in captcha_config.get("not_verify"): |
|
||||||
return True |
|
||||||
|
|
||||||
gt = GeeTestLib(captcha_config["gee_test_access_id"], captcha_config["gee_test_access_key"]) |
|
||||||
challenge = verify_data.get(gt.FN_CHALLENGE, '') |
|
||||||
validate = verify_data.get(gt.FN_VALIDATE, '') |
|
||||||
seccode = verify_data.get(gt.FN_SECCODE, '') |
|
||||||
# status = request.session.get(gt.GT_STATUS_SESSION_KEY, 1) |
|
||||||
# user_id = request.session.get("user_id") |
|
||||||
|
|
||||||
if status: |
|
||||||
result = gt.success_validate(challenge, validate, seccode, None) |
|
||||||
else: |
|
||||||
result = gt.failback_validate(challenge, validate, seccode) |
|
||||||
return True if result else False |
|
||||||
else: |
|
||||||
return True |
|
@ -1,199 +0,0 @@ |
|||||||
# !/usr/bin/env python |
|
||||||
# -*- coding:utf-8 -*- |
|
||||||
|
|
||||||
import sys |
|
||||||
import random |
|
||||||
import json |
|
||||||
import requests |
|
||||||
import time |
|
||||||
from hashlib import md5 |
|
||||||
|
|
||||||
if sys.version_info >= (3,): |
|
||||||
xrange = range |
|
||||||
|
|
||||||
VERSION = "3.2.0" |
|
||||||
|
|
||||||
|
|
||||||
class GeeTestLib(object): |
|
||||||
FN_CHALLENGE = "geetest_challenge" |
|
||||||
FN_VALIDATE = "geetest_validate" |
|
||||||
FN_SECCODE = "geetest_seccode" |
|
||||||
|
|
||||||
GT_STATUS_SESSION_KEY = "gt_server_status" |
|
||||||
|
|
||||||
API_URL = "http://api.geetest.com" |
|
||||||
REGISTER_HANDLER = "/register.php" |
|
||||||
VALIDATE_HANDLER = "/validate.php" |
|
||||||
|
|
||||||
def __init__(self, captcha_id, private_key): |
|
||||||
self.private_key = private_key |
|
||||||
self.captcha_id = captcha_id |
|
||||||
self.sdk_version = VERSION |
|
||||||
self._response_str = "" |
|
||||||
|
|
||||||
def pre_process(self, user_id=None): |
|
||||||
""" |
|
||||||
验证初始化预处理. |
|
||||||
""" |
|
||||||
status, challenge = self._register(user_id) |
|
||||||
self._response_str = self._make_response_format(status, challenge) |
|
||||||
return status |
|
||||||
|
|
||||||
def _register(self, user_id=None): |
|
||||||
challenge = self._register_challenge(user_id) |
|
||||||
if len(challenge) == 32: |
|
||||||
challenge = self._md5_encode("".join([challenge, self.private_key])) |
|
||||||
return 1, challenge |
|
||||||
else: |
|
||||||
return 0, self._make_fail_challenge() |
|
||||||
|
|
||||||
def get_response_str(self): |
|
||||||
return self._response_str |
|
||||||
|
|
||||||
def _make_fail_challenge(self): |
|
||||||
rnd1 = random.randint(0, 99) |
|
||||||
rnd2 = random.randint(0, 99) |
|
||||||
md5_str1 = self._md5_encode(str(rnd1)) |
|
||||||
md5_str2 = self._md5_encode(str(rnd2)) |
|
||||||
challenge = md5_str1 + md5_str2[0:2] |
|
||||||
return challenge |
|
||||||
|
|
||||||
def _make_response_format(self, success=1, challenge=None): |
|
||||||
if not challenge: |
|
||||||
challenge = self._make_fail_challenge() |
|
||||||
string_format = json.dumps( |
|
||||||
{'success': success, 'gt': self.captcha_id, 'challenge': challenge}) |
|
||||||
return string_format |
|
||||||
|
|
||||||
def _register_challenge(self, user_id=None): |
|
||||||
if user_id: |
|
||||||
register_url = "{api_url}{handler}?gt={captcha_ID}&user_id={user_id}".format( |
|
||||||
api_url=self.API_URL, handler=self.REGISTER_HANDLER, captcha_ID=self.captcha_id, user_id=user_id) |
|
||||||
else: |
|
||||||
register_url = "{api_url}{handler}?gt={captcha_ID}".format( |
|
||||||
api_url=self.API_URL, handler=self.REGISTER_HANDLER, captcha_ID=self.captcha_id) |
|
||||||
try: |
|
||||||
response = requests.get(register_url, timeout=2) |
|
||||||
if response.status_code == requests.codes.ok: |
|
||||||
res_string = response.text |
|
||||||
else: |
|
||||||
res_string = "" |
|
||||||
except: |
|
||||||
res_string = "" |
|
||||||
return res_string |
|
||||||
|
|
||||||
def success_validate(self, challenge, validate, seccode, user_id=None, gt=None, data='', userinfo=''): |
|
||||||
""" |
|
||||||
正常模式的二次验证方式.向geetest server 请求验证结果. |
|
||||||
""" |
|
||||||
if not self._check_para(challenge, validate, seccode): |
|
||||||
return 0 |
|
||||||
if not self._check_result(challenge, validate): |
|
||||||
return 0 |
|
||||||
validate_url = "{api_url}{handler}".format( |
|
||||||
api_url=self.API_URL, handler=self.VALIDATE_HANDLER) |
|
||||||
query = { |
|
||||||
"seccode": seccode, |
|
||||||
"sdk": ''.join(["python_", self.sdk_version]), |
|
||||||
"user_id": user_id, |
|
||||||
"data": data, |
|
||||||
"timestamp": time.time(), |
|
||||||
"challenge": challenge, |
|
||||||
"userinfo": userinfo, |
|
||||||
"captchaid": gt |
|
||||||
} |
|
||||||
backinfo = self._post_values(validate_url, query) |
|
||||||
if backinfo == self._md5_encode(seccode): |
|
||||||
return 1 |
|
||||||
else: |
|
||||||
return 0 |
|
||||||
|
|
||||||
def _post_values(self, apiserver, data): |
|
||||||
response = requests.post(apiserver, data) |
|
||||||
return response.text |
|
||||||
|
|
||||||
def _check_result(self, origin, validate): |
|
||||||
encodeStr = self._md5_encode(self.private_key + "geetest" + origin) |
|
||||||
if validate == encodeStr: |
|
||||||
return True |
|
||||||
else: |
|
||||||
return False |
|
||||||
|
|
||||||
def failback_validate(self, challenge, validate, seccode): |
|
||||||
""" |
|
||||||
failback模式的二次验证方式.在本地对轨迹进行简单的判断返回验证结果. |
|
||||||
""" |
|
||||||
if not self._check_para(challenge, validate, seccode): |
|
||||||
return 0 |
|
||||||
validate_str = validate.split('_') |
|
||||||
encode_ans = validate_str[0] |
|
||||||
encode_fbii = validate_str[1] |
|
||||||
encode_igi = validate_str[2] |
|
||||||
decode_ans = self._decode_response(challenge, encode_ans) |
|
||||||
decode_fbii = self._decode_response(challenge, encode_fbii) |
|
||||||
decode_igi = self._decode_response(challenge, encode_igi) |
|
||||||
validate_result = self._validate_fail_image( |
|
||||||
decode_ans, decode_fbii, decode_igi) |
|
||||||
return validate_result |
|
||||||
|
|
||||||
def _check_para(self, challenge, validate, seccode): |
|
||||||
return (bool(challenge.strip()) and bool(validate.strip()) and bool(seccode.strip())) |
|
||||||
|
|
||||||
def _validate_fail_image(self, ans, full_bg_index, img_grp_index): |
|
||||||
thread = 3 |
|
||||||
full_bg_name = str(self._md5_encode(str(full_bg_index)))[0:10] |
|
||||||
bg_name = str(self._md5_encode(str(img_grp_index)))[10:20] |
|
||||||
answer_decode = "" |
|
||||||
for i in range(0, 9): |
|
||||||
if i % 2 == 0: |
|
||||||
answer_decode += full_bg_name[i] |
|
||||||
elif i % 2 == 1: |
|
||||||
answer_decode += bg_name[i] |
|
||||||
x_decode = answer_decode[4:] |
|
||||||
x_int = int(x_decode, 16) |
|
||||||
result = x_int % 200 |
|
||||||
if result < 40: |
|
||||||
result = 40 |
|
||||||
if abs(ans - result) < thread: |
|
||||||
return 1 |
|
||||||
else: |
|
||||||
return 0 |
|
||||||
|
|
||||||
def _md5_encode(self, values): |
|
||||||
if type(values) == str: |
|
||||||
values = values.encode() |
|
||||||
m = md5(values) |
|
||||||
return m.hexdigest() |
|
||||||
|
|
||||||
def _decode_rand_base(self, challenge): |
|
||||||
str_base = challenge[32:] |
|
||||||
i = 0 |
|
||||||
temp_array = [] |
|
||||||
for i in xrange(len(str_base)): |
|
||||||
temp_char = str_base[i] |
|
||||||
temp_ascii = ord(temp_char) |
|
||||||
result = temp_ascii - 87 if temp_ascii > 57 else temp_ascii - 48 |
|
||||||
temp_array.append(result) |
|
||||||
decode_res = temp_array[0] * 36 + temp_array[1] |
|
||||||
return decode_res |
|
||||||
|
|
||||||
def _decode_response(self, challenge, userresponse): |
|
||||||
if len(userresponse) > 100: |
|
||||||
return 0 |
|
||||||
shuzi = (1, 2, 5, 10, 50) |
|
||||||
chongfu = set() |
|
||||||
key = {} |
|
||||||
count = 0 |
|
||||||
for i in challenge: |
|
||||||
if i in chongfu: |
|
||||||
continue |
|
||||||
else: |
|
||||||
value = shuzi[count % 5] |
|
||||||
chongfu.add(i) |
|
||||||
count += 1 |
|
||||||
key.update({i: value}) |
|
||||||
res = 0 |
|
||||||
for i in userresponse: |
|
||||||
res += key.get(i, 0) |
|
||||||
res = res - self._decode_rand_base(challenge) |
|
||||||
return res |
|
@ -1,19 +0,0 @@ |
|||||||
from django.core.cache import cache |
|
||||||
|
|
||||||
import datetime |
|
||||||
|
|
||||||
from rest_framework.authentication import BaseAuthentication |
|
||||||
from rest_framework import exceptions |
|
||||||
from api.models import Token |
|
||||||
|
|
||||||
from rest_framework.permissions import BasePermission |
|
||||||
|
|
||||||
|
|
||||||
class LoginUserPermission(BaseAuthentication): |
|
||||||
|
|
||||||
def has_permission(self, request, view): |
|
||||||
|
|
||||||
if request.user: |
|
||||||
return True |
|
||||||
else: |
|
||||||
return False |
|
@ -1,36 +0,0 @@ |
|||||||
from rest_framework.views import APIView |
|
||||||
from api.utils.geetest import GeeTestLib |
|
||||||
from django.conf import settings |
|
||||||
import json |
|
||||||
from rest_framework.response import Response |
|
||||||
|
|
||||||
|
|
||||||
class CaptchaView(APIView): |
|
||||||
def get(self, request): |
|
||||||
gt = GeeTestLib(settings.GEE_TEST["gee_test_access_id"], settings.GEE_TEST["gee_test_access_key"]) |
|
||||||
gt.pre_process() |
|
||||||
# 设置 geetest session, 用于是否启用滑动验证码向 geetest 发起远程验证, 如果取不到的话只是对本地轨迹进行校验 |
|
||||||
# self.request.session[gt.GT_STATUS_SESSION_KEY] = status |
|
||||||
# request.session["user_id"] = user_id |
|
||||||
response_str = gt.get_response_str() |
|
||||||
response_str = json.loads(response_str) |
|
||||||
|
|
||||||
return Response({"error_no": 0, "data": response_str}) |
|
||||||
|
|
||||||
|
|
||||||
from captcha.models import CaptchaStore |
|
||||||
from captcha.helpers import captcha_image_url |
|
||||||
import json |
|
||||||
|
|
||||||
|
|
||||||
class AjaxExampleForm(APIView): |
|
||||||
|
|
||||||
def get(self, request): |
|
||||||
to_json_response = dict() |
|
||||||
to_json_response['status'] = 0 |
|
||||||
to_json_response['new_cptch_key'] = CaptchaStore.generate_key() |
|
||||||
to_json_response['new_cptch_image'] = captcha_image_url(to_json_response['new_cptch_key']) |
|
||||||
CaptchaStore.remove_expired() |
|
||||||
a = CaptchaStore.objects.filter(hashkey=to_json_response['new_cptch_key']).first() |
|
||||||
print(a) |
|
||||||
return Response(to_json_response) |
|
Loading…
Reference in new issue