feat(账户): 添加邮箱管理功能并重构账户仓库

- 创建 Email 值对象用于封装邮箱信息
- 扩展 AccountRepoInterface 添加邮箱管理方法
- 重命名 AccountBalanceRepo 为 AccountRepo 并实现邮箱功能
- 更新相关测试用例和配置以适配新功能
This commit is contained in:
李东云
2025-11-28 18:25:52 +08:00
parent 6bc423417c
commit cae728b392
11 changed files with 5617 additions and 18 deletions

View File

@@ -0,0 +1,83 @@
# 邮箱管理 SDK 生成计划(最终版本)
## 任务目标
根据 OpenAPI 规范,生成“获取用户常用邮箱”和“更新用户常用邮箱”接口的 SDK严格遵循 DDD 架构,不创建新的 Rpc 文件,创建独立的邮箱管理仓库或合理命名现有仓库。
## 分析与设计
### 1. 接口分析
从 OpenAPI 规范中,我找到了两个邮箱管理相关接口:
- **GET /rpc/v2/account/{uid}/inv-email**:获取用户常用邮箱
- **PUT /rpc/v2/account/{uid}/inv-email**:更新用户常用邮箱
### 2. 现有代码结构DDD 架构)
- **Domain 层**
- `AccountRepoInterface`:账户仓库接口
- `AccountBalance``PointsBalance`:账户相关聚合根和值对象
- `PointType``PointAction`:枚举类
- **Infrastructure 层**
- `AccountBalanceRepo`:实现了 `AccountRepoInterface`,但名称仅反映余额管理
- `AbstractRepo`:基础仓库类,封装了 HTTP 请求
### 3. 实现方案
#### 3.1 方案选择
考虑到用户反馈,我选择以下方案:
- **扩展 AccountRepoInterface**:添加邮箱管理方法
- **创建新的 AccountRepo 实现**:将 AccountBalanceRepo 重命名为 AccountRepo使其更通用
- **创建 Email 领域对象**:创建 Email 值对象封装邮箱信息
#### 3.2 具体设计
1. **创建 Email 领域对象**
- `Email`:值对象,封装邮箱信息
2. **扩展 AccountRepoInterface**
- `getEmail`:获取用户常用邮箱,返回 `Email` 对象
- `updateEmail`:更新用户常用邮箱,接收 `Email` 对象
3. **重命名并扩展 AccountBalanceRepo**
-`AccountBalanceRepo` 重命名为 `AccountRepo`
- 实现新添加的邮箱管理方法
- 保持原有余额管理功能不变
## 执行步骤
1. **创建 Email 领域对象**
-`Domain/Account/ValueObject` 目录下创建 `Email.php`
2. **扩展 AccountRepoInterface**
- 添加 `getEmail``updateEmail` 方法
3. **重命名并扩展 AccountBalanceRepo**
-`AccountBalanceRepo` 重命名为 `AccountRepo`
- 实现邮箱管理方法
4. **更新 ConfigProvider**
- 更新依赖注入配置,将 `AccountRepoInterface` 指向新的 `AccountRepo`
5. **编写测试用例**
- 验证邮箱管理功能
## 预期结果
- 完成邮箱管理相关接口的 SDK 实现
- 严格遵循 DDD 架构,不创建新的 Rpc 文件
- 仓库名称更合理,支持账户的多种操作(余额和邮箱)
- 创建了 Email 领域对象,封装邮箱信息
- 代码结构符合项目现有规范
- 包含必要的测试用例
## 技术细节
- 使用现有的 `AbstractRepo` 作为基础类
- 使用 `RequestService` 进行 HTTP 请求
- 遵循项目现有的代码风格和命名规范
- 使用 PHP 8.2 的特性(如 readonly 属性、命名参数)
- 保持与现有代码的一致性
## 命名调整说明
-`AccountBalanceRepo` 重命名为 `AccountRepo`,使其更通用,能够处理账户相关的多种操作,包括余额和邮箱管理
- 创建 `Email` 值对象,封装邮箱信息,符合 DDD 领域驱动设计原则

5399
openapi.json Normal file

File diff suppressed because one or more lines are too long

View File

@@ -14,7 +14,7 @@ use Singularity\HDK\Pay\Domain\Invoice\Repository\InvoiceRepoInterface;
use Singularity\HDK\Pay\Domain\Product\Repository\ExchangeRepoInterface;
use Singularity\HDK\Pay\Domain\Product\Repository\RechargeProductRepoInterface;
use Singularity\HDK\Pay\Domain\Transaction\Repository\OrderRepoInterface;
use Singularity\HDK\Pay\Infrastructure\Repository\AccountBalanceRepo;
use Singularity\HDK\Pay\Infrastructure\Repository\AccountRepo;
use Singularity\HDK\Pay\Infrastructure\Repository\FrequentAddressRepo;
use Singularity\HDK\Pay\Infrastructure\Repository\InvoiceProductRepo;
use Singularity\HDK\Pay\Infrastructure\Repository\InvoiceRepo;
@@ -40,7 +40,7 @@ class ConfigProvider
// Repo
// account
AccountRepoInterface::class => AccountBalanceRepo::class,
AccountRepoInterface::class => AccountRepo::class,
PointLogRepoInterface::class => PointLogRepo::class,
// product

View File

@@ -7,6 +7,7 @@
* Powered by PhpStorm
* Created on 2025/8/17
*/
declare(strict_types=1);
namespace Singularity\HDK\Pay\Domain\Account\Repository;
@@ -15,6 +16,7 @@ use Singularity\HDK\Pay\Application\Command\InitialAccountCmd;
use Singularity\HDK\Pay\Domain\Account\Aggregate\Account\AccountBalance;
use Singularity\HDK\Pay\Domain\Account\Aggregate\Account\PointsBalance;
use Singularity\HDK\Pay\Domain\Account\Enum\PointType;
use Singularity\HDK\Pay\Domain\Account\ValueObject\Email;
interface AccountRepoInterface
{
@@ -36,4 +38,21 @@ interface AccountRepoInterface
* @return void
*/
public function initial(InitialAccountCmd $cmd): void;
/**
* 获取用户常用邮箱
*
* @param string $uid
* @return Email
*/
public function getEmail(string $uid): Email;
/**
* 更新用户常用邮箱
*
* @param string $uid
* @param Email $email
* @return void
*/
public function updateEmail(string $uid, Email $email): void;
}

View File

@@ -0,0 +1,38 @@
<?php
/**
* Email.php@Pay
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2025/11/28
*/
declare(strict_types=1);
namespace Singularity\HDK\Pay\Domain\Account\ValueObject;
use Singularity\HDK\Pay\Domain\ValueObject;
final class Email extends ValueObject
{
private string $email;
public function __construct(string $email)
{
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new \InvalidArgumentException('Invalid email address: ' . $email);
}
$this->email = $email;
}
public function getValue(): string
{
return $this->email;
}
public function __toString(): string
{
return $this->email;
}
}

View File

@@ -7,6 +7,7 @@
* Powered by PhpStorm
* Created on 2025/8/12
*/
declare(strict_types=1);
namespace Singularity\HDK\Pay\Domain;

View File

@@ -1,12 +1,13 @@
<?php
/**
* AccountBalanceRpc.php@Pay
* AccountRepo.php@Pay
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2025/8/17
*/
declare(strict_types=1);
namespace Singularity\HDK\Pay\Infrastructure\Repository;
@@ -18,8 +19,9 @@ use Singularity\HDK\Pay\Domain\Account\Aggregate\Account\AccountBalance;
use Singularity\HDK\Pay\Domain\Account\Aggregate\Account\PointsBalance;
use Singularity\HDK\Pay\Domain\Account\Enum\PointType;
use Singularity\HDK\Pay\Domain\Account\Repository\AccountRepoInterface;
use Singularity\HDK\Pay\Domain\Account\ValueObject\Email;
final class AccountBalanceRepo extends AbstractRepo implements AccountRepoInterface
final class AccountRepo extends AbstractRepo implements AccountRepoInterface
{
public function getAccount(string $uid): AccountBalance
{
@@ -43,7 +45,7 @@ final class AccountBalanceRepo extends AbstractRepo implements AccountRepoInterf
cost: $pointBalance['cost'],
amount: $pointBalance['amount'],
version: $pointBalance['version'],
expiredAt: isset($pointBalance['expired_at']) ? new Carbon($pointBalance['expired_at']): null,
expiredAt: isset($pointBalance['expired_at']) ? new Carbon($pointBalance['expired_at']) : null,
),
array: $result['point_balance'],
),
@@ -65,7 +67,7 @@ final class AccountBalanceRepo extends AbstractRepo implements AccountRepoInterf
cost: $result['cost'],
amount: $result['amount'],
version: $result['version'],
expiredAt: isset($result['expired_at']) ? new Carbon($result['expired_at']): null,
expiredAt: isset($result['expired_at']) ? new Carbon($result['expired_at']) : null,
);
}
@@ -81,4 +83,26 @@ final class AccountBalanceRepo extends AbstractRepo implements AccountRepoInterf
data: $cmd->pointsBalances
);
}
public function getEmail(string $uid): Email
{
$response = $this->requestService->requestGet(
url: "/rpc/v2/account/$uid/inv-email"
);
$content = $response->getBody()->getContents();
$result = Json::decode($content);
return new Email($result['email']);
}
public function updateEmail(string $uid, Email $email): void
{
$this->requestService->requestPut(
url: "/rpc/v2/account/$uid/inv-email",
data: [
'email' => $email->getValue()
]
);
}
}

View File

@@ -12,7 +12,7 @@ use Carbon\Carbon;
use Singularity\HDK\Pay\Application\Command\InitialAccountCmd;
use Singularity\HDK\Pay\Domain\Account\Enum\PointType;
use Singularity\HDK\Pay\Infrastructure\Repository\AccountBalanceRepo;
use Singularity\HDK\Pay\Infrastructure\Repository\AccountRepo;
use function Hyperf\Support\make;
@@ -41,12 +41,12 @@ it('should initial account balance', function () {
type: PointType::from($point_balance['type']),
basic: $point_balance['basic'],
bonus: $point_balance['bonus'],
expiredAt:$point_balance['expired_at'],
expiredAt: $point_balance['expired_at'],
version: $point_balance['version'],
);
}
$repo = make(AccountBalanceRepo::class);
$repo = make(AccountRepo::class);
$repo->initial($cmd);
expect(true)->toBeTrue();

View File

@@ -9,13 +9,13 @@
*/
use Singularity\HDK\Pay\Domain\Account\Aggregate\Account\AccountBalance;
use Singularity\HDK\Pay\Infrastructure\Repository\AccountBalanceRepo;
use Singularity\HDK\Pay\Infrastructure\Repository\AccountRepo;
use function Hyperf\Support\make;
it('should be able to query account information', function () {
$uid = '123456';
$repo = make(AccountBalanceRepo::class);
$repo = make(AccountRepo::class);
$result = $repo->getAccount($uid);
expect($result)
->toBeInstanceOf(AccountBalance::class)

View File

@@ -0,0 +1,35 @@
<?php
/**
* QueryEmailTest.php@Pay
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2025/11/28
*/
use Singularity\HDK\Pay\Domain\Account\ValueObject\Email;
use Singularity\HDK\Pay\Infrastructure\Repository\AccountRepo;
use function Hyperf\Support\make;
it('should be able to get user email', function () {
$uid = '123456';
$repo = make(AccountRepo::class);
$result = $repo->getEmail($uid);
expect($result)
->toBeInstanceOf(Email::class);
});
it('should be able to update user email', function () {
$uid = '123456';
$newEmail = 'test@example.com';
$repo = make(AccountRepo::class);
$email = new Email($newEmail);
$repo->updateEmail($uid, $email);
// 验证更新后的邮箱
$result = $repo->getEmail($uid);
expect($result->getValue())->toBe($newEmail);
});

View File

@@ -10,13 +10,13 @@
use Singularity\HDK\Pay\Domain\Account\Aggregate\Account\PointsBalance;
use Singularity\HDK\Pay\Domain\Account\Enum\PointType;
use Singularity\HDK\Pay\Infrastructure\Repository\AccountBalanceRepo;
use Singularity\HDK\Pay\Infrastructure\Repository\AccountRepo;
use function Hyperf\Support\make;
it('should query point balance', function () {
$uid = 'cn3221';
$repo = make(AccountBalanceRepo::class);
$repo = make(AccountRepo::class);
$point_balance = $repo->getPointBalance($uid, PointType::EMA);
expect($point_balance)
->toBeInstanceOf(PointsBalance::class)