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 07 Python
Python实现将16进制字符串转化为ascii字符的方法分析
Jul 21 Python
python 高效去重复 支持GB级别大文件的示例代码
Nov 08 Python
python 多线程重启方法
Feb 18 Python
python3+pyqt5+itchat微信定时发送消息的方法
Feb 20 Python
python在openstreetmap地图上绘制路线图的实现
Jul 11 Python
python 批量修改 labelImg 生成的xml文件的方法
Sep 09 Python
python 画3维轨迹图并进行比较的实例
Dec 06 Python
python 两种方法删除空文件夹
Sep 29 Python
python 自动刷新网页的两种方法
Apr 20 Python
Python 机器学习工具包SKlearn的安装与使用
May 14 Python
Django+Nginx+uWSGI 定时任务的实现方法
Jan 22 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
为什么夜间收到的中波电台比白天多
2021/03/01 无线电
S900/ ETON E1-XM 收音机
2021/03/02 无线电
PHP通过iconv将字符串从GBK转换为UTF8字符集
2011/07/18 PHP
让CodeIgniter的ellipsize()支持中文截断的方法
2014/06/12 PHP
深入理解PHP中的global
2014/08/19 PHP
PHP+jQuery翻板抽奖功能实现
2015/10/19 PHP
Zend Framework教程之Loader以及PluginLoader用法详解
2016/03/09 PHP
PHP实现的策略模式示例
2019/03/20 PHP
理解JAVASCRIPT中hasOwnProperty()的作用
2013/06/05 Javascript
JavaScript 函数惰性载入的实现及其优点介绍
2013/08/12 Javascript
一个JS函数搞定网页标题(title)闪动效果
2014/05/13 Javascript
jquery实现上下左右滑动的方法
2015/02/09 Javascript
AngularJS单选框及多选框实现双向动态绑定
2016/01/13 Javascript
详解BootStrap中Affix控件的使用及保持布局的美观的方法
2016/07/08 Javascript
jQuery事件与动画基础详解
2017/02/23 Javascript
利用jsonp与代理服务器方案解决跨域问题
2017/09/14 Javascript
原生js实现仿window10系统日历效果的实例
2017/10/31 Javascript
vue.js给动态绑定的radio列表做批量编辑的方法
2018/02/28 Javascript
在vue中,v-for的索引index在html中的使用方法
2018/03/06 Javascript
微信小程序基于高德地图查找位置并显示文字
2019/10/30 Javascript
[01:14:31]Secret vs VG 2018国际邀请赛淘汰赛BO3 第一场 8.23
2018/08/24 DOTA
python用ConfigObj读写配置文件的实现代码
2013/03/04 Python
python实现带错误处理功能的远程文件读取方法
2015/04/29 Python
Python之Web框架Django项目搭建全过程
2017/05/02 Python
python机器学习理论与实战(四)逻辑回归
2018/01/19 Python
python 获取当天凌晨零点的时间戳方法
2018/05/22 Python
为什么从Python 3.6开始字典有序并效率更高
2019/07/15 Python
Python对接六大主流数据库(只需三步)
2019/07/31 Python
Python3 hashlib密码散列算法原理详解
2020/03/30 Python
python中使用asyncio实现异步IO实例分析
2021/02/26 Python
阿迪达斯加拿大官网:Adidas加拿大
2016/08/25 全球购物
幼儿园端午节活动方案
2014/08/25 职场文书
2015学校六五普法工作总结
2015/04/22 职场文书
2016年国庆节假期旅游工作总结
2016/04/01 职场文书
大学生奶茶店创业计划书
2019/06/25 职场文书
浅谈如何提高PHP代码的质量
2021/05/28 PHP