PHP项目数字印尼盾与eIDR

wen PHP项目 1

本文目录导读:

PHP项目数字印尼盾与eIDR

  1. 基础概念
  2. PHP 数字处理方案
  3. 大数字处理(防止溢出)
  4. 数据库设计
  5. 交易处理类
  6. 前端展示与交互
  7. 安全注意事项
  8. 推荐使用的库

我来为您详细解释PHP项目中处理数字印尼盾(IDR)和eIDR(电子印尼盾/数字货币印尼盾)的相关技术实现。

基础概念

数字印尼盾 vs eIDR

类型 描述 特点
IDR 传统印尼盾 法定货币,面额大,需处理大数字
eIDR 电子印尼盾(数字货币) 通常以更小单位存储,需处理精度

PHP 数字处理方案

金额存储与格式化

<?php
class IDRHandler {
    // 印尼盾格式化(带千分位)
    public static function formatIDR($amount, $decimal = 0) {
        return 'Rp ' . number_format($amount, $decimal, ',', '.');
    }
    // eIDR格式化(通常有小数位)
    public static function formatEIDR($amount, $decimal = 2) {
        return number_format($amount, $decimal, '.', ',');
    }
    // 转换eIDR到IDR(假设1 eIDR = 1 IDR)
    public static function eIDRToIDR($eidrAmount) {
        return (int) round($eidrAmount);
    }
    // IDR转eIDR
    public static function IDRToEIDR($idrAmount) {
        return (float) $idrAmount;
    }
}
echo IDRHandler::formatIDR(1500000); // Rp 1.500.000
echo IDRHandler::formatEIDR(1500000.50); // 1,500,000.50
?>

大数字处理(防止溢出)

印尼盾面额大,需使用高精度处理:

<?php
use Brick\Math\BigDecimal;
use Brick\Math\RoundingMode;
class IDRBigMath {
    // 使用BCMath或BigDecimal处理大数字
    public static function add($amount1, $amount2) {
        return bcadd($amount1, $amount2, 2);
    }
    public static function multiply($amount, $rate) {
        return bcmul($amount, $rate, 2);
    }
    public static function format($amount, $currency = 'IDR') {
        if ($currency === 'IDR') {
            return 'Rp ' . number_format((int)$amount, 0, ',', '.');
        }
        return number_format((float)$amount, 2, '.', ',');
    }
}
// 处理大额交易
$purchase = '1000000000000'; // 1万亿
$tax = bcmul($purchase, '0.11', 2); // 11%税
echo IDRBigMath::format($tax); // Rp 110.000.000.000
?>

数据库设计

MySQL 表结构

-- 账户表
CREATE TABLE accounts (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id BIGINT,
    balance_idr DECIMAL(20,2) DEFAULT 0.00,  -- IDR余额
    balance_eidr DECIMAL(20,8) DEFAULT 0.00000000, -- eIDR余额(更高精度)
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 交易记录表
CREATE TABLE transactions (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    transaction_id VARCHAR(36) UNIQUE,
    from_account BIGINT,
    to_account BIGINT,
    amount DECIMAL(20,2),      -- IDR金额
    amount_eidr DECIMAL(20,8), -- eIDR金额(如果需要)
    currency ENUM('IDR', 'eIDR') NOT NULL,
    status ENUM('pending', 'completed', 'failed') DEFAULT 'pending',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 汇率表(如果eIDR与IDR不同)
CREATE TABLE exchange_rates (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    from_currency VARCHAR(10),
    to_currency VARCHAR(10),
    rate DECIMAL(20,8),
    effective_date DATE
);

交易处理类

<?php
class EIDRTransaction {
    private $db;
    private $precision = 8; // eIDR精度
    public function __construct($dbConnection) {
        $this->db = $dbConnection;
    }
    // IDR转账
    public function transferIDR($fromUserId, $toUserId, $amount) {
        try {
            $this->db->beginTransaction();
            // 检查余额
            $fromBalance = $this->getBalanceIDR($fromUserId);
            if ($fromBalance < $amount) {
                throw new Exception("IDR余额不足");
            }
            // 扣款
            $this->updateBalanceIDR($fromUserId, -$amount);
            // 加款
            $this->updateBalanceIDR($toUserId, $amount);
            // 记录交易
            $this->recordTransaction([
                'from' => $fromUserId,
                'to' => $toUserId,
                'amount' => $amount,
                'currency' => 'IDR'
            ]);
            $this->db->commit();
            return true;
        } catch (Exception $e) {
            $this->db->rollback();
            throw $e;
        }
    }
    // eIDR转账(带精度处理)
    public function transferEIDR($fromUserId, $toUserId, $eidrAmount) {
        $eidrAmount = number_format((float)$eidrAmount, $this->precision, '.', '');
        try {
            $this->db->beginTransaction();
            $fromBalance = $this->getBalanceEIDR($fromUserId);
            if (bccomp($fromBalance, $eidrAmount, $this->precision) < 0) {
                throw new Exception("eIDR余额不足");
            }
            $this->updateBalanceEIDR($fromUserId, '-' . $eidrAmount);
            $this->updateBalanceEIDR($toUserId, $eidrAmount);
            $this->recordTransaction([
                'from' => $fromUserId,
                'to' => $toUserId,
                'amount_eidr' => $eidrAmount,
                'currency' => 'eIDR'
            ]);
            $this->db->commit();
            return true;
        } catch (Exception $e) {
            $this->db->rollback();
            throw $e;
        }
    }
    // 获取IDR余额
    private function getBalanceIDR($userId) {
        $stmt = $this->db->prepare("SELECT balance_idr FROM accounts WHERE user_id = ?");
        $stmt->execute([$userId]);
        return $stmt->fetchColumn();
    }
    // 获取eIDR余额
    private function getBalanceEIDR($userId) {
        $stmt = $this->db->prepare("SELECT balance_eidr FROM accounts WHERE user_id = ?");
        $stmt->execute([$userId]);
        return $stmt->fetchColumn();
    }
    // 更新IDR余额
    private function updateBalanceIDR($userId, $amount) {
        $stmt = $this->db->prepare(
            "UPDATE accounts SET balance_idr = balance_idr + ? WHERE user_id = ?"
        );
        $stmt->execute([$amount, $userId]);
    }
    // 更新eIDR余额(使用字符串避免精度问题)
    private function updateBalanceEIDR($userId, $amount) {
        $stmt = $this->db->prepare(
            "UPDATE accounts SET balance_eidr = balance_eidr + CAST(? AS DECIMAL(20,8)) WHERE user_id = ?"
        );
        $stmt->execute([$amount, $userId]);
    }
    private function recordTransaction($tx) {
        $stmt = $this->db->prepare(
            "INSERT INTO transactions (transaction_id, from_account, to_account, amount, amount_eidr, currency) 
             VALUES (UUID(), ?, ?, ?, ?, ?)"
        );
        $stmt->execute([
            $tx['from'],
            $tx['to'],
            $tx['amount'] ?? 0,
            $tx['amount_eidr'] ?? 0,
            $tx['currency']
        ]);
    }
}
?>

前端展示与交互

<?php
// 在视图中使用
$idrAmount = 1500000;
$eidrAmount = 1.50000000;
echo "传统显示: " . number_format($idrAmount, 0, ',', '.') . " IDR\n";
echo "科学显示: " . number_format($eidrAmount, 2, ',', '.') . " eIDR\n";
echo "智能显示: " . ((int)$idrAmount >= 1000) ? 
     number_format($idrAmount/1000000, 1) . " Juta IDR" : 
     number_format($idrAmount, 0, ',', '.') . " IDR";
?>

安全注意事项

  1. 浮点运算问题:始终使用 BCMathDecimal
  2. 输入验证:严格验证数字格式,防止注入
  3. 事务管理:所有金额操作使用数据库事务
  4. 日志记录:记录所有金额变更操作

推荐使用的库

# 安装高精度数学库
composer require brick/math
composer require moneyphp/money

关键要点

  • 大金额用 DECIMAL 类型存储
  • 使用 bcmath 扩展进行运算
  • eIDR 可能需要更高精度(8-10位小数)
  • 始终使用事务保证数据一致性

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