1. 前提准备

1.1 开通了微信支付功能(每年需要交300元)

  • 需要自己去申请,需要上传营业执照及其所要求的信息

1.2 小程序id&&小程序密钥

1.3 商户密钥key

  • key设置路径:微信商户平台(pay.weixin.qq.com)-->账户中心-->账户设置-->API安全-->设置API密钥

1.4 支付的官方文档

支付文档https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_4&index=3

2.使用

前端

2.1 目录

2.2 login(登录获取openid,小程序支付必须需要openid)

html

<!--pages/login/login.wxml-->
<input placeholder="请输入手机号" bindinput="inputPhone" value="{{phone}}"></input>
<button bindtap="getUserProfile">登录</button>

js

// pages/login/login.js
Page({/*** 页面的初始数据*/data: {phone: '',openid: ''},// 获取input数据inputPhone: function (e) {// 获取input信息var phone = e.detail.valuethis.setData({phone: phone})},// 登录getUserProfile: function (e) {// 获取openidwx.login({success: res => {this.setData({openid: res.code})}})// 向后台发送数据wx.request({url: 'http://127.0.0.1:8023/login/',data: {phone: this.data.phone,openid: this.data.openid},dataType: "json",method: "POST",success: (result) => {console.log(result.data)},})},/*** 生命周期函数--监听页面加载*/onLoad: function (options) {},/*** 生命周期函数--监听页面初次渲染完成*/onReady: function () {},/*** 生命周期函数--监听页面显示*/onShow: function () {},/*** 生命周期函数--监听页面隐藏*/onHide: function () {},/*** 生命周期函数--监听页面卸载*/onUnload: function () {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh: function () {},/*** 页面上拉触底事件的处理函数*/onReachBottom: function () {},/*** 用户点击右上角分享*/onShareAppMessage: function () {}
})

2.3 index

html

<!--index.wxml-->
<radio-group bindchange="changeGoods"><view class='row' wx:for="{{goodsList}}" wx:key="index"><text>{{item.title}} - {{item.price}}</text><radio class="radio" value="{{item.id}}"></radio></view>
</radio-group><button bindtap="doPayment">购买</button>

js

// pages/index/index.js
Page({/*** 页面的初始数据*/data: {goodsList: [],seletedId: ''},// 选中物品的idchangeGoods: function (e) {// console.log(e.detail.value)this.setData({seletedId: e.detail.value})// console.log(this.data.seletedId)},// 点击购买doPayment: function () {this.data.seletedId// 向后台发送一个请求,生成一大堆数据// 获取这一大堆数据,然后弹出支付二维码wx.request({url: 'http://127.0.0.1:8023/payment/',data: {goodsId: this.data.seletedId},method: 'POST',dataType: 'json',success: (res) => {console.log(res.data);// 生成二维码wx.requestPayment({'timeStamp': res.data.timeStamp,'nonceStr': res.data.nonceStr,'package': res.data.package,'signType': res.data.signType,'paySign': res.data.paySign,'success': function (res) {// 进行逻辑判断},'fail': function (res) {},'complete': function (res) {}})}})},/*** 生命周期函数--监听页面加载*/onLoad: function (options) {// 物品渲染wx.request({url: 'http://127.0.0.1:8023/index/',method: 'GET',dataType: 'json',success: (res) => {this.setData({goodsList: res.data})}})},/*** 生命周期函数--监听页面初次渲染完成*/onReady: function () {},/*** 生命周期函数--监听页面显示*/onShow: function () {},/*** 生命周期函数--监听页面隐藏*/onHide: function () {},/*** 生命周期函数--监听页面卸载*/onUnload: function () {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh: function () {},/*** 页面上拉触底事件的处理函数*/onReachBottom: function () {},/*** 用户点击右上角分享*/onShareAppMessage: function () {}
})

2.4 全局app.json

{"pages": ["pages/index/index","pages/login/login"],"window": {"backgroundTextStyle": "light","navigationBarBackgroundColor": "#fff","navigationBarTitleText": "Weixin","navigationBarTextStyle": "black"},"tabBar": {"backgroundColor": "#fafafa","borderStyle": "white","color": "#666","selectedColor": "#b4282d","position": "bottom","list": [{"pagePath": "pages/index/index","text": "首页"},{"pagePath": "pages/login/login","text": "登录"}]},"style": "v2","sitemapLocation": "sitemap.json"
}

后端

2.1 url

from django.contrib import admin
from django.urls import pathfrom app01 import viewsurlpatterns = [path('admin/', admin.site.urls),path('index/', views.IndexData.as_view()),path('login/', views.LoginView.as_view()),path('payment/', views.PaymentView.as_view()),path('pay/notify/', views.NotifyView.as_view()),
]

2.2 view

import time
import randomimport requests
from rest_framework import serializers
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.generics import ListAPIView
from xml.etree import ElementTree as ETfrom app01 import modelsclass IndexDataModelSerializer(serializers.ModelSerializer):"""首页序列化器"""class Meta:model = models.Goodsfields = '__all__'class IndexData(ListAPIView):"""首页渲染"""queryset = models.Goods.objects.all()serializer_class = IndexDataModelSerializerclass LoginView(APIView):"""登录视图"""def post(self, request, *args, **kwargs):# 从前端获取数据phone = request.data.get('phone')wx_code = request.data.get('openid')# print(wx_code)if not wx_code:return Response('无openid')# print(wx_code)# openid的获取:需要拿着wx_code去微信申请#  https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html# login服务端,发送请求的路由地址# https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.htmlinfo = {'appid': "微信小程序appid",  # 微信小程序appid'secret': "微信小程序密钥key",  # 微信小程序密钥key'js_code': wx_code,  # openid'grant_type': "authorization_code",  # 默认值即可}result = requests.get(url='https://api.weixin.qq.com/sns/jscode2session', params=info)openid = result.json()['openid']models.UserInfo.objects.get_or_create(phone=phone, defaults={'openid': openid})return Response('ok')# 进行加密
def md5(string):"""md5加密"""import hashlibm = hashlib.md5()m.update(string.encode('utf-8'))return m.hexdigest()# 支付通知
class PaymentView(APIView):"""支付视图及操作"""def post(self, request, *args, **kwargs):# 前端传送过来的商品idgoods_id = request.data.get('goodsId')order_random_string = str(int(time.time()))# 获取用户对象,应该是当前登录用户,这里写死了user_object = models.UserInfo.objects.filter(id=1).first()  # user_object.openid# 商品的对象goods_object = models.Goods.objects.filter(id=goods_id).first()  # goods_object.price# 创建一个订单order_object = models.Order.objects.create(goods=goods_object, user=user_object, uid=order_random_string,status=1)# 按照微信的规则,去生成支付需要的一大堆的数据# https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_3&index=1# print(order_random_string)# ###################### 1.调用支付统一下单 ######################info = {# 小程序id T'appid': '小程序id',# 商户关联id T'mch_id': '商户关联id',# 设备号 F'device_info': 'ymq-text',# 随机字符串 T'nonce_str': "".join([chr(random.randint(65, 90)) for _ in range(12)]),# 签名类型 F'sign_type': "MD5",# 商品描述 F'body': "支付测试",# 商品详情 F'detail': '这是一个商品详细描述信息.',# 附加数据 F'attach': '河南彭于晏',# 商户订单号 T'out_trade_no': order_random_string,# 标价金额 T'total_fee': goods_object.price,  # 总金额# 终端IP(用户ip) F'spbill_create_ip': request.META.get('REMOTE_ADDR'),# # 支付成功之后,微信异步通知(post) T'notify_url': "http://106.14.42.256:8023/pay/notify/",# 交易类型 T'trade_type': 'JSAPI',# 用户标识(trade_type=JSAPI,此参数必传)'openid': user_object.openid}# 1.1 签名#       对字典中的key按照ASCII码从小到大排序#       将排完序的值拼接 stringA = appid=wx55cca0b94f723dc7&mch_id=1526049051#       让stringA和key拼接:stringSignTemp = stringA+"&key=192006250b4c09247ec02edce69f6a2d" key为商户平台设置的密钥key#       MD5(stringSignTemp)#       将密文转换为大写#       得到签名 sign#       把签名再添加到info中    info['sign'] = sign值# 商户密钥keypay_key = "key为商户平台设置的密钥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_idroot = 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'appId': "小程序的appid",'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# print(info_dict)return Response(info_dict)class NotifyView(APIView):"""支付完成之后的通知"""def post(self, request, *args, **kwargs):# 1. 获取结果把结果XML转换为字典格式root = ET.XML(request.body.decode('utf-8'))result = {child.tag: child.text for child in root}# 2. 校验签名是否正确,防止恶意请求。sign = result.pop('sign')# key为商户平台设置的密钥keykey = "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)

微信小程序支付---详解(python)相关推荐

  1. 微信小程序支付详解:

    前段时间在公司的开发了一个微信小程序的项目,今天来说一说微信小程序的支付,有很多优秀的文章都说了小程序支付的 开发流程步骤,这里我们推荐一个博主以前就是看他的开发小程序支付:https://githu ...

  2. 微信小程序python flask_Python Flask 搭建微信小程序后台详解

    前言: 近期需要开发一个打分的微信小程序,涉及到与后台服务器的数据交互,因为业务逻辑相对简单,故选择Python的轻量化web框架Flask来搭建后台程序.因为是初次接触小程序,经过一番摸索和尝试,个 ...

  3. 微信小程序点击按钮弹出弹窗_转载 | 广东大学生就业创业微信小程序操作流程详解(一)...

    广东大学生就业创业微信小程序 操作流程详解(一) 转眼来到10月,炎炎夏日也阻挡不了青春的忙碌,同学萌走出校园,迈向社会. 在这段时间,同学们不仅要准备毕业论文,应对毕业答辩,还需要兼顾各种毕业手续的 ...

  4. python微信小程序抢购_Python实现微信小程序支付功能!Python确实强的一批!

    正文 由于最近自己在做小程序的支付,就在这里简单介绍一下讲一下用python做小程序支付这个流程.当然在进行开发之前还是建议读一下具体的流程,清楚支付的过程. 1.支付交互流程 2.获取openid( ...

  5. 微信小程序版本管理详解

    本来觉得没必要写版本管理的文章. 奈何微信的官方文档真的是太不友好了!!! 一顿操作猛如虎.(请原谅我知识轻薄). 本文只是我这几天操作过的,一些个人理解总结,如果,有什么不对的,欢迎大家纠正我的错误 ...

  6. flask ajax小程序,Python Flask 搭建微信小程序后台详解

    后台程序返回了数据后,第三步就是小程序该怎么接收返回数据并进行相关业务逻辑处理. 小程序接收返回数据.Python-Flask向小程序返回了JSON格式的数据后,小程序的wx.requset()函数里 ...

  7. Python Flask 搭建微信小程序后台详解

    前言: 近期需要开发一个打分的微信小程序,涉及到与后台服务器的数据交互,因为业务逻辑相对简单,故选择Python的轻量化web框架Flask来搭建后台程序.因为是初次接触小程序,经过一番摸索和尝试,个 ...

  8. 字节跳动小程序支付详解

    微信支付详解 1.为什么要写这篇文章 参考了字节跳动官方的文档之后发现写的太简单,完全一头雾水摸不清头脑,后来在百度了别人的实现方案,才得以总结出来. 2.背景 我司要开发一个头条小程序,需要支持支付 ...

  9. 一、微信小程序开发详解

    目录 1.什么是小程序? 2.小程序可以干什么? 3.相关资料 第一个小程序 一.申请帐号 二.测试号申请 三.安装开发工具 四.你的第一个小程序 五.编译预览 六.目录结构 七.JSON 配置 八. ...

  10. 企业级微信小程序实战详解

    项目地址:github.com/wudiufo/WeC- 完成效果展示:www.bilibili.com/video/av488- 小爱心是否点赞组件 components/like 思路: like ...

最新文章

  1. LeetCode 04寻找两个正序数组的中位数(困难)二分法
  2. css 链接悬浮动画
  3. iOS-应用生命周期
  4. 如何利用JavaScript的arguments对象实现用代码打印调用栈的需求
  5. python中怎么创建配置文件_如何在Django中创建配置文件注册表单?
  6. 卷积和池化后特征图的大小~
  7. substring substr slice 区别
  8. Mysql优化(出自官方文档) - 第三篇
  9. 深度去除WinRAR广告
  10. Qunee for HTML5的学习与使用笔记(一)
  11. 美学心得(第二百二十五集)罗国正
  12. Python自动发抖音脚本教程(1:介绍和源码)
  13. 保密基本知识试题(2017年版)(共281题)
  14. 普通上班族如何快速买房买车,一个程序员摸索的实操经验分享
  15. 面向功利编程,面向Star开源? 一个开发者的2019反思总结
  16. 治近视的秘方!1000度近视降到只有200度
  17. 安卓识别身份证,自动提取身份证信息功能实现(附源码)
  18. 金沙滩51单片机74HC138 三八译码器的应用
  19. 基于Redis实现在线游戏积分排行榜
  20. android arm代码,为Android ARMV7编译OpenSSL 1.1.0

热门文章

  1. Java医院管理系统完整代码_医院管理系统(JAVA代码)
  2. 服务器的日常运维巡检视频,日常运维检查记录表
  3. 08CMS之后台二次开发
  4. NKOI 3539 移棋子游戏[6月月赛题A]
  5. Behavior Creator 行为树可视化编辑器
  6. 基于视觉SLAM的无人机仿真-px4-gazebo
  7. Warship+NPOI导入导出组件介绍【对象化】
  8. 魅族计算机软件不见了,非常全面的魅族手机常见故障原因及解决办法
  9. Redis 学习笔记-雷云龙
  10. Simulink 搭建模型【MATLAB官网帮助】