From 41e2260e95e4b2b26083fe2c1aad19de23757806 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Tue, 13 Aug 2019 10:24:38 -0500 Subject: [PATCH 1/8] On tests, create Fiel using FielData --- tests/TestCase.php | 9 +++++---- tests/Unit/Shared/FielTest.php | 10 +++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/TestCase.php b/tests/TestCase.php index f3ad45c..663c1d5 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -6,6 +6,7 @@ use DOMDocument; use PhpCfdi\SatWsDescargaMasiva\Shared\Fiel; +use PhpCfdi\SatWsDescargaMasiva\Tests\Scripts\Helpers\FielData; class TestCase extends \PHPUnit\Framework\TestCase { @@ -22,12 +23,12 @@ public static function fileContents(string $filename): string public function createFielUsingTestingFiles(string $password = null): Fiel { - $fiel = new Fiel( - $this->fileContents('fake-fiel/aaa010101aaa_FIEL_password.key.pem'), - $this->fileContents('fake-fiel/aaa010101aaa_FIEL.cer'), + $fielData = new FielData( + $this->filePath('fake-fiel/aaa010101aaa_FIEL.cer'), + $this->filePath('fake-fiel/aaa010101aaa_FIEL_password.key.pem'), $password ?? trim($this->fileContents('fake-fiel/password.txt')) ); - return $fiel; + return $fielData->createFiel(); } public static function xmlFormat(string $content): string diff --git a/tests/Unit/Shared/FielTest.php b/tests/Unit/Shared/FielTest.php index 942f169..81042c8 100644 --- a/tests/Unit/Shared/FielTest.php +++ b/tests/Unit/Shared/FielTest.php @@ -4,7 +4,7 @@ namespace PhpCfdi\SatWsDescargaMasiva\Tests\Unit\Shared; -use PhpCfdi\SatWsDescargaMasiva\Shared\Fiel; +use PhpCfdi\SatWsDescargaMasiva\Tests\Scripts\Helpers\FielData; use PhpCfdi\SatWsDescargaMasiva\Tests\TestCase; class FielTest extends TestCase @@ -23,11 +23,11 @@ public function testFielWithCorrectPassword(): void public function testFielUnprotected(): void { - $fiel = new Fiel( - $this->fileContents('fake-fiel/aaa010101aaa_FIEL.key.pem'), - $this->fileContents('fake-fiel/aaa010101aaa_FIEL.cer'), + $fiel = (new FielData( + $this->filePath('fake-fiel/aaa010101aaa_FIEL.cer'), + $this->filePath('fake-fiel/aaa010101aaa_FIEL.key.pem'), '' - ); + ))->createFiel(); $this->assertTrue($fiel->isValid()); } } From cadd4230965fa0a7d3d648d42dcf8f3d9ee12e5b Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Tue, 13 Aug 2019 16:46:06 -0500 Subject: [PATCH 2/8] Refactor Fiel to depends on phpcfdi/credentials eclipxe/cfdiutils is droped in favor of phpcfdi/credentials --- composer.json | 2 +- src/Shared/Certificado.php | 263 ----------------------------- src/Shared/Fiel.php | 59 +++---- tests/Scripts/Helpers/FielData.php | 9 +- tests/Unit/Shared/FielTest.php | 7 +- 5 files changed, 30 insertions(+), 310 deletions(-) delete mode 100644 src/Shared/Certificado.php diff --git a/composer.json b/composer.json index e3733ee..f226d8f 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "ext-dom": "*", "ext-json": "*", "ext-zip": "*", - "eclipxe/cfdiutils": "^2.10", + "phpcfdi/credentials": "dev-master", "eclipxe/enum": "^0.2.0" }, "require-dev": { diff --git a/src/Shared/Certificado.php b/src/Shared/Certificado.php deleted file mode 100644 index c43056f..0000000 --- a/src/Shared/Certificado.php +++ /dev/null @@ -1,263 +0,0 @@ -setOpenSSL($openSSL ?: new OpenSSL()); - $contents = $this->obtainPemCertificate($contents); - - // get the certificate data - $data = openssl_x509_parse($contents, true); - if (! is_array($data)) { - throw new RuntimeException('Cannot parse certificate contents'); - } - - // get the public key - $pubKey = $this->obtainPubKeyFromContents($contents); - - // set all the values - $this->certificateName = strval($data['name'] ?? ''); - $this->rfc = (string) strstr(($data['subject']['x500UniqueIdentifier'] ?? '') . ' ', ' ', true); - $this->name = strval($data['subject']['name'] ?? ''); - $serial = new SerialNumber(''); - if (isset($data['serialNumberHex'])) { - $serial->loadHexadecimal($data['serialNumberHex']); - } elseif (isset($data['serialNumber'])) { - $serial->loadDecimal($data['serialNumber']); - } else { - throw new RuntimeException('Cannot get serialNumberHex or serialNumber from certificate'); - } - $this->serial = $serial; - $this->validFrom = $data['validFrom_time_t'] ?? 0; - $this->validTo = $data['validTo_time_t'] ?? 0; - $this->pubkey = $pubKey; - $this->pemContents = $contents; - } - - private function obtainPemCertificate(string $contents): string - { - $openssl = $this->getOpenSSL(); - $extracted = $openssl->readPemContents($contents)->certificate(); - if ('' === $extracted) { // cannot extract, could be on DER format - $extracted = $openssl->derCerConvertPhp($contents); - } - return $extracted; - } - - /** - * Check if this certificate belongs to a private key - * - * @param string $pemKeyFile - * @param string $passPhrase - * - * @return bool - * - * @throws UnexpectedValueException if the file does not exists or is not readable - * @throws UnexpectedValueException if the file is not a PEM private key - * @throws RuntimeException if cannot open the private key file - */ - public function belongsTo(string $pemKeyFile, string $passPhrase = ''): bool - { - $this->assertFileExists($pemKeyFile); - $openSSL = $this->getOpenSSL(); - $keyContents = $openSSL->readPemContents( - // intentionally silence this error, if return false then cast it to string - strval(@file_get_contents($pemKeyFile)) - )->privateKey(); - if ('' === $keyContents) { - throw new UnexpectedValueException("The file $pemKeyFile is not a PEM private key"); - } - $privateKey = openssl_get_privatekey($keyContents, $passPhrase); - if (false === $privateKey) { - throw new RuntimeException("Cannot open the private key file $pemKeyFile"); - } - $belongs = openssl_x509_check_private_key($this->getPemContents(), $privateKey); - openssl_free_key($privateKey); - return $belongs; - } - - /** - * RFC (Registro Federal de Contribuyentes) set when certificate was created - * @return string - */ - public function getRfc(): string - { - return $this->rfc; - } - - public function getCertificateName(): string - { - return $this->certificateName; - } - - /** - * Name (Razón Social) set when certificate was created - * @return string - */ - public function getName(): string - { - return $this->name; - } - - /** - * Certificate serial number as ASCII, this data is in the format required by CFDI - * @return string - */ - public function getSerial(): string - { - return $this->serial->asAscii(); - } - - public function getSerialObject(): SerialNumber - { - return clone $this->serial; - } - - /** - * Timestamp since the certificate is valid - * @return int - */ - public function getValidFrom(): int - { - return $this->validFrom; - } - - /** - * Timestamp until the certificate is valid - * @return int - */ - public function getValidTo(): int - { - return $this->validTo; - } - - /** - * String representation of the public key - * @return string - */ - public function getPubkey(): string - { - return $this->pubkey; - } - - /** - * The contents of the certificate in PEM format - * @return string - */ - public function getPemContents(): string - { - return $this->pemContents; - } - - /** - * Verify the signature of some data - * - * @param string $data - * @param string $signature - * @param int $algorithm - * - * @return bool - * - * @throws RuntimeException if cannot open the public key from certificate - * @throws RuntimeException if openssl report an error - */ - public function verify(string $data, string $signature, int $algorithm = OPENSSL_ALGO_SHA256): bool - { - $pubKey = openssl_get_publickey($this->getPubkey()); - if (false === $pubKey) { - throw new RuntimeException('Cannot open public key from certificate'); - } - try { - $verify = openssl_verify($data, $signature, $pubKey, $algorithm); - if (-1 === $verify) { - throw new RuntimeException('OpenSSL Error: ' . openssl_error_string()); - } - } finally { - openssl_free_key($pubKey); - } - return (1 === $verify); - } - - /** - * @param string $filename - * @throws UnexpectedValueException when the file does not exists or is not readable - * @return void - */ - protected function assertFileExists(string $filename): void - { - if (! file_exists($filename) || ! is_readable($filename) || is_dir($filename)) { - throw new UnexpectedValueException("File $filename does not exists or is not readable"); - } - } - - protected function obtainPubKeyFromContents(string $contents): string - { - try { - $pubkey = openssl_get_publickey($contents); - if (! is_resource($pubkey)) { - return ''; - } - $pubData = openssl_pkey_get_details($pubkey) ?: []; - return $pubData['key'] ?? ''; - } finally { - // close public key even if the flow is throw an exception - if (is_resource($pubkey)) { - openssl_free_key($pubkey); - } - } - } -} diff --git a/src/Shared/Fiel.php b/src/Shared/Fiel.php index e06f780..e0a97e8 100644 --- a/src/Shared/Fiel.php +++ b/src/Shared/Fiel.php @@ -4,78 +4,57 @@ namespace PhpCfdi\SatWsDescargaMasiva\Shared; -use CfdiUtils\OpenSSL\OpenSSL; -use CfdiUtils\PemPrivateKey\PemPrivateKey; +use PhpCfdi\Credentials\Credential; class Fiel { - /** @var PemPrivateKey */ - private $privateKey; + /** @var Credential */ + private $credential; - /** @var Certificado*/ - private $certificate; - - /** @var string */ - private $passPhrase; + public function __construct(Credential $credential) + { + $this->credential = $credential; + } - public function __construct(string $pemPrivateKey, string $pemCertificate, string $passPhrase) + public function create(string $certificate, string $privateKey, string $passPhrase): self { - $openSsl = new OpenSSL(); - $this->privateKey = new PemPrivateKey($pemPrivateKey, $openSsl); - $this->certificate = new Certificado($pemCertificate, $openSsl); - $this->passPhrase = $passPhrase; + $credential = Credential::create($certificate, $privateKey, $passPhrase); + return new self($credential); } public function sign(string $toSign, int $algorithm = OPENSSL_ALGO_SHA1): string { - $this->privateKey->open($this->passPhrase); - try { - return $this->privateKey->sign($toSign, $algorithm); - } finally { - $this->privateKey->close(); - } + return $this->credential->sign($toSign, $algorithm); } public function isValid(): bool { - if (! $this->privateKey->open($this->passPhrase)) { + if (! $this->credential->certificate()->satType()->isFiel()) { return false; } - try { - return $this->privateKey->belongsTo($this->getCertificatePemContents()); - } finally { - $this->privateKey->close(); + if (! $this->credential->certificate()->validOn()) { + return false; } + return true; } public function getCertificatePemContents(): string { - return $this->certificate->getPemContents(); + return $this->credential->certificate()->pem(); } public function getRfc(): string { - return $this->certificate->getRfc(); + return $this->credential->rfc(); } public function getCertificateSerial(): string { - return $this->certificate->getSerialObject()->asDecimal(); + return $this->credential->certificate()->serialNumber()->decimal(); } public function getCertificateIssuerName(): string { - $data = openssl_x509_parse($this->certificate->getPemContents()) ?: []; - $issuerData = $data['issuer'] ?? []; - if (! is_array($issuerData)) { - $issuerData = []; - } - return implode(',', array_map( - function ($key, $value): string { - return $key . '=' . $value; - }, - array_keys($issuerData), - $issuerData - )); + return $this->credential->certificate()->issuerAsRfc4514(); } } diff --git a/tests/Scripts/Helpers/FielData.php b/tests/Scripts/Helpers/FielData.php index bf807cc..d525940 100644 --- a/tests/Scripts/Helpers/FielData.php +++ b/tests/Scripts/Helpers/FielData.php @@ -4,6 +4,7 @@ namespace PhpCfdi\SatWsDescargaMasiva\Tests\Scripts\Helpers; +use PhpCfdi\Credentials\Credential; use PhpCfdi\SatWsDescargaMasiva\Shared\Fiel; use RuntimeException; @@ -43,9 +44,11 @@ public function getPassPhrase(): string public function createFiel(): Fiel { return new Fiel( - $this->readContents($this->getPrivateKeyFile()), - $this->readContents($this->getCertificateFile()), - $this->getPassPhrase() + Credential::openFiles( + $this->getCertificateFile(), + $this->getPrivateKeyFile(), + $this->getPassPhrase() + ) ); } diff --git a/tests/Unit/Shared/FielTest.php b/tests/Unit/Shared/FielTest.php index 81042c8..7074cbf 100644 --- a/tests/Unit/Shared/FielTest.php +++ b/tests/Unit/Shared/FielTest.php @@ -4,15 +4,16 @@ namespace PhpCfdi\SatWsDescargaMasiva\Tests\Unit\Shared; +use Exception; use PhpCfdi\SatWsDescargaMasiva\Tests\Scripts\Helpers\FielData; use PhpCfdi\SatWsDescargaMasiva\Tests\TestCase; class FielTest extends TestCase { - public function testFielWithIncorrectPassword(): void + public function testFielWithIncorrectPasswordCreateAnException(): void { - $fiel = $this->createFielUsingTestingFiles('invalid password'); - $this->assertFalse($fiel->isValid()); + $this->expectException(Exception::class); + $this->createFielUsingTestingFiles('invalid password'); } public function testFielWithCorrectPassword(): void From d713cd8469a7fc68d4df539d2dec9cc882031c3f Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Tue, 13 Aug 2019 16:52:53 -0500 Subject: [PATCH 3/8] Change `,` to `\2c` according to RFC 4514 --- tests/_files/download/request.xml | 2 +- tests/_files/query/request.xml | 2 +- tests/_files/verify/request.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/_files/download/request.xml b/tests/_files/download/request.xml index 01f6261..a075d56 100644 --- a/tests/_files/download/request.xml +++ b/tests/_files/download/request.xml @@ -19,7 +19,7 @@ - CN=A.C. 2 de pruebas(4096),O=Servicio de Administración Tributaria,OU=Administración de Seguridad de la Información,emailAddress=asisnet@pruebas.sat.gob.mx,street=Av. Hidalgo 77, Col. Guerrero,postalCode=06300,C=MX,ST=Distrito Federal,L=Coyoacán,x500UniqueIdentifier=SAT970701NN3,unstructuredName=Responsable: ACDMA + CN=A.C. 2 de pruebas(4096),O=Servicio de Administración Tributaria,OU=Administración de Seguridad de la Información,emailAddress=asisnet@pruebas.sat.gob.mx,street=Av. Hidalgo 77\2c Col. Guerrero,postalCode=06300,C=MX,ST=Distrito Federal,L=Coyoacán,x500UniqueIdentifier=SAT970701NN3,unstructuredName=Responsable: ACDMA 292233162870206001759766198425879490508935804981 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 diff --git a/tests/_files/query/request.xml b/tests/_files/query/request.xml index 8d99b47..1a9d4ed 100644 --- a/tests/_files/query/request.xml +++ b/tests/_files/query/request.xml @@ -20,7 +20,7 @@ - CN=A.C. 2 de pruebas(4096),O=Servicio de Administración Tributaria,OU=Administración de Seguridad de la Información,emailAddress=asisnet@pruebas.sat.gob.mx,street=Av. Hidalgo 77, Col. Guerrero,postalCode=06300,C=MX,ST=Distrito Federal,L=Coyoacán,x500UniqueIdentifier=SAT970701NN3,unstructuredName=Responsable: ACDMA + CN=A.C. 2 de pruebas(4096),O=Servicio de Administración Tributaria,OU=Administración de Seguridad de la Información,emailAddress=asisnet@pruebas.sat.gob.mx,street=Av. Hidalgo 77\2c Col. Guerrero,postalCode=06300,C=MX,ST=Distrito Federal,L=Coyoacán,x500UniqueIdentifier=SAT970701NN3,unstructuredName=Responsable: ACDMA 292233162870206001759766198425879490508935804981 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 diff --git a/tests/_files/verify/request.xml b/tests/_files/verify/request.xml index 97da178..15db7ab 100644 --- a/tests/_files/verify/request.xml +++ b/tests/_files/verify/request.xml @@ -19,7 +19,7 @@ - CN=A.C. 2 de pruebas(4096),O=Servicio de Administración Tributaria,OU=Administración de Seguridad de la Información,emailAddress=asisnet@pruebas.sat.gob.mx,street=Av. Hidalgo 77, Col. Guerrero,postalCode=06300,C=MX,ST=Distrito Federal,L=Coyoacán,x500UniqueIdentifier=SAT970701NN3,unstructuredName=Responsable: ACDMA + CN=A.C. 2 de pruebas(4096),O=Servicio de Administración Tributaria,OU=Administración de Seguridad de la Información,emailAddress=asisnet@pruebas.sat.gob.mx,street=Av. Hidalgo 77\2c Col. Guerrero,postalCode=06300,C=MX,ST=Distrito Federal,L=Coyoacán,x500UniqueIdentifier=SAT970701NN3,unstructuredName=Responsable: ACDMA 292233162870206001759766198425879490508935804981 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 From ec6461a5588e042f4e74ad2f34aa76b8acbc2e68 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Tue, 13 Aug 2019 16:59:40 -0500 Subject: [PATCH 4/8] Fiel::create method should be static, create test --- src/Shared/Fiel.php | 2 +- tests/Unit/Shared/FielTest.php | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Shared/Fiel.php b/src/Shared/Fiel.php index e0a97e8..e26c70b 100644 --- a/src/Shared/Fiel.php +++ b/src/Shared/Fiel.php @@ -16,7 +16,7 @@ public function __construct(Credential $credential) $this->credential = $credential; } - public function create(string $certificate, string $privateKey, string $passPhrase): self + public static function create(string $certificate, string $privateKey, string $passPhrase): self { $credential = Credential::create($certificate, $privateKey, $passPhrase); return new self($credential); diff --git a/tests/Unit/Shared/FielTest.php b/tests/Unit/Shared/FielTest.php index 7074cbf..6c01e28 100644 --- a/tests/Unit/Shared/FielTest.php +++ b/tests/Unit/Shared/FielTest.php @@ -5,6 +5,7 @@ namespace PhpCfdi\SatWsDescargaMasiva\Tests\Unit\Shared; use Exception; +use PhpCfdi\SatWsDescargaMasiva\Shared\Fiel; use PhpCfdi\SatWsDescargaMasiva\Tests\Scripts\Helpers\FielData; use PhpCfdi\SatWsDescargaMasiva\Tests\TestCase; @@ -31,4 +32,14 @@ public function testFielUnprotected(): void ))->createFiel(); $this->assertTrue($fiel->isValid()); } + + public function testFielCreatingFromContents(): void + { + $fiel = Fiel::create( + $this->fileContents('fake-fiel/aaa010101aaa_FIEL.cer'), + $this->fileContents('fake-fiel/aaa010101aaa_FIEL.key.pem'), + '' + ); + $this->assertTrue($fiel->isValid()); + } } From f0df07a8cfe527f8fa996fc19b543596ce0a9b0a Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Tue, 13 Aug 2019 17:07:07 -0500 Subject: [PATCH 5/8] remove svg extensions on img shields --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 471a248..a120515 100644 --- a/README.md +++ b/README.md @@ -183,11 +183,11 @@ and licensed for use under the MIT License (MIT). Please see [LICENSE][] for mor [coverage]: https://scrutinizer-ci.com/g/phpcfdi/sat-ws-descarga-masiva/code-structure/master/code-coverage/src/ [downloads]: https://packagist.org/packages/phpcfdi/sat-ws-descarga-masiva -[badge-source]: http://img.shields.io/badge/source-phpcfdi/sat--ws--descarga--masiva-blue.svg?style=flat-square -[badge-discord]: https://img.shields.io/discord/459860554090283019.svg?logo=discord&style=flat-square -[badge-release]: https://img.shields.io/github/release/phpcfdi/sat-ws-descarga-masiva.svg?style=flat-square -[badge-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square -[badge-build]: https://img.shields.io/travis/phpcfdi/sat-ws-descarga-masiva/master.svg?style=flat-square -[badge-quality]: https://img.shields.io/scrutinizer/g/phpcfdi/sat-ws-descarga-masiva/master.svg?style=flat-square -[badge-coverage]: https://img.shields.io/scrutinizer/coverage/g/phpcfdi/sat-ws-descarga-masiva/master.svg?style=flat-square -[badge-downloads]: https://img.shields.io/packagist/dt/phpcfdi/sat-ws-descarga-masiva.svg?style=flat-square +[badge-source]: http://img.shields.io/badge/source-phpcfdi/sat--ws--descarga--masiva-blue?style=flat-square +[badge-discord]: https://img.shields.io/discord/459860554090283019?logo=discord&style=flat-square +[badge-release]: https://img.shields.io/github/release/phpcfdi/sat-ws-descarga-masiva?style=flat-square +[badge-license]: https://img.shields.io/badge/license-MIT-brightgreen?style=flat-square +[badge-build]: https://img.shields.io/travis/phpcfdi/sat-ws-descarga-masiva/master?style=flat-square +[badge-quality]: https://img.shields.io/scrutinizer/g/phpcfdi/sat-ws-descarga-masiva/master?style=flat-square +[badge-coverage]: https://img.shields.io/scrutinizer/coverage/g/phpcfdi/sat-ws-descarga-masiva/master?style=flat-square +[badge-downloads]: https://img.shields.io/packagist/dt/phpcfdi/sat-ws-descarga-masiva?style=flat-square From 5caea3e72319f6e0dcd175171379c76f77ce11ad Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Tue, 13 Aug 2019 17:07:46 -0500 Subject: [PATCH 6/8] Fix basic usage according to recent changes --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a120515..5ed9f30 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ use PhpCfdi\SatWsDescargaMasiva\Shared\RequestType; use PhpCfdi\SatWsDescargaMasiva\WebClient\WebClientInterface; // Creación de la fiel -$fiel = new Fiel( +$fiel = Fiel::create( file_get_contents('llaveprivada.key.pem'), // en formato PEM file_get_contents('certificado.cer'), // en formato PEM o DER '12345678a' From 17df9ab677c5679ce53edf5e756ebf8fcd228c5d Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Tue, 13 Aug 2019 17:09:38 -0500 Subject: [PATCH 7/8] Document changes to 0.2.0 --- docs/CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 3271a9c..77d7f73 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -11,6 +11,24 @@ In summary, [SemVer](https://semver.org/) can be viewed as ` Breaking . Feature **Version `0.x.x` doesn't have to apply any of the SemVer rules** +## Version 0.2.0 2019-08-13 + +Breaking changes: + +- `CodeRequest::isNotFound` is replaced by `CodeRequest::isEmptyResult` +- `Fiel` has been rewritten with other dependences. + To create a Fiel object use any of this: + - `FielData::createFiel()` + - `Fiel::create($certificateContents, $privateKeyContents, $passPhrase)` +- XML SEC Signature now follow RFC 4514 on `X509IssuerName` node. +- Removed dependence to `eclipxe/cfdiutils`, it depends now on `phpcfdi/credentials`. + +Other changes: + +- Fix & improve composer/phpunit/travis/scrutinizer calls. +- Fix documentation typos. + + ## Version 0.1.0 2019-08-09 - Initial working release From 3a011eef64dc6ef8c0fa6f89b7703487da2aa215 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Tue, 13 Aug 2019 19:12:22 -0500 Subject: [PATCH 8/8] depends on stable phpcfdi/credentials ^1.0 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index f226d8f..1d9a3c5 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "ext-dom": "*", "ext-json": "*", "ext-zip": "*", - "phpcfdi/credentials": "dev-master", + "phpcfdi/credentials": "^1.0", "eclipxe/enum": "^0.2.0" }, "require-dev": {