AADE myDATA PHP Package

repository·5.x·Indexed 41 days ago

https://github.com/firebed/aade-mydata

A PHP package providing a fluent interface for interacting with the Greek tax authority's (AADE) myDATA REST API. It simplifies sending, cancelling, and managing invoices and digital goods movement, supporting both direct ERP channel communication and licensed e-invoicing providers via a Gateway pattern. Requires PHP 8.1 and guzzlehttp/guzzle >= 7.0.

Tokens
91.7K
Snippets
180
Records
209
Agent score
48%

What's inside AADE myDATA

  1. Automatic XML construction for myDATA

    5.x

    The library handles the complex task of converting data into the specific XML structure required by AADE myDATA.

    Starting from version 4, the library automatically manages the correct field order and structure. This eliminates the need for manual XML manipulation or worrying about the specific sequence of fields required by the myDATA schema, ensuring reliable communication with the API.

  2. Pass extra data to a custom gateway

    5.x

    When implementing a custom Gateway, you can access more than just the XML body. For specific actions like SendInvoices and SendPaymentsMethod, the library provides access to the underlying models. This allows a provider gateway to extract metadata that is not included in the standard myDATA XML (such as precise issue times or unit prices) but is required by the provider.

    Available Model Methods for Gateways

    • SendInvoices::getInvoicesDoc(): Returns the invoice document model.
    • SendPaymentsMethod::getPaymentMethodsDoc(): Returns the payment methods document model.

    Data available in models but not in XML

    • InvoiceHeader::setIssueTime('hh:mm:ss'): The specific issue time.
    • InvoiceDetails::setUnitPrice(float): The price per unit.
    • InvoiceDetails::setDiscount(DiscountType, float): Line discounts (supports DiscountType::PERCENTAGE or DiscountType::AMOUNT). Use getDiscountType() and getDiscountValue() to retrieve them.
    • setExtraFields(['key' => 'value']) or addExtraField('key', 'value'): Available on Invoice, InvoiceDetails, and PaymentMethodDetail to pass arbitrary key/value pairs to the provider.
  3. Handle pagination in RequestVatInfo

    5.x

    When search results exceed the maximum allowed limit, the API returns results in partitions. To retrieve the next set of results, you must use the nextPartitionKey and nextRowKey provided in the current response as parameters for your subsequent request.

    In the PHP client, you can retrieve these values using the getContinuationToken() method on the response object.

    // For calling the next partition of results
    $continuationToken = $response->getContinuationToken();
  4. Process results from SendInvoices

    5.x

    The handle() method returns a Firebed\AadeMyData\Models\ResponseDoc object. This object contains a collection of Firebed\AadeMyData\Models\Response objects—one for each invoice transmitted.

    Key Response Properties:

    • getIndex(): Returns a 1-based index corresponding to the position of the invoice in the original input array (e.g., index 1 corresponds to array index 0).
    • isSuccessful(): Returns true if the status field is Success.
    • getInvoiceUid(): Retrieves the unique identifier (UID) from myDATA.
    • getInvoiceMark(): Retrieves the invoice mark.
    • getCancellationMark(): Retrieves the cancellation mark.
    • getQrUrl(): Retrieves the QR code URL.
    • getErrors(): If the invoice failed, this returns a collection of error objects containing getCode() and getMessage().

    Caution: When sending multiple invoices, always check the result of each individual invoice. It is possible for some to succeed while others fail.

    use Firebed\AadeMyData\Http\SendInvoices;
    use Firebed\AadeMyData\Models\Invoice;
    use Firebed\AadeMyData\Exceptions\MyDataException;
    
    $invoicesToBeSent = [new Invoice(), new Invoice()];
    $sendInvoices = new SendInvoices();
    
    try {
        $responses = $sendInvoices->handle($invoicesToBeSent);
        
        foreach ($responses as $response) {
            if ($response->isSuccessful()) {
                // Success logic
                $index = $response->getIndex();
                $uid = $response->getInvoiceUid();
                $mark = $response->getInvoiceMark();
                $cancelledByMark = $response->getCancellationMark();
                $qrUrl = $response->getQrUrl();
                
                print_r(compact('index', 'uid', 'mark', 'cancelledByMark', 'qrUrl'));
            } else {
                // Error logic for specific invoice
                foreach ($response->getErrors() as $error) {
                    echo $response->getIndex() . ': ' . $error->getCode() . ': ' . $error->getMessage() . PHP_EOL;
                }
            }
        }
    } catch (MyDataException $e) {
        // Communication error: nothing was sent
        echo "Communication error: " . $e->getMessage();
    }
  5. How to paginate results with RequestDocs

    5.x

    When search results exceed the maximum allowed size, they are returned in segments (pages). To retrieve the next segment, you must use the pagination tokens provided in the current response.

    1. Call handle() to get the first page.
    2. Retrieve the continuation token from the response using $response->getContinuationToken().
    3. For the subsequent call, pass the values from the token into the nextPartitionKey and nextRowKey parameters of the handle() method.

    Note on filtering behavior:

    • If dateFrom or dateTo is omitted, the search is performed for that specific date. If both are provided, the search covers the range between them.
    • receiverVatNumber and invType are always applied using an equality operator.
    • invType must be provided as a numeric value corresponding to the types defined in the Appendix.
    use Firebed\AadeMyData\Enums\InvoiceType;
    use Firebed\AadeMyData\Http\RequestDocs;
    
    try {
        // 1. Fetch the first page
        $request1 = new RequestDocs();
        $response1 = $request1->handle("1234567890");
        
        // 2. Get the continuation token
        $continuationToken = $response1->getContinuationToken();
        
        // 3. Fetch the second page using the tokens
        $request2 = new RequestDocs();
        $response2 = $request2->handle(
            mark: "1234567890",
            dateFrom: "01/01/2021",
            dateTo: "31/12/2021",
            receiverVatNumber: "123456789",
            entityVatNumber: "123456789",
            invType: InvoiceType::TYPE_1_1,
            nextPartitionKey: $continuationToken->getNextPartitionKey(),
            nextRowKey: $continuationToken->getNextRowKey(),
        );
    } catch (MyDataException $e) {
        echo "Error: " . $e->getMessage();
    }
  6. Understand the authenticationCode

    5.x

    The authenticationCode is a string provided by the Service when transmission occurs via an Electronic Invoicing Provider. It is calculated as a SHA-1 hash of the following 10 fields:

    • Issuer VAT (ΑΦΜ Eκδότη)
    • Issue Date (Ημερομηνία Έκδοσης)
    • Taxis Installation Number (Αριθμός Εγκατάστασης στο Μητρώσιο του Taxis)
    • Document Type (Τύπος Παραστατικού)
    • Sequence (Σειρά)
    • AA (ΑΑ)
    • Document Mark (Μ.ΑΡ.Κ Παραστατικού)
    • Total Value (Συνολική Αξία Παραστατικού)
    • Total VAT Value (Σύνολο Αξίας Φ.Π.Α. Παραστατικού)
    • Recipient VAT (ΑΦΜ Λήπτη)
  7. Usage rules for Invoice Variation Types

    5.x

    Each variation type code has specific constraints regarding which document types (παραστατικών) it can be applied to:

    • Code 1 (Recipient Omission): Used when the Recipient transmits data because the Issuer failed to do so.

      • Allowed document types: 1.1, 1.6, 2.1, 2.4, 5.2, 8.1, and 8.2.
    • Code 2 (Issuer Omission): Used when the Issuer transmits data and agrees with the Recipient's marking of an omission on the Issuer's part.

      • Allowed document types: 11.3, 11.4, 13.1, and 13.31.
    • Code 3 (Recipient Discrepancy): Used when the Recipient transmits data (non-matching documents) due to a discrepancy in the Issuer's data transmission.

      • Allowed document types: 11.3, 11.4, 13.1, and 13.31.
      • Note: For documents issued specifically within 2021, the allowed types are 1.1 and 5.2.
    • Code 4 (Issuer Discrepancy): Used when the Issuer transmits data and agrees with the Recipient's "Discrepancy in Transmission" (Απόκλιση Διαβίβασης) marking on the corresponding A1 document type previously sent to the Recipient.

      • Allowed document types: 11.3, 11.4, 13.1, and 13.31.
  8. Understand the difference between technical and business errors

    5.x

    It is critical to distinguish between how the library reports technical failures versus business logic failures:

    Technical Errors

    These represent failures in the communication layer (e.g., network issues, authentication failures). These result in thrown PHP exceptions (see Handle technical exceptions).

    Business Errors (Επιχειρησιακά Σφάλματα)

    These occur when the request is technically successful (the server returns an HTTP 200 OK), but the data provided fails business validation. Examples include:

    • Invalid VAT numbers (ΑΦΜ)
    • Incorrect document sets
    • Invalid revenue or expense classifications

    There are over 100 different business errors. Because these return an HTTP 200, they do not trigger PHP exceptions; you must inspect the response body according to the myDATA documentation (refer to the official myDATA PDF for specific error codes).

  9. Handle paginated data with RequestedDoc and continuationToken

    5.x

    When calling data retrieval methods such as \Firebed\AadeMyData\Http\RequestDocs or \Firebed\AadeMyData\Http\RequestTransmittedDocs, the response is returned as a \Firebed\AadeMyData\Models\RequestedDoc object.

    If the volume of data exceeds the allowed limit and is retrieved partially, the RequestedDoc object will contain a continuationToken. This token includes nextPartitionKey and nextRowKey parameters. To retrieve the next batch of data, you must pass these parameters into the subsequent call to the same method used previously.

    // If data retrieval is partial
    $continuationToken = $requestedDoc->getContinuationToken();
    
    // The token contains parameters for the next call
    // (nextPartitionKey and nextRowKey)
  10. Verify cancelled invoices in RequestedDoc

    5.x

    After a successful cancellation, the status of the document can be verified through the RequestedDoc data structure:

    1. RequestedDoc::getCancelledInvoices(): The recently cancelled document will be included in the list of cancelled invoices.
    2. RequestedDoc::getInvoices(): The original document will still appear in the main invoice list, but it will be marked with a cancelledByMark field. This field contains the same cancellation mark received during the CancelInvoice process ($response->getCancellationMark()).

    XML Structure Example:

    <RequestedDoc>
        <invoicesDoc>
            <invoice>
                <uid>5AD65A46SFD5498SDV416WS5F1VS65VDFS65VDF</uid>
                <mark>800000165789544</mark>
                <cancelledByMark>800000165989544</cancelledByMark>
            </invoice>
        </invoicesDoc>
        <cancelledInvoicesDoc>
            <cancelledInvoice>
                <invoiceMark>800000165789544</invoiceMark>
                <cancellationMark>800000165989544</cancellationMark>
                <cancellationDate>2021-12-12</cancellationDate>
            </cancelledInvoice>
        </cancelledInvoicesDoc>
    </RequestedDoc>
  11. Handle pagination for RequestMyExpenses

    5.x

    When search results exceed the maximum allowed limit, they are returned in partitions. To retrieve the next set of results, you must use the nextPartitionKey and nextRowKey provided in the current response.

    In the PHP implementation, you can retrieve these values using the $response->getContinuationToken() method to facilitate subsequent calls.