phpcfdi/finkok

用于连接 FINKOK 服务 API 的库

v0.5.5 2024-05-24 19:18 UTC

README

Source Code Latest Version Software License Build Status Scrutinizer Coverage Status Total Downloads

用于连接 FINKOK 服务 API(墨西哥)的库

🇺🇸 本项目的文档是西班牙语,因为这是目标受众的自然语言。

关于 phpcfdi/finkok

这个库是 https://www.phpcfdi.com/ 社区为了有一个可以利用 FINKOK 集成商提供的功能而做出的努力。

与 Finkok 无关,Finkok 是 FINKOK, SAPI DE CV 的注册商标。

安装

使用 composer

composer require phpcfdi/finkok

基本用法示例

use PhpCfdi\Finkok\FinkokEnvironment;
use PhpCfdi\Finkok\FinkokSettings;
use PhpCfdi\Finkok\QuickFinkok;

$settings = new FinkokSettings('user@host.com', 'secret', FinkokEnvironment::makeProduction());
$finkok = new QuickFinkok($settings);

// el PreCFDI a firmar, podría venir de CfdiUtils ;) $creator->asXml()
$precfdi = file_get_contents('precfdi-to-sign.xml');

$stampResult = $finkok->stamp($precfdi); // <- aquí contactamos a Finkok

if ($stampResult->hasAlerts()) { // stamp es un objeto con propiedades nombradas
    foreach ($stampResult->alerts() as $alert) {
        echo $alert->id() . ' - ' . $alert->message() . PHP_EOL;
    }
} else {
    file_put_contents($stampResult->uuid() . '.xml', $stampResult->xml()); // CFDI firmado
}

还有其他解释性的示例

以及所有集成测试,其中测试了与测试平台的通信和响应。

建议使用 PhpCfdi\Finkok\QuickFinkok 类快速使用 finkok 命令,不过也可以使用完全显式和粒度化的 命令服务结果 模式。

实现的方法

该库使用基于命令、服务和结果的模型。命令是对我们想要执行的操作的定义,包含所有必要的参数。服务负责使用该命令作为输入,在 Finkok(通过 SOAP)中执行它,并根据响应构建结果。结果是表示响应的数据。

我们没有有意实现需要传输 CSD(数字签名证书)或 eFirma/FIEL(电子签名)的私钥的命令。我们不认为我们会实现它们,因为 a) 不需要,b) 不安全。

打印服务

Finkok 有两种签名方法:stampquickstamp

  • stamp(Stamping\StampingCommand $command): Stamping\StampingResult
  • quickstamp(Stamping\StampingCommand $command): Stamping\StampingResult

用于检查是否已生成 CFDI 的 stamped 服务

  • stamped(Stamping\StampingCommand $command): Stamping\StampingResult

如果使用 pending buffer,则使用 stampQueryPending

  • stampQueryPending(Stamping\QueryPendingCommand $command): Stamping\QueryPendingResult

取消服务

只能使用 cancelSignature 通过这个库取消 CFDI,因为这是唯一不需要传输机密信息的命令。

  • cancelSignature(Cancel\CancelSignatureCommand $command): Cancel\CancelSignatureResult

您可以使用 getSatStatus 查询 CFDI 的状态(取消前后)

  • getSatStatus(Cancel\GetSatStatusCommand $command): Cancel\GetSatStatusResult

您可以使用 getCancelReceipt 获取取消请求的 SAT 最后收据。虽然请记住,拥有收据并不意味着已取消,收据只包含提交给 SAT 的取消响应。

  • getCancelReceipt(Cancel\GetReceiptResult $command): Cancel\GetReceiptResult

通过 getPendingToCancel 可以获取由接收方待取消的 CFDI 列表。

  • getPendingToCancel(Cancel\GetPendingCommand $command): Cancel\GetPendingResult

可以通过使用 getRelatedSignature 获取相关子项(与查询的 UUID 相关)和父项(与查询的 UUID 相关联)。正如 cancelSignature 方法一样,此方法需要签名消息。

  • getRelatedSignature(Cancel\GetRelatedSignatureCommand $command): Cancel\GetRelatedSignatureResult

此外,可以使用 acceptRejectSignature 接受或拒绝取消请求。此方法可以处理多个 UUID,但 Finkok 建议一次只执行一个。与 cancelSignature 方法一样,此方法需要签名消息。

  • acceptRejectSignature(Cancel\AcceptRejectSignatureCommand $command): Cancel\AcceptRejectSignatureResult

工具和客户管理

获取 Finkok 的时间(如果遇到 CFDI 时间问题)

  • datetime(): Utilities\DatetimeResult

获取过去 3 个月内使用 Finkok 签署的 CFDI

  • downloadXml(Utilities\DownloadXmlCommand $command): Utilities\DownloadXmlResult

获取信用消费和客户管理报告

  • reportCredit(Utilities\ReportCreditCommand $command): Utilities\ReportCreditResult
  • reportTotal(Utilities\ReportTotalCommand $command): Utilities\ReportTotalResult
  • reportUuid(Utilities\ReportUuidCommand $command): Utilities\ReportUuidResult
  • registrationAdd(Registration\AddCommand $command): Registration\AddResult
  • registrationAssign(Registration\AssignCommand $command): Registration\AssignResult
  • registrationEdit(Registration\EditCommand $command): Registration\EditResult
  • registrationSwitch(Registration\SwitchCommand $command): Registration\SwitchResult
  • registrationObtain(Registration\ObtainCommand $command): Registration\ObtainResult
  • registrationCustomers(Registration\ObtainCustomersCommand $command): Registration\ObtainCustomersResult

清单和合同

获取合同和发送签名分别使用 getContractssignContracts

  • getContracts(Manifest\GetContractsCommand $command): Manifest\GetContractsResult
  • signContracts(Manifest\SignContractsCommand $command): Manifest\SignContractsResult

扣缴

扣缴 CFDI 和付款信息(RET)遵循与 CFDI 3.2 更相似的标准。其取消是即时的(与当前的取消请求不同)。

  • stamp(Retentions\StampCommand $command): Retentions\StampResult
  • stamped(Retentions\StampedCommand $command): Retentions\StampedResult
  • cancelSignature(Retentions\CancelSignatureCommand $command): Retentions\StampedResult

要下载扣缴,应使用预先实现的 Utilerias 服务中的 get_xml 方法。同样,已创建 QuickFinkok::retentionDownload($uuid, $rfc) 方法以简化其实施。

为 SAT 和 Finkok 签署 XML 的帮助

此库实现了与 SAT 消息的 CSD 签署以取消、获取相关 UUID 和接受或拒绝取消请求。创建签名 XML 所涉及的所有逻辑都位于库 phpcfdi/xml-cancelacion 中。

它还实现了与 Finkok 的 清单 的 FIEL 签署。

为这些任务创建了以下对象,以允许执行签名信息

  • Helpers\CancelSigner:帮助签署取消请求。
  • Helpers\GetRelatedSigner:帮助签署相关 UUID 信息请求。
  • Helpers\AcceptRejectSigner:帮助签署单个 UUID 的取消响应。
  • Helpers\DocumentSigner:帮助签署 Finkok 的 清单 文档。

此外,这些方法使用库 phpcfdi/credentials 来创建 SAT 或 Finkok 所需的签名和信息。

QuickFinkok 类节省了签署请求数据的过程,并自动执行,但以下示例显示了使用证书和私钥在文件中签署单个 UUID 取消请求的过程。

use PhpCfdi\Credentials\Credential;
use PhpCfdi\Finkok\Helpers\CancelSigner;
use PhpCfdi\Finkok\Services\Cancel\CancelSignatureCommand;

// el objeto con el que se van a firmar las solicitudes
$credential = Credential::openFiles('certificate.cer', 'privateKey.pem', 'password');

// el firmador de datos
$signer = new CancelSigner(['11111111-2222-3333-4444-000000000001']);
$signedXml = $signer->sign($credential);

// el comando a pasar al método Finkok::cancelSignature o al comando CancelSignatureService
$cancelCommand = new CancelSignatureCommand($signedXml);

实现说明

在实施过程中,我创建了各种笔记和文档

捕获HTTP会话

有时,在向Finkok报告问题时,我们需要HTTP会话(请求响应)以便检查发送的信息。

此库使用PSR-3: Logger Interface生成消息,并在SoapFactory对象内使用,以创建SoapCaller对象。此对象发送两种类型的信息:LogLevel::ERROR在建立服务通信时发生错误,以及LogLevel::DEBUG在执行SOAP调用时。这两种信息都表示为JSON格式的字符串,因此,为了便于阅读,解码它很重要。

JSON格式更好,因为它允许分析文本并找到特殊字符,而将它们转换为更易于人类理解的文字时,这些特殊字符可能会被隐藏或错误解释。

提供PhpCfdi\Finkok\Helpers\FileLogger类作为LoggerInterface的实用工具,将接收到的消息发送到标准输出或文件。

还提供PhpCfdi\Finkok\Helpers\JsonDecoderLogger类作为LoggerInterface的实用工具,它解码JSON消息并将其转换为字符串,然后使用print_r()将其发送到另一个LoggerInterface对象。

以下示例显示了设置Logger对象的建议方法,还显示了使用JsonDecoderLogger将JSON转换为文本以及使用FileLogger将消息发送到特定文件的方法。

JsonDecoderLogger可能会丢失信息,但消息更易于理解。如果也想包含JSON消息,可以使用JsonDecoderLogger::setAlsoLogJsonMessage(true)

use PhpCfdi\Finkok\FinkokEnvironment;
use PhpCfdi\Finkok\FinkokSettings;
use PhpCfdi\Finkok\Helpers\FileLogger;
use PhpCfdi\Finkok\Helpers\JsonDecoderLogger;

$logger = new JsonDecoderLogger(new FileLogger('/tmp/finkok.log'));
$logger->setAlsoLogJsonMessage(true); // enviar en texto simple y también en formato JSON

$settings = new FinkokSettings('user@host.com', 'secret', FinkokEnvironment::makeProduction());
$settings->soapFactory()->setLogger($logger);

如果您使用Laravel,则已经具有LoggerInterface的实现,因此建议使用

/** @var \Psr\Log\LoggerInterface $logger */
$logger = app(\Psr\Log\LoggerInterface::class);

// Encapsular el logger en el decodificador JSON:
$logger = new \PhpCfdi\Finkok\Helpers\JsonDecoderLogger($logger);

兼容性

此库将保持与最新的具有PHP活跃支持版本的兼容性。

我们还使用了语义化版本 2.0.0,因此你可以使用这个库而不用担心破坏你的应用程序。

贡献

欢迎贡献。请阅读CONTRIBUTING以获取更多详细信息,并记得查看待办事项文件TODO以及变更日志文件CHANGELOG

版权和许可

phpcfdi/finkok库的版权© PhpCfdi,并许可在MIT许可证(MIT)下使用。请参阅LICENSE以获取更多信息。