Merchant   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 221
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 18
lcom 1
cbo 3
dl 0
loc 221
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
B call() 0 27 4
A executeCurl() 0 15 3
A __construct() 0 7 1
A getCardNumber() 0 4 1
A __destruct() 0 4 2
B getBalance() 0 34 1
B getHistory() 0 44 2
A cleanupCardNumber() 0 4 1
A buildSignature() 0 8 1
A innerXML() 0 8 2
1
<?php
2
3
namespace Mukhin\PrivatbankBundle;
4
5
use Mukhin\PrivatbankBundle\Exception\PrivatbankException;
6
use Mukhin\PrivatbankBundle\Model\Balance;
7
use Mukhin\PrivatbankBundle\Model\Statements;
8
9
class Merchant
10
{
11
    const API_URL = 'https://api.privatbank.ua/p24api';
12
13
    /** @var resource */
14
    protected $curl;
15
16
    /** @var string */
17
    protected $merchantId;
18
19
    /** @var string */
20
    protected $merchantSecret;
21
22
    /** @var string */
23
    protected $cardNumber;
24
25
    /**
26
     * @param string $merchantId
27
     * @param string $merchantSecret
28
     */
29
    public function __construct($merchantId, $merchantSecret, $cardNumber)
30
    {
31
        $this->curl = curl_init();
32
        $this->merchantId = $merchantId;
33
        $this->merchantSecret = $merchantSecret;
34
        $this->cardNumber = $cardNumber;
35
    }
36
37
    public function getCardNumber()
38
    {
39
        return $this->cardNumber;
40
    }
41
42
    /**
43
     * Close curl
44
     */
45
    public function __destruct()
46
    {
47
        $this->curl && curl_close($this->curl);
48
    }
49
50
    /**
51
     * @see https://api.privatbank.ua/#p24/balance
52
     *
53
     * @return Balance
54
     */
55
    public function getBalance()
56
    {
57
        $request = new \SimpleXMLElement("<?xml version=\"1.0\" encoding=\"UTF-8\" ?><request version=\"1.0\"></request>");
58
59
        # Data
60
        $data = $request->addChild('data');
61
        $data->addChild('oper', 'cmt');
62
        $data->addChild('wait', '0');
63
        $data->addChild('test', '0');
64
65
        # Data > Payment
66
        $payment = $data->addChild('payment');
67
        $payment->addAttribute('id', '');
68
69
        # Data > Payment > Cardnum
70
        $cardnum = $payment->addChild('prop');
71
        $cardnum->addAttribute('name', 'cardnum');
72
        $cardnum->addAttribute('value', $this->cleanupCardNumber($this->cardNumber));
73
74
        # Data > Payment > Country
75
        $country = $payment->addChild('prop');
76
        $country->addAttribute('name', 'country');
77
        $country->addAttribute('value', 'UA');
78
79
        # Merchant
80
        $merchant = $request->addChild('merchant');
81
        $merchant->addChild('id', $this->merchantId);
82
        $merchant->addChild('signature', $this->buildSignature($this->innerXML($data)));
83
84
        $response = $this->call('balance', $request->asXML());
85
        return Balance::fromResponse(
86
            $response->data->info->cardbalance
87
        );
88
    }
89
90
    /**
91
     * @see https://api.privatbank.ua/#p24/orders
92
     *
93
     * @return Statements
94
     */
95
    public function getHistory(\DateTime $sinceDate, \DateTime $toDate = null)
96
    {
97
        if (null === $toDate) {
98
            $toDate = new \DateTime();
99
        }
100
101
        $request = new \SimpleXMLElement("<?xml version=\"1.0\" encoding=\"UTF-8\" ?><request version=\"1.0\"></request>");
102
103
        # Data
104
        $data = $request->addChild('data');
105
        $data->addChild('oper', 'cmt');
106
        $data->addChild('wait', '0');
107
        $data->addChild('test', '0');
108
109
        # Data > Payment
110
        $payment = $data->addChild('payment');
111
        $payment->addAttribute('id', '');
112
113
        # Data > Payment > Cardnum
114
        $cardnum = $payment->addChild('prop');
115
        $cardnum->addAttribute('name', 'cardnum');
116
        $cardnum->addAttribute('value', $this->cleanupCardNumber($this->cardNumber));
117
118
        # Data > Payment > Start Date
119
        $country = $payment->addChild('prop');
120
        $country->addAttribute('name', 'sd');
121
        $country->addAttribute('value', $sinceDate->format('d.m.Y'));
122
123
        # Data > Payment > End Date
124
        $country = $payment->addChild('prop');
125
        $country->addAttribute('name', 'ed');
126
        $country->addAttribute('value', $toDate->format('d.m.Y'));
127
128
        # Merchant
129
        $merchant = $request->addChild('merchant');
130
        $merchant->addChild('id', $this->merchantId);
131
        $merchant->addChild('signature', $this->buildSignature($this->innerXML($data)));
132
133
        $response = $this->call('rest_fiz', $request->asXML());
134
135
        return Statements::fromResponse(
136
            $response->data->info->statements
137
        );
138
    }
139
140
    /**
141
     * @param string $cardNumber
142
     * @return string
143
     */
144
    protected function cleanupCardNumber($cardNumber)
145
    {
146
        return preg_replace('/[^0-9]/', '', $cardNumber);
147
    }
148
149
    /**
150
     * @param string $data
151
     * @return string
152
     */
153
    protected function buildSignature($data)
154
    {
155
        return sha1(md5(sprintf(
156
            '%s%s',
157
            $data,
158
                $this->merchantSecret
159
        )));
160
    }
161
162
    /**
163
     * @param \SimpleXMLElement $node
164
     * @return string
165
     */
166
    protected function innerXML(\SimpleXMLElement $node)
167
    {
168
        $content = "";
169
        foreach($node->children() as $child) {
170
            $content .= $child->asXML();
171
        }
172
        return $content;
173
    }
174
175
    /**
176
     * Call method
177
     *
178
     * @param string $method
179
     * @param string|null $data
180
     * @return \SimpleXMLElement
181
     */
182
    protected function call($method = '', $data = null)
183
    {
184
        $options = [
185
            CURLOPT_URL => sprintf('%s/%s', self::API_URL, $method),
186
            CURLOPT_RETURNTRANSFER => true,
187
            CURLOPT_POST => null,
188
            CURLOPT_POSTFIELDS => null,
189
        ];
190
191
        if ($data) {
192
            $options[CURLOPT_POST] = true;
193
            $options[CURLOPT_POSTFIELDS] = $data;
194
        }
195
196
        $response = new \SimpleXMLElement($this->executeCurl($options));
197
198
        if (isset($response->data->error)) {
199
            throw new PrivatbankException((string)$response->data->error['message']);
200
        }
201
202
        // Fuck, Privatbank, you kidding me?
203
        if (isset($response->data->info->error)) {
204
            throw new PrivatbankException((string)$response->data->info->error);
205
        }
206
207
        return $response;
208
    }
209
210
    /**
211
     * @param array $options
212
     * @return string
213
     */
214
    protected function executeCurl(array $options)
215
    {
216
        curl_setopt_array($this->curl, $options);
217
218
        $result = curl_exec($this->curl);
219
        if ($result === false) {
220
            throw new PrivatbankException(curl_error($this->curl), curl_errno($this->curl));
221
        }
222
223
        $httpCode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
224
        if (!in_array($httpCode, array(200))) {
225
            throw new PrivatbankException(sprintf('Server returned HTTP code %s', $httpCode), $httpCode);
226
        }
227
        return $result;
228
    }
229
}
230