Failed Conditions
Push — develop ( 567ea4...abb342 )
by Reüel
02:58
created

src/Client.php (9 issues)

1
<?php
2
/**
3
 * Client.
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2019 Pronamic
7
 * @license   GPL-3.0-or-later
8
 * @package   Pronamic\WordPress\Pay\Gateways\ING\KassaCompleet
9
 */
10
11
namespace Pronamic\WordPress\Pay\Gateways\ING\KassaCompleet;
12
13
use Pronamic\WordPress\Pay\Core\XML\Security;
14
use WP_Error;
15
16
/**
17
 * Title: ING Kassa Compleet client
18
 * Description:
19
 * Copyright: 2005-2019 Pronamic
20
 * Company: Pronamic
21
 *
22
 * @author  Reüel van der Steege
23
 * @version 2.0.0
24
 * @since   1.0.0
25
 */
26
class Client {
27
	/**
28
	 * ING Kasse Compleet API endpoint URL
29
	 *
30
	 * @var string url
31
	 */
32
	const API_URL = 'https://api.kassacompleet.nl/v1/';
33
34
	/**
35
	 * API Key
36
	 *
37
	 * @var string
38
	 */
39
	private $api_key;
40
41
	/**
42
	 * Error
43
	 *
44
	 * @var WP_Error
45
	 */
46
	private $error;
47
48
	/**
49
	 * Constructs and initalize an ING Kassa Compleet client object
50
	 *
51
	 * @param string $api_key API key.
52
	 */
53
	public function __construct( $api_key ) {
54
		$this->api_key = $api_key;
55
	}
56
57
	/**
58
	 * Error
59
	 *
60
	 * @return WP_Error
61
	 */
62
	public function get_error() {
63
		return $this->error;
64
	}
65
66
	/**
67
	 * Send request with the specified action and parameters
68
	 *
69
	 * @param string $endpoint API endpoint.
70
	 * @param string $method   HTTP method to use for request.
71
	 * @param array  $data     Data to send.
72
	 *
73
	 * @return array|WP_Error
74
	 */
75
	private function send_request( $endpoint, $method = 'POST', array $data = array() ) {
76
		$url = self::API_URL . $endpoint;
77
78
		$headers = array(
79
			'Authorization' => 'Basic ' . base64_encode( $this->api_key . ':' ),
80
		);
81
82
		if ( is_array( $data ) && ! empty( $data ) ) {
83
			$data = wp_json_encode( $data );
84
85
			$headers['Content-Type'] = 'application/json';
86
		}
87
88
		$return = wp_remote_request(
89
			$url,
90
			array(
91
				'method'  => $method,
92
				'headers' => $headers,
93
				'body'    => $data,
94
			)
95
		);
96
97
		return $return;
98
	}
99
100
	/**
101
	 * Create order.
102
	 *
103
	 * @param OrderRequest $request Order request.
104
	 *
105
	 * @return array|mixed|object|null
106
	 */
107
	public function create_order( OrderRequest $request ) {
108
		$result = null;
109
110
		$data = $request->get_array();
111
112
		$response = $this->send_request( 'orders/', 'POST', $data );
113
114
		if ( is_wp_error( $response ) ) {
115
			$this->error = $response;
0 ignored issues
show
Documentation Bug introduced by
It seems like $response can also be of type array. However, the property $error is declared as type WP_Error. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
116
117
			return $result;
118
		}
119
120
		$response_code = wp_remote_retrieve_response_code( $response );
0 ignored issues
show
It seems like $response can also be of type WP_Error; however, parameter $response of wp_remote_retrieve_response_code() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

120
		$response_code = wp_remote_retrieve_response_code( /** @scrutinizer ignore-type */ $response );
Loading history...
121
122
		$body = wp_remote_retrieve_body( $response );
0 ignored issues
show
It seems like $response can also be of type WP_Error; however, parameter $response of wp_remote_retrieve_body() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

122
		$body = wp_remote_retrieve_body( /** @scrutinizer ignore-type */ $response );
Loading history...
123
124
		// NULL is returned if the json cannot be decoded or if the encoded data is deeper than the recursion limit.
125
		$ing_result = json_decode( $body );
126
127
		if ( 201 === $response_code ) {
128
			if ( $ing_result && 'error' === $ing_result->status ) {
129
				$error_msg = $ing_result->transactions[0]->reason;
130
				$error     = $ing_result->transactions[0];
131
			} else {
132
				$result = $ing_result;
133
			}
134
		} else {
135
			$error_msg = '';
136
			$error     = '';
137
138
			if ( $ing_result ) {
139
				$error_msg = $ing_result->error->value;
140
				$error     = $ing_result->error;
141
			}
142
143
			if ( 401 === $response_code ) {
144
				// The default error message for an unauthorized API call does not mention the API key in any way.
145
				$error_msg .= ' Please check the API key.';
146
			}
147
		}
148
149
		if ( isset( $error_msg, $error ) ) {
150
			$this->error = new WP_Error( 'ing_kassa_compleet_error', $error_msg, $error );
151
		}
152
153
		return $result;
154
	}
155
156
	/**
157
	 * Get order.
158
	 *
159
	 * @param string $order_id Order ID.
160
	 *
161
	 * @return array|mixed|object|null
162
	 */
163
	public function get_order( $order_id ) {
164
		$result = null;
165
166
		$response = $this->send_request( 'orders/' . $order_id . '/', 'GET' );
167
168
		if ( is_wp_error( $response ) ) {
169
			$this->error = $response;
0 ignored issues
show
Documentation Bug introduced by
It seems like $response can also be of type array. However, the property $error is declared as type WP_Error. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
170
171
			return $result;
172
		}
173
174
		$response_code = wp_remote_retrieve_response_code( $response );
0 ignored issues
show
It seems like $response can also be of type WP_Error; however, parameter $response of wp_remote_retrieve_response_code() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

174
		$response_code = wp_remote_retrieve_response_code( /** @scrutinizer ignore-type */ $response );
Loading history...
175
176
		if ( 200 === $response_code ) {
177
			$body = wp_remote_retrieve_body( $response );
0 ignored issues
show
It seems like $response can also be of type WP_Error; however, parameter $response of wp_remote_retrieve_body() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

177
			$body = wp_remote_retrieve_body( /** @scrutinizer ignore-type */ $response );
Loading history...
178
179
			// NULL is returned if the json cannot be decoded or if the encoded data is deeper than the recursion limit.
180
			$result = json_decode( $body );
181
		}
182
183
		return $result;
184
	}
185
186
	/**
187
	 * Get issuers.
188
	 *
189
	 * @return array|bool
190
	 */
191
	public function get_issuers() {
192
		$issuers = false;
193
194
		$response = $this->send_request( 'ideal/issuers/', 'GET' );
195
196
		if ( is_wp_error( $response ) ) {
197
			$this->error = $response;
0 ignored issues
show
Documentation Bug introduced by
It seems like $response can also be of type array. However, the property $error is declared as type WP_Error. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
198
199
			return $issuers;
200
		}
201
202
		$response_code = wp_remote_retrieve_response_code( $response );
0 ignored issues
show
It seems like $response can also be of type WP_Error; however, parameter $response of wp_remote_retrieve_response_code() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

202
		$response_code = wp_remote_retrieve_response_code( /** @scrutinizer ignore-type */ $response );
Loading history...
203
204
		if ( 200 === $response_code ) {
205
			$body = wp_remote_retrieve_body( $response );
0 ignored issues
show
It seems like $response can also be of type WP_Error; however, parameter $response of wp_remote_retrieve_body() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

205
			$body = wp_remote_retrieve_body( /** @scrutinizer ignore-type */ $response );
Loading history...
206
207
			// NULL is returned if the json cannot be decoded or if the encoded data is deeper than the recursion limit.
208
			$result = json_decode( $body );
209
210
			if ( null !== $result ) {
211
				$issuers = array();
212
213
				foreach ( $result as $issuer ) {
214
					$id   = Security::filter( $issuer->id );
215
					$name = Security::filter( $issuer->name );
216
217
					$issuers[ $id ] = $name;
218
				}
219
			}
220
		} else {
221
			$body = wp_remote_retrieve_body( $response );
222
223
			$ing_result = json_decode( $body );
224
225
			$error_msg = $ing_result->error->value;
226
227
			if ( 401 === $response_code ) {
228
				// An unauthorized API call has nothing to do with the browser of the user in our case, remove to prevent confusion.
229
				$error_msg = str_replace( "You either supplied the wrong credentials (e.g. a bad password), or your browser doesn't understand how to supply the credentials required.", '', $error_msg );
230
231
				// The default error message for an unauthorized API call does not mention the API key in any way.
232
				$error_msg .= ' Please check the API key.';
233
			}
234
235
			$this->error = new WP_Error( 'ing_kassa_compleet_error', $error_msg, $ing_result->error );
236
		}
237
238
		return $issuers;
239
	}
240
}
241