本文目录导读:

我来为您详细解释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";
?>
安全注意事项
- 浮点运算问题:始终使用
BCMath或Decimal类 - 输入验证:严格验证数字格式,防止注入
- 事务管理:所有金额操作使用数据库事务
- 日志记录:记录所有金额变更操作
推荐使用的库
# 安装高精度数学库 composer require brick/math composer require moneyphp/money
关键要点:
- 大金额用
DECIMAL类型存储 - 使用
bcmath扩展进行运算 - eIDR 可能需要更高精度(8-10位小数)
- 始终使用事务保证数据一致性
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播