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提示[Errno 32]Broken pipe导致线程crash错误解决方法
Nov 19 Python
Python抓取手机号归属地信息示例代码
Nov 28 Python
python编程羊车门问题代码示例
Oct 25 Python
小白如何入门Python? 制作一个网站为例
Mar 06 Python
Python迭代器与生成器用法实例分析
Jul 09 Python
PySide和PyQt加载ui文件的两种方法
Feb 27 Python
python设计tcp数据包协议类的例子
Jul 23 Python
python脚本之一键移动自定格式文件方法实例
Sep 02 Python
python str字符串转uuid实例
Mar 03 Python
Python爬虫之Selenium实现关闭浏览器
Dec 04 Python
Django实现翻页的示例代码
May 24 Python
Python Django ORM连表正反操作技巧
Jun 13 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获取目标函数执行时间示例
2014/03/04 PHP
Laravel 集成 Geetest验证码的方法
2018/05/14 PHP
php处理多图上传压缩代码功能
2018/06/13 PHP
常用参考资料(手册)下载或者链接
2006/07/22 Javascript
javascript的键盘控制事件说明
2008/04/15 Javascript
利用CSS、JavaScript及Ajax实现高效的图片预加载
2013/10/16 Javascript
解析jQuery的三种bind/One/Live事件绑定使用方法
2013/12/30 Javascript
jquery提交form表单简单示例分享
2014/03/03 Javascript
jQuery基于ajax实现星星评论代码
2015/08/07 Javascript
JS模拟简易滚动条效果代码(附demo源码)
2016/04/05 Javascript
ajax的分页查询示例(不刷新页面)
2017/01/11 Javascript
详解nodejs微信公众号开发——6.自定义菜单
2017/04/13 NodeJs
JS异步处理的进化史深入讲解
2019/08/25 Javascript
在vue项目中 实现定义全局变量 全局函数操作
2020/10/26 Javascript
jquery实现拖拽添加元素功能
2020/12/01 jQuery
微信小程序之高德地图多点路线规划过程示例详解
2021/01/18 Javascript
[14:56]教你分分钟做大人:巫医
2014/10/30 DOTA
[39:52]2018DOTA2亚洲邀请赛 4.3 突围赛 EG vs Newbee 第一场
2018/04/04 DOTA
Python实现生成简单的Makefile文件代码示例
2015/03/10 Python
简单介绍Python中用于求最小值的min()方法
2015/05/15 Python
ubuntu17.4下为python和python3装上pip的方法
2018/06/12 Python
Python实现删除排序数组中重复项的两种方法示例
2019/01/31 Python
Python实现插入排序和选择排序的方法
2019/05/12 Python
Python基本数据结构之字典类型dict用法分析
2019/06/08 Python
Python turtle库绘制菱形的3种方式小结
2019/11/23 Python
python使用openCV遍历文件夹里所有视频文件并保存成图片
2020/01/14 Python
Soft Cotton捷克:来自爱琴海棉花的浴袍
2017/02/01 全球购物
澳大利亚和新西兰最大的在线旅行社之一:Aunt Betty
2019/08/07 全球购物
豪华床上用品 :Jennifer Adams
2019/09/15 全球购物
国际贸易专业个人求职信范文分享
2013/12/14 职场文书
大学本科毕业生求职信范文
2013/12/18 职场文书
甜品店的创业计划书范文
2014/01/02 职场文书
无财产无子女离婚协议书范文
2014/09/14 职场文书
学校运动会报道稿
2014/09/23 职场文书
2014年机关作风建设工作总结
2014/10/23 职场文书
2014年前台个人工作总结
2014/11/14 职场文书