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调用浏览器并打开一个网址的例子
Jun 05 Python
Python自动登录126邮箱的方法
Jul 10 Python
python使用wmi模块获取windows下的系统信息 监控系统
Oct 27 Python
深入理解Python中的super()方法
Nov 20 Python
简单了解python模块概念
Jan 11 Python
python里 super类的工作原理详解
Jun 19 Python
对django layer弹窗组件的使用详解
Aug 31 Python
Python使用Slider组件实现调整曲线参数功能示例
Sep 06 Python
Python调用接口合并Excel表代码实例
Mar 31 Python
Python 操作 PostgreSQL 数据库示例【连接、增删改查等】
Apr 21 Python
Python打包exe时各种异常处理方案总结
May 18 Python
Django模型层实现多表关系创建和多表操作
Jul 21 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判断GIF图片是否为动画的方法
2020/09/04 PHP
深入了解PHP中的Array数组和foreach
2016/11/06 PHP
Thinkphp3.2简单解决多文件上传只上传一张的问题
2017/09/26 PHP
javascript 面向对象编程基础:继承
2009/08/21 Javascript
JavaScript 加号(+)运算符号
2009/12/06 Javascript
JSChart轻量级图形报表工具(内置函数中文参考)
2010/10/11 Javascript
父节点获取子节点的字符串示例代码
2014/02/26 Javascript
浅析jquery的js图表组件highcharts
2014/03/06 Javascript
jQuery中parents()方法用法实例
2015/01/07 Javascript
js的window.showModalDialog及window.open用法实例分析
2015/01/29 Javascript
jQuery内容过滤选择器用法分析
2015/02/10 Javascript
jQuery选择器源码解读(八):addCombinator函数
2015/03/31 Javascript
jQuery实现仿腾讯微博滑出效果报告每日天气的方法
2015/05/11 Javascript
用JavaScript动态建立或增加CSS样式表的实现方法
2016/05/20 Javascript
jquery实现ajax加载超时提示的方法
2016/07/23 Javascript
JavaScript版经典游戏之扫雷游戏完整示例【附demo源码下载】
2016/12/12 Javascript
js select下拉联动 更具级联性!
2020/04/17 Javascript
jquery dataTable 后台加载数据并分页实例代码
2017/06/07 jQuery
Vue SPA 首屏优化方案
2021/02/26 Vue.js
[48:52]DOTA2上海特级锦标赛A组小组赛#2 Secret VS CDEC第一局
2016/02/25 DOTA
深入分析在Python模块顶层运行的代码引起的一个Bug
2014/07/04 Python
Django中模型Model添加JSON类型字段的方法
2015/06/17 Python
Python实现自动上京东抢手机
2018/02/06 Python
Python实现动态添加属性和方法操作示例
2018/07/25 Python
python如何编写win程序
2020/06/08 Python
Yves Rocher捷克官方网站:植物化妆品的创造者
2019/07/31 全球购物
团员学习总结的自我评价范文
2013/10/14 职场文书
共产党员岗位承诺书
2014/05/29 职场文书
代领学位证书毕业证书委托书
2014/09/30 职场文书
健康教育主题班会
2015/08/14 职场文书
搞笑婚礼主持词开场白
2015/11/24 职场文书
2016年党员干部公开承诺书
2016/03/24 职场文书
Python3 多线程(连接池)操作MySQL插入数据
2021/06/09 Python
全面盘点MySQL中的那些重要日志文件
2021/11/27 MySQL
分享Python异步爬取知乎热榜
2022/04/12 Python
Java 轮询锁使用时遇到问题
2022/05/11 Java/Android