Completed
Push — master ( bddabe...f158c6 )
by Leith
07:44
created

PurchaseRequest   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 200
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 4

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 24
lcom 3
cbo 4
dl 0
loc 200
ccs 99
cts 99
cp 1
rs 10
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A getHmacKey() 0 4 1
A setHmacKey() 0 4 1
A getHmacKeyID() 0 4 1
A setHmacKeyID() 0 4 1
A getScpId() 0 4 1
A setScpId() 0 4 1
A getSiteId() 0 4 1
A setSiteId() 0 4 1
A setItems() 0 8 3
C getData() 0 119 8
A sendData() 0 8 1
A getSoapClient() 0 4 2
A getEndpoint() 0 4 2
1
<?php
2
3
namespace Omnipay\CapitaPay360\Message;
4
5
use SoapClient;
6
use Omnipay\Common\Message\AbstractRequest;
7
use Omnipay\CapitaPay360\ItemBag;
8
9
/**
10
 * CapitaPay360 Purchase Request
11
 */
12
class PurchaseRequest extends AbstractRequest
13
{
14
    /** @var string */
15
    protected $liveWSDL = 'https://sbs.e-paycapita.com/scp/scpws/scpSimpleClient.wsdl';
16
    /** @var string */
17
    protected $testWSDL = 'https://sbsctest.e-paycapita.com/scp/scpws/scpSimpleClient.wsdl';
18
    /** @var mixed Soap client, added as property for unit testing and error checking */
19
    public $soapClient = null;
20
21 8
    public function getHmacKey()
22
    {
23 8
        return $this->getParameter('hmacKey');
24
    }
25
26 11
    public function setHmacKey($value)
27
    {
28 11
        return $this->setParameter('hmacKey', $value);
29
    }
30
31 8
    public function getHmacKeyID()
32
    {
33 8
        return $this->getParameter('hmacKeyID');
34
    }
35
36 11
    public function setHmacKeyID($value)
37
    {
38 11
        return $this->setParameter('hmacKeyID', $value);
39
    }
40
41 8
    public function getScpId()
42
    {
43 8
        return $this->getParameter('scpId');
44
    }
45
46 11
    public function setScpId($value)
47
    {
48 11
        return $this->setParameter('scpId', $value);
49
    }
50
51 8
    public function getSiteId()
52
    {
53 8
        return $this->getParameter('siteId');
54
    }
55
56 11
    public function setSiteId($value)
57
    {
58 11
        return $this->setParameter('siteId', $value);
59
    }
60
61
    /**
62
     * Override {@see AbstractRequest::setItems()} to provide additional attributes
63
     */
64 1
    public function setItems($items)
65
    {
66 1
        if ($items && !$items instanceof ItemBag) {
67 1
            $items = new ItemBag($items);
68
        }
69
70 1
        return $this->setParameter('items', $items);
71
    }
72
73 4
    public function getData()
74
    {
75 4
        $this->validate('scpId', 'siteId', 'hmacKeyID', 'hmacKey', 'amount', 'currency');
76 4
        $timeStamp = gmdate("YmdHis");
77 4
        $uniqueReference = uniqid('PB');
78 4
        $subjectType = 'CapitaPortal';
79 4
        $algorithm = 'Original';
80 4
        $credentialsToHash = implode('!', array(
81 4
            $subjectType,
82 4
            $this->getScpId(),
83 4
            $uniqueReference,
84 4
            $timeStamp,
85 4
            $algorithm,
86 4
            $this->getHmacKeyId()
87
        ));
88 4
        $key = base64_decode($this->getHmacKey());
89 4
        $hash = hash_hmac('sha256', $credentialsToHash, $key, true);
90 4
        $digest = base64_encode($hash);
91
92
        $data = array(
93
            'credentials' => array(
94
                'subject' => array(
95 4
                    'subjectType' => $subjectType,
96 4
                    'identifier' => $this->getScpId(),
97 4
                    'systemCode' => 'SCP'
98
                ),
99
                'requestIdentification' => array(
100 4
                    'uniqueReference' => $uniqueReference,
101 4
                    'timeStamp' => $timeStamp
102
                ),
103
                'signature' => array(
104 4
                    'algorithm' => $algorithm,
105 4
                    'hmacKeyID' => $this->getHmacKeyId(),
106 4
                    'digest' => $digest
107
                )
108
            ),
109 4
            'requestType' => 'payOnly',
110 4
            'requestId' => $this->getTransactionId(),
111
            'routing' => array(
112 4
                'returnUrl' => $this->getReturnUrl(),
113 4
                'backUrl' => $this->getCancelUrl(),
114 4
                'siteId' => $this->getSiteId(),
115 4
                'scpId' => $this->getScpId()
116
            ),
117 4
            'panEntryMethod' => 'ECOM',
118
            'sale' => array(
119
                'saleSummary' => array(
120 4
                    'description' => substr($this->getDescription(), 0, 100),
121 4
                    'amountInMinorUnits' => $this->getAmountInteger()
122
                )
123
            )
124
        );
125
126
        // add card holder details if available
127 4
        $card = $this->getCard();
128 4
        if ($card) {
129 1
            $address = array_filter(array(
130 1
                'address1' => substr($card->getAddress1(), 0, 50),
131 1
                'address2' => substr($card->getAddress2(), 0, 50),
132 1
                'address3' => substr($card->getAddress3(), 0, 50),
133 1
                'address4' => substr($card->getCity(), 0, 50),
134 1
                'county' => substr($card->getState(), 0, 50),
135 1
                'country' => substr($card->getCountry(), 0, 50),
136 1
                'postcode' => substr($card->getPostcode(), 0, 10),
137 1
            ));
138 1
            $cardHolderDetails = array_filter(array(
139 1
                'cardHolderName' => $card->getName(),
140 1
                'address' => $address,
141 1
            ));
142 1
            if ($cardHolderDetails) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $cardHolderDetails of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
143
                $data['billing'] = array('cardHolderDetails' => $cardHolderDetails);
144 1
            }
145 1
        }
146 1
147 1
        // Create items array to return
148
        $items = $this->getItems();
149
        if ($items) {
150 1
            $saleItems = array();
151
            $itemContactDetails = array();
152
            // assumption: contact details for each item are the same as the purchaser, not set individually
153
            if ($card) {
154 4
                $accountName = array_filter(array(
155 4
                    'title' => $card->getTitle(),
156 1
                    'forename' => $card->getFirstName(),
157 1
                    'surname' => $card->getLastName(),
158 1
                ));
159 1
                $contact = array_filter(array(
160 1
                    'email' => $card->getEmail(),
161 1
                ));
162 1
                $itemContactDetails += array_filter(array(
163 1
                    'accountName' => $accountName,
164 1
                    'accountAddress' => $address,
0 ignored issues
show
Bug introduced by
The variable $address does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
165 1
                    'contact' => $contact,
166 1
                ));
167 1
            }
168 1
            foreach ($items as $itemIndex => $item) {
169 1
                $reference = $item->getReference();
170 1
                $lgItemDetails = array_filter($itemContactDetails + array(
171
                    'additionalReference' => $item->getAdditionalReference(),
172
                    'fundCode' => $item->getFundCode(),
173
                    'narrative' => $item->getNarrative(),
174 4
                ));
175
                $saleItems[] = array(
176
                    'itemSummary' => array(
177 1
                        'description' => substr($item->getName(), 0, 100),
178
                        'amountInMinorUnits' => (int) round(
179 1
                            $item->getQuantity() * $item->getPrice() * pow(10, $this->getCurrencyDecimalPlaces())
180
                        ),
181 1
                    ) + ($reference ? array('reference' => $reference) : array()),
182
                    'quantity' => $item->getQuantity(),
183
                    'lineId' => $itemIndex + 1
184 2
                ) + ($lgItemDetails ? array('lgItemDetails' => $lgItemDetails) : array());
185
            }
186 2
            // only supply item detail if there are any items
187
            $data['sale']['items'] = $saleItems;
188
        }
189 1
190
        return $data;
191 1
    }
192
193
    public function sendData($data)
194
    {
195
        // workaround so that SoapClient doesn't add 'id' attributes and references on identical nodes (e.g. address)
196
        $data = unserialize(serialize($data));
197
        $responseData = $this->getSoapClient()->scpSimpleInvoke($data);
198
199
        return $this->response = new PurchaseResponse($this, $responseData);
200
    }
201
202
    protected function getSoapClient()
203
    {
204
        return $this->soapClient === null ? new SoapClient($this->getEndpoint(), array()) : $this->soapClient;
205
    }
206
207
    public function getEndpoint()
208
    {
209
        return $this->getTestMode() ? $this->testWSDL : $this->liveWSDL;
210
    }
211
}
212