SpringBoot实现支付宝沙箱支付的完整步骤

 更新时间:2024年04月02日 10:11:55   作者:知码开门  
沙箱支付是一种用于模拟真实支付环境的测试工具,它提供了一个安全的测试环境,供开发者在不影响真实交易的情况下进行支付功能的开发和测试,这篇文章给大家介绍了SpringBoot实现支付宝沙箱支付的完整步骤,需要的朋友可以参考下

1、进入支付宝开放平台

支付宝开发者平台开放平台

1.1 登录支付宝账号后下拉选择网页/移动应用开发

1.2 创建网页应用

1.3 创建成功后进入沙箱

沙箱比较不好找到 沙箱地址在这里:

登录 - 支付宝

欢迎登录支付宝,支付宝-全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验以及转账收款/水电煤缴费/信用卡还款等生活服务应用;为广大为从事电子商务的网站提供支付产品/支付服务的在线订购和技术支持等服务,帮助商家快速接入支付工具,高效、安全、快捷地开展电子商务。

登录 - 支付宝

1.4 点击启用公钥(有重要作用!springboot整合时会用到)

2、开始springboot与支付宝沙箱的整合

2.1导入支付宝api的依赖

 
       <!--引入支付宝支付 -->
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-easysdk</artifactId>
            <version>2.2.1</version>
        </dependency>
 
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>4.22.113.ALL</version>
        </dependency>

2.2 配置 application.yml 沙箱参数

#支付宝
alipay:
  appId: 
  appPrivateKey: 
  alipayPublicKey: 
  notifyUrl: 
  returnUrl: 

这五个参数都是什么意思呢?

appId: 沙箱中的应用id

appPrivateKey: 应用私钥

alipayPublicKey: 支付宝公钥

notifyUrl: 调用支付宝支付接口后产生的回调,需要内网穿透,后面详细讲,先不配置

returnUrl: 支付成功后的页面跳转,设置成你项目中的成功支付界面(可不填)

appPrivateKey: 应用私钥与 alipayPublicKey: 支付宝公钥在这里:点击查看

 
import com.alipay.api.DefaultAlipayClient;
 
/**
 * @method: $
 * @description: 
 * @date: $
 * @author: myth
 * @return $
 */
public class AliPayUtils {
 
    public static AlipayClient alipayClient;
 
    static {
        alipayClient =
                new DefaultAlipayClient(
                        "https://openapi-sandbox.dl.alipaydev.com/gateway.do",
                        "123123123",
                        "MIIEvgIBADANBgkq.......",
                        "json",
                        //UTF-8编码格式
                        "UTF-8",
                        "MIIBIjANBgkqhk......",
                        //RSA非对称加密
                        "RSA2");
    }
 
    public static AlipayClient getAlipayClient() {
        return alipayClient;
    }
}

2.3 在过滤器和拦截器中忽略掉alipay的系列端口

package com.gyp.studytour.common;
 
import com.gyp.studytour.common.JwtInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
 
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {
 
    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor())
                .addPathPatterns("/**").excludePathPatterns("/alipay/**");
        super.addInterceptors(registry);
    }
 
    @Bean
    public JwtInterceptor jwtInterceptor() {
        return new JwtInterceptor();
    }
 
}

2.4 新建AlipayController.java,定义了支付接口与支付回调接口:

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
 * @Author myth
 * @Date Created in  2024/4/23 15:23
 * @DESCRIPTION:
 * @Version V1.0
 */
@RestController
@RequestMapping("alipay")
@Transactional(rollbackFor = Exception.class)
public class AliPayController {
 
   @Resource
   AliPayConfig aliPayConfig;
 
   @Resource
   AddressBookMapper addressBookMapper;
 
   @Autowired
   OrderServiceImpl orderServiceImpl;
 
   private static final String GATEWAY_URL ="https://openapi-sandbox.dl.alipaydev.com/gateway.do";
   private static final String FORMAT ="JSON";
   private static final String CHARSET ="utf-8";
   private static final String SIGN_TYPE ="RSA2";
 
   @GetMapping("/pay") // 前端路径参数格式?subject=xxx&traceNo=xxx&totalAmount=xxx
   public void pay(AliPay aliPay, HttpServletResponse httpResponse) throws Exception {
      AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL, aliPayConfig.getAppId(),
              aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);
      AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
      request.setNotifyUrl(aliPayConfig.getNotifyUrl());
      request.setReturnUrl(aliPayConfig.getReturnUrl());
      request.setBizContent("{\"out_trade_no\":\"" + aliPay.getTraceNo() + "\","
              + "\"total_amount\":\"" + aliPay.getTotalAmount() + "\","
              + "\"subject\":\"" + aliPay.getSubject() + "\","
              + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
      String form = "";
      try {
         // 调用SDK生成表单
         form = alipayClient.pageExecute(request).getBody();
      } catch (AlipayApiException e) {
         e.printStackTrace();
      }
      httpResponse.setContentType("text/html;charset=" + CHARSET);
      // 直接将完整的表单html输出到页面
      httpResponse.getWriter().write(form);
      httpResponse.getWriter().flush();
      httpResponse.getWriter().close();
   }
 
   @PostMapping("/notify")  // 注意这里必须是POST接口
   public String payNotify(HttpServletRequest request) throws Exception {
      if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
         
 
         Map<String, String> params = new HashMap<>();
         Map<String, String[]> requestParams = request.getParameterMap();
         for (String name : requestParams.keySet()) {
            params.put(name, request.getParameter(name));
         }
 
         String tradeNo = params.get("out_trade_no");
         String gmtPayment = params.get("gmt_payment");
         String alipayTradeNo = params.get("trade_no");
         // 支付宝验签
         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"));
 
            // 更新订单已支付的逻辑代码
           
         }
      }
      return "success";
   }
 
}

前端页面调用

async function handleBuy(){ window.open('http://localhost:80/alipay/pay') }

2.5 编写AliPay.java  接收前端传来的参数

package com.songqiao.waimai.alipay.payparameter;
 
import lombok.Data;
 
/**
 * @Author myth
 * @Date Created in  2024/4/23 15:26
 * @DESCRIPTION: alipay接口参数
 * @Version V1.0
 */
@Data
public class AliPay {
   //订单编号
   private String traceNo;
   //商品金额
   private double totalAmount;
   //商品名称
   private String subject;
   //订单追踪号,商户自己生成,可已不使用
   private String alipayTraceNo;
}

在application.yml中还有一个重要的参数 notifyUrl 没有配置,这个参数是支付成功后支付宝的回调函数访问本地系统的路径,需要以内网穿透的方式让支付宝访问本地系统。

3、使用natapp进行内网穿透

3.1 进入natapp官网注册账号,并进行实名认证、与支付宝账号进行绑定。

NATAPP-内网穿透 基于ngrok的国内高速内网映射工具

natapp是基于ngrok的国内高速内网穿透专业服务商,独家彻底解决ngrok1.7内存泄漏问题.稳定拒绝掉线,适用于微信开发调试,本地架设演示服务器,外网可以访问,远程服务器,远程桌面,远程办公,游戏联机等

NATAPP-内网穿透 基于ngrok的国内高速内网映射工具

3.2 下载指定版本的natapp应用

我这里选用的是Windows 64位下载,下载并解压成功后的内容为:

3.2.1 运行natapp.exe

出现以下界面

3.2.2 配置natapp中的隧道

回到natapp官网,点击购买隧道->免费隧道->创建隧道并配置程序中的端口等信息

创建成功后点击我的隧道->点击配置->点击复制获取authtoken

3.2.3 启动自己本机的web服务

在natapp.exe启动后的命令行输入natapp -authtoken=刚刚复制的token,就会与本机的8080端口映射成功!

出现如图所示状态后,那么恭喜你!外网即可访问你的本机的8080端口,支付宝api支付成功后即可完成回调!

3.3 配置application.yml中notifyUrl参数

4、支付宝沙箱支付前端Vue代码

调用后端接口并拼接get请求的参数,完成

async goToPaySuccess(){
    //在这里我选择了window.open(url,'_self')形式,也就是不跳转新的页面,在本页面直接跳转
    window.open("http://127.0.0.1:8080/alipay/pay?subject="+"鱼头,"+this.note+"&traceNo="+Math.floor(Math.random() * 900000) + 100000+"&totalAmount="+this.goodsPrice,'_self')
 },

5、启动项目并测试功能

点击支付按钮后跳转支付界面,为了避免被当做违规图片,我把二维码遮盖了。

注意!大坑!此时要求你登录的支付宝账号密码是支付宝沙箱的账号密码!不要混淆! 

支付宝沙箱账号密码在沙箱中查看!

登录 - 支付宝

欢迎登录支付宝,支付宝-全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验以及转账收款/水电煤缴费/信用卡还款等生活服务应用;为广大为从事电子商务的网站提供支付产品/支付服务的在线订购和技术支持等服务,帮助商家快速接入支付工具,高效、安全、快捷地开展电子商务。

登录 - 支付宝

输入账号密码后即可进行付款

确认付款后会有两种结果:1.付款成功界面 2.付款成功后跳转到你指定的页面(在前面的application.yml的配置中设置) 如果没有配置就会展示成功界面,配置了就会在几秒后跳转到你配置的界面中去!

以上就是SpringBoot实现支付宝沙箱支付的完整步骤的详细内容,更多关于SpringBoot沙箱支付的资料请关注脚本之家其它相关文章!

相关文章

  • Java集合类之TreeSet的用法详解

    Java集合类之TreeSet的用法详解

    这篇文章主要为大家详细介绍了Java集合类中TreeSet的用法,文中的示例代码讲解详细,对我们学习Java有一定的帮助,感兴趣的可以了解一下
    2022-08-08
  • Java基础之重载(Overload)与重写(Override)详解

    Java基础之重载(Overload)与重写(Override)详解

    这篇文章主要介绍了Java基础之重载(Overload)与重写(Override)详解,文中有非常详细的代码示例,对正在学习java基础的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-04-04
  • MyBatis中resultType和parameterType和resultMap使用总结

    MyBatis中resultType和parameterType和resultMap使用总结

    这篇文章主要介绍了MyBatis中resultType和parameterType和resultMap使用总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • Fluent Mybatis实现环境隔离和租户隔离

    Fluent Mybatis实现环境隔离和租户隔离

    我们在实际的业务开发中,经常会碰到环境逻辑隔离和租户数据逻辑隔离的问题。本文就详细的来介绍一下,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • Java实现LeetCode(报数)

    Java实现LeetCode(报数)

    这篇文章主要介绍了Java实现LeetCode(报数),本文通过使用java实现leetcode的报数题目和实现思路分析,需要的朋友可以参考下
    2021-06-06
  • Spring Cloud 配置中心内容加密的配置方法

    Spring Cloud 配置中心内容加密的配置方法

    这篇文章主要介绍了Spring Cloud 配置中心内容加密的配置方法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-06-06
  • jmeter中json提取器如何提取多个参数值

    jmeter中json提取器如何提取多个参数值

    关于jmeter中的正则表达式及json提取器可以提取响应值,但是实际可以需要上个接口的多个响应值,本文就详细的介绍一下如何使用,感兴趣的可以了解一下
    2021-11-11
  • 流式图表拒绝增删改查之kafka核心消费逻辑上篇

    流式图表拒绝增删改查之kafka核心消费逻辑上篇

    这篇文章主要为大家介绍了流式图表拒绝增删改查之kafka核心消费逻辑详解的上篇,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • java去除中文括号小括号,或者英文括号的实例代码

    java去除中文括号小括号,或者英文括号的实例代码

    这篇文章主要介绍了java去除中文括号小括号,或者英文括号的实例代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • Java简单实现猜数字游戏附C语言版本

    Java简单实现猜数字游戏附C语言版本

    猜数字是兴起于英国的益智类小游戏,起源于20世纪中期,一般由两个人或多人玩,也可以由一个人和电脑玩。游戏规则为一方出数字,一方猜,今天我们来用Java和C语言分别把这个小游戏写出来练练手
    2021-11-11

最新评论