支付宝支付接入流程

news2024/12/23 4:05:05

一、 接入准备

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

在这里插入图片描述

点击开发工具中的沙箱

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

  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")

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

12 原子性|可见性|有序性|JMM内存模型

1 并发三大特性 1.1 原子性 一个或多个操作,要么全部执行,要么全部不执行。Java中,对基本数据类型的变量的读取和赋值操作是原子性操作,但不采取任何原子性保障措施的自增操作不是原子性的,如:i public c…

C语言系统化精讲(六):C语言选择结构和循环结构

文章目录 一、C语言选择结构1.1 if语句1.2 if…else语句1.3 else if语句1.4 if语句的嵌套1.5 条件运算符1.6 switch语句的基本形式1.7 多路开关模式的switch语句1.8 if…else语句和switch语句的区别 二、C语言循环结构2.1 C语言while循环和do while循环详解2.1.1 while循环2.1.…

基于机器视觉的停车位识别检测 计算机竞赛

简介 你是不是经常在停车场周围转来转去寻找停车位。如果你的车辆能准确地告诉你最近的停车位在哪里,那是不是很爽?事实证明,基于深度学习和OpenCV解决这个问题相对容易,只需获取停车场的实时视频即可。 该项目较为新颖&#xf…

为什么后端老是觉得前端简单?

首先,相对于后端来说,前端入门的门槛较低,有些人因程序员的高薪酬而转行,却又不愿学习更多的知识和技术,入行很久却还在做着最基础的工作,久而久之,前端工程师的技术水平参差不齐,进…

【嵌入式开发 Linux 常用命令系列 8 --代码格式修改工具 astyle】

文章目录 AStyle 介绍Ubuntu 下安装Windows 下安装 AStyle 介绍 AStyle,全名 Artistic Style,是一款源代码格式化工具。它可以自动格式化 C,C,C#,和Java源代码。使用它您可以轻松地对代码进行格式化,以满足…

python DevOps

1、用python的 subprocess就能写出ping 255个ip哪个不通。多进程就能快很多,用fork 2、子进程在循环中不写exit(),会发生再生成子进程,核心就是子进程下次循环就少一次,生出孙进程,循环少两次。。。直到结束 windows是没有os.fo…

Mac怎么清理磁盘空间?释放Mac磁盘空间有效方法

相信很多使用macOS系统的小伙伴都收到过提示“磁盘空间已满”消息,尤其是采用SSD固态硬盘的MacBook系列,120G的硬盘空间本就捉襟见肘,使用一段时间后,即使自己没有存放很多大文件, Mac的磁盘很快就满了。那么&#xff…

echarts的柱状图的重叠和堆叠实现两个柱体的显示和之前的差值显示

效果图 主要思路 准备三个柱体(原计划,实际进度,差值) 原计划和实际进度设置成重叠 {barWidth: 20,// yAxisIndex: 1,z: 1,name: 原计划,type: bar,stack: ab,emphasis: { // 点击柱体其他柱体颜色会变浅disabled: true},label…

山西电力市场日前价格预测【2023-10-27】

日前价格预测 预测说明: 如上图所示,预测明日(2023-10-27)山西电力市场全天平均日前电价为347.06元/MWh。其中,最高日前电价为618.09元/MWh,预计出现在18: 15。最低日前电价为163.49元/MWh,预计…

VM虚拟机的安装与配置及操作系统的安装

目录 一.操作系统 1.简介 2.常见操作系统 2.1 windows操作系统 2.2 UNIX操作系统 2.3 linux操作系统 2.4 mac操作系统 2.5 嵌入式操作系统 3.个人版本和服务器版本的区别 4.Linux的版本介绍 4.1 Debian 4.2 Ubuntu 4.3 Redhat 4.4 Fedora 4.5 centos 二.VM虚拟…

微前端系列-样式隔离、元素隔离

样式隔离问题 各个应用之间可能相互设置标签样式,会相互影响,或者影响全局样式,比如应用A给body设置样式,应用B也给body设置样式 方法一 样式增加不同前缀 每个应用通过前缀独立区分开,京东micro-app默认是采用的这…

pika皮卡丘RCE靶场

pika |拼接命令,直接 find 寻找根目录下的文件,使用 grep 过滤 127.0.0.1 | find / | grep flag

超声电机工作原理

超声波电机的工作原理 在压电陶瓷振子上加高频交流电压时,利用逆压电效应或电致伸缩效应使定子产生微观机械振动。并将这种振动通过共振放大和摩擦耦合变换成旋转或直线型运动。 超声波驱动有两个前提条件: 需在定子表面激励出稳态的质点椭圆运动轨迹…

NTP(Network Time Protocol 网络时间协议)

作用 大数据产生与处理系统是各种计算设备集群的,计算设备将统一、同步的标准时间用于记录各种事件发生时序,如 E-MAIL 信息、文件创建和访问时间、数据库处理时间等。大数据系统内不同计算设备之间控制、计算、处理、应用等数据或操作都具有时序性&…

荣耀推送服务消息分类标准

前言 为了提升终端用户的推送体验、营造良好可持续的通知生态,荣耀推送服务将对推送消息进行分类管理。 消息分类 定义 荣耀推送服务将根据应用类型、消息内容和消息发送场景,将推送消息分成服务通讯和资讯营销两大类别。 服务通讯类,包…

如何在宝塔面板安装配置MySQL数据库并实现公网访问

宝塔安装MySQL数据库,并内网穿透实现公网远程访问 文章目录 宝塔安装MySQL数据库,并内网穿透实现公网远程访问前言1.Mysql服务安装2.创建数据库3.安装cpolar3.2 创建HTTP隧道 4.远程连接5.固定TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网…

【科普】干货!带你从0了解移动机器人(六) (底盘结构类型)

牵引式移动机器人(AGV/AMR),通常由一个牵引车和一个或多个被牵引的车辆组成。牵引车是机器人的核心部分,它具有自主导航和定位功能,可以根据预先设定的路径或地标进行导航,并通过传感器和视觉系统感知周围环…

音视频开发(一)ffmpeg 简单学习

前言 简单音视频处理。 学习自: 小破站FFmpeg最强教学丨入门FFmpeg看这一篇就够了丨从入门到放弃系列_哔哩哔哩_bilibili 01 下载、配置_哔哩哔哩_bilibili 基础知识 音视频处理基本都是:采样-处理得到帧队列-编码得到包队列-封装得到文件。 视频…

怎么设置禁止使用U盘

怎么设置禁止使用U盘 在工作中,数据对企业来说是尤为重要的,一旦企业或机构的数据泄露,就会给企业或机构带来极大的损失,企业为了保护公司数据的安全,往往禁用公司电脑使用U盘,禁用U盘也成为了企业的必要措…

Allegro电商平台:为卖家打开全球市场,为消费者带来无限选择

Allegro电商平台是一个全球性的在线零售平台,为卖家提供了一个广阔的市场,让他们可以在全球范围内销售产品。这个平台以其丰富的产品类别、便捷的购物体验和优质的客户服务而受到卖家和消费者的欢迎。本文将介绍Allegro电商平台的特点,以及卖…