• 支付宝沙箱支付


    支付宝沙箱支付

    支付宝沙箱(Alipay Sandbox)是支付宝提供的一个模拟环境,用于开发者在不影响真实交易的情况下进行支付宝相关功能的测试和调试。在软件开发中,沙箱环境通常指的是一个隔离的测试环境,可以模拟真实环境的行为,但不会对真实数据产生影响。

    支付宝沙箱为开发者提供了一套模拟的支付流程和接口,使开发者能够在沙箱环境中进行支付测试,验证其支付功能是否正常工作,而无需使用真实的资金进行交易。这有助于开发者在应用上线之前进行充分的测试,确保支付流程的稳定性和安全性。

    使用支付宝沙箱,开发者可以模拟各种支付场景,包括扫码支付、APP支付、H5支付等。此外,支付宝沙箱还提供了一些调试工具和接口文档,帮助开发者更方便地进行测试和开发。

    使用支付宝沙箱环境可以帮助开发者在开发和测试阶段及时发现和解决问题,确保支付功能的稳定和安全。一旦开发者在支付宝沙箱环境中完成了测试和调试,就可以将代码和配置切换到真实的支付宝环境中进行生产部署。

    支付宝开放平台 (alipay.com)

    准备工作

    引入依赖

            
            <dependency>
                <groupId>com.alipay.sdkgroupId>
                <artifactId>alipay-sdk-javaartifactId>
                <version>4.38.133.ALLversion>
            dependency>
            
           <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starterartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
            dependency>
            <dependency>
                <groupId>com.alibabagroupId>
                <artifactId>fastjsonartifactId>
                <version>1.2.33version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    配置文件

    alipay:
        appId: # 应用id
        appPrivateKey: # 应用私钥
        alipayPublicKey: # 支付宝公钥
        notifyUrl: # 异步通知地址 
        gateway: # 支付宝网关
    server:
        port: 8088
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    代码编写

    配置类

    AliPayConfig 支付宝支付配置类 方便我们获取配置参数

    @Data
    @Component
    @ConfigurationProperties(prefix = "alipay")
    public class AliPayConfig {
        private String appId;
        private String appPrivateKey;
        private String alipayPublicKey;
        private String notifyUrl;
        private String gateway;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    AlipayClientConfig 支付宝客户端配置类

    @Configuration
    public class AlipayClientConfig {
        @Autowired
        private AliPayConfig aliPayConfig;
    
        @Bean
        public AlipayClient getAlipayClient(){
            AlipayClient alipayClient = new DefaultAlipayClient(
                    aliPayConfig.getGateway(),
                    aliPayConfig.getAppId(),
                    aliPayConfig.getAppPrivateKey(),
                    AlipayConstants.FORMAT_JSON,
                    AlipayConstants.CHARSET_UTF8,
                    aliPayConfig.getAlipayPublicKey(),
                    AlipayConstants.SIGN_TYPE_RSA2);
            return alipayClient;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    controller

    AlipayController

    @RestController
    @RequestMapping("/alipay")
    public class AlipayController {
        @Autowired
        private AlipayService alipayService;
    
        /**
         *  支付接口
         * @param order 订单
         * @return
         */
        @PostMapping("/pay")
        public R pay(@RequestBody Order order){
            // 使用时间当订单号
            order.setOrderId(String.valueOf(System.currentTimeMillis()));
            return alipayService.pay(order);
        }
    
        /**
         *  订单状态通知 异步通知
         * @param request
         * @return
         * @throws AlipayApiException
         */
        @GetMapping("/notify")
        public R payNotify(HttpServletRequest request) throws AlipayApiException {
            return alipayService.payNotify(request);
        }
    }
    
    
    • 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

    Service

    AlipayService

    public interface AlipayService {
        /**
         *  支付接口
         * @param order
         * @return
         */
        R pay(Order order);
    
        /**
         *  异步通知
         * @param request
         * @return
         */
        R payNotify(HttpServletRequest request);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    AlipayServiceImpl

    @Service
    public class AlipayServiceImpl implements AlipayService {
        @Value("${alipay.alipayPublicKey}")
        private String publicKey;
        @Value("${alipay.notifyUrl}")
        private String notifyUrl;
    
        @Autowired
        private AlipayClient alipayClient;
        @Override
        public R pay(Order order){
            AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
            // 异步通知的地址
            request.setNotifyUrl(notifyUrl);
            Map<String,String> map = new HashMap<>();
            map.put("out_trade_no",order.getOrderId());
            map.put("total_amount",order.getPrice());
            map.put("subject",order.getSubject());
            map.put("body",order.getBody());
            map.put("product_code","FAST_INSTANT_TRADE_PAY");
    
            // 设置业务参数
            request.setBizContent(JSONObject.toJSONString(map));
    
            // 发起支付请求
            // 发起支付请求
            AlipayTradePagePayResponse response = null;
            try {
                response = alipayClient.pageExecute(request);
            } catch (AlipayApiException e) {
                throw new RuntimeException(e);
            }
            // 获取响应结果
            if (response.isSuccess()) {
                System.out.println("调用成功");
                System.out.println("支付宝支付链接:" + response.getBody());
                return R.ok(response.getBody());
            } else {
                System.out.println("调用失败");
                System.out.println("错误信息:" + response.getMsg());
                return R.fail("调用失败",40010);
            }
        }
    
        @Override
        public R payNotify(HttpServletRequest request) {
            Map<String, String[]> paramMap = request.getParameterMap();
            Map<String, String> params = new HashMap<>();
            for (Map.Entry<String, String[]> entry : paramMap.entrySet()) {
                String name = entry.getKey();
                String[] values = entry.getValue();
                StringBuilder valueStr = new StringBuilder();
                for (int i = 0; i < values.length; i++) {
                    valueStr.append((i == values.length - 1) ? values[i] : values[i] + ",");
                }
                params.put(name, valueStr.toString());
            }
    
            // 调用SDK验证签名
            boolean verifyResult = false;
            try {
                verifyResult = AlipaySignature.rsaCheckV1(params, publicKey, AlipayConstants.CHARSET_UTF8, AlipayConstants.SIGN_TYPE_RSA2);
            } catch (AlipayApiException e) {
                throw new RuntimeException(e);
            }
    
            if (verifyResult) {
                // 验证成功,处理业务逻辑,更新订单状态等
                // 注意:请防止重复处理,可以通过记录支付状态或者订单号来判断是否已经处理过
                System.out.println("支付宝异步通知验证成功");
                // 返回给支付宝成功处理的响应
                return R.ok();
            } else {
                // 验证失败,不处理业务逻辑
                System.out.println("支付宝异步通知验证失败");
                // 返回给支付宝失败处理的响应
                return R.fail("支付失败",40010);
            }
        }
    }
    
    • 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

    工具类

    Order 订单类

    @Data
    public class Order {
        // 订单id
        private String orderId;
        // 价格
        private String price;
        // 商品名称
        private String subject;
        // 商品描述
        private String body;
        // 支付场景
        /**
         * FAST_INSTANT_TRADE_PAY(即时到账):适用于即时交易场景,买家付款后,卖家立即收到款项。
         * QUICK_MSECURITY_PAY(手机网页支付):适用于手机网页支付场景。
         * FACE_TO_FACE_PAYMENT(当面付):适用于线下面对面付款场景,比如扫码支付。
         * APP支付(APP支付场景):适用于在APP内的支付场景。
         * WAP支付(手机网站支付场景):适用于手机网站支付场景。
         * PRE_AUTH(预授权):适用于预先授权场景,买家授权预先冻结资金,商家在完成业务后调用支付宝解冻资金
         */
        private String code;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    R 响应类

    @Data
    public class R {
        private String data;
        private String msg;
        private int code;
    
        public R() {
        }
    
        public R (String msg, int code) {
            this.msg = msg;
            this.code = code;
        }
    
        public R( String msg, int code,String data) {
            this.data = data;
            this.msg = msg;
            this.code = code;
        }
    
        public static R ok(){
            return new R("成功",200);
        }
        public static R ok(String data){
            return new R("成功",200,data);
        }
        public static R fail(String message, int code) {
            return new R( message,code);
        }
    }
    
    • 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

    测试页面

    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title>商城title>
        <script src="https://cdn.jsdelivr.net/npm/vue@2">script>
        <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js">script>
    head>
    <body>
    <div id="box">
        <div>
            <h1>订单列表h1>
            <ul>
                <li v-for="order in orders" :key="order.orderId">
                    <h3>{{ order.subject }}h3>
                    <p>价格: ¥{{ order.price }}p>
                    <p>{{ order.body }}p>
                    <button v-on:click="pay(order)">购买button>
                    <hr>
                li>
            ul>
        div>
        <div v-html="paymentFormHtml">div>
    div>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#box',
            data: {
                orders: [
                    {
                        "price": "12148.00",
                        "subject": "iPhone 15 Pro Max 512GB 原色钛金属",
                        "body": "iPhone 15 Pro Max 512GB 原色钛金属"
                    },
                    {
                        "price": "4999",
                        "subject": "xiaomi 14 钛金属",
                        "body": "xiaomi 14 钛金属 256gb"
                    }
                ],
    
    
                paymentFormHtml: "" // 新增 paymentFormHtml 属性
            },
            methods: {
                pay: function (order) {
    
                    axios.post('http://127.0.0.1:8088/alipay/pay', order)
    
                        .then(res => {
                            // 处理支付成功的逻辑
                            console.log('支付成功', res.data);
                            this.paymentFormHtml = res.data.data;
                            // 手动提交表单
    
                            // 在延时后提交表单
                            setTimeout(function () {
                                document.forms['punchout_form'].submit();
                            }, 1000); // 1000毫秒,即1秒
    
                        })
                        .catch(error => {
                            // 处理支付失败或其他错误的逻辑
                            console.error('支付失败', error);
                        });
                }
            }
        });
    script>
    
    
    body>
    
    html>
    
    
    • 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

    测试

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    计算机毕业设计Java校园食堂订餐系统(源码+系统+mysql数据库+Lw文档)
    如何使用Grid中的repeat函数
    美化QTabWidget(3)
    Docker搭建ELK
    jupyter notebook找不到python内核(kernel)的解决记录
    干货︱部分领域数字孪生白皮书及报告汇总(附下载)
    保姆级前端翻牌效果(CSS)
    Windows系统利用cpolar内网穿透搭建Zblog博客网站并实现公网访问内网!
    Vue:实现TodoList案例(尚硅谷)
    Java面试题——继承,多态
  • 原文地址:https://blog.csdn.net/zxwyhzy/article/details/134498076