Completed
Push — master ( 374367...b950ab )
by Vladimir
09:30
created

Gateway::init()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 39
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 39
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 32
nc 1
nop 9

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace AcquiroPay;
6
7
use AcquiroPay\Gateway\Responses\InitResponse;
8
use AcquiroPay\Gateway\Responses\PaymentStatusByCfResponse;
9
use DOMDocument;
10
use DOMElement;
11
use GuzzleHttp\Client as Http;
12
use Illuminate\Support\Collection;
13
use Symfony\Component\Serializer\Encoder\XmlEncoder;
14
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
15
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
16
use Symfony\Component\Serializer\Serializer;
17
18
class Gateway
19
{
20
    private const LIVE_URL = 'https://gateway.acquiropay.com';
21
    private const TEST_URL = 'https://gateway.acqp.co';
22
23
    protected $http;
24
    protected $url;
25
26
    protected $merchantId;
27
    protected $secretWord;
28
29
    protected $request;
30
31
    public function __construct(
32
        Http $http,
33
        int $merchantId = null,
0 ignored issues
show
Unused Code introduced by
The parameter $merchantId is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
34
        string $secretWord = null,
0 ignored issues
show
Unused Code introduced by
The parameter $secretWord is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
35
        bool $live = false
0 ignored issues
show
Unused Code introduced by
The parameter $live is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
36
    )
37
    {
38
        $this->http = $http;
39
    }
40
41
    public function setUrl(string $url): Gateway
42
    {
43
        $this->url = $url;
44
45
        return $this;
46
    }
47
48
    public function setMerchantId(int $merchantId): Gateway
49
    {
50
        $this->merchantId = $merchantId;
51
52
        return $this;
53
    }
54
55
    public function setSecretWord(string $secretWord): Gateway
56
    {
57
        $this->secretWord = $secretWord;
58
59
        return $this;
60
    }
61
62
    public function setLive(bool $live): Gateway
63
    {
64
        $this->url = $live ? self::LIVE_URL : self::TEST_URL;
65
66
        return $this;
67
    }
68
69
    /**
70
     * Init payment.
71
     *
72
     * @param int $productId
73
     * @param string $pan
74
     * @param string $cardHolder
75
     * @param int $expiryMonth
76
     * @param int $expiryYear
77
     * @param string $cvv
78
     * @param string $cf
79
     * @param float|string $amount
80
     * @param array $parameters
81
     *
82
     * @return InitResponse
83
     */
84
    public function init(
85
        int $productId,
86
        string $pan,
87
        string $cardHolder,
88
        int $expiryMonth,
89
        int $expiryYear,
90
        string $cvv,
91
        string $cf,
92
        float $amount,
93
        array $parameters = []
94
    ): InitResponse
95
    {
96
        $amount = $this->formatAmount($amount);
97
98
        $parameters = array_merge($parameters, [
99
            'opcode' => 0,
100
            'product_id' => $productId,
101
            'amount' => $amount,
102
            'cf' => $cf,
103
            'pan' => $pan,
104
            'cvv' => $cvv,
105
            'exp_month' => $expiryMonth,
106
            'exp_year' => $expiryYear,
107
            'cardholder' => $cardHolder,
108
            'token' => md5(
109
                $this->merchantId .
110
                $productId .
111
                $amount .
112
                $cf .
113
                array_get($parameters, 'cf2') .
114
                array_get($parameters, 'cf3') .
115
                $this->secretWord
116
            ),
117
        ]);
118
119
        $response = $this->send($parameters);
120
121
        return $this->deserialize($response, InitResponse::class);
122
    }
123
124
    /**
125
     * Get payment status using cf.
126
     *
127
     * @param int $productId
128
     * @param string $cf
129
     *
130
     * @return Collection|PaymentStatusByCfResponse[]
131
     */
132
    public function paymentStatusByCf(int $productId, string $cf)
133
    {
134
        $parameters = [
135
            'opcode' => 2,
136
            'product_id' => $productId,
137
            'cf' => $cf,
138
            'token' => md5($this->merchantId . $productId . $cf . $this->secretWord),
139
        ];
140
141
        $response = $this->send($parameters);
142
143
        $xml = new DOMDocument;
144
        $xml->formatOutput = true;
145
        $xml->loadXML($response);
146
147
        // один платеж
148
        if ($xml->getElementsByTagName('payments')->length === 0) {
149
            return collect([$this->deserialize($response, PaymentStatusByCfResponse::class)]);
150
        }
151
152
        $payments = collect();
153
        $elements = $xml->getElementsByTagName('payments')->item(0)->getElementsByTagName('payment');
154
155
        /** @var DOMElement $element */
156
        foreach ($elements as $element) {
157
            $payments->push($this->deserialize($xml->saveXML($element), PaymentStatusByCfResponse::class));
158
        }
159
160
        return $payments;
161
    }
162
163
    public function getRequest(): ?array
164
    {
165
        return $this->request;
166
    }
167
168
    private function send(array $parameters): string
169
    {
170
        $this->request = $parameters;
171
172
        $response = $this->http->post($this->url, ['form_params' => $parameters, 'verify' => false]);
173
174
        return (string)$response->getBody();
175
    }
176
177
    private function deserialize(string $data, string $class)
178
    {
179
        $normalizers = [new ObjectNormalizer(null, new CamelCaseToSnakeCaseNameConverter)];
180
        $encoders = [new XmlEncoder];
181
182
        return (new Serializer($normalizers, $encoders))->deserialize($data, $class, 'xml');
183
    }
184
185
    private function formatAmount(float $amount): string
186
    {
187
        return number_format($amount, 2, '.', '');
188
    }
189
}