• Django中对接第三方支付(支付宝)实现支付的流程


    1. 业务逻辑
    准备

      1. 使用沙箱提供的商家环境

        沙箱环境:是支付宝提供给开发者的模拟支付的环境

        沙箱应用:https://docs.open.alipay.com/200/105311

        沙箱账号:https://openhome.alipay.com/platform/appDaily.htm?tab=account

     支付宝开发者文档:

        文档主页:https://openhome.alipay.com/developmentDocument.htm

        产品介绍:https://docs.open.alipay.com/270

        快速接入:https://docs.open.alipay.com/270/105899/

        SDK:https://docs.open.alipay.com/270/106291/

          python对接支付宝SDK:https://github.com/fzlee/alipay/blob/master/README.zh-hans.m

        API列表:https://docs.open.alipay.com/270/105900/
      2.. 生成密钥对
      3. 将公钥加到商品环境中
      4. 将Alipay提供的公钥加入项目中
        支付功能
      5. 根据order_id查询订单对象
      6. 创建alipay对象
      7. 调用方法,生成url
      8. 返回url
        保存支付状态
      9. 根据返回的url请求支付宝
      10. 支付成功后返回商家回调页面--------->会传回很多Alipay传回来的参数,很多明文,防止别人攻击
      11. 返回商家的同时请求后台服务器------>发送这些参数给后台
      12. 接收参数并且验证,成功则创建订单支付对象返回订单号,否则提示支付失败

    2.安装包

    pip install python-alipay-sdk --upgrade

    3.新建一个payments的app应用

    python ../../manage.py startapp payments

    4.定义一个模型类,继承自BaseModel(创建时间与修改时间)

     class Payment(BaseModel):
            """
            支付信息
            """
            order = models.ForeignKey(
                OrderInfo, on_delete=models.CASCADE, verbose_name='订单')
            trade_id = models.CharField(
                max_length=100, verbose_name="支付流水号")
    
        class Meta:
            db_table = 'tb_payment'
            verbose_name = '支付信息'
            verbose_name_plural = verbose_name

    5.配置密钥

      5.1.登录沙箱

        在payments应用中新建keys目录,用来保存秘钥文件。

         将应用私钥文件app_private_key.pem复制到payment/keys目录下。

      5.1.1生成应用的私钥和公钥 

    openssl
    OpenSSL> genrsa -out app_private_key.pem 2048  # 私钥RSA2
    OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem # 导出公钥
    
    OpenSSL> exit

      5.2 保存应用私钥文件

      5.3 查看公钥

    cat app_publict_key.pem
    # 将公钥内容复制给支付宝沙箱的<应用私钥>,得到支付宝的<支付宝公钥>

      5.4 保存支付宝公钥

      在payments/keys目录下新建alipay_public_key.pem文件,用于保存支付宝的公钥文件。

      将支付宝的公钥内容复制到alipay_public_key.pem文件中

    6.配置路由

    GET /orders/(?P<order_id>d+)/payment/

    7.在配置文件中配置ailipay的信息

     # 支付宝支付的配置
    ALIPAY_APPID = 'xxxxxxxxxxxxx'
    ALIPAY_PRIVATE_KEY_PATH = os.path.join(BASE_DIR, 'apps/payments/alipay/app_private_key.pem')
    ALIPAY_PUBLIC_KEY_PATH = os.path.join(BASE_DIR, 'apps/payments/alipay/alipay_public_key.pem')
    ALIPAY_DEBUG = True
    ALIPAY_SUBJECT = '智学客-订单支付'
    ALIPAY_RETURN_URL = 'http://www.xxx.com/pay_success.html'
    ALIPAY_GATE = 'https://openapi.alipaydev.com/gateway.do?'

    8.定义视图

    两个参数: 

          order_id: 订单编号

          alipay_uel: 支付宝支付链接

    代码如下:

     class AliPayURLView(APIView):
        def get(self, request, order_id):
            # 1.根据order_id查询订单对象
            try:
                order_obj = OrderInfo.objects.get(pk=order_id)
            except:
                raise Exception("订单号无效")
    
            # 2.创建alipay对象
            alipay = AliPay(
                appid=settings.ALIPAY_APPID,
                app_notify_url=None,
                app_private_key_path=settings.ALIPAY_PRIVATE_KEY_PATH,
                alipay_public_key_path=settings.ALIPAY_PUBLIC_KEY_PATH,
                debug=settings.ALIPAY_DEBUG
            )
    
            # 3.调用方法,生成url
            # 电脑网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string
            order_string = alipay.api_alipay_trade_page_pay(
                subject=settings.ALIPAY_SUBJECT,
                out_trade_no=order_id,  # 订单编号
                total_amount=str(order_obj.total_amount),  # 支付总金额,类型为Decimal(),不支持序列化,需要强转成str
                return_url=settings.ALIPAY_RETURN_URL  # 支付成功后的回调地址
    
            )
            # 4.返回url
            return Response({"alipay_url": settings.ALIPAY_GATE + order_string})

      8.1 在payments/urls.py中定义路由规则 

     url('^orders/(?P<order_id>d+)/payment/$',views.PaymentView.as_view()),

    9.保存支付状态

    请求方式:PUT /payment/status/?支付宝参数

    参数:trade_id:支付宝流水账号

    代码实现:

    class OrderStatusView(APIView):
        """验证用户是否登录成功"""
    
        def put(self, request):
            # 1.接收支付宝返回的数据
            data = request.query_params.dict()
    
            # 2.验证是否支付成功
            # 2.1删除签名,不参与验证
            signature = data.pop("sign")
    
            # 2.2 创建alipay对象
            alipay = AliPay(
                appid=settings.ALIPAY_APPID,
                app_notify_url=None,
                app_private_key_path=settings.ALIPAY_PRIVATE_KEY_PATH,
                alipay_public_key_path=settings.ALIPAY_PUBLIC_KEY_PATH,
                debug=settings.ALIPAY_DEBUG
            )
    
            # 2.3 调用verify(字典,签名)
            success = alipay.verify(data, signature)
            if success:
                # 支付成功
                '''
                {
                    'total_amount': '11388.00', 支付金额
                    'auth_app_id': '2016082100304973', 应用编号
                    'method': 'alipay.trade.page.pay.return',
                    'trade_no': '2018110722001420410500545016',流水号
                    'timestamp': '2018-11-07 16:59:20',时间
                    'app_id': '2016082100304973',应用编号
                   'out_trade_no': '20181107160224000000001',商城的订单编号
                   'charset': 'utf-8',编码
                   'seller_id': '2088102172415825',商家编号
                   'version': '1.0'版本
                }
                '''
                # 1 获取订单号
                order_id = data["out_trade_no"]
                # 2 修改订单状态
                try:
                    order_obj = OrderInfo.objects.get(pk=order_id)
                except:
                    raise Exception("订单号无效")
                order_obj.status = 2
                order_obj.save()
    
                # 3.创建订单支付对象
                trade_no = data.get('trade_no')  # 获取流水号
                Payment.objects.create(
                    order_id=order_id,
                    trade_no=trade_no
                )
    
                # 4.响应
                return Response({"trade_id": trade_no})
            else:
                raise Exception("支付失败")

      9.1 定义路由规则 

       url('^payment/status/$',views.PaymentStatusView.as_view()),
  • 相关阅读:
    EDA cheat sheet
    numpy.bincount()
    非负矩阵分解的两种方法简析
    Python列表解析和字典解析
    Pandas使用groupby()时是否会保留顺序?
    Reduce pandas memory size
    Understanding the Transform Function in Pandas
    What’s up with the Graph Laplacian
    如何在github上下载单个文件夹
    TCP回射服务器修订版(ubuntu 18.04)
  • 原文地址:https://www.cnblogs.com/xiaolu915/p/10528155.html
Copyright © 2020-2023  润新知