Build an Alipay Payment System with Django: Step‑by‑Step Guide

This tutorial walks you through creating a Django project, configuring RSA keys, setting up Alipay sandbox credentials, writing a Python Alipay class, building front‑end pages, and wiring view functions and URLs to enable PC‑side Alipay payments.

Python Crawling & Data Mining
Python Crawling & Data Mining
Python Crawling & Data Mining
Build an Alipay Payment System with Django: Step‑by‑Step Guide

1. Introduction

The article shows how to use the Python web framework Django to implement Alipay payment, a useful project for the upcoming Chinese New Year when many users prefer WeChat or Alipay for transactions.

2. Create Django Project and App

First create a Django project and an app inside it.

3. Configure and Start

Set up urls.py for the project and the app, then run migrations and start the development server.

After configuring the URLs, run python manage.py migrate and python manage.py runserver to verify the app starts correctly.

4. Generate RSA Keys and Configure Alipay

Log in to the Alipay developer console, create an application, and set the encryption method to RSA2 (SHA256). Download the Alipay key generator (or use OpenSSL) to generate a public/private key pair, then upload the public key to the Alipay console and save both keys locally.

Store the generated private2048.txt, public2048.txt, and Alipay public key files in a rsakey folder inside the Django app.

5. PC‑Side Alipay Payment Interface

Encapsulate the payment logic in a Python class AliPay:

from datetime import datetime
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from urllib.parse import quote_plus, urlparse, parse_qs
from base64 import decodebytes, encodebytes
import json

class AliPay(object):
    """Alipay payment interface (PC side)"""
    def __init__(self, appid, app_notify_url, app_private_key_path,
                 alipay_public_key_path, return_url, debug=False):
        self.appid = appid
        self.app_notify_url = app_notify_url
        self.app_private_key_path = app_private_key_path
        self.app_private_key = None
        self.return_url = return_url
        with open(self.app_private_key_path) as fp:
            self.app_private_key = RSA.importKey(fp.read())
        self.alipay_public_key_path = alipay_public_key_path
        with open(self.alipay_public_key_path) as fp:
            self.alipay_public_key = RSA.importKey(fp.read())
        self.__gateway = "https://openapi.alipaydev.com/gateway.do" if debug else "https://openapi.alipay.com/gateway.do"

    def direct_pay(self, subject, out_trade_no, total_amount, return_url=None, **kwargs):
        biz_content = {"subject": subject, "out_trade_no": out_trade_no,
                       "total_amount": total_amount, "product_code": "FAST_INSTANT_TRADE_PAY"}
        biz_content.update(kwargs)
        data = self.build_body("alipay.trade.page.pay", biz_content, self.return_url)
        return self.sign_data(data)

    def build_body(self, method, biz_content, return_url=None):
        data = {"app_id": self.appid, "method": method, "charset": "utf-8",
                "sign_type": "RSA2", "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                "version": "1.0", "biz_content": biz_content}
        if return_url is not None:
            data["notify_url"] = self.app_notify_url
            data["return_url"] = self.return_url
        return data

    def sign_data(self, data):
        data.pop("sign", None)
        unsigned_items = self.ordered_data(data)
        unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in unsigned_items)
        sign = self.sign(unsigned_string.encode("utf-8"))
        quoted_string = "&".join("{0}={1}".format(k, quote_plus(v)) for k, v in unsigned_items)
        signed_string = quoted_string + "&sign=" + quote_plus(sign)
        return signed_string

    def ordered_data(self, data):
        complex_keys = []
        for key, value in data.items():
            if isinstance(value, dict):
                complex_keys.append(key)
        for key in complex_keys:
            data[key] = json.dumps(data[key], separators=(",", ":"))
        return sorted([(k, v) for k, v in data.items()])

    def sign(self, unsigned_string):
        signer = PKCS1_v1_5.new(self.app_private_key)
        signature = signer.sign(SHA256.new(unsigned_string))
        return encodebytes(signature).decode("utf8").replace("
", "")

    def _verify(self, raw_content, signature):
        signer = PKCS1_v1_5.new(self.alipay_public_key)
        digest = SHA256.new()
        digest.update(raw_content.encode("utf8"))
        return signer.verify(digest, decodebytes(signature.encode("utf8")))

    def verify(self, data, signature):
        data.pop("sign_type", None)
        unsigned_items = self.ordered_data(data)
        message = "&".join(u"{}={}".format(k, v) for k, v in unsigned_items)
        return self._verify(message, signature)

6. Front‑End Pages

Two simple HTML templates are used: index.html to display a product list and show.html to show the payment result.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        table, table tr th, table tr td { border:1px solid #0094ff; }
        table { width:300px; min-height:25px; line-height:25px; text-align:center; border-collapse:collapse; padding:2px; }
        a{ text-decoration:none; }
    </style>
</head>
<body>
    <h1>欢迎来到购物商场</h1>
    <table border="1">
        <thead>商品目录</thead>
        <tr><td>商品名</td><td>商品单价</td><td>商品数量</td><td>是否购买</td></tr>
        <tr><td>梨子</td><td>0.1</td><td>1</td><td><a href="{% url 'dingdan' %}">购买</a></td></tr>
    </table>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <h1>支付结果:{{msg}}</h1>
</body>
</html>

7. View Functions

from django.shortcuts import render, redirect
from django.http import HttpResponse, JsonResponse
from .pay import AliPay
import uuid
from urllib.parse import parse_qs

def index(request):
    return render(request, 'index.html')

def dingdan(request):
    alipay = AliPay(appid="YOUR_APPID", app_notify_url='http://127.0.0.1:8000/paypay/check/',
                    return_url='http://127.0.0.1:8000/paypay/show/',
                    app_private_key_path=r'C:\path\private2048.txt',
                    alipay_public_key_path=r'C:\path\paypublic.txt', debug=True)
    res = alipay.direct_pay(subject='梨子', out_trade_no=str(uuid.uuid4()), total_amount='0.1')
    url = 'https://openapi.alipaydev.com/gateway.do?{0}'.format(res)
    return redirect(url)

def show(request):
    if request.method == 'GET':
        alipay = AliPay(appid="YOUR_APPID", app_notify_url='http://127.0.0.1:8000/paypay/check/',
                        return_url='http://127.0.0.1:8000/paypay/show/',
                        app_private_key_path=r'C:\path\private2048.txt',
                        alipay_public_key_path=r'C:\path\paypublic.txt', debug=True)
        param = request.GET.dict()
        sign = param.pop('sign', None)
        statu = alipay.verify(param, sign)
        if statu:
            return render(request, 'show.html', {'msg': '支付成功'})
        else:
            return render(request, 'show.html', {'msg': '支付失败'})
    else:
        return render(request, 'show.html', {'msg': '只支持GET请求,不支持其它请求'})

def check(request):
    if request.method == 'POST':
        alipay = AliPay(appid="YOUR_APPID", app_notify_url='http://127.0.0.1:8000/paypay/check/',
                        return_url='http://127.0.0.1:8000/show_msg/',
                        app_private_key_path=r'C:\path\private2048.txt',
                        alipay_public_key_path=r'C:\path\paypublic.txt', debug=True)
        body = request.body.decode('utf-8')
        post_data = parse_qs(body)
        post_dict = {k: v[0] for k, v in post_data.items()}
        sign = post_dict.pop('sign', None)
        status = alipay.verify(post_dict, sign)
        return HttpResponse('支付成功' if status else '支付失败')
    else:
        return HttpResponse('只支持POST请求')

8. URL Routing

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('dingdan/', views.dingdan, name='dingdan'),
    path('show/', views.show, name='show'),
    path('check/', views.check, name='check'),
]

9. Run the Project

After all files are in place, execute python manage.py migrate and python manage.py runserver. Visiting the home page, selecting a product, and clicking “购买” will redirect to the Alipay sandbox payment page, and the result will be displayed on show.html.

10. Summary

The sandbox implementation works, but you must replace the placeholder APPID and upload your own RSA public/private keys before using it in production.

Pythonbackend developmentDjangopayment integrationAlipayWeb Tutorial
Python Crawling & Data Mining
Written by

Python Crawling & Data Mining

Life's short, I code in Python. This channel shares Python web crawling, data mining, analysis, processing, visualization, automated testing, DevOps, big data, AI, cloud computing, machine learning tools, resources, news, technical articles, tutorial videos and learning materials. Join us!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.