<noframes id="7xbfr"><pre id="7xbfr"><output id="7xbfr"></output></pre>

      <big id="7xbfr"><font id="7xbfr"><listing id="7xbfr"></listing></font></big>
        <p id="7xbfr"></p>
        <menuitem id="7xbfr"></menuitem>

          <video id="7xbfr"><mark id="7xbfr"><listing id="7xbfr"></listing></mark></video>
            <form id="7xbfr"></form>

          <delect id="7xbfr"><var id="7xbfr"></var></delect>

          django支付寶支付流程

          時間:2022-05-23 18:02:37 類型:python
          字號:    

          一. 為什么使用第三方支付 

            在沒有第三方支付平臺之前,用戶發起支付請求的時候,用戶要去和銀行簽約(轉賬),特別的不方便,銀行對我們這些小客戶愛答不理,為了解決這些問題,就有了三方支付,三方平臺去完成簽約,給用戶節省時間

          二. 支付寶支付流程

            商戶拿到支付寶的公鑰、自己的私鑰(私鑰加密、公鑰解密),用私鑰請求支付寶,支付寶解密、驗簽、進行支付處理,支付寶將處理的返回值傳給商戶,當支付成功后,返還給商戶訂單號、金額、時間戳等消息,支付失敗后同樣給商戶反饋結果

          三. 配置流程

              1, 登錄阿里支付開放平臺 https://open.alipay.com/

              2,  進入沙箱 

            https://open.alipay.com/develop/sandbox/app

            線上環境需要創建應用,因為我們不是企業,沒有資質,所以只能申請沙箱環境

            簡單來講沙箱環境就是給開發者使用的測試環境

              3, 得到APPID 并 使用ali工具生成應用公鑰和私鑰

                  生成工具下載地址: https://opendocs.alipay.com/common/02kipl

                  下載安裝

                   

          1.jpg

                             2.jpg

                           拷貝應用公鑰中的內容到 沙箱,生成支付寶公鑰

                        

          3.jpg

                                4.jpg

                     強調: 這里的支付寶公鑰才是后續我們要用的信息,否則會驗證簽名不通過

              

            4. 現在已經有了需要的支付寶公鑰, 開始我們的代碼之路

                     新建Django項目

                     

            pip install python-alipay-sdk --upgrade #安裝支付寶開源框架
            pip install PyCryptodome #加密使用

                 5. 項目下建立tools/ali包

                     5.jpg

                    alipay.py文件內容

          from datetime import datetime
          from Crypto.PublicKey import RSA
          from Crypto.Signature import PKCS1_v1_5
          from Crypto.Hash import SHA256
          from urllib.parse import quote_plus
          from urllib.parse import urlparse, parse_qs
          from base64 import decodebytes, encodebytes
          import json
          
          
          class AliPay(object):
              """
              支付寶支付接口(PC端支付接口)
              """
          
              def __init__(self, appid, app_notify_url, app_private_key_path,
                           alipay_public_key_path, return_url, debug=False):
                  self.appid = appid
                  self.app_notify_url = app_notify_url
                  self.app_private_key_path = app_private_key_path
                  self.app_private_key = None
                  self.return_url = return_url
                  with open(self.app_private_key_path) as fp:
                      self.app_private_key = RSA.importKey(fp.read())
                  self.alipay_public_key_path = alipay_public_key_path
                  with open(self.alipay_public_key_path) as fp:
                      self.alipay_public_key = RSA.importKey(fp.read())
          
                  if debug is True:
                      self.__gateway = "https://openapi.alipaydev.com/gateway.do"
                  else:
                      self.__gateway = "https://openapi.alipay.com/gateway.do"
          
              def direct_pay(self, subject, out_trade_no, total_amount, return_url=None, **kwargs):
                  biz_content = {
                      "subject": subject,
                      "out_trade_no": out_trade_no,
                      "total_amount": total_amount,
                      "product_code": "FAST_INSTANT_TRADE_PAY",
                      # "qr_pay_mode":4
                  }
          
                  biz_content.update(kwargs)
                  data = self.build_body("alipay.trade.page.pay", biz_content, self.return_url)
                  return self.sign_data(data)
          
              def build_body(self, method, biz_content, return_url=None):
                  data = {
                      "app_id": self.appid,
                      "method": method,
                      "charset": "utf-8",
                      "sign_type": "RSA2",
                      "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                      "version": "1.0",
                      "biz_content": biz_content
                  }
          
                  if return_url is not None:
                      data["notify_url"] = self.app_notify_url
                      data["return_url"] = self.return_url
          
                  return data
          
              def sign_data(self, data):
                  data.pop("sign", None)
                  # 排序后的字符串
                  unsigned_items = self.ordered_data(data)
                  unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in unsigned_items)
                  sign = self.sign(unsigned_string.encode("utf-8"))
                  # ordered_items = self.ordered_data(data)
                  quoted_string = "&".join("{0}={1}".format(k, quote_plus(v)) for k, v in unsigned_items)
          
                  # 獲得最終的訂單信息字符串
                  signed_string = quoted_string + "&sign=" + quote_plus(sign)
                  return signed_string
          
              def ordered_data(self, data):
                  complex_keys = []
                  for key, value in data.items():
                      if isinstance(value, dict):
                          complex_keys.append(key)
          
                          # 將字典類型的數據dump出來
                  for key in complex_keys:
                      data[key] = json.dumps(data[key], separators=(',', ':'))
          
                  return sorted([(k, v) for k, v in data.items()])
          
              def sign(self, unsigned_string):
                  # 開始計算簽名
                  key = self.app_private_key
                  signer = PKCS1_v1_5.new(key)
                  signature = signer.sign(SHA256.new(unsigned_string))
                  # base64 編碼,轉換為unicode表示并移除回車
                  sign = encodebytes(signature).decode("utf8").replace("\n", "")
                  return sign
          
              def _verify(self, raw_content, signature):
                  # 開始計算簽名
                  key = self.alipay_public_key
                  signer = PKCS1_v1_5.new(key)
                  digest = SHA256.new()
                  digest.update(raw_content.encode("utf8"))
                  if signer.verify(digest, decodebytes(signature.encode("utf8"))):
                      return True
                  return False
          
              def verify(self, data, signature):
                  if "sign_type" in data:
                      sign_type = data.pop("sign_type")
                      # 排序后的字符串
                  unsigned_items = self.ordered_data(data)
                  message = "&".join(u"{}={}".format(k, v) for k, v in unsigned_items)
                  return self._verify(message, signature)

           aliobject.py文件內容

          # 導入支付基類
          from tools.ali.alipay import AliPay
          import os
          
          
          # 初始化阿里支付對象
          def get_ali_object():
              # 沙箱環境地址:https://openhome.alipay.com/platform/appDaily.htm?tab=info
              app_id = "2016092100559133"  # APPID (沙箱應用)
              # 支付完成后,支付偷偷向這里地址發送一個post請求,識別公網IP,如果是 192.168.20.13局域網IP ,支付寶找不到,def page2() 接收不到這個請求
              notify_url = "http://534p89j219.zicp.vip/pay/alipay/notify/"
              # 支付完成后,跳轉的地址。
              return_url = "http://534p89j219.zicp.vip/pay/alipay/notify/"
          
              #寫入定義的公鑰密鑰
              merchant_private_key_path = os.path.join(os.path.dirname(__file__),"merchant_private_key.txt")  # 應用私鑰
              #用工具生成的私鑰
              alipay_public_key_path = os.path.join(os.path.dirname(__file__), "alipay_public_key.txt")  # 支付寶公鑰
              #通過工具生成的公鑰到支付寶沙箱然后生成的 支付寶公鑰 (強調: 是支付寶公鑰, 不是應用公鑰)
              alipay = AliPay(
                  appid=app_id,
                  app_notify_url=notify_url,
                  return_url=return_url,
                  app_private_key_path=merchant_private_key_path,
                  alipay_public_key_path=alipay_public_key_path,  # 支付寶的公鑰,驗證支付寶回傳消息使用,不是你自己的公鑰
                  debug=True,  # 默認False,
              )
              return alipay

                     以上內容中,注意appid的配置

             建立:alipay_public_key.txty文件  拷貝支付寶公鑰內容(強調是支付寶公鑰,不是應用公鑰)

                       建立:merchant_private_key.txt   拷貝應用公鑰內容

                         注意內容前后加 begin和end:如下

                       6.jpg7.jpg



            

              生成訂單向支付寶發送請求,及支付寶異步,同步通知頁面:

             建立alipay包及pay.py文件

             8.jpg

             pay.py內容如下:

          from django.shortcuts import redirect,render,HttpResponse
          from django.views.decorators.csrf import csrf_exempt # 在對就的函數上加上@csrf_exempt,免除csrf校驗
          
          from tools.ali.alipayobject import get_ali_object
          import time
          
          #生成訂單并發送請求
          def buy(request):  
              if request.method == "GET":
                  alipay = get_ali_object()
                  # 生成支付的url
                  query_params = alipay.direct_pay(
                      subject="帥氣的西服",  # 商品簡單描述
                      out_trade_no='yt' + str(time.time()),  # 用戶購買的商品訂單號(每次不一樣) 20180301073422891
                      total_amount=888,  # 交易金額(單位: 元 保留倆位小數)
                  )
                  #實際代碼應該是根據頁面選擇的產品,得到標題,價格及訂單號
                  #把 訂單信息存儲到數據庫中, 比如 訂單名稱,數量,價格,產品id, 訂單號, 生成日期, 支付狀態(待支付)等
                  pay_url = "https://openapi.alipaydev.com/gateway.do?{0}".format(query_params)  # 支付寶網關地址(沙箱應用)
          
                  return redirect(pay_url)
                  return HttpResponse(pay_url)
          
          
          @csrf_exempt
          def notify(request):
              if request.method == "GET":  #同步通知
                 data = request.GET.dict()
                 print("同步",data)
                 signature = data.pop("sign", None)
                 alipay = get_ali_object()
                 success = alipay.verify(data, signature)  # 驗證簽名
                 #跳轉到希望用戶看到的指定頁面
                 return HttpResponse("同步success")
              elif request.method == "POST": #異步通知
                  data = request.POST.dict()  #支付寶返回的訂單信息
                  signature = data.pop("sign",None)
                  alipay = get_ali_object()
                  success = alipay.verify(data, signature) #驗證簽名
                  # demo  先驗證, 簽名,狀態,金額,商家 appid等, 沒有問題,更新數據庫訂單狀態,再返回success
                 # print(success)
                  if success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED" ):
                      out_trade_no = data.get("out_trade_no")  #商家訂單號  唯一
                      #根據訂單號修改該訂單支付狀態
                      trade_no = data.get("trade_no")  # 支付寶返回的支付寶訂單 退款時用
                      #更多判斷看https://opendocs.alipay.com/open/270/105902 異步返回結果的驗簽
                  return HttpResponse("success") #返回success,不再通知,否則會不斷重復通知

          配置項目下的urls.py

          path('pay/alipay/', include("alipay.urls"))

          tools包下增加urls.py內容如下:

          from django.urls import path
          from . import pay
          urlpatterns = [
              path('buy/', pay.buy),
              path('notify/', pay.notify),
          ]

          因為本地無法返回支付寶信息,這里我使用 花生殼軟件 映射一個公共地址

          訂單生成并請求: http://534p89j219.zicp.vip/pay/alipay/buy

          9.jpg

           然后輸入賬號,密碼,就可以支付了

           支付成功支付寶會返回異步信息到我們指定的url,在指定url我們根據接收到信息

           驗證,并更新訂單狀態

          同步跳轉后,我們跳轉到希望顯示的頁面OK

          黄网站免费 <