更新统一使用 PHPDoc + PSR-19 标准注释

This commit is contained in:
技术老胡
2026-04-21 08:38:59 +08:00
parent dcd58e24ce
commit 9a16a88640
252 changed files with 9218 additions and 659 deletions

View File

@@ -8,9 +8,22 @@ use app\service\account\ledger\MerchantAccountLedgerService;
/**
* 商户门户余额服务。
*
* 负责余额快照、可提现余额和资金流水页面的数据拼装。
*
* @property MerchantPortalSupportService $supportService 支持服务
* @property MerchantAccountService $merchantAccountService 商户账户服务
* @property MerchantAccountLedgerService $merchantAccountLedgerService 商户账户流水服务
*/
class MerchantPortalBalanceService extends BaseService
{
/**
* 构造方法。
*
* @param MerchantPortalSupportService $supportService 支持服务
* @param MerchantAccountService $merchantAccountService 商户账户服务
* @param MerchantAccountLedgerService $merchantAccountLedgerService 商户账户流水服务
*/
public function __construct(
protected MerchantPortalSupportService $supportService,
protected MerchantAccountService $merchantAccountService,
@@ -18,13 +31,19 @@ class MerchantPortalBalanceService extends BaseService
) {
}
/**
* 查询商户门户可提现余额。
*
* @param int $merchantId 商户ID
* @return array 余额摘要
*/
public function withdrawableBalance(int $merchantId): array
{
$merchant = $this->supportService->merchantSummary($merchantId);
$snapshot = $this->merchantAccountService->getBalanceSnapshot($merchantId);
$snapshot['available_balance_text'] = $this->supportService->formatAmount((int) ($snapshot['available_balance'] ?? 0));
$snapshot['frozen_balance_text'] = $this->supportService->formatAmount((int) ($snapshot['frozen_balance'] ?? 0));
$snapshot['available_balance_text'] = $this->formatAmount((int) ($snapshot['available_balance'] ?? 0));
$snapshot['frozen_balance_text'] = $this->formatAmount((int) ($snapshot['frozen_balance'] ?? 0));
$snapshot['withdrawable_balance_text'] = $snapshot['available_balance_text'];
return [
@@ -33,6 +52,15 @@ class MerchantPortalBalanceService extends BaseService
];
}
/**
* 查询商户门户资金流水。
*
* @param array $filters 筛选条件
* @param int $merchantId 商户ID
* @param int $page 页码
* @param int $pageSize 每页条数
* @return array 流水列表数据
*/
public function balanceFlows(array $filters, int $merchantId, int $page, int $pageSize): array
{
$filters['merchant_id'] = $merchantId;
@@ -48,3 +76,5 @@ class MerchantPortalBalanceService extends BaseService
];
}
}

View File

@@ -11,9 +11,18 @@ use app\repository\payment\config\PaymentChannelRepository;
* 商户门户通道查询服务。
*
* 负责商户通道列表查询和通道行格式化。
*
* @property MerchantPortalSupportService $supportService 支持服务
* @property PaymentChannelRepository $paymentChannelRepository 支付渠道仓库
*/
class MerchantPortalChannelQueryService extends BaseService
{
/**
* 构造方法。
*
* @param MerchantPortalSupportService $supportService 支持服务
* @param PaymentChannelRepository $paymentChannelRepository 支付渠道仓库
*/
public function __construct(
protected MerchantPortalSupportService $supportService,
protected PaymentChannelRepository $paymentChannelRepository
@@ -22,6 +31,12 @@ class MerchantPortalChannelQueryService extends BaseService
/**
* 查询当前商户的通道列表。
*
* @param array $filters 筛选条件
* @param int $merchantId 商户ID
* @param int $page 页码
* @param int $pageSize 每页条数
* @return array 通道列表数据
*/
public function myChannels(array $filters, int $merchantId, int $page, int $pageSize): array
{
@@ -95,19 +110,27 @@ class MerchantPortalChannelQueryService extends BaseService
];
}
/**
* 为通道行补充文本字段。
*
* @param object $row 通道行
* @return object 处理后的通道行
*/
private function decorateChannelRow(object $row): object
{
$row->channel_mode_text = (string) (RouteConstant::channelModeMap()[(int) $row->channel_mode] ?? '未知');
$row->status_text = (string) (CommonConstant::statusMap()[(int) $row->status] ?? '未知');
$row->split_rate_text = $this->supportService->formatRate((int) $row->split_rate_bp);
$row->cost_rate_text = $this->supportService->formatRate((int) $row->cost_rate_bp);
$row->daily_limit_amount_text = $this->supportService->formatAmountOrUnlimited((int) $row->daily_limit_amount);
$row->daily_limit_count_text = $this->supportService->formatCountOrUnlimited((int) $row->daily_limit_count);
$row->min_amount_text = $this->supportService->formatAmountOrUnlimited((int) $row->min_amount);
$row->max_amount_text = $this->supportService->formatAmountOrUnlimited((int) $row->max_amount);
$row->created_at_text = $this->supportService->formatDateTime($row->created_at ?? null);
$row->updated_at_text = $this->supportService->formatDateTime($row->updated_at ?? null);
$row->split_rate_text = $this->formatRate((int) $row->split_rate_bp);
$row->cost_rate_text = $this->formatRate((int) $row->cost_rate_bp);
$row->daily_limit_amount_text = $this->formatAmountOrUnlimited((int) $row->daily_limit_amount);
$row->daily_limit_count_text = $this->formatCountOrUnlimited((int) $row->daily_limit_count);
$row->min_amount_text = $this->formatAmountOrUnlimited((int) $row->min_amount);
$row->max_amount_text = $this->formatAmountOrUnlimited((int) $row->max_amount);
$row->created_at_text = $this->formatDateTime($row->created_at ?? null);
$row->updated_at_text = $this->formatDateTime($row->updated_at ?? null);
return $row;
}
}

View File

@@ -5,25 +5,51 @@ namespace app\service\merchant\portal;
use app\common\base\BaseService;
/**
* 商户门户通道门面服务。
* 商户门户通道服务。
*
* 对外保留原有调用契约,内部委托给通道查询和路由预览子服务
* @property MerchantPortalChannelQueryService $queryService 查询服务
* @property MerchantPortalRoutePreviewService $routePreviewService 路由解析服务
*/
class MerchantPortalChannelService extends BaseService
{
/**
* 构造方法。
*
* @param MerchantPortalChannelQueryService $queryService 查询服务
* @param MerchantPortalRoutePreviewService $routePreviewService 路由解析服务
*/
public function __construct(
protected MerchantPortalChannelQueryService $queryService,
protected MerchantPortalRoutePreviewService $routePreviewService
) {
}
/**
* 查询当前商户已开通的渠道。
*
* @param array $filters 筛选条件
* @param int $merchantId 商户ID
* @param int $page 页码
* @param int $pageSize 每页条数
* @return array 渠道列表数据
*/
public function myChannels(array $filters, int $merchantId, int $page, int $pageSize): array
{
return $this->queryService->myChannels($filters, $merchantId, $page, $pageSize);
}
/**
* 获取商户渠道路由解析结果。
*
* @param int $merchantId 商户ID
* @param int $payTypeId 支付类型ID
* @param int $payAmount 支付金额
* @param string $statDate 统计日期
* @return array 路由解析数据
*/
public function routePreview(int $merchantId, int $payTypeId, int $payAmount, string $statDate = ''): array
{
return $this->routePreviewService->routePreview($merchantId, $payTypeId, $payAmount, $statDate);
}
}

View File

@@ -7,10 +7,21 @@ use app\repository\merchant\credential\MerchantApiCredentialRepository;
use app\service\merchant\security\MerchantApiCredentialService;
/**
* 商户门户接口凭证命令服务。
* 商户门户 API 凭证命令服务。
*
* @property MerchantPortalSupportService $supportService 支持服务
* @property MerchantApiCredentialRepository $merchantApiCredentialRepository 商户 API 凭证仓库
* @property MerchantApiCredentialService $merchantApiCredentialService 商户 API 凭证服务
*/
class MerchantPortalCredentialCommandService extends BaseService
{
/**
* 构造方法。
*
* @param MerchantPortalSupportService $supportService 支持服务
* @param MerchantApiCredentialRepository $merchantApiCredentialRepository 商户 API 凭证仓库
* @param MerchantApiCredentialService $merchantApiCredentialService 商户 API 凭证服务
*/
public function __construct(
protected MerchantPortalSupportService $supportService,
protected MerchantApiCredentialRepository $merchantApiCredentialRepository,
@@ -18,10 +29,17 @@ class MerchantPortalCredentialCommandService extends BaseService
) {
}
/**
* 生成或重置商户 API 凭证。
*
* @param int $merchantId 商户ID
* @return array 凭证数据
*/
public function issueCredential(int $merchantId): array
{
$merchant = $this->supportService->merchantSummary($merchantId);
$credentialValue = $this->merchantApiCredentialService->issueCredential($merchantId);
// 凭证明文只在发放当次返回一次,随后再查库只拿脱敏后的展示结构。
$credential = $this->merchantApiCredentialRepository->findByMerchantId($merchantId);
return [
@@ -31,6 +49,13 @@ class MerchantPortalCredentialCommandService extends BaseService
];
}
/**
* 格式化接口凭证展示数据。
*
* @param \app\model\merchant\MerchantApiCredential $credential 凭证
* @param array $merchant 商户摘要
* @return array 展示数据
*/
private function formatCredential(\app\model\merchant\MerchantApiCredential $credential, array $merchant): array
{
$signType = (int) $credential->sign_type;
@@ -42,12 +67,13 @@ class MerchantPortalCredentialCommandService extends BaseService
'merchant_name' => (string) ($merchant['merchant_name'] ?? ''),
'sign_type' => $signType,
'sign_type_text' => $this->supportService->signTypeText($signType),
'api_key_preview' => $this->supportService->maskCredentialValue((string) $credential->api_key),
// 展示页只保留脱敏后的 key 片段,避免明文凭证再次暴露。
'api_key_preview' => $this->maskCredentialValue((string) $credential->api_key),
'status' => (int) $credential->status,
'status_text' => (string) ($credential->status ? '启用' : '禁用'),
'last_used_at' => $this->supportService->formatDateTime($credential->last_used_at ?? null),
'created_at' => $this->supportService->formatDateTime($credential->created_at ?? null),
'updated_at' => $this->supportService->formatDateTime($credential->updated_at ?? null),
'last_used_at' => $this->formatDateTime($credential->last_used_at ?? null),
'created_at' => $this->formatDateTime($credential->created_at ?? null),
'updated_at' => $this->formatDateTime($credential->updated_at ?? null),
];
}
}

View File

@@ -8,16 +8,31 @@ use app\model\merchant\MerchantApiCredential;
use app\repository\merchant\credential\MerchantApiCredentialRepository;
/**
* 商户门户接口凭证查询服务。
* 商户门户 API 凭证查询服务。
*
* @property MerchantPortalSupportService $supportService 支持服务
* @property MerchantApiCredentialRepository $merchantApiCredentialRepository 商户 API 凭证仓库
*/
class MerchantPortalCredentialQueryService extends BaseService
{
/**
* 构造方法。
*
* @param MerchantPortalSupportService $supportService 支持服务
* @param MerchantApiCredentialRepository $merchantApiCredentialRepository 商户 API 凭证仓库
*/
public function __construct(
protected MerchantPortalSupportService $supportService,
protected MerchantApiCredentialRepository $merchantApiCredentialRepository
) {
}
/**
* 查询商户 API 凭证详情。
*
* @param int $merchantId 商户ID
* @return array 凭证详情
*/
public function apiCredential(int $merchantId): array
{
$merchant = $this->supportService->merchantSummary($merchantId);
@@ -30,6 +45,13 @@ class MerchantPortalCredentialQueryService extends BaseService
];
}
/**
* 格式化接口凭证展示数据。
*
* @param MerchantApiCredential $credential 凭证
* @param array $merchant 商户摘要
* @return array 展示数据
*/
private function formatCredential(MerchantApiCredential $credential, array $merchant): array
{
$signType = (int) $credential->sign_type;
@@ -42,12 +64,14 @@ class MerchantPortalCredentialQueryService extends BaseService
'merchant_name' => (string) ($merchant['merchant_name'] ?? ''),
'sign_type' => $signType,
'sign_type_text' => $this->supportService->signTypeText($signType),
'api_key_preview' => $this->supportService->maskCredentialValue((string) $credential->api_key),
'api_key_preview' => $this->maskCredentialValue((string) $credential->api_key),
'status' => $status,
'status_text' => (string) (CommonConstant::statusMap()[$status] ?? '未知'),
'last_used_at' => $this->supportService->formatDateTime($credential->last_used_at ?? null),
'created_at' => $this->supportService->formatDateTime($credential->created_at ?? null),
'updated_at' => $this->supportService->formatDateTime($credential->updated_at ?? null),
'last_used_at' => $this->formatDateTime($credential->last_used_at ?? null),
'created_at' => $this->formatDateTime($credential->created_at ?? null),
'updated_at' => $this->formatDateTime($credential->updated_at ?? null),
];
}
}

View File

@@ -5,23 +5,45 @@ namespace app\service\merchant\portal;
use app\common\base\BaseService;
/**
* 商户门户接口凭证门面服务。
* 商户门户 API 凭证服务。
*
* @property MerchantPortalCredentialQueryService $queryService 查询服务
* @property MerchantPortalCredentialCommandService $commandService 命令服务
*/
class MerchantPortalCredentialService extends BaseService
{
/**
* 构造方法。
*
* @param MerchantPortalCredentialQueryService $queryService 查询服务
* @param MerchantPortalCredentialCommandService $commandService 命令服务
*/
public function __construct(
protected MerchantPortalCredentialQueryService $queryService,
protected MerchantPortalCredentialCommandService $commandService
) {
}
/**
* 查询商户 API 凭证。
*
* @param int $merchantId 商户ID
* @return array 凭证数据
*/
public function apiCredential(int $merchantId): array
{
return $this->queryService->apiCredential($merchantId);
}
/**
* 生成或重置商户 API 凭证。
*
* @param int $merchantId 商户ID
* @return array 凭证数据
*/
public function issueCredential(int $merchantId): array
{
return $this->commandService->issueCredential($merchantId);
}
}

View File

@@ -5,35 +5,76 @@ namespace app\service\merchant\portal;
use app\common\base\BaseService;
/**
* 商户门户资金与清算门面服务。
* 商户门户资金与清算服务。
*
* 对外保留原有调用契约,内部委托给清算与余额子服务
* @property MerchantPortalSettlementService $settlementService 结算服务
* @property MerchantPortalBalanceService $balanceService 余额服务
*/
class MerchantPortalFinanceService extends BaseService
{
/**
* 构造方法。
*
* @param MerchantPortalSettlementService $settlementService 结算服务
* @param MerchantPortalBalanceService $balanceService 余额服务
*/
public function __construct(
protected MerchantPortalSettlementService $settlementService,
protected MerchantPortalBalanceService $balanceService
) {
}
/**
* 查询商户结算记录。
*
* @param array $filters 筛选条件
* @param int $merchantId 商户ID
* @param int $page 页码
* @param int $pageSize 每页条数
* @return array 结算记录列表
*/
public function settlementRecords(array $filters, int $merchantId, int $page, int $pageSize): array
{
return $this->settlementService->settlementRecords($filters, $merchantId, $page, $pageSize);
}
/**
* 查询商户结算记录详情。
*
* @param string $settleNo 结算单号
* @param int $merchantId 商户ID
* @return array|null 结算详情
*/
public function settlementRecordDetail(string $settleNo, int $merchantId): ?array
{
return $this->settlementService->settlementRecordDetail($settleNo, $merchantId);
}
/**
* 查询商户可提现余额。
*
* @param int $merchantId 商户ID
* @return array 余额数据
*/
public function withdrawableBalance(int $merchantId): array
{
return $this->balanceService->withdrawableBalance($merchantId);
}
/**
* 查询商户资金流水。
*
* @param array $filters 筛选条件
* @param int $merchantId 商户ID
* @param int $page 页码
* @param int $pageSize 每页条数
* @return array 流水列表
*/
public function balanceFlows(array $filters, int $merchantId, int $page, int $pageSize): array
{
return $this->balanceService->balanceFlows($filters, $merchantId, $page, $pageSize);
}
}

View File

@@ -9,15 +9,32 @@ use app\repository\merchant\base\MerchantRepository;
/**
* 商户门户资料命令服务。
*
* @property MerchantPortalSupportService $supportService 支持服务
* @property MerchantRepository $merchantRepository 商户仓库
*/
class MerchantPortalProfileCommandService extends BaseService
{
/**
* 构造方法。
*
* @param MerchantPortalSupportService $supportService 支持服务
* @param MerchantRepository $merchantRepository 商户仓库
*/
public function __construct(
protected MerchantPortalSupportService $supportService,
protected MerchantRepository $merchantRepository
) {
}
/**
* 更新商户门户资料。
*
* @param int $merchantId 商户ID
* @param array $data 资料数据
* @return array 更新后的资料数据
* @throws ResourceNotFoundException
*/
public function updateProfile(int $merchantId, array $data): array
{
$merchant = $this->merchantRepository->find($merchantId);
@@ -42,6 +59,15 @@ class MerchantPortalProfileCommandService extends BaseService
];
}
/**
* 修改商户门户密码。
*
* @param int $merchantId 商户ID
* @param array $data 密码数据
* @return array 密码修改结果
* @throws ResourceNotFoundException
* @throws ValidationException
*/
public function changePassword(int $merchantId, array $data): array
{
$merchant = $this->merchantRepository->find($merchantId);
@@ -63,7 +89,8 @@ class MerchantPortalProfileCommandService extends BaseService
return [
'updated' => true,
'password_updated_at' => $this->supportService->formatDateTime($this->now()),
'password_updated_at' => $this->formatDateTime($this->now()),
];
}
}

View File

@@ -6,14 +6,27 @@ use app\common\base\BaseService;
/**
* 商户门户资料查询服务。
*
* @property MerchantPortalSupportService $supportService 支持服务
*/
class MerchantPortalProfileQueryService extends BaseService
{
/**
* 构造方法。
*
* @param MerchantPortalSupportService $supportService 支持服务
*/
public function __construct(
protected MerchantPortalSupportService $supportService
) {
}
/**
* 查询商户门户资料页数据。
*
* @param int $merchantId 商户ID
* @return array 页面数据
*/
public function profile(int $merchantId): array
{
return [
@@ -22,3 +35,6 @@ class MerchantPortalProfileQueryService extends BaseService
];
}
}

View File

@@ -5,28 +5,59 @@ namespace app\service\merchant\portal;
use app\common\base\BaseService;
/**
* 商户门户资料门面服务。
* 商户门户资料服务。
*
* @property MerchantPortalProfileQueryService $queryService 查询服务
* @property MerchantPortalProfileCommandService $commandService 命令服务
*/
class MerchantPortalProfileService extends BaseService
{
/**
* 构造方法。
*
* @param MerchantPortalProfileQueryService $queryService 查询服务
* @param MerchantPortalProfileCommandService $commandService 命令服务
*/
public function __construct(
protected MerchantPortalProfileQueryService $queryService,
protected MerchantPortalProfileCommandService $commandService
) {
}
/**
* 查询商户门户资料。
*
* @param int $merchantId 商户ID
* @return array 资料数据
*/
public function profile(int $merchantId): array
{
return $this->queryService->profile($merchantId);
}
/**
* 更新商户门户资料。
*
* @param int $merchantId 商户ID
* @param array $data 资料数据
* @return array 更新后的资料数据
*/
public function updateProfile(int $merchantId, array $data): array
{
return $this->commandService->updateProfile($merchantId, $data);
}
/**
* 修改商户门户密码。
*
* @param int $merchantId 商户ID
* @param array $data 密码数据
* @return array 密码修改结果
*/
public function changePassword(int $merchantId, array $data): array
{
return $this->commandService->changePassword($merchantId, $data);
}
}

View File

@@ -10,10 +10,21 @@ use app\service\payment\runtime\PaymentRouteService;
use Throwable;
/**
* 商户门户路由预览服务。
* 商户门户路由解析服务。
*
* 负责根据商户分组、支付方式和金额解析路由结果。
*
* @property MerchantPortalSupportService $supportService 支持服务
* @property PaymentRouteService $paymentRouteService 支付路由服务
*/
class MerchantPortalRoutePreviewService extends BaseService
{
/**
* 构造方法。
*
* @param MerchantPortalSupportService $supportService 支持服务
* @param PaymentRouteService $paymentRouteService 支付路由服务
*/
public function __construct(
protected MerchantPortalSupportService $supportService,
protected PaymentRouteService $paymentRouteService
@@ -21,22 +32,30 @@ class MerchantPortalRoutePreviewService extends BaseService
}
/**
* 预览当前商户的路由选择结果。
* 获取当前商户的路由解析结果。
*
* @param int $merchantId 商户ID
* @param int $payTypeId 支付类型ID
* @param int $payAmount 支付金额
* @param string $statDate 统计日期
* @return array 路由解析数据
*/
public function routePreview(int $merchantId, int $payTypeId, int $payAmount, string $statDate = ''): array
{
// 先拿商户摘要,后面即使路由解析失败,也还能返回基础商户信息给前端展示。
$merchant = $this->supportService->merchantSummary($merchantId);
$statDate = trim($statDate) !== '' ? trim($statDate) : FormatHelper::timestamp(time(), 'Y-m-d');
// 先组一个可直接渲染的基础响应结构,失败时只需要改 reason 和可用状态。
$response = [
'merchant' => $merchant,
'pay_types' => $this->supportService->enabledPayTypeOptions(),
'pay_type_id' => $payTypeId,
'pay_amount' => $payAmount,
'pay_amount_text' => $this->supportService->formatAmount($payAmount),
'pay_amount_text' => $this->formatAmount($payAmount),
'stat_date' => $statDate,
'available' => false,
'reason' => '请选择支付方式和金额后预览路由',
'reason' => '请选择支付方式和金额后解析路由',
'merchant_group_id' => (int) ($merchant['merchant_group_id'] ?? 0),
'merchant_group_name' => (string) ($merchant['merchant_group_name'] ?? ''),
'bind' => null,
@@ -50,11 +69,12 @@ class MerchantPortalRoutePreviewService extends BaseService
}
if ((int) $merchant['merchant_group_id'] <= 0) {
$response['reason'] = '当前商户未配置商户分组,无法预览路由';
$response['reason'] = '当前商户未配置商户分组,无法解析路由';
return $response;
}
try {
// 只有基础条件满足时,才进入完整的路由解析流程。
$resolved = $this->paymentRouteService->resolveByMerchantGroup(
(int) $merchant['merchant_group_id'],
$payTypeId,
@@ -63,7 +83,8 @@ class MerchantPortalRoutePreviewService extends BaseService
);
$response['available'] = true;
$response['reason'] = '路由预览成功';
$response['reason'] = '路由解析成功';
// 把模型和仓库返回的对象统一整理成前端可直接展示的数组结构。
$response['bind'] = $this->normalizeBind($resolved['bind'] ?? null);
$response['poll_group'] = $this->normalizePollGroup($resolved['poll_group'] ?? null);
$response['selected_channel'] = $this->normalizePreviewCandidate($resolved['selected_channel'] ?? null);
@@ -73,15 +94,22 @@ class MerchantPortalRoutePreviewService extends BaseService
(array) ($resolved['candidates'] ?? [])
));
} catch (Throwable $e) {
$response['reason'] = $e->getMessage() !== '' ? $e->getMessage() : '路由预览失败';
// 解析异常只影响路由结果,不影响基础信息展示,因此这里只回填失败原因。
$response['reason'] = $e->getMessage() !== '' ? $e->getMessage() : '路由解析失败';
}
return $response;
}
private function normalizeBind(mixed $bind): ?array
/**
* 标准化商户分组与支付方式绑定数据。
*
* @param array|object|null $bind 绑定数据
* @return array|null 标准化结果
*/
private function normalizeBind(array|object|null $bind): ?array
{
$data = $this->supportService->normalizeModel($bind);
$data = $this->normalizeModel($bind);
if ($data === null) {
return null;
}
@@ -95,14 +123,20 @@ class MerchantPortalRoutePreviewService extends BaseService
'status' => $status,
'status_text' => (string) (CommonConstant::statusMap()[$status] ?? '未知'),
'remark' => (string) ($data['remark'] ?? ''),
'created_at' => $this->supportService->formatDateTime($data['created_at'] ?? null),
'updated_at' => $this->supportService->formatDateTime($data['updated_at'] ?? null),
'created_at' => $this->formatDateTime($data['created_at'] ?? null),
'updated_at' => $this->formatDateTime($data['updated_at'] ?? null),
];
}
private function normalizePollGroup(mixed $pollGroup): ?array
/**
* 标准化轮询分组数据。
*
* @param array|object|null $pollGroup 轮询分组
* @return array|null 标准化结果
*/
private function normalizePollGroup(array|object|null $pollGroup): ?array
{
$data = $this->supportService->normalizeModel($pollGroup);
$data = $this->normalizeModel($pollGroup);
if ($data === null) {
return null;
}
@@ -119,21 +153,28 @@ class MerchantPortalRoutePreviewService extends BaseService
'status' => $status,
'status_text' => (string) (CommonConstant::statusMap()[$status] ?? '未知'),
'remark' => (string) ($data['remark'] ?? ''),
'created_at' => $this->supportService->formatDateTime($data['created_at'] ?? null),
'updated_at' => $this->supportService->formatDateTime($data['updated_at'] ?? null),
'created_at' => $this->formatDateTime($data['created_at'] ?? null),
'updated_at' => $this->formatDateTime($data['updated_at'] ?? null),
];
}
private function normalizePreviewCandidate(mixed $candidate): ?array
/**
* 标准化路由候选数据。
*
* @param array|object|null $candidate 候选数据
* @return array|null 标准化结果
*/
private function normalizePreviewCandidate(array|object|null $candidate): ?array
{
$data = is_array($candidate) ? $candidate : $this->supportService->normalizeModel($candidate);
$data = is_array($candidate) ? $candidate : $this->normalizeModel($candidate);
if ($data === null) {
return null;
}
$channel = $this->supportService->normalizeModel($data['channel'] ?? null) ?? [];
$pollGroupChannel = $this->supportService->normalizeModel($data['poll_group_channel'] ?? null) ?? [];
$dailyStat = $this->supportService->normalizeModel($data['daily_stat'] ?? null) ?? [];
// 一个候选项会同时带出通道、轮询关系和日统计三层数据,后面统一整理成展示结构。
$channel = $this->normalizeModel($data['channel'] ?? null) ?? [];
$pollGroupChannel = $this->normalizeModel($data['poll_group_channel'] ?? null) ?? [];
$dailyStat = $this->normalizeModel($data['daily_stat'] ?? null) ?? [];
$channelMode = (int) ($channel['channel_mode'] ?? 0);
$status = (int) ($channel['status'] ?? 0);
@@ -152,27 +193,28 @@ class MerchantPortalRoutePreviewService extends BaseService
'sort_no' => (int) ($pollGroupChannel['sort_no'] ?? 0),
'weight' => (int) ($pollGroupChannel['weight'] ?? 0),
'is_default' => (int) ($pollGroupChannel['is_default'] ?? 0),
// 统计指标同时返回原始值和格式化文本,前端可以直接展示而不再二次换算。
'health_score' => (int) ($dailyStat['health_score'] ?? 0),
'health_score_text' => (string) ($dailyStat['health_score'] ?? 0),
'success_rate_bp' => (int) ($dailyStat['success_rate_bp'] ?? 0),
'success_rate_text' => $this->supportService->formatRate((int) ($dailyStat['success_rate_bp'] ?? 0)),
'success_rate_text' => $this->formatRate((int) ($dailyStat['success_rate_bp'] ?? 0)),
'avg_latency_ms' => (int) ($dailyStat['avg_latency_ms'] ?? 0),
'avg_latency_text' => $this->supportService->formatLatency((int) ($dailyStat['avg_latency_ms'] ?? 0)),
'avg_latency_text' => $this->formatLatency((int) ($dailyStat['avg_latency_ms'] ?? 0)),
'split_rate_bp' => (int) ($channel['split_rate_bp'] ?? 0),
'split_rate_text' => $this->supportService->formatRate((int) ($channel['split_rate_bp'] ?? 0)),
'split_rate_text' => $this->formatRate((int) ($channel['split_rate_bp'] ?? 0)),
'cost_rate_bp' => (int) ($channel['cost_rate_bp'] ?? 0),
'cost_rate_text' => $this->supportService->formatRate((int) ($channel['cost_rate_bp'] ?? 0)),
'cost_rate_text' => $this->formatRate((int) ($channel['cost_rate_bp'] ?? 0)),
'daily_limit_amount' => (int) ($channel['daily_limit_amount'] ?? 0),
'daily_limit_amount_text' => $this->supportService->formatAmountOrUnlimited((int) ($channel['daily_limit_amount'] ?? 0)),
'daily_limit_amount_text' => $this->formatAmountOrUnlimited((int) ($channel['daily_limit_amount'] ?? 0)),
'daily_limit_count' => (int) ($channel['daily_limit_count'] ?? 0),
'daily_limit_count_text' => $this->supportService->formatCountOrUnlimited((int) ($channel['daily_limit_count'] ?? 0)),
'daily_limit_count_text' => $this->formatCountOrUnlimited((int) ($channel['daily_limit_count'] ?? 0)),
'min_amount' => (int) ($channel['min_amount'] ?? 0),
'min_amount_text' => $this->supportService->formatAmountOrUnlimited((int) ($channel['min_amount'] ?? 0)),
'min_amount_text' => $this->formatAmountOrUnlimited((int) ($channel['min_amount'] ?? 0)),
'max_amount' => (int) ($channel['max_amount'] ?? 0),
'max_amount_text' => $this->supportService->formatAmountOrUnlimited((int) ($channel['max_amount'] ?? 0)),
'max_amount_text' => $this->formatAmountOrUnlimited((int) ($channel['max_amount'] ?? 0)),
'remark' => (string) ($channel['remark'] ?? ''),
'created_at' => $this->supportService->formatDateTime($channel['created_at'] ?? null),
'updated_at' => $this->supportService->formatDateTime($channel['updated_at'] ?? null),
'created_at' => $this->formatDateTime($channel['created_at'] ?? null),
'updated_at' => $this->formatDateTime($channel['updated_at'] ?? null),
];
}
}

View File

@@ -5,12 +5,23 @@ namespace app\service\merchant\portal;
use app\common\base\BaseService;
/**
* 商户后台基础页面服务门面
* 商户后台门户服务
*
* 仅保留控制器依赖的统一入口,具体能力拆到资料、通道、凭证和资金子服务
* @property MerchantPortalProfileService $profileService 资料服务
* @property MerchantPortalChannelService $channelService 渠道服务
* @property MerchantPortalCredentialService $credentialService 凭证服务
* @property MerchantPortalFinanceService $financeService 财务服务
*/
class MerchantPortalService extends BaseService
{
/**
* 构造方法。
*
* @param MerchantPortalProfileService $profileService 资料服务
* @param MerchantPortalChannelService $channelService 渠道服务
* @param MerchantPortalCredentialService $credentialService 凭证服务
* @param MerchantPortalFinanceService $financeService 财务服务
*/
public function __construct(
protected MerchantPortalProfileService $profileService,
protected MerchantPortalChannelService $channelService,
@@ -19,56 +30,137 @@ class MerchantPortalService extends BaseService
) {
}
/**
* 查询商户门户资料。
*
* @param int $merchantId 商户ID
* @return array 资料数据
*/
public function profile(int $merchantId): array
{
return $this->profileService->profile($merchantId);
}
/**
* 更新商户门户资料。
*
* @param int $merchantId 商户ID
* @param array $data 资料数据
* @return array 更新后的资料数据
*/
public function updateProfile(int $merchantId, array $data): array
{
return $this->profileService->updateProfile($merchantId, $data);
}
/**
* 修改商户门户密码。
*
* @param int $merchantId 商户ID
* @param array $data 密码数据
* @return array 密码修改结果
*/
public function changePassword(int $merchantId, array $data): array
{
return $this->profileService->changePassword($merchantId, $data);
}
/**
* 查询当前商户已开通的渠道。
*
* @param array $filters 筛选条件
* @param int $merchantId 商户ID
* @param int $page 页码
* @param int $pageSize 每页条数
* @return array 渠道列表
*/
public function myChannels(array $filters, int $merchantId, int $page, int $pageSize): array
{
return $this->channelService->myChannels($filters, $merchantId, $page, $pageSize);
}
/**
* 获取商户路由解析结果。
*
* @param int $merchantId 商户ID
* @param int $payTypeId 支付类型ID
* @param int $payAmount 支付金额
* @param string $statDate 统计日期
* @return array 路由解析数据
*/
public function routePreview(int $merchantId, int $payTypeId, int $payAmount, string $statDate = ''): array
{
return $this->channelService->routePreview($merchantId, $payTypeId, $payAmount, $statDate);
}
/**
* 查询商户 API 凭证。
*
* @param int $merchantId 商户ID
* @return array 凭证数据
*/
public function apiCredential(int $merchantId): array
{
return $this->credentialService->apiCredential($merchantId);
}
/**
* 生成或重置商户门户接口凭证。
*
* @param int $merchantId 商户ID
* @return array 凭证数据
*/
public function issueCredential(int $merchantId): array
{
return $this->credentialService->issueCredential($merchantId);
}
/**
* 查询商户结算记录。
*
* @param array $filters 筛选条件
* @param int $merchantId 商户ID
* @param int $page 页码
* @param int $pageSize 每页条数
* @return array 结算记录列表
*/
public function settlementRecords(array $filters, int $merchantId, int $page, int $pageSize): array
{
return $this->financeService->settlementRecords($filters, $merchantId, $page, $pageSize);
}
/**
* 查询商户结算记录详情。
*
* @param string $settleNo 结算单号
* @param int $merchantId 商户ID
* @return array|null 结算详情
*/
public function settlementRecordDetail(string $settleNo, int $merchantId): ?array
{
return $this->financeService->settlementRecordDetail($settleNo, $merchantId);
}
/**
* 查询商户可提现余额。
*
* @param int $merchantId 商户ID
* @return array 余额数据
*/
public function withdrawableBalance(int $merchantId): array
{
return $this->financeService->withdrawableBalance($merchantId);
}
/**
* 查询商户资金流水。
*
* @param array $filters 筛选条件
* @param int $merchantId 商户ID
* @param int $page 页码
* @param int $pageSize 每页条数
* @return array 流水列表
*/
public function balanceFlows(array $filters, int $merchantId, int $page, int $pageSize): array
{
return $this->financeService->balanceFlows($filters, $merchantId, $page, $pageSize);

View File

@@ -8,15 +8,33 @@ use app\service\payment\settlement\SettlementOrderQueryService;
/**
* 商户门户清算服务。
*
* @property MerchantPortalSupportService $supportService 支持服务
* @property SettlementOrderQueryService $settlementOrderQueryService 结算订单查询服务
*/
class MerchantPortalSettlementService extends BaseService
{
/**
* 构造方法。
*
* @param MerchantPortalSupportService $supportService 支持服务
* @param SettlementOrderQueryService $settlementOrderQueryService 结算订单查询服务
*/
public function __construct(
protected MerchantPortalSupportService $supportService,
protected SettlementOrderQueryService $settlementOrderQueryService
) {
}
/**
* 查询商户结算记录。
*
* @param array $filters 筛选条件
* @param int $merchantId 商户ID
* @param int $page 页码
* @param int $pageSize 每页条数
* @return array 结算记录列表
*/
public function settlementRecords(array $filters, int $merchantId, int $page, int $pageSize): array
{
$paginator = $this->settlementOrderQueryService->paginate($filters, $page, $pageSize, $merchantId);
@@ -30,6 +48,13 @@ class MerchantPortalSettlementService extends BaseService
];
}
/**
* 查询商户结算记录详情。
*
* @param string $settleNo 结算单号
* @param int $merchantId 商户ID
* @return array|null 结算详情
*/
public function settlementRecordDetail(string $settleNo, int $merchantId): ?array
{
try {
@@ -45,3 +70,6 @@ class MerchantPortalSettlementService extends BaseService
];
}
}

View File

@@ -10,12 +10,23 @@ use app\service\merchant\MerchantService;
use app\service\payment\config\PaymentTypeService;
/**
* 商户门户公共支持服务。
* 商户门户支持服务。
*
* 统一承接商户门户里复用的商户摘要、支付方式和通用格式化能力。
* 统一承接商户门户里复用的商户摘要、支付方式和展示整理能力。
*
* @property MerchantService $merchantService 商户服务
* @property MerchantRepository $merchantRepository 商户仓库
* @property PaymentTypeService $paymentTypeService 支付类型服务
*/
class MerchantPortalSupportService extends BaseService
{
/**
* 构造方法。
*
* @param MerchantService $merchantService 商户服务
* @param MerchantRepository $merchantRepository 商户仓库
* @param PaymentTypeService $paymentTypeService 支付类型服务
*/
public function __construct(
protected MerchantService $merchantService,
protected MerchantRepository $merchantRepository,
@@ -25,6 +36,10 @@ class MerchantPortalSupportService extends BaseService
/**
* 当前商户基础资料摘要。
*
* @param int $merchantId 商户ID
* @return array 商户摘要
* @throws ResourceNotFoundException
*/
public function merchantSummary(int $merchantId): array
{
@@ -106,7 +121,9 @@ class MerchantPortalSupportService extends BaseService
}
/**
* 启用的支付方式选项。
* 获取启用的支付方式选项。
*
* @return array 支付方式选项
*/
public function enabledPayTypeOptions(): array
{
@@ -115,6 +132,9 @@ class MerchantPortalSupportService extends BaseService
/**
* 根据支付方式 ID 获取名称。
*
* @param int $payTypeId 支付类型ID
* @return string 支付方式名称
*/
public function paymentTypeName(int $payTypeId): string
{
@@ -127,72 +147,11 @@ class MerchantPortalSupportService extends BaseService
return $payTypeId > 0 ? '未知' : '';
}
/**
* 格式化金额,单位为元。
*/
public function formatAmount(int $amount): string
{
return parent::formatAmount($amount);
}
/**
* 格式化金额0 时显示不限。
*/
public function formatAmountOrUnlimited(int $amount): string
{
return parent::formatAmountOrUnlimited($amount);
}
/**
* 格式化次数0 时显示不限。
*/
public function formatCountOrUnlimited(int $count): string
{
return parent::formatCountOrUnlimited($count);
}
/**
* 格式化费率,单位为百分点。
*/
public function formatRate(int $basisPoints): string
{
return parent::formatRate($basisPoints);
}
/**
* 格式化延迟。
*/
public function formatLatency(int $latencyMs): string
{
return parent::formatLatency($latencyMs);
}
/**
* 格式化日期时间。
*/
public function formatDateTime(mixed $value, string $emptyText = ''): string
{
return parent::formatDateTime($value, $emptyText);
}
/**
* 归一化模型对象,兼容模型和数组。
*/
public function normalizeModel(mixed $value): ?array
{
return parent::normalizeModel($value);
}
/**
* 隐藏接口凭证明文。
*/
public function maskCredentialValue(string $credentialValue, bool $maskShortValue = true): string
{
return parent::maskCredentialValue($credentialValue, $maskShortValue);
}
/**
* 签名类型文案。
*
* @param int $signType 签名类型
* @return string 签名类型文本
*/
public function signTypeText(int $signType): string
{