阅读支付宝开放平台的电脑网站支付文档前端
在github上搜索alipay, 选择星最多的sdk, 而后安装: pip install python-alipay-sdk --upgradepython
下载支付宝官方提供的一键生成 RSA 密钥工具, 生成应用公钥和应用私钥, 将应用公钥添加到支付宝开放平台, 而后获取支付宝公钥ios
二次封装网页支付sdkgit
''' # ...\luffyapi\luffyapi\libs\alipay\web_pay.py from alipay import AliPay from .settings import * alipay = AliPay( # 真实appid则debug为False, 沙箱appid则debug为True appid=APP_ID, debug=DEBUG, app_notify_url=None, app_private_key_string=APP_PRIVATE_KEY_STRING, alipay_public_key_string=ALIPAY_PUBLIC_KEY_STRING, sign_type=SIGN, ) # ...\luffyapi\luffyapi\libs\alipay\__init__.py from .web_pay import alipay from .settings import GATEWAY as alipay_gateway # 支付宝网关接口 '''
''' # ...\luffyapi\luffyapi\apps\order\views.py ... from rest_framework.generics import CreateAPIView from rest_framework.permissions import IsAuthenticated class OrderCreateAPIView(CreateAPIView): permission_classes = [IsAuthenticated] # 设置登陆后才能购买课程 serializer_class = order_serializers.OrderModelSerializer def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data, context={'request': request}) # 将request对象传入OrderModelSerializer类中 serializer.is_valid(raise_exception=True) self.perform_create(serializer) return Response(serializer.pay_url) # ...\luffyapi\luffyapi\apps\order\order_serializers.py from rest_framework import serializers from . import models from ..course.models import Course class OrderModelSerializer(serializers.ModelSerializer): courses = serializers.PrimaryKeyRelatedField(required=True, queryset=Course.objects.all(), many=True) # 自定义反序列化字段 class Meta: model = models.Order fields = ['subject', 'total_amount', 'pay_type', 'courses'] ... def _check_total_amount(self, attrs): total_amount = attrs.get('total_amount') # 获取前端传过来的订单总价 # 根据订单中的课程信息统计出实际的订单总价 total_amount_temp = 0 courses = attrs.get('courses') for course in courses: total_amount_temp += course.price # 将前端传过来的订单总价与实际的订单总价进行比对 if total_amount != total_amount_temp: raise serializers.ValidationError({'total_amount': '价格异常'}) return total_amount def _get_out_trade_no(self): import time temp_no = '%.7f' % time.time() out_trade_no = temp_no.replace('.', '') return out_trade_no[-13: -1] # 从传入的request对象中获取用户对象 def _get_request_user(self): return self.context.get('request').user def _get_pay_url(self, out_trade_no, total_amount, subject): from luffyapi.libs.alipay import alipay, alipay_gateway from django.conf import settings order_string = alipay.api_alipay_trade_page_pay( out_trade_no=out_trade_no, total_amount=str(total_amount), subject=subject, return_url=settings.RETURN_URL, # 同步回调的前端接口 notify_url=settings.NOTIFY_URL # 异步回调的后端接口 ) return alipay_gateway + order_string def validate(self, attrs): total_amount = self._check_total_amount(attrs) # 校验订单总价 out_trade_no = self._get_out_trade_no() # 生成订单号 user = self._get_request_user() # 获取下单用户 pay_url = self._get_pay_url(out_trade_no, total_amount, attrs.get('subject')) # 生成支付连接 self.pay_url = pay_url # 将支付连接绑定给OrderModelSerializer类的pay_url属性 # 在订单表中建立新的订单记录时所须要的额外字段数据 attrs['out_trade_no'] = out_trade_no attrs['user'] = user return attrs 重写create方法: 1. 在订单表中建立新的订单记录, 2. 在订单详情表中建立新的订单详情记录 def create(self, validated_data): courses = validated_data.pop('courses') # 将订单中的课程信息取出额外记录到订单详情表中 order_obj = models.Order.objects.create(**validated_data) # 在订单表中建立新的订单记录 # 在订单详情表中建立新订单详情记录 for course in courses: models.OrderDetail.objects.create(order=order_obj, course=course, price=course.price, real_price=course.price) return order_obj '''
''' # ...\luffyapi\luffyapi\apps\order\views.py ... from luffyapi.libs.alipay import alipay from luffyapi.utils.my_logging import logger ... class PayResAPIView(APIView): # 对前端转发的支付宝同步回调数据做出响应 def get(self, request, *args, **kwargs): return Response(data='received') # 处理支付宝异步回调传过来的数据 def post(self, request, *args, **kwargs): data = request.data.dict() # QueryDict类的对象没有pop方法, 能够经过".dict()"转化为dict类的对象 # 验签 sign = data.pop('sign') result = alipay.verify(data, sign) out_trade_no = data.get('out_trade_no') # 获取订单号 trade_status = data.get("trade_status") # 获取交易状态 # 根据验签结果和交易状态修改数据库中的订单状态 if result and trade_status in ("TRADE_SUCCESS", "TRADE_FINISHED"): models.Order.objects.filter(out_trade_no=out_trade_no).update(order_status=1) logger.critical('订单号:%s, 交易状态: %s' % (out_trade_no, trade_status)) # 项目上线后, 没有控制台输出结果, 须要经过日志记录订单支付信息 return Response('success') return Response('failed') '''
drf-jwt的JWT_AUTH配置须要写在drf的REST_FRAMEWORK配置以前github
前端携带tokenweb
''' this.$axios({ ..., headers: { authorization: `jwt ${token}`, } }).then(response => { ...; }).catch(error => { ...; }) '''
前端非同站点页面跳转: window.open(url, '_self')
, _self表示跳转时不新开标签页, 前端同站点页面跳转: this.$router.push(url)
数据库
前端使用 location.search 获取url中?以及?后的字符串django
前端字符串裁剪: "cql".substring(1, 2) # q
axios
前端异常处理语句: try {} catch (e) {}
后端
前端对url编码数据进行解码: decodeURLComponet(...)
码云上配置的公钥私钥与电脑进行绑定, 支付宝开放平台配置的公钥私钥与项目应用进行绑定