java ,springboot 对接支付宝支付,实现生成付款二维码,退款,查询订单状态等接口

ops/2025/1/24 12:45:31/

查看文档 支付宝文档地址:

小程序文档 - 支付宝文档中心

使用沙箱环境

沙箱登录地址

登录 - 支付宝

点击查看 才能看钥匙截图写错了。。 问号可以看默认加密方式

点击沙箱帐号 这里我们就具备所有条件了

实战开始

pom文件增加依赖

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

创建配置文件,将沙箱内的信息填写到配置文件

java"># 支付宝网关名
open_api_domain = https://openapi-sandbox.dl.alipaydev.com/gateway.do#此处请填写你的PID
pid = 20887210111111
#此处请填写你当面付的APPID
appid = 902101111110# RSA私钥、公钥和支付宝公钥
#此处请填写你的应用私钥且转PKCS8格式
private_key = cpwVvks4h8PwdWDm13Jc207PvY5iy+8xMQd919ClW9H8lVBbpuyA+uyRmoPHp63SpmSnyXAye7ZvjDvuJ4kH9edbLnL
#此处请填写你的应用公钥
public_key = qRhLEXLU+LvD91mAs1iVCGx4bpfl2eLpwLMYvCePwijD6xdBPuRsNv3Chw4xUHfoqK6MKRLzXeqJPdEinhr/DZrAnSbkdH8BwIDAQAB#SHA256withRsa对应支付宝公钥
alipay_public_key = MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqGJldKdkvrx1WirZ4LGUP1DCELrb9Ci1qIdU1Y35z7v4V44BWv2QZoFVVjqVd7mAy7EtCM/cnTH5# 签名类型: RSA->SHA1withRsa,RSA2->SHA256withRsa
sign_type = RSA2
# 当面付最大查询次数和查询间隔(毫秒)
max_query_retry = 5
query_duration = 5000# 当面付最大撤销次数和撤销间隔(毫秒)
max_cancel_retry = 3
cancel_duration = 2000# 交易保障线程第一次调度延迟和调度间隔(秒)
heartbeat_delay = 5
heartbeat_duration = 900#异步通知url(注意拦截器是否拦截)
NotifyUrl=http://fpwquz.natappfree.cc/callbac

支付实体

java">package com.bjbr.controller;import com.alipay.api.domain.GoodsDetail;import java.util.List;/*** 支付宝当面付实体类**/
public class ZFBFaceToFaceModel {private String outTradeNo;// (必填) 商户网站订单系统中唯一订单号 ,64个字符以内,只能包含字母、数字、下划线, 需保证商户系统端不能重复,建议通过数据库sequence生成private String subject; // (必填) 订单标题,粗略描述用户的支付目的。如“喜士多(浦东店)消费”private String totalAmount;// (必填) 订单总金额单位为元,不能超过1亿元 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】private String undiscountableAmount;// (可选) 订单不可打折金额,可以配合商家平台配置折扣活动,如果酒水不参与打折,则将对应金额填写至此字段 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】private String sellerId;// 卖家支付宝账号ID,用于支持一个签约账号下支持打款到不同的收款账号,(打款到sellerId对应的支付宝账号)// 如果该字段为空,则默认为与支付宝签约的商户的PID,也就是appid对应的PIDprivate String body;// // 订单描述,可以对交易或商品进行一个详细地描述,比如填写"购买商品2件共15.00元"private String operatorId; // 商户操作员编号,添加此参数可以为商户操作员做销售统计private String storeId; // (必填) 商户门店编号,通过门店号和商家后台可以配置精准到门店的折扣信息,详询支付宝技术支持private String timeoutExpress;//支付超时如:“120m”,定义为120分钟private List<GoodsDetail> goodsDetailList; //商品明细列表,需填写购买商品详细信息,private String NotifyUrl;// 支付成功之后 支付宝异步调用的接口地址;private String MoblieReturnUrl;//手机支付同步通知页面地址;private String refundReason;//退款原因,(退款使用)private String tradeNo;//支付宝订单号,(退款使用)public String getTradeNo() {return tradeNo;}public void setTradeNo(String tradeNo) {this.tradeNo = tradeNo;}public String getRefundReason() {return refundReason;}public void setRefundReason(String refundReason) {this.refundReason = refundReason;}/*** (必填) 商户网站订单系统中唯一订单号 ,64个字符以内,只能包含字母、数字、下划线, 需保证商户系统端不能重复,建议通过数据库sequence生成* @return*/public String getOutTradeNo() {return outTradeNo;}/*** (必填) 商户网站订单系统中唯一订单号 ,64个字符以内,只能包含字母、数字、下划线, 需保证商户系统端不能重复,建议通过数据库sequence生成* @param outTradeNo*/public void setOutTradeNo(String outTradeNo) {this.outTradeNo = outTradeNo;}/*** (必填) 订单标题,粗略描述用户的支付目的。如“喜士多(浦东店)消费”* @return*/public String getSubject() {return subject;}/*** (必填) 订单标题,粗略描述用户的支付目的。如“喜士多(浦东店)消费”* @param subject*/public void setSubject(String subject) {this.subject = subject;}/***  (必填) 订单总金额单位为元,不能超过1亿元 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】* @return*/public String getTotalAmount() {return totalAmount;}/***  (必填) 订单总金额单位为元,不能超过1亿元 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】* @param totalAmount*/public void setTotalAmount(String totalAmount) {this.totalAmount = totalAmount;}/*** (可选) 订单不可打折金额,可以配合商家平台配置折扣活动,如果酒水不参与打折,则将对应金额填写至此字段 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】* @return*/public String getUndiscountableAmount() {return undiscountableAmount;}/*** (可选) 订单不可打折金额,可以配合商家平台配置折扣活动,如果酒水不参与打折,则将对应金额填写至此字段 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】* @param undiscountableAmount*/public void setUndiscountableAmount(String undiscountableAmount) {this.undiscountableAmount = undiscountableAmount;}/*** // 卖家支付宝账号ID,用于支持一个签约账号下支持打款到不同的收款账号,(打款到sellerId对应的支付宝账号)// 如果该字段为空,则默认为与支付宝签约的商户的PID,也就是appid对应的PID* @return*/public String getSellerId() {return sellerId;}/*** // 卖家支付宝账号ID,用于支持一个签约账号下支持打款到不同的收款账号,(打款到sellerId对应的支付宝账号)// 如果该字段为空,则默认为与支付宝签约的商户的PID,也就是appid对应的PID* @param sellerId*/public void setSellerId(String sellerId) {this.sellerId = sellerId;}/*** 订单描述,可以对交易或商品进行一个详细地描述,比如填写"购买商品2件共15.00元"* @return*/public String getBody() {return body;}/*** 订单描述,可以对交易或商品进行一个详细地描述,比如填写"购买商品2件共15.00元"* @param body*/public void setBody(String body) {this.body = body;}/***商户操作员编号,添加此参数可以为商户操作员做销售统计* @return*/public String getOperatorId() {return operatorId;}/***商户操作员编号,添加此参数可以为商户操作员做销售统计* @param operatorId*/public void setOperatorId(String operatorId) {this.operatorId = operatorId;}/*** (必填) 商户门店编号,通过门店号和商家后台可以配置精准到门店的折扣信息,详询支付宝技术支持* @return*/public String getStoreId() {return storeId;}/*** (必填) 商户门店编号,通过门店号和商家后台可以配置精准到门店的折扣信息,详询支付宝技术支持* @param storeId*/public void setStoreId(String storeId) {this.storeId = storeId;}/***支付超时如:“120m”,定义为120分钟* @return*/public String getTimeoutExpress() {return timeoutExpress;}/***支付超时如:“120m”,定义为120分钟* @param timeoutExpress*/public void setTimeoutExpress(String timeoutExpress) {this.timeoutExpress = timeoutExpress;}/***商品明细列表,需填写购买商品详细信息,* @return*/public List<GoodsDetail> getGoodsDetailList() {return goodsDetailList;}/***商品明细列表,需填写购买商品详细信息,* @param goodsDetailList*/public void setGoodsDetailList(List<GoodsDetail> goodsDetailList) {this.goodsDetailList = goodsDetailList;}/***支付成功之后 支付宝异步调用的接口地址;* @return*/public String getNotifyUrl() {return NotifyUrl;}/***支付成功之后 支付宝异步调用的接口地址;* @param notifyUrl*/public void setNotifyUrl(String notifyUrl) {NotifyUrl = notifyUrl;}/*** 手机支付后跳转的页面地址* @return*/public String getMoblieReturnUrl() {return MoblieReturnUrl;}/*** 手机支付后跳转的页面地址* @return*/public void setMoblieReturnUrl(String moblieReturnUrl) {MoblieReturnUrl = moblieReturnUrl;}
}

根据键值获取配置文件内容方法

java">public static String getZFBinfoValue(String name){try(InputStream inputStream = CommonUtils.class.getClassLoader().getResourceAsStream("config/zfbinfo.properties")) {if(properties==null){properties = new Properties();properties.load(new InputStreamReader(inputStream, StandardCharsets.UTF_8));}return properties.getProperty(name,"");} catch (Exception e) {log.error(e.getMessage(),e);return "";}}

获取二维码接口

java">public static String getZFBPreorder(ZFBFaceToFaceModel zfbFaceToFaceModel) throws AlipayApiException {CommonUtils commonUtils = new CommonUtils();/** 支付宝网关 **/String URL = commonUtils.getZFBinfoValue("open_api_domain");/** 应用id,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/190/201602493024 **/String APP_ID = commonUtils.getZFBinfoValue("appid");/** 应用私钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602469554 **/String APP_PRIVATE_KEY = commonUtils.getZFBinfoValue("private_key");/** 支付宝公钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602487431 **/String ALIPAY_PUBLIC_KEY = commonUtils.getZFBinfoValue("alipay_public_key");/** 初始化 **/AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, "json", "UTF-8", ALIPAY_PUBLIC_KEY, "RSA2");/** 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.precreate(统一收单线下交易预创建(扫码支付)) **/AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();/** 设置业务参数  **/AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();/** 商户订单号,商户自定义,需保证在商户端不重复,如:20200612000001 **/model.setOutTradeNo(zfbFaceToFaceModel.getOutTradeNo());/**订单标题 **/model.setSubject(zfbFaceToFaceModel.getSubject());/** 订单金额,精确到小数点后两位 **/model.setTotalAmount(zfbFaceToFaceModel.getTotalAmount());/** 订单描述 **/model.setBody(zfbFaceToFaceModel.getBody());/** 将业务参数传至request中 **/request.setBizModel(model);/** 异步通知地址,以http或者https开头的,商户外网可以post访问的异步地址,用于接收支付宝返回的支付结果,如果未收到该通知可参考该文档进行确认:https://opensupport.alipay.com/support/helpcenter/193/201602475759 **/request.setNotifyUrl(zfbFaceToFaceModel.getNotifyUrl());/** 通过alipayClient调用API,获得对应的response类  **/AlipayTradePrecreateResponse response = alipayClient.execute(request);/** 获取接口调用结果,如果调用失败,可根据返回错误信息到该文档寻找排查方案:https://opensupport.alipay.com/support/helpcenter/101 **/System.out.println(response.getBody());return response.getBody();}

退款接口

java">public static String ZFBTradeRefund(ZFBFaceToFaceModel zfbFaceToFaceModel) throws AlipayApiException {CommonUtils commonUtils = new CommonUtils();/** 支付宝网关 **/String URL = commonUtils.getZFBinfoValue("open_api_domain");/** 应用id,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/190/201602493024 **/String APP_ID = commonUtils.getZFBinfoValue("appid");/** 应用私钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602469554 **/String APP_PRIVATE_KEY = commonUtils.getZFBinfoValue("private_key");/** 支付宝公钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602487431 **/String ALIPAY_PUBLIC_KEY = commonUtils.getZFBinfoValue("alipay_public_key");/** 初始化 **/AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, "json", "UTF-8", ALIPAY_PUBLIC_KEY, "RSA2");/** 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.refund(统一收单交易退款接口) **/AlipayTradeRefundRequest  request = new AlipayTradeRefundRequest();/** 设置业务参数  **/AlipayTradeRefundModel model = new AlipayTradeRefundModel ();/** 商户订单号,商户自定义,需保证在商户端不重复,如:20200612000001 **/model.setOutTradeNo(zfbFaceToFaceModel.getOutTradeNo());model.setTradeNo(zfbFaceToFaceModel.getTradeNo());// 设置退款金额model.setRefundAmount(zfbFaceToFaceModel.getTotalAmount());// 设置退款原因说明model.setRefundReason(zfbFaceToFaceModel.getRefundReason());// 设置退款请求号 退款请求号。 标识一次退款请求,需要保证在交易号下唯一model.setOutRequestNo(UUID.randomUUID().toString());/** 将业务参数传至request中 **/request.setBizModel(model);/** TODO暂时不用退款通知 异步通知地址,以http或者https开头的,商户外网可以post访问的异步地址,用于接收支付宝返回的支付结果,如果未收到该通知可参考该文档进行确认:https://opensupport.alipay.com/support/helpcenter/193/201602475759 **/request.setNotifyUrl("");AlipayTradeRefundResponse response = alipayClient.execute(request);/** 获取接口调用结果,如果调用失败,可根据返回错误信息到该文档寻找排查方案:https://opensupport.alipay.com/support/helpcenter/101 **/System.out.println(response.getBody());if (response.isSuccess()) {System.out.println("调用成功");} else {System.out.println("调用失败");}return response.getBody();}

查询订单状态接口

java">public static String ZFBTradeQuery(ZFBFaceToFaceModel zfbFaceToFaceModel) throws AlipayApiException {CommonUtils commonUtils = new CommonUtils();/** 支付宝网关 **/String URL = commonUtils.getZFBinfoValue("open_api_domain");/** 应用id,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/190/201602493024 **/String APP_ID = commonUtils.getZFBinfoValue("appid");/** 应用私钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602469554 **/String APP_PRIVATE_KEY = commonUtils.getZFBinfoValue("private_key");/** 支付宝公钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602487431 **/String ALIPAY_PUBLIC_KEY = commonUtils.getZFBinfoValue("alipay_public_key");/** 初始化 **/AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, "json", "UTF-8", ALIPAY_PUBLIC_KEY, "RSA2");/** 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.refund(统一收单交易退款接口) **/AlipayTradeQueryRequest request = new AlipayTradeQueryRequest ();/** 设置业务参数  **/AlipayTradeQueryModel model = new AlipayTradeQueryModel  ();/** 商户订单号,商户自定义,需保证在商户端不重复,如:20200612000001 **/model.setOutTradeNo(zfbFaceToFaceModel.getOutTradeNo());model.setTradeNo(zfbFaceToFaceModel.getTradeNo());/** 将业务参数传至request中 **/request.setBizModel(model);AlipayTradeQueryResponse response = alipayClient.execute(request);/** 获取接口调用结果,如果调用失败,可根据返回错误信息到该文档寻找排查方案:https://opensupport.alipay.com/support/helpcenter/101 **///解析json数据JSONObject jsonObject=JSONObject.parseObject(response.getBody());//得到alipay_trade_query_response数据后再强转JSONObjectJSONObject jsonobj_two=(JSONObject)jsonObject.get("alipay_trade_query_response");//再通过jsonobj_two获取到二维码地址String code=jsonobj_two.get("code").toString();//交易状态:WAIT_BUYER_PAY(交易创建,等待买家付款)、TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、TRADE_SUCCESS(交易支付成功)、TRADE_FINISHED(交易结束,不可退款)String trade_status=jsonobj_two.get("trade_status").toString();if (trade_status.equals("TRADE_SUCCESS")) {//用户已付款 直接调用回调return "yzf";}else {return "wzf";}}


http://www.ppmy.cn/ops/152742.html

相关文章

Spring Boot 自动配置

目录 什么是自动配置&#xff1f; Spring 加载 Bean ComponentScan Import 导入类 导入 ImportSelector 接口的实现类 SpringBoot 原理分析 EnableAutoConfiguration Import(AutoConfigurationImportSelector.class) AutoConfigurationPackage SpringBoot 自动配置流…

探索Linux中的进程控制:从启动到退出的背后原理

个人主页&#xff1a;chian-ocean 文章专栏-Linux 前言&#xff1a; 进程控制是操作系统对进程的创建、运行、调度、中止等活动进行管理和协调的行为。它是操作系统中至关重要的一部分&#xff0c;保证多任务处理环境下的资源分配和系统稳定性。 进程创建 fork( ) fork() 调…

Linux 网络:cBPF 简介

文章目录 1. 前言2. 什么是 cBPF&#xff1f;2.1 cBPF 工作原理2.2 cBPF 的使用2.3 实现细节2.3.1 挂接 BPF 指令到 sokcet2.3.2 执行 BPF 指令过滤数据包 3. cBPF 示例&#xff1a;过滤 EDSA 协议下的 PTP 以太网帧4. 参考资料 1. 前言 限于作者能力水平&#xff0c;本文可能…

kotlin的协程的基础概念

Kotlin的协程是一种用于简化异步编程的强大工具。 理解协程的基础概念可以帮助开发者有效地利用其能力。 以下是Kotlin协程的一些关键基础概念&#xff1a; 协程&#xff08;Coroutines&#xff09; &#xff1a; 协程是一种用于处理并发任务的编程模型&#xff0c;它可以在单…

使用qwen作为基座训练分类大模型

训练大模型 import torch from transformers import AutoModelForSequenceClassification, AutoTokenizer, Trainer, TrainingArguments from datasets import load_dataset, DatasetDict# 1. 加载 Qwen2.5-0.5B 预训练模型和分词器 model_name "Qwen/Qwen2.5-0.5B"…

理解深度学习pytorch框架中的线性层

文章目录 1. 数学角度&#xff1a; y W x b \displaystyle y W\,x b yWxb示例 2. 编程实现角度&#xff1a; y x W T b \displaystyle y x\,W^T b yxWTb3. 常见错误与易混点解析4. 小结参考链接 在神经网络或机器学习的线性层&#xff08;Linear Layer / Fully Connect…

doris:阿里云 OSS 导入数据

Doris 提供两种方式从阿里云 OSS 导入文件&#xff1a; 使用 S3 Load 将阿里云 OSS 文件导入到 Doris 中&#xff0c;这是一个异步的导入方式。使用 TVF 将阿里云 OSS 文件导入到 Doris 中&#xff0c;这是一个同步的导入方式。 使用 S3 Load 导入​ 使用 S3 Load 导入对象存…

网络安全 | 0day漏洞介绍

关注&#xff1a;CodingTechWork 引言 在网络安全领域&#xff0c;0day漏洞&#xff08;Zero-day Vulnerability&#xff09;是指一个尚未被厂商、开发者或安全人员发现、修复或发布修补程序的安全漏洞。0day漏洞是黑客利用的一个重要攻击工具&#xff0c;因其未被披露或未被修…