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

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

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

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

使用沙箱环境

沙箱登录地址

登录 - 支付宝

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

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

实战开始

pom文件增加依赖

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

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

# 支付宝网关名
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

支付实体

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对应的PID
    private 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;
    }
}

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

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 "";
		}

	}

获取二维码接口

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();

    }

退款接口

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();

        }

查询订单状态接口

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数据后再强转JSONObject
                JSONObject 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.kler.cn/a/514838.html

相关文章:

  • 计算机组成原理——数据表示(二)
  • yolov11 pose 推理代码
  • Mixly米思齐1.0 2.0 3.0 软件windows版本MAC苹果电脑系统安装使用常见问题与解决
  • 阿九的python 爬虫进阶课18.3 学习笔记
  • Linux Bash 中使用重定向运算符的 5 种方法
  • 什么样的问题适合用递归
  • 十三、数据的的输入与输出(3)
  • Android节点读写实现
  • 【影刀RPA_初级课程_影刀初相识】
  • 解决安装 Composer 依赖报错:“./composer.json“ does not match the expected JSON schema
  • 【QNX】QNX侧查看CPU的信息
  • 如何在Matplotlib中绘制多个Y轴刻度
  • Unity Line Renderer Component入门
  • IP所属地与上网地点:如何匹配?
  • 2024大模型双向突破:MoE架构创新与小模型崛起
  • [Dialog屏幕开发] 屏幕绘制(文本/输入框/按钮控件)
  • 【组件分享】商品列表组件-最佳实践
  • 【子矩阵——优先队列】
  • Leecode刷题C语言之从栈中取出K个硬币的最大面积和
  • node.js 07.npm下包慢的问题与nrm的使用
  • Java 设计模式一
  • 聚类OTU vs 降噪识别生物序列——谁将主宰扩增子领域未来
  • CSDN 博客之星 2024:默语的技术进阶与社区耕耘之旅
  • Markdown Viewer 浏览器, vscode
  • 如何为64位LabVIEW配置正确的驱动程序
  • 基于STM32F103驱动AD7606串行采集数据信号