sj_royd / efaktura_service
Requires
- guzzlehttp/guzzle: ^6.0
- netresearch/jsonmapper: ^1.4
Suggests
- sj_royd/efaktura_documents: HTML/XML Generator and XML parser for eFaktura documents
README
该库允许您下载并发送文档到电子发票平台(PEF)(https://efaktura.gov.pl/)。
PEF 适用于谁
电子发票平台(PEF)用于在公共采购承包商和招标当局之间转发发票和其他结构化文档。服务由两个PEF经纪人并行提供。
已根据PEPPOL BIS 3.0和CEFACT指南准备了已发送文档的实现。
1. 安装
$ composer require sj_royd/efaktura_service
2. 使用
<?php
use SJRoyd\PEF\PEF;
use SJRoyd\PEF\Error;
try {
$pefID = 'user id'; // API user ID
$pefSecret = 'user secret'; // API user secret
$pefService = PEF::BROKER_INFINITE; // available PEF::BROKER_PEFEXPERT or PEF::BROKER_INFINITE
$pef = new PEF($pefID, $pefSecret, $pefService);
$queueLength = 0;
do {
// gets the first message from the queue
$msgGeneral = $pef->queue->getMessage();
$msg = $msgGeneral->getMessage();
// gets the number of messages in the queue
$queueLength = $pef->queue->getQueueLength();
// if the message exists
if($msg){
// if the message indicates the existence of a document
if($msgGeneral->getDocumentContent){
// gets the content of the document
$content = $pef->document->getDocumentContent($msg->documentId);
// sets the status of the document to read
$pef->document->readDocument($msg->documentId);
// do something with the document, ex. save in a storage
}
// sets the status of the message to read last
// because document->getDocumentContent() can throw
// an Error\ClientError or Error\ServerError and we
// can go back to the message next time
$pef->queue->sendMessageAck($msg->messageId);
}
} while($queueLength > 1);
} catch (Error\AuthError $ex) {
echo 'Auth error';
} catch (Error\ClientError $ex) {
echo 'Client error';
} catch (Error\ServerError $ex) {
echo 'Server error';
}
3. 操作
getMessage()
等待消息队列;位置$pef->queue
对于外部系统(标识为外部系统帐户),PEF系统维护一个指向它的消息队列。操作允许下载队列中的第一条消息。再次调用此操作将返回相同的消息,直到外部系统使用
sendMessageAck()
操作确认已正确处理该消息。sendMessageAck()
确认接收消息;位置$pef->queue
操作允许确认最后下载的消息已被正确处理。调用此操作后,将会有新的消息(如果有的话)出现在消息队列中。调用此操作也意味着接收文档(在关于新传入文档的消息的上下文中)。
getQueueLength()
队列中消息的数量;位置$pef->queue
操作返回在执行操作
getMessage()
后队列中等待的消息数量。sendDocument()
发送文档;位置$pef->document
操作允许将文档发送到PEF系统。
您可以选择发送以下六种文档类型之一 - 辅助
Document\Type
文档以Ubl或Cefact格式提供 - 辅助
Document\Format
文档的接收者根据文档内容确定。PEF系统异步将文档发送给接收者。可以从消息队列中检索发送文档的状态信息。如果PEF系统正确接受文档,则此操作返回文档标识符(
documentId
)。该标识符应由外部系统保存,以便将消息队列中未来出现的关于该文档的消息关联起来。getDocumentContent()
获取文档内容;位置$pef->document
操作允许获取来自另一个来源接收或发送的文档的内容(在Ubl格式中)。从收到关于新文档的消息的时间起,文档内容可保留7天。
readDocument()
标记文档为已读;位置$pef->document
操作允许传达外部系统用户已阅读文档的信息。
4. 消息队列
操作getMessage()
返回SJRoyd\PEF\Response\Message对象,该对象包含以下五种类型之一的消息(如下)和有关getDocumentContent
的信息,告诉消息是否已分配给要使用方法getDocumentContent()
获取的文档。
在getMessage()
操作的getMessage()
方法上返回特定的消息。每个消息都有一个messageId
字段,用于标识消息,documentId
是文档标识符。
可以使用switch
块处理消息
<?php
$msgGen = $pef->message->getMessage();
$msg = $msgGen->getMessage();
switch(true) {
case $msg instanceof Message\ReceivedDocumentStatusChanged:
// do something
break;
case $msg instanceof Message\SentDocumentStatusChanged:
// do something
break;
// etc...
}
或if
块
<?php
$msgGen = $pef->message->getMessage();
if(($msg = $msgGen->receivedDocumentStatusChangedMessage)){
// do something
}
if(($msg = $msgGen->sentDocumentStatusChangedMessage)){
// do something
}
// etc...
4.1 消息 Message\ReceivedDocumentStatusChanged
关于接收到的文档状态变更的消息。当文档状态通过其他渠道(WEB应用或桌面应用)更改时,将触发此消息。
消息字段
messageId
: uuiddocumentId
: uuidstatus
: 枚举 [ RECEIVED, READ ] - 辅助Status\DocumentReceived
4.2 消息 Message\SentDocumentStatusChanged
关于已发送文档状态变更的消息。
消息字段
messageId
: uuiddocumentId
: uuidstatus
: 枚举 [ PENDING, SENT, RECEIVED, READ ] - 辅助Status\DocumentSend
4.3 消息 Message\SentDocumentErrorMessage
指示文档发送过程中出现错误的消息。
消息字段
messageId
: uuiddocumentId
: uuiderrors
: Message\Error 列表errorCode
: 枚举 [ 401, 402, 403, 404, 501 ]errorMessage
: 字符串
errorCode
根据字典
401 错误请求
402 文档内容验证错误
403 收件人的端点未在PEPPOL网络中注册
404 收件人不支持文档类型
501 文档投递错误。尽管尝试重传,文档仍无法投递。
errorMessage
- 错误的技术描述。描述旨在向技术人员(而非最终用户)展示错误。
4.4 消息 Message\DocumentReceived
通知您已收到文档的消息。可以使用 getDocumentContent()
操作下载文档内容。
消息字段
messageId
: uuiddocumentId
: uuidbusinessValidationReport
: Message\BusinessValidationReportreportDate
: DateTime 对象warnings
: 枚举 [ EMPTY_CONTRACT_ID, EMPTY_ORDER_REFERENCE, EMPTY_DESPATCH_DOCUMENT_REFERENCE, EMPTY_RECEIPT_DOCUMENT_REFERENCE, EMPTY_INVOICE_DOCUMENT_REFERENCE, REFERENCED_ORDER_NOT_FOUND, REFERENCED_DESPATCH_NOT_FOUND, REFERENCED_RECEIPT_NOT_FOUND, REFERENCED_INVOICE_NOT_FOUND ] - 辅助Message\Warning
documentType
: 枚举 [ CREDIT_NOTE, DESPATCH_ADVICE, INVOICE, INVOICE_CORRECTION, ORDER, RECEIPT_ADVICE ] - 辅助Document\Type
4.5 消息 Message\DocumentSentFromOtherSource
通知表示通过系统支持的邮箱(从WEB或桌面应用)通过其他渠道发送了文档。可以使用 getDocumentContent()
操作下载文档内容。
消息字段
messageId
: uuiddocumentId
: uuiddocumentType
: 枚举 [ CREDIT_NOTE, DESPATCH_ADVICE, INVOICE, INVOICE_CORRECTION, ORDER, RECEIPT_ADVICE ] - 辅助Document\Type
5. 辅助类
辅助类具有静态方法
getList(): list
- 返回类中的常量列表exists($const): boolean
- 返回给定值是否存在作为常量的信息
辅助类 Document\Type
<?php
namespace SJRoyd\PEF\Helper\Document;
use SJRoyd\PEF\Helper\Constants;
class Type
{
use Constants;
const CREDIT_NOTE = 'CREDIT_NOTE';
const DESPATCH_ADVICE = 'DESPATCH_ADVICE';
const INVOICE = 'INVOICE';
const INVOICE_CORRECTION = 'INVOICE_CORRECTION';
const ORDER = 'ORDER';
const RECEIPT_ADVICE = 'RECEIPT_ADVICE';
}
辅助类 Document\Format
<?php
namespace SJRoyd\PEF\Helper\Document;
use SJRoyd\PEF\Helper\Constants;
class Format
{
use Constants;
const UBL = 'Ubl';
const CEFACT = 'Cefact';
}
辅助类 Status\DocumentReceived
<?php
namespace SJRoyd\PEF\Helper\Status;
use SJRoyd\PEF\Helper\Constants;
class DocumentReceived
{
use Constants;
const RECEIVED = 'RECEIVED';
const READ = 'READ';
}
辅助类 Status\DocumentSend
<?php
namespace SJRoyd\PEF\Helper\Status;
use SJRoyd\PEF\Helper\Constants;
class DocumentSend
{
use Constants;
const PENDING = 'PENDING';
const SENT = 'SENT';
const RECEIVED = 'RECEIVED';
const READ = 'READ';
}
辅助类 Message\Warning
<?php
namespace SJRoyd\PEF\Helper\Message;
use SJRoyd\PEF\Helper\Constants;
class Warning
{
use Constants;
const EMPTY_CONTRACT_ID = 'EMPTY_CONTRACT_ID';
const EMPTY_ORDER_REFERENCE = 'EMPTY_ORDER_REFERENCE';
const EMPTY_DESPATCH_DOCUMENT_REFERENCE = 'EMPTY_DESPATCH_DOCUMENT_REFERENCE';
const EMPTY_RECEIPT_DOCUMENT_REFERENCE = 'EMPTY_RECEIPT_DOCUMENT_REFERENCE';
const EMPTY_INVOICE_DOCUMENT_REFERENCE = 'EMPTY_INVOICE_DOCUMENT_REFERENCE';
const REFERENCED_ORDER_NOT_FOUND = 'REFERENCED_ORDER_NOT_FOUND';
const REFERENCED_DESPATCH_NOT_FOUND = 'REFERENCED_DESPATCH_NOT_FOUND';
const REFERENCED_RECEIPT_NOT_FOUND = 'REFERENCED_RECEIPT_NOT_FOUND';
const REFERENCED_INVOICE_NOT_FOUND = 'REFERENCED_INVOICE_NOT_FOUND';
}