zoukankan      html  css  js  c++  java
  • Django网站项目线下二维码扫描支付

    1、前期工作

    •  设置密钥的方式需要下载以支付宝生成密钥工具:工具包的地址及提取码:

      链接:https://pan.baidu.com/s/1AXK3s4SBowNp1K47Qc1QHw
      提取码:2u04

      运行.exe文件

      

    •  复制my_private_key.pem的内容,并且保证里面不含有空格和换行等字符;将复制的内容再填入第一张图中的RSA2密钥的设置中,会生成支付宝公钥并复制存放在alipay_public_key.pem文件中

    python SDK工具包下载(坑的不得了)

    • 在下载的过程中,支付宝官方提供了SDK工具包,在cmd命令行中运行:pip install alipay-sdk-pythoon。如果在下载的过程中没有出现错误,那你就是幸运儿;如果你报错了,那么恭喜你已经入坑了。别急,我既然这么说了,就有帮你解决问题的能力。

    在你下载的过程中肯定会遇到上述这样的情况,下载sdk的时候,需要上面红框内的三个依赖包,第一个和第二个你有可能自己去pip下载,或者他帮你已经下载好了,但是第三个包好像是下载不了,经过我大量的搜索,好像是下载另外一个类似于这样的包,这个包是他的延申——pycryptodome。所以你得去pip install pycryptodome了。但是在你下载这个包的时候,还是会报上面一样的错误。所以支付宝开发者平台给我们提供的SDK包是无法下载的。

    • 问题解决:经我翻天覆地的搜索,无意中看到了另外一种下载方式,这一种方式就是使用了pycryptodome这个依赖包,那么你就可以直接下载了:

    pip install python-alipay-sdk

    这种下载就会没错了。

    创建项目app

    • 进入项目目录下运行:python manage.py startapp payment
    • 然后再创建下面图一样的目录(只需要看payment app目录即可,文件颜色不用管)将之前保存的私钥公钥文件都粘贴到key的目录下

    • 这里就省略主url配置了,直接进入子url配置了
      • urls.py文件
    from django.urls import path
    from . import views
    
    app_name = '[payment]'
    urlpatterns = [
        path("alipay/", views.AliPayView.as_view(), name="alipay"),   # 支付宝支付
        path("check_pay/", views.CheckPayView.as_view(), name="check_pay"),   # 验证支付是否完成
    ]
    • 视图文件就很重头戏了
      • 分别创建这两个类了,另外在类的外部先定义好Alipay的对象。相信大家已经看过很多Alipay对象的创建了,他们初始化对象的参数是不一样的,因为他们是没有下载SDK工具包,所以应该都是去github上复制了一份别人封装的alipay的工具包,所以在使用对象调用方法是有些是不一样的。如果你下载了SDK工具包,按照我的步骤就不会错的。还有不能一味的跟着别人的代码敲,多看看里面的源码以及他的实现方式。废话不多说,上代码了(这里我一部分一部分写,这样有助于理解,也让自己增强记忆,但都是同一个views.py文件中)P
      • 第一步就是初始化我们的Alipay类的对象,首先先看下Alipay类的源码,他是继承了BasePay类,所以直接看BasePay类的源码,我这里直接去当前使用并且中的地方。方式:AliPay——>BaseAliPay——>查看他的__init__初始化方法,主要看我添加注释的地方,似乎不是加载应用私钥文件和支付宝公钥文件,最后一句是调用了加载这两种文件的方法——>_load_key方法,里面的注释很重要,这里不复制,主要讲述的内容是我们需要pem文件格式的内容,而在文件头和文件尾都需要添加----- 描述性语言 -----。浏览_load_key方法的时候就会知道为什么需要pem文件和文件头和文件尾的样式。然后在读取文件时也需要像下面这样读取,当然如果你能保证获取的内容相同,读取文件的方式可以不一致。
    def __init__(
            self,
            appid,
            app_notify_url,
            app_private_key_string=None,    
            alipay_public_key_string=None,  
            sign_type="RSA2",
            debug=False
        ):
            """
            初始化:
            alipay = AliPay(
              appid="",
              app_notify_url="http://example.com",
              sign_type="RSA2"
            )
            """
            self._appid = str(appid)
            self._app_notify_url = app_notify_url
    
            #  就是my_private_key.pem里面的内容
            self._app_private_key_string = app_private_key_string
    
            #  就是alipay_public_key.pem里面的内容
            self._alipay_public_key_string = alipay_public_key_string
    
            self._app_private_key = None
            self._alipay_public_key = None
            if sign_type not in ("RSA", "RSA2"):
                raise AliPayException(None, "Unsupported sign type {}".format(sign_type))
            self._sign_type = sign_type
    
            if debug is True:
                self._gateway = "https://openapi.alipaydev.com/gateway.do"
            else:
                self._gateway = "https://openapi.alipay.com/gateway.do"
    
            # load key file immediately
    
            #  这里很关键,也是重点
            self._load_key()
    AliPay初始化方法__init__
    from alipay import AliPay
    
    my_private_key = ""
    alipay_public_key = ""
    with open("./payment/key/my_private_key.pem") as f1:
        for read in f1.readlines():
            my_private_key += read
    
    with open("./payment/key/alipay_public_key.pem") as f2:
        for read in f2.readlines():
            alipay_public_key += read
    alipay = AliPay(appid='2016102100732430',
                    app_notify_url='http://127.0.0.1:8000/payment/check_pay/',
                    app_private_key_string=my_private_key,
                    alipay_public_key_string=alipay_public_key,
                    debug=True)
      • 这个时候我们可以在前端发出一个请求,像发出类似支付这样的请求。前端拿到这样的地址,做一个重定向。
    class AliPayView(ListAPIView):
        # 这里只是定义一个全局的订单号
        order_id = None
    
        def get(self, request):
            """
            请求获取支付宝的支付二维码
            :param request: 获取的请求
            :return: 含有支付二维码的请求地址
            """
            all_price = request.GET.get("all_price")
            AliPayView.order_id = request.GET.get("order_id")
    
            params = alipay.api_alipay_trade_page_pay(
                subject="商品购买",        # 收费的名称
                out_trade_no=str(uuid.uuid4()),   #商户的订单号,唯一,使用uuid比较方便
                total_amount=all_price,      # 从前端获取的价格
                # 这个很关键,这里是支付的时候需要验证一个请求的地址
                return_url="http://127.0.0.1:8000/payment/check_pay/",    
            )
            # 支付宝网关的地址:因为是debug=False所以是沙箱的地址
            url = alipay._gateway + "?" + params
    
            return Response(data={"url": url})
      • 当我们用沙箱支付宝扫码并且支付成功时,会像服务器发出上面return_url地址的get请求,并且他会携带上述的params的参数,而且参数中会有sign的标识,需要使用AliPay对象调用签名验证的方法verify,他的返回值是boolean值
    class CheckPayView(APIView):
    
        def get(self, request):
            """
            验证用户是否支付成功,支付成功就需要修改订单的状态,
            :param request: 获取的请求
            :return: 重定向到订单页面
            """
            params = request.GET.dict()
            sign = params.pop("sign")
            if alipay.verify(params, sign):
                order = Orders.objects.get(pk=AliPayView.order_id)
                order.status = 2
                order.save()
            return redirect(reverse("operations:order"))
      • 这样views.py文件已经写完
  • 相关阅读:
    UVa 12174 (滑动窗口) Shuffle
    UVa 1607 (二分) Gates
    CodeForces ZeptoLab Code Rush 2015
    HDU 1525 (博弈) Euclid's Game
    HDU 2147 (博弈) kiki's game
    UVa 11093 Just Finish it up
    UVa 10954 (Huffman 优先队列) Add All
    CodeForces Round #298 Div.2
    UVa 12627 (递归 计数 找规律) Erratic Expansion
    UVa 714 (二分) Copying Books
  • 原文地址:https://www.cnblogs.com/aitiknowledge/p/12699694.html
Copyright © 2011-2022 走看看