電腦網站的支付流程以及支付寶沙箱環境使用前的配置
-
1、電腦網站的支付流程


-
2、支付寶沙箱環境的介紹以及使用前的配置

使用前的配置配置
-
1、打開網站,使用已有的支付寶賬號登錄
https://open.alipay.com/platform/home.htm
-
2、點擊開發者中心 ---- 研發中心 -------- 沙箱應用 -------- 設置密鑰



-
3、公鑰和密鑰的介紹
用戶需要有自己的公鑰和密鑰,密鑰由自己保持,作用是將發送給支付寶網站的數據進行加密,並且用戶需要將自己的公鑰告訴支付寶,支付寶可以用公鑰進行解密。同樣的,用戶也需要拿到支付寶的公鑰。

-
4、生成公鑰和私鑰
window系統可以使用支付寶提供的軟件進行公鑰和私鑰的生成

復制公鑰,粘貼在上面打開的沙箱應用 ----- RSA2密鑰設置中

同時保存支付寶的公鑰
在項目中創建文件夾key,專門存放用戶私鑰和支付寶公鑰
在文件夾key中,創建兩個文件 alipay_public_key.pem(存放支付寶公鑰)和app_private_key.pem(存放用戶私鑰)

分別打開,將私鑰和公鑰復制進去,格式:
-----BEGIN RSA PRIVATE KEY-----
公鑰或者私鑰復制在這里
-----END RSA PRIVATE KEY-----
將兩個文件的絕對路徑加入到項目settings文件中
## 公鑰和私鑰的地址 APP_PRIVATE_KEY_PATH = os.path.join(BASE_DIR,'key/app_private_key.pem') ALIPAY_PUBLIC_KEY_PATH = os.path.join(BASE_DIR,'key/alipay_public_key.pem')
-
5、使用python-alipay-sdk
由於支付寶沒有提供Python的alipay-SDK,所以需要借助第三方的非官方支付寶 Python SDK
相關網址:https://github.com/fzlee/alipay/blob/master/README.zh-hans.md#alipay.trade.page.pay
安裝:
# 從 1.3.0升級上來的用戶, 請先卸載pycrypto: pip uninstall pycrypto # 安裝python-alipay-sdk pip install python-alipay-sdk --upgrade
天天生鮮項目的訂單支付
-
1、訂單支付的邏輯分析
當用戶在前端點擊訂單支付時,需要將訂單的id傳遞到后台,后台需要對數據進行校驗,並連接支付寶沙箱,並傳遞支付鏈接,引導用戶跳轉到支付鏈接
-
2、訂單支付的視圖函數和模板文件
from alipay import AliPay ## 使用支付寶付款,接收的參數:訂單id:order_id 參數校驗之后引導用戶跳轉到支付頁面 class OrderPayView(View): '''支付處理''' def post(self,request): '''支付處理''' order_id = request.POST.get('order_id') ## 1、 參數校驗 user = request.user if not user.is_authenticated: return JsonResponse({'res':0,'errmsg':'用戶未登錄'}) if not order_id: return JsonResponse({'res':1,'errmsg':'參數不完整'}) try: order = OrderInfo.objects.get(order_id=order_id) ## 計算訂單的總金額,轉化成字符串格式 total_amount = order.total_price+order.transit_price total_amount = str(total_amount) except OrderInfo.DoesNoExist: return JsonResponse({'res':2,'errmsg':'訂單不存在'}) ## 業務處理 ## 支付初始化 app_private_key_string = open(settings.APP_PRIVATE_KEY_PATH).read() alipay_public_key_string = open(settings.ALIPAY_PUBLIC_KEY_PATH).read() alipay = AliPay( appid='2016102400751639', app_notify_url=None, # 默認回調url app_private_key_string=app_private_key_string, # 支付寶的公鑰,驗證支付寶回傳消息使用,不是你自己的公鑰, alipay_public_key_string=alipay_public_key_string, sign_type="RSA2" , # RSA 或者 RSA2 debug = True # 默認False ) ## 接口調用 # 電腦網站支付,需要跳轉到https://openapi.alipay.com/gateway.do? + order_string order_string = alipay.api_alipay_trade_page_pay( out_trade_no=order_id, ## 訂單的編號 total_amount=total_amount, ## 訂單的總金額 subject='天天生鮮%s'%order_id, ## 訂單的名稱 return_url=None, notify_url=None ) ## 3、返回應答 pay_url = 'https://openapi.alipaydev.com/gateway.do?' + order_string return JsonResponse({'res':3,'pay_url':pay_url})
{% extends 'base_user_center.html' %} {% load static %} {% block title %}天天生鮮-用戶中心{% endblock title %} {% block right_content %} <div class="right_content clearfix"> {% csrf_token %} <h3 class="common_title2">全部訂單</h3> {% for order in order_pages %} <ul class="order_list_th w978 clearfix"> <li class="col01">{{ order.create_time }}</li> <li class="col02">訂單號:{{ order.order_id }}</li> <li class="col02 stress">{{ order.status }}</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"><a href="{% url 'goods:detail' order_sku.sku.id %}"><img src="{{ order_sku.sku.image.url }}" ></a></li> <li class="col02">{{ order_sku.sku.name }}<em>{{ order_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|add:order.transit_price }}(含運費:{{ order.transit_price }})元</td> <td width="15%">{{ order.status }}</td> <td width="15%"><a href="#" class="oper_btn" order_status="{{ order.order_status }}" order_id="{{ order.order_id }}">去付款</a></td> </tr> </tbody> </table> {% endfor %} <div class="pagenation"> {% if order_pages.has_previous %} <a href="{% url 'user:order' order_pages.previous_page_number %}"><上一頁</a> {% endif %} {% for pindex in pages %} {% if pindex == order_pages.number %} <a href="{% url 'user:order' pindex %}" class="active">{{ pindex }}</a> {% else %} <a href="{% url 'user:order' pindex %}">{{ pindex }}</a> {% endif %} {% endfor %} {% if order_pages.has_next %} <a href="{% url 'user:order' order_pages.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(){ // 判斷訂單的支付狀態,只有待支付才能付款 var order_status = $(this).attr('order_status'); if (order_status == 1){ // 准備參數: 訂單id:order_id var order_id = $(this).attr('order_id'); var csrf = $('input[name="csrfmiddlewaretoken"]').val(); // 組織參數 var context = {'order_id':order_id,'csrfmiddlewaretoken':csrf}; // ajax post請求,地址:/order/pay $.post('/order/pay',context,function(data){ if (data.res == 3){ // 通過驗證,引導用戶跳轉到支付頁面 window.open(data.pay_url); } else{ //通過失敗 alert(data.errmsg); } }) } }) </script> {% endblock bottomfiles %}
-
3、訂單支付結果的查詢
當用戶點擊支付按鈕的時候,前端不僅需要通過ajax post向后台申請支付頁面,還要立即通過ajax post提交向后台請求支付結果的查詢
后端查詢支付結果的視圖函數:
1 ## 接收的參數:訂單id:order_id 2 class CheckPayView(View): 3 '''查詢訂單支付結果''' 4 def post(self,request): 5 '''查詢訂單支付結果''' 6 order_id = request.POST.get('order_id') 7 8 ## 1、 參數校驗 9 user = request.user 10 if not user.is_authenticated: 11 return JsonResponse({'res': 0, 'errmsg': '用戶未登錄'}) 12 if not order_id: 13 return JsonResponse({'res': 1, 'errmsg': '參數不完整'}) 14 try: 15 order = OrderInfo.objects.get(order_id=order_id) 16 except OrderInfo.DoesNoExist: 17 return JsonResponse({'res': 2, 'errmsg': '訂單不存在'}) 18 19 ## 業務處理 20 ## 支付初始化 21 22 app_private_key_string = open(settings.APP_PRIVATE_KEY_PATH).read() 23 alipay_public_key_string = open(settings.ALIPAY_PUBLIC_KEY_PATH).read() 24 25 alipay = AliPay( 26 appid='2016102400751639', 27 app_notify_url=None, # 默認回調url 28 app_private_key_string=app_private_key_string, 29 # 支付寶的公鑰,驗證支付寶回傳消息使用,不是你自己的公鑰, 30 alipay_public_key_string=alipay_public_key_string, 31 sign_type="RSA2", # RSA 或者 RSA2 32 debug=True # 默認False 33 ) 34 while 1: 35 ## 循環查詢,直到查詢到結果才跳出循環 36 ## 連接到支付寶的支付查詢接口 37 response = alipay.api_alipay_trade_query(order_id) 38 39 # response = { 40 # "trade_no": "2017032121001004070200176844", # 支付寶交易號 41 # "code": "10000", # 接口調用是否成功 42 # "invoice_amount": "20.00", 43 # "open_id": "20880072506750308812798160715407", 44 # "fund_bill_list": [ 45 # { 46 # "amount": "20.00", 47 # "fund_channel": "ALIPAYACCOUNT" 48 # } 49 # ], 50 # "buyer_logon_id": "csq***@sandbox.com", 51 # "send_pay_date": "2017-03-21 13:29:17", 52 # "receipt_amount": "20.00", 53 # "out_trade_no": "out_trade_no15", 54 # "buyer_pay_amount": "20.00", 55 # "buyer_user_id": "2088102169481075", 56 # "msg": "Success", 57 # "point_amount": "0.00", 58 # "trade_status": "TRADE_SUCCESS", # 支付結果 59 # "total_amount": "20.00" 60 # } 61 62 63 ## 獲取校驗的結果並進行相應的處理 64 code = response.get('code') ## 接口調用 65 trade_status = response.get('trade_status') ## 支付結果 66 if code == '10000' and trade_status == 'TRADE_SUCCESS': 67 ## 支付成功 68 ## 更新訂單狀態,返回應答 69 order.order_status = 4 70 ## 添加支付編號 71 order.trade_no = response.get('trade_no') 72 order.save() 73 print(order.order_status) 74 print('支付成功') 75 ## 返回應答 76 return JsonResponse({'res':3,'message':'支付成功'}) 77 elif code == '40004' or (code == '10000' and response.get('trade_status') == 'WAIT_BUYER_PAY'): 78 # 等待買家付款 79 # 業務處理失敗,可能一會就會成功 80 import time 81 time.sleep(5) 82 print('這里還在等待支付') 83 continue 84 else: 85 ## 支付失敗 86 return JsonResponse({'res':4,'errmsg':'支付失敗'})
模板文件:
{% extends 'base_user_center.html' %} {% load static %} {% block title %}天天生鮮-用戶中心{% endblock title %} {% block right_content %} <div class="right_content clearfix"> {% csrf_token %} <h3 class="common_title2">全部訂單</h3> {% for order in order_pages %} <ul class="order_list_th w978 clearfix"> <li class="col01">{{ order.create_time }}</li> <li class="col02">訂單號:{{ order.order_id }}</li> <li class="col02 stress">{{ order.status }}</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"><a href="{% url 'goods:detail' order_sku.sku.id %}"><img src="{{ order_sku.sku.image.url }}" ></a></li> <li class="col02">{{ order_sku.sku.name }}<em>{{ order_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|add:order.transit_price }}(含運費:{{ order.transit_price }})元</td> <td width="15%">{{ order.status }}</td> <td width="15%"><a href="#" class="oper_btn" order_status="{{ order.order_status }}" order_id="{{ order.order_id }}">去付款</a></td> </tr> </tbody> </table> {% endfor %} <div class="pagenation"> {% if order_pages.has_previous %} <a href="{% url 'user:order' order_pages.previous_page_number %}"><上一頁</a> {% endif %} {% for pindex in pages %} {% if pindex == order_pages.number %} <a href="{% url 'user:order' pindex %}" class="active">{{ pindex }}</a> {% else %} <a href="{% url 'user:order' pindex %}">{{ pindex }}</a> {% endif %} {% endfor %} {% if order_pages.has_next %} <a href="{% url 'user:order' order_pages.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(){ // 判斷訂單的支付狀態,只有待支付才能付款 var order_status = $(this).attr('order_status'); if (order_status == 1){ // 准備參數: 訂單id:order_id var order_id = $(this).attr('order_id'); var csrf = $('input[name="csrfmiddlewaretoken"]').val(); // 組織參數 var context = {'order_id':order_id,'csrfmiddlewaretoken':csrf}; // ajax post請求,地址:/order/pay $.post('/order/pay',context,function(data){ if (data.res == 3){ // 通過驗證,引導用戶跳轉到支付頁面 window.open(data.pay_url); // 發起ajax post 請求 /order/check ,查詢訂單支付結果,傳遞的參數:order_id $.post('/order/check',context,function(data){ // 判斷是否支付成功 if (data.res == 3){ // 支付成功,打印支付成功信息,並更新訂單狀態 alert(data.message); // 刷新頁面 location.reload() } }) } else{ //通過失敗 alert(data.errmsg); } }) } }) </script> {% endblock bottomfiles %}
