PHP项目数字挪威克朗与eNOK

wen PHP项目 2

本文目录导读:

PHP项目数字挪威克朗与eNOK

  1. 货币基础配置
  2. 货币值对象
  3. 货币转换服务
  4. 账户与交易模型
  5. 货币兑换功能
  6. 使用示例
  7. 注意事项

我来帮您分析PHP项目中处理数字挪威克朗(NOK)与电子克朗(eNOK)的相关实现。

货币基础配置

<?php
// 货币配置类
class CurrencyConfig {
    // 货币代码
    const NOK = 'NOK';  // 挪威克朗
    const ENOK = 'eNOK'; // 电子克朗
    // 货币精度(小数位数)
    const PRECISION_NOK = 2;   // 挪威克朗2位小数
    const PRECISION_ENOK = 2;  // 电子克朗2位小数
    // 货币符号
    const SYMBOL_NOK = 'kr';
    const SYMBOL_ENOK = 'e-kr';
    // 汇率配置(示例)
    const RATIO_NOK_TO_ENOK = 1; // 1:1 兑换(实际中可能有差异)
}

货币值对象

<?php
// 不可变的货币值对象
class Money {
    private float $amount;
    private string $currency;
    public function __construct(float $amount, string $currency) {
        if (!in_array($currency, [CurrencyConfig::NOK, CurrencyConfig::ENOK])) {
            throw new InvalidArgumentException("不支持的货币类型");
        }
        $this->amount = $this->round($amount, $this->getPrecision($currency));
        $this->currency = $currency;
    }
    public function getAmount(): float {
        return $this->amount;
    }
    public function getCurrency(): string {
        return $this->currency;
    }
    // 货币加减运算
    public function add(Money $other): Money {
        $this->assertSameCurrency($other);
        return new Money(
            $this->amount + $other->amount,
            $this->currency
        );
    }
    public function subtract(Money $other): Money {
        $this->assertSameCurrency($other);
        return new Money(
            $this->amount - $other->amount,
            $this->currency
        );
    }
    // 乘法(用于计算税费等)
    public function multiply(float $multiplier): Money {
        return new Money(
            $this->amount * $multiplier,
            $this->currency
        );
    }
    // 格式化显示
    public function format(): string {
        $formatted = number_format(
            $this->amount,
            $this->getPrecision($this->currency),
            ',',
            ' '
        );
        if ($this->currency === CurrencyConfig::NOK) {
            return $formatted . ' ' . CurrencyConfig::SYMBOL_NOK;
        }
        return $formatted . ' ' . CurrencyConfig::SYMBOL_ENOK;
    }
    private function getPrecision(string $currency): int {
        return $currency === CurrencyConfig::NOK 
            ? CurrencyConfig::PRECISION_NOK 
            : CurrencyConfig::PRECISION_ENOK;
    }
    private function round(float $amount, int $precision): float {
        return round($amount, $precision);
    }
    private function assertSameCurrency(Money $other): void {
        if ($this->currency !== $other->currency) {
            throw new InvalidArgumentException("货币类型不匹配");
        }
    }
}

货币转换服务

<?php
// 货币转换服务
class CurrencyConversionService {
    private array $exchangeRates;
    public function __construct(array $exchangeRates = []) {
        // 默认汇率配置
        $this->exchangeRates = $exchangeRates ?: [
            CurrencyConfig::NOK => [
                CurrencyConfig::ENOK => 1.0,  // 1 NOK = 1 eNOK
            ],
            CurrencyConfig::ENOK => [
                CurrencyConfig::NOK => 1.0,  // 1 eNOK = 1 NOK
            ]
        ];
    }
    // 货币转换
    public function convert(Money $money, string $targetCurrency): Money {
        if ($money->getCurrency() === $targetCurrency) {
            return $money;
        }
        $rate = $this->getExchangeRate($money->getCurrency(), $targetCurrency);
        $convertedAmount = $money->getAmount() * $rate;
        return new Money($convertedAmount, $targetCurrency);
    }
    // 批量转换
    public function convertAll(array $moneyList, string $targetCurrency): array {
        return array_map(
            fn(Money $money) => $this->convert($money, $targetCurrency),
            $moneyList
        );
    }
    private function getExchangeRate(string $from, string $to): float {
        if (!isset($this->exchangeRates[$from][$to])) {
            throw new RuntimeException("汇率未配置: $from -> $to");
        }
        return $this->exchangeRates[$from][$to];
    }
}

账户与交易模型

<?php
// 账户模型
class Account {
    private string $accountId;
    private string $userId;
    private Money $balance;
    private string $accountType; // 'nok' 或 'enok'
    public function __construct(string $userId, string $currency) {
        $this->accountId = uniqid('acc_', true);
        $this->userId = $userId;
        $this->balance = new Money(0, $currency);
        $this->accountType = $currency;
    }
    // 存款
    public function deposit(Money $amount): Transaction {
        if ($amount->getCurrency() !== $this->balance->getCurrency()) {
            throw new InvalidArgumentException("货币类型不匹配");
        }
        $this->balance = $this->balance->add($amount);
        return new Transaction(
            $this->accountId,
            $amount,
            Transaction::TYPE_DEPOSIT
        );
    }
    // 取款
    public function withdraw(Money $amount): Transaction {
        if ($amount->getCurrency() !== $this->balance->getCurrency()) {
            throw new InvalidArgumentException("货币类型不匹配");
        }
        if ($amount->getAmount() > $this->balance->getAmount()) {
            throw new InsufficientFundsException("余额不足");
        }
        $this->balance = $this->balance->subtract($amount);
        return new Transaction(
            $this->accountId,
            $amount,
            Transaction::TYPE_WITHDRAWAL
        );
    }
    // 获取余额
    public function getBalance(): Money {
        return $this->balance;
    }
}
// 交易记录
class Transaction {
    const TYPE_DEPOSIT = 'deposit';
    const TYPE_WITHDRAWAL = 'withdrawal';
    const TYPE_TRANSFER = 'transfer';
    const TYPE_EXCHANGE = 'exchange';
    private string $transactionId;
    private string $accountId;
    private Money $amount;
    private string $type;
    private DateTime $createdAt;
    public function __construct(string $accountId, Money $amount, string $type) {
        $this->transactionId = uniqid('txn_', true);
        $this->accountId = $accountId;
        $this->amount = $amount;
        $this->type = $type;
        $this->createdAt = new DateTime();
    }
}

货币兑换功能

<?php
// 货币兑换服务
class CurrencyExchangeService {
    private CurrencyConversionService $conversionService;
    public function __construct(CurrencyConversionService $conversionService) {
        $this->conversionService = $conversionService;
    }
    // 账户间兑换
    public function exchange(
        Account $fromAccount, 
        Account $toAccount, 
        Money $amount
    ): array {
        if ($fromAccount->getBalance()->getCurrency() === 
            $toAccount->getBalance()->getCurrency()) {
            throw new InvalidArgumentException("不能兑换相同货币");
        }
        // 从源账户取款
        $withdrawalTransaction = $fromAccount->withdraw($amount);
        // 转换货币
        $targetCurrency = $toAccount->getBalance()->getCurrency();
        $convertedAmount = $this->conversionService->convert(
            $amount, 
            $targetCurrency
        );
        // 存入目标账户
        $depositTransaction = $toAccount->deposit($convertedAmount);
        return [$withdrawalTransaction, $depositTransaction];
    }
}

使用示例

<?php
// 使用示例
try {
    // 创建账户
    $nokAccount = new Account('user1', CurrencyConfig::NOK);
    $enokAccount = new Account('user1', CurrencyConfig::ENOK);
    // 存入NOK
    $depositAmount = new Money(1000.50, CurrencyConfig::NOK);
    $nokAccount->deposit($depositAmount);
    echo "NOK余额: " . $nokAccount->getBalance()->format() . "\n";
    // 输出: 1 000,50 kr
    // 存入eNOK
    $enokDeposit = new Money(500.00, CurrencyConfig::ENOK);
    $enokAccount->deposit($enokDeposit);
    echo "eNOK余额: " . $enokAccount->getBalance()->format() . "\n";
    // 输出: 500,00 e-kr
    // 货币兑换
    $exchangeService = new CurrencyExchangeService(
        new CurrencyConversionService()
    );
    $exchangeAmount = new Money(200.00, CurrencyConfig::NOK);
    $transactions = $exchangeService->exchange(
        $nokAccount, 
        $enokAccount, 
        $exchangeAmount
    );
    echo "兑换后NOK余额: " . $nokAccount->getBalance()->format() . "\n";
    echo "兑换后eNOK余额: " . $enokAccount->getBalance()->format() . "\n";
} catch (Exception $e) {
    echo "错误: " . $e->getMessage() . "\n";
}

注意事项

  1. 精度处理: 使用 round() 函数确保货币精度
  2. 不可变对象: Money 类设计为不可变,确保数据安全
  3. 类型安全: 严格检查货币类型,防止错误操作
  4. 汇率更新: 实际应用中汇率需要定期更新
  5. 数据库存储: 建议使用 DECIMAL 类型存储金额
  6. 审计日志: 所有货币操作应记录详细日志

这个实现提供了完整的挪威克朗与电子克朗处理功能,包括创建、转换、交易等核心操作。

抱歉,评论功能暂时关闭!