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转换HTML到Text纯文本的方法
Jan 15 Python
Python快速排序算法实例分析
Nov 29 Python
Python基于回溯法解决01背包问题实例
Dec 06 Python
python自动化报告的输出用例详解
May 30 Python
Python类的继承用法示例
Jan 31 Python
通过PYTHON来实现图像分割详解
Jun 26 Python
python爬虫神器Pyppeteer入门及使用
Jul 13 Python
Django如何简单快速实现PUT、DELETE方法
Jul 24 Python
python中time库的实例使用方法
Oct 31 Python
python matplotlib如何给图中的点加标签
Nov 14 Python
PyQt5多线程刷新界面防假死示例
Dec 13 Python
python使用Thread的setDaemon启动后台线程教程
Apr 25 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代码保护--Zend Guard的使用详解
2013/06/03 PHP
PHP实现HTTP断点续传的方法
2015/06/17 PHP
postman的安装与使用方法(模拟Get和Post请求)
2018/08/06 PHP
javascript当onmousedown、onmouseup、onclick同时应用于同一个标签节点Element
2010/01/05 Javascript
validator验证控件使用代码
2010/11/23 Javascript
jQuery旋转插件—rotate支持(ie/Firefox/SafariOpera/Chrome)
2013/01/16 Javascript
点击页面其它地方隐藏该div的两种思路
2013/11/18 Javascript
jquery iframe操作详细解析
2013/11/20 Javascript
Jquery 切换不同图片示例代码
2013/12/05 Javascript
javascript回车完美实现tab切换功能
2014/03/13 Javascript
javascript中AJAX用法实例分析
2015/01/30 Javascript
跟我学习javascript的prototype使用注意事项
2015/11/17 Javascript
JS控制静态页面传递参数并获取参数应用
2016/08/10 Javascript
从零到一详聊创建Vue工程及遇到的常见问题
2019/04/25 Javascript
Vue拖拽组件列表实现动态页面配置功能
2019/06/17 Javascript
解决layui数据表格table的横向滚动条显示问题
2019/09/04 Javascript
layui table去掉右侧滑动条的实现方法
2019/09/05 Javascript
全面解析Vue中的$nextTick
2020/12/24 Vue.js
Python3.6简单操作Mysql数据库
2017/09/12 Python
解决python 自动安装缺少模块的问题
2018/10/22 Python
Python中文编码知识点
2019/02/18 Python
OpenCV中VideoCapture类的使用详解
2020/02/14 Python
Python多线程threading创建及使用方法解析
2020/06/17 Python
Python实现EM算法实例代码
2020/10/04 Python
pycharm实现猜数游戏
2020/12/07 Python
英国网上花店:Bunches
2016/11/29 全球购物
Clarks鞋美国官网:全球领军鞋履品牌
2017/05/13 全球购物
澳大利亚领先的在线美容商店:Facial Co
2017/10/22 全球购物
Baby Tulai澳大利亚:美国婴儿背带品牌
2018/10/15 全球购物
美国最大的在线生存商店:Survival Frog
2020/12/13 全球购物
SQL Server的固定数据库角色都有哪些?对应的服务器权限有哪些?
2013/05/18 面试题
简历中自我评价范文3则
2013/12/14 职场文书
2014年乡镇民政工作总结
2014/12/02 职场文书
员工辞职信范文大全
2015/05/12 职场文书
如何在向量化NumPy数组上进行移动窗口
2021/05/18 Python
python for循环赋值问题
2021/06/03 Python