本文目录导读:

在 PHP 项目中实现发票电子化,通常涉及开具、存储、版式文件生成、查验、以及符合税务规范这几个核心环节,由于中国(以及许多国家)的电子发票有严格的格式和验签标准,实现方式主要分为调用第三方服务和自研底层两种路径。
以下是详细的实现方案和技术选型建议:
首选方案:接入第三方电子发票平台(推荐)
绝大多数企业项目采用此方案,原因在于税局接口复杂、频繁更新(如数电票),自己维护成本极高。
常见平台
- 官方平台:国家税务总局的电子发票服务平台(针对数电票)。
- 第三方服务商:票通、百望云、诺诺网、高灯科技、腾讯云发票、阿里云发票等。
实现流程(以 PHP 为例)
- 发票申请:订单完成后,系统调用第三方 SDK/API 申请开票。
- 参数准备:传递订单号、购买方信息(抬头/税号)、商品明细、含税金额等。
- 开具:第三方平台向税局系统提交请求,生成电子发票版式文件(OFD/PDF/XML)。
- 获取结果:接口返回发票号码、校验码、版式文件下载 URL、发票数据。
- 分发:将发票下载链接或PDF文件通过邮件、APP推送、公众号发送给客户。
PHP 集成代码示例(伪代码)
<?php
// 使用 GuzzleHttp 或 curl 调用第三方发票 API
function createInvoice($orderData) {
$appKey = 'your_app_key';
$appSecret = 'your_app_secret';
// 构造请求参数(以票通/百望为例)
$params = [
'order_sn' => $orderData['order_sn'],
'buyer_name' => $orderData['buyer_name'],
'buyer_tax_no' => $orderData['buyer_tax_no'],
'invoice_type' => 'special', // 专票/普票
'amount' => $orderData['amount'],
'items' => [
['name' => '商品A', 'quantity' => 1, 'price' => 100, 'tax_rate' => 13]
],
'callback_url' => 'https://yourdomain.com/invoice/callback' // 异步回调地址
];
// 发送POST请求
$response = $client->post('https://api.thirdparty.com/invoice/create', [
'json' => $params,
'headers' => ['Authorization' => 'Bearer '.$appKey]
]);
$result = json_decode($response->getBody(), true);
// 将发票记录存入数据库
DB::table('invoices')->insert([
'order_sn' => $orderData['order_sn'],
'invoice_no' => $result['invoice_no'],
'status' => 'pending', // 等待开票回调
'raw_data' => json_encode($result),
'pdf_url' => $result['pdf_url'] ?? ''
]);
return $result;
}
- 回调处理:第三方平台开票成功后,会 POST 请求到
callback_url,更新数据库发票状态为success,并通知业务方。
进阶方案:自研实现(适用于大型企业或有特殊需求)
如果你需要完全掌控发票生成流程,或者需要离线开具,可以考虑自研。
核心技术点
- OFD 文档生成:国家推荐标准(GB/T 33590-2017),支持国密算法(SM2/SM3),PHP 可以使用
TCPDF(但仅支持PDF),生成 OFD 需要额外库或调用 Java/C# 组件。 - XML 数据结构:税局要求的格式(如金税四期标准)。
- 数字签名:使用税务 UKey(税控盘或税务云证书)对发票数据进行签名。
- 税局上报:定期将开具发票汇总数据加密上传至税局。
PHP 实现注意点
- 使用扩展:
openssl处理签名,php-gmp或php-bcmath处理大数运算(国密算法需要)。 - PDF/OFD 生成:
- PDF:
TCPDF、FPDF、Dompdf,但金四后逐渐不推荐使用 PDF 作为正式发票。 - OFD:PHP 原生支持较弱,常见做法是使用 Java/Swoole 子进程生成,或调用命令行工具(如
LibreOffice转换)。 - HTML转PDF:使用
wkhtmltopdf配合xpath处理定位。
- PDF:
- 签名验签:需要引入国密算法库(如
lizhichao/one-sm或northton/sm-crypto)。
关键功能模块设计(无论选哪种方案)
在 PHP 项目中,你需要设计以下核心表结构:
-- 发票主表 CREATE TABLE `invoices` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `order_sn` varchar(32) NOT NULL COMMENT '订单号', `invoice_no` varchar(20) DEFAULT NULL COMMENT '发票号码', `invoice_code` varchar(20) DEFAULT NULL COMMENT '发票代码(数电票可为空)', `buyer_name` varchar(100) NOT NULL COMMENT '购买方名称', `buyer_tax_no` varchar(20) DEFAULT NULL COMMENT '纳税人识别号', `amount` decimal(10,2) NOT NULL COMMENT '含税金额', `tax_amount` decimal(10,2) NOT NULL COMMENT '税额', `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0待开具 1成功 2失败 3红冲', `pdf_url` varchar(255) DEFAULT NULL COMMENT '版式文件地址', `xml_data` longtext COMMENT '发票原始XML数据', `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_order_sn` (`order_sn`), KEY `idx_invoice_no` (`invoice_no`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
- 发票项表:存储商品明细(名称、规格、单位、数量、单价、税率、税额)。
- 红冲记录表:记录原发票红冲(负数发票)的关联关系。
税金与财务处理注意事项
- 税率管理:不同商品/服务税率不同(13%、9%、6%、0%等),建议在商品SKU层级预制税率。
- 含税/不含税计算:PHP 处理浮点运算应使用
bcmath函数进行精确计算,避免精度丢失。$price = '100.00'; // 含税单价 $quantity = '2'; $taxRate = '0.13'; // 13% $amountExcludingTax = bcdiv($price, bcadd(1, $taxRate, 4), 2); $taxAmount = bcsub($price, $amountExcludingTax, 2);
- 库存核对:电子发票通常以订单为粒度开具,但要保证发票金额不超过订单实付金额。
- 断号处理:如果连续开票有失败,需要记录失败的票据状态(如
failed),税局要求发票号码不能跳号丢弃。
技术栈与性能建议
- 开发框架:Laravel 或 Hyperf(协程版,适合高并发场景)。
- 队列处理:建议将开票请求放入消息队列(如 RabbitMQ、Redis Queue),避免接口超时阻塞业务。
- 日志审计:所有税务接口调用(请求/响应/错误)必须记录日志,以备税务稽查。
- 存储方案:
- 发票版式文件(PDF/OFD)建议存 OSS 或 S3,加速客户下载。
- 发票 XML 数据(包含签名)需保留至少10年,建议存数据库或归档存储。
- 安全建议:购买方信息(邮箱、手机号)用于发送发票,需脱敏处理;税务UKey密码、第三方API密钥需加密存储(如 Laravel 的
env或配置管理工具)。
常见问题与解决方案(FQA)
Q:如何防止重复开票?
A:在数据库 invoices 表中对 order_sn 加唯一索引,开票前先校验订单是否已开具。
Q:发票抬头校验怎么做? A:调用税局接口或第三方平台的企业名称模糊匹配接口(部分服务商提供),避免非正常发票。
Q:发票如何红冲(作废)? A:原发票开具当月可以直接作废(部分平台支持),跨月需要填开红字信息表并申请红冲,接口通常需要提供原发票号码、代码、金额。
Q:数电票(全电发票)有何不同? A
- 不需要税控盘,直接使用税局电子发票平台。
- 版式文件为 OFD/PDF,但推荐 OFD。
- 没有发票代码,只有发票号码(20位)。
- XML 是唯一合法入账凭证(PDF只是展示)。
实现路线图
- 调研阶段:选择一家成熟的第三方服务商(如百望云/票通),确认支持你的业务场景(专票/普票/电子票/数电票)。
- 开发阶段:集成 PHP SDK/API,设计数据库表,处理异步回调。
- 测试阶段:使用沙箱环境测试开具、冲红、查询功能,注意测试不同税率、含税/不含税金额计算。
- 上线阶段:配置生产环境 API 参数,开启队列消费,24小时监控开票成功率。
- 维护阶段:关注税局政策变化(特别是金税四期数电票推广),及时更新API版本。
如果你只有1-2个项目的发票需求,强烈建议使用第三方服务,如果团队有税务业务开发经验且预算充足,再考虑自研。