Passed
Pull Request — master (#5)
by Carlos C
02:00
created

DocumentSigner   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 72
Duplicated Lines 0 %

Test Coverage

Coverage 97.44%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 36
c 1
b 0
f 0
dl 0
loc 72
ccs 38
cts 39
cp 0.9744
rs 10
wmc 7

6 Methods

Rating   Name   Duplication   Size   Complexity  
A date() 0 3 1
A __construct() 0 5 1
A sign() 0 14 1
A rfc() 0 3 1
A signDocumentUsingCredential() 0 23 2
A content() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpCfdi\Finkok\Helpers;
6
7
use DateTimeImmutable;
8
use DOMDocument;
9
use LogicException;
10
use PhpCfdi\Credentials\Credential;
11
use RobRichards\XMLSecLibs\XMLSecurityDSig;
12
use RobRichards\XMLSecLibs\XMLSecurityKey;
13
14
class DocumentSigner
15
{
16
    /** @var string */
17
    private $rfc;
18
19
    /** @var DateTimeImmutable */
20
    private $date;
21
22
    /** @var string */
23
    private $content;
24
25 1
    public function __construct(string $rfc, DateTimeImmutable $date, string $content)
26
    {
27 1
        $this->rfc = $rfc;
28 1
        $this->date = $date;
29 1
        $this->content = $content;
30 1
    }
31
32 1
    public function rfc(): string
33
    {
34 1
        return $this->rfc;
35
    }
36
37 1
    public function date(): DateTimeImmutable
38
    {
39 1
        return $this->date;
40
    }
41
42 1
    public function content(): string
43
    {
44 1
        return $this->content;
45
    }
46
47 1
    public function sign(string $certificateFile, string $privateKeyFile, string $passPhrase): string
48
    {
49 1
        $document = new DOMDocument('1.0', 'UTF-8');
50 1
        $root = $document->createElement('documento');
51 1
        $document->appendChild($root);
52 1
        $contract = $document->createElement('contrato', $this->content());
53 1
        $contract->setAttribute('rfc', $this->rfc());
54 1
        $contract->setAttribute('fecha', $this->date()->format('Y-m-d\TH:i:s'));
55 1
        $root->appendChild($contract);
56
57 1
        $credential = Credential::openFiles($certificateFile, $privateKeyFile, $passPhrase);
58 1
        $this->signDocumentUsingCredential($document, $credential);
59
60 1
        return $document->saveXML();
61
    }
62
63 1
    public function signDocumentUsingCredential(DOMDocument $document, Credential $credential): void
64
    {
65 1
        $root = $document->documentElement;
66 1
        if (null === $root) {
67
            throw new LogicException('The DOM Document does not contains a root element');
68
        }
69 1
        $objDSig = new XMLSecurityDSig();
70 1
        $objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
71 1
        $objDSig->addReference(
72 1
            $document,
73 1
            XMLSecurityDSig::SHA1,
74 1
            ['http://www.w3.org/2000/09/xmldsig#enveloped-signature'],
75 1
            ['force_uri' => true]
76
        );
77
78 1
        $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, ['type' => 'private']);
79 1
        $objKey->passphrase = $credential->privateKey()->passPhrase(); // set passphrase before loading key
80 1
        $objKey->loadKey($credential->privateKey()->pem(), false, false);
81
82 1
        $objDSig->sign($objKey);
83 1
        $objDSig->add509Cert($credential->certificate()->pem(), true, false);
84
85 1
        $objDSig->appendSignature($root);
86 1
    }
87
}
88