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+selenium实现登录账户后自动点击的示例
Dec 22 Python
python实现微信远程控制电脑
Feb 22 Python
python微信跳一跳系列之棋子定位颜色识别
Feb 26 Python
python pandas.DataFrame选取、修改数据最好用.loc,.iloc,.ix实现
Jun 11 Python
浅谈python 读excel数值为浮点型的问题
Dec 25 Python
windows10下安装TensorFlow Object Detection API的步骤
Jun 13 Python
python TK库简单应用(实时显示子进程输出)
Oct 29 Python
Python jieba库用法及实例解析
Nov 04 Python
python opencv把一张图片嵌入(叠加)到另一张图片上的实现代码
Jun 11 Python
Python数据可视化图实现过程详解
Jun 12 Python
从零开始的TensorFlow+VScode开发环境搭建的步骤(图文)
Aug 31 Python
Python 转移文件至云对象存储的方法
Feb 07 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面向对象学习笔记之二 生成对象的设计模式
2012/10/06 PHP
PHP生成随机用户名和密码的实现代码
2013/02/27 PHP
非常好用的Zend Framework分页类
2014/06/25 PHP
Json_encode防止汉字转义成unicode的方法
2016/02/25 PHP
Thinkphp3.2.3分页使用实例解析
2016/07/28 PHP
PHPCrawl爬虫库实现抓取酷狗歌单的方法示例
2017/12/21 PHP
JObj预览一个JS的框架
2008/03/13 Javascript
Jquery 弹出层插件实现代码
2009/10/24 Javascript
JavaScript入门之对象与JSON详解
2011/10/21 Javascript
jquery的相对父元素和相对文档定位示例代码
2013/08/02 Javascript
纯js实现无限空间大小的本地存储
2015/06/18 Javascript
使用Script元素发送JSONP请求的方法
2016/06/12 Javascript
第六篇Bootstrap表格样式介绍
2016/06/21 Javascript
Extjs 点击复选框在表格中增加相关信息行
2016/07/12 Javascript
新闻上下滚动jquery 超简洁(必看篇)
2017/01/21 Javascript
JS对象创建的几种方式整理
2017/02/28 Javascript
浅析Javascript中双等号(==)隐性转换机制
2017/10/27 Javascript
详解Eslint 配置及规则说明
2018/09/10 Javascript
vue-cli中安装方法(图文详细步骤)
2018/12/12 Javascript
详解用场景去理解函数柯里化(入门篇)
2019/04/11 Javascript
详解Vue.js中引入图片路径的几种方式
2019/06/17 Javascript
Python函数返回值实例分析
2015/06/08 Python
详解django2中关于时间处理策略
2019/03/06 Python
python 获取计算机的网卡信息
2021/02/18 Python
CSS3对图片照片进行边缘模糊处理的实现
2018/08/08 HTML / CSS
浅谈css3中的渐进增强和优雅降级
2017/12/01 HTML / CSS
HTML5中Canvas与SVG的画图原理比较
2013/01/16 HTML / CSS
澳大利亚墨水站Ink Station:墨水和碳粉打印机墨盒
2019/03/24 全球购物
简短的公司员工自我评价分享
2013/11/13 职场文书
关于幼儿的自我评价
2013/12/18 职场文书
怎样写离婚协议书
2014/09/10 职场文书
个人纪律作风整改措施思想汇报
2014/10/12 职场文书
旷工检讨书大全
2015/08/15 职场文书
任命书格式模板
2015/09/22 职场文书
关于Javascript闭包与应用的详解
2021/04/22 Javascript
css display table 自适应高度、宽度问题的解决
2021/05/07 HTML / CSS