閱讀支付寶開放平臺的電腦網站支付文檔前端
在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(...)
碼雲上配置的公鑰私鑰與電腦進行綁定, 支付寶開放平臺配置的公鑰私鑰與項目應用進行綁定