說明:該篇博客是博主一字一碼編寫的,實屬不易,請尊重原創,謝謝你們!javascript
接着上一篇博客繼續往下寫 :https://blog.csdn.net/qq_41782425/article/details/86660480html
目錄java
一丶支付接口python
二丶支付寶支付後端接口編寫mysql
三丶支付寶支付測試linux
五丶測試訂單支付成功後對訂單狀態的修改github
七丶項目優化redis
1.分析:當客戶下單後,房東須要進入客戶訂單中,將該訂單進行接單處理後,那麼在客戶的個人訂單功能中,才能對此訂單進行支付操做,當客戶點擊支付後,接入支付寶支付(這裏以支付寶爲支付方式,微信的話邏輯也是同樣)
2.支付寶開發文檔
3.支付寶產品流程
步驟1:用戶在瀏覽器中訪問商家網頁應用,選擇商品下單、確認購買,進入支付環節,選擇支付寶付款,用戶點擊去支付,以下圖1;
步驟2:進入到支付寶支付路由頁面,支付寶處理支付請求,並嘗試喚起支付寶客戶端,以下圖2;
步驟3:進入到支付寶頁面,調起支付寶支付,出現確認支付界面,以下圖3;
圖1: | 圖2: | 圖3: |
步驟4:用戶確認收款方和金額,點擊當即支付後出現輸入密碼界面,以下圖4;
步驟5:輸入正確密碼後,支付寶端顯示支付結果,以下圖5;
步驟6:自動回跳到瀏覽器中,商家根據付款結果個性化展現訂單處理結果,以下圖6。
注意:在iOS系統中,喚起支付寶App支付完成後,不會自動回到瀏覽器或商戶App。用戶可手工切回到瀏覽器或商戶App。
圖4: | 圖5: | 圖6: |
用戶未安裝支付寶支付流程
步驟1:若用戶未安裝支付寶客戶端,用戶進入到支付寶網頁收銀臺,用戶登陸支付寶帳戶,如圖7和圖8;
步驟2:登陸成功後,進入付款確認頁面,如圖9;
步驟3:用戶點擊確認付款,進入支付密碼頁面,如圖10;
步驟4:用戶輸入密碼,完成支付,展現支付結果,如圖11。
圖7: | 圖8: | 圖9: |
圖10: | 圖11: |
4.建立應用
5.沙箱:這是支付寶提供開發人員測試的那麼一個環境,這個沙箱環境與線上的環境是同樣的,在沙箱環境與線上使用惟一不一樣的就是APPID,若是須要轉換爲線上的話,只須要將APPID修改成你的應用的APPID便可,程序代碼不須要做任何改變,進入支付寶沙箱,在沙箱帳號中分爲賣家信息和買家信息,帳戶餘額能夠任意充值
6.支付流程圖
7.在支付寶開發平臺中,只有JAVA PHP 以及.NET三種語言的SDK,在github上也有他人封裝好的支付寶支付的SDK
https://github.com/fzlee/alipay/blob/master/README.zh-hans.md
1.生成祕鑰文件
2.邏輯編寫
@api.route("/orders/<int:order_id>/payment", methods=["POST"]) @login_required def order_pay(order_id): """支付寶支付""" pass
user_id = g.user_id
try: order = Order.query.filter(Order.id==order_id, Order.user_id==user_id, Order.status=="WAIT_PAYMENT").first() except Exception as e: current_app.logger.error(e) return jsonify(errno=RET.DBERR, errmsg="數據庫異常")
if not order: return jsonify(errno=RET.NODATA, errmsg="訂單數據有誤")
app_private_key_path = os.path.join(os.path.dirname(__file__), "keys/app_private_key.pem") app_private_key_string = open(app_private_key_path).read()
alipay_public_key_path = os.path.join(os.path.dirname(__file__), "keys/alipay_public_key.pem") alipay_public_key_string = open(alipay_public_key_path).read()
app_client = AliPay( appid="2016092400589177", # 沙箱的appid 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 )
order_string = app_client.api_alipay_trade_wap_pay( out_trade_no=order.id, # 訂單編號 total_amount=str(order.amount/100.0), # 總金額 subject=u"愛家租房<%s>" % order.id, # 訂單標題 return_url="http://127.0.0.1:5000/orders.html", notify_url=None # 可選, 不填則使用默認notify url )
pay_url = constants.ALIPAY_URL_PREFIX + order_string return jsonify(errno=RET.OK, errmsg="OK", data={"pay_url":pay_url})
1.運行項目,清除瀏覽器緩存,進入http://127.0.0.1:5000/orders.html個人訂單頁面
2.在訂單編號爲5的訂單上進行點擊去支付, 而後會出現一個檢查客戶到的頁面,若是客戶端存在則會在手機上打開支付寶客戶端(注:由於這裏博主使用的是沙箱進行開發測試,因此在手機端須要安裝沙箱版的支付寶,詳細說明在開發平臺文檔中有相關說明,此支付寶只暫不支持IOS)
3.由於博主是在電腦Web上進行測試,因此當環境中沒有支付寶客戶端,那麼就會跳轉到支付寶手機網頁登陸界面,選擇支付寶帳號登陸(左圖),輸入開發平臺沙箱買家帳號(右圖)進行登陸
4.點擊下一步後,會出現房屋的編號,以及金額,與個人訂單中編號5的的訂單信息一致(左圖),點擊確認付款後,輸入支付密碼,而後出現(右圖)成功界面
5.點擊完成後,根據return_url編寫的代碼邏輯會跳轉到http://127.0.0.1:5000/orders.html訂單頁面,此時訂單5的狀態依然顯示待支付(左圖),那是由於這一塊的邏輯還未進行編寫,當支付寶支付成功返回正確響應數據給咱們時,咱們還未在頁面中對訂單的狀態進行修改,若是此時再點擊該訂單的去支付,則會出現(右圖)頁面,而不會跳轉到訂單支付界面,此時若是點擊繼續支付,則會報錯,由於此訂單在支付寶後臺已經有對應的流水了
1.分析:根據代碼邏輯當客戶進行訂單支付後,支付顯示成功後,支付寶會攜帶如下參數跳轉到訂單頁面,正常來講那麼在這個頁面就應該根據支付寶返回的參數,進行處理,可是放在訂單頁面進行處理的話就比較麻煩,由於我客戶訪問個人訂單頁面時,是不須要攜帶參數的,而從個人訂單頁面去訪問支付寶支付接口時,成功支付後,返回的個人訂單頁面是攜帶了參數的,因此若是要在個人訂單頁面進行處理的話,須要進行判斷究竟是客戶訪問的仍是支付寶返回回來的這是其一,其二就是在個人訂單頁面何時讓後端去對訂單狀態進行更改,因此在個人訂單頁面進行處理的話,邏輯比較複雜,那麼最好的方式就是定義一個過渡頁面,當支付寶支付成功後,不是直接跳轉到個人訂單頁面,而是跳轉到咱們定義的過渡頁面,在這個過渡頁面確定是有支付寶發送過來的參數,那麼就在後端對訂單狀態進行修改,再跳轉到個人訂單頁面,顯示成功支付後的訂單狀態
前臺回跳參數
公共參數:
參數 | 類型 | 是否必填 | 最大長度 | 描述 | 示例值 |
---|---|---|---|---|---|
app_id | String | 是 | 32 | 支付寶分配給開發者的應用ID | 2016040501024706 |
method | String | 是 | 128 | 接口名稱 | alipay.trade.wap.pay.return |
sign_type | String | 是 | 10 | 簽名算法類型,目前支持RSA2和RSA,推薦使用RSA2 | RSA2 |
sign | String | 是 | 256 | 支付寶對本次支付結果的簽名,開發者必須使用支付寶公鑰驗證簽名 | 詳見示例 |
charset | String | 是 | 10 | 編碼格式,如utf-8,gbk,gb2312等 | utf-8 |
timestamp | String | 是 | 19 | 前臺回跳的時間,格式"yyyy-MM-dd HH:mm:ss" | 2016-08-11 19:36:01 |
version | String | 是 | 3 | 調用的接口版本,固定爲:1.0 | 1.0 |
業務參數:
參數 | 類型 | 是否必填 | 最大長度 | 描述 | 示例值 |
---|---|---|---|---|---|
out_trade_no | String | 是 | 64 | 商戶網站惟一訂單號 | 70501111111S001111119 |
trade_no | String | 是 | 64 | 該交易在支付寶系統中的交易流水號。最長64位。 | 2016081121001004630200142207 |
total_amount | Price | 是 | 9 | 該筆訂單的資金總額,單位爲RMB-Yuan。取值範圍爲[0.01,100000000.00],精確到小數點後兩位。 | 9.00 |
seller_id | String | 是 | 16 | 收款支付寶帳號對應的支付寶惟一用戶號。 以2088開頭的純16位數字 | 2088111111116894 |
2.邏輯編寫
<div class="container"> <div class="top-bar"> <div class="nav-bar"> <h3 class="page-title">支付完成</h3> <a class="nav-btn fl" href="/my.html"><span><i class="fa fa-angle-left fa-2x"></i></span></a> </div> </div> <div class="orders-con"> <p style="font-size: 20px;margin: auto">支付已完成</p> <a href="orders.html" style="font-size: 18px">返回到個人訂單頁</a> </div> <div class="footer"> <p><span><i class="fa fa-copyright"></i></span>愛家租房 享受家的舒適</p> </div> </div>
return_url="http://127.0.0.1:5000/payComplete.html"
# /api_v1.0/order/payment @api.route("/order/payment", methods=["PUT"]) def save_order_payment_result(): """保存訂單支付結果""" pass
alipay_dict = request.form.to_dict()
alipay_sign = alipay_dict.pop("sign")
# 獲取應用私鑰 app_private_key_path = os.path.join(os.path.dirname(__file__), "keys/app_private_key.pem") app_private_key_string = open(app_private_key_path).read() # 獲取支付寶公鑰 alipay_public_key_path = os.path.join(os.path.dirname(__file__), "keys/alipay_public_key.pem") alipay_public_key_string = open(alipay_public_key_path).read()
app_client = AliPay( appid="2016092400589177", # 沙箱的appid 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 )
result = app_client.verify(alipay_dict, alipay_sign)
if result: # 獲取請求中的參數 order_id = alipay_dict.get("out_trade_no") # 訂單號 trade_no = alipay_dict.get("trade_no") # 支付寶的流水號 try: # 查詢並修改該訂單的狀態以及在支付寶中的交易流水號 Order.query.filter_by(id=order_id).update({"status": "WAIT_COMMENT", "trade_no": trade_no}) db.session.commit() except Exception as e: current_app.logger.error(e) db.session.rollback() return jsonify(errno=RET.OK, errmsg="OK")
3.更新數據庫ih_order_info表字段,增長trade_no字段
說明:由於當初在建立數據庫時,未設置訂單對應的支付寶交易流水號的字段,因此這裏進行一個更新
trade_no = db.Column(db.String(128)) # 支付寶交易流水號
4.在payComplete.html中編寫js代碼,向後端/api/v1.0/order/payment接口發送請求,並攜帶支付寶支付成功返回的參數
<script type="text/javascript"> function getCookie(name) { var r = document.cookie.match("\\b" + name + "=([^;]*)\\b"); return r ? r[1] : undefined; } // 獲取支付寶返回的url中的參數,並經過substr方法從去掉第一個元素?,由於返回的url參數是以鍵值對方式進行構造的,因此這裏是以請求體數據進行發送給後端接口 var alipayData = document.location.search.substr(1); $.ajax({ url: "/api/v1.0/order/payment", type: "put", data: alipayData, headers: { "X-CSRFToken": getCookie("csrf_token") } }) </script>
1.運行項目,清除頁面緩存,刷新網頁,進入個人訂單(左圖),由於前面測試支付時,對訂單編號爲5的訂單已經支付成功,因此對應的在支付寶後臺中已經造成了此訂單編號爲5的交易號,因此這裏需從數據庫中將該訂單的編號進行修改,這裏修改成100(右圖)
update ih_order_info set id= 100 where id = 5;
2.而後將訂單編號爲100的訂單進行支付(左圖),點擊確認付款後,支付寶顯示成功後,則跳轉到payComplete.html頁面,在此頁面中點擊返回個人訂單頁,此訂單狀態爲發表評價(右圖),按理說當訂單支付成功後,該訂單狀態顯示爲已支付,等待用戶退房或者完成住宿後,纔會出現待評價,這個邏輯被直接省掉了,在此項目中用戶一旦支付成功則該訂單顯示發表評價
3.第一次使用支付寶支付接口的朋友們,通常不知道支付寶會收取手續費的,那麼博主就帶你們看看支付寶的手續費是多少
1.對訂單編號爲100的訂單(左圖),點擊發表評論按鈕,彈出評論框(右圖)
2.點擊肯定按鈕後,該訂單的狀態變成已完成,顯示客戶評論
3.查看數據庫房屋信息表ih_user_info,訂單量order_count值從0變成1,代碼邏輯當訂單狀態變成已完成則order_count加1
1.解決csrf_token缺失的bug,INFO csrf.py:251 The CSRF token is missing.,在用戶進行退出時,不將session數據所有清除,須要將csrf_token的數據保存到session中
# 在清除session數據時,先從session中獲取csrf_token的值 csrf_token = session.get("csrf_token") session.clear() # 當session數據清除完後 再設置session中的csrf_token的值,這樣能夠解決csrf_token缺失的bug session["csrf_token"] = csrf_token
2.數據庫優化:
a. 表結構設計 擴展 查詢的快慢
三範式 https://www.zhihu.com/question/24696366
設計的時候就考慮可能會用到的查詢,爲方便查詢而設計,好比用空間換時間,適當增長冗餘字段節省查詢開銷
b. 建索引 主鍵 惟一(unique) 索引(key index) (外鍵)
http://www.jianshu.com/p/2b541c028157
提高 查詢速度 複合索引 where k1 k2 k3 k4
下降 增刪改
c. sql語句優化
使用索引 注意關鍵字順序 最左原則 where
不要select *
能使用聯合查詢,不使用嵌套(子查詢)
select from tbl_a a inner join tbl_b b on a.field=b.filed where b.=
select from tbl_a where filed=(select field from tbl_b where b.=)
能不使用聯合查詢,儘可能不用聯合查詢
外鍵 cascade 級聯 (維護外鍵有額外開銷,影響性能) 數據量大的時候,再也不使用外鍵
使用分析工具分析效率低的sql語句 慢查詢工具
https://flyerboy.github.io/2016/12/23/mysql_slow/
https://yemengying.com/2016/05/24/mysql-tuning/
d. 緩存
redis memcached
e. 讀寫分離
主從熱備份 主(寫 增刪改) 從(查)
f. 分庫分表 水平分庫分表
http://www.infoq.com/cn/articles/key-steps-and-likely-problems-of-split-table