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实现读取并保存文件的类
May 11 Python
Python2.7+pytesser实现简单验证码的识别方法
Dec 29 Python
Python Web程序部署到Ubuntu服务器上的方法
Feb 22 Python
python爬取足球直播吧五大联赛积分榜
Jun 13 Python
使用django-guardian实现django-admin的行级权限控制的方法
Oct 30 Python
浅谈django url请求与数据库连接池的共享问题
Aug 29 Python
Python的条件锁与事件共享详解
Sep 12 Python
python3 tkinter实现添加图片和文本
Nov 26 Python
Pytorch之卷积层的使用详解
Dec 31 Python
python3读取csv文件任意行列代码实例
Jan 13 Python
使用python实现时间序列白噪声检验方式
Jun 03 Python
聊聊基于pytorch实现Resnet对本地数据集的训练问题
Mar 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批量删除jQuery操作
2017/07/23 PHP
PHP mysqli事务操作常用方法分析
2017/07/22 PHP
jQuery选择器的工作原理和优化分析
2011/07/25 Javascript
jQuery滚动加载图片效果的实现
2013/03/06 Javascript
对jQuary选择器的全面总结
2016/06/20 Javascript
jQuery EasyUI基础教程之EasyUI常用组件(推荐)
2016/07/15 Javascript
JS比较两个数值的大小实例
2016/11/25 Javascript
如何在AngularJs中调用第三方插件库
2017/05/21 Javascript
Node解决简单重复问题系列之Excel内容的获取
2018/01/02 Javascript
微信小程序事件流原理解析
2019/11/27 Javascript
微信小程序关键字变色实现代码实例
2019/12/13 Javascript
修改vue源码实现动态路由缓存的方法
2020/01/21 Javascript
[49:08]OpTic vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
python连接mongodb操作数据示例(mongodb数据库配置类)
2013/12/31 Python
在Python操作时间和日期之asctime()方法的使用
2015/05/22 Python
Python IDE PyCharm的基本快捷键和配置简介
2015/11/04 Python
Python模拟登录验证码(代码简单)
2016/02/06 Python
python 全文检索引擎详解
2017/04/25 Python
Python 迭代器与生成器实例详解
2017/05/18 Python
python 快速把超大txt文件转存为csv的实例
2018/10/26 Python
对Python多线程读写文件加锁的实例详解
2019/01/14 Python
拿来就用!Python批量合并PDF的示例代码
2020/08/10 Python
Python使用windows设置定时执行脚本
2020/11/12 Python
英国拳击装备购物网站:RDX Sports
2018/01/23 全球购物
Black Halo官方网站:购买连衣裙、礼服和连体裤
2018/06/13 全球购物
联强国际笔试题面试题
2013/07/10 面试题
自荐信的五个重要部分
2013/10/29 职场文书
毕业生的自我鉴定该怎么写
2013/12/02 职场文书
安全生产计划书
2014/05/04 职场文书
教师三严三实对照检查材料
2014/09/25 职场文书
2014年大学班级工作总结
2014/11/14 职场文书
2015年母亲节活动策划方案
2015/05/04 职场文书
2019年干货:自我鉴定
2019/03/25 职场文书
mysql timestamp比较查询遇到的坑及解决
2021/11/27 MySQL
关于MySQL临时表为什么可以重名的问题
2022/03/22 MySQL
Hive日期格式转换方法总结
2022/06/25 数据库