本文目录导读:

针对PHP项目中处理波兰兹罗提(PLN) 以及其电子形式ePLN(通常指电子发票或收据格式)的需求,以下是一些核心的技术实现思路与最佳实践建议。
货币处理(PLN)
基本格式与精度
波兰兹罗提使用两位小数(格罗希,Grosz)。
PHP 中避免使用 float 进行财务计算,推荐使用 int(以格罗希为单位)或 BCMath。
// 以格罗希为单位存储(推荐)
$amountGroszy = 1999; // 19.99 PLN
// 显示格式化
function formatPLN(int $groszy): string {
$zloty = number_format($groszy / 100, 2, ',', ' ');
return $zloty . ' PLN';
}
echo formatPLN(1999); // "19,99 PLN"
国际化与本地化(ICU)
使用 NumberFormatter 实现正确的波兰语区域格式(包括空格分隔千位,逗号小数)。
$fmt = new NumberFormatter('pl_PL', NumberFormatter::CURRENCY);
echo $fmt->formatCurrency(19.99, 'PLN'); // "19,99 zł"
高精度计算(BCMath)
$price = '19.99';
$tax = '0.23';
$total = bcmul($price, bcadd('1', $tax, 4), 2); // "24.58"
电子发票 / ePLN 格式处理
ePLN(Elektroniczny Potwierdzenie Nadania / Faktura)在波兰通常指 JPK_FA(Jednolity Plik Kontrolny dla Faktur)或 Faktura XML(基于KSeF标准)。
生成标准ePLN XML(KSeF兼容)
波兰国家税务局(KSeF)自2024年起要求部分企业强制使用结构化发票,PHP 生成XML的典型结构:
$dom = new DOMDocument('1.0', 'UTF-8');
$root = $dom->createElementNS('http://ksef.mf.gov.pl/schema/gtw/svc/online/types/2021/10/01/0001', 'KSeFInvoice');
// 发票编号
$nr = $dom->createElement('InvoiceNumber', 'FA/2025/001');
// 金额(净额、税率、总额)必须精确到格罗希
$net = $dom->createElement('NetAmount', '100.00');
$vat = $dom->createElement('VatAmount', '23.00');
$gross = $dom->createElement('GrossAmount', '123.00');
// 税码(23% -> PTU B)
$taxRate = $dom->createElement('VatRate', 'PTU_B');
// 数字签名(可选,KSeF要求电子签名)
注意:KSeF要求发票通过官方API提交,直接生成XML后需要使用企业数字签名(电子印章 / Podpis elektroniczny)。
ePLN 支付处理(银行转账单)
ePLN(Elektroniczne Polecenie Przelewu)一般是银行标准转账单(Elixir / SEPA),PHP处理:
生成转账单(PayByLink / QR)
使用波兰标准 BLIK 或 Przelewy24, PayU 等支付网关API。
// 生成标准转账单结构
$transfer = [
'receiver' => 'Firma XYZ Sp. z o.o.',
'receiverBank' => '12 1234 1234 1234 1234 1234 1234', // NRB (26 digits)
'amount' => '123.00', => 'Faktura FA/2025/001',
'dueDate' => '2025-03-15',
];
// 生成PayByLink URL(示例:Przelewy24)
$p24Client = new Przelewy24Client();
$paymentUrl = $p24Client->createTransaction([
'sessionId' => uniqid(),
'amount' => $transfer['amount'] * 100, // 格罗希
'currency' => 'PLN',
'description' => $transfer['title'],
'email' => $customerEmail,
]);
验证波兰银行账号(NRB)
function validateNRB(string $nrb): bool {
$nrb = preg_replace('/\s+/', '', $nrb);
if (strlen($nrb) !== 26) return false;
// 转换为 IBAN (PL + 2位校验码 + NRB)
$iban = 'PL' . $nrb;
return iban_validate($iban); // 使用现有IBAN验证库
}
法规与合规建议
| 要求 | PHP实现要点 |
|---|---|
| 增值税计算(23%, 8%, 5%, 0%) | 使用 enum 或配置表存储税率,BCMath确保精度 |
| 千分位空格分隔 | number_format(1999.00, 2, ',', ' ') |
| 发票存档(JPK) | 生成标准JPK_FA XML,使用ZIP压缩并摘要签名 |
| 与KSeF集成 | 调用SOAP/REST API(需Guzzle或SoapClient,并配置SSL客户端证书) |
示例:完整的PLN金额处理类
class MoneyPLN {
private int $groszy;
public function __construct(int $groszy) {
$this->groszy = $groszy;
}
public static function fromFloat(float $amount): self {
return new self((int) round($amount * 100));
}
public function getAmount(): float {
return $this->groszy / 100.0;
}
public function format(): string {
return number_format($this->groszy / 100, 2, ',', ' ') . ' zł';
}
public function add(self $other): self {
return new self($this->groszy + $other->groszy);
}
// 增值税计算
public function applyVat(float $rate): self {
$vat = bcmul((string) $this->groszy, (string) $rate, 0);
// BCmath 保留0位小数,因为groszy是整数
return new self($this->groszy + (int) $vat);
}
}
// 使用
$price = MoneyPLN::fromFloat(99.99);
echo $price->format(); // "99,99 zł"
常用PHP库推荐
| 用途 | 推荐库 |
|---|---|
| 货币计算 | moneyphp/money (支持PLN货币对象) |
| 国际化格式化 | ext-intl (PHP内置) |
| XML生成 | DOMDocument 或 SimpleXML |
| KSeF集成 | mpetrovich/ksef-sdk (第三方开源) |
| 银行账号验证 | malkusch/bav (德国/波兰银行验证库) |
注意事项
- ePLN 背景:在波兰数字金融语境中,“ePLN”可能指:
- 电子发票(JPK / KSeF)
- 电子银行转账命令
- 加密货币ePLN(较少见,需确认上下文)
- 时区:波兰为
Europe/Warsaw,发票时间需使用DateTimeZone确保夏令时正确。 - 库存单位:商品价格必须精确到 01 PLN,不允许舍入误差。
如果您的项目涉及KSeF强制电子发票(2024-2026年分期实施),请确保代码中包含 数字签名的生成 和 与政府API的HTTPS双向认证。