Django实现微信小程序支付的示例代码


Posted in Python onSeptember 03, 2020

1.下载相关的库

微信官方已经提供了方便开发者的SDK,可是使用pip方式下载:

pip install wechatpy

2. 在项目的settings.py文件添加相关配置

具体的参数需要自己到小程序微信公众平台和微信商户平台获取。

WECHAT = {
    'APPID': 'appid',               # 小程序ID
    'APPSECRET': 'appsecret',			# 小程序SECRET
    'MCH_ID': 'mch_id',                   # 商户号
    'TOTAL_FEE': '1',                      # 总金额, 单位为“分”
    'SPBILL_CREATE_IP': '127.0.0.1',              # 终端IP
    'NOTIFY_URL': 'http://127.0.0.1:8000/wechat/payNotify/',     # 通知地址
    'TRADE_TYPE': 'JSAPI',                   # 交易类型
    'MERCHANT_KEY': 'merchant_key',     # 商户KEY
    'BODY': '商品描述',                # 商品描述
}

3. 给Django项目新建app

  • 例如我新建的app为:Pay
  • 在settings.py文件的INSTALLED_APPS添加刚才新建的app

4. 编写app/views.py:

from django.http import HttpResponse
import requests
import json
from django.conf import settings
from wechatpy.pay import WeChatPay
from app_base.base_viewset import BaseAPIView
from rest_framework import permissions
from lxml import etree as et
from rest_framework import status


class WeChatPayViewSet(BaseAPIView):
  """
  通过小程序前端 wx.login() 接口获取临时登录凭证 code
  将 code 作为参数传入,调用 get_user_info() 方法获取 openid
  """

  def get_user_info(self, js_code):
    """
    使用 临时登录凭证code 获取 session_key 和 openid 等
    支付部分仅需 openid,如需其他用户信息请按微信官方开发文档自行解密
    """
    req_params = {
      'appid': settings.WECHAT['APPID'],
      'secret': settings.WECHAT['APPSECRET'],
      'js_code': js_code,
      'grant_type': 'authorization_code',
    }
    user_info = requests.get('https://api.weixin.qq.com/sns/jscode2session',
                 params=req_params, timeout=3, verify=False)
    return user_info.json()

  def get(self, request):
    code = request.GET.get("code", None)
    openid = self.get_user_info(code)['openid']

    pay = WeChatPay(settings.WECHAT['APPID'], settings.WECHAT['MERCHANT_KEY'], settings.WECHAT['MCH_ID'])
    order = pay.order.create(
      trade_type=settings.WECHAT['TRADE_TYPE'], # 交易类型,小程序取值:JSAPI
      body=settings.WECHAT['BODY'], # 商品描述,商品简单描述
      total_fee=settings.WECHAT['TOTAL_FEE'], # 标价金额,订单总金额,单位为分
      notify_url=settings.WECHAT['NOTIFY_URL'], # 通知地址,异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。
      user_id=openid # 用户标识,trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识。
    )
    wxpay_params = pay.jsapi.get_jsapi_params(order['prepay_id'])
    return HttpResponse(json.dumps(wxpay_params))


class WeChatPayNotifyViewSet(BaseAPIView):
  permission_classes = (permissions.AllowAny, )

  def get(self, request):
    _xml = request.body
    # 拿到微信发送的xml请求 即微信支付后的回调内容
    xml = str(_xml, encoding="utf-8")
    print("xml", xml)
    return_dict = {}
    tree = et.fromstring(xml)
    # xml 解析
    return_code = tree.find("return_code").text
    try:
      if return_code == 'FAIL':
        # 官方发出错误
        return_dict['message'] = '支付失败'
        # return Response(return_dict, status=status.HTTP_400_BAD_REQUEST)
      elif return_code == 'SUCCESS':
        # 拿到自己这次支付的 out_trade_no
        _out_trade_no = tree.find("out_trade_no").text
        # TODO 这里省略了 拿到订单号后的操作 看自己的业务需求
    except Exception as e:
      pass
    finally:
      return HttpResponse(return_dict, status=status.HTTP_200_OK)

补充一些继承的类:

# -*- coding: utf-8 -*-
from rest_framework.authentication import TokenAuthentication
from rest_framework.views import APIView
from rest_framework import permissions

__author__ = 'JayChen'


class BaseAPIView(APIView):
  permission_classes = (permissions.IsAuthenticated,)
  # authentication_classes = (TokenAuthentication,)

5. 给Pay app添加urls.py并编写

# -*- coding: utf-8 -*-

__author__ = 'JayChen'

from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from pay import views

app_name = 'pay'
urlpatterns = [
  # 微信小程序支付
  url(r'^pay/', views.WeChatPayViewSet.as_view(), name='pay'),
  # 支付结果回调
  url(r'^payNotify/', views.WeChatPayNotifyViewSet.as_view(), name='pay_notify'),
]

6.在项目的urls.py添加上面新增的urls.py

from django.contrib import admin
from django.urls import path, include
from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
  path('admin/', admin.site.urls),
  path('token_auth/', obtain_jwt_token, name='jwt_token'),
  path('user/', include('auth_jwt.urls')),
  
  path('wechat/', include('pay.urls')), # 微信支付相关
]

7.调试

微信小程序登陆后会得到一个code,把这个code作为参数发送给Django项目的后端:
例如:http://0.0.0.0:8000/wechat/pay/?code=033h0P0w3ANPRU2ntl0w36HHyy1h0P08

注意:这个code每次登录都会返回,并且只能使用一次,然后就失效。

返回的数据:

{
  "appId": "wx14b75285dfe1",
  "timeStamp": "1595228",
  "nonceStr": "1Wtu5lKb6T3fJLiNzc09ay2Z",
  "signType": "MD5",
  "package": "prepay_id=wx02158826854686197390000",
  "paySign": "89599A11E051D3B20FF57"
}

小程序拿到这些数据就能调起支付。

到此这篇关于Django实现微信小程序支付的文章就介绍到这了,更多相关Django实现微信小程序支付内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python实现的最近最少使用算法
Jul 10 Python
Python中将字典转换为XML以及相关的命名空间解析
Oct 15 Python
启动targetcli时遇到错误解决办法
Oct 26 Python
python使用opencv按一定间隔截取视频帧
Mar 06 Python
python爬取个性签名的方法
Jun 17 Python
python设置值及NaN值处理方法
Jul 03 Python
python实现抖音点赞功能
Apr 07 Python
使用Python和Scribus创建一个RGB立方体的方法
Jul 17 Python
python递归调用中的坑:打印有值, 返回却None
Mar 16 Python
python 实现aes256加密
Nov 27 Python
Python制作运行进度条的实现效果(代码运行不无聊)
Feb 24 Python
Django路由层如何获取正确的url
Jul 15 Python
解决Python3.7.0 SSL低版本导致Pip无法使用问题
Sep 03 #Python
一篇文章搞懂python的转义字符及用法
Sep 03 #Python
容易被忽略的Python内置类型
Sep 03 #Python
python类共享变量操作
Sep 03 #Python
Python pip install之SSL异常处理操作
Sep 03 #Python
详解python tkinter 图片插入问题
Sep 03 #Python
解决PyCharm IDE环境下,执行unittest不生成测试报告的问题
Sep 03 #Python
You might like
php zip文件解压类代码
2009/12/02 PHP
thinkPHP实现签到功能的方法
2017/03/15 PHP
jquery与google map api结合使用 控件,监听器
2010/03/04 Javascript
juqery 学习之三 选择器 层级 基本
2010/11/25 Javascript
基于Jquery实现的一个图片滚动切换
2012/06/21 Javascript
如何动态的导入js文件具体该怎么实现
2014/01/14 Javascript
JavaScript实现鼠标滑过图片变换效果的方法
2015/04/16 Javascript
解决jQuery uploadify在非IE核心浏览器下无法上传
2015/08/05 Javascript
JS获取时间的相关函数及时间戳与时间日期之间的转换
2016/02/04 Javascript
javascript 用函数实现继承详解
2016/05/28 Javascript
jQuery针对input的class属性写了多个值情况下的选择方法
2016/06/03 Javascript
BootStrap Datetimepicker 汉化的实现代码
2017/02/10 Javascript
Vue.js中extend选项和delimiters选项的比较
2017/07/17 Javascript
js排序与重组的实例讲解
2017/08/28 Javascript
vue中axios的封装问题(简易版拦截,get,post)
2018/06/15 Javascript
微信小程序上线发布流程图文详解
2019/05/06 Javascript
浅谈Vue SSR中的Bundle的具有使用
2019/11/21 Javascript
JQuery实现折叠式菜单的详细代码
2020/06/03 jQuery
python实现无证书加密解密实例
2014/10/27 Python
Python中第三方库Requests库的高级用法详解
2017/03/12 Python
python 如何快速找出两个电子表中数据的差异
2017/05/26 Python
python3 读取Excel表格中的数据
2018/10/16 Python
在python3中pyqt5和mayavi不兼容问题的解决方法
2019/01/08 Python
Python 多维List创建的问题小结
2019/01/18 Python
python3 selenium自动化测试 强大的CSS定位方法
2019/08/23 Python
python数据分析工具之 matplotlib详解
2020/04/09 Python
学校花圃的标语
2014/06/18 职场文书
学习型党组织心得体会
2014/09/12 职场文书
户籍证明格式
2014/09/15 职场文书
医院志愿者活动总结
2015/05/06 职场文书
入党积极分子半年考察意见
2015/06/02 职场文书
七一表彰大会简报
2015/07/20 职场文书
班主任班级管理心得体会
2016/01/07 职场文书
学校2016年全国助残日活动总结
2016/04/01 职场文书
个人的事迹材料怎么写
2019/04/24 职场文书
Spring Cloud Gateway去掉url前缀
2021/07/15 Java/Android