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

news2024/12/28 3:48:35

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

参考 登录 - 支付宝

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

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

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

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

1.创建前端页面

订单列表页 order.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

<!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是为了将配置类中的信息,一次性读取注入到属性中:

        <!--   支付宝     -->
        <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 

# 支付宝配置信息
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属性类:

@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配置类

@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控制类:

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

}

实现效果:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

谁能取代迈巴赫,征服互联网安全大佬周鸿祎?

‍作者 |老缅 编辑 |德新 4月18日&#xff0c;「周鸿祎卖车」登上了微博热搜。这位360创始人、董事长发微博称&#xff1a;自己做了一个艰难的决定&#xff0c;将把陪伴9年的迈巴赫600给卖掉。 随后&#xff0c;他解释道&#xff1a;「这是因为我需要体验新一代车的感觉。古人…

从零开始学RSA: [WUSTCTF2020]情书等5题

1 [WUSTCTF2020]情书 题目 Premise: Enumerate the alphabet by 0、1、2、..... 、25 Using the RSA system Encryption:0156 0821 1616 0041 0140 2130 1616 0793 Public Key:2537 and 13 Private Key:2537 and 937flag: wctf2020{Decryption}解题 前提&#xff1a;用0、…

C++初阶学习第五弹——类与对象(下)——类与对象的收官战

类与对象&#xff08;上&#xff09;&#xff1a;C初阶学习第三弹——类与对象&#xff08;上&#xff09;——初始类与对象-CSDN博客 类与对象&#xff08;中&#xff09;&#xff1a;C初阶学习第四弹——类与对象&#xff08;中&#xff09;——刨析类与对象的核心点-CSDN博…

Linux环境下的事件驱动力量:探索Libevent的高性能I/O架构

hello &#xff01;大家好呀&#xff01; 欢迎大家来到我的Linux高性能服务器编程系列之《Linux环境下的事件驱动力量&#xff1a;探索Libevent的高性能I/O架构》&#xff0c;在这篇文章中&#xff0c;你将会学习到Libevent的高性能I/O原理以及应用&#xff0c;并且我会给出源码…

攻防世界-xff-referer

题目信息 分析过程 显示ip必须为123.123.123.123&#xff0c;则进行伪造 解题过程 打开repeator 提示必须来自https://www.google.com&#xff0c;则再次构造Referer 相关知识 x-forwarded-for 和 referer的区别: x-forwarded-for 用来证明ip的像是“127.0.0.1”这种&a…

为什么感觉没有效果

以前在辅导小儿作业的时候&#xff0c;我会在常用的搜索引擎里去寻找答案&#xff0c;一般情况下都能解决问题。 但是最近一段时间&#xff0c;我发现&#xff0c;搜索引擎搜出来的结果还没有利用短视频搜出来的答案更全面&#xff0c;短视频软件不仅可以显示AI整理出来的答案…

“先锋”西凤

执笔 | 文 清 编辑 | 古利特 制曲是酿酒的第一道工序&#xff0c;也是中国酿酒史上的一大创新&#xff0c;对白酒风味的影响至关重要。西凤酿酒人坚信“曲是酒之骨”&#xff0c;“曲”的品质决定酒的“骨气”&#xff0c;“酒曲”是酒体形成主题风味的基本定型元素和催化剂…

5分钟学会掼蛋

一、基本规则 1、用牌&#xff1a;总计108张&#xff0c;每人发牌27张。 2、牌型&#xff1a;八炸弹、七炸弹、六炸弹、五炸弹、四炸弹、天王炸、同花顺、顺子、钢板、三同张、三带二、单牌、对牌、三连对&#xff0c;注意掼蛋没有三带一的牌型。3、牌型大小&#xff1a;天王炸…

跟TED演讲学英文:What moral decisions should driverless cars make by Iyad Rahwan

What moral decisions should driverless cars make? Link: https://www.ted.com/talks/iyad_rahwan_what_moral_decisions_should_driverless_cars_make Speaker: Iyad Rahwan Date: September 2016 文章目录 What moral decisions should driverless cars make?Introduct…

electron 通信总结

默认开启上下文隔离的情况下 渲染进程调用主进程方法&#xff1a; 主进程 在 main.js 中&#xff0c; 使用 ipcMain.handle&#xff0c;添加要处理的主进程方法 const { ipcMain } require("electron"); 在 electron 中创建 preload.ts 文件&#xff0c;从 ele…

LangChain框架学习总结

目录 一、简介 二、概念 三、组件具体介绍 3.1 Models 3.1.1 LLMs 3.1.2 Chat Models 3.1.3 Text Embedding Modesl 3.1.4 总结 3.2 Prompts 3.2.1 LLM Prompt Template 3.2.1.1 自定义PromptTemplate 3.2.1.2 partial PromptTemplate 3.2.1.3 序列化PromptTemplat…

Python使用割圆法求π值

三国时期刘徽提出的割圆法有多牛掰&#xff0c;看这个&#xff1a;刘徽割圆术到底做了什么&#xff1f; - 知乎 用Python实现的该算法代码如下&#xff1a; #!/usr/bin/env python """使用割圆法计算π值Usage::$ python calc_circle_pi.py 20 # 参数20是迭代…

【Kubernetes系统与CKA(D)考试经验】

文章目录 应用程序部署模式的发展历程传统部署模式虚拟化部署模式容器部署模式容器部署模式的好处容器部署的弊端 容器编排Kubernetes网址Kubernetes架构互联网架构体系云原生&#xff08;微服务容器化Devops不可变基础设施&#xff09;Kubernetes架构Kubernetes组件 Kubernete…

【Docker】★★★

docker 的网络模式 ●host模式&#xff1a;使用 --nethost 指定 容器与宿主机共享网络命名空间、ip和端口 ●container模式&#xff1a;使用 --netcontainer:NAME_or_ID 指定 新建的容器共享已有容器的网络命名空间、ip和端口 ●none模式&#xff1a;使用 --netnone 指定 不进行…

数据结构——链表专题2

文章目录 一、返回倒数第k 个节点二、链表的回文结构三、相交链表 一、返回倒数第k 个节点 原题链接&#xff1a;返回倒数第k 个节点 利用快慢指针的方法&#xff1a;先让fast走k步&#xff0c;然后fast和slow一起走&#xff0c;直到fast为空&#xff0c;最后slow指向的结点就…

如何利用现货黄金避险功能来交易?

黄金自古以来就是投资者青睐的具有规避风险功能的投资品种&#xff0c;现货黄金作为以黄金为投资标的物的品种&#xff0c;自然也具备了规避风险的功能。如果出现了风险事件&#xff0c;避险情绪会为现货黄金带来颇为可观的行情&#xff0c;所以我们需要懂得如何利用现货黄金的…

智能AI摄像头项目

项目概要 硬件说明&#xff1a;易百纳rv1126 38板&#xff0c;易百纳GC2053摄像头&#xff0c;拓展版&#xff08;自绘&#xff09;&#xff0c;屏幕驱动板&#xff08;自绘&#xff09;&#xff0c;3.1inch mipi屏&#xff0c;FT5316触摸屏 开发环境 硬件分析 开发环境及sd…

代码随想录训练营31day-动态规划4

一、完全背包&#xff08;参考博客&#xff09; 和01背包区别在于物品可以无限次放入背包。完全背包和01背包问题唯一不同的地方就是&#xff0c;每种物品有无限件。 因此在需要在遍历顺序上进行区别&#xff0c;参考代码随想录&#xff1a; 二、518.零钱兑换II 题目求的是组…

光端机(2)——光纤通信学习笔记九

学习笔记里面只关注基本原理和概念&#xff0c;复杂的公式和推导都没有涉及 光端机 光发射机 作用&#xff1a;实现电光转换。将来自电端机的电信号对光源发出的光波进行调制&#xff0c;然后将调制好的光信号耦合到光线中传输。 基本性能要求 1.合适的发光波长&#xff08;光…

FreeBSD RISCV 在QEME中实践-网络配置

在前一篇文章中&#xff0c;我们一起进行了FreeBSD RISCV 在QEME中实践 现在&#xff0c;让我们配置好网络吧&#xff01; 先上结论&#xff1a;用默认配置启动即可&#xff0c;网络就加载好了&#xff0c;只是不能ping罢了。因为不能ping&#xff0c;以为网络没通&#xff0…