侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Django1.11配合uni-app发起微信支付的实现

微信(小程序)  /  管理员 发布于 7年前   171

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

经过三天的断断续续的奋战,我终于是干动了微信支付。为了以后不忘记,现在来一篇教程,来来来,开干!!!

一、准备阶段

1、准备阶段我们需要去微信官网申请一个小程序或者公众号。获得AppID和AppSecret。

2、去微信商户平台 成为商家,开通JSAPI用来获得商户号和自己配置的钥匙。然后再商户平台上面绑定小程序appid。

(点击下面图片进入官方链接!)

在配置里面配置一个自己的key,需要记住后台开发的时候需要!

关联后即可在小程序管理页面开通微信支付!

到此,准备阶段完成!

二、梳理流程

在这里我大概写一下流程:首先我们在前端发起微信登陆,此时微信会给我们返回一个openid,这个openid一定要留存在某一个位置。然后前段发起微信支付,向后端发送数据请求,后端对结合前段的数据向微信方面发送一个请求,请求相关数据,得到相关数据之后把数据发送给前段,前段收到数据,利用微信接口再向微信指定连接发送请求,微信返回请求,即可!这个就是全流程,很多人肯定已经懵了。没事,咱一步一步来,别步子跨大了――扯到蛋了!

以上就是数据处理阶段大概流程!

三、代码实现

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' # 小程序appidclient_secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxx' # 小程序secretMch_id = 'xxxxxxxxxxx' # 商户号Mch_key = 'xxxxxxxxxxxxxxxxxxx' # 商户Keyorder_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_urlimport hashlibimport datetimeimport xml.etree.ElementTree as ETimport requestsfrom ..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()  # 根据当前系统时间来生成商品订单号。时间精确到微秒  payOrdrID = date.strftime("%Y%m%d%H%M%S%f")  return payOrdrID# 获取全部参数信息,封装成xmldef 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 = '<xml>'  bodyData += '<appid>' + client_appid + '</appid>' # 小程序ID  bodyData += '<body>' + body + '</body>' # 商品描述  bodyData += '<mch_id>' + Mch_id + '</mch_id>' # 商户号  bodyData += '<nonce_str>' + nonce_str + '</nonce_str>' # 随机字符串  bodyData += '<notify_url>' + notify_url + '</notify_url>' # 支付成功的回调地址  bodyData += '<openid>' + openid + '</openid>' # 用户标识  bodyData += '<out_trade_no>' + out_trade_no + '</out_trade_no>' # 商户订单号  bodyData += '<spbill_create_ip>' + client_ip + '</spbill_create_ip>' # 客户端终端IP  bodyData += '<total_fee>' + total_fee + '</total_fee>' # 总金额 单位为分  bodyData += '<trade_type>JSAPI</trade_type>' # 交易类型 小程序取值如下:JSAPI  bodyData += '<sign>' + sign + '</sign>'  bodyData += '</xml>'  return bodyDatadef 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_dictdef dict_to_xml(dict_data):  '''  dict to xml  :param dict_data:  :return:  '''  xml = ["<xml>"]  for k, v in dict_data.iteritems():    xml.append("<{0}>{1}</{0}>".format(k, v))  xml.append("</xml>")  return "".join(xml)# 获取返回给小程序的paySigndef 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: () => {}        });          }

至此相信大家也就会了。

附上我的目录结构

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


  • 上一条:
    django 微信网页授权认证api的步骤详解
    下一条:
    Zabbix实现微信报警功能
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 微信模板消息改版后发送规则记录(微信订阅消息参数值内容限制说明)(1个评论)
    • 微信支付v3对接所需工具及命令(0个评论)
    • 2023年9月1日起:微信小程序必须备案才能上线运营(0个评论)
    • 腾讯官方客服回应了:微信好友上限约10000个!(1个评论)
    • 2023年做微信小程序的老铁注意:新增收费项、微信小程序获取手机号也收费了(2个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2017-10
    • 2018-01
    • 2020-03
    • 2021-06
    • 2021-10
    • 2022-03
    • 2023-02
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-10
    • 2023-11
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客