在 Spring Boot 中实现 Callback 回调的常用方法

Spring Boot 中实现 Callback(回调) 通常用于处理外部系统调用你的服务接口。例如,当一个第三方服务完成某项操作后通知你的应用完成结果。以下是实现回调的完整流程:

1. 回调的基本流程

  1. 注册回调地址
    • 第三方服务需要知道你的回调 URL,你需要向第三方注册一个 URL。
    • 例如:https://yourdomain.com/callback.
  2. 实现回调接口
    • 创建一个控制器处理第三方服务的回调请求。
    • 通常是 POSTGET 方法。
  3. 验证请求(可选):
    • 验证请求的合法性,确保回调确实来自第三方服务。
    • 可以使用签名验证、白名单 IP、Token 等方法。
  4. 处理回调数据
    • 接收并解析回调数据。
    • 根据业务逻辑更新系统状态。
  5. 返回响应
    • 返回第三方服务指定的响应,通常是 200 OK 或其他业务约定的格式。

2. 示例代码

2.1 创建回调接口

假设第三方服务会通过 POST 请求回调数据到 /callback,并发送如下 JSON 数据:

{
  "orderId": "123456",
  "status": "COMPLETED",
  "signature": "abcdef123456"
}

实现代码如下:

import org.springframework.web.bind.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;

@RestController
@RequestMapping("/callback")
public class CallbackController {

    private static final Logger logger = LoggerFactory.getLogger(CallbackController.class);

    @PostMapping
    public String handleCallback(@RequestBody Map<String, Object> payload) {
        // 日志打印回调数据
        logger.info("Received callback: {}", payload);

        // 提取回调参数
        String orderId = (String) payload.get("orderId");
        String status = (String) payload.get("status");
        String signature = (String) payload.get("signature");

        // 验证签名 (示例,可替换为实际验证逻辑)
        if (!isValidSignature(payload, signature)) {
            logger.warn("Invalid signature for callback with orderId: {}", orderId);
            return "Invalid signature";
        }

        // 处理业务逻辑
        if ("COMPLETED".equals(status)) {
            logger.info("Order {} completed successfully!", orderId);
            // 更新订单状态,执行其他逻辑
        }

        // 返回响应
        return "Callback received successfully!";
    }

    private boolean isValidSignature(Map<String, Object> payload, String signature) {
        // 模拟签名验证逻辑,可替换为真实的验证算法
        String expectedSignature = "abcdef123456"; // 示例签名
        return expectedSignature.equals(signature);
    }
}

2.2 注册回调 URL

向第三方服务提供回调地址,例如:

https://yourdomain.com/callback

2.3 配置 Web 应用

确保你的 Spring Boot 应用可以接收到外部请求:

  1. 配置 application.ymlapplication.properties 中的服务器端口和上下文路径:
server:
  port: 8080

如果应用部署在防火墙后,确保端口 8080 可访问,或者通过 Nginx 反向代理将流量引导到 /callback

3. 验证回调请求

为了安全性,回调接口通常需要验证请求来源的合法性。常见验证方法:

3.1 签名验证

  • 第三方服务发送回调请求时,会包含一个签名字段。
  • 你可以通过回调数据和预共享的密钥生成签名,并与回调请求中的签名对比。

示例签名生成:

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class SignatureUtils {

    public static String generateSignature(String data, String secretKey) throws NoSuchAlgorithmException {
        String input = data + secretKey;
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8));
        StringBuilder hexString = new StringBuilder();
        for (byte b : hash) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString();
    }
}

3.2 IP 白名单

  • 检查回调请求的来源 IP 是否在允许范围内:
@RequestHeader("X-Forwarded-For") String ipAddress

通过拦截器或过滤器限制允许的 IP。

4. 返回第三方约定的响应

根据第三方的需求,返回特定的响应格式。例如:

  • 如果回调成功,需要返回:json复制代码
{ "status": "success", "message": "OK" }

修改代码如下:

@PostMapping
public Map<String, String> handleCallback(@RequestBody Map<String, Object> payload) {
    // 处理逻辑
    Map<String, String> response = new HashMap<>();
    response.put("status", "success");
    response.put("message", "OK");
    return response;
}

5. 测试回调接口

5.1 使用 Postman

  1. 打开 Postman,创建一个新的 POST 请求。
  2. 设置 URL 为 http://localhost:8080/callback
  3. 在 Body 中选择 raw,内容类型为 JSON,输入测试数据:
{
  "orderId": "123456",
  "status": "COMPLETED",
  "signature": "abcdef123456"
}

4. 点击发送,检查接口是否返回预期响应。

5.2 使用模拟工具

  • 如果第三方未提供实际回调,可以使用工具(如 BeeceptorNgrok)模拟回调请求。

6. 总结

  • 回调接口的核心是接收外部服务的数据并处理。
  • 安全性是实现回调接口的关键,推荐使用签名验证、IP 白名单等方法保护接口。
  • 测试时确保网络配置正确,验证接口能够正常接收和处理回调请求。

发布者:myrgd,转载请注明出处:https://www.object-c.cn/4512

Like (0)
Previous 2024年11月24日 下午9:55
Next 2024年11月24日 下午10:09

相关推荐

  • 多方面的优化包括启动时间、React Native 速度提升 550% 运行时性能以及渲染效率的提升

    React Native 速度提升 550% 可能涉及多方面的优化,包括启动时间、运行时性能以及渲染效率的提升。这通常是通过框架改进、代码优化和工程实践的结合来实现的。以下是实现 React Native 性能大幅提升的一些关键方法和策略: 1. 启动时间优化 1.1 减少 JS Bundle 大小 1.2 预加载资源 1.3 使用优化的原生模块 2. 渲染…

    2024年12月7日
    00
  • 在使用 VS Code 和 Keil 协同开发 STM32 程序

    在使用 VS Code 和 Keil 协同开发 STM32 程序时,可以利用 Keil 强大的编译器 和 VS Code 的高效代码编辑功能,结合起来提高开发效率。以下是实现协同开发的详细步骤: 前置准备安装 Keil确保已安装 Keil MDK-ARM,并配置好开发环境。Keil 下载地址:Keil 官方网站安装 VS Code下载并安装最新版本的 VS …

    2024年12月1日
    00
  • 使用 CLion 编写 C51 (即8051微控制器) 程序时,遇到 sbit 相关报错

    在使用 CLion 编写 C51 (即8051微控制器) 程序时,遇到 sbit 相关报错,通常是因为 CLion 默认并不支持8051的特殊语法和寄存器定义方式。sbit 是 C51 编译器中的一个关键字,用来将一个单独的位(bit)映射到特定的硬件寄存器或端口引脚。常见的报错及解决方法sbit 语法问题: CLion 本身不支持 C51 特有的语法,sb…

    2024年11月27日
    00
  • Java 8 到 Java 17 的升级涉及一些关键变化

    JDK 8 升级到 JDK 17 指南Java 8 到 Java 17 的升级涉及一些关键变化,包括语言特性、API 更新和性能改进。以下是一些升级要点:语法和语言特性:记录类(Record Class):Java 14 引入了记录类,提供了一种简化创建不可变数据对象的方式。密封类(Sealed Classes):Java 15 引入了密封类,允许开发者限制…

    2024年11月27日
    00
  • 使用 Python Selenium 控制 Chrome 浏览器 进行自动化操作

    使用 Python Selenium 控制 Chrome 浏览器 进行自动化操作是 Web 自动化测试和爬虫的常用方法之一。以下是一个完整的入门教程,包括如何安装、配置以及一些示例代码。 1. 安装所需环境 1.1 安装 Selenium 使用 pip 安装 Selenium: 1.2 下载 ChromeDriver 1.3 配置 ChromeDriver …

    2024年11月25日
    00
  • Java Spring MVC 超详解介绍

    Spring MVC 是 Spring 框架中用于构建 Web 应用程序的模块,它采用了 MVC 模式(Model-View-Controller)。Spring MVC 的核心目标是将业务逻辑、数据层、以及展示层分离,使得代码清晰易维护。 Spring MVC 的架构 1. 核心组件 Spring MVC 工作流程 Spring MVC 核心注解 1. @…

    2024年11月21日
    00
  • 在 .NET 环境下,使用 OpenTK 为 SkiaSharp 提供 OpenGL 支持是一个常见的方式

    在 .NET 环境下,使用 OpenTK 为 SkiaSharp 提供 OpenGL 支持是一个常见的方式,可以高效地进行 2D 图形渲染。下面是具体如何实现和一些关键概念的介绍: 背景知识 实现步骤 1. 添加必要的 NuGet 包 确保你的项目安装了以下 NuGet 包: 2. 创建 OpenGL 上下文 使用 OpenTK 创建一个 OpenGL 上下…

    2024年12月8日
    00
  • 在 Go 语言中,对文件的基础操作介绍

    在 Go 语言中,文件操作是基础技能之一,主要通过 os、io 和 io/ioutil 等标准库完成。以下是对文件操作的全面介绍,帮助你在 Go 语言的“成神之路”上迈出关键一步! 1. 创建文件使用 os.Create 创建文件,如果文件已存在会被清空。示例代码 2. 打开文件使用 os.Open 打开文件(只读模式),使用 os.OpenFile 可以指…

    2024年12月2日
    00
  • 在使用 uni-app 开发小程序或移动端应用时 title image失效问题

    在使用 uni-app 开发小程序或移动端应用时,若发现 分享的标题(title) 和 图片(image) 配置无效,可能是由于配置错误、平台限制或代码逻辑问题。以下是排查和解决问题的详细指南: 1. 确保正确使用分享 API onShareAppMessage(自定义转发) 确保在 pages 的页面代码中正确使用了 onShareAppMessage 方…

    2024年11月25日
    00
  • C++ STL vector 类:动态数组的高效应用

    vector 是 C++ 标准库(STL)中最常用的容器之一,它提供了一个动态数组的实现,能够根据需要自动扩展或收缩。vector 是一个线性数据结构,具有高效的随机访问能力和动态扩展能力,广泛应用于需要频繁增删元素且对随机访问要求较高的场景。 1. vector 类简介 vector 是 C++ 标准模板库(STL)中提供的一种容器类,它类似于动态数组(d…

    2024年11月25日
    00
  • 使用 Redis 和 Spring Cache 实现基于注解的缓存功能

    Spring Cache 提供了一种简单的方法来通过注解对方法的返回结果进行缓存。结合 Redis,可以构建一个高效的分布式缓存解决方案。以下是详细实现步骤: 1. 引入必要的依赖在 pom.xml 文件中添加以下依赖(适用于 Spring Boot 项目): 2. 配置 Redis在 application.yml 或 application.proper…

    2024年12月1日
    00
  • 实现微信支付提现api接口教程

    微信支付的提现功能,通常是通过调用 企业付款到零钱 API 或 企业付款到银行卡 API 来实现的。以下是如何使用微信支付提现 API 的详细教程,包括其前置条件、接口调用以及注意事项。 1. 准备工作 1.1. 开通微信支付商户号 1.2. 配置证书 将这些文件保存在你的服务器上,用于发起 HTTPS 请求。 1.3. 获取 API 密钥 2. 企业付款到…

    2024年11月24日
    00
  • pywebview 页面请求数据总是报错:TypeError: Cannot read properties of undefined (reading ‘api’)

    pywebview 中的 TypeError: Cannot read properties of undefined (reading ‘api’) 错误通常意味着 JavaScript 代码试图访问一个未定义的对象或属性(如 api)。这种问题通常出现在 Python 与前端 JavaScript 交互时,可能是由于以下原因:可能的原因及解决方法:Jav…

    2024年11月27日
    00
  • Python 的 json模块序列化数据从文件里读取出来或存入文件

    Python 的 json 模块用于处理 JSON 格式的数据,可以将 JSON 数据与 Python 数据结构之间相互转换。以下是具体用法,包括从文件读取 JSON 数据以及将数据写入文件: 1. 将 JSON 数据从文件中读取到 Python 数据结构 代码示例: 解析过程: 2. 将 Python 数据结构写入到文件中(序列化为 JSON) 代码示例:…

    2024年11月26日
    00
  • C语言中的操作符(Operators)对数据进行运算的符号

    C语言中的操作符(Operators)是对数据进行运算的符号,分为多种类型,支持从基本算术到复杂的逻辑操作。以下是C语言操作符的详解: 1. 算术操作符(Arithmetic Operators) 用于执行基本数学运算: 示例: 2. 关系操作符(Relational Operators) 用于比较两个值,结果为布尔值: 示例: 3. 逻辑操作符(Logic…

    2024年11月22日
    00

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

在线咨询: QQ交谈

邮件:723923060@qq.com

关注微信