From fd8b4498dabb6d6ad41c511a8e6759cf8f3b816a Mon Sep 17 00:00:00 2001
From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Date: Wed, 1 Apr 2026 17:41:56 -0300
Subject: [PATCH 1/4] feat(dto): add totalTributosPercentual fields to DpsData
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
---
src/Dto/DpsData.php | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/Dto/DpsData.php b/src/Dto/DpsData.php
index bd51b83..bfb281c 100644
--- a/src/Dto/DpsData.php
+++ b/src/Dto/DpsData.php
@@ -72,6 +72,15 @@ public function __construct(
/** Indicador de tributação total. */
public int $indicadorTributacao = 0,
+ /** Percentual total estimado de tributos federais. */
+ public string $totalTributosPercentualFederal = '',
+
+ /** Percentual total estimado de tributos estaduais. */
+ public string $totalTributosPercentualEstadual = '',
+
+ /** Percentual total estimado de tributos municipais. */
+ public string $totalTributosPercentualMunicipal = '',
+
/** Whether ISS is retained at source. */
public bool $issRetido = false,
From 2b15d3d4f1929f4c247909d25993d75511a6fab6 Mon Sep 17 00:00:00 2001
From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Date: Wed, 1 Apr 2026 17:42:08 -0300
Subject: [PATCH 2/4] feat(xml): fix element ordering and extract
buildServico/buildValores methods
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
---
src/Xml/XmlBuilder.php | 166 +++++++++++++++++++++++++++++------------
1 file changed, 119 insertions(+), 47 deletions(-)
diff --git a/src/Xml/XmlBuilder.php b/src/Xml/XmlBuilder.php
index 61a37ee..dba82d1 100644
--- a/src/Xml/XmlBuilder.php
+++ b/src/Xml/XmlBuilder.php
@@ -25,6 +25,9 @@ public function buildDps(DpsData $dps): string
$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;
+ $emissionDateTime = $this->formattedEmissionDateTime();
+ $competenceDate = $dps->dataCompetencia ?: substr($emissionDateTime, 0, 10);
+
$root = $doc->createElementNS(self::XSD_NAMESPACE, 'DPS');
$root->setAttribute('versao', self::DPS_VERSION);
$root->setAttribute('xsi:schemaLocation', self::XSD_SCHEMA);
@@ -35,42 +38,27 @@ public function buildDps(DpsData $dps): string
$infDps->setAttribute('Id', $this->buildIdentifier($dps));
$root->appendChild($infDps);
- // Municipality
- $cMun = $doc->createElement('cMun', $dps->municipioIbge);
- $infDps->appendChild($cMun);
+ $infDps->appendChild($doc->createElement('tpAmb', (string) $dps->tipoAmbiente));
+ $infDps->appendChild($doc->createElement('dhEmi', $emissionDateTime));
+ $infDps->appendChild($doc->createElement('verAplic', $dps->versaoAplicativo));
+ $infDps->appendChild($doc->createElement('serie', str_pad($dps->serie, 5, '0', STR_PAD_LEFT)));
+ $infDps->appendChild($doc->createElement('nDPS', $dps->numeroDps));
+ $infDps->appendChild($doc->createElement('dCompet', $competenceDate));
+ $infDps->appendChild($doc->createElement('tpEmit', (string) $dps->tipoEmissao));
$infDps->appendChild($doc->createElement('cLocEmi', $dps->municipioIbge));
- // Prestador
$prest = $doc->createElement('prest');
$cnpj = $doc->createElement('CNPJ', $dps->cnpjPrestador);
$prest->appendChild($cnpj);
$prest->appendChild($this->buildRegTrib($doc, $dps));
$infDps->appendChild($prest);
- // Service block
- $serv = $doc->createElement('serv');
-
- $itemListaServico = $doc->createElement('cServ');
- $itemListaServico->appendChild($doc->createElement('cTribNac', $dps->codigoTributacaoNacional));
- $serv->appendChild($itemListaServico);
-
- $serv->appendChild($doc->createElement('xDescServ', htmlspecialchars($dps->discriminacao, ENT_XML1)));
- $infDps->appendChild($serv);
-
- // Tomador (optional — absent for foreign buyers with no document)
if ($dps->documentoTomador !== '') {
$infDps->appendChild($this->buildToma($doc, $dps));
}
- // Values
- $valores = $doc->createElement('valores');
-
- $vServPrest = $doc->createElement('vServPrest');
- $vServPrest->appendChild($doc->createElement('vServ', $dps->valorServico));
- $valores->appendChild($vServPrest);
-
- $valores->appendChild($this->buildTotTrib($doc, $dps));
- $infDps->appendChild($valores);
+ $infDps->appendChild($this->buildServico($doc, $dps));
+ $infDps->appendChild($this->buildValores($doc, $dps));
return $doc->saveXML() ?: '';
}
@@ -85,35 +73,90 @@ private function buildIdentifier(DpsData $dps): string
. str_pad($dps->numeroDps, 15, '0', STR_PAD_LEFT);
}
- private function buildTotTrib(\DOMDocument $doc, DpsData $dps): \DOMElement
+ private function buildValores(\DOMDocument $doc, DpsData $dps): \DOMElement
{
- $totTrib = $doc->createElement('totTrib');
+ $valores = $doc->createElement('valores');
- // tribMun contains ISS and conditional pAliq
+ $vServPrest = $doc->createElement('vServPrest');
+ $vServPrest->appendChild($doc->createElement('vServ', $dps->valorServico));
+ $valores->appendChild($vServPrest);
+
+ $trib = $doc->createElement('trib');
+ $trib->appendChild($this->buildTribMun($doc, $dps));
+
+ if ($this->hasFederalTaxationData($dps)) {
+ $trib->appendChild($this->buildTribFederal($doc, $dps));
+ }
+
+ if ($this->hasTotalTributosPercentuais($dps)) {
+ $trib->appendChild($this->buildTotTrib($doc, $dps));
+ }
+
+ $valores->appendChild($trib);
+
+ return $valores;
+ }
+
+ private function buildTribMun(\DOMDocument $doc, DpsData $dps): \DOMElement
+ {
$tribMun = $doc->createElement('tribMun');
$tribMun->appendChild($doc->createElement('tribISSQN', $dps->issRetido ? '2' : '1'));
$tribMun->appendChild($doc->createElement('tpRetISSQN', (string) $dps->tipoRetencaoIss));
- // E0617: For não optante (opSimpNac=1), pAliq must NOT be present
if ($dps->opcaoSimplesNacional !== 1) {
$tribMun->appendChild($doc->createElement('pAliq', $dps->aliquota));
}
- $totTrib->appendChild($tribMun);
+ return $tribMun;
+ }
- if ($this->hasFederalTaxationData($dps)) {
- $totTrib->appendChild($this->buildTribFederal($doc, $dps));
+ private function buildTotTrib(\DOMDocument $doc, DpsData $dps): \DOMElement
+ {
+ $totTrib = $doc->createElement('totTrib');
+ $percentuais = $doc->createElement('pTotTrib');
+
+ if ($dps->totalTributosPercentualFederal !== '') {
+ $percentuais->appendChild($doc->createElement('pTotTribFed', $dps->totalTributosPercentualFederal));
+ }
+
+ if ($dps->totalTributosPercentualEstadual !== '') {
+ $percentuais->appendChild($doc->createElement('pTotTribEst', $dps->totalTributosPercentualEstadual));
+ }
+
+ if ($dps->totalTributosPercentualMunicipal !== '') {
+ $percentuais->appendChild($doc->createElement('pTotTribMun', $dps->totalTributosPercentualMunicipal));
}
- // E0715: indTotTrib is ALWAYS included to avoid schema validation errors
- $totTrib->appendChild($doc->createElement('indTotTrib', (string) $dps->indicadorTributacao));
+ $totTrib->appendChild($percentuais);
return $totTrib;
}
+ private function buildServico(\DOMDocument $doc, DpsData $dps): \DOMElement
+ {
+ $serv = $doc->createElement('serv');
+
+ $locPrest = $doc->createElement('locPrest');
+ $locPrest->appendChild($doc->createElement('cLocPrestacao', $dps->municipioIbge));
+ $serv->appendChild($locPrest);
+
+ $cServ = $doc->createElement('cServ');
+ $cServ->appendChild($doc->createElement('cTribNac', $dps->codigoTributacaoNacional));
+
+ if ($dps->itemListaServico !== '') {
+ $cServ->appendChild($doc->createElement('cTribMun', $dps->itemListaServico));
+ }
+
+ $cServ->appendChild($doc->createElement('xDescServ', htmlspecialchars($dps->discriminacao, ENT_XML1)));
+ $serv->appendChild($cServ);
+
+ return $serv;
+ }
+
private function buildRegTrib(\DOMDocument $doc, DpsData $dps): \DOMElement
{
$regTrib = $doc->createElement('regTrib');
+ $regTrib->appendChild($doc->createElement('opSimpNac', (string) $dps->opcaoSimplesNacional));
$regTrib->appendChild($doc->createElement('regEspTrib', (string) $dps->regimeEspecialTributacao));
return $regTrib;
@@ -141,26 +184,38 @@ private function buildToma(\DOMDocument $doc, DpsData $dps): \DOMElement
private function buildTribFederal(\DOMDocument $doc, DpsData $dps): \DOMElement
{
$tribFed = $doc->createElement('tribFed');
+ $piscofins = $doc->createElement('piscofins');
if ($dps->federalPiscofinsSituacaoTributaria !== '') {
- $tribFed->appendChild($doc->createElement('sitTribPISCOFINS', $dps->federalPiscofinsSituacaoTributaria));
+ $piscofins->appendChild($doc->createElement('CST', str_pad($dps->federalPiscofinsSituacaoTributaria, 2, '0', STR_PAD_LEFT)));
+ }
+
+ foreach ([
+ 'vBCPisCofins' => $dps->federalPiscofinsBaseCalculo,
+ 'pAliqPis' => $dps->federalPiscofinsAliquotaPis,
+ 'pAliqCofins' => $dps->federalPiscofinsAliquotaCofins,
+ 'vPis' => $dps->federalPiscofinsValorPis,
+ 'vCofins' => $dps->federalPiscofinsValorCofins,
+ ] as $tag => $value) {
+ if ($value !== '') {
+ $piscofins->appendChild($doc->createElement($tag, $value));
+ }
}
if ($dps->federalPiscofinsTipoRetencao !== '') {
- $tribFed->appendChild($doc->createElement('tpRetPISCOFINSCSLL', $dps->federalPiscofinsTipoRetencao));
+ $piscofins->appendChild($doc->createElement('tpRetPisCofins', $dps->federalPiscofinsTipoRetencao));
+ }
+
+ if ($piscofins->hasChildNodes()) {
+ $tribFed->appendChild($piscofins);
}
foreach ([
- 'vBCPISCOFINS' => $dps->federalPiscofinsBaseCalculo,
- 'pAliqPIS' => $dps->federalPiscofinsAliquotaPis,
- 'vPIS' => $dps->federalPiscofinsValorPis,
- 'pAliqCOFINS' => $dps->federalPiscofinsAliquotaCofins,
- 'vCOFINS' => $dps->federalPiscofinsValorCofins,
- 'vIRRF' => $dps->federalValorIrrf,
- 'vCSLL' => $dps->federalValorCsll,
- 'vCP' => $dps->federalValorCp,
+ 'vRetIRRF' => $dps->federalValorIrrf,
+ 'vRetCSLL' => $dps->federalValorCsll,
+ 'vRetCP' => $dps->federalValorCp,
] as $tag => $value) {
- if ($value !== '') {
+ if ($this->hasNonZeroDecimalValue($value)) {
$tribFed->appendChild($doc->createElement($tag, $value));
}
}
@@ -168,6 +223,18 @@ private function buildTribFederal(\DOMDocument $doc, DpsData $dps): \DOMElement
return $tribFed;
}
+ private function formattedEmissionDateTime(): string
+ {
+ return (new \DateTimeImmutable())->format('Y-m-d\\TH:i:sP');
+ }
+
+ private function hasTotalTributosPercentuais(DpsData $dps): bool
+ {
+ return $dps->totalTributosPercentualFederal !== ''
+ || $dps->totalTributosPercentualEstadual !== ''
+ || $dps->totalTributosPercentualMunicipal !== '';
+ }
+
private function hasFederalTaxationData(DpsData $dps): bool
{
return $dps->federalPiscofinsSituacaoTributaria !== ''
@@ -177,8 +244,13 @@ private function hasFederalTaxationData(DpsData $dps): bool
|| $dps->federalPiscofinsValorPis !== ''
|| $dps->federalPiscofinsAliquotaCofins !== ''
|| $dps->federalPiscofinsValorCofins !== ''
- || $dps->federalValorIrrf !== ''
- || $dps->federalValorCsll !== ''
- || $dps->federalValorCp !== '';
+ || $this->hasNonZeroDecimalValue($dps->federalValorIrrf)
+ || $this->hasNonZeroDecimalValue($dps->federalValorCsll)
+ || $this->hasNonZeroDecimalValue($dps->federalValorCp);
+ }
+
+ private function hasNonZeroDecimalValue(string $value): bool
+ {
+ return $value !== '' && (float) $value !== 0.0;
}
}
From b80f6fec17e2c954ea853484f9daee1ddbb41c38 Mon Sep 17 00:00:00 2001
From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Date: Wed, 1 Apr 2026 17:42:23 -0300
Subject: [PATCH 3/4] test(xml): update and extend XmlBuilder tests for new
structure
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
---
tests/Unit/Xml/XmlBuilderTest.php | 111 ++++++++++++++++++++++++------
1 file changed, 90 insertions(+), 21 deletions(-)
diff --git a/tests/Unit/Xml/XmlBuilderTest.php b/tests/Unit/Xml/XmlBuilderTest.php
index ee22abe..fd8a0ae 100644
--- a/tests/Unit/Xml/XmlBuilderTest.php
+++ b/tests/Unit/Xml/XmlBuilderTest.php
@@ -72,6 +72,35 @@ public function testBuildDpsContainsMunicipioIbge(): void
self::assertStringContainsString('3303302', $xml);
self::assertStringContainsString('3303302', $xml);
+ self::assertStringContainsString('3303302', $xml);
+ }
+
+ public function testBuildDpsStartsInfDpsWithTpAmbBeforeMunicipalityFields(): void
+ {
+ $xml = $this->builder->buildDps($this->makeDps(municipioIbge: '3303302'));
+
+ $doc = new \DOMDocument();
+ $doc->loadXML($xml);
+ $xpath = new \DOMXPath($doc);
+ $xpath->registerNamespace('n', 'http://www.sped.fazenda.gov.br/nfse');
+
+ $infDps = $xpath->query('//n:infDPS')->item(0);
+ self::assertNotNull($infDps);
+
+ $headerElements = [];
+
+ foreach ($infDps?->childNodes ?? [] as $childNode) {
+ if ($childNode instanceof \DOMElement) {
+ $headerElements[] = $childNode->localName;
+ }
+ }
+
+ self::assertSame(
+ ['tpAmb', 'dhEmi', 'verAplic', 'serie', 'nDPS', 'dCompet', 'tpEmit', 'cLocEmi'],
+ array_slice($headerElements, 0, 8),
+ );
+ self::assertSame('2', $xpath->query('//n:infDPS/n:tpAmb')->item(0)?->textContent);
+ self::assertSame(0, $xpath->query('//n:infDPS/n:cMun')->length);
}
public function testBuildDpsUsesNationalTaxCodeInCtribnac(): void
@@ -79,7 +108,10 @@ public function testBuildDpsUsesNationalTaxCodeInCtribnac(): void
$dps = $this->makeDps(itemListaServico: '0107', codigoTributacaoNacional: '101011');
$xml = $this->builder->buildDps($dps);
- self::assertStringContainsString('101011', str_replace(["\n", ' '], '', $xml));
+ self::assertStringContainsString(
+ '1010110107Consultoria em TI',
+ str_replace(["\n", ' '], '', $xml),
+ );
}
public function testBuildDpsContainsValorServico(): void
@@ -193,6 +225,10 @@ public function testBuildDpsAlwaysIncludesProviderTaxRegime(): void
$nodes = $xpath->query('//n:prest/n:regTrib/n:regEspTrib');
self::assertSame(1, $nodes->length, ' must always be present');
self::assertSame('0', $nodes->item(0)->textContent);
+
+ $simplesNodes = $xpath->query('//n:prest/n:regTrib/n:opSimpNac');
+ self::assertSame(1, $simplesNodes->length, ' must always be present');
+ self::assertSame('1', $simplesNodes->item(0)->textContent);
}
public function testBuildDpsIncludesFederalTaxationBlockWhenConfigured(): void
@@ -213,16 +249,37 @@ public function testBuildDpsIncludesFederalTaxationBlockWhenConfigured(): void
$xml = $this->builder->buildDps($dps);
self::assertStringContainsString('', $xml);
- self::assertStringContainsString('1', $xml);
- self::assertStringContainsString('3', $xml);
- self::assertStringContainsString('1000.00', $xml);
- self::assertStringContainsString('1.65', $xml);
- self::assertStringContainsString('16.50', $xml);
- self::assertStringContainsString('7.60', $xml);
- self::assertStringContainsString('76.00', $xml);
- self::assertStringContainsString('15.00', $xml);
- self::assertStringContainsString('10.00', $xml);
- self::assertStringContainsString('5.00', $xml);
+ self::assertStringContainsString('', $xml);
+ self::assertStringContainsString('01', $xml);
+ self::assertStringContainsString('3', $xml);
+ self::assertStringContainsString('1000.00', $xml);
+ self::assertStringContainsString('1.65', $xml);
+ self::assertStringContainsString('16.50', $xml);
+ self::assertStringContainsString('7.60', $xml);
+ self::assertStringContainsString('76.00', $xml);
+ self::assertStringContainsString('15.00', $xml);
+ self::assertStringContainsString('10.00', $xml);
+ self::assertStringContainsString('5.00', $xml);
+ }
+
+ public function testBuildDpsOmitsZeroValuedOptionalFederalRetentions(): void
+ {
+ $xml = $this->builder->buildDps($this->makeDps(
+ federalPiscofinsSituacaoTributaria: '1',
+ federalPiscofinsTipoRetencao: '4',
+ federalPiscofinsBaseCalculo: '14227.50',
+ federalPiscofinsAliquotaPis: '0.65',
+ federalPiscofinsValorPis: '92.48',
+ federalPiscofinsAliquotaCofins: '3.00',
+ federalPiscofinsValorCofins: '426.83',
+ federalValorIrrf: '472.50',
+ federalValorCsll: '0.00',
+ federalValorCp: '0.00',
+ ));
+
+ self::assertStringContainsString('472.50', $xml);
+ self::assertStringNotContainsString('', $xml);
+ self::assertStringNotContainsString('', $xml);
}
// -------------------------------------------------------------------------
@@ -240,15 +297,10 @@ public function testNonSimplesnacionalMustNotIncludeIndtottribAndPaliq(): void
);
$xml = $this->builder->buildDps($dpsNaoOptante);
- // For "não optante" (opSimpNac = 1), pAliq must NOT be present
- // but indTotTrib is now ALWAYS included (even if 0) to avoid schema validation errors
+ // For "não optante" (opSimpNac = 1), pAliq must NOT be present.
self::assertStringNotContainsString('', $xml);
- self::assertStringContainsString('', $xml);
-
- // totTrib container must exist with content
- self::assertStringContainsString('', $xml);
- // tribMun and tribISSQN must still exist
self::assertStringContainsString('', $xml);
self::assertStringContainsString('', $xml);
}
@@ -263,13 +315,24 @@ public function testOptiontSimplesnacionalIncludesIndtottribAndPaliq(): void
valorServico: '1000.00',
aliquota: '5.00',
opcaoSimplesNacional: 2, // optante
- indicadorTributacao: 1,
);
$xml = $this->builder->buildDps($dpsOptante);
- // For "optante" (opSimpNac = 2), indTotTrib and pAliq MUST be present
- self::assertStringContainsString('', $xml);
+ // For "optante" (opSimpNac = 2), pAliq MUST be present.
self::assertStringContainsString('', $xml);
+ self::assertStringNotContainsString('', $xml);
+ }
+
+ public function testBuildDpsIncludesTotalTributosPercentuaisWhenConfigured(): void
+ {
+ $xml = $this->builder->buildDps($this->makeDps(
+ indicadorTributacao: 2,
+ totalTributosPercentualFederal: '3.65',
+ totalTributosPercentualEstadual: '0.00',
+ totalTributosPercentualMunicipal: '2.00',
+ ));
+
+ self::assertStringContainsString('3.650.002.00', str_replace(["\n", ' '], '', $xml));
}
// -------------------------------------------------------------------------
@@ -291,6 +354,9 @@ private function makeDps(
int $tipoRetencaoIss = 1,
int $opcaoSimplesNacional = 1,
int $indicadorTributacao = 0,
+ string $totalTributosPercentualFederal = '',
+ string $totalTributosPercentualEstadual = '',
+ string $totalTributosPercentualMunicipal = '',
string $federalPiscofinsSituacaoTributaria = '',
string $federalPiscofinsTipoRetencao = '',
string $federalPiscofinsBaseCalculo = '',
@@ -319,6 +385,9 @@ private function makeDps(
issRetido: $issRetido,
opcaoSimplesNacional: $opcaoSimplesNacional,
indicadorTributacao: $indicadorTributacao,
+ totalTributosPercentualFederal: $totalTributosPercentualFederal,
+ totalTributosPercentualEstadual: $totalTributosPercentualEstadual,
+ totalTributosPercentualMunicipal: $totalTributosPercentualMunicipal,
federalPiscofinsSituacaoTributaria: $federalPiscofinsSituacaoTributaria,
federalPiscofinsTipoRetencao: $federalPiscofinsTipoRetencao,
federalPiscofinsBaseCalculo: $federalPiscofinsBaseCalculo,
From 7905c2b59f3f90f921a40275a1c68e94f2d2f04d Mon Sep 17 00:00:00 2001
From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Date: Wed, 1 Apr 2026 17:42:23 -0300
Subject: [PATCH 4/4] test(client): fix cMun->cLocEmi assertion and extend emit
coverage
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
---
tests/Unit/Http/NfseClientTest.php | 44 ++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/tests/Unit/Http/NfseClientTest.php b/tests/Unit/Http/NfseClientTest.php
index f566c6f..a7aaa2f 100644
--- a/tests/Unit/Http/NfseClientTest.php
+++ b/tests/Unit/Http/NfseClientTest.php
@@ -79,6 +79,50 @@ public function testEmitReturnsReceiptDataOnSuccess(): void
self::assertSame('ok', $receipt->rawXml);
}
+ public function testEmitBuildsXmlWithTpAmbBeforeMunicipalityFields(): void
+ {
+ $payload = json_encode([
+ 'nNFSe' => '100',
+ 'chaveAcesso' => 'tpamb-order-ok',
+ 'dataHoraProcessamento' => '2026-01-02T10:00:00',
+ ], JSON_THROW_ON_ERROR);
+
+ self::$server->setResponseOfPath(
+ '/SefinNacional/nfse',
+ new Response($payload, ['Content-Type' => 'application/json'], 201)
+ );
+
+ $holder = new class () {
+ public string $capturedXml = '';
+ };
+
+ $capturingSigner = new class ($holder) implements XmlSignerInterface {
+ public function __construct(private object $holder)
+ {
+ }
+
+ public function sign(string $xml, string $cnpj): string
+ {
+ $this->holder->capturedXml = $xml;
+
+ return $xml;
+ }
+ };
+
+ $client = $this->makeClient($capturingSigner);
+ $client->emit($this->makeDps());
+
+ self::assertNotSame('', $holder->capturedXml);
+
+ $normalizedXml = str_replace(["\n", ' '], '', $holder->capturedXml);
+ $tpAmbIndex = strpos($normalizedXml, '2');
+ $cLocEmiIndex = strpos($normalizedXml, '3303302');
+
+ self::assertNotFalse($tpAmbIndex);
+ self::assertNotFalse($cLocEmiIndex);
+ self::assertLessThan($cLocEmiIndex, $tpAmbIndex);
+ }
+
public function testQueryReturnsReceiptDataOnSuccess(): void
{
$payload = json_encode([