CompletePurchaseResponse   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 137
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 15
lcom 1
cbo 3
dl 0
loc 137
ccs 33
cts 33
cp 1
rs 10
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A isSuccessful() 0 4 1
A getTransactionReference() 0 4 1
A __construct() 0 22 4
A getTransactionId() 0 4 1
A getAuthCode() 0 4 1
A getReasonCode() 0 4 1
A getMessage() 0 4 1
A getCardNumber() 0 4 1
A getCardType() 0 4 1
A getCardExpiry() 0 4 1
A getKey() 0 4 2
1
<?php
2
3
namespace Omnipay\CyberSource\Message;
4
5
use Omnipay\Common\Message\AbstractResponse;
6
use Omnipay\Common\Message\RequestInterface;
7
use Omnipay\Common\Exception\InvalidResponseException;
8
9
/**
10
 * CyberSource Complete Purchase Response
11
 */
12
class CompletePurchaseResponse extends AbstractResponse
13
{
14
    /**
15
     * Constructor
16
     *
17
     * @param RequestInterface $request the initiating request.
18
     * @param mixed $data
19
     *
20
     * @throws InvalidResponseException If merchant data or order number is missing, or signature does not match
21
     */
22 13
    public function __construct(RequestInterface $request, $data)
23
    {
24 13
        parent::__construct($request, $data);
25
26 13
        foreach (array('decision', 'signed_field_names', 'signature') as $key) {
27 13
            if (empty($data[$key])) {
28 5
                throw new InvalidResponseException('Invalid response from payment gateway (no data)');
29
            }
30
        }
31
32 8
        $security = new Security();
33
34 8
        $returnSignature = $security->createSignature(
35 8
            $data,
36 8
            explode(',', $data['signed_field_names']),
37 8
            $this->request->getSecretKey()
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Omnipay\Common\Message\RequestInterface as the method getSecretKey() does only exist in the following implementations of said interface: Omnipay\CyberSource\Mess...CompletePurchaseRequest, Omnipay\CyberSource\Message\PurchaseRequest.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
38
        );
39
40 8
        if ($returnSignature != $data['signature']) {
41 1
            throw new InvalidResponseException('Invalid response from payment gateway (signature mismatch)');
42
        }
43 7
    }
44
45
    /**
46
     * Is the response successful?
47
     *
48
     * Possible values: 'ACCEPT', 'DECLINE', 'REVIEW', 'ERROR', 'CANCEL'
49
     *
50
     * @return boolean
51
     */
52 7
    public function isSuccessful()
53
    {
54 7
        return $this->getKey('decision') === 'ACCEPT';
55
    }
56
57
    /**
58
     * Get the transaction identifier if available.
59
     *
60
     * @return null|string
61
     */
62 4
    public function getTransactionReference()
63
    {
64 4
        return $this->getKey('transaction_id');
65
    }
66
67
    /**
68
     * Get the merchant-supplied transaction identifier if available.
69
     *
70
     * @return null|string
71
     */
72 1
    public function getTransactionId()
73
    {
74 1
        return $this->getKey('req_reference_number');
75
    }
76
77
    /**
78
     * Get the authorisation code if available.
79
     *
80
     * @return null|string
81
     */
82 3
    public function getAuthCode()
83
    {
84 3
        return $this->getKey('auth_code');
85
    }
86
87
    /**
88
     * Get the reason code if available.
89
     *
90
     * @return null|string
91
     */
92 3
    public function getReasonCode()
93
    {
94 3
        return $this->getKey('reason_code');
95
    }
96
97
    /**
98
     * Get the merchant response message if available.
99
     *
100
     * @return null|string
101
     */
102 4
    public function getMessage()
103
    {
104 4
        return $this->getKey('message');
105
    }
106
107
    /**
108
     * Get the card number if available.
109
     *
110
     * @return null|string
111
     */
112 3
    public function getCardNumber()
113
    {
114 3
        return $this->getKey('req_card_number');
115
    }
116
117
    /**
118
     * Get the card type if available.
119
     *
120
     * @return null|string  3-digit number that maps to CyberSource-specific list of card types
121
     */
122 3
    public function getCardType()
123
    {
124 3
        return $this->getKey('req_card_type');
125
    }
126
127
    /**
128
     * Get the card expiry if available.
129
     *
130
     * @return null|string  Format 'mm-yyyy'
131
     */
132 3
    public function getCardExpiry()
133
    {
134 3
        return $this->getKey('req_card_expiry_date');
135
    }
136
137
    /**
138
     * Helper method to get a specific response parameter if available.
139
     *
140
     * @param string $key The key to look up
141
     *
142
     * @return null|mixed
143
     */
144 7
    protected function getKey($key)
145
    {
146 7
        return isset($this->data[$key]) ? $this->data[$key] : null;
147
    }
148
}
149