当前位置: 首页 > article >正文

Springboot整合支付宝支付

支付宝支付功能

  • 步骤一:沙箱配置
    • 支付宝沙箱配置
  • 步骤二:使用内网穿透
  • 步骤三:开始对接
    • SDK
    • 配置文件
    • 支付

步骤一:沙箱配置

支付宝沙箱配置

需要有支付宝沙箱:提供一个虚拟的支付环境,用于测验调试,点击这里进入沙箱环境,可以打开支付宝开放平台
支付宝开放平台
image.png
在这里我们只需要里面的几个数据,分别为:

  1. 支付宝网关地址
  2. 支付宝的公钥和私钥
  3. 支付宝的APPID
  4. 支付宝提供的SDK

步骤二:使用内网穿透

目的是为了允许外部网络用户访问,这里可以使用natapp
为什么需要内网穿透呢?因为本质上调用人家的服务,当请求以后,支付宝需要返回给你信息,这就需要你的地址。这样才能找到我们的接口,我们才能根据他返回的信息做出一些业务处理。
natapp官网
image.png
使用免费的即可,需要进行实名认证
image.png
填写信息
image.png
在我的隧道中查看
image.png
下载客户端,根据自己需要下载我是windows64的
image.png
运行natapp
image.png
image.png
双击natapp
注意:需要将本地的web服务端口改为80,也就是将我们的项目端口改为80端口,这个80端口可以在natapp-》我的隧道-》隧道配置中进行修改
image.png
然后启动自己的web项目就可以访问到了,注意隧道的80端口一定要和项目的端口一样也是80,如果要修改,则去natapp中修改完再和项目保持一致

步骤三:开始对接

SDK

<dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-java</artifactId><version>4.9.28.ALL</version>
</dependency>

配置文件

server:port: 80alipay:# appidappId: 自己的支付宝APPID# 应用私钥appPrivateKey: 支付宝开放平台应用私钥,前面已经介绍# 支付宝公钥alipayPublicKey: 支付宝开放平台应用公钥,前面已经介绍# 回调接口,支付宝通过什么接口通知你,这里就是填写具体接口地址,我们使用公网的地址以及接口uri /公网地址/uri# http://iw3naq.natappfree.cc是内网穿透的路径notifyUrl: http://iw3naq.natappfree.cc/alipay/notify
/*** 读取yml中的配置信息,自动填充到对应的属性*/
@Data
@Component
@ConfigurationProperties(prefix = "alipay")
public class AliPayConfig {private String appId;private String appPrivateKey;private String alipayPublicKey;private String notifyUrl;}

支付

1.具体步骤

  • 必须传递如下参数(支付订单号(必须唯一), 订单名称,订单金额)
  • 创建支付客户端 设定appid 公钥密钥等等信息,用于知道这个订单谁发出的,钱给到谁的账户
  • 将请求的订单号等等写入支付的请求对象中 并且请求对象设置回调接口以及支付后的接口
  • 支付客户端对象根据支付请求对象去执行,调用支付宝API
  • 这个API接口会返回一个表单页面,让用户去输入帐号密码(也就是谁来支付),成功显示金额等等信息,填写支付密码进行转账
  • 转账以后无论成功与否,支付宝都会调用你的回调接口,传入数据
    2.代码
    业务参数
/*** 支付宝支付请求对象 所需要的参数*/
@Data
public class PayVO {private String out_trade_no; // 商户订单号 必填private String subject; // 订单名称 必填private BigDecimal total_amount; // 付款金额 必填private String body; // 商品描述 可空
}

支付宝客户端执行

@RestController
@RequestMapping("/alipay")
@Transactional(rollbackFor = Exception.class)
public class AliPayController {@ResourceAliPayConfig aliPayConfig;@Resourceprivate ShopOrderDao shopOrderMapper;private static final String GATEWAY_URL = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";private static final String FORMAT = "JSON";private static final String CHARSET = "utf-8";private static final String SIGN_TYPE = "RSA2";/*** 支付接口 传入业务参数* 支付是一个我向你要钱的过程,设置api参数就是为了,知道收钱的人是谁,* 当执行以后支付宝会返回一个登录页面,支付的人输入帐号密码。并且确定金额输入支付密码进行支付* @param aliPay* @param httpResponse* @throws Exception*/// 这里使用Get其实不是很恰当,应该使用post,这里为了调试方便使用Get@GetMapping("/pay")public void pay(PayVO aliPay, HttpServletResponse httpResponse) throws Exception {// 1、根据支付宝的配置生成一个支付客户端 客户端用于去调用支付宝的API// 官方写法AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL, aliPayConfig.getAppId(),aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);// 2、创建一个支付请求对象AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();// 设置回调接口request.setNotifyUrl(aliPayConfig.getNotifyUrl());// 商户订单号,商户网站订单系统中唯一订单号,必填,支付宝不允许有两个相同的订单号// 使用uuid生成 避免重复aliPay.setOut_trade_no(UUID.randomUUID().toString());String out_trade_no = aliPay.getOut_trade_no();// 付款金额,必填BigDecimal total_amount = aliPay.getTotal_amount();// 订单名称,必填String subject = aliPay.getSubject();// 商品描述,可空String body = aliPay.getBody();// 设置 业务参数 是一个json对象// 这个json对象 支付宝后台回去识别,根据这些参数进行处理,例如 金额,订单名称,商品描述request.setBizContent("{"out_trade_no":"" + out_trade_no + "","+ ""total_amount":"" + total_amount + "","+ ""subject":"" + subject + "","+ ""body":""+ body +"","+ ""product_code":"FAST_INSTANT_TRADE_PAY"}");// 支付完以后跳转的地址request.setReturnUrl("http://loaclhost:9090/hello/pay");// 3. 客户端执行请求// 客户端执行请求,拿到响应的结果,返回给浏览器String form = "";try {// 调用阿里的SDK生成表单// 会收到支付宝的响应,响应的是一个页面,一开始是登陆,然后显示金额,让用户输入密码进行付款form = alipayClient.pageExecute(request).getBody();} catch (AlipayApiException e) {e.printStackTrace();}httpResponse.setContentType("text/html;charset=" + CHARSET);// 直接将完整的表单html输出到页面httpResponse.getWriter().write(form);httpResponse.getWriter().flush();httpResponse.getWriter().close();}

3.效果
输入地址
http://localhost:80/alipay/pay?subject=测试商品&total_amount=1000
支付宝返回页面
image.png
输入帐号密码(沙箱有测试的密码)
image.png
image.png
输入支付密码支付
image.png
image.png
4.回调接口
支付宝返回信息
image.png

"gmt_create" -> "2024-03-16 22:40:26""charset" -> "utf-8""gmt_payment" -> "2024-03-16 22:40:30""notify_time" -> "2024-03-16 22:40:31""subject" -> "测试商品""sign" -> "XfBcgT1lIYpxYm0DzaBtLz7WjzxHxhBK4gUdmDCtD/JTAwhohqu""buyer_id" -> "2088722031942622""body" -> "null""invoice_amount" -> "1000.00""version" -> "1.0""notify_id" -> "2024031601222224031142620502419""fund_bill_list" -> "[{"amount":"1000.00","fundChannel":"ALIPAYACCOUNT"}]""notify_type" -> "trade_status_sync""out_trade_no" -> "96b14931-b0a7-49bb-aa93-498432247a4""total_amount" -> "1000.00""trade_status" -> "TRADE_SUCCESS""trade_no" -> "20240316220014426205023040""auth_app_id" -> "9021000135634074""receipt_amount" -> "1000.00""point_amount" -> "0.00""buyer_pay_amount" -> "1000.00""app_id" -> "90210001354""sign_type" -> "RSA2""seller_id" -> "20887976059"

5.具体实现

@PostMapping("/notify")  // 注意这里必须是POST接口
public String payNotify(HttpServletRequest request) throws Exception {// 判断返回状态trade_status 支付成功是TRADE_SUCCESSif (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {System.out.println("=========支付宝异步回调========");Map<String, String> params = new HashMap<>();// 返回的所有元素 其中有gmt_create=2024-03-16 22:26:17, charset=utf-8, gmt_payment=2024-03-16 22:26:21, notify_time=2024-03-16 22:26:23, subject=测试商品Map<String, String[]> requestParams = request.getParameterMap();for (String name : requestParams.keySet()) {// servlet写法 通过key获取valueparams.put(name, request.getParameter(name));}System.out.println(params);System.out.println(params.size());String tradeNo = params.get("out_trade_no");String gmtPayment = params.get("gmt_payment");// 支付宝验签// 这里必须要初始化不然报错if (Factory.Payment.Common().verifyNotify(params)) {// 验签通过System.out.println("交易名称: " + params.get("subject"));System.out.println("交易状态: " + params.get("trade_status"));System.out.println("支付宝交易凭证号: " + params.get("trade_no"));System.out.println("商户订单号: " + params.get("out_trade_no"));System.out.println("交易金额: " + params.get("total_amount"));System.out.println("买家在支付宝唯一id: " + params.get("buyer_id"));System.out.println("买家付款时间: " + params.get("gmt_payment"));System.out.println("买家付款金额: " + params.get("buyer_pay_amount"));// 更新订单未已支付// 做一些业务上的处理 例如说支付成功以后 更新订单状态 改为已支付等等ShopOrder order = new ShopOrder();order.setId(tradeNo);order.setStatus("1");order.setZhhifuTime(gmtPayment);shopOrderMapper.save(order);}}return "success";}

以上代码可能有问题,需要调整,sdk没有初始化
修改代码

/*** 读取yml中的配置信息,自动填充到对应的属性*/
@Data
@Component
@ConfigurationProperties(prefix = "alipay")
public class AliPayConfig {private String appId;private String appPrivateKey;private String alipayPublicKey;private String notifyUrl;/*** 初始化sdk 这样回调接口的时候 才能知道sdk的基础信息*/@PostConstructpublic void init() {// 设置参数(全局只需设置一次)Config config = new Config();config.protocol = "https";config.gatewayHost = "openapi-sandbox.dl.alipaydev.com";config.signType = "RSA2";config.appId = this.appId;config.merchantPrivateKey = this.appPrivateKey;config.alipayPublicKey = this.alipayPublicKey;config.notifyUrl = this.notifyUrl;Factory.setOptions(config);System.out.println("=======支付宝SDK初始化成功=======");}
}

完成

相关文章:

Springboot整合支付宝支付

支付宝支付功能 步骤一&#xff1a;沙箱配置支付宝沙箱配置 步骤二&#xff1a;使用内网穿透步骤三&#xff1a;开始对接SDK配置文件支付 步骤一&#xff1a;沙箱配置 支付宝沙箱配置 需要有支付宝沙箱&#xff1a;提供一个虚拟的支付环境&#xff0c;用于测验调试&#xff0…...

deepseek+kimi一键生成PPT

1、deepseek生成大纲内容 访问deepseek官方网站&#xff1a;https://www.deepseek.com/ 将你想要编写的PPT内容输入到对话框&#xff0c;点击【蓝色】发送按钮&#xff0c;让deepseek生成内容大纲&#xff0c;并以markdown形式输出。 等待deepseek生成内容完毕后&#xff0c…...

Druid GetConnectionTimeoutException解决方案之一

> Druid版本&#xff1a;v1.2.18 最近项目中经常出现&#xff1a;com.alibaba.druid.pool.GetConnectionTimeoutException: wait millis 120000, active 0, maxActive 128, creating 0, createErrorCount 2&#xff0c;但是其他平台连接这个数据源正常的 于是做了一个实验复…...

基于ssm的超市订单管理系统

一、系统架构 前端&#xff1a;jsp | web components | jquery | css | ajax 后端&#xff1a;spring | springmvc | mybatis 环境&#xff1a;jdk1.8 | mysql | maven | tomcat 二、代码及数据 三、功能介绍 01. 登录 02. 首页 03. 订单管理 04. 供应…...

AnyPlace:学习机器人操作的泛化目标放置

25年2月来自多伦多大学、Vector Inst、上海交大等机构的论文“AnyPlace: Learning Generalized Object Placement for Robot Manipulation”。 由于目标几何形状和放置的配置多种多样&#xff0c;因此在机器人任务中放置目标本身就具有挑战性。为了解决这个问题&#xff0c;An…...

wps配置deepseek

wps 配置deepseek https://e6jy62bip4.feishu.cn/docx/R09IdpU5HoADyDxcgfQcjpR8nnb...

github不翻墙就可以访问

目录 简介资料准备windows平台设置下载运行git设置firefox设置 ubuntu平台设置下载启动服务设置系统代理git设置firefox设置证书 注意事项 简介 由于github访问不稳定,严重影响了国内软件开发,在网上搜索并验证了一些方法.现在整理出来一个可以正常使用的方法, 在windows和Lin…...

【DeepSeek】在本地计算机上部署DeepSeek-R1大模型实战(完整版)

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈人工智能与大模型应用 ⌋ ⌋ ⌋ 人工智能&#xff08;AI&#xff09;通过算法模拟人类智能&#xff0c;利用机器学习、深度学习等技术驱动医疗、金融等领域的智能化。大模型是千亿参数的深度神经网络&#xff08;如ChatGPT&…...

基于全志T507的边缘计算机,推动光伏电站向智能运维转型

智能监控与维护 光伏电站通常分布在广阔的地域内&#xff0c;传统的监控方式往往需要大量的人力物力进行现场检查和数据采集。采用全志T507为核心的嵌入式工控机或边缘计算控制器可以实现光伏电站的实时监测&#xff0c;通过连接传感器网络收集电站各个组件的工作状态信息&…...

Swift的方法派发机制

1. 静态派发&#xff08;Static Dispatch&#xff09; 静态派发在编译时确定方法的具体实现&#xff0c;调用时直接跳转到该实现。静态派发的优点是性能高&#xff0c;因为不需要运行时查找方法实现。 适用场景&#xff1a; 值类型&#xff08;Struct 和 Enum&#xff09;&am…...

用户认证练习实验

一.拓扑 二.sw2配置 三.ip配置 四.dhcp分配IP地址 五.安全区域配置 六.防火墙地址组信息 七.管理员 创建管理员角色 创建管理员 启动tenlnet 八.用户认证配置 认证策略 九.安全策略配置...

Miniforge —— 轻量化的 conda 解决方案

引言 在日常使用中&#xff0c;我们常常使用 Anaconda 或 Miniconda 来管理 Python 环境和包。但由于 Anaconda/Miniconda 属于商业产品&#xff0c;当企业规模超过一定人数时就会涉及付费问题。相比之下&#xff0c;Miniforge 是由社区主导维护的一个完全免费的替代方案&…...

【登录认证】

目录 一. 会话技术1.1 cookie1.2 session1.3 令牌方案 二. JWT令牌三. 过滤器Filter四. 拦截器Interceptor \quad 一. 会话技术 \quad \quad 1.1 cookie \quad \quad 1.2 session \quad \quad 1.3 令牌方案 \quad \quad 二. JWT令牌 \quad \quad 三. 过滤器Filter \quad \quad …...

10bit VS 8bit 视频:色彩深度的较量,谁才是视觉盛宴的王者?

10bit 和 8bit 视频 10bit 视频和 8bit 视频的主要区别在于色彩深度和细节表现能力。10bit 视频具有更高的色彩深度和更丰富的细节表现,能够提供更平滑的色彩过渡和更真实的图像质量,但需要更多的存储空间和带宽。8bit 视频则在存储和传输方面更加高效,适合于对存储空间和带…...

DeepSeek 赋能智慧教育 | 讯方“教学有方”大模型全面接入 DeepSeek!

国产 DeepSeek 大模型以强大的深度学习能力和广泛应用场景迅速火爆全球&#xff0c;其在智能对话、文本创作、语义解析、计算推理、代码生成与补全等多个应用领域&#xff0c;展现出了无与伦比的实力和魅力。2月10日 &#xff0c;由讯方技术自研的教育行业大模型“教学有方”全…...

代码随想录算法营Day36 | 56. 合并区间,738. 单调递增的数字,968. 监控二叉树

56. 合并区间 每当遇到不重叠的区间就append到结果数组里&#xff0c;遇到重叠的就更新结果数组最后一位的区间的end值。 class Solution:def merge(self, intervals: List[List[int]]) -> List[List[int]]:intervals.sort()res []for start,end in intervals:if len(res…...

Unity中自定义协程的简单实现

在 Unity 中&#xff0c;协程&#xff08;Coroutine&#xff09;是一种非常强大的工具&#xff0c;它允许我们在不阻塞主线程的情况下&#xff0c;将代码的执行分成多个步骤&#xff0c;在不同的帧中执行。 Unity中协程实现原理 迭代器与状态机&#xff1a;本质上是基于C#的迭…...

C++ 设计模式-单例模式

以下是一个使用 C 实现的线程安全单例模式示例&#xff0c;结合配置管理器的经典场景&#xff0c;并附带完整测试代码&#xff1a; #include <iostream> #include <unordered_map> #include <mutex> #include <thread> #include <vector> #incl…...

Ubuntu 上安装和配置 Apache RocketMQ 4.7.1

在 Ubuntu 上安装和配置 Apache RocketMQ 4.7.1 需要以下步骤。RocketMQ 是一个分布式消息队列系统&#xff0c;通常需要安装 Namesrv&#xff08;Name Server&#xff09;和 Broker 组件。 1. 系统准备 更新系统和安装依赖 运行以下命令更新系统并安装必要的依赖项&#xff…...

打开Visual Studio Code的时候发现未检测到适用于linux的windows子系统,那么该问题要如何解决?

两个月没有使用vscode编写代码&#xff0c;今天使用的时候发现了以上的问题导致我的vscode无法编写程序&#xff0c;接下来我将本人解决该问题的思路分享给大家。 首先我们要清楚WSL是适用于linux的window的子系统&#xff0c;是一个在Windows 10\11上能够运行原生Linux二进制可…...

Linux(socket网络编程)TCP连接

Linux&#xff08;socket网络编程&#xff09;TCP连接 基础文件目录函数系统进程控制函数fork()exec系列函数void abort(void)void assert(int expression)void exit(int status)void _exit(int status)int atexit(void (*func)(void))int on_exit(void (*function)(int,void*)…...

力扣刷题 遍历字符串

根据网上的学习 对遍历字符串 学习了一些自己的见解。给一个字符串组成的句子(带空格或标点)&#xff0c;然后对句中单个字符串进行一系列处理的题目 参考链接 1805. 字符串中不同整数的数目 - 力扣&#xff08;LeetCode&#xff09; 模版1 s " "; //这里在最后一…...

深度剖析观察者模式:从理论到实战的Java实现

在软件设计中&#xff0c;观察者模式&#xff08;Observer Pattern&#xff09; 是一种高频使用的行为型设计模式&#xff0c;它定义了对象之间一对多的依赖关系&#xff0c;使得当一个对象状态改变时&#xff0c;其所有依赖对象&#xff08;观察者&#xff09;会自动收到通知并…...

Rust学习总结之所有权(一)

不管是计算机的哪种语言&#xff0c;都有内存的管理方式。主流有两种&#xff0c;一是以C为代表的由开发者来决定申请和释放内存&#xff0c;二是以Python为代表的通过语言本身的垃圾回收机制来自动管理内存。Rust开辟了第三种方式&#xff0c;通过所有权系统管理内存。 Rust所…...

汇编简介常用语法

为什么要有汇编 因为Cortex-A芯片一上电SP指针还没初始化&#xff0c;C环境还没准备 好&#xff0c;所以肯定不能运行C代码&#xff0c;必须先用汇编语言设置好C环境&#xff0c;比如初始化DDR、设置SP 指针等等&#xff0c;当汇编把C环境设置好了以后才可以运行C代码 GNU语法…...

xtquant库在量化交易中的安装与实战应用

xtquant库在量化交易中的安装与实战应用 技术背景与应用场景 在量化交易领域&#xff0c;xtquant库作为迅投官方开发的Python包&#xff0c;扮演着至关重要的角色。它主要用于与MiniQMT通信&#xff0c;使得开发者能够获取MiniQMT中的数据&#xff0c;并下达交易指令。通过xt…...

ANR学习

一、ANR 概述 ANR 是 Android 系统用于监控应用是否及时响应的关键机制。形象地说&#xff0c;如同设置定时炸弹场景&#xff1a;系统的中控系统&#xff08;system_server 进程&#xff09;启动倒计时&#xff0c;若应用进程在规定时间内未完成特定任务&#xff0c;中控系统将…...

前端知识速记--JS篇:instanceof

前端知识速记–JS篇&#xff1a;instanceof 在JavaScript中&#xff0c;instanceof运算符用于检测一个对象是否是另一个对象的实例。它的基本语法为&#xff1a;obj instanceof Constructor。如果obj是Constructor的实例&#xff0c;它将返回true&#xff0c;否则返回false。这…...

Tcp_socket

Tcp不保证报文完整性&#xff08;面向字节流&#xff09; 所以我们需要在应用层指定协议&#xff0c;确保报文完整性 // {json} -> len\r\n{json}\r\n bool Encode(std::string &message) {if(message.size() 0) return false;std::string package std::to_string(m…...

idea插件开发,如何获取idea设置的系统语言

手打不易&#xff0c;如果转摘&#xff0c;请注明出处&#xff01; 注明原文&#xff1a;https://zhangxiaofan.blog.csdn.net/article/details/145578160 版本要求 大于 2024.3 错误用法 网上有的说使用&#xff1a;UIUtil com.intellij.util.ui.UIUtil 代码示例&#xf…...