Implementing Alipay Payment Integration in Python: Order Creation and Callback Handling

When integrating Alipay payment functionality, it's essential to understand the two main communication flows:

  1. Alipay server sends a synchronous callback result to the frontend
  2. 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:

  1. Create application public and private keys
  2. Add the application public key to the Alipay Open Platform
  3. 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

Tags: alipay payment-integration python-sdk django-rest-framework asynchronous-callbacks

Posted on Sat, 05 Sep 2026 16:39:57 +0000 by jofield