byrokrat/autogiro

Read and write files for the swedish direct debit system autogirot

1.1.0 2020-12-25 23:14 UTC

README

byrokrat

Autogiro

Packagist Version Build Status Quality Score

Read and write files for the swedish direct debit system autogirot.

For a command line utility that can convert autogiro files to XML see autogiro2xml.

Installation

composer require byrokrat/autogiro

Table of contents

  1. Autogiro specifications
  2. Generating autogiro request files
  3. Parsing autogiro files
  4. Accessing nodes using visitors
  5. Generating XML from node trees
  6. Hacking

Autogiro specifications

This library is developed against the technichal manual (in swedish) of the direct debit system (autogirot) revised 2016-12-13. For later versions of this document see Bankgirocentralen.

Generating autogiro request files

Create a writer by supplying your bankgiro account number and BGC customer number to WriterFactory.

$writer = (new \byrokrat\autogiro\Writer\WriterFactory)->createWriter(
    '123456',
    (new \byrokrat\banking\BankgiroFactory)->createAccount('1111-1119')
);

Perform actions on the writer and generate file.

$writer->deleteMandate('1234567890');
$rawFile = $writer->getContent();
echo $rawFile;

Will output something like:

0120180114AUTOGIRO                                            1234560011111119  
0300111111190000001234567890                                                    

Parsing autogiro files

Create a parser using the ParserFactory.

$factory = new \byrokrat\autogiro\Parser\ParserFactory;
$parser = $factory->createParser();

The created parser will by default parse and validate monetary amounts, account numbers and identification numbers. Opt out of this functionality by using one of the visitor constants:

$factory->createParser(\byrokrat\autogiro\Parser\ParserFactory::VISITOR_IGNORE_OBJECTS);

Parsing a file creates a node object.

use byrokrat\autogiro\Tree\Node;

/** @var Node */
$node = $parser->parse($rawFile);

Accessing special objects

Account, Amount, StateId and Date nodes are nested structures, where child node Object contains constructed php objects. Access using something like:

$money = $node->getChild(Node::AMOUNT)->getObjectValue();

Walking the parse tree

A simpler way of doing this is by using visitors. See below.

Walk the tree by calling hasChild(), getChild() and getChildren().

echo $node->getChild(Node::MANDATE_REQUEST_SECTION)
    ->getChild(Node::DELETE_MANDATE_REQUEST)
    ->getChild(Node::PAYER_NUMBER)
    ->getValue();

Or access all Node::DELETE_MANDATE_REQUEST nodes.

$mandateRequests = $node->getChild(Node::MANDATE_REQUEST_SECTION);

foreach ($mandateRequests->getChildren(Node::DELETE_MANDATE_REQUEST) as $deleteRequest) {
    // process...
}

Trying to access a child that does not exist returns a NullNode.

echo $node->getChild('this-does-not-exist')
    ->getChild('and-neither-does-this')
    ->isNull();

Accessing nodes using visitors

With the use of visitors nodes can be accessed based on name or type.

class MyVisitor extends \byrokrat\autogiro\Visitor\Visitor {
    function beforeDeleteMandateRequest($node) {
        echo "Delete mandate request found!";
    }
}

$visitor = new MyVisitor;

$node->accept($visitor);

This can also be done dynamically.

$visitor = new \byrokrat\autogiro\Visitor\Visitor;

$visitor->before(Node::DELETE_MANDATE_REQUEST, function ($node) {
    echo "Delete mandate request found!";
});

Finding mandate responses

$visitor->before(Node::MANDATE_RESPONSE, function ($node) {
    if ($node->hasChild(Node::CREATED_FLAG)) {
        // Mandate successfully created
    }
    if ($node->hasChild(Node::DELETED_FLAG)) {
        // Mandate successfully deleted
    }
    if ($node->hasChild(Node::ERROR_FLAG)) {
        // Mandate error state
    }
});

Finding payment responses

$visitor->before(Node::SUCCESSFUL_INCOMING_PAYMENT_RESPONSE, function ($node) {
    // successfull payment..
});

$visitor->before(Node::FAILED_INCOMING_PAYMENT_RESPONSE, function ($node) {
    // failed payment..
});

Generating XML from node trees

Using this feature can be very helpful to understand how the parser interprets various layouts.

$xmlWriter = (new \byrokrat\autogiro\Xml\XmlWriterFactory)->createXmlWriter();

echo $xmlWriter->asXml(
    $parser->parse($rawFile)
);

Hacking

With composer installed as composer

make

Or use something like

make COMPOSER_CMD=./composer.phar