Tokenizer   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 130
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 10
c 1
b 0
f 0
lcom 1
cbo 3
dl 0
loc 130
ccs 41
cts 41
cp 1
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 2
A setApiKey() 0 4 1
A setClientId() 0 4 1
A tokenize() 0 16 2
B performTokenizationRequest() 0 25 1
A generateDigest() 0 4 1
A getTimestamp() 0 9 2
1
<?php
2
/**
3
 * HAPI (HomeAway Payment Island) Tokenizer.
4
 */
5
namespace Gueststream\HomeAway;
6
7
use Gueststream\HomeAway\Exception\TokenizerException;
8
use GuzzleHttp\Client as GuzzleClient;
9
use GuzzleHttp\Exception\ClientException as GuzzleClientException;
10
11
class Tokenizer
12
{
13
    /**
14
     * Token type for all tokenizations requests is always CC.
15
     */
16
    const TOKEN_TYPE = "CC";
17
    /**
18
     * Tokenization Server URL
19
     */
20
    const SERVER_URL = "https://sensei.homeaway.com/tokens";
21
    /**
22
     * HAPI Secure API Key.
23
     *
24
     * @var string
25
     */
26
    private $apiKey;
27
    /**
28
     * HAPI Client ID.
29
     *
30
     * @var string
31
     */
32
    private $clientId;
33
    /**
34
     * @var GuzzleClient
35
     */
36
    private $guzzleClient;
37
    /**
38
     * Unix Timestamp for generating the digest hash.
39
     *
40
     * @var string
41
     */
42
    private $timestamp;
43
44
    /**
45
     * HAPI constructor.
46
     *
47
     * @param $apiKey
48
     * @param $clientId
49
     */
50 6
    public function __construct($apiKey, $clientId, GuzzleClient $guzzleClient = null)
51
    {
52 6
        $this->setApiKey($apiKey);
53 6
        $this->setClientId($clientId);
54 6
        $this->guzzleClient = !is_null($guzzleClient) ? $guzzleClient : new GuzzleClient();
55 6
    }
56
57
    /**
58
     * @param mixed $apiKey
59
     */
60 6
    private function setApiKey($apiKey)
61
    {
62 6
        $this->apiKey = $apiKey;
63 6
    }
64
65
    /**
66
     * @param mixed $clientId
67
     */
68 6
    private function setClientId($clientId)
69
    {
70 6
        $this->clientId = $clientId;
71 6
    }
72
73
    /**
74
     * @param $creditCardNumber
75
     * @throws TokenizerException
76
     */
77 6
    public function tokenize($creditCardNumber)
78
    {
79
        try {
80 6
            $tokenData = $this->performTokenizationRequest($creditCardNumber);
81 5
        } catch (GuzzleClientException $exception) {
82
            /**
83
             * Convert Guzzle Exceptions to Tokenizer Exception.
84
             * It seems every actual error ties to a non-200 response which
85
             * causes Guzzle to throw an Exception with the JSON body content as
86
             * the message anyway.
87
             */
88 3
            throw new TokenizerException('something went wrong');
89
        }
90
91 3
        return $tokenData->{'@id'};
92
    }
93
94 6
    private function performTokenizationRequest($creditCardNumber)
95
    {
96 6
        $httpResponse = $this->guzzleClient->request(
97 6
            'POST',
98 6
            self::SERVER_URL,
99
            [
100
                'query' => [
101 6
                    'time' => $this->getTimestamp(),
102 6
                    'digest' => $this->generateDigest(),
103 6
                    'clientId' => $this->clientId
104 6
                ],
105
                'json' => [
106 6
                    'tokenType' => 'CC',
107 2
                    'value' => $creditCardNumber
108 4
                ],
109 4
                'allow_redirects' => false,
110
                'headers' => [
111 4
                    'User-Agent' => 'Gueststream/1.0',
112
                    'Accept' => 'application/json'
113 4
                ]
114 4
            ]
115 4
        );
116
117 3
        return json_decode($httpResponse->getBody());
118
    }
119
120
    /**
121
     * @return string
122
     */
123 6
    private function generateDigest()
124
    {
125 6
        return hash("sha256", $this->getTimestamp() . $this->apiKey);
126
    }
127
128
    /**
129
     * @return string
130
     */
131 6
    private function getTimestamp()
132
    {
133 6
        if (!$this->timestamp) {
134 6
            $epoch_milliseconds = time() * 1000;
135 6
            $this->timestamp = number_format($epoch_milliseconds, 0, '.', '');
136 4
        }
137
138 6
        return $this->timestamp;
139
    }
140
}
141