django项目中如何实现支付宝付款功能

    科技2024-05-17  89

    支付宝开放平台网址:https://open.alipay.com/platform/home.htm

    1. 网站对接支付宝流程图

    2. 使用python工具包 

    使用教程网址:https://github.com/fzlee/alipay/blob/master/README.zh-hans.md

    (1)安装

    # 从 1.3.0升级上来的用户, 请先卸载pycrypto: pip uninstall pycrypto # 安装python-alipay-sdk pip install python-alipay-sdk --upgrade (2)切换到openssl命令

    (3)生成秘钥文件

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

    (4)打开公钥文件,将内容复制粘贴到沙箱里面

    支付宝开放平台网址:https://open.alipay.com/platform/home.htm

    (5)在项目中支付页面对应的应用下面新建一个文件:alipay_public_key.pem

    将支付宝公钥复制到该文件中,并且第一行和最后一行加两句话

    注意:公钥文件保存的是支付宝公钥的内容,私钥文件是我们本机生成的私钥文件

    (6)将刚才生成的私钥文件:app_private_key.pem  也复制到第五步的目录中去

    (7)支付的视图函数代码如下

    from alipay import AliPay from django.conf import settings import os # 采用ajax post请求,参数:order_id class OrderPayView(View): """订单支付""" def post(self, request): """订单支付""" # 用户是否登录 user = request.user if not user.is_authenticated(): return JsonResponse({"res": 0, "errmsg": "用户未登录"}) # 接收参数 order_id = request.POST.get("order_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调用支付宝的支付接口 # 初始化 alipay = AliPay( appid="2016102500758385", # 订单id app_notify_url=None, # 默认回调url # app_private_key_path=os.path.join(settings.BASE_DIR, "apps/order/app_private_key.pem"), # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥, # alipay_public_key_path=os.path.join(settings.BASE_DIR, "apps/order/alipay_public_key.pem"), app_private_key_string= """-----BEGIN RSA PRIVATE KEY----- ........................... -----END RSA PRIVATE KEY-----""", alipay_public_key_string= """-----BEGIN PUBLIC KEY----- .......................... -----END PUBLIC KEY-----""", sign_type="RSA2", # RSA 或者 RSA2, 签名 debug=True, # 默认False, 沙箱模式需改为True ) # 调用支付接口 # 电脑网站支付,需要跳转到沙箱环境https://openapi.alipaydev.com/gateway.do? + order_string # 电脑网站支付,需要跳转到正式环境https://openapi.alipay.com/gateway.do? + order_string total_pay = order.total_price + order.transit_price # decimal order_string = alipay.api_alipay_trade_page_pay( out_trade_no=order_id, # 订单id # total_amount支持json,但是decimal数据不能直接序列化成json,所以转换成字符串即可 total_amount=str(total_pay), # 支付总金额 subject="天天生鲜{}".format(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})

    (8)获取支付结果代码如下:

    # 采用ajax post请求,参数:order_id class CheckPayView(View): """查看订单支付的结果""" def post(self, request): """查询支付结果""" # 用户是否登录 user = request.user if not user.is_authenticated(): return JsonResponse({"res": 0, "errmsg": "用户未登录"}) # 接收参数 order_id = request.POST.get("order_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调用支付宝的支付接口 # 初始化 alipay = AliPay( appid="2016102500758385", # 订单id app_notify_url=None, # 默认回调url # app_private_key_path=os.path.join(settings.BASE_DIR, "apps/order/app_private_key.pem"), # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥, # alipay_public_key_path=os.path.join(settings.BASE_DIR, "apps/order/alipay_public_key.pem"), app_private_key_string= """-----BEGIN RSA PRIVATE KEY----- ....... -----END RSA PRIVATE KEY-----""", alipay_public_key_string= """-----BEGIN PUBLIC KEY----- ....... -----END PUBLIC KEY-----""", sign_type="RSA2", # RSA 或者 RSA2, 签名 debug=True, # 默认False, 沙箱模式需改为True ) # 调用支付宝的交易查询接口 while True: response = alipay.api_alipay_trade_query(out_trade_no=order_id) # 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", # 支付的结果 # "total_amount": "20.00" # } code = response.get("code") trade_status = response.get("trade_status") if code == "10000" and 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 trade_status == "WAIT_BUYER_PAY"): # 等待买家付款 # 业务处理失败,可能一会就会成功 import time time.sleep(2) continue else: # 支付出错 return JsonResponse({"res": 4, "errmsg": "支付失败"})

     

    (9)html用户订单付款页面如下

    {% extends "base_user_center.html" %} {% load staticfiles %} {% load filters %} {% block right_content %} <div class="right_content clearfix"> {% csrf_token %} <h3 class="common_title2">全部订单</h3> {% for order in order_page %} <ul class="order_list_th w978 clearfix"> <li class="col01">{{ order.create_time|date:'Y年m月d日 H:i:s' }}</li> <li class="col02">订单号:{{ order.order_id }}</li> <li class="col02 stress">{{ order.status_name }}</li> </ul> <table class="order_list_table w980"> <tbody> <tr> <td width="55%"> {% for order_sku in order.order_skus %} <ul class="order_goods_list clearfix"> <li class="col01"><img src="{{ order_sku.sku.image.url }}"></li> <li class="col02">{{ order_sku.sku.name }}<em>{{ sku.price }}元/{{ order_sku.sku.unite }}</em> </li> <li class="col03">{{ order_sku.count }}</li> <li class="col04">{{ order_sku.amount }}元</li> </ul> {% endfor %} </td> <td width="15%">{{ order.total_price|save_two:order.transit_price }}{% if order.total_price >= 80 %} (满80免运费){% else %}(含运费:{{ order.transit_price }})元{% endif %}</td> <td width="15%">{{ order.status_name }}</td> <td width="15%"><a href="#" order_id="{{ order.order_id }}" status="{{ order.order_status }}" class="oper_btn">去付款</a></td> </tr> </tbody> </table> {% endfor %} <div class="pagenation"> {% if order_page.has_previous_page %} <a href="{% url 'user:order' order_page.previous_page_number %}">上一页</a> {% endif %} {% for pindex in pages %} {% if pindex == order_page.number %} <a href="{% url 'user:order' pindex %}" class="active">{{ pindex }}</a> {% else %} <a href="{% url 'user:order' pindex %}">{{ pindex }}</a> {% endif %} {% endfor %} {% if order_page.has_next_page %} <a href="{% url 'user:order' order_page.next_page_number %} ">下一页></a> {% endif %} </div> </div> {% endblock right_content %} {% block bottomfiles %} <script src="{% static 'js/jquery-1.12.4.min.js' %}"></script> <script> $(".oper_btn").click(function () { // 获取status status = $(this).attr("status"); if(status == 1){ // 进行支付,获取订单id order_id = $(this).attr("order_id"); 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("支付成功"); // 刷新页面 location.reload(); } else{ // 显示出错信息 alert(data.errmsg); } }) } else{ // 支付失败 alert(data.errmsg); } }) } else{ // 其他情况 } }) </script> {% endblock bottomfiles %}

    (9) 支付流程图

     

    Processed: 0.010, SQL: 8