Spring Boot集成支付宝电脑网站支付功能

3,311 阅读14分钟

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第6篇文章,点击查看活动详情

接入准备

登录

访问支付宝开放平台:https://open.alipay.com/ 登录后补充开发者信息,然后在开发接入项,点击网页/移动应用开发项跳转创建应用。 在这里插入图片描述

创建应用

填写应用基础信息 在这里插入图片描述

添加能力

创建应用后,配置应用的能力,在添加能力项加入需要的能力,如电脑网站支付能力 在这里插入图片描述

生成私钥与公钥

访问https://opendocs.alipay.com/common/02khjo下载密匙生成工具,然后生成公钥与私钥 在这里插入图片描述

开发设置

在这里插入图片描述 设置自己生成的公钥 在这里插入图片描述 将自己生成的公钥告诉支付宝,支付宝返回一个支付宝公钥 在这里插入图片描述 最终得到3个密匙:1.应用公钥 2.应用私钥 3.支付宝公钥

沙箱环境

沙箱地址:https://open.alipay.com/develop/sandbox/app

参考上述生成私钥与公钥开发设置,在接口加签方式处进行设置。最终得到3个密匙:1.应用公钥 2.应用私钥 3.支付宝公钥 在这里插入图片描述 沙箱账号用于支付测试 在这里插入图片描述

示例Demo的使用与学习

下载Demo

在文档中心:https://openhome.alipay.com/docCenter/docCenter.htm找到需要接入应用类型的对应文档 在这里插入图片描述 或者直接搜索,如电脑网站支付 在这里插入图片描述 找到需要文档后,查看文档中的SDK&Demo项,下载对应语言Demo,用于学习 在这里插入图片描述

启动项目

在这里插入图片描述

参数配置

在Demo项目中的AlipayConfig类中配置:应用ID,商户私钥(应用私钥)、支付宝公钥、异步通知、同步通知地址等参数。

注意:如果这里使用沙箱环境测试,一定要修改支付宝网关,否则调试错误 在这里插入图片描述

沙箱环境网关为: https://openapi.alipaydev.com/gateway.do 

正式环境网关为:https://openapi.alipay.com/gateway.do 
/* *
 *类名:AlipayConfig
 *功能:基础配置类
 *详细:设置帐户有关信息及返回路径
 *修改日期:2017-04-05
 *说明:
 *以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
 *该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
 */

public class AlipayConfig {

//↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

	// 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
	public static String app_id = "20166660581647";

	// 商户私钥,您的PKCS8格式RSA2私钥
    public static String merchant_private_key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCKNOWSnUMsaeEZZMDy+DvbdUMVTuJ/jQ4Ks8lQEatRjXS7ZWX+NMszQir3HyRWe1q8+8n6ZvJSiMGpS2Ku7ZeTHyZvOB9BTG3vgapDKKJAQ0NYaB3561FaU3ZRnCay5ls50WVCZ82pO//NZ5xRYND53+ZjSvOZi58FV1uKnCEAx8tPZKeGi5c2hQ6epjjzcjsdD/1fZEF5B667AM8nLe3zZWftvBxJe8Z1yoRP/w4aWW451myFViQWaKiWsERz7KAHCJEu+wAyvgqB18MOoNk76svqr71Z0whjrTF/1eEHaoictzMdao8hWYNhveaPA4Ic46rWoBTyHOHdt9p+hF1NAgMBAAECggEAQP39E4RWyeXbYlyw+nq+Y/ch0WP4Q5lFY0iIGSfW2D+P9xp4QHGQNr4mUsxho9BMjU0KyZ41/j5LfpqO0s+abeQgAvwP3WXm9EkgcDP1UulCG74YQmXa7e+ORT3+3Vmt6lC/rY3SurFLl2HNkH1dBHhO2+XpYV/WGDDRFJ/WxI3gFdWF31sqT9n75HsozFtA5vp90ZOq3SxqtQKBgQDZDqfj6Aw5jCI+rPapmp4NISDLUHtcIKKfRx/2yjmCPZ/WCnIW4R7jxyf3rvd4beNMqVHfAhdwISfug5C3n2nZJV4aMY/o52DEH38d2dYqkJX78V+Jaw0vy8DvuxGtVCB/5r3tK4zbza9g2uFPUb9/8QBo3h8KKbjs6haOxBLFqwKBgQCjAKqhTsrZwI0AR1NQ76U558CkR5NbR15pROgzXvzLwnr5L2pOhrf+IEsGOZklXgv727jc907Gp/VlBQrsFU5rPKMc091HdLV7fmsVY/CIb9P+oSGj7nZ5X6O2n3wY2nJzlnWT4+wZSLQDiThuUA+awDe1TZZ4jVX4Y9kDOLwA5wKBgHWhsLEdp8pkPIbU+9SMu80HwBsPYdtawGcrh5IapDIGLaI1BQGLPU9aNjnP88OrYfzA4mLGYmddQKPNX1d0KEwLKUVuyLwC8Pk4zI4j6SImO3JPrGPvxTS66rPBIOJbbkWCijmHWY4hmUMXO/Xdqreup3ctsYqzc8nJTzJN5pKDAoGAQxOuI81BypPjMj8nuQG1E3wcGT5fFEvtPRKfHyyyiMMSSeLKM2Ba7NerJ/eh3u+xrMYBb+TRZQyO/jAyC27FI3oDgYRp5dLQL+6Y8Gd8/xhNu9Xg+w3RcSb7Ptaoga27NXewENjVOp5hfacFMtf9Y+g/xHsWNauruhiUoC/DpfcCgYEA2KjZndyY4iKQg2ia3PrRREZukoTAiYVE36i66YVYhwnrqjP3VRwrrK8kpG/HMhcPYFEuO1d7pKLShoxn10UdDlAX1R7mkFSGS/t8KNp7LqNHaDxL0lWeUq7/WEHn7vxvlHtB3dIB+cuq5iC/VuTvnQhXPOGU/6hgJu1ImuDz5uQ=";

	// 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
    public static String alipay_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1j83H1RmHZeuLbYyxhWAn80GTK/963/SnGHfZAujXsB4/EWn+BqHK6zOmBwXAZAsvjrG+oFakMagANwBVEpwIHF7o9DdX6skYlyO2HRfc/XZMKBg1snAXA/OBjUjTcKTeFJx75zezxgTwrHl3MSrXEr4WnGPAxu+jC9cFrsFdTTGz1gp4K25OBbsSNFdEnqaVbWmJT/U0wAAE8eOcHSk5TYgQfmvqFLuSpjOwDWF0m6/Ymr7EKagsBvtb/Y+IUyQKWi62nqJrDbuduaRiC43hUp6nU3E2VNDuxdexkuQF/cjz5l3/GEeRtFgb00RmkmjtnC+FwIDAQAB";

	// 服务器异步通知页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
	public static String notify_url = "http://localhost:8080/alipay.trade.page.pay-JAVA-UTF-8/notify_url.jsp";

	// 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
	public static String return_url = "http://localhost:8080/alipay.trade.page.pay-JAVA-UTF-8/return_url.jsp";

	// 签名方式
	public static String sign_type = "RSA2";

	// 字符编码格式
	public static String charset = "utf-8";

	// 支付宝网关
//	public static String gatewayUrl = "https://openapi.alipay.com/gateway.do";
	public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";

	// 支付宝网关
	public static String log_path = "C:\\";


//↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

    /**
     * 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
     * @param sWord 要写入日志里的文本内容
     */
    public static void logResult(String sWord) {
        FileWriter writer = null;
        try {
            writer = new FileWriter(log_path + "alipay_log_" + System.currentTimeMillis()+".txt");
            writer.write(sWord);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

执行测试

发起一个付款操作 在这里插入图片描述 跳到转支付页面,输入沙箱环境中的测试账号进行登录 在这里插入图片描述

选择支付方式,输入支付密码 在这里插入图片描述 支付成功,最终会跳转到配置的回调地址 在这里插入图片描述 至此,支付宝Demo的支付功能就测试通过,具体实现就可以参考源码进行学习。

Spring Boot集成支付宝支付功能

获取SDK

在开发工具包(SDK)下载页面:https://opendocs.alipay.com/open/02nk0x找到依赖坐标 在这里插入图片描述

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

添加依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!-- 移除掉默认支持的 Tomcat -->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        
        <!-- 添加 Undertow 容器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>4.9.28.ALL</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

配置application.properties

在application.properties文件中配置支付相关配置

#--------------------支付宝相关的配置--------------------
# 应用ID
alipay.app_id=201607712345681647
# 商户私钥
alipay.merchant_private_key=MIIEvQIqqANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCKNOWSnUMsaeEZZMDy+DvbdUMVTuJ/jQ4Ks8lQEatRjXS7ZWX+NMszQir3HyRWe1q8+8n6ZvJSiMGpS2Ku7ZeTHyZvOB9BTG3vgapDKKJAQ0NYaB3561FaU3ZRnCay5ls50WVCZ82pO//NZ5xRYND53+ZjSvOZi58FV1uKnCEAx8tPZKeGi5c2hQ6epjjzcjsdD/1fZEF5B667AM8nLe3zZWftvBxJe8Z1yoRP/w4aWW451myFViQWaKiWsERz7KAHCJEu+wAyvgqB18MOoNk76svqr71Z0whjrTF/1eEHaoictzMdao8hWYNhveaPA4Ic46rWoBTyHOHdt9p+hF1NAgMB1231232139E4RWyXUFAO8LeXbYlyw+nq+Y/ch0WP4Q5lFY0iIGSfW2D+P9xp4QHGQNr4mUsxho9BMjU0KyZ41m28IpLGtSpKysrgVmEWJVkf1yx2uaKOHVbuiFOkfTdS9MV4bSUY8x4hd0dGgdtBdMQEyaGVd8PSdLBOLOpjFdgAJJ1tZrAENG1VqbSgRdAs0cIFSPPUpjK+EC61zIG4Cb/j5LfpqO0s+abeQgAvwP3WXm9EkgcDP1UulCG74YQmXa7e+ORT3+3Vmt6lC/rY3SurFLl2HNkH1dBHhO2+XpYV/WGDDRFJ/WxI3gFdWF31sqT9n75HsozFtA5vp90ZOq3SxqtQKBgQDZDqfj6Aw5jCI+rPapmp4NISDLUHeeeKfRx/2yjmCPZ/WCnIW4R7jxyf3rvd4beNMqVHfAhdwISfug5C3n2nZJV4aMY/o52DEH38d2dYqkJX78V+Jaw0vy8DvuxGtVCB/5r3tK4zbza9g2uFPUb9/8QBo3h8KKbjs6haOxBLFqwKBgQCjAKqhTsrZwI0AR1NQ76U558CkR5NbR15pROgzXvzLwnr5L2pOhrf+IEsGOZklXgv727jc907Gp/VlBQrsFU5rPKMc091HdLV7fmsVY/CIb9P+oSGj7nZ5X6O2n3wY2nJzlnWT4+wZSLQDiThuUA+awDe1TZZ4jVX4Y9kDOLwA5wKBgHWhsLEdp8pkPIbU+9SMu80HwBsPYdtawGcrh5IapDIGLaI1BQGLPU9aNjnP88OrYfzA4mLGYmddQKPNX1d0KEwLKUVuyLwC8Pk4zI4j6SImO3JPrGPvxTS66rPBIOJbbkWCijmHWY4hmUMXO/Xdqreup3ctsYqzc8nJTzJN5pKDAoGAQxOuI81BypPjMj8nuQG1E3wcGT5fFEvtPRKfHyyyiMMSSeLKM2Ba7NerJ/eh3u+xrMYBb+TRZQyO/jAyC27FI3oDgYRp5dLQL+6Y8Gd8/xhNu9Xg+w3RcSb7Ptaoga27NXewENjVOp5hfacFMtf9Y+g/xHsWNauruhiUoC/DpfcCgYEA2KjZndyY4iKQg2ia3PrRREZukoTAiYVE36i66YVYhwnrqjP3VRwrrK8kpG/HMhcPYFEuO1d7pKLShoxn10UdDlAX1R7mkFSGS/t8KNp7LqNHaDxL0lWeUq7/WEHn7vxvlHtB3dIB+cuq5iC/VuTvnQhXPOGU/6hgJu1ImuDz5uQ=
# 支付宝公钥
alipay.alipay_public_key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1j83H1RmHZeuLbYyxhWAn80GTK/963/SnGHfZAujXsB4/EWn+BqHK6zOmBwXAZAsv1231231234fFVEpwIHF7o9DdX6skYlSYv1eeq2HRfc/XZMKBg1snAXA/OBjUjTcKTeFJx75zezxgTwrHl3MSrXEr4WnGPAxu+jC9cFreeep4K25OBbsSNFdEnqaVbWmJT/U0wAAE8eOcHSk5TYgQfmvqFLuSpjOwDWF0m6/YmqagsBvtb/Y+IUyQKWi62nqJrDbuduaRiC43hUp6nU3E2VNDuxdexkuQF/cjz5l3/GEeRtFgb00RmkmjtnC+FwIDAQAB
# 服务器异步通知页面路径
alipay.notify_url=http://jackchen.imwork.net:27687/pay/asyncNotify
# 页面跳转同步通知页面路径
alipay.return_url=http://jackchen.imwork.net:27687/pay/syncNotify
# 签名方式
alipay.sign_type=RSA2
# 字符编码格式
alipay.charset=utf-8
# 支付宝网关
#alipay.gatewayUrl=https://openapi.alipaydev.com/gateway.do
# 支付宝沙箱网关
alipay.gatewayUrl=https://openapi.alipaydev.com/gateway.do

# 异步通知 对时间字段格式化,否则异步通知失败
spring.mvc.date-format=yyyy-MM-dd HH:mm:ss

创建AlipayUtil

支付信息VO

@Data
public class PayVo {
    /**
     * 商户订单号,必填
     */
    private String out_trade_no;
    /**
     * 订单名称,必填
     */
    private String subject;
    /**
     * 付款金额,必填
     */
    private String total_amount;
    /**
     * 商品描述,可为空
     */
    private String body;
}

AlipayUtil 工具类

@ConfigurationProperties(prefix = "alipay")
@Component
@Data
public class AlipayUtil {
    /**
     * 应用ID
     */
    public String app_id;
    /**
     * 商户私钥
     */
    public String merchant_private_key;
    /**
     * 支付宝公钥
     */
    public String alipay_public_key;
    /**
     * 服务器[异步通知]页面路径 必须外网可以正常访问 支付宝会告诉支付成功的信息
     */
    public String notify_url;
    /**
     * 页面跳转[同步通知]页面路径 必须外网可以正常访问 支付成功跳转到成功页
     */
    public String return_url;
    /**
     * 签名方式
     */
    private String sign_type;
    /**
     * 字符编码格式
     */
    private String charset;
    /**
     * 订单超时时间
     */
    private String timeout = "1m";
    /**
     * 支付网关
     */
    public String gatewayUrl;

    /**
     * 发起支付请求
     * @param vo 支付信息
     * @return
     * @throws AlipayApiException
     */
    public String pay(PayVo vo) throws AlipayApiException {
        // 根据支付宝的配置生成一个支付客户端
        AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl, app_id, merchant_private_key, "json", charset, alipay_public_key, sign_type);

        // 创建一个支付请求
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        // 设置请求参数
        alipayRequest.setReturnUrl(return_url);
        alipayRequest.setNotifyUrl(notify_url);

        // 商户订单号,商户网站订单系统中唯一订单号
        String out_trade_no = vo.getOut_trade_no();
        // 付款金额
        String total_amount = vo.getTotal_amount();
        // 订单名称
        String subject = vo.getSubject();
        // 商品描述
        String body = vo.getBody();

        alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
                + "\"total_amount\":\"" + total_amount + "\","
                + "\"subject\":\"" + subject + "\","
                + "\"body\":\"" + body + "\","
                + "\"timeout_express\":\"" + timeout + "\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

        String result = alipayClient.pageExecute(alipayRequest).getBody();

        // 收到支付宝的响应,响应一个页面,浏览器显示这个页面,就会自动到支付宝的收银台页面
        System.out.println("支付宝响应:" + result);

        return result;

    }
}

创建支付成功返回页面

paySuccess.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h2>您已支付成功</h2>
</body>
</html>

异步/同步通知参数封装对象

@ToString
@Data
public class PayAsyncVo {
    /**
     * 交易创建时间。格式为 yyyy-MM-dd HH:mm:ss
     */
    private String gmt_create;
    /**
     * 编码格式。如 utf-8、gbk、gb312等。
     */
    private String charset;
    /**
     * 交易付款时间。格式为 yyyy-MM-dd HH:mm:ss
     */
    private String gmt_payment;
    /**
     * 通知的发送时间。格式为 yyyy-MM-dd HH:mm:ss
     */
    private Date notify_time;
    /**
     * 订单标题/商品标题/交易标题/订单关键字等,是请求时对应参数,会在通知中原样传回
     */
    private String subject;
    /**
     * 签名。详情可查看 异步返回结果的验签
     */
    private String sign;
    /**
     * 买家支付宝账号 ID。以 2088 开头的纯 16 位数字
     */
    private String buyer_id;
    /**
     * 商品描述。该订单的备注、描述、明细等。对应请求时的 body 参数,会在通知中原样传回
     */
    private String body;
    /**
     * 开票金额。用户在交易中支付的可开发票的金额,单位为人民币(元),精确到小数点后 2 位
     */
    private String invoice_amount;
    /**
     * 调用的接口版本。固定为1.0
     */
    private String version;
    /**
     * 通知校验 ID
     */
    private String notify_id;
    /**
     * 支付金额信息。支付成功的各个渠道金额信息。详情可查看下文 资金明细信息说明
     */
    private String fund_bill_list;
    /**
     * 通知类型
     */
    private String notify_type;
    /**
     * 商家订单号。原支付请求的商家订单号
     */
    private String out_trade_no;
    /**
     * 订单金额。本次交易支付订单金额,单位为人民币(元),精确到小数点后 2 位
     */
    private String total_amount;
    /**
     * 交易状态。交易目前所处状态,详情可查看下表 交易状态说明
     */
    private String trade_status;
    /**
     * 支付宝交易号,支付宝交易凭证号
     */
    private String trade_no;
    /**
     * 授权方的APPID。由于本接口暂不开放第三方应用授权,因此 auth_app_id=app_id
     */
    private String auth_app_id;
    /**
     * 实收金额。商家在交易中实际收到的款项,单位为人民币(元),精确到小数点后 2 位
     */
    private String receipt_amount;
    /**
     * 使用集分宝支付金额,单位为人民币(元),精确到小数点后 2 位
     */
    private String point_amount;
    /**
     * 支付宝应用的APPID。支付宝分配给开发者的应用 ID
     */
    private String app_id;
    /**
     * 用户在交易中支付的金额,单位为人民币(元),精确到小数点后 2 位
     */
    private String buyer_pay_amount;
    /**
     * 签名类型。签名算法类型,目前支持RSA2和RSA,推荐使用 RSA2
     */
    private String sign_type;
    /**
     * 卖家支付宝账号 ID。以 2088 开头的纯 16 位数字
     */
    private String seller_id;
}

API接口

@Controller
public class TestController {

    @Autowired
    private AlipayUtil alipayUtil;

    @ResponseBody
    @RequestMapping("/test")
    public String index() {
        return "Hello World";
    }

    /**
     * 用户下单:支付宝支付
     * 1、让支付页让浏览器展示
     * 2、支付成功以后,跳转到用户的订单列表页
     *
     * @param orderCode 订单编码
     * @return
     * @throws AlipayApiException
     */
    @ResponseBody
    @GetMapping(value = "/payOrder", produces = "text/html")
    public String aliPayOrder(@RequestParam String orderCode) throws AlipayApiException {
        // 通过订单编码查询支付信息
        // PayVo payVo = orderService.getOrderPay(orderCode);

        System.out.println("订单编码:" + orderCode);
        // 构造一份订单支付信息
        PayVo payVo = new PayVo();
        payVo.setOut_trade_no(UUID.randomUUID().toString());
        payVo.setSubject("话费充值100元");
        payVo.setTotal_amount("99.8");
        payVo.setBody("话费充值100元,急速充值。");

        String pay = alipayUtil.pay(payVo);
        return pay;
    }

    @GetMapping(value = "/pay/syncNotify")
    public String paySyncNotify(PayAsyncVo payasyncVo, HttpServletRequest request) {
        System.out.println("同步通知内容:" + payasyncVo);
        return "paySuccess";
    }

    /**
     * 支付宝的异步通知,只要返回 success 支付宝便不再通知
     */
    @PostMapping(value = "/pay/asyncNotify")
    @ResponseBody
    public String payAsyncNotify(PayAsyncVo asyncVo, HttpServletRequest request) throws AlipayApiException {
        // 获取支付宝反馈信息
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 出现乱码时使用
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        // 调用SDK验证签名
        boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayUtil.getAlipay_public_key(), alipayUtil.getCharset(), alipayUtil.getSign_type());

        if (signVerified) {
            System.out.println("签名验证成功...");
            // 业务处理,如修改订单状态
            System.out.println(asyncVo.toString());

            return "success";
        } else {
            System.out.println("签名验证失败...");
            return "error";
        }
    }
}

支付测试

统一收单下单并支付页面接口调用时序图 image.png 请求http://localhost:8080/payOrder/?orderCode=123378904789支付地址,生成如下表单脚本

订单编码:123378904789
支付宝响应:<form name="punchout_form" method="post" action="https://openapi.alipaydev.com/gateway.do?charset=utf-8&method=alipay.trade.page.pay&sign=SxbAuMfBTS3KPP1qWTjr29mmfDhWUtnu4YEaadJ6PCoqvL3kkQlJqFcZWZnprR3xs5iGrJdcPfzuq4Oga9ga8wMRhxfdjF4FaygFq4EJTaWMcePphfdhNpv4k8wPjNbHblYt7YK5oeDf0Ssj33EPfCHdMjR0OVu%2F8grmR4kq2%2FaBtmeYwdaHwmIGvOgAwnp%2Be12OZXgNksiuH0ex1YeFKxbYveaa6Yi2SGLd8voPSria7MsFhS%2B%2F6NQ5VZ79XwUY4NseJY2%2BGBEm8Vv2dO9EbngKBP4sGj%2FDg8opgsMmW%2FlrZTxifQ6fzyk7rsrwSp6zSB5YzL%2B82u7mZvSsC0egXw%3D%3D&return_url=http%3A%2F%2Fjackchen.imwork.net%3A27687%2Fpay%2FsyncNotify&notify_url=http%3A%2F%2Fjackchen.imwork.net%3A27687%2Fpay%2FasyncNotify&version=1.0&app_id=2016092300581647&sign_type=RSA2&timestamp=2022-09-11+21%3A09%3A42&alipay_sdk=alipay-sdk-java-dynamicVersionNo&format=json">
<input type="hidden" name="biz_content" value="{&quot;out_trade_no&quot;:&quot;aec33d19-eda4-4f17-8cb5-5aa0e6129b4b&quot;,&quot;total_amount&quot;:&quot;99.8&quot;,&quot;subject&quot;:&quot;话费充值100元&quot;,&quot;body&quot;:&quot;话费充值100元,急速充值。&quot;,&quot;timeout_express&quot;:&quot;1m&quot;,&quot;product_code&quot;:&quot;FAST_INSTANT_TRADE_PAY&quot;}">
<input type="submit" value="立即支付" style="display:none" >
</form>
<script>document.forms[0].submit();</script>

上述脚本返回游览器,自动执行,生成如下页面。 在这里插入图片描述 登录沙箱环境账号进行支付 在这里插入图片描述 支付成功异步回调执行 在这里插入图片描述

签名验证成功...
PayAsyncVo(gmt_create=2022-09-11 21:09:56, charset=utf-8, gmt_payment=2022-09-11 21:10:18, notify_time=Sun Sep 11 21:10:19 CST 2022, subject=话费充值100元, sign=Yty7oT1xpLQ5UwC5DKVFwMO+k2XtOBOza37itFL/R8rIjtFxDoMtP3Qxdi8r76hmLyDjBShz8IQxag6zcqvfhN3OvoyN/gYzYpKz/sqKIYgDqQJqgM4SYA1/4W7kRhG4A0yw2M9ANpm8MYq+i21lvDerQ6R2w71urn/HR7GteZLOFvniisbUu6/Dcykdb6tDgM9tsl1iqGSE/xf6kahcboTXlSdAasFAKPHmiPhjrvs7lpwoFiZZeHlDMYFUkg0hhmJVz/VT8tkVNSEfN/jXZDU+2nvJwK6tR0EkG4gpiQEa7cRP26Jjmbl/pAZ1qKqkhzxRsCa+0U2xYUMy5/r+AQ==, buyer_id=2088102177032991, body=话费充值100元,急速充值。, invoice_amount=99.80, version=1.0, notify_id=2022091100222211018032990521528764, fund_bill_list=[{"amount":"99.80","fundChannel":"ALIPAYACCOUNT"}], notify_type=trade_status_sync, out_trade_no=aec33d19-eda4-4f17-8cb5-5aa0e6129b4b, total_amount=99.80, trade_status=TRADE_SUCCESS, trade_no=2022091122001432990501977422, auth_app_id=2016092300581647, receipt_amount=99.80, point_amount=0.00, app_id=2016092300581647, buyer_pay_amount=99.80, sign_type=RSA2, seller_id=2088102176985780)

等待几秒后,返回同步通知配置地址

同步通知内容:PayAsyncVo(gmt_create=null, charset=utf-8, gmt_payment=null, notify_time=null, subject=null, sign=JuFKKdvhaFPJ6LAJ2BIwVLNS7xb1gZzLtg4kvs2XpuC4i/ElwxKgouyDa/OnJkxCjiO1+YkOhFkPGSNnaWbsic9vgskER5OwChbs5CXgPIZKzG1nFPHTitYHpOeC6XP7O1gzhj9Rq/W3lzYhvnhQBcea3SiF5We21icEMWvahJHp25hlbpOJVxWJOXSB1DjRlnbd30zp09aAV5o+VVDdqByPuBS3ff8owPYh0duhP0f1LEh/BHmJUpBXbeUbwgruay1Tmqzf37SXY/YQymHIIbnz0BpCJ60xj+SuXMlnTwy3LnK0xni9JK+QeHcdY5XpqdtJNl1Vy75zl6PTIgei5A==, buyer_id=null, body=null, invoice_amount=null, version=1.0, notify_id=null, fund_bill_list=null, notify_type=null, out_trade_no=aec33d19-eda4-4f17-8cb5-5aa0e6129b4b, total_amount=99.80, trade_status=null, trade_no=2022091122001432990501977422, auth_app_id=2016092300581647, receipt_amount=null, point_amount=null, app_id=2016092300581647, buyer_pay_amount=null, sign_type=RSA2, seller_id=2088102176985780)

在这里插入图片描述

支付查询测试

AlipayUtil添加订单查询方法

    public String payQuery(String outTradeNo) throws AlipayApiException {
        // 根据支付宝的配置生成一个支付客户端
        AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl, app_id, merchant_private_key, "json", charset, alipay_public_key, sign_type);

        // 创建一个支付请求
        AlipayTradeQueryRequest alipayRequest = new AlipayTradeQueryRequest();

        JSONObject bizContent = new JSONObject();
        // 订单支付时传入的商户订单号,和支付宝交易号不能同时为空。trade_no,out_trade_no如果同时存在优先取trade_no
        bizContent.put("out_trade_no", outTradeNo);
        // 支付宝交易号,和商户订单号不能同时为空
        //bizContent.put("trade_no", "2014112611001004680073956707");
        alipayRequest.setBizContent(bizContent.toString());
        AlipayTradeQueryResponse response = alipayClient.execute(alipayRequest);
        if (response.isSuccess()) {
            System.out.println("调用成功");
            return response.getBody();
        } else {
            System.out.println("调用失败");
            return "查询失败。";
        }
    }

订单查询接口

    /**
     * 通过商户订单号进行查询支付信息
     * @param outTradeNo 商户订单号
     * @return
     * @throws AlipayApiException
     */
    @GetMapping(value = "/pay/payQuery")
    @ResponseBody
    public String payQuery(String outTradeNo) throws AlipayApiException {
        String pay = alipayUtil.payQuery(outTradeNo);
        return pay;
    }

发起一份订单支付,得到商户ID:a83cf764-f177-4f27-81f7-615bfb418d43,进入付款页面暂定付款 在这里插入图片描述 访问http://localhost:8080/pay/payQuery?outTradeNo=a83cf764-f177-4f27-81f7-615bfb418d43查询订单状态

交易状态:

WAIT_BUYER_PAY(交易创建,等待买家付款)

TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)

TRADE_SUCCESS(交易支付成功)

TRADE_FINISHED(交易结束,不可退款)

订单查询接口响应信息如下:

{"alipay_trade_query_response":{"code":"10000","msg":"Success","buyer_logon_id":"cvj***@sandbox.com","buyer_pay_amount":"0.00","buyer_user_id":"2088102177032991","buyer_user_type":"PRIVATE","invoice_amount":"0.00","out_trade_no":"a83cf764-f177-4f27-81f7-615bfb418d43","point_amount":"0.00","receipt_amount":"0.00","total_amount":"99.80","trade_no":"2022091222001432990501977609","trade_status":"WAIT_BUYER_PAY"},"sign":"Ab5EVgiN1y+4z78gIfepK9V4ZDb03gX4IjE3Ao/O3LfIRclFVoTFbvl9MbkVvJ7jfELt/cQ3HQYs9ihxQC3n+2xz/tS0MwYVlvPIdBfu+9uP9nzjYp6Qzd1ccTag0BTCue/bASUdV3Ze4/l86Zec/FC7x30HIu2dPVY9PPK7QabXUypFLb24DUkTPUlb4xr7TSz6S6Zum1vOHabFPvSR1IgQ/ZqC5dnfmB60KclcyWAchfoBvTHJCfytnXZac8iAAfd+E2PKE2SOqpFQFquvC75/JleBsXdt0AuXMXXKDKJTq0g6qPVEOSgZQW+hnsbOaIB2A2OTxlNrvtdOBSVQ8A=="}

订单关闭测试

AlipayUtil添加订单关闭方法

    public String payClose(String outTradeNo) throws AlipayApiException {
        // 根据支付宝的配置生成一个支付客户端
        AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl, app_id, merchant_private_key, "json", charset, alipay_public_key, sign_type);

        // 创建一个支付请求
        AlipayTradeCloseRequest alipayRequest = new AlipayTradeCloseRequest();

        JSONObject bizContent = new JSONObject();
        // 该交易在支付宝系统中的交易流水号。最短 16 位,最长 64 位。和out_trade_no不能同时为空,如果同时传了 out_trade_no和 trade_no,则以 trade_no为准。
//        bizContent.put("trade_no", "2013112611001004680073956707");
        // 	订单支付时传入的商户订单号,和支付宝交易号不能同时为空。 trade_no,out_trade_no如果同时存在优先取trade_no
        bizContent.put("out_trade_no", outTradeNo);
        alipayRequest.setBizContent(bizContent.toString());
        AlipayTradeCloseResponse response = alipayClient.execute(alipayRequest);
        if(response.isSuccess()){
            System.out.println("调用成功");
            return response.getBody();
        } else {
            System.out.println("调用失败");
            return "订单关闭失败。";
        }
    }

订单关闭接口

    /**
     * 未支付订单关闭
     * @param outTradeNo 商户订单号
     * @return
     * @throws AlipayApiException
     */
    @GetMapping(value = "/pay/payClose")
    @ResponseBody
    public String payClose(String outTradeNo) throws AlipayApiException {
        String pay = alipayUtil.payClose(outTradeNo);
        return pay;
    }

访问:http://localhost:8080/pay/payClose?outTradeNo=a83cf764-f177-4f27-81f7-615bfb418d43接口关闭订单

订单关闭接口响应信息如下:

{"alipay_trade_close_response":{"code":"10000","msg":"Success","out_trade_no":"a83cf764-f177-4f27-81f7-615bfb418d43","trade_no":"2022091222001432990501977609"},"sign":"Jem6c7OOfcRHbats0Cx7nGJivIqzrnGwzAYElyay3jEVRKcd/gCYkMwpAM7axDg6PAKLRPS7yXW9GyFeuQm/vweKrEeQxZPq9GbBFLZmwJ272nj0Qxo5lkqwI7nneU1srje/HfVOF8uTiPQIr1kO8FZw0z4QD2E28PFNUG7xouVweN5+U847ha2crWoWJR/VtJRr5oR925/BMlPjOt8ih25P3Wt0SxiXnU7/iKPV7OK7NJV4zGIZ81AO1kFD+rNEWkDbbRnESPEqvTTSqbWLrAP8n1nKvCoaQRRCsyJvuCv9m6gs7AG62qZxYLca9QbiIUjHtGqMOR8g8V5Vfz8bHA=="}

再次访问http://localhost:8080/pay/payQuery?outTradeNo=a83cf764-f177-4f27-81f7-615bfb418d43查询订单状态

交易状态:

WAIT_BUYER_PAY(交易创建,等待买家付款)

TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)

TRADE_SUCCESS(交易支付成功)

TRADE_FINISHED(交易结束,不可退款)

订单查询接口响应信息如下:

{"alipay_trade_query_response":{"code":"10000","msg":"Success","buyer_logon_id":"cvj***@sandbox.com","buyer_pay_amount":"0.00","buyer_user_id":"2088102177032991","buyer_user_type":"PRIVATE","invoice_amount":"0.00","out_trade_no":"a83cf764-f177-4f27-81f7-615bfb418d43","point_amount":"0.00","receipt_amount":"0.00","total_amount":"99.80","trade_no":"2022091222001432990501977609","trade_status":"TRADE_CLOSED"},"sign":"Ab5EVgiN1y+4z78gIfepK9V4ZDb03gX4IjE3Ao/O3LfIRclFVoTFbvl9MbkVvJ7jfELt/cQ3HQYs9ihxQC3n+2xz/tS0MwYVlvPIdBfu+9uP9nzjYp6Qzd1ccTag0BTCue/bASUdV3Ze4/l86Zec/FC7x30HIu2dPVY9PPK7QabXUypFLb24DUkTPUlb4xr7TSz6S6Zum1vOHabFPvSR1IgQ/ZqC5dnfmB60KclcyWAchfoBvTHJCfytnXZac8iAAfd+E2PKE2SOqpFQFquvC75/JleBsXdt0AuXMXXKDKJTq0g6qPVEOSgZQW+hnsbOaIB2A2OTxlNrvtdOBSVQ8A=="}