• SpringBoot实现支付宝沙箱


    SpringBoot实现支付宝沙箱

    接入文档:https://opendocs.alipay.com/common/02khjm

    1 申请沙箱账号并配置

    https://open.alipay.com/develop/manage
    ①申请沙箱账号
    在这里插入图片描述
    ②配置公钥
    在这里插入图片描述

    选择启用,启用之后选择查看,可以看到有应用公钥、应用私钥、支付宝公钥,这三个是需要记住的

    如果要测试APP支付的,可以下载沙箱版支付宝APP(暂支持Android)
    
    • 1

    沙箱版的支付宝APP,系统会默认给我们配置好账号,不用我们自己注册
    在这里插入图片描述
    沙箱版APP下载,在页面左侧的沙箱工具中,直接使用正式版支付宝扫码下载即可

    2 创建SpringBoot项目配置环境

    此处为了演示,我就没有创建数据库、以及实体类等操作了

    如果有人想看稍微完整的过程,可以在gitee或者GitHub上搜索Alipay-demo
    例如:https://gitee.com/xqnode/alipay-demo?_from=gitee_search

    注意:我们如果想要支付宝调用我们,需要暴露在公网,此处我使用内网穿透工具natapp实现

    natapp官网
    大家参考网上的教程实现即可,该工具是免费的。

    2.1 application.properties

    # 应用名称
    spring.application.name=demo
    # 应用服务 WEB 访问端口
    server.port=8080
    
    
    # 支付宝沙箱配置
    alipay.appId=2021000121681756
    alipay.appPrivateKey=MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCXUQi/JIYwYTfMAZTzirtUOjcUFh2yZ0MrueG3fUnun+LO1tnUvSZk+nKjpYpE5k0RRs+M3t2YgfZLGHed/34iVACgIP2hKzb3DLLO0qUgCOj6kUdbpReWA1k97Ga2l7DvknePYkg+XCtvE8s4jflAxYaKEpmIwrKgl9TlAO9+6yObEVbyLkQOwDamsTA2vqwVYXu9NIB5cnNV0qWPy4/NXaQ9+1IgJcvT71fnVku6vGr4rxUoWGg9FjDFzADLN4KzUbF5+qp+3CHrtF5I8GJ4fCLIw9H8N/uZW+3T5+6ovg+4IDl9eVzMAp8dpy1LKy4+dlX7kggmDAwyaJgYvFSLAgMBAAECggEALTnnJ1o/UU59YthGMNSSUQZlV/eUQLJkfTk9oZ4s7smS/MdyrAcs5pmEkiz0Osuq1TMY7b3e9apCdweFGRA4HwKEfVfe9sD32LdO6kpDWGPRXrL1ZQrfFdNCZSO3P3PvSmu4mH6DoT/jK3v7DZhBm35uS+5rPVkUErPOyfORoZknx6+LS2Ih1EbykxJLj5Pmnc1MU0W4gGpckCVP43y5bKWLMXDMzQT72CqKJxgrnEzlhZH1IlFObMFvYhv0WCKu58Aq/filcWVeY3T6i44ZNU1/8iACex5ohteCoI+oC/E/FufE0k6MO7Iai1pD368zkAzHsKBuFWqtettAmzgzIQKBgQDc3cXvCjn9J5WqmzGgtFih+61UzG3F7ICaqy6xFLiSaqTlARS3w8eNrNgZEysXUXQz2ucBkzILHeKtTdVcj4W+cBngIa14cvINTn6R4/Yi9HZFmvdOpAfJXBajNvIEPbVAL4fbTSYfNEXR5hQ9S6RJ2uKvDhm4Ihy/36tTmXr9LQKBgQCvYwVrobpJOVXY6vh+tDm7dCTVVC4iqIJudZtu9IFi/nfSOkl7SNh0dBBDJXs0j9sW7w2EZIAdDkPtOxHLIEMBIiOM/bXcjA+De41WCFWeP9GEuzVfY6100uL93qSQnJN2MLuNyTDp65yEexrrehN5fhOhG0NSFRJWjKcOkTpblwKBgGKV51Tkpq+2LJsjfMpz1aAwG9VfDpyrDVh8knHeguhwC7xgeCPykq9NeIPwx2o4JHtE+Zn9XvgRVe3vcQ5IzfUMSrB9t9Ws0RhZciuiqmo93lEBc+Q5WXRq03v0+aAk/zNwQ98Cl8KT7ZpcbapSijmhJ0/mJlrHdze6GdpOBtTdAoGBAKkQ1B3P9eo2GdoTj11cUDayG/uEvUBtneXq+t13Vu5djJWb2E++heGkLDT+AYlGjxTJdgdEdfcMVFBv25QqUkzaYti7jT6/yQie5jyjphz5OfgwGqAMTx3JWEUPBSXduYx6J6Hi6oLju6o9nVKXCATakwN/a2LJqzbBORyixFWbAoGBAMI6KuvLND1C00rWWzxF2PzES9jUB1GA+vZ9qyOtQT33cYL43LNZylGaynpyg3W9onRLjan8HKeK7XpfuET+6SK2RoZQF9cJ1OheZixBQm7B2+ONPNhY0LbiWsIHQjFSeCS7Kw03J8eJd9M73X8eE8ha4OlQPpbYSMhBWb4jGzZ+
    alipay.alipayPublicKey=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn8X7CR4VKB7r7bcdfyc+23RJcmQdLPybnDBVlHMnZPM2aeQwQLgNymKUqxjMdQoPUtGWMV7x63xjTstaPLCnTJffQL4S9bLB8RskAniz+24uzGdqXOzWhpRk09LdjMOtbC8ceNrBtBLyQJoB2NtsB0pGh8fgHQHfX0b8lhyvpgmtg2BEXkXWpi9KBb5bSC79Evve30O7Vg4nWC5Rz/vv8Op/GGtLy03PvxovvEGMZgX3m8t+vYQIB5PpQaS0f3M4HguXL0cwol48iKDknDSzAhISwZHKzvu9AosXBi2kV9vQPBglJkHdYxxMlpiUy1BvrDyAhz9xFQiz+qCdv4L3GwIDAQAB
    alipay.notifyUrl="natapp映射的网址"/alipay/notify
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    pom文件所需依赖:

    <!-- alipay-sdk-java -->
    <dependency>
        <groupId>com.alipay.sdk</groupId>
        <artifactId>alipay-sdk-java</artifactId>
        <version>4.16.2.ALL</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.2 配置类【封装公私钥】

    AlipayConfig

    @Data
    @Component
    @ConfigurationProperties(prefix = "alipay")
    public class AlipayConfig {
        private String appId;
        //应用私钥
        private String appPrivateKey;
        //阿里公钥
        private String alipayPublicKey;
        //阿里调用我们的地址【内网穿透】
        private String notifyUrl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.3 创建实体类【与阿里交互的对象】

    //与阿里交互的对象
    @Data
    public class AliPay {
        private String traceNo;//我们的订单号
    
        private Double totalAmount;//总金额
    
        private String subject;//主题
    
        private String alipayTraceNo;//阿里的流水号
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.4 controller

    ①请求支付宝
    @GetMapping("/pay") // ?subject=xxx&traceNo=xxx&totalAmount=xxx
    public void pay(AliPay aliPay, HttpServletResponse response) throws IOException {
        //1.创建client,通过阿里SDK提供的client,负责调用支付宝的API
        AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL,
                alipayConfig.getAppId(),
                alipayConfig.getAppPrivateKey(),
                FORMAT,
                CHARSET,
                alipayConfig.getAlipayPublicKey(),
                SIGN_TYPE);
        //2.创建request,并设置request参数
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        request.setNotifyUrl(alipayConfig.getNotifyUrl());
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", aliPay.getTraceNo());//我们自己生成的订单编号
        bizContent.put("total_amount", aliPay.getTotalPrice());//订单总金额
        bizContent.put("subject", aliPay.getSubject());//支付名称
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");//固定配置
        request.setBizContent(bizContent.toString());
    
        //执行请求,拿到响应的结果,返回给浏览器
        String form = "";
        try{
            form = alipayClient.pageExecute(request).getBody();//调用SDK生成表单
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        //设置响应结果,将返回的内容写出到浏览器
        response.setContentType("text/html;charset=" + CHARSET);
        response.getWriter().write(form);//直接将完整的表单html输出到页面
        response.getWriter().flush();
        response.getWriter().close();
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    ②支付宝回调【post】
    /**
     * 支付宝异步回调【必须是POST】
     * @return
     */
    @PostMapping("/notify")
    public String payNotify(HttpServletRequest request) throws AlipayApiException {
        if(request.getParameter("trade_status").equals("TRADE_SUCCESS")){
            System.out.println("-------------支付宝异步回调----");
            Map<String, String> params = new HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            System.out.println("-----params-----------");
            for(String name : requestParams.keySet()){
                params.put(name, request.getParameter(name));
                System.out.println(name +"     " + request.getParameter(name));
            }
    
            String outTradeNo = params.get("out_trade_no");
            String gmtPayment = params.get("gmt_payment");//支付时间
            String alipayTradeNo = params.get("trade_no");
    
            String sign = params.get("sign");//拿到签名
            String content = AlipaySignature.getSignCheckContentV1(params);
            boolean checkSignature = AlipaySignature.rsa256CheckContent(content,
                    sign,
                    alipayConfig.getAlipayPublicKey(),
                    "UTF-8");//验证签名
            //支付宝验签
            if(checkSignature){
                //验签通过
                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"));
    
    
                // 查询订单
                //TODO 支付成功,操作数据库,创建对应订单,修改对应商品数据
    
            }
        }
    
        return "success";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    完整controller代码

    @RestController
    @RequestMapping("/alipay")
    public class AliPayController {
    
        //阿里网关地址
        private static final String GATEWAY_URL = "https://openapi.alipaydev.com/gateway.do";
    
        //数据格式
        private static final String FORMAT = "JSON";
    
        //编码格式
        private static final String CHARSET = "UTF-8";
    
        //签名方式
        private static final String SIGN_TYPE = "RSA2";
    
        @Resource
        private AlipayConfig alipayConfig;
    
    
        @GetMapping("/pay") // ?subject=xxx&traceNo=xxx&totalAmount=xxx
        public void pay(AliPay aliPay, HttpServletResponse response) throws IOException {
            //1.创建client,通过阿里SDK提供的client,负责调用支付宝的API
            AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL,
                    alipayConfig.getAppId(),
                    alipayConfig.getAppPrivateKey(),
                    FORMAT,
                    CHARSET,
                    alipayConfig.getAlipayPublicKey(),
                    SIGN_TYPE);
            //2.创建request,并设置request参数
            AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
            request.setNotifyUrl(alipayConfig.getNotifyUrl());
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", aliPay.getTraceNo());//我们自己生成的订单编号
            bizContent.put("total_amount", aliPay.getTotalPrice());//订单总金额
            bizContent.put("subject", aliPay.getSubject());//支付名称
            bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");//固定配置
            request.setBizContent(bizContent.toString());
    
            //执行请求,拿到响应的结果,返回给浏览器
            String form = "";
            try{
                form = alipayClient.pageExecute(request).getBody();//调用SDK生成表单
            } catch (AlipayApiException e) {
                e.printStackTrace();
            }
            //设置响应结果,将返回的内容写出到浏览器
            response.setContentType("text/html;charset=" + CHARSET);
            response.getWriter().write(form);//直接将完整的表单html输出到页面
            response.getWriter().flush();
            response.getWriter().close();
    
        }
    
        /**
         * 支付宝异步回调【必须是POST】
         * @return
         */
        @PostMapping("/notify")
        public String payNotify(HttpServletRequest request) throws AlipayApiException {
            if(request.getParameter("trade_status").equals("TRADE_SUCCESS")){
                System.out.println("-------------支付宝异步回调----");
                Map<String, String> params = new HashMap<>();
                Map<String, String[]> requestParams = request.getParameterMap();
                System.out.println("-----params-----------");
                for(String name : requestParams.keySet()){
                    params.put(name, request.getParameter(name));
                    System.out.println(name +"     " + request.getParameter(name));
                }
    
                String outTradeNo = params.get("out_trade_no");
                String gmtPayment = params.get("gmt_payment");//支付时间
                String alipayTradeNo = params.get("trade_no");
    
                String sign = params.get("sign");//拿到签名
                String content = AlipaySignature.getSignCheckContentV1(params);
                boolean checkSignature = AlipaySignature.rsa256CheckContent(content,
                        sign,
                        alipayConfig.getAlipayPublicKey(),
                        "UTF-8");//验证签名
                //支付宝验签
                if(checkSignature){
                    //验签通过
                    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"));
    
    
                    // 查询订单
                    //TODO 支付成功,操作数据库,创建对应订单,修改对应商品数据
    
                }
            }
    
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103

    3 测试

    在浏览器中输入:

    localhost:8080/alipay/pay?subject=收购阿里&traceNo=412341243&totalAmount=999999
    
    • 1

    在这里插入图片描述

    此处我们可以直接选用网上支付或者通过沙箱版APP扫码支付,输入开始沙箱账号的支付密码即可

    此处我选择网上支付,直接输入支付密码点击下一步
    在这里插入图片描述
    选择确认付款【余额不足的实现在沙箱账号那个位置,点击充值即可】:
    在这里插入图片描述

    至此,实现支付宝沙箱支付成功

    控制台结果:

    -------------支付宝异步回调----
    -----params-----------
    gmt_create     2022-10-19 11:37:11
    charset     UTF-8
    gmt_payment     2022-10-19 11:37:30
    notify_time     2022-10-19 11:37:32
    subject     收购阿里
    sign     YOeaSKhFkL8y4NPXIOizH18t2kDZRfVYFDVaqUDQMUO+1GfYg2ALxQblt6/AlZLqFD1I5ewFHG+8SdlOatO/ggWh04zuy+CDh/hdW0LIKzsCOAdAF+tgCxLnzB2EBdwkSVHlphplxjW3YxQfs92MYKs/NFTd2UlzILh+GwiJxSsjLxTTN5S7vpfqjBBcFiZ1um5OWA20x2ZuChYfgyJASnqSdWI0aL6dQDH72t8eprZ0yxHGlO9DVXZ9p65j00e62+KcDGlptcQOhdlPsfq1nhswJBQ+gcMgyah2K6FLbQYrO2D9uXTIywlhatvpyCtSkbPRWseHCn+od81dCpVrRw==
    buyer_id     2088622999628670
    invoice_amount     999999.00
    version     1.0
    notify_id     2022101900222113731028670522160981
    fund_bill_list     [{"amount":"999999.00","fundChannel":"ALIPAYACCOUNT"}]
    notify_type     trade_status_sync
    out_trade_no     49141241413
    total_amount     999999.00
    trade_status     TRADE_SUCCESS
    trade_no     2022101922001428670502495150
    auth_app_id     2021000121681756
    receipt_amount     999999.00
    point_amount     0.00
    app_id     2021000121681756
    buyer_pay_amount     999999.00
    sign_type     RSA2
    seller_id     2088621993737227
    交易名称: 收购阿里
    交易状态: TRADE_SUCCESS
    支付宝交易凭证号: 2022101922001428670502495150
    商户订单号: 49141241413
    交易金额: 999999.00
    买家在支付宝唯一id: 2088622999628670
    买家付款时间: 2022-10-19 11:37:30
    买家付款金额: 999999.00
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    4 更加完整详细代码

    https://gitee.com/Zifasdfa/alipay-demo
    参考:https://gitee.com/xqnode

  • 相关阅读:
    正点原子嵌入式linux驱动开发——新字符设备驱动实验
    免费获取天气预报的API接口(Json格式)
    nvm 版本管理详解
    4-9封装与隐藏
    Redis 的线程模型
    nvm 安装后出现的各种问题解决方法
    【Unity Shader】纹理实践5.0:世界空间下使用法线纹理
    C++ 核心编程(2)
    自定义注解,利用AOP实现日志保存(数据库),代码全贴,复制就能用
    Kernel Memory 入门系列:自定义处理流程
  • 原文地址:https://blog.csdn.net/weixin_45565886/article/details/127400241