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正则表达式
Jan 15 Python
python中函数传参详解
Jul 03 Python
pandas表连接 索引上的合并方法
Jun 08 Python
解决Python安装后pip不能用的问题
Jun 12 Python
Python基于多线程实现ping扫描功能示例
Jul 23 Python
Python3中bytes类型转换为str类型
Sep 27 Python
Python调用C语言的实现
Jul 26 Python
Python如何调用JS文件中的函数
Aug 16 Python
Python操作列表常用方法实例小结【创建、遍历、统计、切片等】
Oct 25 Python
pytorch中的inference使用实例
Feb 20 Python
python基于tkinter制作无损音乐下载工具
Mar 29 Python
Python还能这么玩之用Python做个小游戏的外挂
Jun 04 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
PHP5.2下chunk_split()函数整数溢出漏洞 分析
2007/06/06 PHP
php 文件上传系统手记
2009/10/26 PHP
php模拟asp中的XmlHttpRequest实现http请求的代码
2011/03/24 PHP
php基于curl实现的股票信息查询类实例
2016/11/11 PHP
JavaScript方法和技巧大全
2006/12/27 Javascript
理解 JavaScript 预解析
2009/10/25 Javascript
js获取input长度并根据页面宽度设置其大小及居中对齐
2014/08/22 Javascript
JavaScript 基本概念
2015/01/20 Javascript
Jquery实现鼠标移动放大图片功能实例
2015/03/25 Javascript
Bootstrap布局组件教程之Bootstrap下拉菜单
2016/06/12 Javascript
Javascript点击其他任意地方隐藏关闭DIV实例
2016/06/21 Javascript
artDialog+plupload实现多文件上传
2016/07/19 Javascript
jQuery实现别踩白块儿网页版小游戏
2017/01/18 Javascript
Bootstrap里的文件分别代表什么意思及其引用方法
2017/05/01 Javascript
vue刷新和tab切换实例
2018/02/11 Javascript
修改npm全局安装模式的路径方法
2018/05/15 Javascript
jQuery实现的鼠标拖动浮层功能示例【拖动div等任何标签】
2018/12/29 jQuery
vue将后台数据时间戳转换成日期格式
2019/07/31 Javascript
mpvue实现微信小程序快递单号查询代码
2020/04/03 Javascript
[01:06]DOTA2亚洲邀请赛专属珍藏-荧煌之礼
2017/03/24 DOTA
python分治法求二维数组局部峰值方法
2018/04/03 Python
Python中实现变量赋值传递时的引用和拷贝方法
2018/04/29 Python
python3中的md5加密实例
2018/05/29 Python
python图像处理模块Pillow的学习详解
2019/10/09 Python
wxpython布局的实现方法
2019/11/01 Python
pycharm设置默认的UTF-8编码模式的方法详解
2020/06/01 Python
HTML5 Canvas中绘制椭圆的4种方法
2015/04/24 HTML / CSS
Kathmandu新西兰官网:新西兰户外运动品牌
2019/07/27 全球购物
日本酒店、民宿、温泉旅馆、当地旅行团中文预订:e路东瀛
2019/12/09 全球购物
小学老师寄语大全
2014/04/04 职场文书
房展策划方案
2014/06/07 职场文书
思想作风整顿个人剖析材料
2014/10/06 职场文书
党员“四风”问题批评与自我批评思想汇报
2014/10/06 职场文书
Sql-Server数据库单表查询 4.3实验课
2021/04/05 SQL Server
完美解决golang go get私有仓库的问题
2021/05/05 Golang
关于Nginx中虚拟主机的一些冷门知识小结
2022/03/03 Servers