YaKassa::responseUnauthorized()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
1
<?php
2
3
/**
4
 * This file is part of Ya.Kassa package.
5
 *
6
 * © Appwilio (http://appwilio.com)
7
 * © JhaoDa (https://github.com/jhaoda)
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
declare(strict_types=1);
13
14
namespace Appwilio\YaKassa;
15
16
use Illuminate\Http\Response;
17
use Appwilio\YaKassa\Contracts\YaKassaOrder;
18
19
class YaKassa
20
{
21
    public const STATE_DECLINED     = 100;
22
    public const STATE_ACCEPTED     = 0;
23
    public const STATE_UNAUTHORIZED = 1;
24
25
    private const PAYMENT_URL = 'yoomoney.ru/eshop.xml';
26
27
    /** @var string */
28
    private $shopId;
29
30
    /** @var string */
31
    private $showcaseId;
32
33
    /** @var string */
34
    private $shopPassword;
35
36
    /** @var YaKassaRequest */
37
    private $request;
38
39
    /** @var string */
40
    private $genuineAmount;
41
42
    /** @var array */
43
    private static $significantFields = [
44
        // DO NOT CHANGE ORDER OF ELEMENTS!!!
45
        'action',
46
        'orderSumAmount',
47
        'orderSumCurrencyPaycash',
48
        'orderSumBankPaycash',
49
        'shopId',
50
        'invoiceId',
51
        'customerNumber',
52
    ];
53
54
    /** @var bool */
55
    private $testMode;
56
57 7
    public function __construct(string $shopId, string $showcaseId, string $shopPassword, bool $testMode = false)
58
    {
59 7
        $this->shopId = $shopId;
60 7
        $this->showcaseId = $showcaseId;
61 7
        $this->shopPassword = $shopPassword;
62
63 7
        $this->testMode = $testMode;
64 7
    }
65
66
    public function getRequest(): YaKassaRequest
67
    {
68
        return $this->request;
69
    }
70
71 6
    public function setRequest(YaKassaRequest $request)
72
    {
73 6
        $this->request = $request;
74
75 6
        return $this;
76
    }
77
78 6
    public function setGenuineOrderSumAmount(float $amount)
79
    {
80 6
        $this->genuineAmount = number_format($amount, 2, '.', '');
81
82 6
        return $this;
83
    }
84
85 6
    public function verify(): bool
86
    {
87 6
        if (! in_array($this->request->getAction(), ['checkOrder', 'paymentAviso'], true)) {
88
            return false;
89
        }
90
91 6
        if (0 !== count(array_diff(self::$significantFields, array_keys($this->request->all())))) {
92
            return false;
93
        }
94
95 6
        $source = array_intersect_key($this->request->all(), array_flip(self::$significantFields));
96
97 6
        $source['shopId'] = $this->shopId;
98 6
        $source['orderSumAmount'] = $this->genuineAmount;
99
100
        uksort($source, function ($a, $b) {
101
            return
102 6
                array_search($a, self::$significantFields, true)
103
                <=>
104 6
                array_search($b, self::$significantFields, true);
105 6
        });
106
107 6
        $source['secret'] = $this->shopPassword;
108
109 6
        return $this->request->get('md5') === strtoupper(md5(implode(';', $source)));
110
    }
111
112
    public function responseDeclined(): Response
113
    {
114
        return $this->buildResponse(self::STATE_DECLINED);
115
    }
116
117
    public function responseAccepted(): Response
118
    {
119
        return $this->buildResponse(self::STATE_ACCEPTED);
120
    }
121
122
    public function responseUnauthorized(): Response
123
    {
124
        return $this->buildResponse(self::STATE_UNAUTHORIZED);
125
    }
126
127
    public function buildPaymentForm(YaKassaOrder $order): YaKassaPaymentForm
128
    {
129
        $form = new YaKassaPaymentForm($this->shopId, $this->showcaseId, $this->getPaymentUrl());
130
131
        $form->setOrder($order);
132
133
        return $form;
134
    }
135
136
    private function buildResponse(int $code): Response
137
    {
138
        $content = '<?xml version="1.0" encoding="UTF-8"?>';
139
140
        $content .= vsprintf('<%sResponse performedDatetime="%s" code="%d" invoiceId="%d" shopId="%d" />', [
141
            $this->request->getAction(),
142
            date(\DateTime::RFC3339),
143
            $code,
144
            $this->request->getInvoiceId(),
145
            $this->shopId,
146
        ]);
147
148
        return new Response($content, Response::HTTP_OK, ['Content-Type' => 'application/xml']);
149
    }
150
151
    private function getPaymentUrl(): string
152
    {
153
        $paymentUrl = ($this->testMode ? 'demo' : '').self::PAYMENT_URL;
154
155
        return "https://{$paymentUrl}";
156
    }
157
}
158