当前位置: 首页 > news >正文

springboot和vue项目中加入支付宝沙盒

首先要再application.yml配置id,密钥等

复制这个格式,按这个添加就行

alipay:
        appId:
        appPrivateKey://这里填应用私钥
        alipayPublicKey://这里填应用公钥
        notifyUrl:    //这里填你的回调地址
        returnUrl:  //这里填的是你再支付结束后会返回的地址

而要添加这些就需要你登陆支付宝开放平台,点击下面的链接跳转即可。

https://open.alipay.com/develop/sandbox/account

到这个界面后,再那个基本信息就可看到你的APPID了,然后填上去。

如果你是第一次登录这个公钥模式默认是关闭的,需要你点击打开,打开之后,点查看

就能看到你的公钥等东西了

然后就是再pom.xml中加上下面的依赖

<dependency>
      <groupId>com.alipay.sdk</groupId>
      <artifactId>alipay-sdk-java</artifactId>
      <version>4.22.110.ALL</version>
    </dependency>

    <dependency>
      <groupId>cn.hutool</groupId>
      <artifactId>hutool-all</artifactId>
      <version>5.7.20</version>
    </dependency>

再在你的项目中新建一个包命名位common,然后创建一个名为AliPayConfig的类

package cn.kmbeast.common;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "alipay")
public class AliPayConfig {
    private String appId;
    private String appPrivateKey;
    private String alipayPublicKey;
    private String notifyUrl;
    private String returnUrl;
    private String scenicNotifyUrl;

}

然后再在controller的包下新建一个名为AliPayController的类,里面的属性需要你在你的实体类下加两个属性。

package cn.kmbeast.controller;

import cn.hutool.json.JSONObject;
import cn.kmbeast.common.AliPayConfig;
import cn.kmbeast.mapper.HotelOrderInfoMapper;
import cn.kmbeast.mapper.ScenicTicketOrderMapper;
import cn.kmbeast.pojo.entity.HotelOrderInfo;
import cn.kmbeast.pojo.entity.ScenicTicketOrder;
import cn.kmbeast.pojo.vo.HotelOrderInfoVO;
import cn.kmbeast.pojo.vo.ScenicTicketOrderVO;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

// xjlugv6874@sandbox.com
// 9428521.24 - 30 = 9428491.24 + 30 = 9428521.24
@CrossOrigin(origins = "*")
@RestController
@RequestMapping("/alipay")
public class AliPayController {

    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";

    @Resource
    private AliPayConfig aliPayConfig;

    @Resource
    private HotelOrderInfoMapper hotelOrderInfoMapper;

    @Resource
    private ScenicTicketOrderMapper scenicTicketOrderMapper;

    @GetMapping("/hotelPay")
    public void hotelPay(@RequestParam("orderId") Integer orderId, HttpServletResponse response) throws Exception {

        System.out.println("进入 hotelPay 方法,orderId: " + orderId);
        // 1. 查询酒店订单信息
        HotelOrderInfo order = hotelOrderInfoMapper.selectById(orderId);
        if (order == null || order.getPayStatus()) {
            response.getWriter().write("订单不存在或已完成支付");
            return;
        }

        // 2. 创建Client,通用SDK提供的Client,负责调用支付宝的API
        AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL, aliPayConfig.getAppId(),
                aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);

        // 3. 创建 Request并设置Request参数
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();  // 发送请求的 Request类
        request.setNotifyUrl(aliPayConfig.getNotifyUrl());
        request.setReturnUrl(aliPayConfig.getReturnUrl());
        JSONObject bizContent = new JSONObject();
        bizContent.set("out_trade_no", order.getOutTradeNo()); //自己生成的10位订单号
        bizContent.set("total_amount", order.getAmount());//打折后的金额
        bizContent.set("subject", order.getRoomId());// 使用酒店订单ID
        bizContent.set("product_code", "FAST_INSTANT_TRADE_PAY");//固定配置
        request.setBizContent(bizContent.toString());

        // 执行请求,拿到响应的结果,返回给浏览器
        String form = "";
        try {
            form = alipayClient.pageExecute(request).getBody(); // 调用SDK生成表单
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        response.setContentType("text/html;charset=" + CHARSET);
        System.out.println("支付宝表单内容:" + form);
        response.getWriter().write(form);// 直接将完整的表单html输出到页面
        response.getWriter().flush();
        response.getWriter().close();
    }

    @PostMapping("/notify")  // 注意这里必须是POST接口
    public String payNotify(HttpServletRequest request) throws Exception {
        if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
            System.out.println("=========支付宝异步回调========");

            Map<String, String> params = new HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            for (String name : requestParams.keySet()) {
                params.put(name, request.getParameter(name));
                // System.out.println(name + " = " + request.getParameter(name));
            }

            String outTradeNo = params.get("out_trade_no");
            String gmtPayment = params.get("pay_time");
            String alipayTradeNo = params.get("trade_no");

            String sign = params.get("sign");
            String content = AlipaySignature.getSignCheckContentV1(params);
            boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign, aliPayConfig.getAlipayPublicKey(), "UTF-8"); // 验证签名
            // 支付宝验签
            if (checkSignature) {
                // 验签通过
                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"));

                Integer outTradeNos = Integer.parseInt(outTradeNo);
                HotelOrderInfoVO orders = hotelOrderInfoMapper.selectByall(outTradeNos);

                HotelOrderInfo order = new HotelOrderInfo();
                if (orders != null) {
                    order.setTradeNo(alipayTradeNo);//支付宝单号
                    order.setPayTime(LocalDateTime.now());//更新时间
                    order.setPayStatus(true);
                    order.setOutTradeNo(outTradeNo);
                    hotelOrderInfoMapper.updateAliPay(order);
                }
            }
        }
        return "success";
    }

}

之后就要改逻辑,我把我的逻辑展示一下。

HotelOrderInfoMapper
void updateAliPay(HotelOrderInfo hotelOrderInfo);

    HotelOrderInfoVO selectById(Integer id);

    HotelOrderInfoVO selectByall(Integer id);
<update id="updateAliPay">
        UPDATE hotel_order_info
        <set>
            <if test="payStatus != null">
                pay_status = #{payStatus},
            </if>
            <if test="payTime != null">
                pay_time = #{payTime},
            </if>
            <if test="tradeNo != null">
                tradeNo = #{tradeNo},
            </if>
        </set>
        WHERE out_trade_no = #{outTradeNo}
    </update>

<select id="selectById" resultMap="BaseResultMap">
        select * from hotel_order_info
        where id = #{Id}
    </select>

    <select id="selectByall" resultMap="BaseResultMap">
        select * from hotel_order_info
        where out_trade_no = #{Id}
    </select>

这样后端的逻辑就写好了,然后前端调用,这个就是调用的逻辑

代码

<el-table-column label="操作" width="110">
                        <template slot-scope="scope">
                            <span class="text-button" v-if="!scope.row.payStatus"
                                @click="handlePay(scope.row)">支付</span>
                            <span class="text-button" @click="handleDelete(scope.row)">删除</span>
                        </template>
                    </el-table-column>

// 处理支付的方法
        handlePay(row) {
			const orderId = row.id;
			   // 替换为后端完整的API地址
			    window.open(
			       `http://localhost:8088/api/online-travel-sys/v1.0/alipay/scenicPay?orderId=${orderId}`, 
			       "_blank"
			     );
			   this.$message.success("请求支付宝成功");
        },

因为用的是本地地址要进行回调的话就需要内网穿透,点击这个链接

https://natapp.cn/tunnel/lists

如果是第一次进入的话就需要先创建一个账号,然后购买隧道,用免费的就行

然后点击我的隧道点击配置,把红箭头指向的端口改为你的后端地址,然后点保存即可。。

然后点击下载

就会得到这么一个东西natapp.exe

然后你在新建一个文本是txt类型的,往里面加入下面的字,之后改为bat类型

natapp.exe -authtoken=//这里填你自己的

改好之后双击运行就行,这样你的本地地址就暴露在公网可以接受支付宝的回调了

后面就是结果展示

你就看到支付时间和支付状态还有支付宝交易号进行了更新

到此,支付宝沙盒功能就在项目中添加完成了。

在我的项目里面路由守卫会导致在点击后回到登录页面,这时你就需要把这个地址单独放行,

前端

后端

感谢你的浏览。

http://www.dtcms.com/a/20157.html

相关文章:

  • Pytest自动化测试框架关联/参数化实战
  • SQL Server 导入Excel数据
  • 基于单片机的常规肺活量SVC简单计算
  • LeetCode 热题 100
  • Synchronized 原理
  • DeepSeek R1完全本地部署实战教程01-课程大纲
  • 【Java 面试 八股文】Spring Cloud 篇
  • 鸿蒙中,UIAbility组件启动模式(3种分别是Singleton(单实例模式)Multiton(多实例模式)Specified(指定实例模式))
  • 如何学习Elasticsearch(ES):从入门到精通的完整指南
  • Java短信验证功能简单使用
  • vscode/cursor+godot C#中使用socketIO
  • SpringMVC新版本踩坑[已解决]
  • AUGUST的深度学习笔记(四,现代循环神经网络与注意力机制)
  • $符(前端)
  • 神经网络常见激活函数 9-CELU函数
  • CAS单点登录(第7版)10.多因素身份验证
  • 02.01、移除重复节点
  • Python关于类的一个坑点
  • 【Film Shot】Shot transition detection
  • Dify:修改环境变量并通过 Docker Compose 复用现有容器
  • 新建github操作
  • 【前端进阶】「全面优化前端开发流程」:利用规范化与自动化工具实现高效构建、部署与团队协作
  • Retrieval-Augmented Generation for LargeLanguage Models: A Survey
  • 用C语言解决逻辑推理问题:找出谋杀案凶手
  • C++游戏开发
  • 关于DispatchTime和DispatchWallTime
  • SQL sever数据导入导出实验
  • 【kafka系列】消费者
  • ubuntu /dev/ttyUSB1重命名为/dev/ttyUSB0。
  • CentOS 7.8 安装MongoDB 7教程