Giao diện API Thanh toán Trong Dự Án

Giao diện API Thanh toán Trong Dự Án

1. Sử dụng giao diện API Thanh toán qua Alipay

  • Trong quá trình phát triển thực tế, chúng ta thường thử nghiệm trước trên môi trường sandbox của Alipay, sau đó chuyển sang môi trường thật.
  • Các bước thực hiện:
1. Truy cập Alipay Open Platform → Trung tâm Phát triển → Ứng dụng Web & Mobile (Chi tiết: Xem thêm) → Tài liệu toàn bộ → Năng lực Thanh toán → Thanh toán trang web → Nhanh chóng kết nối → Theo tài liệu nhanh chóng kết nối để tạo và cấu hình ứng dụng
    
2. Sau khi cấu hình ứng dụng xong, tiến hành cấu hình API thanh toán trong dự án (https://github.com/fzlee/alipay#alipay.trade.page.pay)  
    
3. Khi cấu hình API thanh toán trong dự án hoàn tất, vì cần thử nghiệm trên sandbox, hãy cấu hình môi trường sandbox: Trung tâm Phát triển → Vào bảng điều khiển → Dịch vụ phát triển → Dịch vụ phát triển → Xem môi trường sandbox   
    Các cổng trong môi trường sandbox đều là cổng hợp lệ trên internet, được sử dụng để gắn các tham số vào sau cổng, tạo ra liên kết thanh toán
    Mã QR được tạo ra từ môi trường sandbox chỉ có thể được quét bởi phiên bản sandbox của Alipay (chỉ sử dụng tài khoản sandbox được cung cấp mới có thể thử nghiệm)

2. Sơ đồ luồng công việc của giao diện thanh toán trong dự án

(1) Sơ đồ luồng

(2) Giải thích

  • Chỉ cần phía trước gửi yêu cầu mua sắm đến phía sau, phía sau xử lý và trả về một liên kết thanh toán (liên kết chứa cả callback phía trước và phía sau), đồng thời tạo đơn hàng, phía trước truy cập liên kết thanh toán (cũng cung cấp cho ứng dụng Alipay callback đồng bộ phía trước và callback phía sau), nhận được trang thanh toán, người dùng tương tác trực tiếp với nền tảng Alipay, Alipay sẽ trả về kết quả giao dịch cho callback phía trước và phía sau, cuối cùng, callback xác định giao dịch này có thành công hay không, thành công thì trả về chuỗi 'success', thất bại thì trả về bất kỳ dữ liệu nào khác.
  • Alipay sẽ gửi một yêu cầu callback đồng bộ kiểu GET đến phía trước, gửi tối đa 8 lần yêu cầu callback bất đồng bộ kiểu POST đến phía sau (để tránh lãng phí tài nguyên máy chủ phía sau).
  • Lưu ý: Trong callback phía sau, khi phản hồi thành công, nhất định phải trả về 7 ký tự 'success', khi phản hồi thất bại, kết quả trả về không quan trọng.

3. Cấu hình API Thanh toán Trong Dự Án

  • Ta sử dụng SDK thanh toán Python của Alipay từ GitHub để cấu hình.

(1) Cấu hình API Thanh toán Phía Sau Dự Án

1. Cài đặt phụ thuộc

pip install python-alipay-sdk --upgrade
pip install pyopenssl

2. Cấu trúc API Thanh toán Trong Dự Án

libs
    ├── iPay  							# gói đóng gói lại của aliapy
    │   ├── __init__.py 				# tập tin gói
    │   ├── pay.py						# tập tin thanh toán
    └── └── settings.py  				# cấu hình ứng dụng  

3. Tập tin settings.py Trong Thư Mục iPay

  • Lưu ý: Định dạng viết khóa riêng tư và khóa công khai, tổng cộng 3 dòng, mỗi dòng không được có khoảng trắng ở đầu.
# ID ứng dụng
APP_ID = "2016093000631831"

# Có phải là môi trường sandbox hay không, True nếu sử dụng sandbox, False nếu sử dụng môi trường thật
DEBUG = True

# Thuật toán ký RSA hoặc RSA2
SIGN = 'RSA2'

# Cổng
if DEBUG:
    GATEWAY = 'https://openapi.alipaydev.com/gateway.do?'
else:
    GATEWAY = 'https://openapi.alipay.com/gateway.do?'

# Khóa riêng tư ứng dụng: hai dòng đầu và cuối cố định, giữa là chuỗi khóa riêng tư (không được có ký tự khác)
APP_PRIVATE_KEY_STRING = """-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAl079YgKIx0BFbZJL+HOWBa4+HBoRIX4+rKZXSxqM29/Up86RI4YJkqpBQNb6JC2G9+5av/p3bwQffTCPaxWV5iWFJjTfN3tC6efupOHCtBejr+id+lYhyaudfripjhTJX/N9hmoGIMRb6aMY8FbjrPbNyHoYBWE6pVa/8AmvqPkRmpZMr/UcSlHIVPoPWADWunKwQXL258LisiPY6u1I7gWiTQNsyG8JFYcMDK3I23ls0hAALO0ogHhSJEflCqjlLDMW8AXloih8Pqys5aink05cpIqOobUtGGaLRNTAZXx5jaqA2rJyQRx1rdU6pwenqZZY9Gf9LGlJAxdzOsofqQIDAQABAoIBAEDx9Kx27gKoQaSwYM95vXEewyYIwkWgDILKuzlPYhqWTo7giUe4Jq+/SFbub1vL9tzAgE9a0JzkJif0CfsqvraUcDxgAVetHqGLndFD3fCzHN1KeVSUV9haQzW7SXvkzDLVLpHdPFggMFtuWCwA/6SkItvkHB9jBmsleykq3y0lX5xu5zRrnNBNFj4AVHjbPINpO/13ZK6Ue5mFaK+xnLh4FjJzw6K7Nm8d2VniWjHJZSmYacxSX4D23na+ZipbkAsrJqPP3mqm2acg8L8Ms6DD9CfghfwdSdBJpSa+ul9v7jHxZkw6Q46dPvxNRKiQVFbuCwf1728M1EEKI0MB4ykCgYEA6wETGvZLZvY0d1H7cedDp8P12aMgaeYYs7GDwR/Ljd4RLfTzZKaMUsyT91D4jgw4ZGv6b7mZksUeYIA9U5j0A19bvn6mszaDgHoALVrTYLWDpl0HHpCTU56Rp1GOPgbzC8ap19W2Ac7gzIS+AU0Ap7n0BflcLdOIKt9oSfdcOMcCgYEApNOpIPx9hdL+/QDSzOX5w0dSTr1zv5spxb6sVyj5d0MXy48tHdLdzil1eF576dTF0ffX53IRrg3/6GFA0VLSU/OUqHJU9z5d1QlJd3Ff6MVen/dZYEMxMZwp/Ha5xHAryXU/FpNxHGc7ci3EIHQ1u3OgMei1brnoWZXypgWy1A8CgYB5UMy0FoFGXcMn9cKAQorCiH7aI0QQZyBJY1JI2EkUq5biypj7VJ8L/2BDRCGL8vMJpFRcaMvG4MuVtZ3zEfql4wxRgsA7s+Ce6lw9Da4hNpMHxu5t8OSdPjai0Y9EpgHCCoSTT1fuBwY1jjEoKsAz1eMLUncrkQ+yUjJcPL328QKBgQCRnp4RkoCjNqIojA2xEIz0xZImFqKoaUEify5rYrvjbdcb9EZ7zsw/U8mAqpj3IRAUTM7mn5SXHa81cpZ9WJqRqOVxXHFMbkEf8bCCYhvF3nmXAkRoE3Tmy30cmxfMQP2uYnN2UpTf7yRJ370inwjJr4GcFmgUhxKL8zoJC4fOaQKBgFXp/rWzgaG3f+VJW2d9BspEGy7LzxnnkPtIxKsHW/SS0pAIqDqQelkSqX+cxFzgxku15TwAOvWPcAAu2ZTM2yzky6JS1jk++ysafWWwcQDlxoNKOczy5cgmESkf3j3979Azqo+ic2EzcFoSs9r4o4x4HoplxqBE48BMrbcN5iIk
-----END RSA PRIVATE KEY-----"""

# Khóa công khai Alipay: hai dòng đầu và cuối cố định, giữa là chuỗi khóa công khai (không được có ký tự khác)
ALIPAY_PUBLIC_KEY_STRING = """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgCLK/MIs0gsKSk/DqzKwf7F9m8hyGqJM97af5IRkEdVCvFI5U1Y8xZsR8mWj+YhIU9rv48zZn81uJ7OqkkWXc/ENCMqGTiEe4tKPniLibTdpaIgPNn9c3QSa03psvJI8v/n5+0rs+KKXxN8UwLcmMMN5Zfy8Ejvq/rax9EXepxLqSP7xQ8DXHRBCkFHUY6W2vdIKQZFc8wqMqglRjGjfN8OgYwaN2F6TPPPHdoVbpjduEx1RlACItapHNWv21YTr0PYx+edb3Oj+Tjfinzuyb9S0uXDEHOOGeLrerOSJr3rVwDJpFKye6Lojz9H7aV+gki1Mp4W2qykyefYEmkDtYwIDAQAB
-----END PUBLIC KEY-----"""

4. Tập tin pay.py Trong Thư Mục iPay

from alipay import AliPay
from .settings import *

alipay = AliPay(
    appid=APP_ID,
    app_notify_url=None,  # Thông thường, giao diện thông báo này được thiết lập là None
    # Khóa riêng tư ứng dụng
    app_private_key_string=APP_PRIVATE_KEY_STRING,
    # Khóa công khai Alipay
    alipay_public_key_string=ALIPAY_PUBLIC_KEY_STRING,
    # Thuật toán ký, sử dụng RSA2
    sign_type=SIGN,  # RSA hoặc RSA2
    # Có phải là môi trường sandbox hay không
    debug=DEBUG
)

5. Tập tin __init__.py Trong Thư Mục iPay

# Cung cấp đối tượng thanh toán alipay đã được cấu hình
from .pay import alipay
# Cung cấp cổng thanh toán alipay
from .settings import GATEWAY as alipay_gateway

6. Cấu hình Giao diện Callback Alipay Trong Tập tin dev.py Của Dự Án

# Sau khi triển khai, phải đổi thành địa chỉ công cộng
# Đường dẫn gốc HTTP phía sau
BASE_URL = 'http://127.0.0.1:8000'

# Đường dẫn gốc HTTP phía trước
LUFFY_URL = 'http://127.0.0.1:8080'

# Giao diện callback thành công đơn hàng phía sau
NOTIFY_URL = BASE_URL + '/order/thanh-cong'

# Giao diện callback thành công đơn hàng phía trước
RETURN_URL = LUFFY_URL + '/thanh-toan/thanh-cong'

(2) Ứng dụng Đơn hàng Phía Sau Dự Án: order

1. Tập tin urls.py của order: *****************************************************

from django.urls import path, re_path
from . import views
urlpatterns = [
    # Thanh toán
    path('thanh-toan', views.ThanhToanAPIView.as_view()),
    # Callback thành công thanh toán
    path('thanh-cong', views.ThanhCongAPIView.as_view()),
]

2. Tập tin models.py của order: *****************************************************

# Bảng đơn hàng: Khóa chính, tên tổng sản phẩm, tổng giá, thời gian tạo đơn hàng, thời gian thanh toán, người dùng thanh toán, số đơn hàng, số giao dịch
# Bảng chi tiết đơn hàng: Khóa chính, khóa ngoại đơn hàng, khóa ngoại sản phẩm (khóa học)

from django.db import models
from utils.model import BaseModel
from user.models import User
from khoahoc.models import KhoaHoc

class DonHang(BaseModel):
    """Mô hình đơn hàng"""
    trang_thai_choices = (
        (0, 'Chưa thanh toán'),
        (1, 'Đã thanh toán'),
        (2, 'Đã hủy'),
        (3, 'Hủy do hết hạn'),
    )
    phuong_thuc_thanh_toan_choices = (
        (1, 'Alipay'),
        (2, 'WeChat Pay'),
    )
    tieu_de = models.CharField(max_length=150, verbose_name="Tiêu đề đơn hàng")
    tong_gia = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Tổng giá đơn hàng", default=0)
    so_don_hang = models.CharField(max_length=64, verbose_name="Số đơn hàng", unique=True)
    so_giao_dich = models.CharField(max_length=64, null=True, verbose_name="Số giao dịch")
    trang_thai_don_hang = models.SmallIntegerField(choices=trang_thai_choices, default=0, verbose_name="Trạng thái đơn hàng")
    phuong_thuc_thanh_toan = models.SmallIntegerField(choices=phuong_thuc_thanh_toan_choices, default=1, verbose_name="Phương thức thanh toán")
    thoi_gian_thanh_toan = models.DateTimeField(null=True, verbose_name="Thời gian thanh toán")
    nguoi_dung = models.ForeignKey(User, related_name='don_hangs_cua_nguoi_dung', on_delete=models.DO_NOTHING, db_constraint=False,
                                   verbose_name="Người dùng đặt hàng")

    class Meta:
        db_table = "luffy_donhang"
        verbose_name = "Ghi chép đơn hàng"
        verbose_name_plural = "Ghi chép đơn hàng"

    def __str__(self):
        return "%s - ¥%s" % (self.tieu_de, self.tong_gia)

    @property
    def khoahocs(self):
        danh_sach_du_lieu = []
        for item in self.chiTiet_donhang.all():
            danh_sach_du_lieu.append({
                "id": item.id,
                "ten_khoahoc": item.khoahoc.ten,
                "gia_thuc_te": item.gia_thuc_te,
            })

        return danh_sach_du_lieu


class ChiTietDonHang(BaseModel):
    """Chi tiết đơn hàng"""
    donhang = models.ForeignKey(DonHang, related_name='chiTiet_donhang', on_delete=models.CASCADE, db_constraint=False,
                                verbose_name="Đơn hàng")
    khoahoc = models.ForeignKey(KhoaHoc, related_name='donhang_cua_khoahoc', on_delete=models.CASCADE, db_constraint=False,
                                 verbose_name="Khóa học")
    gia = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="Giá gốc khóa học")
    gia_thuc_te = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="Giá thực tế khóa học")

    class Meta:
        db_table = "luffy_chitiet_donhang"
        verbose_name = "Chi tiết đơn hàng"
        verbose_name_plural = "Chi tiết đơn hàng"

    def __str__(self):
        return "%s của đơn hàng: %s" % (self.khoahoc.ten, self.donhang.so_don_hang)

3. Tập tin views.py của order: *****************************************************

from rest_framework.views import APIView
from rest_framework.response import Response

from . import serializers

# Cần đăng nhập mới có thể truy cập
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated
class ThanhToanAPIView(APIView):
    authentication_classes = [JSONWebTokenAuthentication]
    permission_classes = [IsAuthenticated]
    def post(self, yeu_cau, *args, **kwargs):
        bo_qua = serializers.DonHangModelSerializer(dữ_liệu=yeu_cau.data, context={'yeu_cau': yeu_cau})
        # Kiểm tra thông tin
        bo_qua.is_valid(raise_exception=True)
        # Lưu đơn hàng vào cơ sở dữ liệu
        bo_qua.save()
        # Trả về một liên kết thanh toán
        return Response(bo_qua.lien_ket_thanh_toan)


4. Tập tin serializers.py của order: *****************************************************    

import time
from rest_framework import serializers

from . import models
from khoahoc.models import KhoaHoc

from libs.iPay import alipay, alipay_gateway
from django.conf import settings

class DonHangModelSerializer(serializers.ModelSerializer):
    # Khóa chính của các sản phẩm: tạm định truyền nhiều khóa chính dưới dạng '1,2,3'
    khoa_chinh_san_pham = serializers.CharField(max_length=64)

    class Meta:
        model = models.DonHang
        fields = (
            'tieu_de',
            'tong_gia',
            'phuong_thuc_thanh_toan',
            'khoa_chinh_san_pham',
        )
        extra_kwargs = {
            'tong_gia': {
                'required': True
            }
        }

    # Hậu phương cần kiểm tra tất cả các khóa chính và tổng giá, kiểm tra giá (ngăn chặn việc bị sửa đổi trong quá trình truyền tải)
    def validate(self, du_lieu):
        khoa_chinh_san_pham = du_lieu.pop('khoa_chinh_san_pham')
        khoa_chinh_san_pham = [pk for pk in khoa_chinh_san_pham.split(',')]
        danh_sach_san_pham = []
        for pk in khoa_chinh_san_pham:
            try:
                obj = KhoaHoc.objects.get(pk=pk)
                danh_sach_san_pham.append(obj)
            except:
                raise serializers.ValidationError({'pk': 'Khóa chính khóa học không đúng'})

        tong_gia = 0
        for san_pham in danh_sach_san_pham:
            tong_gia += san_pham.gia

        # Tổng giá sản phẩm
        tong_gia_du_lieu = du_lieu.get('tong_gia')
        if tong_gia != tong_gia_du_lieu:
            raise serializers.ValidationError({'tong_gia': 'Giá bị sửa đổi một cách độc hại'})

        # Tạo số đơn hàng
        so_don_hang = self._tao_so_don_hang()
        # Tên đơn hàng
        tieu_de = du_lieu.get('tieu_de')

        # Tạo liên kết đơn hàng
        tham_so_don_hang = alipay.api_alipay_trade_page_pay(out_trade_no=so_don_hang,
                                                        total_amount=float(tong_gia_du_lieu),
                                                        subject=tieu_de,
                                                        return_url=settings.RETURN_URL,  # Giao diện callback đồng bộ phía trước
                                                        notify_url=settings.NOTIFY_URL  # Giao diện callback bất đồng bộ phía sau
                                                        )
        lien_ket_thanh_toan = alipay_gateway + tham_so_don_hang

        # Lưu liên kết thanh toán vào đối tượng bộ sưu tập
        self.lien_ket_thanh_toan = lien_ket_thanh_toan

        # Thêm các trường bổ sung vào dữ liệu được kiểm tra để hỗ trợ lưu trữ thông tin sản phẩm vào bảng chi tiết đơn hàng
        du_lieu['so_don_hang'] = so_don_hang
        # Lớp xem truyền tham số vào lớp bộ sưu tập
        du_lieu['nguoi_dung'] = self.context.get('yeu_cau').nguoi_dung

        # Lưu trữ tất cả các đối tượng sản phẩm vào dữ liệu được kiểm tra, hỗ trợ lưu trữ thông tin sản phẩm vào bảng chi tiết đơn hàng
        du_lieu['khoahocs'] = danh_sach_san_pham

        # Đại diện cho việc kiểm tra đã qua
        return du_lieu

    # Ghi đè phương thức create, hoàn thành lưu trữ bảng chi tiết đơn hàng
    def create(self, du_lieu_da_kiem_tra):
        khoahocs = du_lieu_da_kiem_tra.pop('khoahocs')

        donhang = super().create(du_lieu_da_kiem_tra)  # Bảng đơn hàng

        # Thao tác bảng mối quan hệ
        danh_sach_chi_tiet_donhang = []
        for khoahoc in khoahocs:
            danh_sach_chi_tiet_donhang.append(models.ChiTietDonHang(donhang=donhang, khoahoc=khoahoc, gia=khoahoc.gia, gia_thuc_te=khoahoc.gia))

        # Lưu trữ nhiều đối tượng chi tiết đơn hàng, lưu trữ hàng loạt vào cơ sở dữ liệu
        models.ChiTietDonHang.objects.bulk_create(danh_sach_chi_tiet_donhang)  # Bảng chi tiết đơn hàng

        return donhang

    def _tao_so_don_hang(self):
        so = '%s' % time.time()
        return so.replace('.', '', 1)

(3) Sự kiện Của Nhãn Mua Ngay Trong Phần Mềm Tiền Tiết

<template>
	...
	<span class="mua-ngay" @click="mua_khoa_hoc(khoa_hoc)">Mua ngay</span>
</template>
<script>
 	export default {
    	methods: {
            // Mua khóa học
            mua_khoa_hoc(khoa_hoc) {
                let token = this.$cookies.get('token');
                if (!token) {
                    this.$message({
                        message: "Vui lòng đăng nhập trước",
                        type: 'warning',
                        duration: 1000,
                    });
                    return false
                }
                // Đã đăng nhập
                this.$axios({
                    url: this.$settings.base_url + '/order/thanh-toan',
                    method: 'post',
                    data: {
                        tieu_de: khoa_hoc.ten,
                        tong_gia: khoa_hoc.gia,
                        khoa_chinh_san_pham: `${khoa_hoc.id}`
                    },
                    headers: {
                        authorization: `jwt ${token}`
                    }
                }).then(phản_hồi => {
                    // console.log(phản_hồi.data)
                    let lien_ket_thanh_toan = phản_hồi.data;
                    window.open(lien_ket_thanh_toan, '_self');
                }).catch(lỗi => {
                    console.log(lỗi.phản_hồi.data)
                })
            },
        }
    }
</script>

(4) Trang Thành Công Thanh Toán Trong Phần Mềm Tiền Tiết

// 1. Tập tin định tuyến:

const định_tuyến = [
    // ...
    {
        đường_dẫn: '/thanh-toan/thanh-cong',
        tên: 'thanh-toan-thanh-cong',
        thành_phần: ThanhCongThanhToan
    },
];

// 2. Tập tin ThanhCong.vue trong thư mục views:

<template>
    <div class="thanh-cong-thanh-toan">
        <div class="chính">
            <div class="tiêu_de">
                <div class="ghi_chú_thành_công">
                    <p class="ghi_chú">Bạn đã mua thành công 1 khóa học!</p>
                </div>
            </div>
            <div class="thông_tin_đơn_hàng">
                <p class="thông_tin"><b>Số đơn hàng:</b><span>{{ kết_qua.so_don_hang }}</span></p>
                <p class="thông_tin"><b>Số giao dịch:</b><span>{{ kết_qua.so_giao_dich }}</span></p>
                <p class="thông_tin"><b>Thời gian thanh toán:</b><span><span>{{ kết_qua.thời_gian }}</span></span></p>
            </div>
            <div class="học">
                <span>Bắt đầu học ngay</span>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        tên: "ThànhCông",
        dữ_liệu() {
            return {
                kết_qua: {},
            };
        },
        được_tạo() {
            // tham số đằng sau dấu hỏi trong url
            console.log(location.search);

            localStorage.this_nav = '/';
            if (!location.search.length) return;

            // phân tích các tham số url callback từ Alipay
            let tham_so = location.search.substring(1);
            let mục = tham_so.length ? tham_so.split('&') : [];
            // thêm từng mục vào đối tượng args
            for (let i = 0; i < mục.length; i++) {
                let k_v = mục[i].split('=');
                // giải mã, vì chuỗi truy vấn được mã hóa
                let k = decodeURIComponent(k_v[0]);
                let v = decodeURIComponent(k_v[1]);
                this.kết_qua[k] = v;
            }
            console.log(this.kết_qua);

            // chuyển kết quả thanh toán trên thanh địa chỉ sang phía sau
            this.$axios({
                url: this.$settings.base_url + '/order/thanh-cong' + location.search,
                phương_thức: 'patch',
                tiêu_đề: {
                    Authorization: token
                }
            }).then(phản_hồi => {
                console.log(phản_hồi.dữ_liệu);
            }).catch(() => {
                console.log('Đồng bộ hóa kết quả thanh toán thất bại');
            })
        },
        thành_phần: {
        }
    }
</script>

<style scoped>
    .chính {
        đệm: 60px 0;
        lề_mở: 0 tự_chọn;
        chiều_rộng: 1200px;
        nền: #fff;
    }

    .chính .tiêu_de {
        hiển_thị: flex;
        căn_bỏng: trung_tâm;
        đệm: 25px 40px;
        đường_viền_dưới: 1px sói_sắt #f2f2f2;
    }

    .chính .tiêu_de .ghi_chú_thành_công {
        hộp_sizing: border-box;
    }

    .tiêu_de hình_ảnh {
        căn_bỏng_trung: trung;
        chiều_rộng: 60px;
        chiều_cao: 60px;
        lề_phải: 40px;
    }

    .tiêu_de .ghi_chú_thành_công {
        hộp_sizing: border-box;
    }

    .tiêu_de .ghi_chú {
        kích_thước_chuỗi_ký_tự: 26px;
        màu: #000;
    }

    .thông_tin span {
        màu: #ec6730;
    }

    .thông_tin_đơn_hàng {
        đệm: 25px 48px;
        đệm_dưới: 15px;
        đường_viền_dưới: 1px sói_sắt #f2f2f2;
    }

    .thông_tin_đơn_hàng p {
        hiển_thị: flex;
        lề_dưới: 10px;
        kích_thước_chuỗi_ký_tự: 16px;
    }

    .thông_tin_đơn_hàng p b {
        độ_in đậm: 400;
        màu: #9d9d9d;
        không_giành_dòng: không_giành_dòng;
    }

    .học {
        đệm: 25px 40px;
    }

    .học span {
        hiển_thị: khối;
        chiều_rộng: 140px;
        chiều_cao: 42px;
        căn_bỏng: trung;
        dòng_cao: 42px;
        con_trỏ: chỉ_chuột;
        nền: #ffc210;
        góc_làm_tròn: 6px;
        kích_thước_chuỗi_ký_tự: 16px;
        màu: #fff;
    }
</style>

(5) Giao diện Callback Thành Công Thanh Toán Phía Sau

from . import models
from utils.logging import logger
from rest_framework.response import Response
class ThanhCongAPIView(APIView):
    # Không thể xác thực, callback bất đồng bộ từ Alipay truy cập giao diện này, chắc chắn không biết thông tin xác thực đăng nhập, số đơn hàng chính là thông tin liên kết quan quan trọng
    def váy(self, yêu_cầu, *args, **kwargs):
        # Mặc định là kiểu QueryDict, không thể sử dụng phương thức pop
        dữ_liệu_yêu_cầu = yêu_cầu.tham_số_truy_vấn.dict()
        # Phải lấy sign, sign_type (có xử lý an ninh bên trong) ra khỏi dữ liệu, so sánh sign với phần còn lại của dữ liệu
        dấu = dữ_liệu_yêu_cầu.pop('sign')
        kết_quả = alipay.xác_minh(dữ_liệu_yêu_cầu, dấu)
        if kết_quả:  # Callback đồng bộ: sửa trạng thái đơn hàng
            try:
                so_don_hang = dữ_liệu_yêu_cầu.get('so_don_hang')
                đơn_hàng = models.DonHang.objects.get(so_don_hang=so_don_hang)
                if đơn_hàng.trạng_thái_don_hàng != 1:
                    đơn_hàng.trạng_thái_don_hàng = 1
                    đơn_hàng.lưu()
            except:
                pass
            return APIResponse(0, 'Thanh toán thành công')
        return APIResponse(1, 'Thanh toán thất bại')

    # Callback bất đồng bộ từ Alipay
    def đăng(self, yêu_cầu, *args, **kwargs):
        # Mặc định là kiểu QueryDict, không thể sử dụng phương thức pop
        dữ_liệu_yêu_cầu = yêu_cầu.dữ_liệu.dict()
        # Phải lấy sign, sign_type (có xử lý an ninh bên trong) ra khỏi dữ liệu, so sánh sign với phần còn lại của dữ liệu
        dấu = dữ_liệu_yêu_cầu.pop('sign')
        kết_quả = alipay.xác_minh(dữ_liệu_yêu_cầu, dấu)
        # Callback bất đồng bộ: sửa trạng thái đơn hàng
        if kết_quả và dữ_liệu_yêu_cầu["trạng_thái_giao_dịch"] in ("TRADE_SUCCESS", "TRADE_FINISHED"):
            so_don_hang = dữ_liệu_yêu_cầu.get('so_don_hang')
            logger.critial('%s thanh toán thành công' % so_don_hang)
            try:
                đơn_hàng = models.DonHang.objects.get(so_don_hang=so_don_hang)
                if đơn_hàng.trạng_thái_don_hàng != 1:
                    đơn_hàng.trạng_thái_don_hàng = 1
                    đơn_hàng.lưu()
            except:
                pass
            # Alipay thông báo 8 lần bất đồng bộ, khi đơn hàng thành công phải trả về 'success'
            return Response('success')
        return Response('failed')

Thẻ: alipay Django RESTful API Thanh toán

Đăng vào ngày 18 tháng 8 lúc 00:20