Request   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 128
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 100%

Importance

Changes 7
Bugs 1 Features 3
Metric Value
wmc 11
c 7
b 1
f 3
lcom 1
cbo 2
dl 0
loc 128
ccs 40
cts 40
cp 1
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A sign() 0 10 2
A execute() 0 8 2
A createRequest() 0 11 1
A appendParameters() 0 12 4
A signParameters() 0 4 1
1
<?php
2
/*
3
 * Copyright 2015 Alexey Maslov <[email protected]>
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
namespace alxmsl\PaymentNinja;
19
20
use alxmsl\Network\Exception\HttpClientErrorCodeException;
21
use alxmsl\Network\Http\Request as HttpRequest;
22
use alxmsl\PaymentNinja\Error\ErrorException;
23
use alxmsl\PaymentNinja\Response\AbstractResponse;
24
use Closure;
25
use LogicException;
26
27
/**
28
 * Class for API requests
29
 * @author alxmsl
30
 */
31
final class Request {
32
    /**
33
     * Payment.Ninja API endpoint
34
     */
35
    const ENDPOINT_URI = 'https://api.payment.ninja/v1';
36
37
    /**
38
     * @var string API method name
39
     */
40
    private $method = '';
41
42
    /**
43
     * @var array method call parameters
44
     */
45
    private $parameters = [];
46
47
    /**
48
     * @var Closure|null response builder function
49
     */
50
    private $ResponseBuilder = null;
51
52
    /**
53
     * @var int request timeout, seconds
54
     */
55
    private $timeout = 0;
56
57
    /**
58
     * @var array map that store relations between API and HTTP methods for requests
59
     */
60
    private static $methodMap = [
61
        'user/resolve'          => HttpRequest::METHOD_POST,
62
        'user/changeRecurring'  => HttpRequest::METHOD_POST,
63
        'user/cancelRecurring'  => HttpRequest::METHOD_POST,
64
        'card/getToken'         => HttpRequest::METHOD_GET,
65
        'card/process'          => HttpRequest::METHOD_POST,
66
        'card/authenticate'     => HttpRequest::METHOD_POST,
67
        'card/processRecurring' => HttpRequest::METHOD_POST,
68
    ];
69
70
    /**
71
     * @param string $method API method name
72
     * @param Closure $ResponseBuilder
73
     * @param array $parameters method call parameters
74
     * @param int $timeout request timeout, seconds
75
     */
76 11
    public function __construct($method, Closure $ResponseBuilder, array $parameters = [], $timeout = 10) {
77 11
        $this->method          = (string) $method;
78 11
        $this->parameters      = $parameters;
79 11
        $this->ResponseBuilder = $ResponseBuilder;
80 11
        $this->timeout         = (int) $timeout;
81 11
    }
82
83
    /**
84
     * Sign request
85
     * @param string $publicKey public application key
86
     * @param string $privateKey private application key
87
     * @throws LogicException when parameters already signed
88
     */
89 8
    public function sign($publicKey, $privateKey) {
90 8
        if (!array_key_exists('signature', $this->parameters)) {
91 8
            $this->parameters = array_merge([
92 8
                'project' => (string) $publicKey,
93 8
            ], $this->parameters);
94 8
            $this->parameters['signature'] = $this->signParameters($this->parameters, (string) $privateKey);
95 8
        } else {
96 1
            throw new LogicException('parameters already signed');
97
        }
98 8
    }
99
100
    /**
101
     * Execute API method
102
     * @codeCoverageIgnore
103
     * @return AbstractResponse response instance
104
     * @throws ErrorException if there is an API error
105
     */
106
    public function execute() {
107
        $Request = $this->createRequest();
108
        try {
109
            return $this->ResponseBuilder->__invoke($Request->send());
110
        } catch (HttpClientErrorCodeException $Ex) {
111
            throw ErrorException::initializeByString($Ex->getMessage());
112
        }
113
    }
114
115
    /**
116
     * Create HTTP request instance fr this API call
117
     * @return HttpRequest HTTP request instance
118
     */
119 1
    private function createRequest() {
120 1
        $HttpRequest = new HttpRequest();
121 1
        $HttpRequest->setTransport(HttpRequest::TRANSPORT_CURL);
122 1
        $HttpRequest->setUrl(self::ENDPOINT_URI)
123 1
            ->setConnectTimeout(1)
124 1
            ->setTimeout($this->timeout)
125 1
            ->addUrlField($this->method)
126 1
            ->setMethod(self::$methodMap[$this->method]);
127 1
        $this->appendParameters($HttpRequest);
128 1
        return $HttpRequest;
129
    }
130
131
    /**
132
     * Append parameters to HTTP request
133
     * @param HttpRequest $HttpRequest HTTP request instance
134
     */
135 1
    private function appendParameters(HttpRequest $HttpRequest) {
136 1
        switch ($HttpRequest->getMethod()) {
137 1
            case HttpRequest::METHOD_GET:
138 1
                foreach ($this->parameters as $field => $value) {
139 1
                    $HttpRequest->addGetField($field, $value);
140 1
                }
141 1
                break;
142 1
            case HttpRequest::METHOD_POST:
143 1
                $HttpRequest->setPostData($this->parameters);
144 1
                break;
145 1
        }
146 1
    }
147
148
    /**
149
     * Calculates signature for incoming parameters
150
     * @param array $parameters parameters
151
     * @param string $privateKey private application key
152
     * @return string signature
153
     */
154 8
    private function signParameters(array $parameters, $privateKey) {
155 8
        sort($parameters, SORT_STRING);
156 8
        return hash_hmac('sha256', join('|', $parameters), $privateKey);
157
    }
158
}
159