Python项目实战之使用Django框架实现支付宝付款功能


Posted in Python onFebruary 23, 2021

一、前言

春节即将来临,大家肯定各种掏腰包花花花,小编相信大家在支付时候,微信、支付宝支付肯定是优先选择。今天小编心血来潮,为大家带来一个很有趣的项目,那就是使用Python web框架Django来实现支付宝支付,废话不多说,一起来看看如何实现吧。

二、建立django应用

我们来建立一个Django项目然后在里面创建一个应用,如图:

Python项目实战之使用Django框架实现支付宝付款功能

三、配置并启动

Python项目实战之使用Django框架实现支付宝付款功能

Python项目实战之使用Django框架实现支付宝付款功能

然后我们设置urls文件的内容,如图:

Python项目实战之使用Django框架实现支付宝付款功能

然后再在子应用中创建一个urls.py文件,当然你也可以直接将一些视图函数写在项目中的urls.py文件中。最后我们编写视图函数并把视图函数添加到urls.py文件中,如图:

Python项目实战之使用Django框架实现支付宝付款功能

Python项目实战之使用Django框架实现支付宝付款功能

最后我们需要提交更改,打开该项目manage.py文件所在的目录并打开cmd,输入如下命令:

python manage.py migrate

现在让我们来本地跑跑这个项目,还是在该目录中,如下:

python manage.py runserver

Python项目实战之使用Django框架实现支付宝付款功能

看到输出的结果表明这个子应用已经启动并返回了结果。我们也可以不用经过子应用直接在创建的项目根目录下运行启动Django应用,首先在pay目录下新建一个view.py文件,然后将其添加到该目录下的urls.py文件中,如下:

Python项目实战之使用Django框架实现支付宝付款功能

Python项目实战之使用Django框架实现支付宝付款功能

运行下看图:

Python项目实战之使用Django框架实现支付宝付款功能

四、登录支付宝并生成rsa密钥

首先登录咱们要收款的支付宝,地址:

https://auth.alipay.com/login/ant_sso_index.htm?goto=https%3A%2F%2Fopenhome.alipay.com%2Fplatform%2FappDaily.htm%3Ftab%3Dinfo

然后进行登录,如图:

Python项目实战之使用Django框架实现支付宝付款功能

然后点击RSA2(SHA256)后面的设置,点击公钥并下载支付宝密钥生成器或者openssl来生成密钥,这里我选择支付宝密钥生成器,如图:

Python项目实战之使用Django框架实现支付宝付款功能

然后点击它之后跳转到下载界面下载,如图:

Python项目实战之使用Django框架实现支付宝付款功能

下载好后打开该工具,选择好密钥长度和密钥格式并生成密钥,如图:

Python项目实战之使用Django框架实现支付宝付款功能

然后进入公私钥的目录,将这个复制到我们的Django项目的子应用目录中,并重命名,等下用的着,如图:

Python项目实战之使用Django框架实现支付宝付款功能

Python项目实战之使用Django框架实现支付宝付款功能

紧接着我们进入自己的开发者中心控制台,地址:

https://open.alipay.com/platform/developerIndex.htm

然后我们去创建一个应用,如图:

Python项目实战之使用Django框架实现支付宝付款功能

按照要求如实填写即可。然后我们来设置它的接口加密方式,如图:

Python项目实战之使用Django框架实现支付宝付款功能

Python项目实战之使用Django框架实现支付宝付款功能

验证好了之后填写刚刚生成的应用公钥,如图:

Python项目实战之使用Django框架实现支付宝付款功能

此时会出现应用公钥和支付宝公钥,将支付宝公钥保存起来,如图:

Python项目实战之使用Django框架实现支付宝付款功能

然后我们将产生的额应用公私钥和支付宝公钥保存为下列内容形式的文件,如图:

Python项目实战之使用Django框架实现支付宝付款功能

Python项目实战之使用Django框架实现支付宝付款功能

Python项目实战之使用Django框架实现支付宝付款功能将这三个文件都保存在rsakey这个文件夹中。现在准备工作都做好了,下面开始编写支付宝支付接口。

注:项目审核通过后才可以使用密钥调用支付宝接口噢!

四、PC端支付宝支付接口

这里我们使用一个类将它封装起来,如下:

from datetime import datetime
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from urllib.parse import quote_plus
from urllib.parse import urlparse, parse_qs
from base64 import decodebytes, encodebytes
import json
 
 
 
 
class AliPay(object):
  """
  支付宝支付接口(PC端支付接口)
  """
 
 
  def __init__(self, appid, app_notify_url, app_private_key_path,
         alipay_public_key_path, return_url, debug=False):
    self.appid = appid
    self.app_notify_url = app_notify_url
    self.app_private_key_path = app_private_key_path
    self.app_private_key = None
    self.return_url = return_url
    with open(self.app_private_key_path) as fp:
      self.app_private_key = RSA.importKey(fp.read())
    self.alipay_public_key_path = alipay_public_key_path
    with open(self.alipay_public_key_path) as fp:
      self.alipay_public_key = RSA.importKey(fp.read())
 
 
    if debug is True:
      self.__gateway = "https://openapi.alipaydev.com/gateway.do"
    else:
      self.__gateway = "https://openapi.alipay.com/gateway.do"
 
 
  def direct_pay(self, subject, out_trade_no, total_amount, return_url=None, **kwargs):
    biz_content = {
      "subject": subject,
      "out_trade_no": out_trade_no,
      "total_amount": total_amount,
      "product_code": "FAST_INSTANT_TRADE_PAY",
      # "qr_pay_mode":4
    }
 
 
    biz_content.update(kwargs)
    data = self.build_body("alipay.trade.page.pay", biz_content, self.return_url)
    return self.sign_data(data)
 
 
  def build_body(self, method, biz_content, return_url=None):
    data = {
      "app_id": self.appid,
      "method": method,
      "charset": "utf-8",
      "sign_type": "RSA2",
      "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
      "version": "1.0",
      "biz_content": biz_content
    }
 
 
    if return_url is not None:
      data["notify_url"] = self.app_notify_url
      data["return_url"] = self.return_url
 
 
    return data
 
 
  def sign_data(self, data):
    data.pop("sign", None)
    # 排序后的字符串
    unsigned_items = self.ordered_data(data)
    unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in unsigned_items)
    sign = self.sign(unsigned_string.encode("utf-8"))
    # ordered_items = self.ordered_data(data)
    quoted_string = "&".join("{0}={1}".format(k, quote_plus(v)) for k, v in unsigned_items)
 
 
    # 获得最终的订单信息字符串
    signed_string = quoted_string + "&sign=" + quote_plus(sign)
    return signed_string
 
 
  def ordered_data(self, data):
    complex_keys = []
    for key, value in data.items():
      if isinstance(value, dict):
        complex_keys.append(key)
 
 
    # 将字典类型的数据dump出来
    for key in complex_keys:
      data[key] = json.dumps(data[key], separators=(',', ':'))
 
 
    return sorted([(k, v) for k, v in data.items()])
 
 
  def sign(self, unsigned_string):
    # 开始计算签名
    key = self.app_private_key
    signer = PKCS1_v1_5.new(key)
    signature = signer.sign(SHA256.new(unsigned_string))
    # base64 编码,转换为unicode表示并移除回车
    sign = encodebytes(signature).decode("utf8").replace("\n", "")
    return sign
 
 
  def _verify(self, raw_content, signature):
    # 开始计算签名
    key = self.alipay_public_key
    signer = PKCS1_v1_5.new(key)
    digest = SHA256.new()
    digest.update(raw_content.encode("utf8"))
    if signer.verify(digest, decodebytes(signature.encode("utf8"))):
      return True
    return False
 
 
  def verify(self, data, signature):
    if "sign_type" in data:
      sign_type = data.pop("sign_type")
    # 排序后的字符串
    unsigned_items = self.ordered_data(data)
    message = "&".join(u"{}={}".format(k, v) for k, v in unsigned_items)
    return self._verify(message, signature)

为了便于调用,我们将这个Python文件放在子应用的目录中,命名为pay.py。

五、编写前端页面

我们通过前端的商品的名称和价格来生成对应的商品信息并发起付款请求,如下:

index.html(商品主页)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
   <style>
 table,table tr th, table tr td { border:1px solid #0094ff; }
    table { width:300px; min-height: 25px; line-height: 25px; text-align: center; border-collapse: collapse; padding:2px;}  
    a{
      text-decoration: none;
    }
</style>
</head>
<body>
  <h1>欢迎来到购物商场</h1>
  <table border="1">
  <thead>商品目录</thead>
  <tr>
    <td>商品名</td>
    <td>商品单价</td>
    <td>商品数量</td>
    <td>是否购买</td>
  </tr>
  <tr>
    <td>梨子</td>
    <td>0.1</td>
    <td>1</td>
    <td><a href="{% url 'dingdan' %}" rel="external nofollow" >购买</a></td>
  </table>
</body>
</html>

show.html(支付结果显示页)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <h1>支付结果:{{msg}}</h1>
</body>
</html>

六、编写视图函数处理渲染

from django.shortcuts import render,redirect
from django.http import HttpResponse,JsonResponse
from .pay import AliPay
import uuid
from urllib.parse import parse_qs
# Create your views here.
def index(request):
   return render(request,'index.html')
def dingdan(request):
  # 实例化AliPay
  alipay = AliPay(
    appid="自己的APPID",
    app_notify_url='http://127.0.0.1:8000/paypay/check/',#支付宝会向这个地址发送post请求
    return_url='http://127.0.0.1:8000/paypay/show/',#支付宝会向这个地址发送get请求
    app_private_key_path=r'C:\Users\Administrator\Desktop\pay\paypay\rsakey\private2048.txt', # 应用私钥
    alipay_public_key_path=r'C:\Users\Administrator\Desktop\pay\paypay\rsakey\paypublic.txt', # 支付宝公钥
    debug=True, # 默认是False
  )
  # 定义请求地址传入的参数
  res=alipay.direct_pay(
    subject='梨子', # 商品描述
    out_trade_no=str(uuid.uuid4()), # 订单号
    total_amount='0.1', # 交易金额(单位是元,保留两位小数)
  )
  #生成跳转到支付宝支付页面的url
  url='https://openapi.alipaydev.com/gateway.do?{0}'.format(res)
  return redirect(url)
 
def show(request):
  if request.method == 'GET':
    alipay = AliPay(
      appid="自己的APPID", 
      app_notify_url='http://127.0.0.1:8000/paypay/check/',
      return_url='http://127.0.0.1:8000/paypay/show/',
      app_private_key_path=r'C:\Users\Administrator\Desktop\pay\paypay\rsakey\private2048.txt', # 应用私钥
      alipay_public_key_path=r'C:\Users\Administrator\Desktop\pay\paypay\rsakey\paypublic.txt', # 支付宝公钥
      debug=True, # 默认是False
    )
    param=request.GET.dict() # 获取请求携带的参数并转换成字典类型
    sign=param.pop('sign', None) # 获取sign的值
    # 对sign参数进行验证
    statu = alipay.verify(param,sign)
    if statu:
      return render(request, 'show.html', {'msg': '支付成功'})
    else:
      return render(request, 'show.html', {'msg': '支付失败'})
  else:
    return render(request, 'show.html', {'msg': '只支持GET请求,不支持其它请求'})
 
def check(request):
  if request.method=='POST':
    alipay=AliPay(appid="自己的APPID",
      app_notify_url='http://127.0.0.1:8000/paypay/check/', # 支付宝会向这个地址发送post请求
      return_url='http://127.0.0.1:8000/show_msg/', # 支付宝会向这个地址发送get请求
      app_private_key_path=r'C:\Users\Administrator\Desktop\pay\paypay\rsakey\private2048.txt', # 应用私钥
      alipay_public_key_path=r'C:\Users\Administrator\Desktop\pay\paypay\rsakey\paypublic.txt', # 支付宝公钥
      debug=True,
    )
    body=request.body.decode('utf-8') # 转成字符串
    post_data = parse_qs(body) # 根据&符号分割
    post_dict = {}
    for k, v in post_data.items():
      post_dict[k] = v[0]
    sign = post_dict.pop('sign', None)
    status = alipay.verify(post_dict, sign)
    if status: # 支付成功
      return HttpResponse('支付成功')
    else:
      return HttpResponse('支付失败')
  else:
    return HttpResponse('只支持POST请求')

七、添加路由函数到url规则中

from django.urls import path
from . import views
urlpatterns=[
 path('',views.index,name='index'),
 path('dingdan/',views.dingdan,name='dingdan'),
 path('show/',views.show,name='show'),
 path('check/',views.check,name='check'),
]

八、运行项目

所有准备工作都做好了,我们赶紧来试着运行下项目吧,如下:

Python项目实战之使用Django框架实现支付宝付款功能

可以看到我们购买商品后链接成功跳转到支付界面。

九、总结

该支付宝支付环境在沙箱中实现,因此安全性毋庸置疑,代码小编已经打包好了,不过里面的appid还有公私钥需要大家自行填写噢。

原生SQL代码链接:https://github.com/cassieeric/python_crawler/tree/master/ZhiFuBao

到此这篇关于Python项目实战之使用Django框架实现支付宝付款功能的文章就介绍到这了,更多相关Django框架支付宝付款内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python读取json文件并将数据插入到mongodb的方法
Mar 23 Python
在Python的框架中为MySQL实现restful接口的教程
Apr 08 Python
Python的Bottle框架中获取制定cookie的教程
Apr 24 Python
在Python的Django框架中调用方法和处理无效变量
Jul 15 Python
Python实现将HTML转换成doc格式文件的方法示例
Nov 20 Python
基于python的图片修复程序(实现水印去除)
Jun 04 Python
对Python 内建函数和保留字详解
Oct 15 Python
Python cv2 图像自适应灰度直方图均衡化处理方法
Dec 07 Python
python实现维吉尼亚加密法
Mar 20 Python
python删除列表元素的三种方法(remove,pop,del)
Jul 22 Python
python集成开发环境配置(pycharm)
Feb 14 Python
利用Python实现字幕挂载(把字幕文件与视频合并)思路详解
Oct 21 Python
Python接口自动化系列之unittest结合ddt的使用教程详解
Feb 23 #Python
python利用opencv实现颜色检测
Feb 23 #Python
详解Python中openpyxl模块基本用法
Feb 23 #Python
python爬虫今日热榜数据到txt文件的源码
Feb 23 #Python
如何用Python和JS实现的Web SSH工具
Feb 23 #Python
Python 带星号(* 或 **)的函数参数详解
Feb 23 #Python
python解决OpenCV在读取显示图片的时候闪退的问题
Feb 23 #Python
You might like
探讨PHP调用时间格式的参数详解
2013/06/06 PHP
ThinkPHP调用百度翻译类实现在线翻译
2014/06/26 PHP
php函数式编程简单示例
2019/08/08 PHP
Extjs学习笔记之八 继承和事件基础
2010/01/08 Javascript
基于jQuery的js分页代码
2010/06/10 Javascript
JavaScript全排列的六种算法 具体实现
2013/06/29 Javascript
jquery事件的ready()方法使用详解
2015/11/11 Javascript
基于jQuery实现文本框只能输入数字(小数、整数)
2016/01/14 Javascript
详解Sea.js中Module.exports和exports的区别
2017/02/12 Javascript
3分钟了解vue数据劫持的原理实现
2019/05/01 Javascript
JS通过ajax + 多列布局 + 自动加载实现瀑布流效果
2019/05/30 Javascript
微信小程序实现左侧滑栏过程解析
2019/08/26 Javascript
[51:05]DOTA2上海特级锦标赛主赛事日 - 5 败者组决赛Liquid VS EG第一局
2016/03/06 DOTA
[01:16:50]DOTA2-DPC中国联赛 正赛 Phoenix vs CDEC BO3 第一场 3月7日
2021/03/11 DOTA
Python 字符串操作方法大全
2014/03/11 Python
Python基于分析Ajax请求实现抓取今日头条街拍图集功能示例
2018/07/19 Python
解决Python下imread,imwrite不支持中文的问题
2018/12/05 Python
python3使用QQ邮箱发送邮件
2020/05/20 Python
详解python做UI界面的方法
2019/02/27 Python
python实现串口自动触发工作的示例
2019/07/02 Python
Pytorch使用MNIST数据集实现基础GAN和DCGAN详解
2020/01/10 Python
CSS实现雨滴动画效果的实例代码
2019/10/08 HTML / CSS
萨克斯第五大道的折扣店:Saks Fifth Avenue OFF 5TH
2016/08/25 全球购物
雪花秀美国官方网站:韩国著名草本护肤化妆品品牌
2016/10/19 全球购物
Clearly澳大利亚:购买眼镜、太阳镜和隐形眼镜
2018/04/26 全球购物
亚洲最大的运动鞋寄售店:KicksCrew
2020/11/26 全球购物
法雷奥SQA(electric)面试问题
2016/01/23 面试题
音乐专业应届生教师求职信
2013/11/04 职场文书
学生检讨书如何写
2014/10/30 职场文书
学校学期工作总结
2015/08/13 职场文书
小学音乐课教学反思
2016/02/18 职场文书
2016大学优秀学生干部事迹材料
2016/03/01 职场文书
python用字节处理文件实例讲解
2021/04/13 Python
MySQL分库分表详情
2021/09/25 MySQL
关于 Python json中load和loads区别
2021/11/07 Python
PO模式在selenium自动化测试框架的优势
2022/03/20 Python