建议大家研究一下ABP预构建模块源代,了解它们是如何在应用中构建和使用的,因为这样你可以看到模块化开发的实现细节。
本节探讨的支付模块,是一个简单而又真实的案例,特别是当你的应用想要升级到高级帐户时,您可以使用它来接收付款。
这里不会展示该模块的开发步骤,只研究基本要点,以便您了解模块结构并构建自己的模块。
## 创建新应用模块
我们使用 ABP CLI 命令行工具创建新解决方案:
```
abp new Payment -t module
```
`-t module` 指定创建的是模块,模块名是`Payment`。打开解决方案,如下图所示:
![](https://img.kancloud.cn/be/65/be65ed86c0ed55f2dc22f268553aff0a_634x624.png)
启动模板有太多的项目,因为它支持多个UI和数据库选项,并且包含一些测试/演示项目,我们需要做筛选,删除不必要的项目:
我们把`src`文件夹中需要的项目留下来,然后删除以下项目:
* 删除了Blazor.\*的项目,因为采用的是MVC/Razor页面。
* 删除了与MongoDB相关的项目,因为这里使用的是EF Core模块。
* 最后,删除了angular文件夹,因为不希望这个模块有angular UI。
清理之后,解决方案中有12个项目。其中4个用于单元和集成测试,剩下8个主模块。
![](https://img.kancloud.cn/88/c9/88c97b0e0fe6f8c5902a8ab508a4dace_634x599.png)
这8个项目是类库项目,因此不能单独运行。它们需要由可执行应用程序使用,例如EventHub。
重新整理后的支付模块的结构和层次已在第9章DDD部分介绍过了,不再重复。
下面我们将进一步演化这种结构,因为我们希望为支付模块提供多个应用层。
## 重组支付模块解决方案
我们将把裁剪过的支付模块安装到EventHub解决方案中。我们回顾第4章,知道EventHub解决方案有两个UI应用程序:
![](https://img.kancloud.cn/0a/5f/0a5fcaea1df884c36359975db63e96ec_302x470.png)
* 主站:最终用户用于创建和参加活动的公共网站,这个应用程序有一个MVC/Razor页面UI。
* 后台:系统管理员使用的后台程序。是由Blazor WebAssembly构建。
为了支持相同的架构,我们将为支付模块提供两个UI应用层:
* 带有MVC/Razor Pages UI的应用层,由EventHub主站使用。最终用户将使用该UI付款。
* 带有Blazor WebAssembly UI的应用层,由EventHub管理后台使用。管理用户将通过该UI查看付款报告。
下图展示重组后的最终支付解决方案:
![](https://img.kancloud.cn/fe/6e/fe6ea2d4153276dfcd86d4eea70c5e24_426x473.png)
admin端,我添加了`Payment.Admin.Application`, `Payment.Admin.Application.Contracts`, `Payment.Admin.Blazor`, `Payment.Admin.HttpApi`, 和`Payment.Admin.HttpApi.Client`
我还加了`Payment.BackgroundServices` 项目定期进行一些后台定时作用。
总体结构:后台应用(Blazor UI)和公共主站应用(MVC/Razor UI)。这两个应用共享相同的领域层和数据库集成代码。
我们了解了支付解决方案的总体结构,下面将介绍付款流程的细节。
## 支付流程
支付模块的职责是向用户提供支付服务,它在内部使用PayPal作为支付网关。支付模块是通用的,可以被任何类型的应用程序使用。支付模块应该包括一些启动支付流程和处理支付结果的集成逻辑。
EventHub使用付款模块从用户处获得付款,付款后的用户将升级为高级用户。所以高级用户在应用中会拥有更多权限。
如果您是组织的所有者,并访问了组织详细信息页面,您将在页面上看到升级到高级按钮,如下图所示
![](https://img.kancloud.cn/41/be/41beee922630ae7ed2835331c3746c0e_620x468.png)
单击“升级到高级”按钮时,您将被重定向到定价页面:
![](https://img.kancloud.cn/67/e3/67e344727c9bbd7a374a257194e56301_619x462.png)
在这里,我们可以看到账户类型及其差异。单击此处的“升级到高级”按钮时,我们将被重定向到预结账页面,该页面由支付模块定义:
![](https://img.kancloud.cn/b8/11/b811e05164ab5dd72bc452dd605ac8c6_650x539.png)
预结账页面通常位于支付模块内部,并且开发为独立于应用的页面。我们可以使用`/Payment/PreCheckout?paymentRequestId=3a002186-cb04-eb46-7310-251e45fc6aed`URL将用户重定向到预签出页面
但是,我们应该首先使用IPaymentRequestAppService服务的CreateAsync方法获取支付请求ID。这在`EventHub.Web`项目的`Pages/Pricing.cshtml.cs`页面中完成。
EventHub应用覆写了视图(UI)部分,使其更好地适应EventHub的UI设计。
这是一个在最终应用中自定义模块的示例。EventHub应用在`Pages/Payment`文件夹下定义了`PreCheckout.cshtml` 和`PostCheckout.cshtml`,如下图所示:
![](https://img.kancloud.cn/46/ab/46ab625a289da922adf153f5f3d34182_384x523.png)
它们会自动覆盖相应的支付页面(因为它们完全位于支付模块定义的同一路径中)。这些页面没有`.cshtml.cs`文件,因为我们不想改变页面的逻辑行为,我们只是想改变一下界面展示。
下图显示了支付的主要组件和流程:
![](https://img.kancloud.cn/f7/88/f788a3b8e31ae495fa3125034dff9cc8_624x342.png)
* 一旦在付款界面我们点击升级按钮,它会跳转到支付模块的确认页面(Checkout),当我们点击确认按钮,我们将跳转到PayPal。
* 支付模块整合了支付系统,一旦我们在PayPal上完成付款,我们将被重定向回应用的结账后页面,该页面将向用户显示感谢信息。
* 当支付过程成功时,支付模块将发布一个分布式事件`PaymentRequestCompletedEto` (定义 在`Payment.Domain.Shared` 项目中)。
EventHub应用通过`PaymentRequestEventHandler` 类订阅上面的事件(定义在`EventHub.Domain`项目中),它会找到已完成付款的用户和组织,升级组织,并发送电子邮件感谢用户升级帐户。
* 在一些罕见的情况下,从PayPal返回时可能会出现错误,我们无法知道支付过程是否成功。对于这种情况,支付模块提供了一个回调,PayPal会调用该回调来通知我们支付操作的状态。回调请求由`PaymentRequestController`(在`Payment.HttpApi`项目中)处理。如果操作成功,将发布相同的`PaymentRequestCompletedEto`事件,以便EventHub应用可以异步升级组织帐户。
接下来,我们将介绍支付模块如何提供配置选项。
## 提供配置选项
支付模块使用PayPal,因此必须配置的PayPal帐户信息。它遵循选项模式(详情参阅第5章的实现选项模式),并提供`PayPalOptions`类,如以下示例所示:
```
Configure(options => {
options.ClientId = "...";
options.Secret = "...";
});
```
我们通常从配置文件(`appsettings.json`)中获取值。付款模块可以由`Payment:PayPal`键获取选项值,如下例所示:
```
"Payment":
{
"PayPal":
{
"ClientId": "...",
"Secret": "...",
"Environment": "Sandbox"
}
}
```
在`Payment.Domain`项目的`PaymentDomainModule`类中配置如下:
```
Configure<PayPalOptions>(configuration.GetSection("Payment:PayPal"));
```
默认,从配置中获取值是一种良好的做法。
我已经介绍了支付模块结构的要点。它的代码与典型的ABP应用没有太大区别。您可以下载源码,了解它的内部工作原理。
- 前言
- 第一部分
- 第1章 现代软件开发和 ABP 框架
- 企业级 Web 开发的挑战
- ABP框架的能力清单
- 第2章 ABP框架入门
- 安装 ABP CLI
- 创建新解决方案
- 运行解决方案
- 探索预构建模块
- 第3章 逐步开发开发ABP应用
- 创建解决方案
- 定义领域对象
- EFCore和数据库映射
- 定义应用服务
- 测试产品
- 产品列表
- 创建产品
- 编辑产品
- 删除产品
- 第4章 探索 EventHub解决方案
- 应用介绍
- 架构探索
- 方案运行
- 第二部分
- 第5章 探索ABP基础架构
- 了解模块化
- 使用依赖注入系统
- 配置应用程序
- 实现选项模式
- 日志系统
- 第6章 数据访问基础架构
- 定义实体
- 定义仓储库
- EF Core集成
- 了解 UoW
- 第7章 探索横切关注点
- 认证授权
- 用户验证
- 异常处理
- 第8章 体验 ABP 的功能和服务
- 获取当前用户
- 使用数据过滤
- 控制审计日志
- 缓存数据
- 本地化用户界面
- 第三部分
- 第9章 理解领域驱动设计
- 介绍 DDD
- 构建基于 DDD 的 解决方案
- 处理多个应用程序
- 了解执行流程
- DDD的通用原则
- 第10章 领域层 Domain
- 领域事件案例分析
- 聚合和实体的设计原则和实践
- 实现领域服务
- 落地存储库
- 构建规约(Specification)
- 领域事件
- 第11章 应用层 Application
- 落地应用服务
- 设计 DTO
- 理解各层的职责
- 第四部分
- 第12章 MVC/Razor 页面
- 主题系统
- 绑定和压缩
- 导航菜单
- Bootstrap标签助手
- 创建表单并验证
- 使用模态窗口
- 使用JS API
- 调用HTTP API
- 第13章 Blazor WebAssembly UI
- 什么是Blazor
- ABP Blazor UI
- 验证用户身份
- 理解主题系统
- 使用菜单
- 使用基本服务
- 使用UI服务
- 消费HTTP API
- 使用全局脚本和样式
- 第14章 HTTP API 和实时服务
- 构建HTTP API
- 使用HTTP API
- 使用SignalR
- 第五部分
- 第15章 落地模块化
- 理解模块化
- 构建支付模块
- 安装模块
- 第16章 实现多租户
- 理解多租户
- 多租户基础设施
- 使用功能系统
- 何时使用多租户
- 第17章 构建自动化测试
- 了解ABP测试基础设施
- 构建单元测试
- 构建集成测试