小程序的支付功能實現


小程序支付功能

詳細流程步驟請看官方文檔:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=3

xcx.wxml

<button bindtap="pay">支付</button>

xcx.js

const app=getApp()
pay: function () {
    wx.request({
      url: app.globalData.URL + 'pay/',
      data: {
        token: wx.getStorageSync("token")
      },
      header: {
        "content-type": "application/json"
      },
      method: "POST",
      success: function (e) {
        console.log("pay_data", e)
        wx.requestPayment(
          {
            'timeStamp': e.data.data.timeStamp,
            'nonceStr': e.data.data.nonceStr,
            'package': e.data.data.package,
            'signType': 'MD5',
            'paySign': e.data.data.paySign,
            'success': function (res) {
              console.log("支付成功", res)
            },
            'fail': function (res) {
              console.log("支付失敗", res)
            }
          })
      }
    })
  }

app.js

globalData: {
    userInfo: null,
    URL:"http://127.0.0.1:8000/",
  }

后台業務(重點)

urls.py

from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
    #path('admin/', admin.site.urls),
    #path('login/', views.LoginAPIView.as_view()),
    #path('userinfo/', views.UserInfo.as_view()),
    path('pay/', views.Pay.as_view()),
]

app01/wx/settings.py

# 小程序 appid
AppId="wx10658d6b326fd700"

# 小程序 appsecret
AppSecret="43cae8cf58c13b2323afef1f8d3c054b"

# 調用的微信后端接口
code2Session="https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code"

# 商戶號
pay_mchid ='1415981402'
pay_apikey = 'xi34nu5jn7x2uujd8u4jiijd2u5d6j8e'

views.py---(由於商戶號(mch_id)及pay_apikey需要申請或公司提供,所有本段代碼無法本地運行驗證)

class Pay(APIView):
    def post(self, request):
        # print(111111)
        param = request.data
        # 獲取前台傳入的token
        if param.get("token"):
            # 檢驗token 拿到緩存數據庫中的 session_key與openid做綁定得到的 val
            cache_data = cache.get(param.get("token"))
            if cache_data:
                # 獲取客戶端ip,如果是負載均衡,就用HTTP_X_FORWARDED_FOR,如果不是就用下面的		
                # 通過 requests.META接口 向微信后端 獲取參數 ip
                if request.META.get('HTTP_X_FORWARDED_FOR'):
                    self.ip = request.META['HTTP_X_FORWARDED_FOR']
                else:
                    self.ip = request.META['REMOTE_ADDR']
                session_key, self.openid = cache_data.split("&")
                # 獲取所有返回參數 重點就是(prepay_id)
                data = self.get_pay_data()
                return Response({"code": 200, "msg": "suc", "data": data})
            else:
                return Response({"code": 202, "msg": "token無效"})
	# 獲取參數nonce_str 隨機字符串
    def get_nonce_str(self, num=30):
        # strs = ""
        # for i in range(30):
        #     strs += str(random.randint(0,9))  產生結果是一個列表
        all_str = "0123456789abcdefghijklmnopqrstuvwxyz"
        # 將列表內的所有字符串以''拼接得到一個字符串
        strs = "".join(random.sample(all_str, num)) 
        return strs
	# 獲取參數out_trade_no
    def get_out_trade_no(self):
        import time
        strs = str(int(time.time())) + self.get_nonce_str(5)
        return strs
	# 獲取參數 簽名 sign
    def get_sign(self):
        data_dic = {
            "nonce_str": self.nonce_str,
            "out_trade_no": self.out_trade_no,
            "spbill_create_ip": self.ip,
            "notify_url": self.notify_url,
            "openid": self.openid,
            "body": self.body,
            "trade_type": "JSAPI",
            "sign_type": "MD5",
            "appid": self.appid,
            "total_fee": self.total_fee,
            "mch_id": self.mch_id
        }
        # 對數據進行排序(sorted)並拼接成需求格式
        # sorted 是對 字典中的 key排序 key1, key2, key3, ...
        str_a = "&".join([f"{i}={data_dic[i]}" for i in sorted(data_dic)])
        str_b = f"{str_a}&key={settings.pay_apikey}"
        md5 = hashlib.md5()
        md5.update(str_b.encode("utf8"))
        return md5.hexdigest().upper()
	# 將 xml 數據轉換成 字典
    def xml_to_dic(self, xml_data):
        # 導入 xml 
        import xml.etree.ElementTree as ET
        xml_data = ET.fromstring(xml_data)
        dic = {}
        for child in xml_data:
            dic[child.tag] = child.text
        return dic
	# 獲取 prepay_id
    def get_prepay_data(self):
        url = "https://api.mch.weixin.qq.com/pay/unifiedorder"
        response = requests.post(url=url, data=self.body_data.encode("utf8"),
        headers={"content-type": "application/xml"})
        xml_data = response.content
        dic_data = self.xml_to_dic(xml_data)
        return dic_data
	# 二次簽名 
    def get_second_sign(self):
        self.second_nonceStr = self.get_nonce_str()
        self.timeStamp = str(int(time.time()))
        data_dic = {
            "appId": settings.AppId,
            "timeStamp": self.timeStamp,
            "nonceStr": self.second_nonceStr,
            "package": f"prepay_id={self.prepay_data.get('prepay_id')}",
            "signType": "MD5"
        }
        print(data_dic)
        str_a = "&".join([f"{i}={data_dic[i]}" for i in sorted(data_dic)])
        str_b = f"{str_a}&key={settings.pay_apikey}"
        md5 = hashlib.md5()
        md5.update(str_b.encode("utf8"))
        return md5.hexdigest().upper()
	# 支付功能 ,返回數據 data
    def get_pay_data(self):
        self.appid = settings.AppId
        self.mch_id = settings.pay_mchid
        self.nonce_str = self.get_nonce_str()
        self.sign_type = "MD5"
        self.body = "py11最難一屆"
        self.out_trade_no = self.get_out_trade_no()
        self.total_fee = 1
        self.spbill_create_ip = self.ip
        self.notify_url = "http://www.weixin.qq.com/wxpay/pay.php"
        self.trade_type = "JSAPI"
        self.sign = self.get_sign()
        self.body_data = f"""
                <xml>
                <appid>{self.appid}</appid>
                <mch_id>{self.mch_id}</mch_id>
                <nonce_str>{self.nonce_str}</nonce_str>
                <sign>{self.sign}</sign>
                <body>{self.body}</body>
                <out_trade_no>{self.out_trade_no}</out_trade_no>
                <total_fee>1</total_fee>
                <sign_type>MD5</sign_type>
                <spbill_create_ip>{ self.spbill_create_ip}</spbill_create_ip>
                <notify_url>{self.notify_url}</notify_url>
                <openid>{self.openid}</openid>
                <trade_type>JSAPI</trade_type> 
                </xml>"""
        self.prepay_data = self.get_prepay_data()

        second_sign = self.get_second_sign()
        data = {
            "timeStamp": self.timeStamp,
            "nonceStr": self.second_nonceStr,
            "package": f"prepay_id={self.prepay_data.get('prepay_id')}",
            "paySign": second_sign
        }
        return data


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM