Completed
Pull Request — master (#9)
by Carlos C
03:14
created

DocumentSigner   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 81
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 39
c 2
b 0
f 0
dl 0
loc 81
ccs 44
cts 44
cp 1
rs 10
wmc 9

8 Methods

Rating   Name   Duplication   Size   Complexity  
A date() 0 3 1
A __construct() 0 5 1
A rfc() 0 3 1
A content() 0 3 1
A sign() 0 4 1
A signDocumentUsingCredential() 0 23 2
A createDocumentToSign() 0 10 1
A signUsingCredential() 0 5 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 2
    public function __construct(string $rfc, DateTimeImmutable $date, string $content)
26
    {
27 2
        $this->rfc = $rfc;
28 2
        $this->date = $date;
29 2
        $this->content = $content;
30 2
    }
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
        $credential = Credential::openFiles($certificateFile, $privateKeyFile, $passPhrase);
50 1
        return $this->signUsingCredential($credential);
51
    }
52
53 1
    public function signUsingCredential(Credential $credential): string
54
    {
55 1
        $document = $this->createDocumentToSign();
56 1
        $this->signDocumentUsingCredential($document, $credential);
57 1
        return $document->saveXML();
58
    }
59
60 1
    public function createDocumentToSign(): DOMDocument
61
    {
62 1
        $document = new DOMDocument('1.0', 'UTF-8');
63 1
        $root = $document->createElement('documento');
64 1
        $document->appendChild($root);
65 1
        $contract = $document->createElement('contrato', $this->content());
66 1
        $contract->setAttribute('rfc', $this->rfc());
67 1
        $contract->setAttribute('fecha', $this->date()->format('Y-m-d\TH:i:s'));
68 1
        $root->appendChild($contract);
69 1
        return $document;
70
    }
71
72 2
    public function signDocumentUsingCredential(DOMDocument $document, Credential $credential): void
73
    {
74 2
        $root = $document->documentElement;
75 2
        if (null === $root) {
76 1
            throw new LogicException('The DOM Document does not contains a root element');
77
        }
78 1
        $objDSig = new XMLSecurityDSig();
79 1
        $objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
80 1
        $objDSig->addReference(
81 1
            $document,
82 1
            XMLSecurityDSig::SHA1,
83 1
            ['http://www.w3.org/2000/09/xmldsig#enveloped-signature'],
84 1
            ['force_uri' => true]
85
        );
86
87 1
        $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, ['type' => 'private']);
88 1
        $objKey->passphrase = $credential->privateKey()->passPhrase(); // set passphrase before loading key
89 1
        $objKey->loadKey($credential->privateKey()->pem(), false, false);
90
91 1
        $objDSig->sign($objKey);
92 1
        $objDSig->add509Cert($credential->certificate()->pem(), true, false);
93
94 1
        $objDSig->appendSignature($root);
95 1
    }
96
}
97