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包的五个简单准则简介
Jun 15 Python
Python pass详细介绍及实例代码
Nov 24 Python
Python3.x对JSON的一些操作示例
Sep 01 Python
微信跳一跳python自动代码解读1.0
Jan 12 Python
python删除服务器文件代码示例
Feb 09 Python
Windows下的Python 3.6.1的下载与安装图文详解(适合32位和64位)
Feb 21 Python
tensorflow 获取模型所有参数总和数量的方法
Jun 14 Python
对Python 窗体(tkinter)文本编辑器(Text)详解
Oct 11 Python
Python爬取商家联系电话以及各种数据的方法
Nov 10 Python
基于python框架Scrapy爬取自己的博客内容过程详解
Aug 05 Python
keras用auc做metrics以及早停实例
Jul 02 Python
Numpy ndarray 多维数组对象的使用
Feb 10 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有道翻译api调用方法实例
2014/12/22 PHP
WordPress中用于创建以及获取侧边栏的PHP函数讲解
2015/12/29 PHP
Laravel模型事件的实现原理详解
2018/03/14 PHP
PHP删除数组中指定值的元素常用方法实例分析【4种方法】
2018/08/21 PHP
ThinkPHP中图片按比例切割的代码实例
2019/03/08 PHP
javascript中的作用域scope介绍
2010/12/28 Javascript
jquery获取tagName再进行判断
2014/05/29 Javascript
9款2014最热门jQuery实用特效推荐
2014/12/07 Javascript
javascript实现多级联动下拉菜单的方法
2015/02/06 Javascript
酷炫jQuery全屏3D焦点图动画效果
2016/03/22 Javascript
vuejs动态组件给子组件传递数据的方法详解
2016/09/09 Javascript
javascript稀疏数组(sparse array)和密集数组用法分析
2016/12/28 Javascript
BootstrapValidator实现注册校验和登录错误提示效果
2017/03/10 Javascript
js Dom实现换肤效果
2017/10/21 Javascript
jQuery+CSS实现的标签页效果示例【测试可用】
2018/08/14 jQuery
简单了解vue中父子组件如何相互传递值(基础向)
2019/07/12 Javascript
webpack5 联邦模块介绍详解
2020/07/08 Javascript
[04:04]DOTA2亚洲邀请赛比赛场馆&酒店全攻略
2017/03/23 DOTA
Python3基础之基本运算符概述
2014/08/13 Python
Python matplotlib画图实例之绘制拥有彩条的图表
2017/12/28 Python
对Python 中矩阵或者数组相减的法则详解
2019/08/26 Python
python 子类调用父类的构造函数实例
2020/03/12 Python
Python判断字符串是否为空和null方法实例
2020/04/26 Python
Python通过字典映射函数实现switch
2020/11/06 Python
python实现马丁策略回测3000只股票的实例代码
2021/01/22 Python
amazeui模态框弹出后立马消失并刷新页面
2020/08/19 HTML / CSS
文员个人的求职信范文
2013/09/26 职场文书
高级护理实习生自荐信
2013/09/28 职场文书
致长跑运动员加油稿
2014/02/20 职场文书
电子工程专业毕业生求职信
2014/03/14 职场文书
2014全年工作总结
2014/11/27 职场文书
慰问信范文
2015/02/14 职场文书
2015年光棍节活动总结
2015/03/24 职场文书
详解Redis在SpringBoot工程中的综合应用
2021/10/16 Redis
python神经网络Xception模型
2022/05/06 Python
win10重装系统后上不了网怎么办 win10重装系统网络故障的解决办法
2022/07/23 数码科技