Django REST framework+Vue to create a fresh supermarket (11) 12. Alipay sandbox environment configuration

Django REST framework+Vue to create a fresh supermarket (11) 12. Alipay sandbox environment configuration

12. Alipay sandbox environment configuration

12.1. Create an application

Enter the Ant Financial Open Platform (https://open.alipay.com/platform/home.htm), log in and enter the management center-->>application list

 Create application

 After the application is created, there will be an appid. Also need to submit information for review. Both WeChat Pay and Alipay Payment can be completed only when enterprise certification is required. Personal development is not possible, so we need to use

Sandbox environment, which allows us to develop and debug first when we don’t have these applications or the application review has not passed

12.2. Sandbox environment

Sandbox application address: https://openhome.alipay.com/platform/appDaily.htm?tab=info

(1) Public key and private key generation method

Address: https://docs.open.alipay.com/291/105971/

Choose winwods, if linux choose linux

Download the tool and generate it according to it.

 (2) Copy the generated public key and private key under trade/keys--->>>Rename--->>Add the following content to the first place

-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----

(3) Copy the Alipay public key to this path, and add the same at the beginning and end

12.3. Document description

We mainly use computer websites to pay, document address: https://docs.open.alipay.com/270

API interface used: unified acquiring and payment page interface

There is documentation inside

Several important parameters

sign

 You should read the instructions in the SDK that does not use the open platform: https://docs.open.alipay.com/291/106118

 Request parameter

Required few:

12.4. Writing code

Change the environment to local

First install a module

pip install pycryptodome

Create alipay.py in utils, the code is as follows:

# apps/utils.py

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


class AliPay(object):
    """
    Alipay payment interface
    """
    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
        #Private key
        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())
        #Public key
        self.alipay_public_key_path = alipay_public_key_path
        with open(self.alipay_public_key_path) as fp:
            self.alipay_public_key = RSA.import_key(fp.read())


        if debug is True:
            self.__gateway = "https://openapi.alipaydev.com/gateway.do"
        else:
            self.__gateway = "https://openapi.alipay.com/gateway.do"

    def direct_pay(self, subject, out_trade_no, total_amount, return_url=None, **kwargs):
        #Request parameters
        biz_content = {
            "subject": subject,
            "out_trade_no": out_trade_no,
            "total_amount": total_amount,
            "product_code": "FAST_INSTANT_TRADE_PAY",
            # "qr_pay_mode":4
        }
        #Allow more parameters to be passed and put in biz_content
        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):
        #build_body The format of the main production message
        #Public request parameters
        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):
        #signature
        data.pop("sign", None)
        # Sorted string
        unsigned_items = self.ordered_data(data)
        #Split together after sorting
        unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in unsigned_items)
        #Here to get the signed string
        sign = self.sign(unsigned_string.encode("utf-8"))
        #Processing the url
        quoted_string = "&".join("{0}={1}".format(k, quote_plus(v)) for k, v in unsigned_items)

        # Get the final order information string
        signed_string = quoted_string + "&sign=" + quote_plus(sign)
        return signed_string

    #Parameters must be sorted when passed in
    def ordered_data(self, data):
        complex_keys = []
        for key, value in data.items():
            if isinstance(value, dict):
                complex_keys.append(key)

        # Dump the dictionary type data
        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):
        # Start to calculate the signature
        key = self.app_private_key
        #Signed object
        signer = PKCS1_v1_5.new(key)
        #Generate signature
        signature = signer.sign(SHA256.new(unsigned_string))
        # base64 encoding, convert to unicode and remove the carriage return
        sign = encodebytes(signature).decode("utf8").replace("\n", "")
        return sign

    def _verify(self, raw_content, signature):
        # Start to calculate the signature
        key = self.alipay_public_key
        signer = PKCS1_v1_5.new(key)
        digest = SHA256.new()
        digest.update(raw_content.encode("utf8"))
        if signer.verify(digest, decodebytes(signature.encode("utf8"))):
            return True
        return False

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


if __name__ == "__main__":
    return_url = 'http://127.0.0.1:8000/?total_amount=100.00×tamp=2017-08-15+23%3A53%3A34&sign=e9E9UE0AxR84NK8TP1CicX6aZL8VQj68ylugWGHnM79zA7BKTIuxxkf%2FvhdDYz4XOLzNf9pTJxTDt8tTAAx%2FfUAJln4WAeZbacf1Gp4IzodcqU%2FsIc4z93xlfIZ7OLBoWW0kpKQ8AdOxrWBMXZck%2F1cffy4Ya2dWOYM6Pcdpd94CLNRPlH6kFsMCJCbhqvyJTflxdpVQ9kpH%2B%2Fhpqrqvm678vLwM%2B29LgqsLq0lojFWLe5ZGS1iFBdKiQI6wZiisBff%2BdAKT9Wcao3XeBUGigzUmVyEoVIcWJBH0Q8KTwz6IRC0S74FtfDWTafplUHlL%2Fnf6j %2FQd1y6Wcr2A5Kl6BQ%3D%3D&trade_no=2017081521001004340200204115&sign_type=RSA2&auth_app_id=2016080600180695&charset=utf-8&seller_id=2088102170208070&method=alipay.185
    o = urlparse(return_url)
    query = parse_qs(o.query)
    processed_query = {}
    ali_sign = query.pop("sign")[0]


# Test case
    alipay = AliPay(
        # Appid value in the sandbox
        appid="2016091500517456",
        #notify_url is an asynchronous url
        app_notify_url="http://127.0.0.1:8000/",
        # Our own merchant's key
        app_private_key_path="../trade/keys/private_2048.txt",
        # Alipay's public key
        alipay_public_key_path="../trade/keys/alipay_key_2048.txt", # Alipay’s public key, to verify the use of Alipay’s return message, not your own public key,
        # Use the url of the sandbox when debug is true. If it is not the url of the official environment
        debug=True, # default False,
        return_url="http://127.0.0.1:8000/alipay/return/"
    )

    for key, value in query.items():
        processed_query[key] = value[0]
    # print (alipay.verify(processed_query, ali_sign))

    # Direct payment: Generate the requested string.
    url = alipay.direct_pay(
        # Order title
        subject="test order derek",
        # Order number generated by our merchant
        out_trade_no="20180417derek",
        # order amount
        total_amount=100,
        #The page redirected to after successful payment, return_url synchronized url
        # return_url="http://127.0.0.1:8000/"
    )
    # Take the generated request string to our url for splicing
    re_url = "https://openapi.alipaydev.com/gateway.do?{data}".format(data=url)

    print(re_url)

Run alipay.py, a payment link url will be generated, click to jump to the payment page

 Click "Login Account Payment" and pay with sandbox account

 Enter the account password and payment password, the payment is successful

12.5. Django integrates Alipay notify_url and return_url

(1) Configure url

# Configure the url of Alipay payment related interface
path('alipay/return/', AlipayView.as_view())

(2) Alipay.py

Change both return_url and notify_url to the address of the remote server

return_url="http://47.93.198.159:8000/alipay/return/"

app_notify_url="http://47.93.198.159:8000/alipay/return/"
# apps/utils.py

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


class AliPay(object):
    """
    Alipay payment interface
    """
    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
        #Private key
        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())
        #Public key
        self.alipay_public_key_path = alipay_public_key_path
        with open(self.alipay_public_key_path) as fp:
            self.alipay_public_key = RSA.import_key(fp.read())


        if debug is True:
            self.__gateway = "https://openapi.alipaydev.com/gateway.do"
        else:
            self.__gateway = "https://openapi.alipay.com/gateway.do"

    def direct_pay(self, subject, out_trade_no, total_amount, return_url=None, **kwargs):
        #Request parameters
        biz_content = {
            "subject": subject,
            "out_trade_no": out_trade_no,
            "total_amount": total_amount,
            "product_code": "FAST_INSTANT_TRADE_PAY",
            # "qr_pay_mode":4
        }
        #Allow more parameters to be passed and put in biz_content
        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):
        #build_body The format of the main production message
        #Public request parameters
        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):
        #signature
        data.pop("sign", None)
        # Sorted string
        unsigned_items = self.ordered_data(data)
        #Split together after sorting
        unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in unsigned_items)
        #Here to get the signed string
        sign = self.sign(unsigned_string.encode("utf-8"))
        #Processing the url
        quoted_string = "&".join("{0}={1}".format(k, quote_plus(v)) for k, v in unsigned_items)

        # Get the final order information string
        signed_string = quoted_string + "&sign=" + quote_plus(sign)
        return signed_string

    #Parameters must be sorted when passed in
    def ordered_data(self, data):
        complex_keys = []
        for key, value in data.items():
            if isinstance(value, dict):
                complex_keys.append(key)

        # Dump the dictionary type data
        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):
        # Start to calculate the signature
        key = self.app_private_key
        #Signed object
        signer = PKCS1_v1_5.new(key)
        #Generate signature
        signature = signer.sign(SHA256.new(unsigned_string))
        # base64 encoding, convert to unicode and remove the carriage return
        sign = encodebytes(signature).decode("utf8").replace("\n", "")
        return sign

    def _verify(self, raw_content, signature):
        # Start to calculate the signature
        key = self.alipay_public_key
        signer = PKCS1_v1_5.new(key)
        digest = SHA256.new()
        digest.update(raw_content.encode("utf8"))
        if signer.verify(digest, decodebytes(signature.encode("utf8"))):
            return True
        return False

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


if __name__ == "__main__":
    return_url = 'http://127.0.0.1:8000/?total_amount=100.00×tamp=2017-08-15+23%3A53%3A34&sign=e9E9UE0AxR84NK8TP1CicX6aZL8VQj68ylugWGHnM79zA7BKTIuxxkf%2FvhdDYz4XOLzNf9pTJxTDt8tTAAx%2FfUAJln4WAeZbacf1Gp4IzodcqU%2FsIc4z93xlfIZ7OLBoWW0kpKQ8AdOxrWBMXZck%2F1cffy4Ya2dWOYM6Pcdpd94CLNRPlH6kFsMCJCbhqvyJTflxdpVQ9kpH%2B%2Fhpqrqvm678vLwM%2B29LgqsLq0lojFWLe5ZGS1iFBdKiQI6wZiisBff%2BdAKT9Wcao3XeBUGigzUmVyEoVIcWJBH0Q8KTwz6IRC0S74FtfDWTafplUHlL%2Fnf6j %2FQd1y6Wcr2A5Kl6BQ%3D%3D&trade_no=2017081521001004340200204115&sign_type=RSA2&auth_app_id=2016080600180695&charset=utf-8&seller_id=2088102170208070&method=alipay.185
    o = urlparse(return_url)
    query = parse_qs(o.query)
    processed_query = {}
    ali_sign = query.pop("sign")[0]


# Test case
    alipay = AliPay(
        # Appid value in the sandbox
        appid="2016091500517456",
        #notify_url is an asynchronous url
        app_notify_url="http://47.93.198.159:8000/alipay/return/",
        # Our own merchant's key
        app_private_key_path="../trade/keys/private_2048.txt",
        # Alipay's public key
        alipay_public_key_path="../trade/keys/alipay_key_2048.txt", # Alipay’s public key, to verify the use of Alipay’s return message, not your own public key,
        # Use the url of the sandbox when debug is true. If it is not the url of the official environment
        debug=True, # default False,
        return_url="http://47.93.198.159:8000/alipay/return/"
    )

    for key, value in query.items():
        processed_query[key] = value[0]
    # print (alipay.verify(processed_query, ali_sign))

    # Direct payment: Generate the requested string.
    url = alipay.direct_pay(
        # Order title
        subject="test order derek",
        # Order number generated by our merchant
        out_trade_no="20180417derek2",
        # order amount
        total_amount=100,
        #The page redirected to after successful payment, return_url synchronized url
        return_url="http://47.93.198.159:8000/alipay/return/"
    )
    # Take the generated request string to our url for splicing
    re_url = "https://openapi.alipaydev.com/gateway.do?{data}".format(data=url)

    print(re_url)

(3) settings.py

 Configure the public key and private key path in settings

# Alipay related key
private_key_path = os.path.join(BASE_DIR,'apps/trade/keys/private_2048.txt')
ali_pub_key_path = os.path.join(BASE_DIR,'apps/trade/keys/alipay_key_2048.txt')

(4) trade/views.py

from datetime import datetime
from utils.alipay import AliPay
from rest_framework.views import APIView
from MxShop.settings import ali_pub_key_path, private_key_path
from rest_framework.response import Response

class AlipayView(APIView):
    def get(self, request):
        """
        Processing Alipay's return_url return
        """
        processed_dict = {}
        # 1. Get parameters in GET
        for key, value in request.GET.items():
            processed_dict[key] = value
        # 2. Take out the sign
        sign = processed_dict.pop("sign", None)

        # 3. Generate ALipay object
        alipay = AliPay(
            appid="2016091500517456",
            app_notify_url="http://47.93.198.159:8000/alipay/return/",
            app_private_key_path=private_key_path,
            alipay_public_key_path=ali_pub_key_path, # Alipay’s public key, to verify the use of Alipay’s return message, not your own public key,
            debug=True, # default False,
            return_url="http://47.93.198.159:8000/alipay/return/"
        )

        verify_re = alipay.verify(processed_dict, sign)

        # You can do nothing here. Because it doesn't matter whether the return url is sent or not. Notify url will modify the order status.
        if verify_re is True:
            order_sn = processed_dict.get('out_trade_no', None)
            trade_no = processed_dict.get('trade_no', None)
            trade_status = processed_dict.get('trade_status', None)

            existed_orders = OrderInfo.objects.filter(order_sn=order_sn)
            for existed_order in existed_orders:
                existed_order.pay_status = trade_status
                existed_order.trade_no = trade_no
                existed_order.pay_time = datetime.now()
                existed_order.save()


    def post(self, request):
        """
        Process Alipay's notify_url
        """
        #Store all the data in the post
        processed_dict = {}
        #Remove the data in the post
        for key, value in request.POST.items():
            processed_dict[key] = value
        #Put signpop off, the document has instructions
        sign = processed_dict.pop("sign", None)

        #Generate an Alipay object
        alipay = AliPay(
            appid="2016091500517456",
            app_notify_url="http://47.93.198.159:8000/alipay/return/",
            app_private_key_path=private_key_path,
            alipay_public_key_path=ali_pub_key_path, # Alipay’s public key, to verify the use of Alipay’s return message, not your own public key,
            debug=True, # default False,
            return_url="http://47.93.198.159:8000/alipay/return/"
        )

        #authenticating
        verify_re = alipay.verify(processed_dict, sign)

        # If the verification is successful
        if verify_re is True:
            #商户网站Unique order number
            order_sn = processed_dict.get('out_trade_no', None)
            #Alipay system transaction serial number
            trade_no = processed_dict.get('trade_no', None)
            #trading status
            trade_status = processed_dict.get('trade_status', None)

            # Query the order record in the database
            existed_orders = OrderInfo.objects.filter(order_sn=order_sn)
            for existed_order in existed_orders:
                # Order item
                order_goods = existed_order.goods.all()
                # Commodity sales increase in order value
                for order_good in order_goods:
                    goods = order_good.goods
                    goods.sold_num += order_good.goods_num
                    goods.save()

                # Update order status
                existed_order.pay_status = trade_status
                existed_order.trade_no = trade_no
                existed_order.pay_time = datetime.now()
                existed_order.save()
            #Need to return a'success' to Alipay, if not returned, Alipay will always send a message that the order payment is successful
            return Response("success")

(5) trade/serializers.py

When an order is created, a payment url is generated. This logic is added to both OderSerializer and OrderDetailSerializer

 #Payment order url
    alipay_url = serializers.SerializerMethodField(read_only=True)

    def get_alipay_url(self, obj):
        alipay = AliPay(
            appid="2016091500517456",
            app_notify_url="http://47.93.198.159:8000/alipay/return/",
            app_private_key_path=private_key_path,
            alipay_public_key_path=ali_pub_key_path, # Alipay’s public key, to verify the use of Alipay’s return message, not your own public key,
            debug=True, # default False,
            return_url="http://47.93.198.159:8000/alipay/return/"
        )

        url = alipay.direct_pay(
            subject=obj.order_sn,
            out_trade_no=obj.order_sn,
            total_amount=obj.order_mount,
        )
        re_url = "https://openapi.alipaydev.com/gateway.do?{data}".format(data=url)

        return re_url
# trade/serializer.py
__author__ ='derek'

import time

from .models import ShoppingCart
from rest_framework import serializers
from goods.models import Goods
from goods.serializers import GoodsSerializer
from .models import OrderInfo,OrderGoods
from MxShop.settings import ali_pub_key_path, private_key_path
from utils.alipay import AliPay

class ShopCartDetailSerializer(serializers.ModelSerializer):
    '''
    Shopping cart product detail information
    '''
    # One shopping cart corresponds to one product
    goods = GoodsSerializer(many=False, read_only=True)
    class Meta:
        model = ShoppingCart
        fields = ("goods", "nums")


class ShopCartSerializer(serializers.Serializer):
    #Get the currently logged-in user
    user = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )
    nums = serializers.IntegerField(required=True, label="quantity",min_value=1,
                                    error_messages={
                                        "min_value":"The quantity of goods cannot be less than one",
                                        "required": "Please select the purchase quantity"
                                    })
    #Here is the inheritance of Serializer, you must specify the queryset object, if you inherit ModelSerializer, you do not need to specify
    #goods is a foreign key, you can get all the values ​​in the goods object by this method
    goods = serializers.PrimaryKeyRelatedField(required=True, queryset=Goods.objects.all())

    #Inherited Serializer has no save function, you must write a create method
    def create(self, validated_data):
        # validated_data is the processed data
        #Get current user
        # view: self.request.user; serizlizer: self.context["request"].user
        user = self.context["request"].user
        nums = validated_data["nums"]
        goods = validated_data["goods"]

        existed = ShoppingCart.objects.filter(user=user, goods=goods)
        #If there is a record in the shopping cart, the quantity is +1
        #If the shopping cart has no record, create it
        if existed:
            existed = existed[0]
            existed.nums += nums
            existed.save()
        else:
            #Add to Cart
            existed = ShoppingCart.objects.create(**validated_data)

        return existed

    def update(self, instance, validated_data):
        # Modify the quantity of goods
        instance.nums = validated_data["nums"]
        instance.save()
        return instance


#Items in the order
class OrderGoodsSerialzier(serializers.ModelSerializer):
    goods = GoodsSerializer(many=False)
    class Meta:
        model = OrderGoods
        fields = "__all__"

#Order product information
# The goods field needs to nest an OrderGoodsSerializer
class OrderDetailSerializer(serializers.ModelSerializer):
    goods = OrderGoodsSerialzier(many=True)
    # Payment order url
    alipay_url = serializers.SerializerMethodField(read_only=True)

    def get_alipay_url(self, obj):
        alipay = AliPay(
            appid="2016091500517456",
            app_notify_url="http://47.93.198.159:8000/alipay/return/",
            app_private_key_path=private_key_path,
            alipay_public_key_path=ali_pub_key_path, # Alipay’s public key, to verify the use of Alipay’s return message, not your own public key,
            debug=True, # default False,
            return_url="http://47.93.198.159:8000/alipay/return/"
        )

        url = alipay.direct_pay(
            subject=obj.order_sn,
            out_trade_no=obj.order_sn,
            total_amount=obj.order_mount,
        )
        re_url = "https://openapi.alipaydev.com/gateway.do?{data}".format(data=url)

        return re_url
    class Meta:
        model = OrderInfo
        fields = "__all__"

class OrderSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )
    #When generating the order, these do not need to post
    pay_status = serializers.CharField(read_only=True)
    trade_no = serializers.CharField(read_only=True)
    order_sn = serializers.CharField(read_only=True)
    pay_time = serializers.DateTimeField(read_only=True)
    nonce_str = serializers.CharField(read_only=True)
    pay_type = serializers.CharField(read_only=True)
    #Payment order url
    alipay_url = serializers.SerializerMethodField(read_only=True)

    def get_alipay_url(self, obj):
        alipay = AliPay(
            appid="2016091500517456",
            app_notify_url="http://47.93.198.159:8000/alipay/return/",
            app_private_key_path=private_key_path,
            alipay_public_key_path=ali_pub_key_path, # Alipay’s public key, to verify the use of Alipay’s return message, not your own public key,
            debug=True, # default False,
            return_url="http://47.93.198.159:8000/alipay/return/"
        )

        url = alipay.direct_pay(
            subject=obj.order_sn,
            out_trade_no=obj.order_sn,
            total_amount=obj.order_mount,
        )
        re_url = "https://openapi.alipaydev.com/gateway.do?{data}".format(data=url)

        return re_url


    def generate_order_sn(self):
        #Generate order number
        # Current time + userid + random number
        from random import Random
        random_ins = Random()
        order_sn = "{time_str}{userid}{ranstr}".format(time_str=time.strftime("%Y%m%d%H%M%S"),
                                                       userid=self.context["request"].user.id,
                                                       ranstr=random_ins.randint(10, 99))
        return order_sn

    def validate(self, attrs):
        #validate add order_sn, and then you can save in the view
        attrs["order_sn"] = self.generate_order_sn()
        return attrs

    class Meta:
        model = OrderInfo
        fields = "__all__"

(6) Test code

The local modification must be uploaded to the server, because we need to debug the code on the server

Change local_host in api.js in vue project to server ip

let local_host ='http://47.93.198.159:8000';

Start running the project in phcharm

Browser access address: http://47.93.198.159:8000/orders/

Create an order

Details of the generated order

12.6.vue static files are placed in django

Vue has two development modes

  • build is used to generate static files 
  • dev

(1) Operation

cnpm run build

The generated static files are under the dist directory

(2) Copy index.html to the templates directory

(3) Create static directory in django

  • Put index.entry.js into the static directory of django
  • Copy the two folders under dist/static to the django static directory

(4) settings to set the static file path

STATIC_URL ='/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)

 (5) Modify the static file path in index.html

<script type="text/javascript" src="/static/index.entry.js"></script></body>

(6) Configure the url of the index

from django.views.generic import TemplateView

urlpatterns = [
    # Home
    path('index/', TemplateView.as_view(template_name='index.html'),name='index')
]

 (7) Configure the return address for successful payment

trade/views.py

 response = redirect("/index/#/app/home/member/order")
            return response

        else:
            response = redirect("index")
            return response
# trade/views.py

from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated
from utils.permissions import IsOwnerOrReadOnly
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.authentication import SessionAuthentication
from .serializers import ShopCartSerializer,ShopCartDetailSerializer,OrderDetailSerializer,OrderGoodsSerialzier,OrderSerializer
from .models import ShoppingCart,OrderGoods,OrderInfo
from rest_framework import mixins
from django.shortcuts import render, redirect


class ShoppingCartViewset(viewsets.ModelViewSet):
    """
    Shopping cart function
    list:
        Get shopping cart details
    create:
        add to Shopping Cart
    delete:
        Delete shopping record
    """
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
    serializer_class = ShopCartSerializer
    #Product id
    lookup_field = "goods_id"

    def get_serializer_class(self):
        if self.action =='list':
            return ShopCartDetailSerializer
        else:
            return ShopCartSerializer

    #Get shopping cart list
    def get_queryset(self):
        return ShoppingCart.objects.filter(user=self.request.user)


class OrderViewset(mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.CreateModelMixin, mixins.DestroyModelMixin,
                   viewsets.GenericViewSet):
    """
    Order management
    list:
        Get personal order
    delete:
        Delete order
    create:
        New order
    """
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
    serializer_class = OrderSerializer
    #Dynamic configuration serializer
    def get_serializer_class(self):
        if self.action == "retrieve":
            return OrderDetailSerializer
        return OrderSerializer
    #Get order list
    def get_queryset(self):
        return OrderInfo.objects.filter(user=self.request.user)

    #There are two more steps before the order is submitted and saved, so here is the custom perform_create method
    #1. Save the goods in the shopping cart to OrderGoods
    #2. Situation shopping cart
    def perform_create(self, serializer):
        order = serializer.save()
        # Get all items in the shopping cart
        shop_carts = ShoppingCart.objects.filter(user=self.request.user)
        for shop_cart in shop_carts:
            order_goods = OrderGoods()
            order_goods.goods = shop_cart.goods
            order_goods.goods_num = shop_cart.nums
            order_goods.order = order
            order_goods.save()
            #Empty shopping cart
            shop_cart.delete()
        return order

from datetime import datetime
from utils.alipay import AliPay
from rest_framework.views import APIView
from MxShop.settings import ali_pub_key_path, private_key_path
from rest_framework.response import Response

class AlipayView(APIView):
    def get(self, request):
        """
        Processing Alipay's return_url return
        """
        processed_dict = {}
        # 1. Get parameters in GET
        for key, value in request.GET.items():
            processed_dict[key] = value
        # 2. Take out the sign
        sign = processed_dict.pop("sign", None)

        # 3. Generate ALipay object
        alipay = AliPay(
            appid="2016091500517456",
            app_notify_url="http://47.93.198.159:8000/alipay/return/",
            app_private_key_path=private_key_path,
            alipay_public_key_path=ali_pub_key_path, # Alipay’s public key, to verify the use of Alipay’s return message, not your own public key,
            debug=True, # default False,
            return_url="http://47.93.198.159:8000/alipay/return/"
        )

        verify_re = alipay.verify(processed_dict, sign)

        # You can do nothing here. Because it doesn't matter whether the return url is sent or not. Notify url will modify the order status.
        if verify_re is True:
            order_sn = processed_dict.get('out_trade_no', None)
            trade_no = processed_dict.get('trade_no', None)
            trade_status = processed_dict.get('trade_status', None)

            existed_orders = OrderInfo.objects.filter(order_sn=order_sn)
            for existed_order in existed_orders:
                existed_order.pay_status = trade_status
                existed_order.trade_no = trade_no
                existed_order.pay_time = datetime.now()
                existed_order.save()

            response = redirect("/index/#/app/home/member/order")
            return response

        else:
            response = redirect("index")
            return response

    def post(self, request):
        """
        Process Alipay's notify_url
        """
        #Store all the data in the post
        processed_dict = {}
        #Remove the data in the post
        for key, value in request.POST.items():
            processed_dict[key] = value
        #Put signpop off, the document has instructions
        sign = processed_dict.pop("sign", None)

        #Generate an Alipay object
        alipay = AliPay(
            appid="2016091500517456",
            app_notify_url="http://47.93.198.159:8000/alipay/return/",
            app_private_key_path=private_key_path,
            alipay_public_key_path=ali_pub_key_path, # Alipay’s public key, to verify the use of Alipay’s return message, not your own public key,
            debug=True, # default False,
            return_url="http://47.93.198.159:8000/alipay/return/"
        )

        #authenticating
        verify_re = alipay.verify(processed_dict, sign)

        # If the verification is successful
        if verify_re is True:
            #商户网站Unique order number
            order_sn = processed_dict.get('out_trade_no', None)
            #Alipay system transaction serial number
            trade_no = processed_dict.get('trade_no', None)
            #trading status
            trade_status = processed_dict.get('trade_status', None)

            # Query the order record in the database
            existed_orders = OrderInfo.objects.filter(order_sn=order_sn)
            for existed_order in existed_orders:
                # Order item
                order_goods = existed_order.goods.all()
                # Commodity sales increase in order value
                for order_good in order_goods:
                    goods = order_good.goods
                    goods.sold_num += order_good.goods_num
                    goods.save()

                # Update order status
                existed_order.pay_status = trade_status
                existed_order.trade_no = trade_no
                existed_order.pay_time = datetime.now()
                existed_order.save()
            #Need to return a'success' to Alipay, if not returned, Alipay will always send a message that the order payment is successful
            return Response("success")

Now you can directly access through index: http://47.93.198.159:8000/index/#/app/home/index

Add goods to the shopping cart-->>Go to checkout-->>Generate order-->>Go to the payment page

Reference: https://cloud.tencent.com/developer/article/1103700 Django REST framework+Vue to create a fresh supermarket (11) 12. Alipay sandbox environment configuration-cloud + community-Tencent Cloud