python调用支付宝接口

这里使用的是支付宝的沙箱环境:https://open.alipay.com/platform/appDaily.htm

关于沙箱的具体配置请看 https://opendocs.alipay.com/common/02kkv7

我们直接来说 python 如何使用支付宝 API。

安装依赖
1
pip install alipay-sdk-pytho
使用
实例化客户端

发起支付、查询交易信息、退款等服务都需要实例化一个客户端。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient
from alipay.aop.api.AlipayClientConfig import AlipayClientConfig

alipay_client_config = AlipayClientConfig()
# 请求网关
alipay_client_config.server_url = current_app.config['SERVER_URL']
# APP ID
alipay_client_config.app_id = current_app.config['APP_ID']
# 个人私钥
alipay_client_config.app_private_key = current_app.config['APP_PRIVATE_KEY']
# 支付宝公钥
alipay_client_config.alipay_public_key = current_app.config['ALIPAY_PUBLIC_KEY']

client = DefaultAlipayClient(alipay_client_config)
构造请求参数模型

不同的服务需要构造不同的参数模型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
'''发起支付'''
from alipay.aop.api.domain.AlipayTradePagePayModel import AlipayTradePagePayModel

model = AlipayTradePagePayModel()
# 订单号
model.out_trade_no = order_id
# 总价
model.total_amount = price
# 标题
model.subject = name
# 订单超时时间,如果买家超过这个时间不付款,会关闭交易(最小1分钟)
model.timeout_express = '5m'
# 产品码
model.product_code = 'FAST_INSTANT_TRADE_PAY'

'''交易查询'''
from alipay.aop.api.domain.AlipayTradeQueryModel import AlipayTradeQueryModel

model = AlipayTradeQueryModel()
# 订单号即可
model.out_trade_no = '202112221533'

'''退款'''
from alipay.aop.api.domain.AlipayTradeRefundModel import AlipayTradeRefundModel

model = AlipayTradeRefundModel()
# 订单号
model.out_trade_no = '202112221533'
# 退款总额
model.refund_amount = 100.50

当然,我们也可以不使用模型来传参,直接向对应请求对象中的 biz_content 赋值,例如退款:

1
2
3
4
from alipay.aop.api.request.AlipayTradeRefundRequest import AlipayTradeRefundRequest

refund_request = AlipayTradeRefundRequest()
refund_request.biz_content = {'out_trade_no': trade_no, 'refund_amount': price}
发起请求并处理响应
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
'''发起支付'''
from alipay.aop.api.request.AlipayTradePagePayRequest import AlipayTradePagePayRequest

pay_request = AlipayTradePagePayRequest(biz_model=model)
# 支付成功后支付宝发送 POST 请求的地址
pay_request.notify_url = 'http://192.168.31.196:5000/pay_result'
# 支付成功后的跳转页面
pay_request.return_url = 'http://192.168.31.196:5000/order'

# 执行 api 调用
# 执行请求 'get'返回支付页面的 url,'post'返回支付页面表单的 html 字符串
pay_url = client.page_execute(pay_request, http_method='GET')
return jsonify({'url': pay_url})

'''查询交易'''
from alipay.aop.api.request.AlipayTradeQueryRequest import AlipayTradeQueryRequest
from alipay.aop.api.response.AlipayTradeQueryResponse import AlipayTradeQueryResponse

query_request = AlipayTradeQueryRequest(biz_model=model)
try:
response_content = client.execute(query_request)
except Exception as e:
print(e)
response = AlipayTradeQueryResponse()
response.parse_response_content(response)
# 请求成功
if res.is_success():
print(response.out_trade_no)
else:
...

'''退款'''
from alipay.aop.api.request.AlipayTradeRefundRequest import AlipayTradeRefundRequest
from alipay.aop.api.response.AlipayTradeRefundResponse import AlipayTradeRefundResponse

# 同上

在支付请求中,当用户支付完成后支付宝会向 notify_url 中的地址发送 post 请求,将订单的信息返回,但必须要求这个地址能够被外网访问,否则不会被请求。

我们得到返回的结果后,需要进行验签:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from alipay.aop.api.util.SignatureUtils import verify_with_rsa

def checkSign(params):
sign = params.pop('sign')
params.pop('sign_type')
params_sorted = sorted(params.items(), key=lambda x:x[0], reverse=False)
params_encode = '&'.join('{}={}'.format(k, v) for k,v in params_sorted).encode()
return verify_with_rsa(current_app.config['ALIPAY_PUBLIC_KEY'], params_encode, sign)

params = request.form
# 验签成功
if checkSign(params):
# 核对订单号等信息
...