支付宝支付接入流程

一、 接入准备

支付宝支付流程没有微信那么复杂,而且支付宝支持沙箱。登录支付宝开放平台控制台

在这里插入图片描述

点击开发工具中的沙箱

在这里插入图片描述
接口加密方式,我这里使用的是自定义密钥。生成密钥的方式

  1. 使用支付宝官方提供的密钥工具,唯一要注意的是支付宝密钥工具生成的是 txt 格式的,也就是不包含头部和尾部标识的
    -----BEGIN PUBLIC KEY-----
    
    -----END PUBLIC KEY-----
    
  2. 使用 openssl 命令自己生成。
    openssl
    OpenSSL> genrsa -out app_private_key.pem 2048  #  私钥
    OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem  #  导出公钥
    OpenSSL> exit
    

我们需要的东西基本都有了。调试的使用可以下载工具支付宝客户端沙箱版 ,用沙箱账号进行支付。

开发

import logging
from enum import Enum

from Cryptodome.PublicKey import RSA
from alipay import AliPay, AliPayConfig

"""
支付宝支付接入
SDK 文档:https://gitee.com/yqmc/alipay/blob/master/README.zh-hans.md
pip install python-alipay-sdk --upgrade
"""


class AlipayType(Enum):
    WEB = 'web'  # 电脑网站支付
    WAP = 'wap'  # 手机网站支付
    APP = 'app'  # app支付
    MINI = 'mini'  # 小程序支付


class AliPayClient:
    def __init__(self, appid, app_private_key_path, alipay_public_key_path, is_sandbox=False, default_notify_url=None,
                 return_url=None):
        """
        初始化数据
        :param appid: APP ID
        :param app_private_key_path: 应用私钥路径
        :param alipay_public_key_path: 支付宝公钥路经
        :param is_sandbox:  是否是沙箱模式
        :param default_notify_url:  默认通知地址
        """
        self.appid = appid
        self.default_notify_url = default_notify_url
        self.return_url = return_url
        self.sandbox = is_sandbox
        self.alipay_gateway_url = 'https://openapi.alipay.com/gateway.do?' if not self.sandbox else 'https://openapi-sandbox.dl.alipaydev.com/gateway.do?'
        self.app_private_key_string = self.read_secret(app_private_key_path)
        self.alipay_public_key_string = self.read_secret(alipay_public_key_path)
        self.alipay = AliPay(
            appid=self.appid,
            app_notify_url=self.default_notify_url,
            app_private_key_string=self.app_private_key_string,
            alipay_public_key_string=self.alipay_public_key_string,
            sign_type="RSA2",
            debug=True,
            verbose=True,  # 输出调试数据
            config=AliPayConfig(timeout=15)  # 可选,请求超时时间
        )
        if self.sandbox:
            logging.debug('当前为沙箱环境')

    @staticmethod
    def read_secret(secret_path, import_key=False):
        """
        从文件加载秘钥
        :param secret_path:
        :param import_key: 是否需要导入秘钥
        :return:
        """
        with open(secret_path, "r") as fp:
            return RSA.importKey(fp.read()) if import_key else fp.read()

    def create_order(self, out_trade_no, amount, subject, notify_url=None, return_url=None,
                     pay_type=AlipayType.WEB.value):
        """
         创建支付订单
        :param out_trade_no: 订单号
        :param amount: 金额
        :param subject: 订单备注
        :param notify_url: 通知地址
        :param return_url: 回调地址
        :param pay_type: AlipayType支付类型
        :return: order_string
        """
        trade_client = {
            AlipayType.WEB.value: self.alipay.api_alipay_trade_page_pay,
            AlipayType.WAP.value: self.alipay.api_alipay_trade_wap_pay,
            AlipayType.APP.value: self.alipay.api_alipay_trade_app_pay,
            AlipayType.MINI.value: self.alipay.api_alipay_trade_create
        }
        kwargs = dict(
            out_trade_no=out_trade_no,
            total_amount=amount,
            subject=subject,
            notify_url=notify_url
        )
        pay_type in [AlipayType.WEB.value, AlipayType.WAP.value] and kwargs.update(return_url=return_url)
        order_string = trade_client[pay_type](**kwargs)
        return self.alipay_gateway_url + order_string

    def create_pre_order(self, subject, out_trade_no, amount, notify_url=None):
        """
        交易预创建(扫码支付)
        :param subject: 订单备注
        :param out_trade_no: 订单号
        :param amount: 金额
        :param notify_url: 通知地址
        return {'code': '10000', 'msg': 'Success', 'out_trade_no': '2023102401', 'qr_code': 'https://qr.alipay.com/bax01636yklunuyxijpc002f'}
        """
        resp = self.alipay.api_alipay_trade_precreate(
            subject=subject,
            out_trade_no=out_trade_no,
            total_amount=amount,
            notify_url=notify_url
        )
        return resp

    def refund(self, out_trade_no, refund_amount):
        result = self.alipay.api_alipay_trade_refund(out_trade_no=out_trade_no, refund_amount=refund_amount)
        return True if result.get("code") == "10000" else False

    def notify_verify(self, data):
        """
        验证回调通知:验证 alipay 的异步通知
         :param data:  来自支付宝回调 POST 给你的 data,字典格式。
                        data = {
                             "subject": "测试订单",
                             "gmt_payment": "2016-11-16 11:42:19",
                             "charset": "utf-8",
                             "seller_id": "xxxx",
                             "trade_status": "TRADE_SUCCESS",
                             "buyer_id": "xxxx",
                             "auth_app_id": "xxxx",
                             "buyer_pay_amount": "0.01",
                             "version": "1.0",
                             "gmt_create": "2016-11-16 11:42:18",
                             "trade_no": "xxxx",
                             "fund_bill_list": "[{\"amount\":\"0.01\",\"fundChannel\":\"ALIPAYACCOUNT\"}]",
                             "app_id": "xxxx",
                             "notify_time": "2016-11-16 11:42:19",
                             "point_amount": "0.00",
                             "total_amount": "0.01",
                             "notify_type": "trade_status_sync",
                             "out_trade_no": "xxxx",
                             "buyer_logon_id": "xxxx",
                             "notify_id": "xxxx",
                             "seller_email": "xxxx",
                             "receipt_amount": "0.01",
                             "invoice_amount": "0.01",
                             "sign": "xxx"
                        }
        """
        signature = data.pop("sign")

        # verification
        success = self.alipay.verify(data, signature)
        return success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/104786.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

idea + Docker-Compose 实现自动化打包部署(仅限测试环境)

一、修改docker.service文件,添加监听端口 vi /usr/lib/systemd/system/docker.service ExecStart/usr/bin/dockerd -H fd:// --containerd/run/containerd/containerd.sock -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock重启docker服务 systemctl daemo…

线性代数3:矢量方程

一、前言 欢迎回到系列文章的第三篇文章,内容是线性代数的基础知识,线性代数是机器学习背后的基础数学。在我之前的文章中,我介绍了梯队矩阵形式。本文将介绍向量、跨度和线性组合,并将这些新想法与我们已经学到的内容联系起来。本…

基于 Redis + Lua 脚本实现分布式锁,确保操作的原子性

1.加锁的Lua脚本: lock.lua --- -1 failed --- 1 success--- getLock key local result redis.call(setnx , KEYS[1] , ARGV[1]) if result 1 then--PEXPIRE:以毫秒的形式指定过期时间redis.call(pexpire , KEYS[1] , 3600000) elseresult -1;-- 如果value相同&…

数据清洗(data clean)

整理了下数据清洗的基本流程,异常值部分整理在了EDA中。

什么是简单网络管理协议(SNMP)

简单网络管理协议(SNMP:Simple Network Management Protocol)是由互联网工程任务组(IETF:Internet Engineering Task Force )定义的一套网络管理协议。该协议基于简单网关监视协议(SGMP&#xf…

React中的Virtual DOM(看这一篇就够了)

文章目录 前言了解Virtual DOMreact创建虚拟dom的方式React Element虚拟dom的流程虚拟dom和真实dom的对比后言 前言 hello world欢迎来到前端的新世界 😜当前文章系列专栏:react合集 🐱‍👓博主在前端领域还有很多知识和技术需要掌…

DevOps持续集成-Jenkins(3)

文章目录 DevOpsDevOps概述Jenkins实战3:实战1和实战2的加强版(新增SonarQube和Harbor)⭐环境准备⭐项目架构图对比Jenkins实战1和实战2,新增内容有哪些?SonarQube教程采用Docker安装SonarQube (在Jenkins所…

生成树协议:监控 STP 端口和交换机

什么是生成树协议 生成树协议 (STP) 用于网络交换机,以防止循环和广播风暴。在局域网 (LAN) 中,两条或多条冗余路径可以连接到同一网段。当交换机或网桥从所有可用端口传输帧时,这些帧开始在网…

基于单片机设计的智能窗帘控制系统

一、前言 智能家居技术在近年来取得了巨大的发展,并逐渐成为人们日常生活中的一部分。智能家居系统带来了便利、舒适和高效的生活体验,拥有广泛的应用领域,其中之一就是智能窗帘控制系统。 传统窗帘需要手动操作,打开或关闭窗帘…

华硕天选1天选2天选3天选4天选air原厂预装出厂系统恢复安装教程方法

华硕天选1天选2天选3天选4天选air原厂预装出厂系统恢复安装教程方法 第一:自备原装swm/esd/wim/iso等格式系统文件,以上这几种格式文件安装恢复非常简单,使用PE工具即可完成恢复安装,还有一种安装方法就是华硕zip工厂恢复模式 1.首先需要自…

Adaptive AUTOSAR RTA-VRTE工具链介绍

ETAS Adaptive AUTOSAR RTA-VRTE是一种面向服务架构的中间件方案,提供了自适应AutoSAR平台,为应用层软件提供了运行环境. RTA-VRTE start kit的构建系统在主机VM内执行,可以创建AUTOSAR自适应应用程序并将其部署到一个或多个目标ECU虚拟机.

【VPX610】 青翼科技基于6U VPX总线架构的高性能实时信号处理平台

板卡概述 VPX610是一款基于6U VPX架构的高性能实时信号处理平台,该平台采用2片TI的KeyStone系列多核DSP TMS320C6678作为主处理单元,采用1片Xilinx的Virtex-7系列FPGA XC7VX690T作为协处理单元,具有2个FMC子卡接口,各个处理节点之…

linux-文件系统

目录 一、文件系统 1.分区 2.文件系统分类 3.文件系统创建工具 4.查看文件系统的属性 5.挂载 6.buffer和cache 一、文件系统 1.分区 1-4个主分区 第五个序号开始,是逻辑分区 2.文件系统分类 vfs文件系统 ------------- virtualenv file System&#xff0…

智慧社区燃气管网监测系统

燃气易燃易爆,一旦操作不当或疏忽大意,极易引发燃气安全事故,造成严重后果,2023年10月24日,在吉林某小区,发生了燃气使用不当产生的爆炸导致了1人死亡,1人重伤,15人轻伤,…

【嵌入式开源库】timeslice的使用,完全解耦的时间片轮询框架构

完全解耦的时间片轮询框架构 简介项目代码timeslice.htimeslice.clist.hlist.c 创建工程移植代码实验函数说明timeslice_task_inittimeslice_task_addtimeslice_tak_deltimeslice_get_task_num 结尾 简介 timeslice是一个时间片轮询框架,他是一个完全解耦的时间片轮…

电脑视频怎么转音频mp3

如果你在电脑上观看视频时喜欢上某个片段的背景音乐,且想将喜欢的背景音乐制作为手机铃声。我是建议你将此视频转换为 MP3 格式,因为 MP3 几乎与所有设备相兼容,让你可以在不同设备上不受限制地去聆听它。那该如何转换呢?无需担心…

LinkedList概念+MyLinkedList的实现

文章目录 LinkedList笔记一、 LinkedList1.概念2.LinkedList的构造方法3.LinkedList的遍历 二、MyLinkedList的实现1.定义内部类2.打印链表、求链表长度、判断是否包含关键字3. 头插法和尾插法4.在任意位置插入5.删除结点6.清空链表 LinkedList笔记 一、 LinkedList 1.概念 L…

将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表

将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表 算法思路: 这个其实就是一个归并排序,我们这里两顺序表为升序,要合并成一个升序表 用i和j分别标记顺序表A和顺序表B的元素,然后新表是C 每次从A和…

HarmonyOS 自定义抽奖转盘开发(ArkTS)

介绍 本篇 Codelab 是基于画布组件、显式动画,实现的一个自定义抽奖圆形转盘。包含如下功能: 1. 通过画布组件 Canvas,画出抽奖圆形转盘。 2. 通过显式动画启动抽奖功能。 3. 通过自定义弹窗弹出抽中的奖品。 相关概念 ● Stack组件…

web自动化测试框架介绍

一、目的 web自动化测试作为软件自动化测试领域中绕不过去的一个“香饽饽”,通常都会作为广大测试从业者的首选学习对象,相较于C/S架构的自动化来说,B/S有着其无法忽视的诸多优势,从行业发展趋、研发模式特点、测试工具支持&…