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实现的文本简单可逆加密算法示例
May 18 Python
Python如何实现MySQL实例初始化详解
Nov 06 Python
Python实现去除列表中重复元素的方法小结【4种方法】
Apr 27 Python
python实现简易数码时钟
Feb 19 Python
对python3中, print横向输出的方法详解
Jan 28 Python
使用 python pyautogui实现鼠标键盘控制功能
Aug 04 Python
Python爬虫运用正则表达式的方法和优缺点
Aug 25 Python
Python logging设置和logger解析
Aug 28 Python
python打印异常信息的两种实现方式
Dec 24 Python
Python3实现飞机大战游戏
Apr 24 Python
详解selenium + chromedriver 被反爬的解决方法
Oct 28 Python
一文读懂python Scrapy爬虫框架
Feb 24 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中用数组的方法设置cookies
2011/04/21 PHP
php的list()的一步操作给一组变量进行赋值的使用
2011/05/18 PHP
php启用zlib压缩文件的配置方法
2013/06/12 PHP
字符串长度函数strlen和mb_strlen的区别示例介绍
2014/09/09 PHP
php 使用mpdf实现指定字段配置字体样式的方法
2019/07/29 PHP
PhpStorm的使用教程(本地运行PHP+远程开发+快捷键)
2020/03/26 PHP
javascript算法学习(直接插入排序)
2011/04/12 Javascript
javascript小数四舍五入多种方法实现
2012/12/23 Javascript
Jquery实现弹出层分享微博插件具备动画效果
2013/04/03 Javascript
通过JS来判断页面控件是否获取焦点
2014/01/03 Javascript
jQuery实现的一个tab切换效果内部还嵌有切换
2014/08/10 Javascript
javascript编写贪吃蛇游戏
2015/07/07 Javascript
JS获取鼠标坐标位置实例分析
2016/01/20 Javascript
关于js原型的面试题讲解
2016/09/25 Javascript
EasyUI 结合JS导出Excel文件的实现方法
2016/11/10 Javascript
jQuery实现点击某个div打开层,点击其他div关闭层实例分析(阻止冒泡)
2016/11/18 Javascript
详解用node搭建简单的静态资源管理器
2017/08/09 Javascript
Nodejs实现爬虫抓取数据实例解析
2018/07/05 NodeJs
重学 JS:为啥 await 不能用在 forEach 中详解
2019/04/15 Javascript
简单了解vue 插值表达式Mustache
2020/07/22 Javascript
springboot+vue+对接支付宝接口+二维码扫描支付功能(沙箱环境)
2020/10/15 Javascript
python友情链接检查方法
2015/07/08 Python
Python 遍历列表里面序号和值的方法(三种)
2017/02/17 Python
python实现用户答题功能
2018/01/17 Python
pygame实现简易飞机大战
2018/09/11 Python
想学python 这5本书籍你必看!
2018/12/11 Python
Pycharm以root权限运行脚本的方法
2019/01/19 Python
深入了解Python iter() 方法的用法
2019/07/11 Python
python SVM 线性分类模型的实现
2019/07/19 Python
python中upper是做什么用的
2020/07/20 Python
法国娇韵诗官方旗舰店:Clarins是来自法国的天然护肤品牌
2018/06/30 全球购物
Waterford英国官方网站:世界上最受欢迎的优质水晶品牌
2019/08/17 全球购物
什么叫应用程序域?什么是托管代码?什么是强类型系统?什么是装箱和拆箱?什么是重载?CTS、CLS和CLR分别作何解释?
2012/05/23 面试题
出生证明范本
2015/06/15 职场文书
nginx的zabbix 5.0安装部署的方法步骤
2021/07/16 Servers
中国十大神话动漫电影排行榜 哪吒登顶 白蛇缘起排第七
2022/03/21 国漫