支付宝没有提供Python SDK。生成预付订单需要使用SHA1withRSA签名,签名的生成比较麻烦容易出错。这里提供了一个简单的库,希望能够简化一些Python开发的流程。
python对接支付宝SDK安装:pip install python-alipay-sdk --upgrade
python对接支付宝SDK:https://github.com/fzlee/alipay/blob/master/README.zh-hans.md
支付宝开发文档快速接入:https://docs.open.alipay.com/270/105899/
1.创建应用
注册为支付宝开发者,创建应用并获取APPID 。
2. 生成应用的公钥 & 私钥
使用下列指令,创建应用的公钥&密钥文件,把应用公钥设置到alipay中,把alipay的公钥复制到应用文件中(在pay子应用中创建keys目录,分别存放应用私钥&alipay公钥)。
openssl
# 生成应用私钥
genrsa -out app_private_key.pem 2048
# 生成应用公钥
rsa -in app_private_key.pem -pubout -out app_public_key.pem
3 .搭建 & 配置开发环境(测试开发使用沙箱环境)
# 支付宝支付-配置
ALIPAY_APPID = "20160917xxx" # appid
ALIPAY_URL = "https://openapi.alipaydev.com/gateway.do" # 沙箱环境
ALIPAY_DEBUG = True # DEBUG模式
# 应用私钥文件路径
APP_PRIVATE_KEY_PATH = os.path.join(BASE_DIR, 'apps/pay/keys/app_private_key.pem')
# 支付宝公钥文件路径
ALIPAY_PUBLIC_KEY_PATH = os.path.join(BASE_DIR, 'apps/pay/keys/alipay_public_key.pem')
4. 根据开发文档 & 支付宝对接流程,调用接口
具体代码如下
from alipay import AliPay
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from mall import settings
from orders.models import OrderInfo
from pay.models import Payment
class AlipayView(APIView):
"""
支付宝-支付
接口分析:
GET /pay/orders/(?P/d+)/
请求参数: order_id
返回值: alipay_url
"""
permission_classes = [IsAuthenticated]
def get(self, request, order_id):
user = request.user
# 1. 根据order_id, 验证订单对象是否存在
try:
order = OrderInfo.objects.get(pk=order_id, user=user,
status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'])
except OrderInfo.DoesNotExist:
return Response(status=status.HTTP_400_BAD_REQUEST)
# 2. 创建alipay对象, 生成order_string,拼接alipay的url
app_private_key_string = open("apps/pay/keys/app_private_key.pem").read()
alipay_public_key_string = open("apps/pay/keys/alipay_public_key.pem").read()
alipay = AliPay(
appid=settings.ALIPAY_APPID,
app_notify_url=None, # 默认回调url
app_private_key_string=app_private_key_string,
alipay_public_key_string=alipay_public_key_string, # 支付宝的公钥,验证支付宝回传消息使用
sign_type="RSA2", # RSA 或者 RSA2
debug = settings.ALIPAY_DEBUG, # 默认False
)
# 如果你是 Python 3的用户,使用默认的字符串即可
subject = "测试订单"
# 电脑网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no=order_id, # order_id
total_amount=str(order.total_amount), # 订单总金额,需要转换成str类型,因为JSON不支持Decimal货币类型
subject=subject,
return_url='http://www.DJ.com:8080/pay_success.html', # 成功回调地址
notify_url=None # 可选, 不填则使用默认notify url
)
# 拼接url
alipay_url = settings.ALIPAY_URL + '?' + order_string
# 返回拼接的alipay_url
return Response({'alipay_url': alipay_url})
class AlipayStatusView(APIView):
"""
支付宝-支付状态
POST /pay/payment/status/?
思路分析:
1. 后端接收前端发送的支付状态数据data,获取标记数据signature
2. 创建alipay对象, 将data & signature传递过去,获取支付状态
3. 如果支付成功,保存支付编号&订单号到数据表,修改订单的状态(未支付-未发货),返回支付编号&成功信息
4. 如果支付未成功, 则返回错误信息
"""
def post(self, request):
# 后端接收前端发送的支付状态数据,转换成字典类型,获取signature
data_dict = request.query_params.dict()
signature = data_dict.pop('sign')
# 创建alipay对象, 将data & signature传递过去,获取支付状态
app_private_key_string = open("apps/pay/keys/app_private_key.pem").read()
alipay_public_key_string = open("apps/pay/keys/alipay_public_key.pem").read()
alipay = AliPay(
appid=settings.ALIPAY_APPID,
app_notify_url=None, # 默认回调url
app_private_key_string=app_private_key_string,
alipay_public_key_string=alipay_public_key_string, # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
sign_type="RSA2", # RSA 或者 RSA2
debug=settings.ALIPAY_DEBUG, # 默认False
)
success = alipay.verify(data_dict, signature)
if success:
order_id = data_dict.get('out_trade_no') # 商户订单号
trade_id = data_dict.get('trade_no') # 交易编号
# 如果支付成功,保存支付编号&订单号到数据表,修改订单的状态(未支付-未发货)
Payment.objects.create(order_id=order_id, trade_id=trade_id)
OrderInfo.objects.filter(pk=order_id).update(
status=OrderInfo.ORDER_STATUS_ENUM['UNSEND'])
return Response({'trade_id':trade_id}, status=status.HTTP_200_OK)
else:
return Response({'message':'订单支付失败'}, status=status.HTTP_400_BAD_REQUEST)
-------------------------- END ------------------------