1: <?php
2:
3: namespace Mypos\IPC;
4:
5: /**
6: * IPC Response class. Parse and validate income data
7: */
8: class Response
9: {
10: /**
11: * @var Config;
12: */
13: private $cnf;
14: private $raw_data, $format, $data, $signature;
15:
16: /**
17: *
18: * @param Config $cnf
19: * @param string|array $raw_data
20: * @param string $format COMMUNICATION_FORMAT_JSON|COMMUNICATION_FORMAT_XML|COMMUNICATION_FORMAT_POST
21: *
22: * @throws IPC_Exception
23: */
24: public function __construct(Config $cnf, $raw_data, $format)
25: {
26: $this->cnf = $cnf;
27: $this->_setData($raw_data, $format);
28: }
29:
30: /**
31: * @param $raw_data
32: * @param $format
33: *
34: * @return $this
35: * @throws IPC_Exception
36: */
37: private function _setData($raw_data, $format)
38: {
39: if (empty($raw_data)) {
40: throw new IPC_Exception('Invalid Response data');
41: }
42:
43: $this->format = $format;
44: $this->raw_data = $raw_data;
45:
46: switch ($this->format) {
47: case Defines::COMMUNICATION_FORMAT_JSON:
48: $this->data = json_decode($this->raw_data, 1);
49: break;
50: case Defines::COMMUNICATION_FORMAT_XML:
51: $this->data = (array)new \SimpleXMLElement($this->raw_data);
52: if (isset($this->data['@attributes'])) {
53: unset($this->data['@attributes']);
54: }
55: break;
56: case Defines::COMMUNICATION_FORMAT_POST:
57: $this->data = $this->raw_data;
58: break;
59: default:
60: throw new IPC_Exception('Invalid response format!');
61: break;
62: }
63:
64: if (empty($this->data)) {
65: throw new IPC_Exception('No IPC Response!');
66: }
67:
68: $this->_extractSignature();
69:
70: if (empty($this->signature) && array_key_exists('Status', $this->data) && $this->data['Status'] === Defines::STATUS_IPC_ERROR) {
71: throw new IPC_Exception('IPC Response - General Error!');
72: }
73:
74: $this->_verifySignature();
75:
76: return $this;
77: }
78:
79: private function _extractSignature()
80: {
81: if (is_array($this->data) && !empty($this->data)) {
82: foreach ($this->data as $k => $v) {
83: if (strtolower($k) == 'signature') {
84: $this->signature = $v;
85: unset($this->data[$k]);
86: }
87: }
88: }
89:
90: return true;
91: }
92:
93: /**
94: * @throws IPC_Exception
95: */
96: private function _verifySignature()
97: {
98: if (empty($this->signature)) {
99: throw new IPC_Exception('Missing request signature!');
100: }
101:
102: if (!$this->cnf) {
103: throw new IPC_Exception('Missing config object!');
104: }
105:
106: $pubKeyId = openssl_get_publickey($this->cnf->getAPIPublicKey());
107: if (!openssl_verify($this->_getSignData(), base64_decode($this->signature), $pubKeyId, Defines::SIGNATURE_ALGO)) {
108: throw new IPC_Exception('Signature check failed!');
109: }
110: }
111:
112: private function _getSignData()
113: {
114: return base64_encode(implode('-', Helper::getValuesFromMultiDimensionalArray($this->data)));
115: }
116:
117: /**
118: * Static class to create Response object
119: *
120: * @param Config $cnf
121: * @param string|array $raw_data
122: * @param string $format
123: *
124: * @return Response
125: * @throws IPC_Exception
126: */
127: public static function getInstance(Config $cnf, $raw_data, $format)
128: {
129: return new self($cnf, $raw_data, $format);
130: }
131:
132: /**
133: * Validate Signature param from IPC response
134: *
135: * @return boolean
136: */
137: public function isSignatureCorrect()
138: {
139: try {
140: $this->_verifySignature();
141: } catch (\Exception $ex) {
142: return false;
143: }
144:
145: return true;
146: }
147:
148: /**
149: * Request param: Signature
150: *
151: * @return string
152: */
153: function getSignature()
154: {
155: return $this->signature;
156: }
157:
158: #############################################
159:
160: /**
161: * Request param: Status
162: *
163: * @return int
164: * @throws IPC_Exception
165: */
166: function getStatus()
167: {
168: return Helper::getArrayVal($this->getData(CASE_LOWER), 'status');
169: }
170:
171: /**
172: * Return IPC Response in array
173: *
174: * @param int $case CASE_LOWER|CASE_UPPER
175: *
176: * @return array
177: * @throws IPC_Exception
178: */
179: function getData($case = null)
180: {
181: if ($case !== null) {
182: if (!in_array($case, [
183: CASE_LOWER,
184: CASE_UPPER,
185: ])) {
186: throw new IPC_Exception('Invalid Key Case!');
187: }
188:
189: return array_change_key_case($this->data, $case);
190: }
191:
192: return $this->data;
193: }
194:
195: /**
196: * Request param: StatusMsg
197: *
198: * @return string
199: * @throws IPC_Exception
200: */
201: function getStatusMsg()
202: {
203: return Helper::getArrayVal($this->getData(CASE_LOWER), 'statusmsg');
204: }
205:
206: /**
207: * Return IPC Response in original format json/xml/array
208: *
209: * @return string|array
210: */
211: function getDataRaw()
212: {
213: return $this->raw_data;
214: }
215: }
216: