支付宝沙箱环境+SpringBoot+内网穿透整合开发

news2024/10/7 8:22:22

目录

1.查看沙箱账号

2.内网穿透

3.沙箱环境整合SpringBoot开发


下面我将以实际案例详细介绍如何使用沙箱环境进行支付宝支付对接的开发

1.查看沙箱账号

 首先什么是沙箱账号?

沙箱账号是指在支付宝沙箱环境中创建的测试账户,用于模拟真实的支付流程。在开发和测试过程中,使用沙箱账号可以避免真实账户数据的泄露和风险,同时可以进行多种测试场景和交易模拟,以保证应用程序的稳定性和可靠性。

支付宝沙箱环境中的测试账户和真实账户一样,可以进行支付、退款、查询等操作。开发人员可以通过创建和使用沙箱账号,进行多种测试和调试,以保证应用程序的正确性和稳定性。同时,沙箱账号的创建和使用是免费的,不需要任何费用。

需要注意的是,沙箱账号只能在支付宝沙箱环境中使用,不能在生产环境中使用。在将应用程序上线之前,需要使用真实账户进行测试和验证。

1.登录支付宝开放平台:https://open.alipay.com/platform/home.htm

 2.点击登录,系统会弹出一个二维码进行扫描登录,当然也可以使用账号密码进行登录

3.点击进入控制台

4.开发工具推荐中选择使用沙箱环境

5.自此完成沙箱账号信息的查看

2.内网穿透

获取方式:电脑应用商店搜索花生壳

网页端申请配置:

1.需要进行实名认证否则用不了

2.需要花6元买个域名映射

 3.将ip和端口换成刚刚申请的域名,填入回调地址处,用于后续的支付宝系统回调接口

客户端:开启自定义映射

下面将进入主题,如何整合SpringBoot进行支付开发

3.沙箱环境整合SpringBoot开发

 1.1.创建Spring Boot项目

可以使用Spring Initializr快速创建一个新项目也可以在maven创建的基础上加上相关的依赖

如果您是maven创建的项目请加如下依赖:

 <dependencies>
        <!-- Spring Boot starter dependencies -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.5.4</version>
        </dependency>
  </dependencies>

如果是基于Spring Initializr快速创建一个SpringBoot项目则导入如下依赖:

2.导入依赖

 <dependencies>
        <!-- Other dependencies -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>3.0.0</version>
        </dependency>
        <!-- Fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.78</version>
        </dependency>
        <!-- slf4j -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.32</version>
        </dependency>

        <!-- JSON -->
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20210307</version>
        </dependency>
    </dependencies>

3.配置应用程序

在application.yml文件中,我们需要添加支付宝支付的相关配置。

# 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号,在沙箱应用中获取
appId: 
# 商户私钥,您的PKCS8格式RSA2私钥,通过开发助手生成的应用私钥
privateKey: 
# 支付宝公钥,在沙箱应用获取,通过应用公钥生成支付宝公钥
publicKey: 
# 服务器异步通知页面路径需http://格式的完整路径,不能加?id=123这类自定义参数
notifyUrl: https://7*****.zicp.fun/alipay/notify
# 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数
returnUrl: https://7*****.zicp.fun/alipay/success
# 支付宝网关,在沙箱应用中获取
gatewayUrl: 

 下面就上面的参数进行说明

所以应用ID、应用私钥和支付宝公钥可以在支付宝开放平台上获取。gateway-url是支付宝支付接口的地址,return-url和notify-url是支付完成后跳转的地址和支付结果通知地址。

4.创建支付服务

接下来,创建一个支付服务类,用于处理支付请求和支付结果通知。在创建支付服务之前,我要先创建一个AlipayClient对象,用于调用支付宝支付接口。

@Configuration
public class AlipayConfig {
  //获取配置文件中的配置信息
    //应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
    @Value("${appId}")
    private String appId;

    //商户私钥 您的PKCS8格式RSA2私钥
    @Value("${privateKey}")
    private String privateKey;

    //支付宝公钥
    @Value("${publicKey}")
    private String publicKey;

    //支付宝网关
    @Value("${gatewayUrl}")
    private String gatewayUrl;

 @Bean
    public AlipayClient alipayClient() {
        return new DefaultAlipayClient(gatewayUrl, appId, privateKey, "json", "UTF-8", publicKey, "RSA2");
    }
}

再创建一个支付服务,用于处理支付请求和支付结果通知。

@Service
public class AlipayService {
    @Autowired
    private AlipayClient alipayClient;

      //服务器异步通知页面路径
    @Value("${notifyUrl}")
    private String notifyUrl;

    //页面跳转同步通知页面路径
    @Value("${returnUrl}")
    private String returnUrl;

    /**
     * 发起支付请求
     * @param order 订单信息
     * @return 支付页面HTML代码
     */
    public String pay(Order order) {
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        request.setReturnUrl(returnUrl);
        request.setNotifyUrl(notifyUrl);

        Map<String, Object> params = new HashMap<>();
        params.put("out_trade_no", order.getOrderId());
        params.put("total_amount", order.getTotalAmount());
        params.put("subject", order.getSubject());
        params.put("body", order.getBody());
        params.put("product_code", "FAST_INSTANT_TRADE_PAY");

        request.setBizContent(JSON.toJSONString(params));

        try {
            AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
            return response.getBody();
        } catch (AlipayApiException e) {
            throw new RuntimeException("支付宝支付失败", e);
        }
    }

    /**
     * 处理支付结果通知
     *
     * @param request 支付结果通知参数
     * @return 处理结果
     */
    public String notify(HttpServletRequest request) throws AlipayApiException {
           log.info("异步回调");
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = iter.next();
            String[] values = requestParams.get(name);
            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());
        }

        log.info("请求参数的传入:" + params);
        String tradeStatus = params.get("trade_status");
        log.info("tradeStatus:" + tradeStatus);
        String outTradeNo = params.get("out_trade_no");
        log.info("outTradeNo:" + outTradeNo);
        String totalAmount = params.get("total_amount");
        log.info("totalAmount:" + totalAmount);
//
//        // 从数据库中查询订单信息
//        Order order = orderService.findByOutTradeNo(outTradeNo);

        // 验证通知是否来自支付宝服务器
        if (!AlipaySignature.rsaCheckV1(params, publicKey, charset, signType)) {
            return "fail";
        }

        // 验证交易状态和订单金额等信息
//            if (!"TRADE_SUCCESS".equals(tradeStatus) || !totalAmount.equals(order.getTotalAmount().toString())) {
        if (!"TRADE_SUCCESS".equals(tradeStatus)) {
            return "fail";
        }

        // 根据交易状态进行业务处理
        switch (tradeStatus) {
            case "TRADE_SUCCESS":
                // 更新订单状态、发货等操作
                break;
            case "TRADE_CLOSED":
                // 订单关闭处理
                break;
            default:
                // 其他状态处理
                break;
        }

        return "success";
        }

    public String success(HttpServletRequest request) throws AlipayApiException, UnsupportedEncodingException {
        log.info("=================同步回调======================");
        // 获取支付宝GET过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) 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);
        }
        log.info("支付宝平台同步回调传入的参数:" + params);
        //验证签名(支付宝公钥)
        boolean signVerified = AlipaySignature.rsaCheckV1(params, publicKey, charset, signType); // 调用SDK验证签名
        //验证签名通过
        if (signVerified) {
            // 商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");

            // 支付宝交易流水号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");

            // 付款金额
            float money = Float.parseFloat(new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8"));

            log.info("商户订单号=" + out_trade_no);
            log.info("支付宝交易号=" + trade_no);
            log.info("付款金额=" + money);

            //在这里编写自己的业务代码(对数据库的操作)
			/*
			################################
			*/
            //跳转到提示页面(成功或者失败的提示页面)
            return "交易成功!";
        } else {
            //跳转到提示页面(成功或者失败的提示页面)
            return "交易失败!";
        }
    }
}

在AlipayService类中,我们使用@Autowired注解注入AlipayClient对象,并使用@Value注解注入支付宝支付的相关配置。

pay方法用于发起支付请求,首先创建一个AlipayTradePagePayRequest对象,设置returnUrl和notifyUrl,然后将订单信息封装成一个Map对象调用alipayClient的pageExecute方法发起支付请求,并返回支付页面的HTML代码。

notify方法用于处理支付结果通知,首先使用AlipaySignature.rsaCheckV1方法验证支付结果通知的签名,然后根据支付结果更新订单状态。

success方法也是如此,但是开发中用notify异步处理效率更高一些。

 5.5.创建支付控制器

创建一个支付控制器,用于处理支付请求和支付结果通知。

@Controller
@RequestMapping("/alipay")
public class AlipayController {
    @Autowired
    private AlipayService alipayService;

    /**
     * 发起支付请求
     * @param order 订单信息
     * @return 支付页面HTML代码
     */
    @RequestMapping("/pay")
    @ResponseBody
    public String pay(Order order) {
        return alipayService.pay(order);
    }

     /**
     * 处理支付结果通知
     * @param request 支付结果通知参数
     * @return 处理结果
     */
    @PostMapping("/notify")
    @ResponseBody
    public String notify(@RequestParam HttpServletRequest request) throws AlipayApiException {
        return alipayService.notify(request);
    }

    /**
     * 支付完成后跳转回商户网站的地址
     *
     * @return 跳转页面
     */
    @RequestMapping("/success")
    @ResponseBody
    public String success(HttpServletRequest request) throws UnsupportedEncodingException, AlipayApiException {
        return alipayService.success(request);
    }
//根据自己的实际业务选择是同步处理还是异步处理
}

在AlipayController类中,我们使用@Autowired注解注入AlipayService对象,并创建pay、notify和returnUrl三个方法,分别用于处理支付请求、支付结果通知和支付完成后跳转回商户网站的地址。 

        这里需要注意的是,只有当方法的返回值类型为voidString时,才需要使用@ResponseBody注解。如果方法的返回值类型为其他类型(如对象、集合等),Spring MVC会自动将其转换为JSON或XML格式的数据并返回给客户端,无需使用@ResponseBody注解。

 6.测试支付功能

现在,我们已经完成了支付宝支付的整合,可以通过调用支付控制器中的pay方法发起支付请求,并在支付完成后处理支付结果通知和支付完成后跳转回商户网站的地址。

可以通过Postman等工具模拟支付请求,或者在网站上添加一个支付按钮,点击按钮后跳转到支付页面完成支付。

在网站上面添加一个支付按钮

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/alipay/pay" method="post">
    订单号:<input type="text" name="out_trade_no" required><br/>
    订单名称:<input type="text" name="subject" required><br/>
    付款金额:<input type="text" name="total_amount" required><br/>
    商品描述:<input type="text" name="body"><br/>
    <input type="submit" value="下单"> <input type="reset" value="重置">
</form>

</body>
</html>

浏览器地址栏输入:http://localhost:8081/

输入支付账号和支付密码即可完成支付

                     支付宝沙箱环境+SpringBoot+内网穿透整合开发完美收官!

                                          有任何问题随时私信我!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/416063.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

The 2022 ICPC Asia Xian Regional Contest

题目顺序大致按照难度排序。 F. Hotel 现在酒店中有单人间和双人间&#xff0c;价格分别是c1&#xff0c;c2&#xff0c;现在有n个队&#xff0c;每队三个人&#xff0c;性别分别用字母表示&#xff0c;当两个人性别相同且在同一个队时&#xff0c;他们可以住在双人间中。求最…

【跑跑Github开源项目系列】基于YOLO和Streamlit的车辆识别系统demo

【跑跑Github开源项目系列】基于YOLO和Streamlit的车辆识别系统demo写在前面环境配置创建虚拟环境安装库项目运行写在前面 相信很多朋友跟我一样在github等平台上偷代码 (读书人的事怎么能叫偷呢) 的时候会发现伟大且无私的作者虽然开源了代码但是readme文件该写的没写&#x…

2023TYUT移动应用软件开发程序设计和填空

目录 程序设计 程序设计1&#xff1a;根据要求设计UI,补充相应布局文件&#xff0c;即.xml文件 程序设计2&#xff1a;根据要求,补充Activity.java文件 程序填空 说明&#xff1a; 程序设计 程序设计1&#xff1a;根据要求设计UI,补充相应布局文件&#xff0c;即.xml文件…

【C++初阶】第十篇:list模拟实现

文章目录一、list的模拟实现三个类及其成员函数接口总览结点类的模拟实现迭代器类的模拟实现迭代器类的模板参数说明迭代器operator->的重载迭代器模拟实现代码list的模拟实现无参构造函数带参构造拷贝构造函数赋值运算符重载函数析构函数begin和endinserteraselist的迭代器…

WordPress添加阿里云OSS对象云储存配置教程

背景&#xff1a;随着页面文章增多&#xff0c;内置图片存储拖连网站响应速度&#xff0c;这里对我来说主要是想提升速度 目的&#xff1a;使用第三方云存储作为图片外存储(图床)&#xff0c;这样处理可以为服务器节省很多磁盘空间&#xff0c;在网站搬家的时候减少文件迁移的工…

【数据结构】堆(笔记总结)

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;数据结构 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&…

MySQL--数据库基础--0406

目录 1.什么是数据库&#xff1f; 2. 基本使用 2.1 连接服务器 2.2 数据库的操作在Linux中的体现 2.3 使用案例 3.服务器&#xff0c;数据库&#xff0c;表关系 4.数据逻辑存储 5.SQL的分类 6.存储引擎 1.什么是数据库&#xff1f; 数据库和文件 文件或者数据库&…

OK-MX93开发板-实现Web页面无线点灯

上篇文章&#xff1a;i.MX9352——介绍一款多核异构开发板&#xff0c;介绍了OK-MX9352开发板的基础硬件功能。 本篇来使用OK-MX9352开发板&#xff0c;通过Web界面进行点灯测试&#xff0c;最终的效果如下&#xff1a; 在进行代码编写之前&#xff0c;先在Ubuntu虚拟机上把这…

对比损失Contrastive Loss(CVPR 2006)原理解析

paper&#xff1a;http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf 本文提出的对比损失contrastive loss被广泛应用于自监督模型中&#xff0c;但最初对比损失是作为一个特征降维方法而提出的。 摘要 降维是学习一种映射关系&#xff0c;通过这种映射关…

day10 线程池及gdb调试多线程

目录 线程池的概念 概念&#xff1a; 必要性&#xff1a; 线程池的基本结构&#xff1a; 线程池的实现 完整代码 线程的GDB调试 线程池的概念 概念&#xff1a; 通俗的讲就是一个线程的池子&#xff0c;可以循环的完成任务的一组线程集合&#xff1b; 必要性&#xff…

【软件工程】为什么要选择软件工程专业?

个人主页&#xff1a;【&#x1f60a;个人主页】 文章目录前言软件工程&#x1f4bb;&#x1f4bb;&#x1f4bb;就业岗位&#x1f468;‍&#x1f4bb;&#x1f468;‍&#x1f4bb;&#x1f468;‍&#x1f4bb;就业前景&#x1f6e9;️&#x1f6e9;️&#x1f6e9;️工作环…

趣谈之什么是 API 货币化?

本文介绍了 API 货币化和 APISIX 实现 API 货币化方法。 作者刘维&#xff0c;API7.ai 技术工程师&#xff0c;Apache APISIX Contributor 原文链接 什么是 API 货币化 想象你开发并部署了一个服务&#xff0c;能够搜集你所在城市所有超市的打折和优惠信息&#xff0c;其他的…

C生万物 | 校招热门考点 —— 结构体内存对齐

文章目录一、前言结构体偏移量计算&#xff1a;offsetof二、规则介绍例题的分解与细说三、习题演练1、练习①2、练习②四、为什么存在内存对齐?1、平台原因(移植原因)2、性能原因五、如何修改默认对齐数六、实战演练✍一道百度笔试题&#xff1a; offsetof 宏的实现&#x1f4…

深度学习基础篇之深度神经网络(DNN)

神经网络不应该看做是一个算法&#xff0c;应该看做是一个特征挖掘方法。在实际的业界发展过程中&#xff0c;数据的作用往往大于模型&#xff0c;当我们把数据的隐藏特征提取出来之后&#xff0c;用很简单的模型也能预测的很好。 神经网络模型由生物神经中得到启发。在生物神…

【Linux】Makefile的简述

目录 前言&#xff1a; 一、Makefile的规则 二、Makefile的函数语法 &#xff08;1&#xff09;通配符pattern ​&#xff08;2&#xff09; 删除clean ​&#xff08;3&#xff09; 立即变量、延时变量 &#xff08;4&#xff09; Makefile常用函数 3-1.Makefile要达到…

第11章_常用类和基础API

第11章_常用类和基础API 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 本章专题与脉络 1. 字符串相关类之不可变字符序列&#xff1a;String 1.1 String的特性 java.lang.String 类代表字符串…

vue之--使用TypeScript

搭配 TypeScript 使用 Vue​ 像 TypeScript 这样的类型系统可以在编译时通过静态分析检测出很多常见错误。这减少了生产环境中的运行时错误&#xff0c;也让我们在重构大型项目的时候更有信心。通过 IDE 中基于类型的自动补全&#xff0c;TypeScript 还改善了开发体验和效率。…

2023年美赛春季赛 Y题详细思路

由于今年各种各样的原因&#xff0c;导致美赛头一次&#xff0c;据说也将是最后一次&#xff0c;临时调整&#xff0c;加设春季赛。这对于急需建模奖项的大家来说是一个很好的机会。无论怎样的原因&#xff0c;今年美赛我们可能有所遗憾。但&#xff0c;春季赛也许就是弥补遗憾…

HTML4.1表单标签

input&#xff08;登录、注册、搜索功能&#xff09; type属性值类型称号展示类型text文本框placeholder占位符password密码框placeholder占位符radio单选框name checked&#xff08;默认选中&#xff09;同类型单选checkbox复选框 checked file 文件选择multiple多文件选择s…

分类预测 | MATLAB实现CNN-GRU-Attention多输入分类预测

分类预测 | MATLAB实现CNN-GRU-Attention多输入分类预测 目录分类预测 | MATLAB实现CNN-GRU-Attention多输入分类预测分类效果模型描述程序设计参考资料分类效果 模型描述 Matlab实现CNN-GRU-Attention多变量分类预测 1.data为数据集&#xff0c;格式为excel&#xff0c;12个输…