调用第三方接口——支付宝付款

沙箱环境是支付宝开放平台为开发者提供的用于接口开发及主要功能联调的模拟环境。

参考 登录 - 支付宝

在沙箱环境下,已经分配好了用于模拟测试的应用信息、商家信息、买家信息等

小程序文档 - 支付宝文档中心

内网穿透(支付宝付款需要在公网进行检查网站)

这里使用natapp内网穿透工具,参考 NATAPP-内网穿透 基于ngrok的国内高速内网映射工具

1.创建前端页面

订单列表页 order.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>订单列表</title>
    <style>
        tr{
            text-align: center;
        }
    </style>
</head>
<body>
    <table border="1px" width="700px" height="200px">
        <tr>
            <th>序号</th>
            <th>订单号</th>
            <th>订单名称</th>
            <th>订单金额</th>
            <th>下单时间</th>
            <td>操作</td>
        </tr>
        <tr>
            <td>1</td>
            <td>202312100001</td>
            <td>测试订单1</td>
            <td>¥1.0</td>
            <td>2023-12-10 10:30:21</td>
            <td>
                <a href="pay.html">去支付</a>
            </td>
        </tr>
        <tr>
            <td>2</td>
            <td>202312100002</td>
            <td>测试订单2</td>
            <td>¥1.0</td>
            <td>2023-12-10 10:30:21</td>
            <td>
                <a href="pay.html">去支付</a>
            </td>
        </tr>
        <tr>
            <td>3</td>
            <td>202312100003</td>
            <td>测试订单3</td>
            <td>¥1.0</td>
            <td>2023-12-10 10:30:21</td>
            <td>
                <a href="pay.html">去支付</a>
            </td>
        </tr>
    </table>
</body>
</html>

确认付款页 pay.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>确认付款</title>   
</head>
<body>
    <h2>确认付款</h2>
    <form id="payForm" method="post" action="http://localhost:8080/alipay/pay">
        <p>订单号:<input type="text" name="orderNo" value="202312100001"></p>
        <p>订单名称:<input type="text" name="subject" value="测试订单1"></p>
        <p>付款金额:<input type="text" name="totalAmount" value="1.0"></p>
        <p><input type="submit" value="付款"></p>
    </form>
</body>
</html>

后端界面:

引入相关的依赖:

processor是为了将配置类中的信息,一次性读取注入到属性中:

XML 复制代码
        <!--   支付宝     -->
        <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-configuration-processor</artifactId>
        </dependency>

application.yml

XML 复制代码
# 支付宝配置信息
alipay:
  appId: xxxxxxx
  appPrivateKey: xxxxxxx
  alipayPublicKey: xxxxxxx
  signType: RSA2
  charset: utf-8
  gatewayUrl: https://openapi-sandbox.dl.alipaydev.com/gateway.do
  notifyUrl: xxxxxxx
  returnUrl: http://127.0.0.1:5500/order.html

创建Alipay属性类:

java 复制代码
@Data
@Component
@ConfigurationProperties(prefix = "alipay")
public class AlipayProperties {

    // 应用id
    private String appId;

    // 应用私钥
    private String appPrivateKey;

    // 支付宝公钥
    private String alipayPublicKey;

    // 签名方式
    private String signType;

    // 字符编码
    private String charset;

    // 支付宝网关
    private String gatewayUrl;

    // 异步通知地址
    private String notifyUrl;

    // 同步跳转地址,即支付完成后跳转的地址
    private String returnUrl;
}

创建Alipay配置类

java 复制代码
@Configuration
public class AlipayConfig {

    @Resource
    private AlipayProperties alipayProperties;

    /**
     * 创建支付客户端
     */
    @Bean
    public AlipayClient alipayClient(){
        AlipayClient alipayClient = new DefaultAlipayClient(
                alipayProperties.getGatewayUrl(),
                alipayProperties.getAppId(),
                alipayProperties.getAppPrivateKey(),
                "json",
                alipayProperties.getCharset(),
                alipayProperties.getAlipayPublicKey(),
                alipayProperties.getSignType());
        return alipayClient;
    }

    /**
     * 创建支付请求对象
     */
    @Bean
    public AlipayTradePagePayRequest alipayTradePagePayRequest(){
        AlipayTradePagePayRequest payRequest = new AlipayTradePagePayRequest();
        payRequest.setNotifyUrl(alipayProperties.getNotifyUrl());
        payRequest.setReturnUrl(alipayProperties.getReturnUrl());
        return payRequest;
    }
}

创建Alipay控制类:

java 复制代码
package net.wanho.controller;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.wanho.properties.AlipayProperties;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

@RestController
@RequestMapping("/alipay")
@CrossOrigin
@Slf4j
public class AlipayController {
    @Resource
    private AlipayClient alipayClient;
    @Resource
    private AlipayTradePagePayRequest payRequest;
    @Resource
    private AlipayProperties alipayProperties;

    /**
     * 支付方法
     */
    @SneakyThrows
    @PostMapping("/pay")
    public void pay(String orderNo, String subject, Double totalAmount, HttpServletResponse response) {
        //封装业务参数
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", orderNo);//订单号
        bizContent.put("subject", subject); //订单名称
        bizContent.put("total_amount", totalAmount); //订单总金额
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY"); // 产品码,固定值
        bizContent.put("timeout_express", "15m"); //超时时间,15min
        payRequest.setBizContent(bizContent.toString());

        //向支付宝发起支付请求
        String result = alipayClient.pageExecute(payRequest).getBody();
        //将结果返回给前端,进入支付用户登录界面
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().print(result);
    }

    /**
     * 异步通知
     */
    @SneakyThrows
    @PostMapping("/notify")
    public String notify(@RequestParam Map<String, String> params) {
        System.out.println(params);
        /**
         * 进行验签操作,防止签名被窜改
         */
        boolean flag = AlipaySignature.rsaCheckV1(params, alipayProperties.getAlipayPublicKey(), alipayProperties.getCharset(), alipayProperties.getSignType());
        if (!flag) {
            log.info("验证签名失败!");
            return "fail";
        }
        /**
         * 判断返回的订单号、订单总金额是否与发送的一致,防止数据被篡改
         */
        String out_trade_no = params.get("out_trade_no");
        String total_amount = params.get("total_amount");

        /**
         * 判断支付宝返回的状态是否正常
         */
        String trade_status = params.get("trade_status");
        if (!trade_status.equals("TRADE_SUCCESS")) {
            log.info("交易失败!");
            return "fail";
        }

        /**
         * 更新相应的订单状态,例如将订单标记为已支付、更新库存等
         */
//        orderService.updateOrderStatus();
        return "success";
    }

}

实现效果:

相关推荐
灯澜忆梦7 分钟前
【面向对象编程C++】| 基础语法
java·c++·算法
一个风轻云淡16 分钟前
GCC 和 GDB命令简单解读
java·linux·前端
省钱兄--zs18 分钟前
西安24小时自助健身房解决方案实战:系统开发与部署全流程指南
java·spring boot·系统架构·intellij-idea·需求分析
资料库0140 分钟前
Linux 8个常见运维故障排查
java·linux·运维
要开心吖ZSH1 小时前
MySQL 慢 SQL 排查操作手册-个人笔记版
java·笔记·sql·mysql·慢查询
Joy T2 小时前
Spring AI 接入已有 Java 项目的三种架构设计
java·人工智能·springai·ai入门·chatclient·ai service·ai能力接入
杨运交2 小时前
[076][核心模块]构建优雅的Java异常处理框架:从错误码到全局异常处理
java·开发语言
caoerzhong2 小时前
仓库数字化成熟度分级:JeeWMS 开源 Java 仓库管理系统如何支撑从可见到自治的四级跃迁
java·开源
MayBaymax2 小时前
RocketMQ 存储机制
java·rocketmq
程序猿_极客3 小时前
【免费】分享一套优质的基于SpringBoot的服装商城管理系统的设计与实现(带可视化图表、协同过滤功能),源码+文档+视频详解(讲解)
java·spring boot·后端·服装商城管理系统