Passed
Push — master ( 8498b3...41586a )
by Roman
02:03
created

SkrillClient::prepareTransfer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 9
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Skrill;
6
7
use ArrayObject;
8
use LimitIterator;
9
use SplFileObject;
10
use DateTimeImmutable;
11
use DateTimeInterface;
12
use Skrill\ValueObject\Sid;
13
use Skrill\ValueObject\Url;
14
use Skrill\ValueObject\Email;
15
use Skrill\Response\Response;
16
use Skrill\Factory\SidFactory;
17
use GuzzleHttp\RequestOptions;
18
use GuzzleHttp\ClientInterface;
19
use Skrill\Request\SaleRequest;
20
use Skrill\Response\HistoryItem;
21
use Skrill\ValueObject\Password;
22
use Skrill\Request\RefundRequest;
23
use Skrill\Request\TransferRequest;
24
use Skrill\Factory\ResponseFactory;
25
use Skrill\Request\OnDemandRequest;
26
use Skrill\ValueObject\CompanyName;
27
use Psr\Http\Message\ResponseInterface;
28
use GuzzleHttp\Exception\GuzzleException;
29
use Skrill\Exception\SkrillResponseException;
30
31
/**
32
 * Skrill HTTP client.
33
 */
34
final class SkrillClient implements SkrillHistoryClientInterface, SkrillOnDemandClientInterface, SkrillSaleClientInterface, SkrillTransferClientInterface, SkrillRefundClientInterface
35
{
36
    /**
37
     * @var ClientInterface
38
     */
39
    private $client;
40
41
    /**
42
     * A description to be shown on the Skrill payment page in the logo area if there is no logo_url parameter.
43
     *
44
     * recipient_description
45
     *
46
     * @var CompanyName|null
47
     */
48
    private $companyName;
49
50
    /**
51
     * Email address of your Skrill merchant account.
52
     *
53
     * pay_to_email
54
     *
55
     * @var Email
56
     */
57
    private $merchantEmail;
58
59
    /**
60
     * The URL of the logo which you would like to appear in the top right of the Skrill page.
61
     *
62
     * logo_url
63
     *
64
     * @var Url|null
65
     */
66
    private $logoUrl;
67
68
    /**
69
     * Skrill API/MQI password.
70
     *
71
     * @var string
72
     */
73
    private $password;
74
75
    /**
76
     * @param ClientInterface  $client
77
     * @param Email            $merchantEmail
78
     * @param Password         $password
79
     * @param Url|null         $logoUrl
80
     * @param CompanyName|null $companyName
81
     */
82
    public function __construct(
83
        ClientInterface $client,
84
        Email $merchantEmail,
85
        Password $password,
86
        Url $logoUrl = null,
87
        CompanyName $companyName = null
88
    ) {
89
        $this->client = $client;
90
        $this->companyName = $companyName;
91
        $this->merchantEmail = $merchantEmail;
92
        $this->logoUrl = $logoUrl;
93
        $this->password = md5(strval($password));
94
    }
95
96
    /**
97
     * {@inheritdoc}
98
     *
99
     * @throws GuzzleException
100
     */
101
    public function prepareSale(SaleRequest $request): Sid
102
    {
103
        $params = $request->getPayload();
104
        $params['prepare_only'] = 1; // Forces only the SID to be returned without the actual page.
105
        $params['pay_to_email'] = strval($this->merchantEmail);
106
107
        if (null != $this->logoUrl) {
108
            $params['logo_url'] = strval($this->logoUrl);
109
        }
110
111
        if (null != $this->companyName) {
112
            $params['recipient_description'] = strval($this->companyName);
113
        }
114
115
        return SidFactory::createFromSaleResponse(
116
            $this->request($params, 'https://pay.skrill.com')
117
        );
118
    }
119
120
    /**
121
     * {@inheritdoc}
122
     *
123
     * @throws GuzzleException
124
     */
125
    public function prepareTransfer(TransferRequest $request): Sid
126
    {
127
        $params = $request->getPayload();
128
        $params['action'] = 'prepare';
129
        $params['email'] = strval($this->merchantEmail);
130
        $params['password'] = $this->password;
131
132
        return SidFactory::createFromXMLResponse(
133
            $this->request($params, 'https://www.skrill.com/app/pay.pl')
134
        );
135
    }
136
137
    /**
138
     * {@inheritdoc}
139
     *
140
     * @throws GuzzleException
141
     */
142
    public function prepareRefund(RefundRequest $request): Sid
143
    {
144
        $params = $request->getPayload();
145
        $params['action'] = 'prepare';
146
        $params['email'] = strval($this->merchantEmail);
147
        $params['password'] = $this->password;
148
149
        return SidFactory::createFromXMLResponse(
150
            $this->request($params, 'https://www.skrill.com/app/refund.pl')
151
        );
152
    }
153
154
    /**
155
     * {@inheritdoc}
156
     *
157
     * @throws GuzzleException
158
     */
159
    public function executeTransfer(Sid $sid): Response
160
    {
161
        return ResponseFactory::createFromTransferResponse(
162
            $this->request(['action' => 'transfer', 'sid' => strval($sid)], 'https://www.skrill.com/app/pay.pl')
163
        );
164
    }
165
166
    /**
167
     * {@inheritdoc}
168
     *
169
     * @throws GuzzleException
170
     */
171
    public function executeRefund(Sid $sid): Response
172
    {
173
        return ResponseFactory::createFromRefundResponse(
174
            $this->request(['action' => 'refund', 'sid' => strval($sid)], 'https://www.skrill.com/app/refund.pl')
175
        );
176
    }
177
178
    /**
179
     * {@inheritdoc}
180
     *
181
     * @throws GuzzleException
182
     */
183
    public function prepareOnDemand(OnDemandRequest $request): Sid
184
    {
185
        $params = $request->getPayload();
186
        $params['action'] = 'prepare';
187
        $params['email'] = strval($this->merchantEmail);
188
        $params['password'] = $this->password;
189
190
        return SidFactory::createFromXMLResponse(
191
            $this->request($params, 'https://www.skrill.com/app/ondemand_request.pl')
192
        );
193
    }
194
195
    /**
196
     * {@inheritdoc}
197
     *
198
     * @throws GuzzleException
199
     */
200
    public function executeOnDemand(Sid $sid): Response
201
    {
202
        return ResponseFactory::createFromTransferResponse(
203
            $this->request(['action' => 'request', 'sid' => strval($sid)], 'https://www.skrill.com/app/ondemand_request.pl')
204
        );
205
    }
206
207
    /**
208
     * {@inheritdoc}
209
     *
210
     * @throws GuzzleException
211
     */
212
    public function viewHistory(DateTimeInterface $startDate, DateTimeInterface $endDate = null): ArrayObject
213
    {
214
        $params = [
215
            'email' => strval($this->merchantEmail),
216
            'password' => $this->password,
217
            'action' => 'history',
218
            'start_date' => $startDate->format('d-m-Y'),
219
        ];
220
221
        if (null != $endDate) {
222
            $params['end_date'] = $endDate->format('d-m-y');
223
        }
224
225
        $tmpFile = new SplFileObject(tempnam(sys_get_temp_dir(), strval(rand())), 'w+');
226
        $this->client->request('POST', 'https://www.skrill.com/app/query.pl', [
227
            RequestOptions::FORM_PARAMS => $params,
228
            RequestOptions::SINK => $tmpFile->getPathname(),
229
        ]);
230
231
        if (preg_match('/^[\d]{3}[\t]{2}(.+)$/', $tmpFile->current(), $matches)) {
232
            throw SkrillResponseException::fromSkillError($matches[1]);
233
        }
234
235
        $result = new ArrayObject();
236
        $tmpFile->rewind();
237
        $tmpFile->setFlags(SplFileObject::READ_CSV | SplFileObject::READ_AHEAD | SplFileObject::SKIP_EMPTY);
238
239
        foreach (new LimitIterator($tmpFile, 1) as $row) {
240
            list(, $time, $type, $details, $lesion, $profit, $status, $balance, $reference, $amount, $currency, $info, $skrillId, $paymentType) = $row;
241
            $datetime = DateTimeImmutable::createFromFormat('d M y H:i', $time);
242
243
            if (!$datetime instanceof DateTimeImmutable) {
244
                throw SkrillResponseException::fromSkillError(sprintf('Invalid time "%s".', $time));
245
            }
246
247
            $result->append(
248
                new HistoryItem($reference, $skrillId, $datetime, $type, $details, $lesion, $profit, $status, $balance, $amount, $currency, $info, $paymentType)
249
            );
250
        }
251
252
        unlink($tmpFile->getPathname());
253
254
        return $result;
255
    }
256
257
    /**
258
     * @param array  $parameters
259
     * @param string $url
260
     *
261
     * @return ResponseInterface
262
     *
263
     * @throws GuzzleException
264
     */
265
    private function request(array $parameters, string $url): ResponseInterface
266
    {
267
        return $this->client->request('POST', $url, [
268
            RequestOptions::FORM_PARAMS => $parameters,
269
            RequestOptions::HEADERS => [
270
                'Accept' => 'text/xml',
271
            ],
272
        ]);
273
    }
274
}
275