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.

PurchaseAction::supports()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BitBag\SyliusBraintreePlugin\Action;
6
7
use BitBag\SyliusBraintreePlugin\ApiClient\BraintreeApiClientInterface;
8
use BitBag\SyliusBraintreePlugin\Reply\Api\PaymentMethodNonceArray;
9
use BitBag\SyliusBraintreePlugin\Reply\Api\TransactionResultArray;
10
use BitBag\SyliusBraintreePlugin\Request\Api\DoSale;
11
use BitBag\SyliusBraintreePlugin\Request\Api\FindPaymentMethodNonce;
12
use BitBag\SyliusBraintreePlugin\Request\ObtainCardholderAuthentication;
13
use BitBag\SyliusBraintreePlugin\Request\ObtainPaymentMethodNonce;
14
use BitBag\SyliusBraintreePlugin\Request\Purchase;
15
use Braintree\Transaction;
16
use Payum\Core\Action\ActionInterface;
17
use Payum\Core\Bridge\Spl\ArrayObject;
18
use Payum\Core\Exception\RequestNotSupportedException;
19
use Payum\Core\Exception\RuntimeException;
20
use Payum\Core\GatewayAwareInterface;
21
use Payum\Core\GatewayAwareTrait;
22
23
final class PurchaseAction implements ActionInterface, GatewayAwareInterface
24
{
25
    use GatewayAwareTrait;
26
27
    protected $cardholderAuthenticationRequired;
28
29
    public function __construct()
30
    {
31
        $this->cardholderAuthenticationRequired = true;
32
    }
33
34
    public function setCardholderAuthenticationRequired(bool $value): void
35
    {
36
        $this->cardholderAuthenticationRequired = $value;
37
    }
38
39
    public function execute($request): void
40
    {
41
        RequestNotSupportedException::assertSupports($this, $request);
42
43
        $details = ArrayObject::ensureArrayObject($request->getModel());
44
45
        if ($details->offsetExists('status')) {
46
            return;
47
        }
48
49
        try {
50
            $this->obtainPaymentMethodNonce($details);
51
52
            $this->obtainCardholderAuthentication($details);
53
54
            $this->doSaleTransaction($details);
55
56
            $this->resolveStatus($details);
57
58
            $details->validateNotEmpty([
59
                'paymentMethodNonce',
60
                'paymentMethodNonceInfo',
61
                'sale',
62
                'status',
63
            ]);
64
        } catch (RuntimeException $exception) {
65
            $details['status'] = 'failed';
66
            $details['status_reason'] = $exception->getMessage();
67
        }
68
    }
69
70
    protected function obtainPaymentMethodNonce(ArrayObject $details): void
71
    {
72
        if ($details->offsetExists('paymentMethodNonce')) {
73
            return;
74
        }
75
76
        $this->gateway->execute($request = new ObtainPaymentMethodNonce($details));
77
78
        $paymentMethodNonce = $request->getResponse();
79
80
        $details['paymentMethodNonce'] = $paymentMethodNonce;
81
82
        $this->findPaymentMethodNonceInfo($details);
83
    }
84
85
    protected function obtainCardholderAuthentication(ArrayObject $details): void
86
    {
87
        $paymentMethodNonceInfo = $details['paymentMethodNonceInfo'];
88
89
        $isNotRequired = true !== $this->cardholderAuthenticationRequired;
90
        $isNotCreditCardType = 'CreditCard' !== $paymentMethodNonceInfo['type'];
91
        $has3DSecureInfo = !empty($paymentMethodNonceInfo['threeDSecureInfo']);
92
93
        if ($isNotRequired || $isNotCreditCardType || $has3DSecureInfo) {
94
            return;
95
        }
96
97
        $this->gateway->execute($request = new ObtainCardholderAuthentication($details));
98
99
        $paymentMethodNonce = $request->getResponse();
100
101
        $details['paymentMethodNonce'] = $paymentMethodNonce;
102
103
        $this->findPaymentMethodNonceInfo($details);
104
    }
105
106
    protected function findPaymentMethodNonceInfo(ArrayObject $details): void
107
    {
108
        $this->gateway->execute($request = new FindPaymentMethodNonce($details['paymentMethodNonce']));
109
110
        $paymentMethodInfo = $request->getResponse();
111
112
        if (null === $paymentMethodInfo) {
113
            throw new RuntimeException('payment_method_nonce not found');
114
        }
115
116
        $details['paymentMethodNonceInfo'] = PaymentMethodNonceArray::toArray($paymentMethodInfo);
117
    }
118
119
    protected function doSaleTransaction(ArrayObject $details): void
120
    {
121
        if ($details->offsetExists('sale')) {
122
            return;
123
        }
124
125
        $saleOptions = [
126
            'submitForSettlement' => true,
127
        ];
128
129
        if ($details->offsetExists('paymentMethodNonce')) {
130
            $saleOptions['threeDSecure'] = [
131
                'required' => $this->cardholderAuthenticationRequired,
132
            ];
133
        }
134
135
        $details['saleOptions'] = $saleOptions;
136
137
        $this->gateway->execute($request = new DoSale($details));
138
139
        $transaction = $request->getResponse();
140
141
        $details['sale'] = TransactionResultArray::toArray($transaction);
142
    }
143
144
    protected function resolveStatus(ArrayObject $details): void
145
    {
146
        $details->validateNotEmpty(['sale']);
147
148
        $sale = $details['sale'];
149
150
        if (true === $sale['success']) {
151
            switch ($sale['transaction']['status']) {
152
                case Transaction::AUTHORIZED:
153
                case Transaction::AUTHORIZING:
154
                    $details['status'] = BraintreeApiClientInterface::AUTHORIZED;
155
156
                    break;
157
                case Transaction::SUBMITTED_FOR_SETTLEMENT:
158
                case Transaction::SETTLING:
159
                case Transaction::SETTLED:
160
                case Transaction::SETTLEMENT_PENDING:
161
                case Transaction::SETTLEMENT_CONFIRMED:
162
                    $details['status'] = BraintreeApiClientInterface::CAPTURED;
163
164
                    break;
165
            }
166
        } else {
167
            $details['status'] = BraintreeApiClientInterface::FAILED;
168
        }
169
    }
170
171
    public function supports($request): bool
172
    {
173
        return
174
            $request instanceof Purchase &&
175
            $request->getModel() instanceof \ArrayAccess
176
        ;
177
    }
178
}
179