GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 0fda94...5b2f37 )
by Stefan
19s queued 13s
created

AbstractSaferpayTest::clickButton()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Karser\PayumSaferpay\Tests\Functional;
4
5
use Goutte\Client;
6
use Karser\PayumSaferpay\Model\CardAlias;
7
use Karser\PayumSaferpay\Model\CardAliasInterface;
8
use Karser\PayumSaferpay\Request\InsertCardAlias;
9
use Karser\PayumSaferpay\SaferpayGatewayFactory;
10
use Payum\Core\Bridge\PlainPhp\Security\TokenFactory;
11
use Payum\Core\GatewayFactoryInterface;
12
use Payum\Core\GatewayInterface;
13
use Payum\Core\Model\Payment;
14
use Payum\Core\Model\PaymentInterface;
15
use Payum\Core\Payum;
16
use Payum\Core\PayumBuilder;
17
use Payum\Core\Registry\StorageRegistryInterface;
18
use Payum\Core\Reply\HttpRedirect;
19
use Payum\Core\Request\Capture;
20
use Payum\Core\Request\GetHumanStatus;
21
use Payum\Core\Security\TokenInterface;
22
use Payum\Core\Storage\FilesystemStorage;
23
use Payum\Core\Storage\StorageInterface;
24
use PHPUnit\Framework\TestCase;
25
use Symfony\Component\BrowserKit\Exception\BadMethodCallException;
26
use Symfony\Component\BrowserKit\Response;
27
use Symfony\Component\DomCrawler\Crawler;
28
29
abstract class AbstractSaferpayTest extends TestCase
30
{
31
    protected const GATEWAY_NAME = 'saferpay';
32
    protected const HOST = 'http://localhost';
33
    protected const AMOUNT = 123; // 1.23
34
    protected const CURRENCY = 'USD';
35
    protected const DESCRIPTION = 'A description';
36
    protected const ALIAS_LIFETIME = 1600;
37
38
    //LS: Liability shift; AUTH: Authenticated; 3D: 3D Secure;
39
    //All cards are from Mastercard
40
    protected const CARD_SUCCESS_LS_AUTH_3D = '9030100052000000';
41
    protected const CARD_SUCCESS = '9030101152000007';
42
    protected const CARD_FAILED = '9030100152000009'; //'9010100152000003';
43
44
    /** @var Payum */
45
    protected $payum;
46
47
    /** @var GatewayInterface */
48
    protected $gateway;
49
50
    /** @var StorageInterface */
51
    protected $storage;
52
53
    /** @var StorageInterface */
54
    protected $cardAliasStorage;
55
56
    /** @var Client */
57
    protected $client;
58
59
    public function setUp(): void
60
    {
61
        $builder = (new PayumBuilder())
62
            ->addDefaultStorages()
63
            ->addStorage(CardAlias::class, new FilesystemStorage(sys_get_temp_dir(), CardAlias::class))
64
            ->setTokenFactory(static function(StorageInterface $tokenStorage, StorageRegistryInterface $registry) {
65
                return new TokenFactory($tokenStorage, $registry, self::HOST);
66
            })
67
            ->addGatewayFactory('saferpay', static function(array $config, GatewayFactoryInterface $coreGatewayFactory) {
68
                return new SaferpayGatewayFactory($config, $coreGatewayFactory);
69
            })
70
            ->addGateway(self::GATEWAY_NAME, [
71
                'factory' => 'saferpay',
72
                'username' => 'API_401860_80003225',
73
                'password' => 'C-y*bv8346Ze5-T8',
74
                'customerId' => '401860',
75
                'terminalId' => '17795278',
76
                'sandbox' => true,
77
            ]);
78
        $payum = $builder->getPayum();
79
80
        $this->payum = $payum;
81
        $this->gateway = $payum->getGateway(self::GATEWAY_NAME);
82
        $this->storage = $this->payum->getStorage(Payment::class);
83
        $this->cardAliasStorage = $this->payum->getStorage(CardAlias::class);
84
85
        $client = new Client();
86
        $client->followRedirects(false);
87
        $this->client = $client;
88
    }
89
90
    protected function submitForm(string $buttonSel, array $fieldValues = [], string $method = 'POST', array $serverParameters = []): Crawler
91
    {
92
        $crawler = $this->client->getCrawler();
93
        if (null === $crawler) {
94
            throw new BadMethodCallException(sprintf('The "request()" method must be called before "%s()".', __METHOD__));
95
        }
96
97
        $buttonNode = $crawler->filter($buttonSel)->first();
98
        $form = $buttonNode->form($fieldValues, $method);
99
100
        return $this->client->submit($form, [], $serverParameters);
101
    }
102
103
    protected function clickLink(string $linkSelector): Crawler
104
    {
105
        $crawler = $this->client->getCrawler();
106
        if (null === $crawler) {
107
            throw new BadMethodCallException(sprintf('The "request()" method must be called before "%s()".', __METHOD__));
108
        }
109
110
        return $this->client->click($crawler->filter($linkSelector)->link());
111
    }
112
113
    protected function clickButton(string $buttonSelector): Crawler
114
    {
115
        $crawler = $this->client->getCrawler();
116
        if (null === $crawler) {
117
            throw new BadMethodCallException(sprintf('The "request()" method must be called before "%s()".', __METHOD__));
118
        }
119
120
        $buttonNode = $crawler->filter($buttonSelector)->first();
121
        $form = $buttonNode->form([], 'POST');
122
123
        return $this->client->submit($form);
124
    }
125
126
    protected function composeFormData(string $card, bool $cvc = true): array
127
    {
128
        $data = [
129
            'CardNumber' => $card,
130
            'Expiry' => sprintf('01/%d', date('Y', strtotime('+1 year'))),
131
            'HolderName' => 'John Doe',
132
        ];
133
        if ($cvc) {
134
            $data['VerificationCode'] = '111';
135
        }
136
        return $data;
137
    }
138
139
    protected function capture(TokenInterface $token, PaymentInterface $payment): ?HttpRedirect
140
    {
141
        $captureRequest = new Capture($token);
142
        $captureRequest->setModel($payment);
143
        return $this->gateway->execute($captureRequest, true);
144
    }
145
146
    protected function assertStatus(string $expected, PaymentInterface $payment): void
147
    {
148
        $status = new GetHumanStatus($payment);
149
        $this->gateway->execute($status);
150
        self::assertEquals($expected, $status->getValue());
151
    }
152
153
    protected function createPayment(array $details = []): Payment
154
    {
155
        /** @var Payment $payment */
156
        $payment = $this->storage->create();
157
        $payment->setNumber(uniqid());
158
        $payment->setCurrencyCode(self::CURRENCY);
159
        $payment->setTotalAmount(self::AMOUNT);
160
        $payment->setDescription(self::DESCRIPTION);
161
        $payment->setDetails($details);
162
        $this->storage->update($payment);
163
        return $payment;
164
    }
165
166
    protected function getThroughCheckout(string $url, array $formData, string $action = 'submit'): string
167
    {
168
        $this->client->request('GET', $url);
169
        if (false !== strpos($url, '/vt2/api/PaymentPage')) {
170
            $this->client->followRedirect();
171
            $this->client->submitForm('MasterCard');
172
            $this->client->followRedirect();
173
        }
174
175
        if (
176
            false !== strpos($this->client->getCrawler()->getUri(), '/VT2/mpp/PaymentDataEntry/Index')
177
            || false !== strpos($this->client->getCrawler()->getUri(), '/vt2/Api/Post')
178
            || false !== strpos($this->client->getCrawler()->getUri(), '/vt2/api/register/card')
179
        ) {
180
            if ($action === 'abort') {
181
                $location = $this->client->getCrawler()->filter('button.btn-abort')->attr('formaction');
182
                if (0 === strpos($location, self::HOST)) {
183
                    return $location;
184
                }
185
                $this->clickButton('button.btn-abort');
186
            } else {
187
                $this->client->submitForm('SubmitToNext', $formData);
188
            }
189
            /** @var Response $response */
190
            $response = $this->client->getResponse();
191
            if ($response->getStatusCode() === 302) {
192
                $location = $response->getHeader('Location');
193
                if (0 === strpos($location, self::HOST)) {
194
                    return $location;
195
                }
196
                $this->client->followRedirect();
197
            }
198
        }
199
200
        if (false !== strpos($this->client->getCrawler()->getUri(), '/VT2/mpp/PaymentDataEntry/Index')) {
201
            self::assertSame(200, $this->client->getResponse()->getStatusCode());
202
            $this->client->submitForm( $action === 'submit' ? 'Buy' : 'Cancel');
203
            self::assertSame(302, $this->client->getResponse()->getStatusCode());
204
            $this->client->followRedirect();
205
        }
206
        if (
207
            false !== strpos($this->client->getCrawler()->getUri(), '/VT2/mpp/ThreeDS/Index')
208
            || false !== strpos($this->client->getCrawler()->getUri(), '/VT2/api/ThreeDs')
209
        ) {
210
            self::assertSame(200, $this->client->getResponse()->getStatusCode());
211
            $this->submitForm('[type="submit"]');
212
            self::assertSame(200, $this->client->getResponse()->getStatusCode());
213
214
            $this->client->submitForm($action === 'submit' ? 'Submit' : 'Cancel');
215
            self::assertSame(200, $this->client->getResponse()->getStatusCode());
216
217
            $this->client->submitForm('Submit');
218
            self::assertSame(200, $this->client->getResponse()->getStatusCode());
219
            $this->clickLink('a.btn-next');
220
221
            $response = $this->client->getResponse();
222
            self::assertSame(302, $response->getStatusCode());
223
            $location = $response->getHeader('Location');
224
            if (0 === strpos($location, self::HOST)) {
225
                return $location;
226
            }
227
            $this->client->followRedirect();
228
        }
229
        if (false !== strpos($this->client->getCrawler()->getUri(), '/VT2/mpp/Error/System')) {
230
            $this->client->submitForm('Cancel');
231
232
            $response = $this->client->getResponse();
233
            self::assertSame(302, $response->getStatusCode());
234
            $location = $response->getHeader('Location');
235
            if (0 === strpos($location, self::HOST)) {
236
                return $location;
237
            }
238
            $this->client->followRedirect();
239
        }
240
        return $this->client->getCrawler()->filter('a.btn-next')->first()->attr('href');
241
    }
242
243
    protected function createCardAlias(array $details): CardAliasInterface
244
    {
245
        /** @var CardAlias $alias */
246
        $alias = $this->cardAliasStorage->create();
247
        $alias->setDetails($details);
248
        $this->cardAliasStorage->update($alias);
249
        return $alias;
250
    }
251
252
    protected function createCapturedPayment(array $options): PaymentInterface
253
    {
254
        $payment = $this->createPayment($options);
255
256
        $token = $this->payum->getTokenFactory()->createCaptureToken(self::GATEWAY_NAME, $payment, 'done.php');
257
        $this->payum->getHttpRequestVerifier()->invalidate($token); //no need to store token
258
259
        # INIT transaction
260
        $reply = $this->capture($token, $payment);
261
        if ($reply instanceof HttpRedirect) {
262
            # submit form
263
            $iframeRedirect = $this->getThroughCheckout($reply->getUrl(), $this->composeFormData(self::CARD_SUCCESS));
264
            parse_str(parse_url($iframeRedirect, PHP_URL_QUERY), $_GET);
265
266
            # AUTHORIZE AND CAPTURE
267
            $this->capture($token, $payment);
268
        }
269
        return $payment;
270
    }
271
272
    protected function createInsertedCardAlias(array $options): CardAliasInterface
273
    {
274
        $cardAlias = $this->createCardAlias($options);
275
276
        $token = $this->payum->getTokenFactory()->createCaptureToken(self::GATEWAY_NAME, $cardAlias, 'done.php');
277
        $this->payum->getHttpRequestVerifier()->invalidate($token); //no need to store token
278
279
        $reply = $this->insertCardAlias($token, $cardAlias);
280
281
        # submit form
282
        $iframeRedirect = $this->getThroughCheckout($reply->getUrl(), $this->composeFormData(self::CARD_SUCCESS, $cvc = false));
283
        parse_str(parse_url($iframeRedirect, PHP_URL_QUERY), $_GET);
284
285
        $this->insertCardAlias($token, $cardAlias);
286
287
        return $cardAlias;
288
    }
289
290
    protected function insertCardAlias(TokenInterface $token, CardAliasInterface $cardAlias): ?HttpRedirect
291
    {
292
        $insertCardAliasRequest = new InsertCardAlias($token);
293
        $insertCardAliasRequest->setModel($cardAlias);
294
        return $this->gateway->execute($insertCardAliasRequest, true);
295
    }
296
}
297