支付宝支付接口
# 立即购买功能,点击立即购买按钮,使用支付宝支付
# 支付宝支付
-测试环境:大家都可以测试
ß
-正式环境:申请,有营业执照
-咱们做不了
# 咱们开发虽然用的沙箱环境,后期上线,公司会自己注册,注册成功后有个商户id号,作为开发,只要有商户id好,其他步骤都是一样,所有无论开发还是测试,代码都一样,只是商户号不一样
# 安装模块
pip install python-alipay-sdk
# 生成公钥私钥---》非对称加密
-使用支付宝提供的工具:https://opendocs.alipay.com/common/02kipl
-就可以生成公钥私钥
将公钥私钥写到python项目中调用
----iPay
-------pem
----------alipay_public_key.pem # 公钥文件
------------app_private_key.pem # 私钥文件
--------pay.py
--------setting.py
公钥私钥文件
alipay_public_key.pem
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAswwWYb08z/lNZ9uzgZ7hcKs4LJoOBymp5WTXVrv6hIjkhadmoUDLhk0eT5eAtt3YaNLQ4eJyAVhdudeVzjdaxXwNgrGgyroDy+tdl1Mx3kKSBYjJmXzhn83663jw3is931ZVOr7lSg/g/9hdF4U2HqnkWPQ5pDDuIuz3/b2I7pwFJwTkjj0wP4VJMStspH4HQEUxHQ3KglgGElYHH31MC7bSG3lVwh1DcbnDfd8C9uH3tI8UWK13xOBajDwsMrONe64w7sqmZE4/VSIjqE+E3kzKPKvCfm4qhYbJRCE1SfSX0kONNb/7hQSnqvHD7AzUYBrZWgHAwg+8AVlJrR81ZwIDAQAB
-----END PUBLIC KEY-----
app_private_key.pem
-----BEGIN RSA PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCzDBZhvTzP+U1n27OBnuFwqzgsmg4HKanlZNdWu/qEiOSFp2ahQMuGTR5Pl4C23dho0tDh4nIBWF2515XON1rFfA2CsaDKugPL612XUzHeQpIFiMmZfOGfzfrrePDeKz3fVlU6vuVKD+D/2F0XhTYeqeRY9DmkMO4i7Pf9vYjunAUnBOSOPTA/hUkxK2ykfgdARTEdDcqCWAYSVgcffUwLttIbeVXCHUNxucN93wL24fe0jxRYrXfE4FqMPCwys417rjDuyqZkTj9VIiOoT4TeTMo8q8J+biqFhslEITVJ9JfSQ401v/uFBKeq8cPsDNRgGtlaAcDCD7wBWUmtHzVnAgMBAAECggEAbpdou7ZHea5jQWNS3R1l4lHfwKznPUVey3IeEFTLyFFF1cgwfCmpjKrVrhPGTS16HkUZAGz+PhZ2zfN7dIR8bL7TGYbd6lo7PhmDFZUtmDtGNmTnIQch1bNE6W0qWhAbh3er7T08IyLrtxvNZFnDs+z8PnWbpO8UKD52byRDEB4Dffr6GGkEBXp6+9n8lO0SzujYfBv6NR3wih4XLFEn6Zy1UrKj2jBdFICBWLn/MUA2z+aIWqriciqxju+9XLoI0TcVz0lEPlnVm+DBnyrcwWprp+0CdfimktWa07zxPLc8IN5PfQebNr7w9vtu4hRQ9le94/5SHhtKBxZSIWXpAQKBgQD2PZFlilR1Ebpu18yAGcrzflMzgYsyXFrftYHA2J6h5wcjt3o5skXUv98Ae4v9WV5kH1nzwiruq/SvFQAfh1b54f7PZnzj9hf6CQ5AKfudtKXg+P2+kClzc85lCjZT9QlYHFt8Kuulp+FZcU07aI0mDN6EaJo50eLgRJFARXXrlQKBgQC6JMF1lWUChjz80DuOjA4YcAMlPa7Fxri2ZnNUlFNOGOtjNp1shk2sL1cVAynKDAM40YfyPLzWODR//wSFm9VbeObJTwnXbdHEp2h+6lCw2XetC0O0YT8SEFPtx6EvfLuI0Q85JC6kZPdXmRVrY00rhpU/UPKeb5Wip1PrGgA+CwKBgBXLw1fyk6E9LXxsO5zHK7C76M9xUwnlJOISZebVBc2c7oPZ1MbQod/AEBQx22VUiMdiAwtRj41KyUDKIhWoXCmIOI7RKpLfEKZAMPO7A5ulBt3QDF3W0uR2Rrmo2sA5u1cCQ5LNFci3AHpzTfvJOF063GNqAuTFUEi7qQPAYjy1AoGAUPiEHv3pfnueM+rwvUU3LHItLBn02Jtk5hMSwAv1YNd+LR4oxHh3eRruqnlByF4JWMHsfPbmvdidHcB02xm6aZvh6Fe1VDy1LvIThoGur/8pC+EGhoR2xwjLOXfJKbr8aLtn/9c5YtF4tmYk5x2/B9v3OB+iKkEnuiVHX9FjoZkCgYAvzXcb0jJcrDowlF8b2hrZCBizI7thaKKXPwXL3zjsxboKnPZF2F1OBFQWBhPUB/Or9OIoesdH0AAx0OysXgzaQXOlhQYiXKXMvEEb2e1ngu9kptDhq13ER2ZlIYo9YkB8HYIBD/mFTWYPMGaBTv1D9MNWnfKNOuD4U0mkBLS7Kw==
-----END RSA PRIVATE KEY-----
主要pay.py文件
from alipay import AliPay
import settings
# 支付对象
alipay = AliPay(
appid=settings.APP_ID,
app_notify_url=None,
app_private_key_string=settings.APP_PRIVATE_KEY_STRING,
alipay_public_key_string=settings.ALIPAY_PUBLIC_KEY_STRING,
sign_type=settings.SIGN,
debug=settings.DEBUG
)
# 支付网关
gateway = settings.GATEWAY
res = alipay.api_alipay_trade_page_pay(subject='完美世界', out_trade_no='12322222222', total_amount=99)
print('https://openapi.alipaydev.com/gateway.do?'+res)
# 这个就是跳转到支付宝支付的链接
settings.py文件 存放配置常量的文件
import os
# 应用私钥
APP_PRIVATE_KEY_STRING = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'pem', 'app_private_key.pem')).read()
# 支付宝公钥
ALIPAY_PUBLIC_KEY_STRING = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'pem', 'alipay_public_key.pem')).read()
# 应用ID
APP_ID = '2021000122628427'
# appid获取地址 https://openhome.alipay.com/develop/sandbox/app
# 加密方式
SIGN = 'RSA2'
# 是否是支付宝测试环境(沙箱环境),如果采用真是支付宝环境,配置False
DEBUG = True
# 支付网关
GATEWAY = 'https://openapi.alipaydev.com/gateway.do' if DEBUG else 'https://openapi.alipay.com/gateway.do'
二次封装支付宝支付
libs
├── alipay_v1 # aliapy二次封装包
│ ├── __init__.py # 包文件
│ ├── pem # 公钥私钥文件夹
│ │ ├── alipay_public_key.pem # 支付宝公钥文件
│ │ ├── app_private_key.pem # 应用私钥文件
│ ├── pay.py # 支付文件
└── └── settings.py
init
from .pay import alipay
from .settings import GATEWAY
pay.py
from alipay import AliPay
from alipay.utils import AliPayConfig
from . import settings
# 支付对象
alipay = AliPay(
appid=settings.APP_ID,
app_notify_url=None,
app_private_key_string=settings.APP_PRIVATE_KEY_STRING,
alipay_public_key_string=settings.ALIPAY_PUBLIC_KEY_STRING,
sign_type=settings.SIGN,
debug=settings.DEBUG,
config=AliPayConfig(timeout=15)
)
# 支付网关
gateway = settings.GATEWAY
下单接口
前端传入 课程id 总金额 商品标题
view.py
class PayView(GenericViewSet, CreateModelMixin):
queryset = Order.objects.all()
serializer_class = PaySerializers
def create(self, request, *args, **kwargs):
res = self.get_serializer(data=request.data)
res.is_valid(raise_exception=True)
self.perform_create(res)
pay_url = res.context.get('pay_url')
return MyResponse(pay_url=pay_url)
# 获得alipay支付网址 传给前端 用户用来支付
具体校验 和 创建订单逻辑都在序列化类中
序列化类
from rest_framework import serializers
from .models import Order, OrderDetail
from LufeiApi.apps.course.models import Course
from uuid import uuid4
from rest_framework.exceptions import APIException
from LufeiApi.libs.alipay_v1 import alipay, gateway
from django.conf import settings
from LufeiApi.apps.user.models import User
class PaySerializers(serializers.ModelSerializer):
courses = serializers.PrimaryKeyRelatedField
(queryset=Course.objects.all(), many=True,write_only=True)
# 序列化关联的表中没有courses字段,所以需要重写该字段
# PrimaryKeyRelatedField 可以通过用户传的主键id 直接查询返回对象
# courses = [数据对象,数据对象]
class Meta:
model = Order
fields = ['courses', 'total_amount', 'subject']
def _check_total_amount(self, attrs):
# 检查前端传来的金额和后端实际金额是否匹配
courses = attrs.get('courses')
total_amount = attrs.get('total_amount')
new_total_amount = 0
for course in courses:
new_total_amount = new_total_amount + course.price
if new_total_amount == total_amount:
return new_total_amount
raise APIException('价格有误')
def _get_out_trade_no(self):
# 生成一个订单号
res = str(uuid4())
return res
def _get_user(self):
# 获得下单用户对象
user = self.context.get('request').user
return user
def _get_pay_url(self, total_amount, out_trade_no, subject):
# 获得支付链接
res = alipay.api_alipay_trade_page_pay(
total_amount=float(total_amount),
subject=subject,
out_trade_no=out_trade_no,
return_url=settings.RETURN_URL,
# 后端支付接口回调地址
# NOTIFY_URL = BACKEND_URL + '/order/success'
notify_url=settings.NOTIFY_URL)
# 前端接口回调地址 RETURN_URL = LUFFY_URL + '/pay/success'
self.context['pay_url'] = gateway + res
# 将生成的支付链接存入.context中
def _before_create(self, attrs, out_trade_no):
# 存入数据库生成表单前的操作
attrs['out_trade_no'] = out_trade_no
attrs['user'] = User.objects.filter(pk=1).first()
def validate(self, attrs):
subject = attrs.get('subject')
total_amount = self._check_total_amount(attrs)
out_trade_no = self._get_out_trade_no()
# user = self._get_user()
self._get_pay_url(total_amount, out_trade_no, subject)
self._before_create(attrs, out_trade_no)
return attrs
def create(self, validated_data):
courses = validated_data.pop('courses')
# 由于Order表中没有courses字段 所以要剔除
order = Order.objects.create(**validated_data)
# 生成订单表
for course in courses:
# 针对每一个课程生成订单详情表
OrderDetail.objects.create(order=order, course=course, price=course.price, real_price=course.price)
return order
支付宝回调接口
class PaySuccessView(APIView):
def get(self, request):
# 给前端用的,前端请求该接口可以查看是否支付成功
out_trade_no = request.query_params.get('out_trade_no')
try:
Order.objects.get(out_trade_no=out_trade_no, order_status=1)
return MyResponse(msg='支付成功')
except Exception:
return MyResponse(code=101, msg='暂未收到款项,请稍等')
def post(self, request):
# 支付宝回调使用 可以验证用户是否支付成功
try:
result_data = request.data.dict()
out_trade_no = result_data.get('out_trade_no')
signature = result_data.pop('sign')
from LufeiApi.libs import alipay_v1
result = alipay_v1.alipay.verify(result_data, signature)
# verif用来验证签名的
if result and result_data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED"):
# 完成订单修改:订单状态、
Order.objects.filter(out_trade_no=out_trade_no).
update(order_status=1)
# 完成日志记录
logger.warning('%s订单支付成功' % out_trade_no)
return Response('success')
else:
logger.error('%s订单支付失败' % out_trade_no)
except:
pass
return Response('failed')
# 支付宝要求的格式,不允许带 code 什么的 固定写法
urls.py
from django.urls import path
from rest_framework.routers import SimpleRouter
from LufeiApi.apps.order import views
router = SimpleRouter()
router.register('pay',views.PayView,'pay')
urlpatterns = [
# api/v1/order/success/
path('success/',views.PaySuccessView.as_view())
# 支付宝回调地址
]
urlpatterns += router.urls
标签:alipay,支付宝,no,settings,接口,trade,路飞,import,out
From: https://www.cnblogs.com/moongodnnn/p/17216077.html