Passed
Push — master ( 8a38a3...18d115 )
by Dmitry
02:02
created

Response::generate_sign()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 2
Metric Value
cc 2
eloc 10
c 2
b 0
f 2
nc 3
nop 1
dl 0
loc 18
rs 9.4285
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
use EasyPay\OpenSSL as OpenSSL;
17
18
abstract class Response extends \DomDocument
19
{
20
    /**
21
     *      @var string
22
     *
23
     */
24
    const TEMPLATE = '<Response><StatusCode></StatusCode><StatusDetail></StatusDetail><DateTime></DateTime></Response>';
25
26
    /**
27
     *      @var \DOMNode
28
     */
29
    protected $Response;
30
31
    /**
32
     *      @var \DOMElement
33
     */
34
    protected $Sign;
35
36
    /**
37
     *      Response constructor
38
     *
39
     */
40
    public function __construct()
41
    {
42
        parent::__construct('1.0', 'UTF-8');
43
44
        $this->loadXML(self::TEMPLATE);
45
46
        $this->Response = $this->firstChild;
47
        $this->set_DateTime();
48
    }
49
50
    /**
51
     *      Set DateTime element value by current time
52
     */
53
    public function set_DateTime()
54
    {
55
        $this->setElementValue('DateTime', date('Y-m-d\TH:i:s', time()));
56
    }
57
58
    /**
59
     *      Create new element node
60
     *
61
     *      @param string $name
62
     *      @param string $value (optional)
63
     */
64
    public function createElement($name, $value=NULL)
65
    {
66
        return parent::createElement($name, $value);
67
    }
68
69
    /**
70
     *      Set node value
71
     *
72
     *      @param string $name
73
     *      @param string $value
74
     */
75
    public function setElementValue($name, $value)
76
    {
77
        foreach ($this->Response->childNodes as $child)
78
        {
79
            if ($child->nodeName == $name)
80
            {
81
                $child->nodeValue = $value;
82
            }
83
        }
84
    }
85
86
    /**
87
     *      Dumps response into a string
88
     *
89
     *      @return string XML
90
     */
91
    public function friendly()
92
    {
93
        $this->encoding = 'UTF-8';
94
        $this->formatOutput = true;
95
        //$this->save('/tmp/test1.xml');
96
97
        return $this->saveXML(NULL, LIBXML_NOEMPTYTAG);
98
    }
99
100
    /**
101
     *      Send response
102
     *
103
     *      @param array $options
104
     */
105
    public function out($options)
106
    {
107
        $this->sign($options);
108
109
        Log::instance()->debug('response sends: ');
110
        Log::instance()->debug($this->friendly());
111
112
        ob_clean();
113
        header("Content-Type: text/xml; charset=utf-8");
114
        echo $this->friendly();
115
        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...
116
    }
117
118
    /**
119
     *      Add Sign (if hasn't yet done)
120
     *
121
     *      @param array $options
122
     */
123
    protected function sign($options)
124
    {
125
        if (isset($this->Sign)) return;
126
127
        if (isset($options['UseSign']) && ($options['UseSign'] === true))
128
        {
129
            $this->Sign = $this->createElement('Sign');
130
            $this->Response->appendChild($this->Sign);
131
132
            $sign = $this->generate_sign($options);
133
134
            $this->Sign->nodeValue = $sign;
135
        }
136
    }
137
138
    /**
139
     *      Generate signature of response
140
     *
141
     *      @param array $options
142
     *      @return string
143
     */
144
    public function generate_sign($options)
145
    {
146
        try
147
        {
148
            $sign = '';
149
            $this->check_sign_result(
150
                $result = (new OpenSSL())->sign(
151
                    $this->friendly(),
152
                    $sign,
153
                    (new OpenSSL())->get_priv_key($this->get_priv_key($options))
154
                )
155
            );
156
157
            return strtoupper(bin2hex($sign));
158
        }
159
        catch (\Exception $e)
160
        {
161
            return null;
162
        }
163
    }
164
165
    /**
166
     *      load file with provider private key
167
     *
168
     *      @param array $options
169
     *      @throws Exception\Runtime
170
     *      @return string
171
     */
172
    protected function get_priv_key($options)
173
    {
174
        if ( ! isset($options['ProviderPKey']))
175
        {
176
            throw new \EasyPay\Exception\Runtime('The parameter ProviderPKey is not set!', -94);
177
        }
178
179
        return (new Key())->get($options['ProviderPKey'], 'private');
180
    }
181
182
    /**
183
     *      check result of openssl sign
184
     *
185
     *      @param bool $result
186
     *      @throws Exception\Sign
187
     */
188
    protected function check_sign_result($result)
189
    {
190
        if ($result === FALSE)
191
        {
192
            throw new \EasyPay\Exception\Sign('Can not generate signature!', -96);
193
        }
194
    }
195
}
196