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 异常处理实例详解
Mar 12 Python
python搜索指定目录的方法
Apr 29 Python
python中类变量与成员变量的使用注意点总结
Apr 29 Python
安装Python的教程-Windows
Jul 22 Python
使用python 和 lint 删除项目无用资源的方法
Dec 20 Python
pandas 把数据写入txt文件每行固定写入一定数量的值方法
Dec 28 Python
用Python从0开始实现一个中文拼音输入法的思路详解
Jul 20 Python
详解python环境安装selenium和手动下载安装selenium的方法
Mar 17 Python
Python 列表推导式需要注意的地方
Oct 23 Python
关于Python 解决Python3.9 pandas.read_excel(‘xxx.xlsx‘)报错的问题
Nov 28 Python
PyTorch 实现L2正则化以及Dropout的操作
May 27 Python
PyTorch中的torch.cat简单介绍
Mar 17 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实现的获取网页中的图片并保存到本地的代码
2010/01/05 PHP
PHP下利用header()函数设置浏览器缓存的代码
2010/09/01 PHP
php强制文件下载而非在浏览器打开的自定义函数分享
2014/05/08 PHP
php使用PDO获取结果集的方法
2017/02/16 PHP
php实现页面纯静态的实例代码
2017/06/21 PHP
基于CI(CodeIgniter)框架实现购物车功能的方法
2018/04/09 PHP
php字符串过滤strip_tags()函数用法实例分析
2019/06/24 PHP
IE中jquery.form中ajax提交没反应解决方法分享
2012/09/11 Javascript
jQuery中ajax的load()方法用法实例
2014/12/26 Javascript
jQuery表单美化插件jqTransform使用详解
2015/04/12 Javascript
JavaScript实现99乘法表及隔行变色实例代码
2016/02/24 Javascript
浅谈JavaScript的push(),pop(),concat()方法
2016/06/03 Javascript
javascript算法之二叉搜索树的示例代码
2017/09/12 Javascript
vue组件父与子通信详解(一)
2017/11/07 Javascript
react redux入门示例
2018/04/19 Javascript
微信小程序onLaunch异步,首页onLoad先执行?
2018/09/20 Javascript
puppeteer实现html截图的示例代码
2019/01/10 Javascript
详解mpvue开发微信小程序基础知识
2019/09/23 Javascript
es6 for循环中let和var区别详解
2020/01/12 Javascript
JS浏览器BOM常见操作实例详解
2020/04/27 Javascript
详解javascript脚本何时会被执行
2021/02/05 Javascript
[44:22]完美世界DOTA2联赛循环赛 FTD vs PXG BO2第一场 11.01
2020/11/02 DOTA
asyncio 的 coroutine对象 与 Future对象使用指南
2016/09/11 Python
Python实现 多进程导入CSV数据到 MySQL
2017/02/26 Python
对python中if语句的真假判断实例详解
2019/02/18 Python
Python3.5装饰器原理及应用实例详解
2019/04/30 Python
Django之路由层的实现
2019/09/09 Python
基于HTML5的WebGL实现json和echarts图表展现在同一个界面
2017/10/26 HTML / CSS
浅谈HTML5新增和废弃的标签
2019/04/28 HTML / CSS
波兰家居饰品和厨房配件网上商店:Maleomi
2020/12/15 全球购物
Delphi CS笔试题
2014/01/04 面试题
学生打架检讨书大全
2014/01/23 职场文书
硕士论文致谢范文
2015/05/14 职场文书
信用卡工资证明范本
2015/06/19 职场文书
vue实力踩坑之push当前页无效
2022/04/10 Vue.js
Smart 2 车辆代号 HC11 全新谍照曝光
2022/04/21 数码科技