Skip to content
This repository has been archived by the owner on Nov 7, 2021. It is now read-only.

QR Bill with QR Reference or Creditor Reference #40

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.php_cs
.php_cs.cache

*.phpunit.result.cache
phpunit.xml

/.idea/
composer.lock
/vendor/
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class PaymentInformation
protected $id;

/**
* @var array
* @var CreditTransfer[]
*/
protected $transactions;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

namespace Z38\SwissPayment\TransactionInformation;

use DOMDocument;
use DOMElement;
use InvalidArgumentException;
use Z38\SwissPayment\FinancialInstitutionInterface;
use Z38\SwissPayment\IBAN;
use Z38\SwissPayment\Money;
use Z38\SwissPayment\PostalAccount;

/**
* BankCreditTransfer contains all the information about a type 3 transaction
* for a QR-Bill with Creditor Reference (SCOR)
*/
class BankCreditTransferWithCreditorReference extends BankCreditTransfer
{
/**
* @var string
*/
protected $creditorReference;

/**
* BankCreditTransferWithQRR constructor.
* @param $instructionId
* @param $endToEndId
* @param Money\Money $amount
* @param $creditorName
* @param $creditorAddress
* @param IBAN $creditorIBAN IBAN of the creditor
* @param FinancialInstitutionInterface $creditorAgent BIC or IID of the creditor's financial institution
* @param string $creditorReference QR reference number (QRR)
*/
public function __construct(
$instructionId,
$endToEndId,
Money\Money $amount,
$creditorName,
$creditorAddress,
IBAN $creditorIBAN,
FinancialInstitutionInterface $creditorAgent,
$creditorReference
) {
$cleanedCreditorReference = str_replace(' ', '', strtoupper($creditorReference));
if (!preg_match('/^RF/', $cleanedCreditorReference)) {
throw new InvalidArgumentException('The creditor reference (SCOR) must starts with RF : ISO-11649');
}
$this->creditorReference = $cleanedCreditorReference;

if (preg_match('/^CH[0-9]{2}3/', $creditorIBAN->normalize())) {
throw new InvalidArgumentException('The IBAN must not be a QR-IBAN');
}

parent::__construct($instructionId, $endToEndId, $amount, $creditorName, $creditorAddress, $creditorIBAN, $creditorAgent);
}

/**
* @param DOMDocument $doc
* @param DOMElement $transaction
*/
protected function appendRemittanceInformation(DOMDocument $doc, DOMElement $transaction)
{
$remittanceInformation = $doc->createElement('RmtInf');

$structured = $doc->createElement('Strd');
$remittanceInformation->appendChild($structured);

$creditorReferenceInformation = $doc->createElement('CdtrRefInf');
$structured->appendChild($creditorReferenceInformation);

$codeOrProperty = $doc->createElement('CdOrPrtry');
$codeOrProperty->appendChild($doc->createElement('Cd', 'SCOR'));
$type = $doc->createElement('Tp');
$type->appendChild($codeOrProperty);

$creditorReferenceInformation->appendChild($type);
$creditorReferenceInformation->appendChild($doc->createElement('Ref', $this->creditorReference));

if (!empty($this->remittanceInformation)) {
$structured->appendChild($doc->createElement('AddtlRmtInf', $this->remittanceInformation));
}

$transaction->appendChild($remittanceInformation);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

namespace Z38\SwissPayment\TransactionInformation;

use DOMDocument;
use DOMElement;
use InvalidArgumentException;
use Z38\SwissPayment\FinancialInstitutionInterface;
use Z38\SwissPayment\IBAN;
use Z38\SwissPayment\Money;
use Z38\SwissPayment\PostalAccount;

/**
* BankCreditTransfer contains all the information about a type 3 transaction
* for a QR-Bill with QR reference (QRR)
*/
class BankCreditTransferWithQRR extends BankCreditTransfer
{
/**
* @var string
*/
protected $creditorReference;

/**
* BankCreditTransferWithQRR constructor.
* @param $instructionId
* @param $endToEndId
* @param Money\Money $amount
* @param $creditorName
* @param $creditorAddress
* @param IBAN $creditorIBAN IBAN of the creditor
* @param FinancialInstitutionInterface $creditorAgent BIC or IID of the creditor's financial institution
* @param string $creditorReference QR reference number (QRR)
*/
public function __construct(
$instructionId,
$endToEndId,
Money\Money $amount,
$creditorName,
$creditorAddress,
IBAN $creditorIBAN,
FinancialInstitutionInterface $creditorAgent,
$creditorReference
) {
if (!preg_match('/^[0-9]{1,27}$/', $creditorReference) || !PostalAccount::validateCheckDigit($creditorReference)) {
throw new InvalidArgumentException('QR reference is invalid.');
}
$this->creditorReference = $creditorReference;

if (!preg_match('/^CH[0-9]{2}3/', $creditorIBAN->normalize())) {
throw new InvalidArgumentException('The IBAN must be a QR-IBAN');
}

parent::__construct($instructionId, $endToEndId, $amount, $creditorName, $creditorAddress, $creditorIBAN, $creditorAgent);
}

/**
* @param DOMDocument $doc
* @param DOMElement $transaction
*/
protected function appendRemittanceInformation(DOMDocument $doc, DOMElement $transaction)
{
$remittanceInformation = $doc->createElement('RmtInf');

$structured = $doc->createElement('Strd');
$remittanceInformation->appendChild($structured);

$creditorReferenceInformation = $doc->createElement('CdtrRefInf');
$structured->appendChild($creditorReferenceInformation);

$codeOrProperty = $doc->createElement('CdOrPrtry');
$codeOrProperty->appendChild($doc->createElement('Prtry', 'QRR'));
$type = $doc->createElement('Tp');
$type->appendChild($codeOrProperty);

$creditorReferenceInformation->appendChild($type);
$creditorReferenceInformation->appendChild($doc->createElement('Ref', $this->creditorReference));

if (!empty($this->remittanceInformation)) {
$structured->appendChild($doc->createElement('AddtlRmtInf', $this->remittanceInformation));
}

$transaction->appendChild($remittanceInformation);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use Z38\SwissPayment\StructuredPostalAddress;
use Z38\SwissPayment\Tests\TestCase;
use Z38\SwissPayment\TransactionInformation\BankCreditTransfer;
use Z38\SwissPayment\TransactionInformation\BankCreditTransferWithCreditorReference;
use Z38\SwissPayment\TransactionInformation\BankCreditTransferWithQRR;
use Z38\SwissPayment\TransactionInformation\ForeignCreditTransfer;
use Z38\SwissPayment\TransactionInformation\IS1CreditTransfer;
use Z38\SwissPayment\TransactionInformation\IS2CreditTransfer;
Expand Down Expand Up @@ -51,6 +53,7 @@ protected function buildMessage()
new IBAN('CH51 0022 5225 9529 1301 C'),
new BIC('UBSWCHZH80A')
);
$transaction->setRemittanceInformation("Test Remittance");
$payment->addTransaction($transaction);

$transaction = new IS1CreditTransfer(
Expand All @@ -73,6 +76,7 @@ protected function buildMessage()
'Musterbank AG',
new PostalAccount('80-151-4')
);
$transaction->setRemittanceInformation("Test Remittance");
$payment->addTransaction($transaction);

$iban = new IBAN('CH51 0022 5225 9529 1301 C');
Expand All @@ -85,6 +89,7 @@ protected function buildMessage()
$iban,
IID::fromIBAN($iban)
);
$transaction->setRemittanceInformation("Test Remittance");
$transaction->setPurpose(new PurposeCode('AIRB'));
$payment->addTransaction($transaction);

Expand Down Expand Up @@ -207,6 +212,42 @@ protected function buildMessage()
new StructuredPostalAddress('Dorfstrasse', '17', '9911', 'Musterwald'),
new PostalAccount('60-9-9')
);
$transaction->setRemittanceInformation("Test Remittance");
$payment->addTransaction($transaction);

$payment = new PaymentInformation(
'payment-050',
'InnoMuster AG',
new BIC('ZKBKCHZZ80A'),
new IBAN('CH6600700110000204481')
);
$message->addPayment($payment);

$qrIban = new IBAN('CH44 3199 9123 0008 8901 2');
$transaction = new BankCreditTransferWithQRR(
'instr-050',
'e2e-050',
new Money\CHF(130000), // CHF 1300.00
'Muster Transport AG',
new StructuredPostalAddress('Wiesenweg', '14b', '8058', 'Zürich-Flughafen'),
$qrIban,
IID::fromIBAN($qrIban),
'210000000003139471430009017'
);
$transaction->setRemittanceInformation("Test Remittance");
$payment->addTransaction($transaction);

$transaction = new BankCreditTransferWithCreditorReference(
'instr-050',
'e2e-050',
new Money\CHF(130000), // CHF 1300.00
'Muster Transport AG',
new StructuredPostalAddress('Wiesenweg', '14b', '8058', 'Zürich-Flughafen'),
$iban,
IID::fromIBAN($iban),
'RF 72 0191 2301 0040 5JSH 0438'
);
$transaction->setRemittanceInformation("Test Remittance");
$payment->addTransaction($transaction);

return $message;
Expand All @@ -222,10 +263,10 @@ public function testGroupHeader()
$xpath->registerNamespace('pain001', self::SCHEMA);

$nbOfTxs = $xpath->evaluate('string(//pain001:GrpHdr/pain001:NbOfTxs)');
$this->assertEquals('12', $nbOfTxs);
$this->assertEquals('14', $nbOfTxs);

$ctrlSum = $xpath->evaluate('string(//pain001:GrpHdr/pain001:CtrlSum)');
$this->assertEquals('4210.001', $ctrlSum);
$this->assertEquals('6810.001', $ctrlSum);
}

public function testSchemaValidation()
Expand All @@ -250,6 +291,6 @@ public function testGetPaymentCount()
{
$message = $this->buildMessage();

$this->assertSame(5, $message->getPaymentCount());
$this->assertSame(6, $message->getPaymentCount());
}
}