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

在 Spring Boot 中使用适配器模式实现支付网关的统一接口

引言

在许多电子商务系统中,集成多个支付网关是常见的需求。不同的支付网关有着不同的接口和实现细节。适配器模式可以帮助我们以一种灵活的方式实现这些不同的支付网关接口。

适配器模式简介

适配器模式将一个类的接口转换为客户期望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

示例

假设我们有一个电商平台,需要支持多种支付网关,包括:

  1. PayPal支付网关
  2. Stripe支付网关
  3. Alipay支付网关
步骤
  1. 定义目标接口 - 首先定义一个目标接口,声明所有支持的支付网关共有的方法。

     java 

    深色版本

    1public interface PaymentGateway {
    2    void processPayment(PaymentRequest request);
    3}
  2. 实现具体的支付网关类 - 接下来,为每种支付网关实现适配器。

    • PayPal支付网关适配器

       java 

      深色版本

      1import org.springframework.stereotype.Component;
      2
      3@Component
      4public class PayPalPaymentGatewayAdapter implements PaymentGateway {
      5    private final PayPalApi paypalApi;
      6
      7    public PayPalPaymentGatewayAdapter(PayPalApi paypalApi) {
      8        this.paypalApi = paypalApi;
      9    }
      10
      11    @Override
      12    public void processPayment(PaymentRequest request) {
      13        PayPalPaymentRequest paypalRequest = new PayPalPaymentRequest(request);
      14        paypalApi.processPayment(paypalRequest);
      15    }
      16}
    • Stripe支付网关适配器

       java 

      深色版本

      1import org.springframework.stereotype.Component;
      2
      3@Component
      4public class StripePaymentGatewayAdapter implements PaymentGateway {
      5    private final StripeApi stripeApi;
      6
      7    public StripePaymentGatewayAdapter(StripeApi stripeApi) {
      8        this.stripeApi = stripeApi;
      9    }
      10
      11    @Override
      12    public void processPayment(PaymentRequest request) {
      13        StripePaymentRequest stripeRequest = new StripePaymentRequest(request);
      14        stripeApi.processPayment(stripeRequest);
      15    }
      16}
    • Alipay支付网关适配器

       java 

      深色版本

      1import org.springframework.stereotype.Component;
      2
      3@Component
      4public class AlipayPaymentGatewayAdapter implements PaymentGateway {
      5    private final AlipayApi alipayApi;
      6
      7    public AlipayPaymentGatewayAdapter(AlipayApi alipayApi) {
      8        this.alipayApi = alipayApi;
      9    }
      10
      11    @Override
      12    public void processPayment(PaymentRequest request) {
      13        AlipayPaymentRequest alipayRequest = new AlipayPaymentRequest(request);
      14        alipayApi.processPayment(alipayRequest);
      15    }
      16}
  3. 定义具体的支付网关 API 接口 - 为每个支付网关定义一个具体的 API 接口。

    • PayPal API 接口

       java 

      深色版本

      1public interface PayPalApi {
      2    void processPayment(PayPalPaymentRequest request);
      3}
    • Stripe API 接口

       java 

      深色版本

      1public interface StripeApi {
      2    void processPayment(StripePaymentRequest request);
      3}
    • Alipay API 接口

       java 

      深色版本

      1public interface AlipayApi {
      2    void processPayment(AlipayPaymentRequest request);
      3}
  4. 实现具体的支付网关 API 类 - 接下来,为每个支付网关实现具体的 API 类。

    • PayPal API 类

       java 

      深色版本

      1import org.springframework.stereotype.Component;
      2
      3@Component
      4public class PayPalApiImpl implements PayPalApi {
      5    @Override
      6    public void processPayment(PayPalPaymentRequest request) {
      7        System.out.println("Processing payment via PayPal: " + request.getAmount());
      8    }
      9}
    • Stripe API 类

       java 

      深色版本

      1import org.springframework.stereotype.Component;
      2
      3@Component
      4public class StripeApiImpl implements StripeApi {
      5    @Override
      6    public void processPayment(StripePaymentRequest request) {
      7        System.out.println("Processing payment via Stripe: " + request.getAmount());
      8    }
      9}
    • Alipay API 类

       java 

      深色版本

      1import org.springframework.stereotype.Component;
      2
      3@Component
      4public class AlipayApiImpl implements AlipayApi {
      5    @Override
      6    public void processPayment(AlipayPaymentRequest request) {
      7        System.out.println("Processing payment via Alipay: " + request.getAmount());
      8    }
      9}
  5. 定义支付请求类 - 定义一个支付请求类,用于封装支付请求的必要信息。

     java 

    深色版本

    1public class PaymentRequest {
    2    private String paymentMethod;
    3    private double amount;
    4
    5    public PaymentRequest(String paymentMethod, double amount) {
    6        this.paymentMethod = paymentMethod;
    7        this.amount = amount;
    8    }
    9
    10    public String getPaymentMethod() {
    11        return paymentMethod;
    12    }
    13
    14    public double getAmount() {
    15        return amount;
    16    }
    17}
  6. 定义具体的支付请求类 - 为每个支付网关定义一个具体的支付请求类。

    • PayPal支付请求

       java 

      深色版本

      1public class PayPalPaymentRequest {
      2    private final PaymentRequest request;
      3
      4    public PayPalPaymentRequest(PaymentRequest request) {
      5        this.request = request;
      6    }
      7
      8    public String getPaymentMethod() {
      9        return request.getPaymentMethod();
      10    }
      11
      12    public double getAmount() {
      13        return request.getAmount();
      14    }
      15}
    • Stripe支付请求

       java 

      深色版本

      1public class StripePaymentRequest {
      2    private final PaymentRequest request;
      3
      4    public StripePaymentRequest(PaymentRequest request) {
      5        this.request = request;
      6    }
      7
      8    public String getPaymentMethod() {
      9        return request.getPaymentMethod();
      10    }
      11
      12    public double getAmount() {
      13        return request.getAmount();
      14    }
      15}
    • Alipay支付请求

       java 

      深色版本

      1public class AlipayPaymentRequest {
      2    private final PaymentRequest request;
      3
      4    public AlipayPaymentRequest(PaymentRequest request) {
      5        this.request = request;
      6    }
      7
      8    public String getPaymentMethod() {
      9        return request.getPaymentMethod();
      10    }
      11
      12    public double getAmount() {
      13        return request.getAmount();
      14    }
      15}
  7. 使用适配器 - 最后,在我们的业务逻辑中,根据需要选择并使用相应的适配器。

     java 

    深色版本

    1import org.springframework.beans.factory.annotation.Autowired;
    2import org.springframework.stereotype.Service;
    3
    4@Service
    5public class PaymentService {
    6
    7    private final Map<String, PaymentGateway> paymentGateways;
    8
    9    @Autowired
    10    public PaymentService(Map<String, PaymentGateway> paymentGateways) {
    11        this.paymentGateways = paymentGateways;
    12    }
    13
    14    public void processPayment(PaymentRequest request) {
    15        PaymentGateway paymentGateway = paymentGateways.get(request.getPaymentMethod());
    16        if (paymentGateway != null) {
    17            paymentGateway.processPayment(request);
    18        } else {
    19            throw new IllegalArgumentException("Unsupported payment method: " + request.getPaymentMethod());
    20        }
    21    }
    22}
  8. 控制器 - 我们还需要一个控制器来测试这个逻辑。

     java 

    深色版本

    1import org.springframework.beans.factory.annotation.Autowired;
    2import org.springframework.web.bind.annotation.GetMapping;
    3import org.springframework.web.bind.annotation.RequestMapping;
    4import org.springframework.web.bind.annotation.RequestParam;
    5import org.springframework.web.bind.annotation.RestController;
    6
    7@RestController
    8@RequestMapping("/payments")
    9public class PaymentController {
    10
    11    private final PaymentService paymentService;
    12
    13    @Autowired
    14    public PaymentController(PaymentService paymentService) {
    15        this.paymentService = paymentService;
    16    }
    17
    18    @GetMapping("/process")
    19    public String processPayment(@RequestParam("method") String method,
    20                                 @RequestParam("amount") double amount) {
    21        PaymentRequest request = new PaymentRequest(method, amount);
    22        paymentService.processPayment(request);
    23        return "Payment processed successfully.";
    24    }
    25}
  9. 测试 - 最后,我们可以通过发送 HTTP 请求来测试不同的支付网关。

     bash 

    深色版本

    1curl 'http://localhost:8080/payments/process?method=paypal&amount=100'
    2curl 'http://localhost:8080/payments/process?method=stripe&amount=150'
    3curl 'http://localhost:8080/payments/process?method=alipay&amount=200'
结论

通过使用适配器模式,我们可以在运行时灵活地选择不同的支付网关,并使用统一的接口与之交互。这种方式不仅提高了代码的可读性和可维护性,还使得扩展新的支付网关变得非常简单。在 Spring Boot 中,依赖注入机制进一步简化了适配器模式的实现过程。

相关文章:

在 Spring Boot 中使用适配器模式实现支付网关的统一接口

引言 在许多电子商务系统中&#xff0c;集成多个支付网关是常见的需求。不同的支付网关有着不同的接口和实现细节。适配器模式可以帮助我们以一种灵活的方式实现这些不同的支付网关接口。 适配器模式简介 适配器模式将一个类的接口转换为客户期望的另一个接口。适配器模式使…...

【书生·浦语大模型实战营】第三期 入门岛作业

入门岛作业 Linux闯关任务&#xff1a;完成 SSH 连接与端口映射并运行 hello_world.py。配置vscode作业内容 可选任务1&#xff1a;将Linux基础命令在开发机上完成一遍作业内容 可选任务 2&#xff1a;使用 VSCODE 远程连接开发机并创建一个conda环境作业内容 可选任务 3&#…...

Redis的String类型常用命令总结

1. set 设置一个键的值。 set key value示例&#xff1a; set username "alice"2. get 获取一个键的值。 get key示例&#xff1a; get username3. getset 设置键的值&#xff0c;并返回键的旧值。 getset key value示例&#xff1a; getset username "…...

河南萌新联赛2024第(四)场:河南理工大学

A 思路&#xff1a; B 思路&#xff1a;有一种贪心的写法&#xff0c;将整个数组排序以后比较两个相邻数的同或值&#xff0c;取 m a x max max&#xff0c;不会证明 int th(int x, int y, int z) {int res 0;for (int i z - 1; i > 0; i --) {int dx (x >> i &…...

Linux中临时使用账号提权进行业务操作

普通账号提权 su&#xff1a;永久提权 Switching users with su sudo&#xff1a;临时提权 Running commands as root with sudo 1&#xff09;su切换账号 需要对方的密码 示例&#xff1a;切换到超级管理员 su - root 建议用-这个 su root 普通用户需要执行特殊指令&…...

lwip 3. 网线拔掉后 lwip_recvfrom不能返回

当网线被拔掉后&#xff0c;‌LWIP的lwip_recvfrom函数无法返回&#xff0c;‌这通常意味着网络连接已经断开&#xff0c;‌而LWIP没有自动检测到这种断开并进行相应的处理。具体卡在这个地方&#xff1a; ret xQueueReceive(mbox->mbx, &(*msg), portMAX_DELAY); //具…...

Linux环境安装Docker Engine

Docker是一个开源的应用容器引擎&#xff0c;由Go语言开发&#xff0c;基于Linux内核技术。Docker通过将应用及其依赖打包到可移植的容器中&#xff0c;实现了应用的快速部署和高效管理。Docker容器具有轻量级、快速启动、可移植性强等特点&#xff0c;能够显著提升资源利用率和…...

大厂面试题分享

大厂面试题分享 Redis持久化方式AOF优缺点RDB优缺点 如何保证Redis和Myql的一致性索引下推输入url到浏览器发生了什么ReentranLock底层原理SpringBoot 的启动流程 Redis持久化方式 Redis提供了两种主要的持久化机制&#xff0c;分别是AOF&#xff08;Append-Only File&#xf…...

FPGA面试问题整理

1. 逻辑设计中竞争与冒险概念&#xff0c;如何识别和消除&#xff1f; 竞争&#xff1a;在组合逻辑电路中&#xff0c;信号经过多条路径到达输出端&#xff0c;每条路径经过的逻辑门不同存在时差&#xff0c;在信号变化的瞬间存在先后顺序。这种现象叫竞争。 冒险&#xff1a;由…...

3Done学习笔记

一、基本操作 1、旋转视角 使用左下角立方体选择&#xff1b; 右键可以拖动视角&#xff1b; 中间滑轮按住拖动整个舞台界面。 2、平移和旋转 右键选择移动&#xff0c;有两种方式。 第一种选择起始点&#xff0c;按照起始点位置移动到终止点&#xff08;边、角、中心点…...

AI学习指南深度学习篇-卷积层详解

AI学习指南深度学习篇-卷积层详解 一、引言 随着人工智能技术的不断发展&#xff0c;深度学习作为人工智能领域的热门分支之一&#xff0c;正在逐渐成为各个领域的核心技术。而在深度学习中&#xff0c;卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN…...

2024年TI杯E题-三子棋游戏装置方案分享-jdk123团队-第二弹 手搓机械臂

第一弹赛题的选择与前期方案的准备 opencv调用摄像头bug的解决 机械臂的组装 采用三个舵机&#xff0c;组成一个三自由度的机械臂。 并且利用电磁吸盘的方式&#xff0c;完成对棋子的抓取工作&#xff0c;后面的事实证明&#xff0c;在预算不足的情况下&#xff0c;队友手搓…...

如何在Java、C、Ruby语言中使用Newscatcher API

Newscatcher 世界实时新闻聚合API 一款强大的数据服务工具&#xff0c;它通过先进的网络爬虫技术&#xff0c;实时从全球超过70,000个新闻源聚合新闻内容。这个API能够提供全面、多角度的新闻报道&#xff0c;包括但不限于标题、作者、发布日期、全文内容以及媒体资源链接。它使…...

集合: Collection的成员方法和相关实现类

Collection: - List(有序【指的是存储和取出的顺序是一致的】且可以发生重复&#xff0c;且有索引的概念) - ArrayList&#xff1a; 底层数据结构是数组&#xff0c;查询快&#xff0c;增删慢&#xff0c;线程不安全的&#xff0c;效率高。 - …...

过滤器与监听器:深入了解 Java Web 开发中的核心概念

在 Java Web 开发中&#xff0c;过滤器&#xff08;Filter&#xff09;和监听器&#xff08;Listener&#xff09;是两个重要的组件&#xff0c;它们帮助开发者在请求处理的各个阶段进行预处理和后处理。这篇博客将深入探讨这两个概念&#xff0c;并展示它们如何在实际应用中发…...

【Linux学习】动静态库从原理到制作

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;Linux从入门到进阶 欢迎大家点赞收藏评论&#x1f60a; 目录 &#x1f351;动静态库&#x1f41f;动静态库的制作与使用&#x1f680;生成静态库&#x1f512;生成动态库 &#x1f98c;动态库的查…...

WPF篇(10)-Label标签+TextBlock文字块+TextBox文本框+RichTextBox富文本框

Label标签 Label控件继承于ContentControl控件&#xff0c;它是一个文本标签&#xff0c;如果您想修改它的标签内容&#xff0c;请设置Content属性。我们曾提过ContentControl的Content属性是object类型&#xff0c;意味着Label的Content也是可以设置为任意的引用类型的。 案…...

JavaFX对话框控件-ChoiceDialog

JavaFX对话框控件-ChoiceDialog 常用属性titlecontentTextinitOwnergraphicheaderTextdefaultValuechoicesdialogPane 常用事件显示事件setOnShowing显示事件setOnShown弹框按钮点击 综合案例自定义下拉框内容 与Alert大部分功能类似按钮不可以自定义多一个下拉框 常用属性 …...

一文了解BTC中的二层协议中Nervos network,CKB,RGB++,UTXO stack 之间的关系

注&#xff1a;该内容不构成投资建议&#xff0c;有些内容摘抄其他地方&#xff0c;如侵权&#xff0c;请联系删除。 Nervos network Nervos Network 是一个开源的区块链生态项目&#xff0c;该项目提供一套解决方案来应对区块链扩展性和互操作性的问题。 Nervos Network 成立…...

Oracle(47)如何创建和使用集合?

在PL/SQL中&#xff0c;集合&#xff08;Collection&#xff09;是一种复合数据类型&#xff0c;用于存储一组相关的数据项。集合主要有三种类型&#xff1a;关联数组&#xff08;Associative Arrays&#xff09;、嵌套表&#xff08;Nested Tables&#xff09;和可变数组&…...

SpringIOC和SpringAOC

lombok插件 XML<!-- 加载资源文件 --><context:property-placeholder location"classpath:jdbc.properties"></context:property-placeholder><!-- 注入数据源 --><bean id"dataSource" class"com.mchange.v2.c3p0.ComboP…...

static关键字详解

文章目录 static使用示例static底层原理静态初始化顺序静态与线程安全 static static是Java中的一个关键字&#xff0c;用于定义类级别的成员&#xff0c;类级别的成员是指那些属于整个类&#xff0c;而不是特定对象实例的成员。在Java中&#xff0c;类级别的成员包括静态变量…...

使用 Java RestClient 与 Elasticsearch 进行索引管理的示例

文章目录 准备工作测试连接创建索引查询索引是否存在删除索引总结 在这篇博客中&#xff0c;我将和大家分享如何使用 Java RestClient 与 Elasticsearch 进行简单的索引管理操作。如果你在开发过程中需要对海量数据进行高效搜索和分析&#xff0c;Elasticsearch 可能是个不错的…...

编程-设计模式 10:外观模式

设计模式 10&#xff1a;外观模式 定义与目的 定义&#xff1a;外观模式&#xff08;Facade Pattern&#xff09;提供了一个统一的接口&#xff0c;用来访问子系统中的一群接口。它定义了一个高层接口&#xff0c;让子系统更容易使用。目的&#xff1a;简化复杂的子系统的使用…...

非范型ArrayList和泛型List<T>

ArrayList 是 C# 中的一个非泛型集合类&#xff0c;它属于 System.Collections 命名空间。它提供了动态数组的功能&#xff0c;允许你在运行时添加、删除和访问元素。然而&#xff0c;需要注意的是&#xff0c;ArrayList 并不是类型安全的&#xff0c;因为你可以向其中添加任何…...

魔众文库系统v7.0.0版本推荐店铺功能,管理菜单逻辑优化

推荐店铺功能&#xff0c;管理菜单逻辑优化 [新功能] RandomImageProvider 逻辑升级重构&#xff0c;支持更丰富的随机图片生成 [新功能] 资源篮订单参数字段 [新功能] 首页推荐店铺功能&#xff0c;需要在后台 文库系统 → 文库店铺 开启推荐 [系统优化] Grid 快捷编辑请求…...

03、流程控制语句

01、位运算符 一、位运算符:是针对二进制数据(补码)的运算。(0看成false&#xff0c;1看成true) &:按位与——求出两个数字对应的二进制&#xff0c;有0则0 | :按位或——求出两个数字对应的二进制&#xff0c;有1则1 ^ :按位异或 ——求出两个数字对应的二进制&#xff0c…...

[Android] [解决]Bottom Navigation Views Activity工程带来的fragment底部遮盖的问题

创建了Bottom Navigation Views Activity之后&#xff0c;在fragment_home.xml&#xff0c;加了一个RecyclerView&#xff0c; 后来添加了item之后发现底部会被盖住一部分。 解决&#xff1a;在layout里面加两句&#xff1a; android:paddingBottom"?attr/actionBarSize&…...

Armv8/Armv9架构中的原子性

B2.2 Arm 架构中的原子性 原子性是内存访问的一个特性,描述为原子访问。Arm 架构描述涉及两种类型的原子性:单次复制原子性和多次复制原子性。在 Arm 架构中,内存访问的原子性要求取决于内存类型,以及访问是显式的还是隐式的。有关更多信息,请参见: 单次复制原子性的要求…...

读零信任网络:在不可信网络中构建安全系统15协议和过滤

1. 协议 1.1. IKE/IPSec 1.1.1. 因特网密钥交换协议&#xff08;Internet Key Exchange,IKE&#xff09;用于执行IPSec认证和密钥交换 1.1.1.1. 通常以后台守护进程的方式实现&#xff0c;使用预共享密钥或X.509证书来认证对端并创建一个安全会话 1.1.2. IKEv1与IKEv2 1.1.2.1…...