人家指定的网站还不错的:https://pypi.org/project/alipay-sdk-python/3.3.398/
pip install alipay-sdk-python==3.3.398
来个例子吧!
import logging
from alipay.aop.api.AlipayClientConfig import AlipayClientConfig
from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient
from alipay.aop.api.domain.AlipayFundTransToaccountTransferModel import AlipayFundTransToaccountTransferModel
from alipay.aop.api.domain.AlipayTradeAppPayModel import AlipayTradeAppPayModel
from alipay.aop.api.domain.AlipayTradePagePayModel import AlipayTradePagePayModel
from alipay.aop.api.request.AlipayTradeAppPayRequest import AlipayTradeAppPayRequest
from alipay.aop.api.request.AlipayTradePagePayRequest import AlipayTradePagePayRequest
from alipay.aop.api.response.AlipayFundTransToaccountTransferResponse import AlipayFundTransToaccountTransferResponse
from alipay.aop.api.request.AlipayFundTransToaccountTransferRequest import AlipayFundTransToaccountTransferRequest
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s',
filemode='a', )
logger = logging.getLogger('')
class Alipay():
def __init__(self, cfg):
# 初始化客户端, sandbox_debug指的是否是调试默认,如果是True,则自动切换为提交环境为沙盒
alipay_client_config = AlipayClientConfig()
#
alipay_client_config.server_url = 'https://openapi.alipay.com/gateway.do'
#
alipay_client_config.app_id = 'app_id'
# 私钥
alipay_client_config.app_private_key = 'private_key'
# 公钥
alipay_client_config.alipay_public_key = 'public_key'
# 开始构建客户端, logger为日志对象
self.client = DefaultAlipayClient(alipay_client_config=alipay_client_config, logger=logger)
# 公钥
self.alipay_public_key = cfg['public_key']
# 签名
self._sign_type = "RSA2"
# 回调url
self.app_notify_url = cfg['app_notify_url']
# 转账
def transfer(self, data):
model = AlipayFundTransToaccountTransferModel()
# 订单号
model.out_biz_no = data['out_biz_no']
# 收款方账户类型
model.payee_type = 'ALIPAY_LOGONID'
# 收款方账户
model.payee_account = data['account']
# 金额
model.amount = data['cost']
# 备注
model.remark = data['remark']
# 执行
request = AlipayFundTransToaccountTransferRequest(biz_model=model)
response_content = None
response_content = self.client.execute(request)
if not response_content:
return ''
else:
# 返回结果
response = AlipayFundTransToaccountTransferResponse()
#
response.parse_response_content(response_content=response_content)
#
return response
# 支付宝APP端支付
def alipay_trade_app_pay(self, data):
model = AlipayTradeAppPayModel()
# 超时关闭订单的时间 30m--30分钟
model.timeout_express = "30m"
# 订单金额
model.total_amount = data['total_amount']
# 销售产品码,商家和支付宝签约的产品码,为固定值QUICK_MSECURITY_PAY
model.product_code = "QUICK_MSECURITY_PAY"
# 商品描述
model.body = data['body']
# 商品标题
model.subject = data['subject']
# 订单号
model.out_trade_no = data['out_trade_no']
request = AlipayTradeAppPayRequest(biz_model=model)
request.notify_url = self.app_notify_url
try:
response = self.client.sdk_execute(request)
return response
except IOError:
return ''
# 支付宝网页端支付
def alipay_trade_page_pay(self):
model = AlipayTradePagePayModel()
model.out_trade_no = "pay201805020000226"
model.total_amount = 0.01
model.subject = "测试"
model.body = "支付宝测试"
model.product_code = "FAST_INSTANT_TRADE_PAY"
request = AlipayTradePagePayRequest(biz_model=model)
# 得到构造的请求,如果http_method是GET,则是一个带完成请求参数的url,如果http_method是POST,则是一段HTML表单片段
response = self.client.page_execute(request, http_method="GET")
request.notify_url = self.app_notify_url
try:
response = self.client.sdk_execute(request)
return response
except IOError:
return ''
回调接口 (官网有写,回调返回的参数https://opendocs.alipay.com/open/204/105301)
@bp.route('/alipay_notify', methods=['GET', 'POST'])
def ali_pay():
"""支付回调"""
data = request.form.to_dict()
# sign 不能参与签名验证
signature = data.pop("sign")
# 回调两种方案 1.验证签名 2.根据订单号查询支付情况
success = Alipay.verify(data, signature)
if success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED"):
# 处理支付成功的业务
return data.get('trade_no') # 这里使用支付宝返回的订单号来显示支付成功
return 'fail'
一:签名验证
import time
import json
from base64 import decodebytes
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256, SHA
# 签名验证
def _verify(self, raw_content, signature):
# 开始计算签名
key = self.alipay_public_key
signer = PKCS1_v1_5.new(key)
if self._sign_type == "RSA":
digest = SHA.new()
else:
digest = SHA256.new()
digest.update(raw_content.encode())
return bool(signer.verify(digest, decodebytes(signature.encode())))
def verify(self, data, signature):
if "sign_type" in data:
sign_type = data.pop("sign_type")
if sign_type != self._sign_type:
raise Exception(None, "Unknown sign type: {}".format(sign_type))
# 排序后的字符串
unsigned_items = self._ordered_data(data)
message = "&".join(u"{}={}".format(k, v) for k, v in unsigned_items)
return self._verify(message, signature)
# 排序
def _ordered_data(self, data):
for k, v in data.items():
if isinstance(v, dict):
# 将字典类型的数据dump出来
data[k] = json.dumps(v, separators=(',', ':'))
return sorted(data.items())
二:订单查询
from alipay.aop.api.request.AlipayTradeQueryRequest import AlipayTradeQueryRequest
from alipay.aop.api.response.AlipayTradeQueryResponse import AlipayTradeQueryResponse
def check_order(self, order):
'''
订单校验
order: 订单号
:return:
'''
request = AlipayTradeQueryRequest()
request.biz_content = {"trade_no": order}
response_content = self.client.execute(request)
response = AlipayTradeQueryResponse()
response.parse_response_content(response_content)
try:
# print(response.send_pay_date)
if response.code == "10000":
# 将购买时间转换为时间戳,取当前时间做对比,如果超过十分钟pass,
stamp_array = time.strptime(response.send_pay_date, '%Y-%m-%d %H:%M:%S')
stamp = int(time.mktime(stamp_array)) # 转换为时间戳
# print('本地时间转换成时间戳:', stamp)
hour = stamp + 360
if hour > time.time():
print('ok!')
else:
print('fail!')
if response.code == "40004":
print("order error1!")
else:
print("order error2!")
except Exception as e:
print('error, check_order')