Django專案整合支付寶支付功能
阿新 • • 發佈:2019-01-24
在沙箱環境下除錯支付寶介面
電腦網站支付流程
接入步驟
- 建立應用
- 配置金鑰
- 搭建和配置開發環境
- 介面呼叫
1.建立應用
新建專案alipay,建立子應用payment
2.配置金鑰
生成應用的私鑰和公鑰
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
儲存應用私鑰檔案
在payment應用中新建 keys 目錄,用來儲存祕鑰檔案。
將生成的應用私鑰檔案 app_private_key.pem 複製到 payment/keys 目錄下。
將公鑰內容複製給支付寶
儲存支付寶公鑰
在 payment/keys 目錄下新建 alipay_public_key.pem 檔案,用於儲存支付寶的公鑰檔案。
將支付寶的公鑰內容複製到 alipay_public_key.pem 檔案中
注意:還需要在公鑰檔案中補充開始與結束標誌
—–BEGIN PUBLIC KEY—–
此處是公鑰內容
—–END PUBLIC KEY—–
3.搭建和配置開發環境
使用者在提交支付時,會發送GET請求,獲取支付寶的支付連結
- 請求方式:GET /orders/(?P\d+)/payment/
- 請求引數:order_id(訂單編號)
- 返回資料:alipay_url(支付寶支付連結)
在 payment/views.py 中編寫檢視
from alipay import AliPay
import os
from orders.models import OrderInfo
from payment.models import Payment
from django.conf import settings
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
# GET /orders/(?P<order_id>\d+)/payment/
class PaymentView(APIView):
""" 獲取支付連結 """
# 判斷使用者是否登入
permission_classes = [IsAuthenticated]
def get(self, request, order_id):
# 獲取引數:order_id, user
user = request.user
# 查詢訂單物件,校驗訂單資訊
try:
order = OrderInfo.objects.get(
order_id=order_id,
user=user,
status=OrderInfo.ORDER_STATUS_ENUM["UNPAID"],
pay_method=OrderInfo.PAY_METHODS_ENUM["ALIPAY"],
)
except OrderInfo.DoesNotExist:
return Response({"message": "訂單資訊有誤"}, status=status.HTTP_400_BAD_REQUEST)
# 向支付寶發起請求,獲取支付連結引數
alipay_client = AliPay(
appid=settings.ALIPAY_APPID, # 沙箱賬號的APPID
app_notify_url=None, # 預設回撥url,配置 notify_url 需要公網環境
app_private_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)), "keys/app_private_key.pem"),
alipay_public_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)), "keys/alipay_public_key.pem"), # 支付寶的公鑰,驗證支付寶回傳訊息使用,不是你自己的公鑰,
sign_type="RSA2", # RSA 或者 RSA2
debug=settings.ALIPAY_DEBUG # 預設False
)
# 電腦網站支付,需要跳轉到 https://openapi.alipay.com/gateway.do? + order_string
order_string = alipay_client.api_alipay_trade_page_pay(
out_trade_no=order_id, # 訂單編號
total_amount=str(order.total_amount), # 訂單總金額,在資料庫中是 Decimal 型別,需要轉換
subject=f"專案標題{order_id}", # 訂單標題,可以自己指定
return_url="https://blog.csdn.net/m0_37714245", # 支付成功回撥url
notify_url=None # 可選
)
# 拼接支付連結地址
alipay_url = settings.ALIPAY_URL + "?" + order_string
return Response({'alipay_url': alipay_url})
使用者在支付成功後,支付寶將使用者重定向到上一步的return_url,並攜帶了支付結果資料,有交易流水號、訂單總金額、支付寶唯一使用者編號等
此時需要將此資料傳送給後端,由後端檢驗並儲存到資料庫中
前端會發送PUT請求,將支付寶的處理結果資料作為請求引數,傳送給後端
- 請求方式:PUT /payment/status/?支付寶引數
- 請求引數:查詢字串引數,參考上面圖片
- 返回資料:trade_id(支付寶交易流水編號)
在payment/views.py中增加檢視
class PaymentStatusView(APIView):
""" 儲存支付結果 """
def put(self, request):
# 獲取查詢字串資料
# out_trade_no: 訂單號, trade_no: 交易流水編號
# total_amount: 訂單總金額 seller_id: 支付寶唯一使用者編號
alipay_request_dict = request.query_params # query_params是一個QueryDict物件
# 如果查詢字串為空,表示前端沒有將支付寶回撥時攜帶的引數傳遞過來
if not alipay_request_dict:
return Response({"message": "缺少引數"}, status=status.HTTP_400_BAD_REQUEST)
# 將QueryDict轉換成python中的字典
data = alipay_request_dict.dict()
# 用pop方法取出簽名,介面文件中推薦使用的方法
sign = data.pop("sign")
# 校驗引數,使用AliPay模組來驗證前端傳過來的資料是否真的是支付寶在回撥時攜帶的引數
alipay_client = AliPay(
appid=settings.ALIPAY_APPID, # 沙箱賬號的APPID
app_notify_url=None, # 預設回撥url
app_private_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)), "keys/app_private_key.pem"),
alipay_public_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),
"keys/alipay_public_key.pem"), # 支付寶的公鑰,驗證支付寶回傳訊息使用,不是你自己的公鑰,
sign_type="RSA2", # RSA 或者 RSA2
debug=settings.ALIPAY_DEBUG # 預設False,是否是沙箱環境
)
# verify函式返回驗證結果,True 或 False
result = alipay_client.verify(data, sign)
if result:
# 儲存支付結果資料
# out_trade_no: 訂單號, trade_no: 交易流水號
# total_amount: 訂單總金額 seller_id: 支付寶唯一使用者號
order_id = data.get("out_trade_no") # 訂單編號
trade_id = data.get("trade_no") # 交易流水號
# 將付款記錄寫入資料庫
Payment.objects.create(
order_id=order_id,
trade_id=trade_id,
)
# 修改訂單狀態
OrderInfo.objects.filter(order_id=order_id).update(status=OrderInfo.ORDER_STATUS_ENUM["UNSEND"])
# 返回 trade_id(交易流水號)
return Response({"trade_id": trade_id})
else:
# 返回引數錯誤
return Response({"message": "引數錯誤"}, status=status.HTTP_400_BAD_REQUEST)
4.配置路由測試
略
到這兒,在電腦網頁上接入支付寶–支付功能就完成了
支付寶的涵蓋的業務太廣泛,還是需要根據公司的業務需求來實現,如果這篇文章能幫到你,那真是太好了!