• django-支付宝支付


    安装python-alipay-sdk

    pip install python-alipay-sdk --upgrade

    配置

     视图函数orders/views.py

    # 订单支付
    # /order/pay
    from alipay import AliPay, ISVAliPay
    import os
    from django.conf import settings
    class OrderPayView(View):
        def post(self, request):
            '''支付页面'''
            # 判断用户是否登录
            user = request.user
            if not user.is_authenticated():
                return JsonResponse({'res':0, 'errmsg':'用户尚未登录'})
            # 接收订单id
            order_id = request.POST.get('order_id')
            # 校验订单id
            if not order_id:
                return JsonResponse({'res':1, 'errmsg':'无效的订单id'})
            # 查询订单信息
            try:
                order = OrderInfo.objects.get(order_id=order_id, user=user, pay_method=3, order_status=1)
            except OrderInfo.DoesNotExist:
                return JsonResponse({'res':2, 'errmsg':'订单错误'})
    
            # 业务处理 使用python sdk调用支付宝的支付接口
            # 支付宝信息   不能放在settings里 会报错
            alipay = AliPay(
                appid="2016101200665304",
                app_notify_url=None,  # 默认回调url  如果为空的话不能用'' 要用None
                # 个人私钥
                app_private_key_string=os.path.join(settings.BASE_DIR, 'apps/orders/app_private_key.pem'),
                # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
                alipay_public_key_string=os.path.join(settings.BASE_DIR, 'apps/orders/alipay_public_key.pem'),
                # 加密方式
                sign_type="RSA2",  # RSA 或者 RSA2
                # 沙箱是True 正式环境是False
                debug=True  # 默认False
            )
            # 调用支付接口
            # 电脑网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string 实际地址
            # 沙箱地址 https://openapi.alipaydev.com/gateway.do? + order_string  沙箱地址在alipay后面加上dev
            total_price = order.total_price + order.transit_price  # Decimal
            order_string = alipay.api_alipay_trade_page_pay(
                out_trade_no=order_id,  # 订单id
                total_amount=str(total_price),  # 支付总金额 因为Decimal格式不能序列化 所以先转成字符串
                subject='天天生鲜%s'%order_id,
                return_url=None,
                notify_url=None  # 可选, 不填则使用默认notify url
            )
            # 返回应答
            pay_url = 'https://openapi.alipaydev.com/gateway.do?' + order_string
            return JsonResponse({'res':3, 'pay_url':pay_url})

    配置路由urls.py

    from django.conf.urls import url
    from orders.views import OrderPlaceView, OrderCommitView, OrderPayView
    
    
    urlpatterns = [
        url(r'^place$', OrderPlaceView.as_view(), name='place'),  # 提交订单页面
        url(r'^commit$', OrderCommitView.as_view(), name='commit'),  # 提交订单处理
        url(r'^pay$', OrderPayView.as_view(), name='pay'),  # 订单支付
    
    ]

     用户订单页面user_center_order.html

    {% block bottomfiles %}
    <script src="{% static 'js/jquery-1.12.4.min.js' %}"></script>
    <script>
        $('.oper_btn').each(function(){
            //获取支付状态
            status = $(this).attr('status')
            if (status == 1){
                $(this).text('去付款')
            }else if (status == 4){
                $(this).text('去评价')
            }else if (status == 5){
                $(this).text('已完成')
            }
        })
        $('.oper_btn').click(function () {
            // 获取status
            status = $(this).attr('status')
            // 获取订单id
            order_id = $(this).attr('order_id')
            console.log(status)
            if (status == 1){
                // 进行支付
                csrf = $('input[name="csrfmiddlewaretoken"]').val()
                // 组织参数
                params = {'order_id':order_id, 'csrfmiddlewaretoken':csrf}
                // 发起ajax post请求,访问/order/pay, 传递参数:order_id
                $.post('/order/pay', params, function (data) {
                    if (data.res == 3){
                        // 引导用户到支付页面
                        window.open(data.pay_url)
    
                    }
                    else{
                        alert(data.errmsg)
                    }
                })
            }
            else if (status == 4){
                // 其他情况
                // 跳转到评价页面
                location.href = '/order/comment/'+order_id
            }
        })
    </script>
    {% endblock bottomfiles %}

    点击去付款,报错

    ValueError at /order/pay
    RSA key format is not supported
    
    Request Method: POST
    Request URL: http://192.168.199.130:8000/order/pay
    Django Version: 1.8.2
    Python Executable: /home/python/.virtualenvs/bj19/bin/python
    Python Version: 3.5.2
    Python Path: ['/home/python/bj19/ttsx/dailyfresh/apps', '/home/python/bj19/ttsx/dailyfresh', '/home/python/.virtualenvs/bj19/lib/python35.zip', '/home/python/.virtualenvs/bj19/lib/python3.5', '/home/python/.virtualenvs/bj19/lib/python3.5/plat-x86_64-linux-gnu', '/home/python/.virtualenvs/bj19/lib/python3.5/lib-dynload', '/usr/lib/python3.5', '/usr/lib/python3.5/plat-x86_64-linux-gnu', '/home/python/.virtualenvs/bj19/lib/python3.5/site-packages', '/home/python/bj19/ttsx/dailyfresh']
    Server time: 星期四, 17 十月 2019 15:21:03 +0800
    Installed Applications:
    ('django.contrib.admin',
     'django.contrib.auth',
     'django.contrib.contenttypes',
     'django.contrib.sessions',
     'django.contrib.messages',
     'django.contrib.staticfiles',
     'tinymce',
     'user',
     'cart',
     'goods',
     'orders',
     'haystack')
    Installed Middleware:
    ('django.contrib.sessions.middleware.SessionMiddleware',
     'django.middleware.common.CommonMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
     'django.middleware.clickjacking.XFrameOptionsMiddleware',
     'django.middleware.security.SecurityMiddleware')
    
    Traceback:
    File "/home/python/.virtualenvs/bj19/lib/python3.5/site-packages/django/core/handlers/base.py" in get_response
      132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
    File "/home/python/.virtualenvs/bj19/lib/python3.5/site-packages/django/views/generic/base.py" in view
      71.             return self.dispatch(request, *args, **kwargs)
    File "/home/python/.virtualenvs/bj19/lib/python3.5/site-packages/django/views/generic/base.py" in dispatch
      89.         return handler(request, *args, **kwargs)
    File "/home/python/bj19/ttsx/dailyfresh/apps/orders/views.py" in post
      374.             debug=True  # 默认False
    File "/home/python/.virtualenvs/bj19/lib/python3.5/site-packages/alipay/__init__.py" in __init__
      81.         self._load_key()
    File "/home/python/.virtualenvs/bj19/lib/python3.5/site-packages/alipay/__init__.py" in _load_key
      89.         self._app_private_key = RSA.importKey(content)
    File "/home/python/.virtualenvs/bj19/lib/python3.5/site-packages/Cryptodome/PublicKey/RSA.py" in import_key
      754.     raise ValueError("RSA key format is not supported")
    
    Exception Type: ValueError at /order/pay
    Exception Value: RSA key format is not supported
    Request information:
    GET: No GET data

    查找原因 视图函数中Alipay{}中

     alipay = AliPay(
                appid="2016101200665304",
                app_notify_url=None,  # 默认回调url  如果为空的话不能用'' 要用None
                # 个人私钥
                app_private_key_path=os.path.join(settings.BASE_DIR, 'keys/app_private_key.pem'),  # 此处是路径用path 不是string
                # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
                alipay_public_key_path=os.path.join(settings.BASE_DIR, 'keys/alipay_public_key.pem'),  # 此处是路径用path 不是string
                # 加密方式
                sign_type="RSA2",  # RSA 或者 RSA2
                # 沙箱是True 正式环境是False
                debug=True  # 默认False
            )

    OK,解决问题,继续

    让网站知道已经支付成功

    视图函数views.py中添加支付查询功能

    class OrderCheckView(View):
        def post(self, request):
            '''支付查询页面'''
            # 判断用户是否登录
            user = request.user
            if not user.is_authenticated():
                return JsonResponse({'res':0, 'errmsg':'用户尚未登录'})
            # 接收订单id
            order_id = request.POST.get('order_id')
            # 校验订单id
            if not order_id:
                return JsonResponse({'res':1, 'errmsg':'无效的订单id'})
            # 查询订单信息
            try:
                order = OrderInfo.objects.get(order_id=order_id, user=user, pay_method=3, order_status=1)
            except OrderInfo.DoesNotExist:
                return JsonResponse({'res':2, 'errmsg':'订单错误'})
    
            # 业务处理 使用python sdk调用支付宝的支付接口
            # 支付宝信息   不能放在settings里 会报错
    
            alipay = AliPay(
                appid="2016101200665304",
                app_notify_url=None,  # 默认回调url  如果为空的话不能用'' 要用None
                # 个人私钥
                app_private_key_path=os.path.join(settings.BASE_DIR, 'keys/app_private_key.pem'),
                # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
                alipay_public_key_path=os.path.join(settings.BASE_DIR, 'keys/alipay_public_key.pem'),
                # 加密方式
                sign_type="RSA2",  # RSA 或者 RSA2
                # 沙箱是True 正式环境是False
                debug=True  # 默认False
            )
    
            # 调用支付宝交易查询接口
            while True:
                response = alipay.api_alipay_trade_query(order_id)
    
                # response = {
                #     "alipay_trade_query_response": {
                #         "trade_no": "2017032121001004070200176844",  # 支付宝交易号
                #         "code": "10000",  # 返回码
                #         "invoice_amount": "20.00",
                #         "open_id": "20880072506750308812798160715407",
                #         "fund_bill_list": [
                #             {
                #                 "amount": "20.00",
                #                 "fund_channel": "ALIPAYACCOUNT"
                #             }
                #         ],
                #         "buyer_logon_id": "csq***@sandbox.com",
                #         "send_pay_date": "2017-03-21 13:29:17",
                #         "receipt_amount": "20.00",
                #         "out_trade_no": "out_trade_no15",
                #         "buyer_pay_amount": "20.00",
                #         "buyer_user_id": "2088102169481075",
                #         "msg": "Success",
                #         "point_amount": "0.00",
                #         "trade_status": "TRADE_SUCCESS",  # 交易状态:WAIT_BUYER_PAY(交易创建,等待买家付款)、TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、TRADE_SUCCESS(交易支付成功)、TRADE_FINISHED(交易结束,不可退款)
                #         "total_amount": "20.00"
                #     },
                #     "sign": ""
                # }
    
                code = response.get('code')
                if code == '10000' and response.get('trade_status') == 'TRADE_SUCCESS':
                    # 支付成功
                    # 获取支付宝交易号
                    trade_no = response.get('trade_no')
                    # 更新订单状态
                    order.trade_no = trade_no
                    order.order_status = 4
                    order.save()  # 更新
                    # 返回结果
                    return JsonResponse({'res':3, 'message':'支付成功'})
                elif code =='40004' or (code == '10000' and response.get('trade_status') == 'WAIT_BUYER_PAY'):
                    # 等待买家付款
                    import time
                    time.sleep(5)
                    continue  # 跳过本次循环 重新开始循环
                else:
                    # 支付出错
                    return JsonResponse({'res':4, 'errmsg':'支付失败'})

    模板中ajax转到查询

    {% block bottomfiles %}
    <script src="{% static 'js/jquery-1.12.4.min.js' %}"></script>
    <script>
        $('.oper_btn').each(function(){
            //获取支付状态
            status = $(this).attr('status')
            if (status == 1){
                $(this).text('去付款')
            }else if (status == 4){
                $(this).text('去评价')
            }else if (status == 5){
                $(this).text('已完成')
            }
        })
        $('.oper_btn').click(function () {
            // 获取status
            status = $(this).attr('status')
            // 获取订单id
            order_id = $(this).attr('order_id')
            console.log(status)
            if (status == 1){
                // 进行支付
                csrf = $('input[name="csrfmiddlewaretoken"]').val()
                // 组织参数
                params = {'order_id':order_id, 'csrfmiddlewaretoken':csrf}
                // 发起ajax post请求,访问/order/pay, 传递参数:order_id
                $.post('/order/pay', params, function (data) {
                    if (data.res == 3){
                        // 引导用户到支付页面
                        window.open(data.pay_url)
                        // 浏览器访问/order/check, 获取支付交易的结果
                        // ajax post 传递参数:order_id
                        $.post('/order/check', params, function (data){
                            if (data.res == 3){
                                alert(data.message)
                                // 刷新页面
                                location.reload()
                            }
                            else{
                                alert(data.errmsg)
                            }
                        })
                    }
                    else{
                        alert(data.errmsg)
                    }
                })
            }
            else if (status == 4){
                // 其他情况
                // 跳转到评价页面
                location.href = '/order/comment/'+order_id
            }
        })
    </script>
    {% endblock bottomfiles %}
  • 相关阅读:
    matplotlib笔记(subplot)
    matplotlib笔记(plot)
    [时间序列处理]python中计算日期差
    Ubuntu 16.04 apt-get更换为国内阿里云源
    居然忘了range()的用法
    elasticsearch+kibana使用中踩的坑,持续更新中。
    Elasticsearch+Logstash+Kibana教程
    ubuntu下anaconda从清华镜像的下载安装及配置
    ubuntu 解决node 修改代码不能同步刷新的问题
    ubuntu18.04 解决sublimie不能使用中文
  • 原文地址:https://www.cnblogs.com/yifengs/p/11691423.html
Copyright © 2020-2023  润新知