python调用支付宝支付接口流程


Posted in Python onAugust 15, 2019

项目演示:

一、输入金额

python调用支付宝支付接口流程

二、跳转到支付宝付款

python调用支付宝支付接口流程

三、支付成功

python调用支付宝支付接口流程

四、跳转回自己网站

python调用支付宝支付接口流程

在使用支付宝接口的前期准备:

1、支付宝公钥

2、应用公钥

3、应用私钥

4、APPID

5、Django 1.11.11 环境

1234均由阿里开放平台生成

如果你不是商户或者你只是想测试,阿里提供了沙箱环境供测试

沙箱环境下的商户账号和用户账号、支付宝app都是沙箱版的,不能用实际账号

这时候我们需要去阿里开放平台去生成一些1234参数

注册网址: https://openhome.alipay.com/platform/appDaily.htm?tab=info

python调用支付宝支付接口流程

点击设置应用公钥

python调用支付宝支付接口流程

下载签名生成工具,解压后找到 RSA签名验签工具.bat 文件打开

python调用支付宝支付接口流程

这个工具会自动保存应用公钥和应用私钥到 RSA密钥 文件夹

将应用公钥拷贝到网站窗口,点保存,在原应用公钥按钮旁就会自动生成支付宝公钥

我们需要将网站窗口生成的支付宝公钥也新建一个txt文件放到这里面

继续操作

修改三个txt文件的名字为英文,如:app_public.txt \  app_private.txt  \ alipay_public.txt

修改三个txt文件内容为固定格式:

-----BEGIN PUBLIC KEY-----  # 加上这行
        密钥部分
-----END PUBLIC KEY-----   # 同上

将三个文件copy到django项目下新建文件夹中,如:

python调用支付宝支付接口流程

你也可以放在app下面,都可以,随你自己,但你可以先按我的一模一样配置将项目先跑通。

建议新建alipay的文件夹,配置及相关py文件可以全部放到这里面来

接下来在settings配置文件中配置这三个txt文件的路径

我的配置:

ALIPAY_PUBLIC = os.path.join(BASE_DIR,'alipay_use','alipay','alipay_keys','alipay_public.txt')
APP_PUBLIC = os.path.join(BASE_DIR,'alipay_use','alipay','alipay_keys','app_public.txt')
APP_PRIVATE = os.path.join(BASE_DIR,'alipay_use','alipay','alipay_keys','app_private.txt')

alipay文件夹下新建alipay.py文件

alipay.py 代码如下:

# _*_ coding=utf-8 _*_
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 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)

这个Alipay类主要是用来生成一个包含订单详情、签名的大字典,然后把这个大字典加密成字符串拼接到支付宝付款网关接口路径后面

视图中重定向到该地址,支付宝处理完成后向我们的路由发get请求携带详细信息和签名,使用这个类的一个方法来校验签名即可

路由层(项目中)

urls.py

from django.contrib import admin
from django.conf.urls import url
from app01 import views
urlpatterns = [
  url('admin/', admin.site.urls),
  url('index/', views.index),
  url('result/', views.pay_result), # 支付宝处理完成后回调的get请求路由
  url('update_order/', views.update_order), # 支付宝处理完成后回调的post请求路由
]

视图层(app中)

views.py

import time
from urllib.parse import parse_qs
from django.conf import settings
from django.shortcuts import render, redirect, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from alipay_use.alipay.alipay import AliPay
def aliPay():
  obj = AliPay(
    appid="2016100100642208",               # 支付宝沙箱里面的APPID,需要改成你自己的
    app_notify_url="http://129.211.29.98/update_order/", # 如果支付成功,支付宝会向这个地址发送POST请求(校验是否支付已经完成),此地址要能够在公网进行访问,需要改成你自己的服务器地址
    return_url="http://129.211.29.98/result/",      # 如果支付成功,重定向回到你的网站的地址。需要你自己改,这里是我的服务器地址
    alipay_public_key_path=settings.ALIPAY_PUBLIC, # 支付宝公钥
    app_private_key_path=settings.APP_PRIVATE,   # 应用私钥
    debug=True, # 默认False,True表示使用沙箱环境测试
  )
  # 优化:在settings里面的设置后使用
  # obj = AliPay(
  #   appid=settings.APPID,
  #   app_notify_url=settings.NOTIFY_URL,
  #   return_url=settings.RETURN_URL,
  #   alipay_public_key_path=settings.PUB_KEY_PATH,
  #   app_private_key_path=settings.PRI_KEY_PATH,
  #   debug=True,
  # )
  return obj
@csrf_exempt
def index(request):
  if request.method == "GET":
    return render(request, 'index.html')
  # 实例化SDK里面的类AliPay
  alipay = aliPay()
  # 对购买的数据进行加密
  money = float(request.POST.get('price')) # 保留俩位小数 前端传回的数据
  out_trade_no = "x2" + str(time.time()) # 商户订单号  # 订单号可以有多中生成方式,可以百度一下
  # 1. 在数据库创建一条数据:状态(待支付)
  query_params = alipay.direct_pay(
    subject="充气式Saber", # 商品简单描述 这里一般是从前端传过来的数据
    out_trade_no=out_trade_no, # 商户订单号 这里一般是从前端传过来的数据
    total_amount=money, # 交易金额(单位: 元 保留俩位小数)  这里一般是从前端传过来的数据
  )
  # 拼接url,转到支付宝支付页面
  pay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(query_params)
  return redirect(pay_url)
@csrf_exempt
def update_order(request):
  """
  支付成功后,支付宝向该地址发送的POST请求(用于修改订单状态)
  :param request:
  :return:
  """
  if request.method == 'POST':
    body_str = request.body.decode('utf-8')
    post_data = parse_qs(body_str)
    post_dict = {}
    for k, v in post_data.items():
      post_dict[k] = v[0]
    alipay = aliPay()
    sign = post_dict.pop('sign', None)
    status = alipay.verify(post_dict, sign)
    if status:
      # 1.修改订单状态
      out_trade_no = post_dict.get('out_trade_no')
      print(out_trade_no)



      # 2. 根据订单号将数据库中的数据进行更新
      return HttpResponse('支付成功')
    else:
      return HttpResponse('支付失败')
  return HttpResponse('')
@csrf_exempt
def pay_result(request):
  """
  支付完成后,跳转回的地址
  :param request:
  :return:
  """
  params = request.GET.dict()
  sign = params.pop('sign', None)
  alipay = aliPay()
  status = alipay.verify(params, sign)
  if status:
    return HttpResponse('支付成功')
  return HttpResponse('支付失败')

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<form action="" method="post">
  <input type="text" name="price">
  <input type="submit">
</form>
</body>
</html>

需要装的模块:

--pycryptodome
--urllib
--base64

支付宝接口流程:

python调用支付宝支付接口流程

总结

以上所述是小编给大家介绍的python调用支付宝支付接口流程,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
python多线程操作实例
Nov 21 Python
python使用paramiko实现远程拷贝文件的方法
Apr 18 Python
Python实现批量更换指定目录下文件扩展名的方法
Sep 19 Python
利用python实现xml与数据库读取转换的方法
Jun 17 Python
python基于twisted框架编写简单聊天室
Jan 02 Python
通过Python 接口使用OpenCV的方法
Apr 02 Python
pandas全表查询定位某个值所在行列的方法
Apr 12 Python
Python 使用PIL numpy 实现拼接图片的示例
May 08 Python
Python实现一个带权无回置随机抽选函数的方法
Jul 24 Python
python自动化测试无法启动谷歌浏览器问题
Oct 10 Python
python3-flask-3将信息写入日志的实操方法
Nov 12 Python
python如何将图片转换素描画
Sep 08 Python
Python使用字典实现的简单记事本功能示例
Aug 15 #Python
Flask框架学习笔记之模板操作实例详解
Aug 15 #Python
Flask框架学习笔记之消息提示与异常处理操作详解
Aug 15 #Python
python打造爬虫代理池过程解析
Aug 15 #Python
使用selenium和pyquery爬取京东商品列表过程解析
Aug 15 #Python
如何爬取通过ajax加载数据的网站
Aug 15 #Python
Python K最近邻从原理到实现的方法
Aug 15 #Python
You might like
PHP中的array数组类型分析说明
2010/07/27 PHP
在smarty中调用php内置函数的方法
2013/02/07 PHP
thinkphp3.2.2前后台公用类架构问题分析
2014/11/25 PHP
php+redis实现消息队列功能示例
2019/09/19 PHP
js关于精确计算和数值格式化以及直接引js文件
2014/01/28 Javascript
浅谈$(document)和$(window)的区别
2015/07/15 Javascript
javascript中异常处理案例(推荐)
2016/10/03 Javascript
学习JavaScript图片预加载模块
2016/11/07 Javascript
使用jQuery操作DOM的方法小结
2017/02/27 Javascript
vue给input file绑定函数获取当前上传的对象完美实现方法
2017/12/15 Javascript
echarts鼠标覆盖高亮显示节点及关系名称详解
2018/03/17 Javascript
vue项目或网页上实现文字转换成语音播放功能
2020/06/09 Javascript
微信小程序实现点击生成随机验证码
2020/09/09 Javascript
[02:36]DOTA2英雄基础教程 帕格纳
2014/01/20 DOTA
python3 实现的人人影视网站自动签到
2016/06/19 Python
对Python中plt的画图函数详解
2018/11/07 Python
Python调用服务接口的实例
2019/01/03 Python
Python制作微信好友背景墙教程(附完整代码)
2019/07/17 Python
python线程信号量semaphore使用解析
2019/11/30 Python
python DataFrame转dict字典过程详解
2019/12/26 Python
python 实现简单的FTP程序
2019/12/27 Python
Python虚拟环境库virtualenvwrapper安装及使用
2020/06/17 Python
通过实例简单了解python yield使用方法
2020/08/06 Python
Python 创建守护进程的示例
2020/09/29 Python
Stefania Mode美国:奢华设计师和时尚服装
2018/01/07 全球购物
PatPat阿根廷:妈妈们的购物平台
2019/05/30 全球购物
怎样比较两个类型为String的字符串
2016/08/17 面试题
幼儿园教育教学反思
2014/01/31 职场文书
团日活动总结怎么写
2014/06/25 职场文书
2015年医院药剂科工作总结
2015/05/04 职场文书
2015年班主任德育工作总结
2015/05/21 职场文书
甲午大海战观后感
2015/06/02 职场文书
后天观后感
2015/06/08 职场文书
导游词之太湖
2019/10/08 职场文书
Java如何实现树的同构?
2021/06/22 Java/Android
Python使用pyecharts控件绘制图表
2022/06/05 Python