中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

django中使用事務及接入支付寶支付功能

發布時間:2020-09-09 19:15:30 來源:腳本之家 閱讀:157 作者:麥葉 欄目:開發技術

之前一直想記錄一下在項目中使用到的事務以及支付寶支付功能,自己一直犯懶沒有完,趁今天有點興致,在這記錄一下。

商城項目必備的就是支付訂單的功能,所以就會涉及到訂單的保存以及支付接口的引入。先來看看訂單的保存,在數據庫模型涉及之初,將訂單分成了兩個表,一個為訂單表,記錄訂單的基本信息,如訂單號,用戶信息,運費之類,一個為訂單商品表,記錄該訂單中的商品信息。在保存訂單時,肯定會涉及到兩個表的新建和保存,其實還有一張表也需要進行一些修改,那就是商品表,當一個訂單保存成功,意味著本次交易成功,商品售出,商品的庫存應該進行修改。所以,在保存訂單這一操作中,涉及到的表有三張。所以在保存訂單時,多表數據的修改,要嘛同時成功,要嘛同時失敗,這就跟數據庫中的事務很像,因此,在這里引入事務,來完成訂單保存的功能。

在Django中可以通過 django.db.transaction 模塊提供的 atomic 來定義一個事務, atomic 提供兩種用法,一種是裝飾器,一種是with語句。

from django.db import transaction
@transaction.atomic
def viewfunc(request):
  # 這些代碼會在一個事務中執行
  ...
from django.db import transaction
def viewfunc(request):
  # 這部分代碼不在事務中,會被Django自動提交
  ...
  with transaction.atomic():
    # 這部分代碼會在事務中執行
    ...  

   

在Django中,還提供了保存點的支持,可以在事務中創建保存點來記錄數據的特定狀態,數據庫出現錯誤時,可以恢復到數據保存點的狀態

from django.db import transaction
# 創建保存點
save_id = transaction.savepoint() 
# 回滾到保存點
transaction.savepoint_rollback(save_id)
# 提交從保存點到當前狀態的所有數據庫事務操作
transaction.savepoint_commit(save_id)

所以,可以在序列化器的create方法中,創建一個事務,還進行數據的修改保存還有新建,若有地方出錯,則直接回滾,若沒有問題則提交事務。代碼如下

   

def create(self, validated_data): """ 保存訂單 """ # 獲取當前下單用戶 user = self.context['request'].user # 組織訂單編號 20170903153611+user.id # timezone.now() -> datetime order_id = timezone.now().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id) address = validated_data['address'] pay_method = validated_data['pay_method'] # 生成訂單 with transaction.atomic(): # 創建一個保存點 save_id = transaction.savepoint() try: # 創建訂單信息 order = OrderInfo.objects.create( order_id=order_id, user=user, address=address, total_count=0, total_amount=Decimal(0), freight=Decimal(10), pay_method=pay_method, status=OrderInfo.ORDER_STATUS_ENUM['UNSEND'] if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH'] else OrderInfo.ORDER_STATUS_ENUM['UNPAID'] ) # 獲取購物車信息 redis_conn = get_redis_connection("cart") redis_cart = redis_conn.hgetall("cart_%s" % user.id) cart_selected = redis_conn.smembers('cart_selected_%s' % user.id) # 將bytes類型轉換為int類型 cart = {} for sku_id in cart_selected: cart[int(sku_id)] = int(redis_cart[sku_id]) # # 一次查詢出所有商品數據 # skus = SKU.objects.filter(id__in=cart.keys()) # 處理訂單商品 sku_id_list = cart.keys() for sku_id in sku_id_list: while True: sku = SKU.objects.get(id=sku_id) sku_count = cart[sku.id] # 判斷庫存 origin_stock = sku.stock # 原始庫存 origin_sales = sku.sales # 原始銷量 if sku_count > origin_stock: transaction.savepoint_rollback(save_id) raise serializers.ValidationError('商品庫存不足') # 用于演示并發下單 # import time # time.sleep(5) # 減少庫存 # sku.stock -= sku_count # sku.sales += sku_count # sku.save() new_stock = origin_stock - sku_count new_sales = origin_sales + sku_count # 根據原始庫存條件更新,返回更新的條目數,樂觀鎖 ret = SKU.objects.filter(id=sku.id, stock=origin_stock).update(stock=new_stock, sales=new_sales) if ret == 0: continue # 累計商品的SPU 銷量信息 sku.goods.sales += sku_count sku.goods.save() # 累計訂單基本信息的數據 order.total_count += sku_count # 累計總金額 order.total_amount += (sku.price * sku_count) # 累計總額 # 保存訂單商品 OrderGoods.objects.create( order=order, sku=sku, count=sku_count, price=sku.price, ) # 更新成功 break # 更新訂單的金額數量信息 order.total_amount += order.freight order.save() except serializers.ValidationError: raise except Exception as e: logger.error(e) transaction.savepoint_rollback(save_id) raise # 提交事務 transaction.savepoint_commit(save_id) # 更新redis中保存的購物車數據 pl = redis_conn.pipeline() pl.hdel('cart_%s' % user.id, *cart_selected) pl.srem('cart_selected_%s' % user.id, *cart_selected) pl.execute() return order

還有一點需要注意的是,當訂單提交,購物車中相應的商品應該進行刪除。好了,以上就是django中的事務。

再來說說支付寶支付功能的引入,現在基本上所有的項目涉及到支付功能時都會引入第三方支付,其中使用最廣泛的應該就是支付寶和微信了,這里我使用的是支付寶支付。當訂單創建完成,接下來就是支付了。

先來縷一下流程,用戶點擊按鈕請求支付寶支付界面,先進行登錄,登錄成功后進行支付操作,支付成功會進行回調。

首先第一步,用戶點擊按鈕,后端會進行url的拼接,將拼接好的url返給前端,前端進行跳轉,跳轉到支付寶相關界面,用戶進行登錄和支付等操作。

查看pythonsdk,首先我們可以通過openssl命令生成一個密鑰(公鑰和私鑰),私鑰自己留存,公鑰用戶校驗。命令如下:

openssl

OpenSSL> genrsa -out app_private_key.pem  2048 # 私鑰 OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem # 導出公鑰 OpenSSL> exit

同時,你要從支付寶獲得一個公鑰字符串,格式可參考:https://github.com/fzlee/alipay/blob/master/tests/certs/ali/ali_public_key.pem

由于上面我們用的是RSA生成的密鑰,所以在支付寶中我們也需要RSA的公鑰

django中使用事務及接入支付寶支付功能

設置好了密鑰,我們就可以開始寫視圖,代碼如下:

class PaymentView(APIView):
  """
  支付
  """
  permission_classes = (IsAuthenticated,)
  def get(self, request, order_id):
    """
    獲取支付鏈接
    """
    # 判斷訂單信息是否正確
    try:
      order = OrderInfo.objects.get(order_id=order_id, user=request.user,
                     pay_method=OrderInfo.PAY_METHODS_ENUM["ALIPAY"],
                     status=OrderInfo.ORDER_STATUS_ENUM["UNPAID"])
    except OrderInfo.DoesNotExist:
      return Response({'message': '訂單信息有誤'}, status=status.HTTP_400_BAD_REQUEST)
    # 構造支付寶支付鏈接地址
    alipay = AliPay(
      appid=settings.ALIPAY_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
    )
    order_string = alipay.api_alipay_trade_page_pay(
      out_trade_no=order_id,
      total_amount=str(order.total_amount),
      subject="美多商城%s" % order_id,
      return_url="http://www.meiduo.site:8080/pay_success.html", 
    )
    # 需要跳轉到https://openapi.alipay.com/gateway.do? + order_string
    # 拼接鏈接返回前端
    alipay_url = settings.ALIPAY_URL + "?" + order_string
    return Response({'alipay_url': alipay_url})

相關的參數可以提前在配置文件中配置好(ALPAY_APPID,ALPAY_URL,ALPAY_DEBUG)注意ALPAY為True時才啟用沙箱環境。當用戶支付成功,會對你填寫的回調網址進行回調,返回的參數如下圖。

django中使用事務及接入支付寶支付功能 

前端頁面將此數據發送給后端,后端檢驗并保存支付結果。以上就是全部過程。具體的過程可以參考pythonsdk。

總結

以上所述是小編給大家介紹的django中使用事務及接入支付寶支付功能,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復大家的!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

黄梅县| 社会| 颍上县| 都兰县| 台东市| 木兰县| 建平县| 财经| 毕节市| 壤塘县| 昌乐县| 常德市| 柘荣县| 新竹市| 莲花县| 象州县| 玉龙| 阳原县| 安泽县| 宜章县| 赫章县| 雷波县| 绥德县| 苗栗市| 桃园县| 红原县| 自治县| 井研县| 冷水江市| 阜阳市| 白沙| 仁化县| 苏州市| 仁怀市| 西乌珠穆沁旗| 泾阳县| 南昌县| 前郭尔| 海南省| 克什克腾旗| 北京市|