SpringBoot整合支付宝沙箱支付功能完整案例

1、pom:

<dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>






        <dependency>
            <groupId>org.mybatis.spring.bootgroupId>
            <artifactId>mybatis-spring-boot-starterartifactId>
            <version>2.2.2version>
        dependency>

        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <scope>runtimescope>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>

        <dependency>
            <groupId>com.baomidougroupId>
            <artifactId>mybatis-plus-boot-starterartifactId>
            <version>3.4.3.1version>
        dependency>

        <dependency>
            <groupId>cn.hutoolgroupId>
            <artifactId>hutool-allartifactId>
            <version>5.8.3version>
        dependency>
        
        <dependency>
            <groupId>com.auth0groupId>
            <artifactId>java-jwtartifactId>
            <version>3.4.0version>
        dependency>

        
        <dependency>
            <groupId>com.alipay.sdkgroupId>
            <artifactId>alipay-easysdkartifactId>
            <version>2.2.0version>
        dependency>
    dependencies>

2、配置类:AliPayConfig

package com.pzj.springboot.config;

import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Data
@Component
@ConfigurationProperties(prefix = "alipay")
public class AliPayConfig {
    private String appId;
    private String appPrivateKey;
    private String alipayPublicKey;
    private String notifyUrl;


    @PostConstruct
    public void init() {
        // 设置参数(全局只需设置一次)
        Config options = getOptions();
        options.appId = this.appId;
        options.merchantPrivateKey = this.appPrivateKey;
        options.alipayPublicKey = this.alipayPublicKey;
        options.notifyUrl = this.notifyUrl;
        Factory.setOptions(options);
        System.out.println("=======支付宝SDK初始化成功=======");
    }

    private Config getOptions() {
        Config config = new Config();
        config.protocol = "https";
        config.gatewayHost = "openapi.alipaydev.com";
        config.signType = "RSA2";
        return config;
    }

}

3、实体类:AliPay,用于 controller 接口接受参数使用

package com.pzj.springboot.controller.dto;

import lombok.Data;

@Data
public class AliPay {

    private String subject;
    private String traceNo;
    private String totalAmount;

}

4、controller接口:AliPayController

package com.pzj.springboot.controller;

import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.pzj.springboot.controller.dto.AliPay;
import com.pzj.springboot.mapper.OrderMapper;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/alipay")
public class AliPayController {

    @Resource
    private OrderMapper orderMapper;

    @GetMapping("/pay")
    public String pay(AliPay aliPay) {
        AlipayTradePagePayResponse response;
        try {
            //  发起API调用(以创建当面付收款二维码为例)
            response = Factory.Payment.Page()
                    .pay(aliPay.getSubject(), aliPay.getTraceNo(), aliPay.getTotalAmount(), "");
        } catch (Exception e) {
            System.err.println("调用遭遇异常,原因:" + e.getMessage());
            throw new RuntimeException(e.getMessage(), e);
        }
        return response.getBody();
    }


    @PostMapping("/notify")  // 注意这里必须是POST接口
    public String payNotify(HttpServletRequest request) throws Exception {
        if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
            System.out.println("=========支付宝异步回调========");

            Map<String, String> params = new HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            for (String name : requestParams.keySet()) {
                params.put(name, request.getParameter(name));
                // System.out.println(name + " = " + request.getParameter(name));
            }

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

                // 更新订单未已支付
                orderMapper.updateState(tradeNo, 1, gmtPayment);
            }
        }
        return "success";
    }

}

5、application.properties

server.port=9090

######################## 配置MySQL连接  ##########################
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/vue?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456

mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

# 接入支付宝 (换成你自己的配置才能使用)
alipay.appId=2016101100661875
alipay.appPrivateKey=MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDCRZRqOUzIBwk7X5zEVtYIWSGOodU2Rj6VMJWSgvOGLQrGGsUq9spRQqxwhGgjETGedPX/qzcqM80afrlHbJfnz4KYE9KMPcsBVMBIwONOW53I6t7tOXTtd+2yYvhicosFor5fZhKsQoJfTwsSC+zIuSoNCGNWaHgyjrw3T09kjEDEXLBoVJeHtDRPsiXUk71RyLmNFpTjwh9o3juf46VmIKWJTSQYZ5USMF4vy58coq16rbbJFaC1gQkQ+hUgwXuxoy5VRkExMtD1nAfWF3TYnRfSXUal3RiQSNC2IJh7VL99GiyYb2K8o2GoM8Xcw2fovVx1W1K/pwAQL1f8H3WJAgMBAAECggEBAJj/73kRE5VdZTnrfS1sLjh46eLJNX//Jn6cus+ebmg3xQpsPugtYP1Kg0BCJzmm6usetjbbAyErltbNAuJrdd9NIE7hHarxZ5Xux1kFAH/Py55Wy6cM3ze+gedB5tix2SdhGolLfF1KLB8fw1o9JgiXO7Tz7Dg7Ip6+pyDwR1ipcmf22Gc4RFPZ+4GyhxhSMKoY6dHNippDJ3L0G9/Azw2cnAEWx/Vd02PU9b+Zj6f9wNR8uWqrTUQmKA5TmM5YFcmLjV/g6xIyRb2CT7mmPzrQdfIXGf9pHqAc3UpVKWi0zeagr7C9Hhxt0XuPI3fyGc9Kb2OpizbRXzTc3jmLmnkCgYEA/omyvggYXPo7mgGXVwZ5cEF0rz75I0+Qricwe15OmJiyqay+4R6RHLqlVafBQWMos5npdYHWLkAtto0uCJntwnY2V8AxEiHHN/PP4kR4M39CeD+YBdwL6QL+OmKc4EkWMKt5+dNKe7cp2BbCHaXAzsv74Qu3G8A+qqW6haOJu5MCgYEAw2NCZGxkw2K3HEusmFTRKFRSE5iva9ihhwy/uLfDYZ/epRCcYdh3+veqplex4qHPj1kis6gPuStWLZ7o2bKtkkdpWg/jZtBX93vzEN3OY8Z+OMCBZrqf2DO6ZWfjNWyhlYmQxX8dySUtwrME9fsMEpzoiG1MF87d+3O9qs2/k/MCgYEArSqs6c/EE21CIzI17cS/1XkSky76e+Vjfre2qheszqFfwJ8rYhOApO1kRfVTSTPtLKCGQ38FcWi0ljqVM7+KmwRQitBfXtzP65M5sPrlTseUH/0Li4URhIMgaYdyR0h4r+szHfeGlp931ApQP+83AhAfUCgYBvf7pIgo6x7ShfblPNDkHZiNzZr/0TRylOXxkdeUh28ntkqOkE8TnurtzkVhD+Kqa+v/gMm/B1E+T23cM1UEC6xCO7sGttpaE9aq9Xxavcxk4LZtexXviOsV5CNhmzyA0hv8Is4hCGU8AcZnqDQMMv7/jGudB9maCVuQPYb9dOvwKBgQC35caCVliQ0xPfhgB9mzxq+janKctq9q/8PPfQIJ0iQX1GqIe8PvXqvaXB5bZs5pBcPFfAawMwykFmAdUjmsZkfpTTz4ZErUFIhalvaqio0rpR78c2eRJnBw7ijRQF888Pyg84KriGJIj4MTMj5Js6sDh8ZKc+vesX4Drx40eYWA==
alipay.alipayPublicKey=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqs/u9nr3IEgpZ3ZLwsJBybq7QkQ3B/lt9bHtX5VZKGoPWM3Prc0RNYPbo44+ZKikqJBImqB1KwtrLmb+b+RSzY30ZRakaWoaqXVKG+DnAxr/VcIy+L4nwKnP2KE8WlVTq+0WvIP9v+D17OJlIp/yB3ffZNJtClOkvS6criGVKDk+Vp8Yoi6Hf/hRXmds4yHRriLmlvn+KcuW4XAchL3wLrwzP+STYl4JfvHFCqldgPjsQGxDJ0AlwZKp2zuYYSvNr66ojm8CtDt61CG4QwzyaJDkyUGE0bknFVVw8JJQ9b8LEJ4WPovDA94Ly
#	飞鸽内网穿透免费域名,否则,支付宝无法回调你的异步通知接口,告知支付状态
alipay.notifyUrl=http://pzj123.free.svipss.top/alipay/notify

6、支付宝相关参数配置(重点):

(比较麻烦,但是最重要的一步,需要细心点,而且支付宝页面可能有变动)

看到第5步中,有几个参数:
alipay.appId
alipay.appPrivateKey
alipay.alipayPublicKey
alipay.notifyUrl
如何获取了?

alipay.notifyUrl,这个参数,其实就是我们自己定义的接口地址,供支付宝回调,告知处理结果的。
所以,是自定义的,和普通controller没什么区别,主要是,你要知道,支付宝回调后,会给你回传
什么参数,然后,拿来更新自己订单状态。

alipay.appId
alipay.appPrivateKey
alipay.alipayPublicKey
这三个参数,如何获取了?
步骤如下:
https://opendocs.alipay.com/common/02kipl
SpringBoot整合支付宝沙箱支付功能完整案例_第1张图片
我是Windows系统,所以,下载Windows版本的,正常安装
SpringBoot整合支付宝沙箱支付功能完整案例_第2张图片
再打开客户端,如下所示操作即可:

这样,就得到 alipay.appPrivateKey 参数,对应图中的应用私钥,贴到application.properties中。
再通过,图中的应用公钥,去获取支付宝公钥。
获取步骤如下:
访问:https://open.alipay.com/
登录后,点击右侧控制台
页面最底下,点击沙箱SpringBoot整合支付宝沙箱支付功能完整案例_第3张图片
页面中,我们选择自定义秘钥,点击设置并查看
SpringBoot整合支付宝沙箱支付功能完整案例_第4张图片
SpringBoot整合支付宝沙箱支付功能完整案例_第5张图片
SpringBoot整合支付宝沙箱支付功能完整案例_第6张图片
SpringBoot整合支付宝沙箱支付功能完整案例_第7张图片

这里,我们就得到了 alipay.appId 参数,就是截图中,基本信息-APPID。
同时,获取到 alipay.alipayPublicKey 这个参数,及图中的支付宝公钥。

复制粘贴到application.properties中即可。

最后,我们还要获取,支付宝沙箱账号,这样,才能测试购买
SpringBoot整合支付宝沙箱支付功能完整案例_第8张图片
到此为止,所有的配置就都做好了,下面进入测试环节。

7、测试:

请求地址:
http://mypay.free.svipss.top/alipay/pay?subject=买书&traceNo=20220723130000001&totalAmount=100.0

会跳转到支付宝沙箱环境的登录页,输入上面的沙箱账号
SpringBoot整合支付宝沙箱支付功能完整案例_第9张图片
SpringBoot整合支付宝沙箱支付功能完整案例_第10张图片
SpringBoot整合支付宝沙箱支付功能完整案例_第11张图片
付款成功后,你再次看自己的商家账号下的账户余额时,就多了刚才支付的100元。

补充:

其中飞鸽内网穿透教程
https://blog.csdn.net/Brave_heart4pzj/article/details/120042579

源码位置:
springboot-vue-demo

你可能感兴趣的:(Spring,All,spring,boot)