Django1.11配合uni-app發起微信支付的實現

    Django1.11配合uni-app發起微信支付!

    經過三天的斷斷續續的奮戰,我終于是干動了微信支付。愛掏網 - it200.com為了以后不忘記,現在來一篇教程,來來來,開干!!!

    一、準備階段

    1、準備階段我們需要去微信官網申請一個小程序或者公眾號。愛掏網 - it200.com獲得AppID和AppSecret。愛掏網 - it200.com

    2、去微信商戶平臺 成為商家,開通JSAPI用來獲得商戶號和自己配置的鑰匙。愛掏網 - it200.com然后再商戶平臺上面綁定小程序appid。愛掏網 - it200.com

    (點擊下面圖片進入官方鏈接!)

    在配置里面配置一個自己的key,需要記住后臺開發的時候需要!

    關聯后即可在小程序管理頁面開通微信支付!

    到此,準備階段完成!

    二、梳理流程

    在這里我大概寫一下流程:首先我們在前端發起微信登陸,此時微信會給我們返回一個openid,這個openid一定要留存在某一個位置。愛掏網 - it200.com然后前段發起微信支付,向后端發送數據請求,后端對結合前段的數據向微信方面發送一個請求,請求相關數據,得到相關數據之后把數據發送給前段,前段收到數據,利用微信接口再向微信指定連接發送請求,微信返回請求,即可!這個就是全流程,很多人肯定已經懵了。愛掏網 - it200.com沒事,咱一步一步來,別步子跨大了——扯到蛋了!

    以上就是數據處理階段大概流程!

    三、代碼實現

    0、用戶登錄根據用戶code獲取openid

    uni.login({
              provider: 'weixin',
              success: function(loginRes) {
                let code = loginRes.code;
                if (!_this.isCanUse) {
                  //非第一次授權獲取用戶信息
                  uni.getUserInfo({
                    provider: 'weixin',
                    success: function(infoRes) { 
                            //獲取用戶信息后向調用信息更新方法
                      _this.nickName = infoRes.userInfo.nickName; //昵稱
                      _this.avatarUrl = infoRes.userInfo.avatarUrl; //頭像
                        _this.updateUserInfo();//調用更新信息方法
                    }
                  });
                }
          
                //2.將用戶登錄code傳遞到后臺置換用戶SessionKey、OpenId等信息
                uni.request({
                  url: 'http://127.0.0.1:8000/users/',
                  data: {
                    code: code,
                  },
                  method: 'GET',
                  header: {
                    'content-type': 'application/json' 
                  },
                  success: (res) => {
                    console.log(res.data)
                    if ( res.data.state== 1001) {
                      console.log("新注冊的用戶!")
                      _this.OpenId = res.data.openid;
                    } else{
                      _this.OpenId = res.data.openid;
                      console.log("注冊過的用戶!開始設置本地緩存!")
                      console.log(res.data[0].id)
                      if ( res.data[0].id ) {
                        //這里獲得登陸狀態,然后根據登陸狀態來改變用戶按鈕信息!!!!
                      } else{
                        
                      };
                      _this.user_id = res.data[0].id
                      uni.setStorage({
                        key: 'user',
                        data: res.data,
                        success: function () {
                          console.log('設置緩存成功');
                        }
                      });
                      // _this.gotoshopping()
                      // uni.reLaunch({//信息更新成功后跳轉到小程序首頁
                      //   url: '/pages/shopping/shopping'
                      // });
                    }
                    //openId、或SessionKdy存儲//隱藏loading
                    uni.hideLoading();
                  }
                });
              },
            });
    if request.GET.get("code"):
          ret = {"state": 1000}
          code = request.GET.get("code")
    
          url = "https://api.weixin.qq.com/sns/jscode2session"
          appid = "xxxxxxxxxxxxx"
          secret = "xxxxxxxxxxxxxxxxxxxxx"
    
          # url一定要拼接,不可用傳參方式
          url = url + "?appid=" + appid + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code"
          import requests
          r = requests.get(url)
          print("======", r.json())
          openid = r.json()['openid']
          user = users.objects.filter(openid=openid).all()
          if not user:
            ret["state"] = 1001
            ret["msg"] = "用戶第一次登陸"
            ret["openid"] = openid
            return Response(ret)
          else:
            serializer = self.get_serializer(user, many=True)
            return Response(serializer.data)

    1、首先需要創建一個confige.py的配置文件!然后寫路由,讓前端找到“門”在哪里!

    config.py

    # 微信支付的配置參數
    client_appid = 'xxxxxxxxxxxxxx' # 小程序appid
    client_secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxx' # 小程序secret
    
    Mch_id = 'xxxxxxxxxxx' # 商戶號
    Mch_key = 'xxxxxxxxxxxxxxxxxxx' # 商戶Key
    order_url = 'https://api.mch.weixin.qq.com/pay/unifiedorder' # 訂單地址
    

    url.py

    router = routers.DefaultRouter()
    router.register("users", views.UsersViewSet)
    router.register("goods", views.GoodsViewSet)
    router.register("comments", views.CommentsViewSet)
    router.register("payOrder", views.OrdersViewSet) #這個就是微信支付的接口
    
    
    urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'', include(router.urls)),
    
    ]+ static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

    view.py

    class OrdersViewSet(viewsets.ModelViewSet):
      queryset = Order.objects.all()
      serializer_class = OrderModelSerializer
    
      def create(self, request, *args, **kwargs):
        if request.data.get("user_id"):
          from goods.wxpay.wxpay import payOrder
          data = payOrder(request)
          print(data)
          return Response(data)
        else:
          serializer = self.get_serializer(data=request.data)
          serializer.is_valid(raise_exception=True)
          self.perform_create(serializer)
          headers = self.get_success_headers(serializer.data)
          return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
    
      def perform_create(self, serializer):
        serializer.save()
    
      def get_success_headers(self, data):
        try:
          return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
          return {}

    2、然后創建邏輯文件,獲取數據請求數據返回數據!

    wxpay.py

    # -*- coding: utf-8 -*-
    from .config import client_appid, client_secret, Mch_id, Mch_key, order_url
    import hashlib
    import datetime
    import xml.etree.ElementTree as ET
    import requests
    from ..models import users
    
    
    # 生成簽名的函數
    def paysign(appid, body, mch_id, nonce_str, notify_url, openid, out_trade_no, spbill_create_ip, total_fee):
      ret = {
        "appid": appid,
        "body": body,
        "mch_id": mch_id,
        "nonce_str": nonce_str,
        "notify_url": notify_url,
        "openid": openid,
        "out_trade_no": out_trade_no,
        "spbill_create_ip": spbill_create_ip,
        "total_fee": total_fee,
        "trade_type": 'JSAPI'
      }
      print(ret)
      # 處理函數,對參數按照key=value的格式,并按照參數名ASCII字典序排序
      stringA = '&'.join(["{0}={1}".format(k, ret.get(k)) for k in sorted(ret)])
      stringSignTemp = '{0}&key={1}'.format(stringA, Mch_key)
      sign = hashlib.md5(stringSignTemp.encode("utf-8")).hexdigest()
      print(sign.upper())
      return sign.upper()
    
    
    # 生成隨機字符串
    def getNonceStr():
      import random
      data = "123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP"
      nonce_str = ''.join(random.sample(data, 30))
      return nonce_str
    
    
    # 生成商品訂單號
    def getWxPayOrdrID():
      date = datetime.datetime.now()
      # 根據當前系統時間來生成商品訂單號。愛掏網 - it200.com時間精確到微秒
      payOrdrID = date.strftime("%Y%m%d%H%M%S%f")
    
      return payOrdrID
    
    
    # 獲取全部參數信息,封裝成xml
    def get_bodyData(openid, client_ip, price):
      body = 'Mytest' # 商品描述
      notify_url = 'https://127.0.0.1:8000/payOrder/' # 支付成功的回調地址 可訪問 不帶參數
      nonce_str = getNonceStr() # 隨機字符串
      out_trade_no = getWxPayOrdrID() # 商戶訂單號
      total_fee = str(price) # 訂單價格 單位是 分
    
      # 獲取簽名
      sign = paysign(client_appid, body, Mch_id, nonce_str, notify_url, openid, out_trade_no, client_ip, total_fee)
    
      bodyData = ''
      bodyData += '' + client_appid + '' # 小程序ID
      bodyData += '' + body + '' # 商品描述
      bodyData += '' + Mch_id + '' # 商戶號
      bodyData += '' + nonce_str + '' # 隨機字符串
      bodyData += '' + notify_url + '' # 支付成功的回調地址
      bodyData += '' + openid + '' # 用戶標識
      bodyData += '' + out_trade_no + '' # 商戶訂單號
      bodyData += '' + client_ip + '' # 客戶端終端IP
      bodyData += '' + total_fee + '' # 總金額 單位為分
      bodyData += 'JSAPI' # 交易類型 小程序取值如下:JSAPI
      bodyData += '' + sign + ''
      bodyData += ''
    
      return bodyData
    
    
    def xml_to_dict(xml_data):
      '''
      xml to dict
      :param xml_data:
      :return:
      '''
      xml_dict = {}
      root = ET.fromstring(xml_data)
      for child in root:
        xml_dict[child.tag] = child.text
      return xml_dict
    
    
    def dict_to_xml(dict_data):
      '''
      dict to xml
      :param dict_data:
      :return:
      '''
      xml = [""]
      for k, v in dict_data.iteritems():
        xml.append("{1}{0}>".format(k, v))
      xml.append("")
      return "".join(xml)
    
    
    # 獲取返回給小程序的paySign
    def get_paysign(prepay_id, timeStamp, nonceStr):
      pay_data = {
        'appId': client_appid,
        'nonceStr': nonceStr,
        'package': "prepay_id=" + prepay_id,
        'signType': 'MD5',
        'timeStamp': timeStamp
      }
      stringA = '&'.join(["{0}={1}".format(k, pay_data.get(k)) for k in sorted(pay_data)])
      stringSignTemp = '{0}&key={1}'.format(stringA, Mch_key)
      sign = hashlib.md5(stringSignTemp.encode("utf-8")).hexdigest()
      return sign.upper()
    
    
    # 統一下單支付接口
    def payOrder(request):
      import time
      # 獲取價格,和用戶是誰
      price = request.data.get("price")
      user_id = request.data.get("user_id")
    
      # 獲取客戶端ip
      client_ip, port = request.get_host().split(":")
    
      # 獲取小程序openid
      openid = users.objects.get(id=user_id).openid
    
      # 請求微信的url
      url = order_url
    
      # 拿到封裝好的xml數據
      body_data = get_bodyData(openid, client_ip, price)
    
      # 獲取時間戳
      timeStamp = str(int(time.time()))
    
      # 請求微信接口下單
      respOne= requests.post(url, body_data.encode("utf-8"), headers={'Content-Type': 'application/xml'})
    
      # 回復數據為xml,將其轉為字典
      cOntent= xml_to_dict(respone.content)
      print(content)
      # 返回給調用函數的數據
      ret = {"state": 1000}
      if content["return_code"] == 'SUCCESS':
        # 獲取預支付交易會話標識
        prepay_id = content.get("prepay_id")
        # 獲取隨機字符串
        nOnceStr= content.get("nonce_str")
    
        # 獲取paySign簽名,這個需要我們根據拿到的prepay_id和nonceStr進行計算簽名
        paySign = get_paysign(prepay_id, timeStamp, nonceStr)
    
        # 封裝返回給前端的數據
        data = {"prepay_id": prepay_id, "nonceStr": nonceStr, "paySign": paySign, "timeStamp": timeStamp}
        print('=========',data)
    
        ret["msg"] = "成功"
        return data
    
      else:
        ret["state"] = 1001
        ret["msg"] = "失敗"
        return ret

    3、前段獲取后端返回的數據給微信再次發送數據請求!(包含點擊的時候往后端發送數據處理請求)

    pay(){
            uni.request({
              url: 'http://127.0.0.1:8000/payOrder/',
              method: 'POST',
              header: {
                'content-type': 'application/json'
              },
              data: {
                user_id:this.user_id,
                price:128
              },
              success: res => {
                console.log("success")
                console.log(res.data)
                
                uni.requestPayment({
                provider: 'wxpay',
                
                timeStamp: res.data.timeStamp,
                nonceStr: res.data.nonceStr,
                package: 'prepay_id='+String(res.data.prepay_id),
                signType: 'MD5',
                paySign: res.data.paySign,
                
                success: function (res) {
                  console.log('success:' + JSON.stringify(res));
                  // 支付成功,給后臺發送數據,保存訂單
                  
                },
                fail: function (err) {
                  console.log('fail:' + JSON.stringify(err));
                  // 支付失敗,給后臺發送數據,保存訂單
                }
                });
    
                
                
              },
              fail: (res) => {
                console.log("fail")
                console.log(res)
              },
              complete: () => {}
            });
            
            
          }

    至此相信大家也就會了。愛掏網 - it200.com

    附上我的目錄結構

    以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持。愛掏網 - it200.com


    聲明:所有內容來自互聯網搜索結果,不保證100%準確性,僅供參考。如若本站內容侵犯了原著者的合法權益,可聯系我們進行處理。
    發表評論
    更多 網友評論0 條評論)
    暫無評論

    返回頂部

    主站蜘蛛池模板: 亚洲综合在线成人一区| 亚洲一区在线观看视频| 久久久久人妻精品一区| 狠狠做深爱婷婷久久综合一区| 一区二区三区日韩精品| 日韩一区二区在线免费观看| 无码国产精品一区二区免费16| 中文字幕日本一区| 日韩一区二区三区视频| 国产伦精品一区二区三区精品 | 国产免费一区二区三区VR| 亚洲AV无码一区二区三区性色 | 精品人妻一区二区三区毛片| 一本一道波多野结衣一区| 综合无码一区二区三区四区五区| 国产麻豆精品一区二区三区v视界| 国产成人高清精品一区二区三区| 天堂不卡一区二区视频在线观看| 日韩一区二区三区免费播放| 亚洲av区一区二区三| 日韩AV在线不卡一区二区三区 | 精品人妻无码一区二区三区蜜桃一| 亚拍精品一区二区三区| 精品一区精品二区制服| 无码人妻精品一区二区蜜桃 | 亚洲国产精品一区二区三区久久 | 亚洲av无码一区二区三区观看| 久久精品国产一区二区三| 亚洲不卡av不卡一区二区| 无码日韩精品一区二区免费暖暖| 无码一区二区三区在线观看| 成人免费观看一区二区| 国产午夜一区二区在线观看| 精品视频一区在线观看| 久久免费视频一区| 亚洲国产福利精品一区二区| 国产精品无码一区二区三区不卡| 视频一区二区在线播放| 久久久久一区二区三区| 日本一区二区视频| 一区二区高清在线观看|