API reference
All classes live in the namespace Darvis\UblPeppol. Every add...() method returns the builder, so calls can be chained. Arguments are positional; PHP named arguments work as well.
The two builders side by side
UblNlBis3Service builds Dutch invoices and credit notes, UblBeBis3Service builds Belgian ones. The method names are the same; the arguments are not always.
Document
| Method | UblNlBis3Service | UblBeBis3Service |
|---|---|---|
createDocument(): self | Starts an <Invoice>. Throws a RuntimeException on a second call | The same |
generateXml() without createDocument() | Throws a RuntimeException | Returns an empty XML declaration |
generateXml(bool $validateFirst = false): string | Puts the elements in schema order and returns the XML. With true it calls validate() first and throws an InvalidArgumentException on errors | Returns the XML. With true the same, plus suggested corrections in the message. On a credit note it always checks the credit note rules |
validate(): InvoiceValidationResult | Code formats and five Dutch rules | Totals and code formats. See Validation |
enableStrictCodelistValidation(?string $jsonPath = null, ?CodelistRegistry $registry = null): self | See Strict code lists | The same |
Header and references
addInvoiceHeader(string $invoiceNumber, $issueDate, $dueDate): self
addAccountingCost(string $value): self // BT-19, optional
addBuyerReference(?string $buyerRef = 'BUYER_REF'): self
addOrderReference(string $orderNumber = 'PO-001'): self
addAdditionalDocumentReference(string $id, ?string $documentType = null): self
The same in both builders, with two differences: the Dutch builder ignores $documentType, and the Belgian addBuyerReference() throws on a credit note. The date arguments have no type declaration in the code; a YYYY-MM-DD string or a \DateTime is accepted.
Parties
UblNlBis3Service:
addAccountingSupplierParty(
string $endpointId,
string $endpointSchemeID,
string $partyId,
string $partyName,
string $street,
string $postalCode,
string $city,
string $countryCode,
string $companyId, // the supplier's VAT number
?string $additionalStreet = null
): self
addAccountingCustomerParty(
string $endpointId,
string $endpointSchemeID,
string $partyId,
string $partyName,
string $street,
string $postalCode,
string $city,
string $countryCode,
?string $additionalStreet = null,
?string $companyId = null, // the customer's registration number (KvK)
?string $contactName = null,
?string $contactPhone = null,
?string $contactEmail = null,
?string $vatNumber = null, // with the country prefix
string $taxSchemeId = 'VAT'
): self
Only in UblNlBis3Service, for the legal registration identifier (BT-30, BT-47):
addSupplierLegalRegistration(string $identifier, string $schemeId = '0106'): self
addCustomerLegalRegistration(string $identifier, string $schemeId = '0106'): self
See Dutch invoices.
The customer’s $partyId (BT-46) is whatever you call this customer, for example your own customer number. The Dutch builder writes the endpoint’s scheme on it only when it is the endpoint identifier itself, 8 digits under scheme 0106 (a KvK number) or 20 digits under 0190 (an OIN); otherwise the optional schemeID is left out. Until 1.9 every value got the scheme, so CUST-710 went out as a KvK number and the receiver’s validation answered with PEPPOL-COMMON-R054.
UblBeBis3Service has the same positions with other names: $name for $partyName, $country for $countryCode, $vatNumber for the supplier’s $companyId, and $registrationNumber for the customer’s $companyId. It has no $taxSchemeId argument.
Delivery, payment, allowances and charges
UblNlBis3Service:
addDelivery(
string $deliveryDate,
?string $locationId = null,
string $locationSchemeId = '0088',
?string $street = null,
?string $additionalStreet = null,
?string $city = null,
?string $postalCode = null,
?string $countryCode = null,
?string $partyName = null
): self
addPaymentMeans(
string $paymentMeansCode = '30',
string $paymentMeansName = 'Credit transfer',
?string $paymentId = null,
?string $accountId = null, // IBAN
?string $accountName = null,
?string $financialInstitutionId = null, // BIC
?string $paymentChannelCode = null,
?string $paymentDueDate = null
): self
addPaymentTerms(?string $note = null): self
addAllowanceCharge(
bool $isCharge = true,
float $amount = 0.0,
string $reason = '',
string $taxCategoryId = 'S',
float $taxPercent = 0.0,
string $currency = 'EUR'
): self
UblBeBis3Service:
addDelivery(
string $deliveryDate,
string $locationId,
string $locationSchemeId,
string $street,
?string $additional_street,
string $city,
string $postal_code,
string $country,
?string $party_name = null
): self
addPaymentMeans(
string $paymentMeansCode,
?string $paymentMeansName,
string $paymentId,
string $account_iban,
?string $account_name,
?string $bic,
?string $channel_code = null, // not written
?string $due_date = null // not written
): self
addPaymentTerms(
?string $note = null,
?float $discount_percent = null, // not written
?float $discount_amount = null, // not written
?string $discount_date = null // not written
): self
addAllowanceCharge(
bool $isCharge,
float $amount,
string $reason,
string $taxCategoryId,
float $taxPercent,
string $currency
): self
Totals and lines
addTaxTotal(array $taxes): self
addLegalMonetaryTotal(array $amounts, string $currency = 'EUR'): self // Dutch builder
addLegalMonetaryTotal(array $totals, string $currency): self // Belgian builder
addInvoiceLine(array $lineData): self
The array keys are listed under Dutch invoices and Belgian invoices.
Credit notes, in both builders
| Method | What it does |
|---|---|
createCreditNoteDocument(): self | Starts a <CreditNote> instead of an <Invoice> |
addCreditNoteHeader(string $creditNoteNumber, $issueDate): self | The header with type code 381. No due date. $issueDate is a YYYY-MM-DD string or a \DateTime; the Dutch builder refuses a date in the future |
addBillingReference(string $originalInvoiceNumber, ?string $originalIssueDate = null): self | The invoice the credit note corrects. Required on a credit note. The Dutch builder throws on an empty number or a date that is not YYYY-MM-DD |
addCreditNoteLine(array $lineData): self | A line with <cbc:CreditedQuantity>. Makes quantity, price and line amount positive |
isCreditNote(): bool | true after createCreditNoteDocument() |
In the Dutch builder since 1.10.0. There, the invoice methods throw a RuntimeException on a credit note and the credit note methods throw one on an invoice. See Credit notes.
Only in UblBeBis3Service
| Method | What it does |
|---|---|
calculateTotals(): array | Adds up the lines added so far. Returns totals, tax_totals and total_tax_amount |
getInvoiceLines(): array, getTotals(): array, getTaxTotals(): array | What you passed in so far |
See Let the builder add up the lines.
Validation\InvoiceValidationResult
Returned by validate(). Public read-only properties: bool $isValid, array $errors, array $warnings, array $corrections.
| Method | Returns |
|---|---|
isValid(): bool | true without errors |
hasErrors(): bool, hasWarnings(): bool | |
getErrorsAsString(string $separator = "\n"): string | |
getWarningsAsString(string $separator = "\n"): string | |
getCorrections(): array | Suggested totals. Nothing is applied to the document |
getCorrection(string $key): mixed | One suggested value, or null |
toArray(): array | is_valid, errors, warnings, corrections |
InvoiceValidationResult::success(): self | A valid result |
InvoiceValidationResult::fromException(\Throwable $e): self | An invalid result with the exception message as its only error |
Validation\UblValidator
Static helpers for single values. The full table is under Validation.
UblValidator::validateVatNumber(?string $vatNumber): ?string
UblValidator::isValidVatNumber(string $vatNumber): bool
UblValidator::validateIban(?string $iban): ?string
UblValidator::isValidUnitCode(string $unitCode): bool
UblValidator::isValidTaxCategory(string $categoryId): bool
UblValidator::isValidCurrencyCodeFormat(string $currencyCode): bool
UblValidator::isValidSchemeIdFormat(string $schemeId): bool
UblValidator::isValidPaymentMeansCodeFormat(string $paymentMeansCode): bool
UblValidator::isValidClassificationScheme(string $schemeId): bool
UblValidator::getClassificationSchemeDescription(string $schemeId): string
UblValidator::validateInvoiceData(array $data): array
UblValidator::validateBasicCodes(array $codes): InvoiceValidationResult
UblValidator::validateStrictCodelists(array $codes, CodelistRegistry $registry): InvoiceValidationResult
UblValidator::validateInvoiceTotals(array $invoiceLines, array $totals, array $taxTotals, float $allowanceTotalAmount = 0.0, float $chargeTotalAmount = 0.0, float $prepaidAmount = 0.0, array $documentAllowances = [], array $documentCharges = []): InvoiceValidationResult
The last three are what the builders’ validate() calls.
Validation\CodelistRegistry
new CodelistRegistry(array $lists) // ['iso4217' => ['EUR'], ...]
CodelistRegistry::fromJsonFile(string $path): self // throws when the file is missing or not JSON
$registry->isLoaded(string $listName): bool // false for a missing or empty list
$registry->has(string $listName, string $code): bool // codes are compared in upper case
Constants\UnitCodes
UnitCodes::isValid(string $code): bool
UnitCodes::getDescription(string $code): ?string // 'hour' for 'HUR'
UnitCodes::getAll(): array // every code the package knows
ViesService
checkVat(string $countryCode, string $vatNumber): array
checkFullVatNumber(string $fullVatNumber): array
Needs the soap extension. See VAT numbers.
CompanyRegistrationService
validate(string $number, string $countryCode): array
getSupportedCountries(): array
See Company numbers.
PeppolService (Laravel)
sendUblXml(string $ublXml, ?string $invoiceNumber = null): array
sendInvoice(object $invoice, string $ublXml): array
testConnection(): array
getConfig(): array // url, username, password_configured
The constructor takes no arguments; it reads the ubl-peppol config. See Sending invoices.
Models\PeppolLog (Laravel)
PeppolLog::tableExists(): bool
PeppolLog::cleanupOldLogs(int $days = 60): int
// query scopes
PeppolLog::success();
PeppolLog::error();
PeppolLog::pending();
PeppolLog::recent(int $days = 60);
PeppolLog::olderThan(int $days);
See The log table is optional.
UblPeppolConfig (Laravel)
The one class that reads the config: UblPeppolConfig::url(), username(), password() (each a string, empty when not set) and logRetentionDays() (an integer, default 60).
Artisan
php artisan peppol:cleanup [--days=]
Publish tags
| Tag | Publishes |
|---|---|
ubl-peppol-config | config/ubl-peppol.php |
ubl-peppol-migrations | The migration for the peppol_logs table |