Completed
Push — master ( 3c661d...2a57f9 )
by Will
26s queued 12s
created

src/Forms/PaymentForm.php (1 issue)

1
<?php
2
3
namespace SilverShop\Forms;
4
5
use SilverShop\Checkout\Checkout;
6
use SilverShop\Checkout\CheckoutComponentConfig;
7
use SilverShop\Checkout\Component\CheckoutComponentNamespaced;
8
use SilverShop\Checkout\Component\OnsitePayment;
9
use SilverShop\Checkout\OrderProcessor;
10
use SilverShop\Model\Order;
11
use SilverStripe\Omnipay\GatewayFieldsFactory;
12
use SilverStripe\Omnipay\GatewayInfo;
13
14
class PaymentForm extends CheckoutForm
15
{
16
    /**
17
     * @var string URL to redirect the user to on payment success.
18
     * Not the same as the "confirm" action in {@link PaymentGatewayController}.
19
     */
20
    protected $successlink;
21
22
    /**
23
     * @var string URL to redirect the user to on payment failure.
24
     * Not the same as the "cancel" action in {@link PaymentGatewayController}.
25
     */
26
    protected $failurelink;
27
28
    /**
29
     * @var OrderProcessor
30
     */
31
    protected $orderProcessor;
32
33
    public function __construct($controller, $name, CheckoutComponentConfig $config)
34
    {
35
        parent::__construct($controller, $name, $config);
36
37
        $this->orderProcessor = OrderProcessor::create($config->getOrder());
38
    }
39
40
    public function setSuccessLink($link)
41
    {
42
        $this->successlink = $link;
43
    }
44
45
    public function getSuccessLink()
46
    {
47
        return $this->successlink;
48
    }
49
50
    public function setFailureLink($link)
51
    {
52
        $this->failurelink = $link;
53
    }
54
55
    public function getFailureLink()
56
    {
57
        return $this->failurelink;
58
    }
59
60
    public function checkoutSubmit($data, $form)
61
    {
62
        // form validation has passed by this point, so we can save data
63
        $this->config->setData($form->getData());
64
        $order = $this->config->getOrder();
65
        $gateway = Checkout::get($order)->getSelectedPaymentMethod(false);
66
        if (GatewayInfo::isOffsite($gateway)
67
            || GatewayInfo::isManual($gateway)
68
            || $this->config->hasComponentWithPaymentData()
69
        ) {
70
            return $this->submitpayment($data, $form);
71
        }
72
73
        return $this->controller->redirect(
74
            $this->controller->Link('payment') //assumes CheckoutPage
75
        );
76
    }
77
78
    /**
79
     * Behaviour can be overwritten by creating a processPaymentResponse method
80
     * on the controller owning this form. It takes a Symfony\Component\HttpFoundation\Response argument,
81
     * and expects an SS_HTTPResponse in return.
82
     */
83
    public function submitpayment($data, $form)
0 ignored issues
show
The parameter $data is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

83
    public function submitpayment(/** @scrutinizer ignore-unused */ $data, $form)

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

Loading history...
84
    {
85
        $data = $form->getData();
86
87
        $cancelUrl = $this->getFailureLink() ? $this->getFailureLink() : $this->controller->Link();
88
89
        $order = $this->config->getOrder();
90
91
        // final recalculation, before making payment
92
        $order->calculate();
93
94
        // handle cases where order total is 0. Note that the order will appear
95
        // as "paid", but without a Payment record attached.
96
        if ($order->GrandTotal() == 0 && Order::config()->allow_zero_order_total) {
97
            if (!$this->orderProcessor->placeOrder()) {
98
                $form->sessionMessage($this->orderProcessor->getError());
99
                return $this->controller->redirectBack();
100
            }
101
            return $this->controller->redirect($this->getSuccessLink());
102
        }
103
104
        // try to place order before payment, if configured
105
        if (Order::config()->place_before_payment) {
106
            if (!$this->orderProcessor->placeOrder()) {
107
                $form->sessionMessage($this->orderProcessor->getError());
108
                return $this->controller->redirectBack();
109
            }
110
            $cancelUrl = $this->orderProcessor->getReturnUrl();
111
        }
112
113
        // if we got here from checkoutSubmit and there's a namespaced Component that provides payment data,
114
        // we need to strip the inputs down to only the checkout component.
115
        $components = $this->config->getComponents();
116
        if ($components->first() instanceof CheckoutComponentNamespaced) {
117
            foreach ($components as $component) {
118
                if ($component->Proxy()->providesPaymentData()) {
119
                    $data = array_merge($data, $component->unnamespaceData($data));
120
                }
121
            }
122
        }
123
124
        $gateway = Checkout::get($order)->getSelectedPaymentMethod(false);
125
        $fieldFactory = new GatewayFieldsFactory($gateway);
126
127
        // This is where the payment is actually attempted
128
        $paymentResponse = $this->orderProcessor->makePayment(
129
            $gateway,
130
            $fieldFactory->normalizeFormData($data),
131
            $this->getSuccessLink(),
132
            $cancelUrl
133
        );
134
135
        $response = null;
136
        if ($this->controller->hasMethod('processPaymentResponse')) {
137
            $response = $this->controller->processPaymentResponse($paymentResponse, $form);
138
        } elseif ($paymentResponse && !$paymentResponse->isError()) {
139
            $response = $paymentResponse->redirectOrRespond();
140
        } else {
141
            $form->sessionMessage($this->orderProcessor->getError(), 'bad');
142
            $response = $this->controller->redirectBack();
143
        }
144
145
        return $response;
146
    }
147
148
    /**
149
     * @param OrderProcessor $processor
150
     */
151
    public function setOrderProcessor(OrderProcessor $processor)
152
    {
153
        $this->orderProcessor = $processor;
154
    }
155
156
    /**
157
     * @return OrderProcessor
158
     */
159
    public function getOrderProcessor()
160
    {
161
        return $this->orderProcessor;
162
    }
163
}
164