zoukankan      html  css  js  c++  java
  • 小程序的支付流程

    小程序的支付流程

    1.用户发起请求下单支付
    2.保证用户是登入状态
    3.组织数据,请求统一下单接口,微信官方会同步返回一个prepay_id
    4.重新组织数据,进行签名,将重新组织的数据返回给小程序,小程序再吊起支付
    5.用户可以进行支付,支付结果会同步返回给小程序
    6.后台修改订单支付状态是通过微信官方服务器的异步通知
    

    xml解析模块

    <xml>
    	<appid name="属性值">{child.text}</appid>
        child.tag表示appid
    </xml>
    
    import xml.etree.ElementTree as ET
    
    如果我们要解析一个xml文件
    tree = ET.parse('country_data.xml')
    root = tree.getroot()
    
    如果解析字符串
    root = ET.fromstring(country_data_ as_string)
    
    这个root是 Element 
    for child in root:
    	 print(child.tag, child.attrib)
    	 #child.tag表是标签名,child.attrib表示获取属性
    	 #child.text就表示获取内容
    

    小程序支付总结

    1.接收到支付请求,先组织数据,然后进行统一下单前的签名
    -请求的数据与相应的数据都是xml,请求的时候,xml数据要变成二进制,heards中的content-type:"application/xml"
    -响应的数据也是xml,我要用xml.etree.ElementTree将他转化为字典
    2.拿到统一下单数据,最重要的prepay_id,进行再次签名。把一下数据发送给小程序。
    			timeStamp": 时间戳
                "nonceStr":随机字符串
                "package": f"prepay_id={data_dict['prepay_id']}",统一下单中的到的prepay_id
                "signType": "MD5",
                "paySign":通过上面数据进行加密的结果
     3 小程序掉用wx.resquestPayment()吊起支付
        
    

    后端的pay.py

    from rest_framework.views import  APIView
    from rest_framework.response import  Response
    from django.core.cache import cache
    from app01.wx import settings
    import hashlib,requests,time
    
    class Pay(APIView):
        def post(self,request):
            param = request.data
            if param.get("token") and param.get("money"):
                openid_session_key = cache.get(param.get("token"))
                if openid_session_key:
                    # 获取客户端ip,如果是负载均衡,就用HTTP_X_FORWARDED_FOR,如果不是就用下面的
                    # nginx 转发:--》访问是nginx,->nginx -> uwsgi
                    if request.META.get('HTTP_X_FORWARDED_FOR'):
                        #有负载均衡就用这个
                        self.ip = request.META['HTTP_X_FORWARDED_FOR']
                    else:
                        #没有负载均衡就用这个
                        self.ip = request.META['REMOTE_ADDR']
                    self.openid =openid_session_key.split("&")[1]
                    self.money =param.get("money")
                    data = self.get_pay_data()
                    return  Response({"code":0,"msg":"ok","data":data})
    
                else:
                    return Response({"code": 2, "msg": "token无效"})
            else:
                return  Response({"code":1,"msg":"缺少参数"})
    
        def get_nonce_str(self):
            import random
            data = "123456789abcdefghijklmn"
            nonce_str = "".join(random.sample(data,10))
            #random.sample(从哪里取,取多小个),变成列表
            return  nonce_str
    
        def get_order_id(self):
            import time
            import random
            data = "123456789abcdefghijklmn"
            order_no = str(time.strftime("%Y%m%d%H%M%S"))+"".join(random.sample(data, 5))
            return  order_no
    
        def get_sign(self):
            data_dict ={
            "appid" :  self.appid,
            "mch_id":self.mch_id,
            "nonce_str" : self.nonce_str,
            "body" :  self.body,
            "out_trade_no" : self.out_trade_no,
            "total_fee" : self.total_fee,
            "spbill_create_ip" : self.ip,
            "notify_url" : self.notify_url,
            "trade_type" :  self.trade_type,
            "openid" : self.openid,
            }
            sign_str = "&".join([f"{k}={data_dict[k]}"  for k in sorted(data_dict)])
            sign_str = f"{sign_str}&key={settings.pay_apikey}"
            print("sign_str", sign_str)
            md5 = hashlib.md5()
            md5.update(sign_str.encode("utf-8"))
            sign = md5.hexdigest()
            return  sign.upper()
    
    
        def xml_to_dict(self,xml_data):
            import xml.etree.ElementTree as ET
    
            xml_dict ={}
    
            root = ET.fromstring(xml_data)
    
            for child in root:
                xml_dict[child.tag]= child.text
            return  xml_dict
    
    
    
        def get_two_sign(self,data):
            data_dict = {
                "appId":settings.AppId,
                "timeStamp":str(int(time.time())),
                "nonceStr":data['nonce_str'],
                "package":f"prepay_id={data['prepay_id']}",
                "signType":"MD5"
    
            }
            sign_str = "&".join([f"{k}={data_dict[k]}" for k in sorted(data_dict)])
            sign_str = f"{sign_str}&key={settings.pay_apikey}"
            md5 = hashlib.md5()
            md5.update(sign_str.encode("utf-8"))
            sign = md5.hexdigest()
            return sign.upper() , data_dict['timeStamp']
    
    
    
        def get_pay_data(self):
            self.appid = settings.AppId
            self.mch_id = settings.pay_mchid
            self.nonce_str = self.get_nonce_str()
            self.body = "老男孩学费"
            self.out_trade_no = self.get_order_id()
            self.total_fee =self.money
            self.spbill_create_ip =self.ip
            self.notify_url = "htttp://www.test.com"
            self.trade_type ="JSAPI"
            self.openid = self.openid
            self.sign = self.get_sign()
    
            body_data = f'''
            <xml>
                <appid>{self.appid}</appid>
                <mch_id>{self.mch_id}</mch_id>
                <nonce_str>{self.nonce_str}</nonce_str>
                <body>{self.body}</body>
                <out_trade_no>{self.out_trade_no}</out_trade_no>
                <total_fee>{self.total_fee}</total_fee>
                <spbill_create_ip>{self.spbill_create_ip}</spbill_create_ip>
                <notify_url>{self.notify_url}</notify_url>
                <trade_type>{self.trade_type }</trade_type>
                <openid>{self.openid }</openid>      
                <sign>{self.sign}</sign>      
            </xml> 
            '''
            url = "https://api.mch.weixin.qq.com/pay/unifiedorder"
            # 如果发送的xml数据要把数据转化二进制。body_data.encode("utf-8")
            # request
            response = requests.post(url,data=body_data.encode("utf-8"),headers = {"content-type":"application/xml"} )
            #接收一个二进制的响应
            data_dict = self.xml_to_dict(response.content)
            pay_sign,timeStamp = self.get_two_sign(data_dict)
            data = {
    
                "timeStamp": timeStamp,
                "nonceStr": data_dict['nonce_str'],
                "package": f"prepay_id={data_dict['prepay_id']}",
                "signType": "MD5",
                "paySign":pay_sign
            }
            return data
    
    
    
    
    
    
    

    小程序中的pay方法:

    pay:function(){
        wx.request({
          url: app.globalData.baseurl+"pay/",
          data:{"money":1,token:wx.getStorageSync('token')},
          method:"POST",
          success (e) {
            console.log("支付数据",e)
            wx.requestPayment(
              {
              'timeStamp':e.data.data.timeStamp,
              'nonceStr': e.data.data.nonceStr,
              'package': e.data.data.package,
              'signType': e.data.data.signType,
              'paySign': e.data.data.paySign,
              'success':function(res){
                console.log("成功",res)
              },
              'fail':function(res){
                console.log("失败",res)
              },
              
              })
          }
    
        })
      }
    
  • 相关阅读:
    HDU 1010 Tempter of the Bone
    HDU 4421 Bit Magic(奇葩式解法)
    HDU 2614 Beat 深搜DFS
    HDU 1495 非常可乐 BFS 搜索
    Road to Cinema
    Sea Battle
    Interview with Oleg
    Spotlights
    Substring
    Dominating Patterns
  • 原文地址:https://www.cnblogs.com/godlover/p/12511418.html
Copyright © 2011-2022 走看看