When integrating Alipay payment functionality, it's essential to understand the two main communication flows:
- Alipay server sends a synchronous callback result to the frontend
- Alipay server makes up to 8 asynchronous callback attempts to the backend, stopping when the backend returns 'success'
Setting Up the Alipay SDK
First, install the Alipay Python SDK from GitHub:
pip install python-alipay-sdk --upgrade
Next, generate RSA keys using the official Alipay tool:
- Create application public and private keys
- Add the application public key to the Alipay Open Platform
- Retrieve the Alipay public key
Alipay Payment SDK Configuraton
Create a wrapper for the Alipay web payment SDK:
# payment_sdk/alipay_client.py
from alipay import AliPay
from .config import *
class AlipayClient:
def __init__(self):
self.client = AliPay(
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_TYPE
)
def get_gateway(self):
return GATEWAY_URL
Order Creation and Payment Link Genertaion
Create an API endpoint for order creation:
# views/order_view.py
from rest_framework.generics import CreateAPIView
from rest_framework.permissions import IsAuthenticated
from .serializers import OrderSerializer
class OrderCreateView(CreateAPIView):
permission_classes = [IsAuthenticated]
serializer_class = OrderSerializer
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data, context={'request': request})
serializer.is_valid(raise_exception=True)
order = serializer.save()
return Response({'payment_url': order.payment_link})
The order serializer handles payment link generation:
# serializers/order_serializer.py
from rest_framework import serializers
from .models import Order
from ..course.models import Course
class OrderSerializer(serializers.ModelSerializer):
selected_courses = serializers.PrimaryKeyRelatedField(
queryset=Course.objects.all(),
many=True
)
class Meta:
model = Order
fields = ['title', 'amount', 'payment_method', 'selected_courses']
def _validate_amount(self, attrs):
amount = attrs.get('amount')
calculated_amount = 0
courses = attrs.get('selected_courses')
for course in courses:
calculated_amount += course.price
if amount != calculated_amount:
raise serializers.ValidationError({'amount': 'Price mismatch detected'})
return amount
def _generate_order_number(self):
import time
timestamp = str(time.time()).replace('.', '')
return timestamp[-12:]
def _get_current_user(self):
return self.context.get('request').user
def _create_payment_link(self, order_number, amount, title):
from payment_sdk.alipay_client import AlipayClient
from django.conf import settings
alipay = AlipayClient()
payment_params = alipay.client.api_alipay_trade_page_pay(
out_trade_no=order_number,
total_amount=str(amount),
subject=title,
return_url=settings.RETURN_URL,
notify_url=settings.NOTIFY_URL
)
return alipay.get_gateway() + payment_params
def validate(self, attrs):
amount = self._validate_amount(attrs)
order_number = self._generate_order_number()
user = self._get_current_user()
payment_link = self._create_payment_link(order_number, amount, attrs.get('title'))
self.payment_link = payment_link
attrs['order_number'] = order_number
attrs['user'] = user
return attrs
def create(self, validated_data):
courses = validated_data.pop('selected_courses')
order = Order.objects.create(**validated_data)
for course in courses:
order.details.create(course=course, price=course.price, actual_price=course.price)
return order
Alipay Asynchronous Callback Handling
Create a view to handle Alipay callbacks:
# views/payment_callback.py
from rest_framework.views import APIView
from rest_framework.response import Response
from payment_sdk.alipay_client import AlipayClient
from .models import Order
from ..utils.logging import log_payment
class PaymentCallbackView(APIView):
def get(self, request, *args, **kwargs):
return Response('Callback received')
def post(self, request, *args, **kwargs):
data = request.data.dict()
signature = data.pop('sign')
alipay = AlipayClient()
is_valid = alipay.client.verify(data, signature)
order_number = data.get('out_trade_no')
transaction_status = data.get('trade_status')
if is_valid and transaction_status in ('TRADE_SUCCESS', 'TRADE_FINISHED'):
Order.objects.filter(order_number=order_number).update(status='paid')
log_payment.critical(f'Order: {order_number}, Status: {transaction_status}')
return Response('success')
return Response('failed')
Important Implementation Notes
- Configure JWT_AUTH before REST_FRAMEWORK in Django settings
- Include authentication token in API requests: ```
this.$axios({
...,
headers: {
authorization:
jwt ${token}, } }) - Use window.open(url, '_self') for same-site navigation
- Use this.$router.push(url) for internal routing
- Retrieve URL parameters with location.search
- String manipulation examples: ```
"example".substring(1, 2) # returns 'x'
- Implement error handling with try-catch blocks
- Decode URL-encoded data with decodeURIComponent()
- Separate key management: local machine keys vs. Alipay platform keys