Passed
Push — master ( df4ed5...14d15a )
by Remco
21:23 queued 11:46
created

Client::create_status_sha1()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 4
1
<?php
2
/**
3
 * Client
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2018 Pronamic
7
 * @license   GPL-3.0-or-later
8
 * @package   Pronamic\WordPress\Pay\Payments
9
 */
10
11
namespace Pronamic\WordPress\Pay\Gateways\Sisow;
12
13
use Pronamic\WordPress\Pay\Core\Util as Core_Util;
14
use Pronamic\WordPress\Pay\Gateways\Sisow\XML\ErrorParser;
15
use Pronamic\WordPress\Pay\Gateways\Sisow\XML\InvoiceParser;
16
use Pronamic\WordPress\Pay\Gateways\Sisow\XML\ReservationParser;
17
use Pronamic\WordPress\Pay\Gateways\Sisow\XML\TransactionParser;
18
use SimpleXMLElement;
19
use WP_Error;
20
21
/**
22
 * Title: Sisow
23
 * Description:
24
 * Copyright: Copyright (c) 2005 - 2018
25
 * Company: Pronamic
26
 *
27
 * @author  Remco Tolsma
28
 * @version 2.0.0
29
 * @since   1.0.0
30
 */
31
class Client {
32
	/**
33
	 * Sisow REST API endpoint URL.
34
	 *
35
	 * @var string
36
	 */
37
	const API_URL = 'https://www.sisow.nl/Sisow/iDeal/RestHandler.ashx';
38
39
	/**
40
	 * Sisow merchant ID.
41
	 *
42
	 * @var string
43
	 */
44
	private $merchant_id;
45
46
	/**
47
	 * Sisow merchant key.
48
	 *
49
	 * @var string
50
	 */
51
	private $merchant_key;
52
53
	/**
54
	 * Indicator to use test mode or not.
55
	 *
56
	 * @var boolean
57
	 */
58
	private $test_mode;
59
60
	/**
61
	 * Error.
62
	 *
63
	 * @var WP_Error|null
64
	 */
65
	private $error;
66
67
	/**
68
	 * Constructs and initializes a Sisow client object.
69
	 *
70
	 * @param string $merchant_id  Merchant ID.
71
	 * @param string $merchant_key Merchant key.
72
	 */
73
	public function __construct( $merchant_id, $merchant_key ) {
74
		$this->merchant_id  = $merchant_id;
75
		$this->merchant_key = $merchant_key;
76
	}
77
78
	/**
79
	 * Error.
80
	 *
81
	 * @return WP_Error|null
82
	 */
83
	public function get_error() {
84
		return $this->error;
85
	}
86
87
	/**
88
	 * Set test mode.
89
	 *
90
	 * @param boolean $test_mode True if test mode, false otherwise.
91
	 */
92
	public function set_test_mode( $test_mode ) {
93
		$this->test_mode = $test_mode;
94
	}
95
96
	/**
97
	 * Send request with the specified action and parameters.
98
	 *
99
	 * @param string       $method  Method.
100
	 * @param Request|null $request Request.
101
	 *
102
	 * @return false|SimpleXMLElement
103
	 */
104
	private function send_request( $method, Request $request = null ) {
105
		$url = self::API_URL . '/' . $method;
106
107
		if ( null !== $request ) {
108
			$request->sign( $this->merchant_key );
109
		}
110
111
		$result = Core_Util::remote_get_body(
112
			$url,
113
			200,
114
			array(
115
				'method' => 'POST',
116
				'body'   => ( null === $request ) ? null : $request->get_parameters(),
117
			)
118
		);
119
120
		if ( $result instanceof WP_Error ) {
121
			$this->error = $result;
122
123
			return false;
124
		}
125
126
		if ( ! is_string( $result ) ) {
127
			return false;
128
		}
129
130
		// XML.
131
		$xml = Core_Util::simplexml_load_string( $result );
132
133
		if ( $xml instanceof WP_Error ) {
0 ignored issues
show
introduced by
$xml is never a sub-type of WP_Error.
Loading history...
134
			$this->error = $xml;
135
136
			return false;
137
		}
138
139
		return $xml;
140
	}
141
142
	/**
143
	 * Parse the specified document and return parsed result.
144
	 *
145
	 * @param SimpleXMLElement $document Document.
146
	 *
147
	 * @return WP_Error|Invoice|Reservation|Transaction|Error
148
	 */
149
	private function parse_document( SimpleXMLElement $document ) {
150
		$this->error = null;
151
152
		$name = $document->getName();
153
154
		switch ( $name ) {
155
			case 'cancelreservationresponse':
156
				$reservation = ReservationParser::parse( $document->reservation );
157
158
				return $reservation;
159
			case 'errorresponse':
160
				$sisow_error = ErrorParser::parse( $document->error );
161
162
				$this->error = new WP_Error( 'ideal_sisow_error', $sisow_error->message, $sisow_error );
163
164
				return $sisow_error;
165
			case 'invoiceresponse':
166
				$invoice = InvoiceParser::parse( $document->invoice );
167
168
				return $invoice;
169
			case 'transactionrequest':
170
				$transaction = TransactionParser::parse( $document->transaction );
171
172
				return $transaction;
173
			case 'statusresponse':
174
				$transaction = TransactionParser::parse( $document->transaction );
175
176
				return $transaction;
177
			default:
178
				return new WP_Error(
179
					'ideal_sisow_error',
180
					/* translators: %s: XML document element name */
181
					sprintf( __( 'Unknwon Sisow message (%s)', 'pronamic_ideal' ), $name )
182
				);
183
		}
184
	}
185
186
	/**
187
	 * Get directory.
188
	 *
189
	 * @return array|false
190
	 */
191
	public function get_directory() {
192
		if ( $this->test_mode ) {
193
			return array(
194
				'99' => __( 'Sisow Bank (test)', 'pronamic_ideal' ),
195
			);
196
		}
197
198
		// Request.
199
		$result = $this->send_request( RequestMethods::DIRECTORY_REQUEST );
200
201
		if ( false === $result ) {
202
			return false;
203
		}
204
205
		// Parse.
206
		$directory = array();
207
208
		foreach ( $result->directory->issuer as $issuer ) {
209
			$id   = (string) $issuer->issuerid;
210
			$name = (string) $issuer->issuername;
211
212
			$directory[ $id ] = $name;
213
		}
214
215
		return $directory;
216
	}
217
218
	/**
219
	 * Create an transaction with the specified parameters.
220
	 *
221
	 * @param TransactionRequest $request Transaction request.
222
	 *
223
	 * @return Transaction|false
224
	 */
225
	public function create_transaction( TransactionRequest $request ) {
226
		// Request.
227
		$response = $this->send_request( RequestMethods::TRANSACTION_REQUEST, $request );
228
229
		if ( false === $response ) {
230
			return false;
231
		}
232
233
		// Parse.
234
		$message = $this->parse_document( $response );
235
236
		if ( $message instanceof Transaction ) {
237
			return $message;
238
		}
239
240
		return false;
241
	}
242
243
	/**
244
	 * Create invoice for reservation payment.
245
	 *
246
	 * @param InvoiceRequest $request Invoice request.
247
	 *
248
	 * @return Invoice|false
249
	 */
250
	public function create_invoice( InvoiceRequest $request ) {
251
		// Request.
252
		$response = $this->send_request( RequestMethods::INVOICE_REQUEST, $request );
253
254
		if ( false === $response ) {
255
			return false;
256
		}
257
258
		// Parse.
259
		$message = $this->parse_document( $response );
260
261
		if ( $message instanceof Invoice ) {
262
			return $message;
263
		}
264
265
		return false;
266
	}
267
268
	/**
269
	 * Cancel reservation payment.
270
	 *
271
	 * @param CancelReservationRequest $request Reservation cancellation request.
272
	 *
273
	 * @return Reservation|false
274
	 */
275
	public function cancel_reservation( CancelReservationRequest $request ) {
276
		$request->set_parameter( 'shopid', null );
277
278
		// Request.
279
		$response = $this->send_request( RequestMethods::CANCEL_RESERVATION_REQUEST, $request );
280
281
		if ( false === $response ) {
282
			return false;
283
		}
284
285
		// Parse.
286
		$message = $this->parse_document( $response );
287
288
		if ( $message instanceof Reservation ) {
289
			return $message;
290
		}
291
292
		return false;
293
	}
294
295
	/**
296
	 * Get the status of the specified transaction ID.
297
	 *
298
	 * @param StatusRequest $request Status request object.
299
	 *
300
	 * @return Transaction|false
301
	 */
302
	public function get_status( StatusRequest $request ) {
303
		// Request.
304
		$response = $this->send_request( RequestMethods::STATUS_REQUEST, $request );
305
306
		if ( false === $response ) {
307
			return false;
308
		}
309
310
		// Parse.
311
		$message = $this->parse_document( $response );
312
313
		if ( $message instanceof Transaction ) {
314
			return $message;
315
		}
316
317
		return false;
318
	}
319
}
320