springboot3+vue3支付宝交易案例-结算支付

springboot3+vue3支付宝交易案例-结算支付!今天下午整理了一下结算的内容。遇到了很多问题。汇总分享给大家。

第一个问题:支付宝结算后,返回的交易编码,和交易时间,交易状态,都应该使用varchar来存。

第二个问题:它交易支付完成后,会自动返回购物车的页面地址。


package com.example.demo.controller;

import cn.hutool.json.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;


import com.alipay.api.internal.util.AlipaySignature;
import com.example.demo.config.AliPayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.example.demo.bean.Orders;
import com.example.demo.service.IOrdersService;
import com.example.demo.service.impl.OrdersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@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 IOrdersService ordersService;
    @Resource
    private AliPayConfig alipayConfig;

    /**
     * 向支付宝发送支付的接口。
     * @param orderNo
     * @param httpResponse
     * @throws IOException
     */
    @GetMapping("/pay")
    public void pay(Integer orderNo, HttpServletResponse httpResponse) throws IOException {
        //查询订单信息
        List<Orders> ordersList= ordersService.getOneOrdersByOrderNo(orderNo);
        Orders order = ordersList.get(0);
        if(order == null){
            return;
        }
        //private static final String GATEWAY_URL = "https://openapi.alipaydev.com/gateway.do";

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

        // 2. 创建 Request并设置Request参数
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();  // 发送请求的 Request类

        request.setNotifyUrl(alipayConfig.getNotifyUrl());//疑惑之一。
        JSONObject bizContent = new JSONObject();
        bizContent.set("out_trade_no", orderNo);  // 我们自己生成的订单编号
        bizContent.set("total_amount", order.getTotal()); // 订单的总金额
        bizContent.set("subject", order.getGoodsName());   // 支付的名称
        bizContent.set("product_code", "FAST_INSTANT_TRADE_PAY");  // 固定配置
        request.setBizContent(bizContent.toString());
        request.setReturnUrl("http://127.0.0.1:5173/cart_list");


        // 执行请求,拿到响应的结果,返回给浏览器
        String form = "";
        try {
            form = alipayClient.pageExecute(request).getBody(); // 调用SDK生成表单
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        //官方回传了一个页面,输入账户,密码,完成支付。
        httpResponse.setContentType("text/html;charset=" + CHARSET);
        httpResponse.getWriter().write(form);// 直接将完整的表单html输出到页面
        httpResponse.getWriter().flush();
        httpResponse.getWriter().close();
    }

    @PostMapping("/notify")  // 注意这里必须是POST接口
    public void 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 tradeNo = params.get("out_trade_no");//订单原始编码
            String gmtPayment = params.get("gmt_payment");//支付的时间
            String alipayTradeNo = params.get("trade_no");//支付交易的编码
            String status = params.get("trade_status");//交易状态
            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"));

                // 更新订单未已支付(更新数据库信息)
                //tradeNo, "已支付", gmtPayment, alipayTradeNo
                //查询订单信息
                Integer orderNo = Integer.valueOf(tradeNo);
                List<Orders> ordersList= ordersService.getOneOrdersByOrderNo(orderNo);
                Orders order = ordersList.get(0);
                order.setStatus(status);
                order.setAlipayNo(alipayTradeNo);
                order.setPayTime(gmtPayment);
                ordersService.updateOneOrders(order);
            }
        }

    }
}

这里面就是支付宝交易的控制器内容。里面有2个方法。一个是支付的,一个是回调的。


package com.example.demo.config;

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

这个是一个配置类,读取了我们的配置信息。


alipay.appId=9021000134634591
alipay.appPrivateKey=MIIEugIBADANBgkqhkiG9w0BAQEFAASCBKQwggSgAgEAAoIBAQCvWMRgjeKZdKnT8tT7nh1Yh6RiLhYCablc5a67CojvWRk5NrooIpP39oXkisV7H2nf5J8zfLmS2l2qroDlwAx4Zx3+Woloo6rcLZ42G0QuB8yBZm4doa73/lMurenmucSgCDaS+ap1opEGvlAFZnRi2O0KZy5t9g9WhwzC/D2EWJMSwroclfSTpVxr/on0MLw7l+jTeqcZTul4czXUhnGufWgVjmA7qAd3we7FhAMCqUcWXa3pLCCGIeSaBkqiaoToyql7eqYuwoV2UkT1DeqCN0fW/Zc5h7YpbuGTDfm2SSB/lfQAvHeV5Y+aNIOFJ1G25VKDnAIQgfQgrDYU3Eg1AgMBAAECgf99V/cJDmPtTngYCn41X9Gad1wK0ubo0qquvYEqM12vuwFM5NIt3onnt1H/DTQdz1bftY4YQBBn6bELUbLSiXZgm1XVfOK86kI5ImL2SodyYCDQX2hXxjxNCoBr3eZWCHWF8FkSt2YisRL6vxB0y8hm4KqRxTBranmMYP2+ZJGVCIyimxHAespfG47yPy42fk02DXf9StJpWqOTw5juCfUNDjDbgYLkk6B5gEmH9sj8jeG2OrNOxxjTLRnMgxxsRGV1goRQqAHD7wUAUYu1oFQCAMz3QAQeIv29OvXklRh9AxohridPImQxqzGOm9AnVB0US2GbnXYNBUEdrADn0+ECgYEA4SF+br+uTANdLANvHjP6uzG7UrOef6imUw0Yoepwzbc4pimxkH8p3lQZFpR9i06/7skIu/u7YAOgrcMVFcDQkmprqLDSXeML/YgQzocCqPg4cwYU6EDrMFrjAT7uBRXJFHaRdVNuEpTdtWWQMMdJe/WbNVxQMf2XBe8NM5AO3PkCgYEAx2PCm//PHkeuaEoOi0hcdCmKf67iA3uahyCl3+IzLO7bgEtpldLAlMiNMxNL+HiuxnGMUxmJXb5GkGeSNPjajMGmYY+pOx2h2SiJcMuHtMLjHwBmnEVWbMzWcD5huF//66jMI8NJN8eXZcfNxcjcD/BIEhlP6bi2vnCs1PInQB0CgYAZWR8WMyjZ0CsmcICLYwjhGNlhl23KK+AGS9wxJudqki2jr+AZR+gb61Yjz7ZPAB/mL+Z23AId7mqiBewS1fHl+muCw937yjuoYTCbQGJRShl5Af9KozyX5jPXCRHdqrVIQ41fK3SiTPalnPjeNSIV/fJq0KkK5+WgOmk/HAJAaQKBgBEat7kWKrhYQdfkcnb0UCoO3jix0eWmlsz8uf4Is4cpPl81GOunVqnswmAdSakZATU4zGbci/IkvnzoxZwRtP3aJuG7pzLRCe9NEO1CKHQTO9SO/j5tnEpdEBA06cEdSyD2K/ztZbyJPK2YhEhxQJ+FZ0lWLorIM7UGiW0DEObpAoGAUaWp+93D8VLYKzLlutCrZXmXw7gFfFXkmr5rd0ylFW7OqTtGPbvXwREpByyoKGyXZSIR9gnyYtjw4PQctKrXNvqqPevFEJ1I8EWm+sKsN9E8Sg7j0M9BhRaJ+9B4/OwDv9+G1N6WOjaia88RBx45s8lVb9l6Fjd5wsI2O5p/1Xw=
alipay.alipayPublicKey=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoBuX6xKYpLdexDoGc+jmfGGijjFnsv/0jvPmPydnt+bUgIWF8ghk2v3ddbY2C6toqdk1n367CyIF/swQl2gZFscWg83tvPHOho+fyHJ9ZANzJqQDeEXD2YVfrOGcTJQt0dnX6w5rfZerzsrD685C1OhAIttP5HKff2iplyvx1ZPaHEhghacYjD4ObFREXo6M1+pkKJJBo5mUmPQ6MBwWwkKqtIaQMMUnszO+o7GyVbVd7CttS/VDXwqTNay0pPlWyyBpH9rSl45XClGGHOFgpkN//CVNO7dBtskLOCKDZ++fGIBPKqU5vEkZXoGanlYBOKhrh38gALiR2CaENPdCIwIDAQAB
alipay.notifyUrl=http://8btgff.natappfree.cc/alipay/notify

这个就是配置参数文件内的配置参数信息。


如图,我们都是使用的字符串存储的。否则很容易报错。存不下。 


 

如图,使用沙箱测试账户(用户角色)jiuky可以支付完成了。


这个就是刚刚结算的订单信息。第一个是支付宝回传过来的交易编码。第二个是交易结算时间,第三个是交易结算状态。 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DMA+串口空闲中断实现RS485不定长数据接收和发送

目录 1、环境说明2、实现不定长数据接收需要做哪些事&#xff1f;2.1、数据的接收与缓存2.2、数据帧的结束判断2.3、数据帧的长度计算 3、RS485串口实现不定长数据发送4、代码实现结语&#xff1a; 1、环境说明 单片机型号;Cortex-M4架构&#xff0c;AT32F437 说明&#xff1a…

C语言操作符

文章目录 1:算术操作符2:移位操作符(移动的是二进制序列中的补码)2.1:知识补充(原码,反码,补码与二进制)2.2:左移操作符(<<)2.2:右移操作符(>>)2.2.1:逻辑右移2.2.2:算术右移 3:位操作符(运算用的是二进制位的补码)3.1:按位与操作符(&)3.2:按位或操作符(|)3.3:…

五大架构风格之一:数据流风格

数据流风格详细介绍 系统架构数据流风格是一种软件体系结构风格&#xff0c;它强调了系统内部不同部分之间的数据流动。这种风格侧重于描述系统中的数据处理过程&#xff0c;以及数据是如何从一个组件传递到另一个组件的。以下是系统架构数据流风格的详细介绍&#xff1a; 1 基…

width:100% 与 width:auto 的区别

width:100% 与 width:auto 的区别 一、当两者的子元素没有 border 或 padding 或 margin 的时候 先看一下示例代码和效果图 <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevi…

【数据结构 03】循环队列

一、原理 循环队列从功能角度具有队列的性质&#xff0c;即遵从先进先出原则&#xff0c;但是其存储方式是顺序存储。 循环队列的存储空间大小通常都是固定的&#xff0c;通过前指针和尾指针的移动控制循环队列数据的增删。 特征&#xff1a;顺序存储、先进先出、容量有限&a…

从前有条街 脚本 辅助 跳一跳

最近沉迷从前有条街。。。即将弃坑。 天工时间长的难以忍受。还好跳一跳能获得快乐水。找了一圈没有可用的脚本&#xff0c;于是自己写。。。 autojsx编写的 需要开启辅助功能跟悬浮窗 具体自行研究。 支持自动开始 无限续盘。目前只适配了1800*2400分辨率 。花了半个小时写的…

LeetCode —— 17. 电话号码的字母组合

&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️Take your time ! &#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️…

树和二叉树基础

树和二叉树基础 1.1树的概念 树是在数据结构中第一次接触到的非线性结构。 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它 叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&am…

Kotlin 协程:深入理解 ‘lifecycleScope‘

Kotlin 协程&#xff1a;深入理解 ‘lifecycleScope’ Kotlin 协程是一种强大的异步编程工具&#xff0c;它提供了一种简洁、易读的方式来处理并发和异步操作。在 Kotlin 协程库中&#xff0c;lifecycleScope 是一个关键的概念&#xff0c;它允许我们将协程的生命周期绑定到 An…

基于SSM的高校班级同学录网站设计与实现(有报告)。Javaee项目,ssm项目。

演示视频&#xff1a; 基于SSM的高校班级同学录网站设计与实现&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm项目。 项目介绍&#xff1a; Javaee项目&#xff0c;采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&…

【C++】构造函数和析构函数详解

目录 前言 类中的六个默认成员函数 构造函数 概念 特性 析构函数 概念 特性&#xff1a; 前言 类中的六个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编…

好用的IDEA插件,免费!

今天给大家推荐一款IDEA插件&#xff1a;Apipost-Helper-2.0&#xff0c;写完代码IDEA内一键生成API文档&#xff0c;无需安装、打开任何其他软件&#xff1b;写完代码IDEA内一键调试&#xff0c;无需安装、打开任何其他软件&#xff1b;生成API目录树&#xff0c;双击即可快速…

利用二分法及不动点迭代求解非线性方程(MatLab)

一、问题描述 利用二分法及不动点迭代求解非线性方程。 二、实验目的 掌握二分法及不动点迭代的算法原理&#xff1b;能分析两种方法的收敛性&#xff1b;能熟练编写代码实现利用二分法及不动点迭代来求解非线性方程。 三、实验内容及要求 二分法 (1) 编写代码计算下列数字…

1990-2021年各省绿色金融指数数据(含原始数据+测算结果)

1990-2021年全国各省绿色金融指数数据&#xff08;含原始数据结果&#xff09; 1、时间&#xff1a;1990-2021年 2、指标&#xff1a;地区、年份、该省环保项目信贷总额&#xff08;亿元&#xff09;、全省信贷总额&#xff08;亿元&#xff09;、绿色信贷、环境污染治理投资…

应用keras建立ANN模型.

介绍&#xff1a; Keras是一个开源的神经网络库&#xff0c;它基于Python语言&#xff0c;并能够在多个深度学习框架上运行&#xff0c;包括TensorFlow、Theano和CNTK。Keras提供了一种简洁而高层次的API&#xff0c;使得用户能够快速构建、训练和部署神经网络模型。 Keras的设…

【算法与数据结构】198、213、337LeetCode打家劫舍I, II, III

文章目录 一、198、打家劫舍二、213、打家劫舍 II三、337、打家劫舍III三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、198、打家劫舍 思路分析&#xff1a;打家劫舍是动态规划的的经典题目。本题的难点在于递归公式…

如何在Excel中清除单元格的格式?这里有详细步骤

Microsoft Excel提供了大量样式选项来自定义电子表格的外观。但是&#xff0c;如果你需要删除格式&#xff0c;则可以很容易地删除选定单元格和整个工作表的格式。我们将向你展示如何操作。 ​注意&#xff1a;清除格式只会删除文本的样式&#xff1b;将保留你的实际文本。 如…

Modern C++ std::get<n>(tuple)的原理

1. 前言 前面我们讲过std::tuple的实现原理&#xff0c;但没有讲如何取出数据&#xff0c;本节着重讲讲这点。本节与之前的blog有较大关联&#xff0c;如果您没看&#xff0c;这里有链接&#xff0c;链接已按由浅入深排好序&#xff0c;您可以按顺序阅读。如果时间少可以直接看…

安卓视图基础

目录 设置视图的宽高 设置视图的间隔 设置视图的对齐方式 设置视图的宽高 设置视图的间隔 设置视图的对齐方式 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"a…