TransferFeeDto.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. namespace App\Module\Transfer\Dtos;
  3. use UCore\Dto\BaseDto;
  4. /**
  5. * 划转手续费计算结果数据传输对象
  6. *
  7. * 用于表示手续费计算的结果,包含手续费率、手续费金额、实际到账金额等信息
  8. */
  9. class TransferFeeDto extends BaseDto
  10. {
  11. /**
  12. * 构造函数
  13. *
  14. * @param float $feeRate 手续费率(小数形式,如 0.01 表示 1%)
  15. * @param string $feeAmount 手续费金额(字符串格式,保持精度)
  16. * @param string $actualAmount 实际到账金额(字符串格式,保持精度)
  17. * @param string $originalAmount 原始金额(字符串格式,保持精度)
  18. * @param bool $hasError 是否有错误
  19. * @param string|null $errorMessage 错误信息
  20. * @param array $additionalInfo 额外信息
  21. */
  22. public function __construct(
  23. public readonly float $feeRate,
  24. public readonly string $feeAmount,
  25. public readonly string $actualAmount,
  26. public readonly string $originalAmount,
  27. public readonly bool $hasError = false,
  28. public readonly ?string $errorMessage = null,
  29. public readonly array $additionalInfo = []
  30. ) {}
  31. /**
  32. * 创建成功的手续费计算结果
  33. *
  34. * @param string $originalAmount 原始金额
  35. * @param float $feeRate 手续费率
  36. * @param string $feeAmount 手续费金额
  37. * @param string $actualAmount 实际到账金额
  38. * @param array $additionalInfo 额外信息
  39. * @return self
  40. */
  41. public static function success(
  42. string $originalAmount,
  43. float $feeRate,
  44. string $feeAmount,
  45. string $actualAmount,
  46. array $additionalInfo = []
  47. ): self {
  48. return new self(
  49. feeRate: $feeRate,
  50. feeAmount: $feeAmount,
  51. actualAmount: $actualAmount,
  52. originalAmount: $originalAmount,
  53. hasError: false,
  54. errorMessage: null,
  55. additionalInfo: $additionalInfo
  56. );
  57. }
  58. /**
  59. * 创建错误的手续费计算结果
  60. *
  61. * @param string $originalAmount 原始金额
  62. * @param string $errorMessage 错误信息
  63. * @param array $additionalInfo 额外信息
  64. * @return self
  65. */
  66. public static function error(
  67. string $originalAmount,
  68. string $errorMessage,
  69. array $additionalInfo = []
  70. ): self {
  71. return new self(
  72. feeRate: 0.0000,
  73. feeAmount: '0.0000',
  74. actualAmount: $originalAmount,
  75. originalAmount: $originalAmount,
  76. hasError: true,
  77. errorMessage: $errorMessage,
  78. additionalInfo: $additionalInfo
  79. );
  80. }
  81. /**
  82. * 从数组创建DTO(兼容旧的数组格式)
  83. *
  84. * @param array $data 数组数据
  85. * @param string $originalAmount 原始金额
  86. * @return self
  87. */
  88. public static function fromLegacyArray(array $data, string $originalAmount = ''): self
  89. {
  90. // 检查是否有错误
  91. if (isset($data['error'])) {
  92. return self::error(
  93. originalAmount: $originalAmount,
  94. errorMessage: $data['error'],
  95. additionalInfo: array_diff_key($data, array_flip(['error']))
  96. );
  97. }
  98. return self::success(
  99. originalAmount: $originalAmount,
  100. feeRate: (float) ($data['fee_rate'] ?? 0.0000),
  101. feeAmount: (string) ($data['fee_amount'] ?? '0.0000'),
  102. actualAmount: (string) ($data['actual_amount'] ?? $originalAmount),
  103. additionalInfo: array_diff_key($data, array_flip(['fee_rate', 'fee_amount', 'actual_amount']))
  104. );
  105. }
  106. /**
  107. * 转换为数组(保持向后兼容)
  108. *
  109. * @return array
  110. */
  111. public function toArray(): array
  112. {
  113. $result = [
  114. 'fee_rate' => $this->feeRate,
  115. 'fee_amount' => $this->feeAmount,
  116. 'actual_amount' => $this->actualAmount,
  117. 'original_amount' => $this->originalAmount,
  118. 'has_error' => $this->hasError,
  119. ];
  120. // 如果有错误,添加错误信息
  121. if ($this->hasError && $this->errorMessage) {
  122. $result['error'] = $this->errorMessage;
  123. }
  124. // 添加额外信息
  125. if (!empty($this->additionalInfo)) {
  126. $result = array_merge($result, $this->additionalInfo);
  127. }
  128. return $result;
  129. }
  130. /**
  131. * 转换为兼容旧格式的数组
  132. *
  133. * @return array
  134. */
  135. public function toLegacyArray(): array
  136. {
  137. if ($this->hasError) {
  138. return [
  139. 'error' => $this->errorMessage,
  140. 'fee_rate' => $this->feeRate,
  141. 'fee_amount' => $this->feeAmount,
  142. 'actual_amount' => $this->actualAmount,
  143. ];
  144. }
  145. return [
  146. 'fee_rate' => $this->feeRate,
  147. 'fee_amount' => $this->feeAmount,
  148. 'actual_amount' => $this->actualAmount,
  149. ];
  150. }
  151. /**
  152. * 获取手续费率百分比格式
  153. *
  154. * @param int $decimals 小数位数
  155. * @return string
  156. */
  157. public function getFeeRatePercent(int $decimals = 2): string
  158. {
  159. return number_format($this->feeRate * 100, $decimals) . '%';
  160. }
  161. /**
  162. * 判断是否有手续费
  163. *
  164. * @return bool
  165. */
  166. public function hasFee(): bool
  167. {
  168. return bccomp($this->feeAmount, '0', 10) > 0;
  169. }
  170. /**
  171. * 判断是否计算成功
  172. *
  173. * @return bool
  174. */
  175. public function isSuccess(): bool
  176. {
  177. return !$this->hasError;
  178. }
  179. /**
  180. * 获取格式化的手续费信息
  181. *
  182. * @return string
  183. */
  184. public function getFormattedFeeInfo(): string
  185. {
  186. if ($this->hasError) {
  187. return "计算失败: {$this->errorMessage}";
  188. }
  189. if (!$this->hasFee()) {
  190. return "无手续费";
  191. }
  192. return "手续费: {$this->feeAmount} ({$this->getFeeRatePercent()})";
  193. }
  194. }