Skip to content

Commit

Permalink
Add XE3. Update builder for uplaod documents
Browse files Browse the repository at this point in the history
Fixed CCT, CDD builder.
  • Loading branch information
andrew-svirin committed Aug 16, 2023
1 parent e1b4f35 commit 1692d4d
Show file tree
Hide file tree
Showing 13 changed files with 332 additions and 133 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@
* Added CurlHttpClient and PsrHttpClient to use standard client.
* Updated AbstractX509Generator to handle custom options.
* Improved Bank-letter
* Fixed padding for encoding that caused problems for upload methods.
* Added XE3
* Fixed CCT, CDD builder.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ try {
| CCT | Upload initiation of the credit transfer per Single Euro Payments Area. |
| CIP | Upload initiation of the instant credit transfer per Single Euro Payments Area. |
| XE2 | Upload initiation of the Swiss credit transfer (i.e available in Switzerland). |
| XE3 | Upload SEPA Direct Debit Initiation, CH definitions, CORE (i.e available in Switzerland). |
| YCT | Upload Credit transfer CGI (SEPA & non SEPA). |
| CDD | Upload initiation of the direct debit transaction. |
| BTD | Download request files of any BTF structure. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,17 @@ public function __construct()
$this->randomService = new RandomService();
}

/**
* @param string $schema has next formula urn:iso:std:iso:20022:tech:xsd:msgName.001.msgNameVersion
* @param string $debitorFinInstBIC
* @param string $debitorIBAN
* @param string $debitorName
*
* @return $this
* @throws \DOMException
*/
public function createInstance(
string $schema,
string $debitorFinInstBIC,
string $debitorIBAN,
string $debitorName
Expand All @@ -41,19 +51,14 @@ public function createInstance(
$now = new DateTime();

$xmDocument = $this->instance->createElementNS(
'http://www.six-interbank-clearing.com/de/pain.001.001.03.ch.02.xsd',
$schema,
'Document'
);
$xmDocument->setAttributeNS(
'http://www.w3.org/2000/xmlns/',
'xmlns:xsi',
'http://www.w3.org/2001/XMLSchema-instance'
);
$xmDocument->setAttributeNS(
'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation',
'http://www.six-interbank-clearing.com/de/pain.001.001.03.ch.02.xsd pain.001.001.03.ch.02.xsd'
);
$this->instance->appendChild($xmDocument);

$xmlCstmrCdtTrfInitn = $this->instance->createElement('CstmrCdtTrfInitn');
Expand Down
13 changes: 6 additions & 7 deletions src/Builders/CustomerDirectDebit/CustomerDirectDebitBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public function __construct()
}

/**
* @param string $schema has next formula urn:iso:std:iso:20022:tech:xsd:msgName.001.msgNameVersion
* @param string $creditorFinInstBic
* @param string $creditorIban
* @param string $creditorName
Expand All @@ -39,9 +40,12 @@ public function __construct()
* least for 15 days. Used for rejecting duplicated transactions (max length: 35 characters)
* @param string|null $paymentReference Overwrite default payment reference -
* visible on creditors bank statement (max length: 35 characters)
*
* @return $this
* @throws \DOMException
*/
public function createInstance(
string $schema,
string $creditorFinInstBic,
string $creditorIban,
string $creditorName,
Expand All @@ -56,19 +60,14 @@ public function createInstance(
$now = new DateTime();

$xmDocument = $this->instance->createElementNS(
'urn:iso:std:iso:20022:tech:xsd:pain.008.001.02',
$schema,
'Document'
);
$xmDocument->setAttributeNS(
'http://www.w3.org/2000/xmlns/',
'xmlns:xsi',
'http://www.w3.org/2001/XMLSchema-instance'
);
$xmDocument->setAttributeNS(
'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation',
'urn:iso:std:iso:20022:tech:xsd:pain.008.001.02.xsdpain.008.001.02'
);
$this->instance->appendChild($xmDocument);

$xmlCstmrDrctDbtInitn = $this->instance->createElement('CstmrDrctDbtInitn');
Expand Down Expand Up @@ -252,7 +251,7 @@ public function addTransaction(
$xmlEndToEndId->nodeValue = $endToEndId;
} else {
$xmlEndToEndId->nodeValue = $this->randomService->uniqueIdWithDate(
'pete' . str_pad((string)$nbOfTxs, 2, '0')
'pete'.str_pad((string)$nbOfTxs, 2, '0')
);
}

Expand Down
10 changes: 10 additions & 0 deletions src/Contracts/EbicsClientInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,16 @@ public function CDD(OrderDataInterface $orderData, DateTimeInterface $dateTime =
*/
public function XE2(OrderDataInterface $orderData, DateTimeInterface $dateTime = null): UploadOrderResult;

/**
* Upload SEPA Direct Debit Initiation, CH definitions, CORE.
* FileFormat pain.008.001.03.ch.02
* OrderType:BTU, Service Name:SDD, Scope:CH,Service Option:COR Container:, MsgName:pain.008,Version: 02
* @param OrderDataInterface $orderData
* @param DateTimeInterface|null $dateTime
* @return UploadOrderResult
*/
public function XE3(OrderDataInterface $orderData, DateTimeInterface $dateTime = null): UploadOrderResult;

/**
* Upload Credit transfer CGI (SEPA & non SEPA).
* OrderType:BTU, Service Name:MCT, Scope:BIL, Container:, MsgName:pain.001
Expand Down
39 changes: 37 additions & 2 deletions src/EbicsClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,10 @@ public function BTU(BTUContext $btuContext, DateTimeInterface $dateTime = null):
$dateTime = new DateTime();
}

$transaction = $this->uploadTransaction(function (UploadTransaction $transaction) use ($btuContext, $dateTime) {
$transaction = $this->uploadTransaction(function (UploadTransaction $transaction) use ($dateTime, $btuContext) {
$transaction->setOrderData($btuContext->getFileData());
$transaction->setDigest($this->cryptService->hash($transaction->getOrderData()));

return $this->requestFactory->createBTU(
$btuContext,
$dateTime,
Expand Down Expand Up @@ -736,6 +737,7 @@ public function FUL(
) {
$transaction->setOrderData($orderData->getContent());
$transaction->setDigest($this->cryptService->hash($transaction->getOrderData()));

return $this->requestFactory->createFUL(
$dateTime,
$fileFormat,
Expand All @@ -761,6 +763,7 @@ public function CCT(OrderDataInterface $orderData, DateTimeInterface $dateTime =
$transaction = $this->uploadTransaction(function (UploadTransaction $transaction) use ($orderData, $dateTime) {
$transaction->setOrderData($orderData->getContent());
$transaction->setDigest($this->cryptService->hash($transaction->getOrderData()));

return $this->requestFactory->createCCT(
$dateTime,
$transaction
Expand All @@ -784,6 +787,7 @@ public function CDD(OrderDataInterface $orderData, DateTimeInterface $dateTime =
$transaction = $this->uploadTransaction(function (UploadTransaction $transaction) use ($dateTime, $orderData) {
$transaction->setOrderData($orderData->getContent());
$transaction->setDigest($this->cryptService->hash($transaction->getOrderData()));

return $this->requestFactory->createCDD(
$dateTime,
$transaction
Expand All @@ -807,6 +811,7 @@ public function XE2(OrderDataInterface $orderData, DateTimeInterface $dateTime =
$transaction = $this->uploadTransaction(function (UploadTransaction $transaction) use ($dateTime, $orderData) {
$transaction->setOrderData($orderData->getContent());
$transaction->setDigest($this->cryptService->hash($transaction->getOrderData()));

return $this->requestFactory->createXE2(
$dateTime,
$transaction
Expand All @@ -816,6 +821,30 @@ public function XE2(OrderDataInterface $orderData, DateTimeInterface $dateTime =
return $this->createUploadOrderResult($transaction, $orderData);
}

/**
* @inheritDoc
* @throws Exceptions\EbicsResponseException
* @throws EbicsException
*/
public function XE3(OrderDataInterface $orderData, DateTimeInterface $dateTime = null): UploadOrderResult
{
if (null === $dateTime) {
$dateTime = new DateTime();
}

$transaction = $this->uploadTransaction(function (UploadTransaction $transaction) use ($dateTime, $orderData) {
$transaction->setOrderData($orderData->getContent());
$transaction->setDigest($this->cryptService->hash($transaction->getOrderData()));

return $this->requestFactory->createXE3(
$dateTime,
$transaction
);
});

return $this->createUploadOrderResult($transaction, $orderData);
}

/**
* @inheritDoc
* @throws Exceptions\EbicsResponseException
Expand All @@ -830,6 +859,7 @@ public function YCT(OrderDataInterface $orderData, DateTimeInterface $dateTime =
$transaction = $this->uploadTransaction(function (UploadTransaction $transaction) use ($dateTime, $orderData) {
$transaction->setOrderData($orderData->getContent());
$transaction->setDigest($this->cryptService->hash($transaction->getOrderData()));

return $this->requestFactory->createYCT(
$dateTime,
$transaction
Expand All @@ -853,6 +883,7 @@ public function CIP(OrderDataInterface $orderData, DateTimeInterface $dateTime =
$transaction = $this->uploadTransaction(function (UploadTransaction $transaction) use ($dateTime, $orderData) {
$transaction->setOrderData($orderData->getContent());
$transaction->setDigest($this->cryptService->hash($transaction->getOrderData()));

return $this->requestFactory->createCIP(
$dateTime,
$transaction
Expand Down Expand Up @@ -921,6 +952,7 @@ public function HVE(HVEContext $hveContext, DateTimeInterface $dateTime = null):
$hveContext
) {
$transaction->setDigest($hveContext->getDigest());

return $this->requestFactory->createHVE(
$hveContext,
$dateTime,
Expand Down Expand Up @@ -1118,7 +1150,7 @@ private function downloadTransaction(callable $requestClosure, callable $storeCl
$requestClosure,
[
$transaction->getLastSegment()->getNextSegmentNumber(),
$transaction->getLastSegment()->isLastNextSegmentNumber()
$transaction->getLastSegment()->isLastNextSegmentNumber(),
]
);

Expand Down Expand Up @@ -1340,6 +1372,7 @@ public function setHttpClient(HttpClientInterface $httpClient): void

/**
* Get user signature.
*
* @param string $type One of allowed user signature type.
* @param bool $createNew Flag to generate new signature force.
*
Expand Down Expand Up @@ -1371,7 +1404,9 @@ private function getUserSignature(string $type, bool $createNew = false): Signat

/**
* Create new signature.
*
* @param string $type
*
* @return SignatureInterface
* @throws EbicsException
*/
Expand Down
2 changes: 2 additions & 0 deletions src/Factories/RequestFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,8 @@ abstract public function createCDD(DateTimeInterface $dateTime, UploadTransactio

abstract public function createXE2(DateTimeInterface $dateTime, UploadTransaction $transaction): Request;

abstract public function createXE3(DateTimeInterface $dateTime, UploadTransaction $transaction): Request;

abstract public function createYCT(DateTimeInterface $dateTime, UploadTransaction $transaction): Request;

/**
Expand Down
65 changes: 65 additions & 0 deletions src/Factories/RequestFactoryV2.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ protected function addOrderType(OrderDetailsBuilder $orderDetailsBuilder, string
case 'CCT':
case 'CDD':
case 'XE2':
case 'XE3':
case 'CIP':
$orderAttribute = OrderDetailsBuilder::ORDER_ATTRIBUTE_OZHNN;
break;
Expand Down Expand Up @@ -771,6 +772,70 @@ public function createXE2(DateTimeInterface $dateTime, UploadTransaction $transa
return $request;
}

/**
* @throws EbicsException
*/
public function createXE3(DateTimeInterface $dateTime, UploadTransaction $transaction): Request
{
$signatureData = new UserSignature();
$this->userSignatureHandler->handle($signatureData, $transaction->getDigest());

$context = (new RequestContext())
->setBank($this->bank)
->setUser($this->user)
->setKeyRing($this->keyRing)
->setDateTime($dateTime)
->setTransactionKey($transaction->getKey())
->setNumSegments($transaction->getNumSegments())
->setSignatureData($signatureData);

$request = $this
->createRequestBuilderInstance()
->addContainerSecured(function (XmlBuilder $builder) use ($context) {
$builder->addHeader(function (HeaderBuilder $builder) use ($context) {
$builder->addStatic(function (StaticBuilder $builder) use ($context) {
$builder
->addHostId($context->getBank()->getHostId())
->addRandomNonce()
->addTimestamp($context->getDateTime())
->addPartnerId($context->getUser()->getPartnerId())
->addUserId($context->getUser()->getUserId())
->addProduct('Ebics client PHP', 'de')
->addOrderDetails(function (OrderDetailsBuilder $orderDetailsBuilder) {
$this
->addOrderType($orderDetailsBuilder, 'XE3')
->addStandardOrderParams();
})
->addBankPubKeyDigests(
$context->getKeyRing()->getBankSignatureXVersion(),
$this->digestResolver->digest($context->getKeyRing()->getBankSignatureX()),
$context->getKeyRing()->getBankSignatureEVersion(),
$this->digestResolver->digest($context->getKeyRing()->getBankSignatureE())
)
->addSecurityMedium(StaticBuilder::SECURITY_MEDIUM_0000)
->addNumSegments($context->getNumSegments());
})->addMutable(function (MutableBuilder $builder) {
$builder->addTransactionPhase(MutableBuilder::PHASE_INITIALIZATION);
});
})->addBody(function (BodyBuilder $builder) use ($context) {
$builder->addDataTransfer(function (DataTransferBuilder $builder) use ($context) {
$builder
->addDataEncryptionInfo(function (DataEncryptionInfoBuilder $builder) use ($context) {
$builder
->addEncryptionPubKeyDigest($context->getKeyRing())
->addTransactionKey($context->getTransactionKey(), $context->getKeyRing());
})
->addSignatureData($context->getSignatureData(), $context->getTransactionKey());
});
});
})
->popInstance();

$this->authSignatureHandler->handle($request);

return $request;
}

public function createYCT(DateTimeInterface $dateTime, UploadTransaction $transaction): Request
{
throw new LogicException('Method not implemented yet for EBICS 2.5');
Expand Down
13 changes: 13 additions & 0 deletions src/Factories/RequestFactoryV3.php
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ public function createZ54(
$btfContext->setServiceName('REP');
$btfContext->setScope('CH');
$btfContext->setMsgName('camt.054');
$btfContext->setMsgNameVersion('04');
$btfContext->setContainerFlag('ZIP');

return $this->createBTD($dateTime, $btfContext, $startDateTime, $endDateTime, $segmentNumber, $isLastSegment);
Expand Down Expand Up @@ -335,6 +336,18 @@ public function createXE2(DateTimeInterface $dateTime, UploadTransaction $transa
throw new LogicException('Method not implemented yet for EBICS 3.0');
}

public function createXE3(DateTimeInterface $dateTime, UploadTransaction $transaction): Request
{
$btfContext = new BTUContext();
$btfContext->setServiceName('SDD');
$btfContext->setScope('CH');
$btfContext->setMsgName('pain.008');
$btfContext->setMsgNameVersion('02');
$btfContext->setFileName('xe3.pain008.xml');

return $this->createBTU($btfContext, $dateTime, $transaction);
}

public function createYCT(DateTimeInterface $dateTime, UploadTransaction $transaction): Request
{
$btfContext = new BTUContext();
Expand Down
Loading

0 comments on commit 1692d4d

Please # to comment.