zoukankan      html  css  js  c++  java
  • (二十六)微信小程序支付流程

    小程序支付官网

    统一下单API官网

    再次签名

    小程序前端页面

    <radio-group bindchange="changeGoods">
      <view class='row'wx:for="{{goodList}}" wx:key="index">
        <text>{{item.title}}-{{item.price}}</text>
        <radio class="radio" value="{{item.id}}"></radio>
      </view>
    </radio-group>
    
    
    <button bindtap="doBuy">购买</button>
    const app = getApp()
    
    Page({
      data: {
      goodList:null,
      selectId:null
      },
      /**
       * 你选着那件商品就知道是哪个id   
       */
      changeGoods:function(e){
        this.setData({
          selectId: e.detail.value
        })
      },
     /**
      * 一启动就展示商品列表
      */
      onLoad: function () {
       wx.request({
         url: 'http://127.0.0.1:8000/goods/',
         method: 'GET',
         dataType: 'json',
         responseType: 'text',
         success: (res) =>{
           console.log(res)
           this.setData({
             goodList:res.data
           })
         },
       })
      },
    })

    // 先写一部分  
    doBuy: function () {
        // 向后台发送一个请求,生成一大堆数据
        wx.request({
          url: 'http://127.0.0.1:8000/payment/',
          data: {
          goodId:this.data.selectId
          },
          method: 'POST',
          dataType: 'json',
          responseType: 'text',
          success: (res)=> {
            console.log(res)
          },
        })
    
        // 获取这一大堆数据,然后弹出支付二维码
      },

    后端

      url(r'^payment/', payment.PaymentView.as_view()),
    # 根据上面 微信小程序官网提供的文档 
    from
    app01 import models from rest_framework.generics import ListAPIView from rest_framework.views import APIView import random from rest_framework import serializers from rest_framework.response import Response from xml.etree import ElementTree as ET # 操作xml import requests import time def md5(string): import hashlib m = hashlib.md5() m.update(string.encode('utf-8')) return m.hexdigest() class PaymentView(APIView): def post(self, request, *args, **kwargs): goods_id = request.data.get('goodId') '''模拟的订单号和用户''' order_random = str(int(time.time())) user_obj = models.UserInfo.objects.filter(id=1).first() # 有openid goods_object = models.Goods.objects.filter(id=goods_id).first() # 商品价格 models.Order.objects.create(goods=goods_object,user=user_obj,uid=order_random,status=1) # 生成一大堆数据 按照微信规则---官方文档 '''https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1&index=1''' # ###################### 1.调用支付统一下单 ###################### info = { 'appid': '', # 小程序id 'mch_id': '', # 商户号 'device_info': '', # 设备号 'nonce_str': "".join([chr(random.randint(65, 90)) for _ in range(12)]), 'sign_type': "MD5", # 加密类型 'body': "保证金", # 'detail': '这是一个商品详细描述信息.', 'attach': '微信小程序', 'out_trade_no': order_random, # 订单id 'total_fee': goods_object.price, # 总金额 'spbill_create_ip': request.META.get('REMOTE_ADDR'), # 终端里的ip # 终端IP(用户IP) remote_addr = request.META.get('REMOTE_ADDR') 'notify_url': "http://1.1.1.1:8012/pay/notify/", # 支付成功之后,微信异步通知 待会要用 'trade_type': 'JSAPI', 'openid': user_obj.openid # openid } # 1.1 签名 '''https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3''' # 对字典中的key按照ASCII码从小到大排序 # 将排完序的值拼接 stringA = appid=wx55cca0b94f723dc7&mch_id=1526049051 # 让stringA和key拼接:stringSignTemp = stringA+"&key=192006250b4c09247ec02edce69f6a2d" key为商户平台设置的密钥key # MD5(stringSignTemp) # 将密文转换为大写 # 得到签名 sign # 把签名再添加到info中 info['sign'] = sign值 pay_key = "2SzCvaKgYExuItWBfYAqJFs72uUleD14" # 商户的key temp = "&".join(["{0}={1}".format(k, info[k]) for k in sorted(info)] + ["{0}={1}".format("key", pay_key, ), ]) sign = md5(temp).upper() info['sign'] = sign # 1.2 向 https://api.mch.weixin.qq.com/pay/unifiedorder 发请求 (json转换为xml) xml_string = "<xml>{0}</xml>".format("".join(["<{0}>{1}</{0}>".format(k, v) for k, v in info.items()])) prepay = requests.post('https://api.mch.weixin.qq.com/pay/unifiedorder',data=xml_string.encode('utf-8')) # 1.3 从结果xml中提取 prepay_id # from xml.etree import ElementTree as ET root = ET.XML(prepay.content.decode('utf-8')) prepay_dict = {child.tag:child.text for child in root} prepay_id = prepay_dict['prepay_id'] # ####################### 2.再次签名 ####################### info_dict = { 'appId': "wx2a313db1501c7253", 'timeStamp': str(int(time.time())), # 时间戳从1970年1月1日00:00:00至今的秒数,即当前的时间 'nonceStr': "".join([chr(random.randint(65, 90)) for _ in range(12)]), # 随机字符串,长度为32个字符以下。 'package': 'prepay_id={0}'.format(prepay_id), # 统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=* 'signType': 'MD5', # 签名类型,默认为MD5,支持HMAC-SHA256和MD5。注意此处需与统一下单的签名类型一致 } temp = "&".join( ["{0}={1}".format(k, info_dict[k]) for k in sorted(info_dict)] + ["{0}={1}".format("key", pay_key, ), ]) sign2 = md5(temp).upper() info_dict['paySign'] = sign2 return Response(info_dict)

    在回到前端

    doBuy: function () {
        // 向后台发送一个请求,生成一大堆数据
        wx.request({
          url: 'http://127.0.0.1:8000/payment/',
          data: {
          goodId:this.data.selectId
          },
          method: 'POST',
          dataType: 'json',
          responseType: 'text',
          success: (res)=> {
            console.log(res.data)
            // 获取这一大堆数据,然后弹出支付二维码
            wx.requestPayment(
              {
                'timeStamp': res.data.timeStamp,
                'nonceStr': res.data.nonceStr,
                'package': res.data.package,
                'signType': 'MD5',
                'paySign': res.data.paySign,
                'success': function (res) { 
                    // 要是成功了 就往上面info里的notify_url发请求
                },
                'fail': function (res) { 
    
                },
                'complete': function (res) { 
    
                }
              })
          },
        })

    notify_url发请求 就是告知我们的ip地址------结合info里的地址

    url(r'^notify/', payment.NotifyView.as_view()),
    class NotifyView(APIView):
        '''支付完后的通知'''
        def post(self, request, *args, **kwargs):
            # 1. 腾讯会发一个XML格式的数据  获取结果把结果XML转换为字典格式
            root = ET.XML(request.body.decode('utf-8'))
            # 变json数据
            result = {child.tag: child.text for child in root}
    
            # 2. 校验签名是否正确,防止恶意请求。
            sign = result.pop('sign')
    
    
            key = "key为商户平台设置的密钥key"
            temp = "&".join(
                ["{0}={1}".format(k, result[k]) for k in sorted(result)] + ["{0}={1}".format("key", key, ), ])
            local_sign = md5(temp).upper()
    
            # 签名一致
            if local_sign == sign:
                # 拿到订单号
                out_trade_no = result.get('out_trade_no')
                # 根据订单号,把数据库的订单状态修改为支付成功
                models.Order.objects.filter(uid=out_trade_no).update(status=2)
                response = """<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"""
                return Response(response)
  • 相关阅读:
    虚拟机中安装vmware tools 到 Debian 时出现 找不到kernel headers的提示
    中小企业信息安全:基本原则
    关于开源的一些注意事项
    创建Odoo8数据库时的“new encoding (UTF8) is incompatible with the encoding of the template database (SQL_ASCII)“问题
    debian8安装Odoo中的Barcode Scanner Hardware Driver模块时,提示没有evdev
    vim /vi中对字符串的查找并替换
    解决 odoo.py: error: option --addons-path: The addons-path 'local-addons/' does not seem to a be a valid Addons Directory!
    debian命令行删除postgresql数据库
    liunx修改字体为宋体
    OpenERP|odoo Web开发
  • 原文地址:https://www.cnblogs.com/a438842265/p/12509981.html
Copyright © 2011-2022 走看看