Passed
Push — master ( 5bfe47...314d48 )
by Dmitry
01:58
created

Response::generate_sign()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 29
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 5
eloc 15
nc 5
nop 1
dl 0
loc 29
rs 8.439
c 1
b 0
f 1
1
<?php
2
3
/**
4
 *      Abstract class for the family of response classes
5
 *
6
 *      @package php_EasyPay
7
 *      @version 1.1
8
 *      @author Dmitry Shovchko <[email protected]>
9
 *
10
 */
11
12
namespace EasyPay\Provider31;
13
14
use EasyPay\Log as Log;
15
use EasyPay\Key as Key;
16
17
abstract class Response extends \DomDocument
18
{
19
        /**
20
         *      @var string
21
         *
22
         */
23
        const TEMPLATE = '<Response><StatusCode></StatusCode><StatusDetail></StatusDetail><DateTime></DateTime></Response>';
24
25
        /**
26
         *      Response constructor
27
         *
28
         */
29
        public function __construct()
30
        {
31
                parent::__construct('1.0', 'UTF-8');
32
33
                self::loadXML(self::TEMPLATE);
0 ignored issues
show
Bug Best Practice introduced by
The method DOMDocument::loadXML() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

33
                self::/** @scrutinizer ignore-call */ 
34
                      loadXML(self::TEMPLATE);
Loading history...
34
35
                $this->Response = $this->firstChild;
0 ignored issues
show
Bug Best Practice introduced by
The property Response does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
36
                $this->setElementValue('DateTime', date('Y-m-d\TH:i:s', time()));
37
        }
38
39
        /**
40
         *      Create new element node
41
         *
42
         *      @param string $name
43
         *      @param string $value (optional)
44
         */
45
        public function createElement($name, $value=NULL)
46
        {
47
                return parent::createElement($name, $value);
48
        }
49
50
        /**
51
         *      Create new node attribute
52
         *
53
         *      @param string $name
54
         *      @param string $value
55
         */
56
        public function create_attr($name, $value)
57
        {
58
                return new DOMAttr($name, $value);
0 ignored issues
show
Bug introduced by
The type EasyPay\Provider31\DOMAttr was not found. Did you mean DOMAttr? If so, make sure to prefix the type with \.
Loading history...
59
        }
60
61
        /**
62
         *      Set node value
63
         *
64
         *      @param string $name
65
         *      @param string $value
66
         */
67
        public function setElementValue($name, $value)
68
        {
69
                foreach ($this->Response->childNodes as $child)
70
                {
71
                        if ($child->nodeName == $name)
72
                        {
73
                                $child->nodeValue = $value;
74
                        }
75
                }
76
        }
77
78
        /**
79
         *      Dumps response into a string
80
         *
81
         *      @return string XML
82
         */
83
        public function friendly()
84
        {
85
                $this->encoding = 'UTF-8';
86
                $this->formatOutput = true;
87
                //$this->save('/tmp/test1.xml');
88
89
                return $this->saveXML(NULL, LIBXML_NOEMPTYTAG);
90
        }
91
92
        /**
93
         *      Send response
94
         *
95
         *      @param array $options
96
         */
97
        public function out($options)
98
        {
99
                $this->sign($options);
100
101
                Log::instance()->debug('response sends: ');
102
                Log::instance()->debug($this->friendly());
103
104
                ob_clean();
105
                header("Content-Type: text/xml; charset=utf-8");
106
                echo $this->friendly();
107
                exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
108
        }
109
110
        /**
111
         *      Add Sign (if hasn't yet done)
112
         *
113
         *      @param array $options
114
         */
115
        protected function sign($options)
116
        {
117
                if (isset($this->Sign)) return;
118
119
                if (isset($options['UseSign']) && ($options['UseSign'] === true))
120
                {
121
                        $this->Sign = self::createElement('Sign');
0 ignored issues
show
Bug Best Practice introduced by
The property Sign does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
Bug Best Practice introduced by
The method EasyPay\Provider31\Response::createElement() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

121
                        /** @scrutinizer ignore-call */ 
122
                        $this->Sign = self::createElement('Sign');
Loading history...
122
                        $this->Response->appendChild($this->Sign);
123
124
                        $sign = $this->generate_sign($options);
125
126
                        $this->Sign->nodeValue = $sign;
127
                }
128
        }
129
130
        /**
131
         *      Generate signature of response
132
         *
133
         *      @param array $options
134
         *      @return string
135
         */
136
        public function generate_sign($options)
137
        {
138
                if ( ! isset($options['ProviderPKey']))
139
                {
140
                        Log::instance()->error('The parameter ProviderPKey is not set!');
141
                        return null;
142
                }
143
                try
144
                {
145
                    $pkeyid = (new Key())->get($options['ProviderPKey'], 'private');
146
                }
147
                catch (\Exception $e)
148
                {
149
                    return null;
150
                }
151
152
                $pr_key = openssl_pkey_get_private($pkeyid);
153
                if ($pr_key === FALSE)
154
                {
155
                        Log::instance()->error('Can not extract the private key from certificate!');
156
                        return null;
157
                }
158
                if (openssl_sign($this->friendly(), $sign, $pr_key) === FALSE)
159
                {
160
                        Log::instance()->error('Can not generate signature!');
161
                        return null;
162
                }
163
164
                return strtoupper(bin2hex($sign));
165
        }
166
}
167