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 04 Python
简单介绍Python中的floor()方法
May 15 Python
Python工程师面试题 与Python基础语法相关
Jan 14 Python
Python有序查找算法之二分法实例分析
Dec 11 Python
情人节快乐! python绘制漂亮玫瑰
Aug 18 Python
深入浅析Python 中 is 语法带来的误解
May 07 Python
对Python 检查文件名是否规范的实例详解
Jun 10 Python
django框架防止XSS注入的方法分析
Jun 21 Python
python爬虫神器Pyppeteer入门及使用
Jul 13 Python
浅析python,PyCharm,Anaconda三者之间的关系
Nov 27 Python
tensorflow2.0的函数签名与图结构(推荐)
Apr 28 Python
python 生成器需注意的小问题
Sep 29 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
CodeIgniter php mvc框架 中国网站
2008/05/26 PHP
php在多维数组中根据键名快速查询其父键以及父键值的代码
2011/05/07 PHP
Codeigniter框架实现获取分页数据和总条数的方法
2014/12/05 PHP
php实现cookie加密的方法
2015/03/10 PHP
Document:getElementsByName()使用方法及示例
2013/10/28 Javascript
ActiveX控件与Javascript之间的交互示例
2014/06/04 Javascript
全国省市二级联动下拉菜单 js版
2016/05/10 Javascript
设计模式中的facade外观模式在JavaScript开发中的运用
2016/05/18 Javascript
几种二级联动案例(jQuery\Array\Ajax php)
2016/08/13 Javascript
详解JavaScript常量定义
2017/01/03 Javascript
vue数据双向绑定原理解析(get & set)
2017/03/08 Javascript
原生JS实现不断变化的标签
2017/05/22 Javascript
关于angularJs清除浏览器缓存的方法
2017/11/28 Javascript
vue 指令之气泡提示效果的实现代码
2018/10/18 Javascript
vue-cli 打包后提交到线上出现 "Uncaught SyntaxError:Unexpected token" 报错
2018/11/06 Javascript
Vue动态面包屑功能的实现方法
2019/07/01 Javascript
vue 使用axios 数据请求第三方插件的使用教程详解
2019/07/05 Javascript
浅谈TypeScript 用 Webpack/ts-node 运行的配置记录
2019/10/11 Javascript
Threejs实现滴滴官网首页地球动画功能
2020/07/13 Javascript
Python urlopen 使用小示例
2008/09/06 Python
Python字符串匹配算法KMP实例
2015/07/18 Python
Python抓取电影天堂电影信息的代码
2016/04/07 Python
Python MySQL数据库连接池组件pymysqlpool详解
2017/07/07 Python
修改python plot折线图的坐标轴刻度方法
2018/12/13 Python
Django3.0 异步通信初体验(小结)
2019/12/04 Python
python 实现将list转成字符串,中间用空格隔开
2019/12/25 Python
Pytorch 实现计算分类器准确率(总分类及子分类)
2020/01/18 Python
Python导入数值型Excel数据并生成矩阵操作
2020/06/09 Python
python Selenium 库的使用技巧
2020/10/16 Python
Opencv python 图片生成视频的方法示例
2020/11/18 Python
弄清Pytorch显存的分配机制
2020/12/10 Python
Clos19英国:高档香槟、葡萄酒和烈酒在线购物平台
2020/07/10 全球购物
平安校园建设方案
2014/05/02 职场文书
大学生入党积极分子党校学习思想汇报
2014/10/25 职场文书
使用python+pygame开发消消乐游戏附完整源码
2021/06/10 Python
win11无法添加打印机怎么办? 提示windows无法打开添加打印机的解决办法
2022/04/05 数码科技