您现在的位置是:首页 >技术教程 >springboot实现支付宝支付(沙箱环境)网站首页技术教程

springboot实现支付宝支付(沙箱环境)

有多勉为其难 2024-10-09 00:01:02
简介springboot实现支付宝支付(沙箱环境)

1. 获取应用id,应用私钥和支付宝公钥

进入支付宝控制台:https://open.alipay.com/develop/manage

找到沙箱
在这里插入图片描述
在这里插入图片描述
这里可以看到应用id
在这里插入图片描述
可以看到应用私钥支付宝公钥,获取这三后就可以开始敲代码了

2. 开始开发

依赖:

        <!--支付宝-->
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>4.34.0.ALL</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

在resources/templates目录下创建一个pay.html文件,用于展示支付宝支付页面。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>支付宝支付</title>
</head>
<body onload="document.forms[0].submit();">
	<div th:utext="${form}"></div>
</body>
</html>

创建同步通知页面
在resources/templates目录下创建一个return.html文件,用于展示同步通知结果。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>支付结果</title>
</head>
<body>
	<h1 th:text="${message}"></h1>
</body>
</html>
# 支付宝支付参数配置
alipay:
  # 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
  appId: 111111111111111111
  # 应用私钥,您的PKCS8格式RSA2私钥
  privateKey: 11111111111111111
  # 支付宝公钥
  publicKey: 111111111111111111111111
  # 支付宝网关
  gatewayUrl: https://openapi.alipaydev.com/gateway.do
  # 服务器异步通知页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
  notifyUrl: http://花生壳地址:花生壳端口/api/alipay/notify
  # 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
  returnUrl: http://花生壳地址:花生壳端口/returnView.html
/**
 * @version 1.0.0
 * @date 2023/6/8
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PayRequest {

    /**
     * 订单编号
     */
    private String out_trade_no;

    /**
     * 商品名称
     */
    private String subject;

    /**
     * 支付金额
     */
    private BigDecimal total_amount;

    /**
     * 商品描述
     */
    private String body;

    /**
     * 电脑网站支付场景固定传值FAST_INSTANT_TRADE_PAY
     */
    private String product_code="FAST_INSTANT_TRADE_PAY";

    /**
     * PC扫码支付的方式
     */
    private String qr_pay_mode;

    /**
     * 支付渠道
     */
    private String enable_pay_channels/*="balance,pcredit,moneyFund,bankPay,creditCard,pcreditpayInstallment"*/;

    /**
     * 商户自定义二维码宽度。
     * 注:qr_pay_mode=4时该参数有效
     */
    private String qrcode_width;
}

/**
 * 支付配置类
 */
@Configuration
@ConfigurationProperties(prefix = "alipay")
@Data
public class PayAliConfig {

    /**
     * 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
     */
    public  String appId;
    
    /**
     * 应用私钥,您的PKCS8格式RSA2私钥
     */
    public String privateKey;

    /**
     * 支付宝公钥
     */
    public String publicKey;
    
    /**
     * 服务器异步通知页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
     */
    public  String notifyUrl;

    /**
     * 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
     */
    public  String returnUrl;

    /**
     * 支付宝网关
     */
    public String gatewayUrl;

}
/**
 * 初始化AlipayClient
 * @version 1.0.0
 * @date 2023/6/7
 */
@Component
public class AliPayClient {

    @Autowired
    private PayAliConfig payAliConfig;

    @Bean
    public AlipayClient AlipayClient()  throws AlipayApiException {
        AlipayConfig alipayConfig = new AlipayConfig();
        //设置网关地址
        alipayConfig.setServerUrl(payAliConfig.gatewayUrl);
        //设置应用ID
        alipayConfig.setAppId(payAliConfig.appId);
        //设置应用私钥
        alipayConfig.setPrivateKey(payAliConfig.privateKey);
        //设置请求格式,固定值json
        alipayConfig.setFormat(AlipayConstants.FORMAT_JSON);
        //设置字符集
        alipayConfig.setCharset(AlipayConstants.CHARSET_UTF8);
        //设置支付宝公钥
        alipayConfig.setAlipayPublicKey(payAliConfig.publicKey);
        //设置签名类型
        alipayConfig.setSignType(AlipayConstants.SIGN_TYPE_RSA2);
        //构造client
        AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
        return alipayClient;
    }
}
/**
 * @version 1.0.0
 * @date 2023/6/6
 */
@RestController
@RequestMapping("/api/alipay")
@Api(tags = "网站支付宝支付")
@Slf4j
public class AlipayController {
    @Autowired
    private AliPayService alipayService;

    /**
     * 创建支付订单,返回支付页面
     */
    @GetMapping("/pay")
    @Timing(remark = "创建支付订单")
    public ModelAndView pay(){

        String outTradeNo= IdUtil.simpleUUID();
        String subject="测试商品";
        BigDecimal totalAmount = BigDecimal.valueOf(250);

        PayRequest payRequest = new PayRequest();
        payRequest.setOut_trade_no(outTradeNo);
        payRequest.setSubject(subject);
        payRequest.setTotal_amount(totalAmount);
        payRequest.setBody("这是一个测试商品描述哦");
        payRequest.setQr_pay_mode("2");

        AlipayTradePagePayResponse response = alipayService.pay(payRequest);
        if (response == null) {
            return null;
        }
        log.info("响应:{}",response.getBody());
        // 返回支付页面
        ModelAndView modelAndView = new ModelAndView("pay");
        modelAndView.addObject("form", response.getBody());

        return modelAndView;
    }


    /**
     * 处理支付宝异步通知
     */
    @PostMapping("/notify")
    @Timing(remark = "处理支付宝异步通知")
    public void notify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        boolean signVerified = alipayService.rsaCheckV1(request);
        // 将请求参数转换为Map
        if (signVerified) {
            // 处理支付成功逻辑,更新订单状态等操作
            response.getWriter().write("success"); // 告诉支付宝已经收到通知并处理成功
        } else {
            response.getWriter().write("failure"); // 告诉支付宝验签失败
        }
    }
}
/**
 * @version 1.0.0
 * @date 2023/6/7
 */
public interface AliPayService {

    AlipayTradePagePayResponse pay(PayRequest payRequest);

    boolean rsaCheckV1(HttpServletRequest request);
}

/**
 * @version 1.0.0
 * @date 2023/6/7
 */
@Service
@Slf4j
public class AliPayServiceImpl implements AliPayService {

    @Autowired
    private AlipayClient alipayClient;

    @Autowired
    private PayAliConfig payAliConfig;

    @Override
    public AlipayTradePagePayResponse pay(PayRequest payRequest) {
        // 构造请求参数
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        request.setReturnUrl(payAliConfig.getReturnUrl());
        request.setNotifyUrl(payAliConfig.getNotifyUrl());
        log.info("生成的字符串:{}", JSONUtil.toJsonStr(payRequest));

        request.setBizContent(JSONUtil.toJsonStr(payRequest));
//        request.setBizContent("{"out_trade_no":"" + UUID.randomUUID().toString().replaceAll("-", "") + "","
//                + ""total_amount":"0.01","
//                + ""subject":"测试商品","
//                + ""body":"测试商品详情","
//                + ""product_code":"FAST_INSTANT_TRADE_PAY"}");

        // 调用SDK生成表单
        try {
            return alipayClient.pageExecute(request);
        } catch (AlipayApiException e) {
            log.error("支付宝请求失败");
        }
        return null;
    }

    @Override
    public boolean rsaCheckV1(HttpServletRequest request) {
        boolean flag = false;
        Map<String, String> params = new HashMap<>();
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String paramName = parameterNames.nextElement();
            String paramValue = request.getParameter(paramName);
            params.put(paramName, paramValue);
        }
        // 调用SDK验证签名
        try {
            flag =AlipaySignature.rsaCheckV1(params, payAliConfig.publicKey, AlipayConstants.CHARSET_UTF8, AlipayConstants.SIGN_TYPE_RSA2);
        } catch (AlipayApiException e) {
            log.error("验签失败");
        }
        return flag;
    }
}

3. 内网穿透

花生壳:https://hsk.oray.com/
下载安装配置一下就好了

4. 测试支付功能

启动Spring Boot应用,访问http://localhost:8889/api/alipay/pay,即可看到支付宝支付页面。输入支付密码后,会自动跳转到同步通知页面,并显示支付结果。

账号密码在沙箱账号中看到

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。