Completed
Push — master ( 18d115...3e67ed )
by Dmitry
02:04
created

Response::out_header()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 4
rs 10
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
96
        return $this->saveXML(NULL, LIBXML_NOEMPTYTAG);
97
    }
98
99
    /**
100
     *      Sign and send response
101
     *
102
     *      @param array $options
103
     */
104
    public function sign_and_out($options)
105
    {
106
        $this->sign($options);
107
        $this->out_header();
108
        $this->out_body($this->friendly());
109
    }
110
111
    /**
112
     *      Send header
113
     */
114
    protected function out_header()
115
    {
116
        ob_clean();
117
        header("Content-Type: text/xml; charset=utf-8");
118
    }
119
120
    /**
121
     *      Send body
122
     *
123
     *      @param string $body
124
     */
125
    protected function out_body($body)
126
    {
127
        Log::instance()->debug('response sends: ');
128
        Log::instance()->debug($body);
129
130
        echo $body;
131
    }
132
133
    /**
134
     *      Add Sign (if hasn't yet done)
135
     *
136
     *      @param array $options
137
     */
138
    protected function sign($options)
139
    {
140
        if (isset($this->Sign)) return;
141
142
        if (isset($options['UseSign']) && ($options['UseSign'] === true))
143
        {
144
            $this->Sign = $this->createElement('Sign');
145
            $this->Response->appendChild($this->Sign);
146
147
            $sign = $this->generate_sign($options);
148
149
            $this->Sign->nodeValue = $sign;
150
        }
151
    }
152
153
    /**
154
     *      Generate signature of response
155
     *
156
     *      @param array $options
157
     *      @return string
158
     */
159
    public function generate_sign($options)
160
    {
161
        try
162
        {
163
            $sign = '';
164
            $this->check_sign_result(
165
                $result = (new OpenSSL())->sign(
166
                    $this->friendly(),
167
                    $sign,
168
                    (new OpenSSL())->get_priv_key($this->get_priv_key($options))
169
                )
170
            );
171
172
            return strtoupper(bin2hex($sign));
173
        }
174
        catch (\Exception $e)
175
        {
176
            return null;
177
        }
178
    }
179
180
    /**
181
     *      load file with provider private key
182
     *
183
     *      @param array $options
184
     *      @throws Exception\Runtime
185
     *      @return string
186
     */
187
    protected function get_priv_key($options)
188
    {
189
        if ( ! isset($options['ProviderPKey']))
190
        {
191
            throw new \EasyPay\Exception\Runtime('The parameter ProviderPKey is not set!', -94);
192
        }
193
194
        return (new Key())->get($options['ProviderPKey'], 'private');
195
    }
196
197
    /**
198
     *      check result of openssl sign
199
     *
200
     *      @param bool $result
201
     *      @throws Exception\Sign
202
     */
203
    protected function check_sign_result($result)
204
    {
205
        if ($result === FALSE)
206
        {
207
            throw new \EasyPay\Exception\Sign('Can not generate signature!', -96);
208
        }
209
    }
210
}
211