Passed
Push — master ( 475cfd...508ec6 )
by Dmitry
01:57
created

Response::out()   A

Complexity

Conditions 1
Paths 0

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 2
Metric Value
cc 1
eloc 7
c 2
b 0
f 2
nc 0
nop 1
dl 0
loc 11
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
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
     *      @var \DOMNode
27
     */
28
    protected $Response;
29
30
    /**
31
     *      @var \DOMElement
32
     */
33
    protected $Sign;
34
35
    /**
36
     *      Response constructor
37
     *
38
     */
39
    public function __construct()
40
    {
41
        parent::__construct('1.0', 'UTF-8');
42
43
        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

43
        self::/** @scrutinizer ignore-call */ 
44
              loadXML(self::TEMPLATE);
Loading history...
44
45
        $this->Response = $this->firstChild;
46
        $this->set_DateTime();
47
    }
48
49
    /**
50
     *      Set DateTime element value by current time
51
     */
52
    public function set_DateTime()
53
    {
54
        $this->setElementValue('DateTime', date('Y-m-d\TH:i:s', time()));
55
    }
56
57
    /**
58
     *      Create new element node
59
     *
60
     *      @param string $name
61
     *      @param string $value (optional)
62
     */
63
    public function createElement($name, $value=NULL)
64
    {
65
        return parent::createElement($name, $value);
66
    }
67
68
    /**
69
     *      Set node value
70
     *
71
     *      @param string $name
72
     *      @param string $value
73
     */
74
    public function setElementValue($name, $value)
75
    {
76
        foreach ($this->Response->childNodes as $child)
77
        {
78
            if ($child->nodeName == $name)
79
            {
80
                $child->nodeValue = $value;
81
            }
82
        }
83
    }
84
85
    /**
86
     *      Dumps response into a string
87
     *
88
     *      @return string XML
89
     */
90
    public function friendly()
91
    {
92
        $this->encoding = 'UTF-8';
93
        $this->formatOutput = true;
94
        //$this->save('/tmp/test1.xml');
95
96
        return $this->saveXML(NULL, LIBXML_NOEMPTYTAG);
97
    }
98
99
    /**
100
     *      Send response
101
     *
102
     *      @param array $options
103
     */
104
    public function out($options)
105
    {
106
        $this->sign($options);
107
108
        Log::instance()->debug('response sends: ');
109
        Log::instance()->debug($this->friendly());
110
111
        ob_clean();
112
        header("Content-Type: text/xml; charset=utf-8");
113
        echo $this->friendly();
114
        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...
115
    }
116
117
    /**
118
     *      Add Sign (if hasn't yet done)
119
     *
120
     *      @param array $options
121
     */
122
    protected function sign($options)
123
    {
124
        if (isset($this->Sign)) return;
125
126
        if (isset($options['UseSign']) && ($options['UseSign'] === true))
127
        {
128
            $this->Sign = self::createElement('Sign');
0 ignored issues
show
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

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