Client::create_transaction()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 16
ccs 0
cts 10
cp 0
rs 10
cc 3
nc 3
nop 1
crap 12
1
<?php
2
/**
3
 * Client
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2022 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\MerchantParser;
17
use Pronamic\WordPress\Pay\Gateways\Sisow\XML\ReservationParser;
18
use Pronamic\WordPress\Pay\Gateways\Sisow\XML\TransactionParser;
19
use SimpleXMLElement;
20
21
/**
22
 * Title: Sisow
23
 * Description:
24
 * Copyright: 2005-2022 Pronamic
25
 * Company: Pronamic
26
 *
27
 * @author  Remco Tolsma
28
 * @version 2.0.4
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
	 * Constructs and initializes a Sisow client object.
62
	 *
63
	 * @param string $merchant_id  Merchant ID.
64
	 * @param string $merchant_key Merchant key.
65
	 */
66
	public function __construct( $merchant_id, $merchant_key ) {
67
		$this->merchant_id  = $merchant_id;
68
		$this->merchant_key = $merchant_key;
69
	}
70
71
	/**
72
	 * Set test mode.
73
	 *
74
	 * @param boolean $test_mode True if test mode, false otherwise.
75
	 * @return void
76
	 */
77
	public function set_test_mode( $test_mode ) {
78
		$this->test_mode = $test_mode;
79
	}
80
81
	/**
82
	 * Send request with the specified action and parameters.
83
	 *
84
	 * @param string       $method  Method.
85
	 * @param Request|null $request Request.
86
	 *
87
	 * @return false|SimpleXMLElement
88
	 */
89
	private function send_request( $method, Request $request = null ) {
90
		$url = self::API_URL . '/' . $method;
91
92
		if ( null !== $request ) {
93
			$request->sign( $this->merchant_key );
94
		}
95
96
		$result = Core_Util::remote_get_body(
97
			$url,
98
			200,
99
			array(
100
				'method' => 'POST',
101
				'body'   => ( null === $request ) ? null : $request->get_parameters(),
102
			)
103
		);
104
105
		if ( ! is_string( $result ) ) {
106
			return false;
107
		}
108
109
		// XML.
110
		$xml = Core_Util::simplexml_load_string( $result );
111
112
		return $xml;
113
	}
114
115
	/**
116
	 * Parse the specified document and return parsed result.
117
	 *
118
	 * @param SimpleXMLElement $document Document.
119
	 *
120
	 * @return Invoice|Merchant|Reservation|Transaction
121
	 * @throws \Exception Throws exception on unknown Sisow message.
122
	 */
123
	private function parse_document( SimpleXMLElement $document ) {
124
		$name = $document->getName();
125
126
		switch ( $name ) {
127
			case 'cancelreservationresponse':
128
				$reservation = ReservationParser::parse( $document->reservation );
129
130
				return $reservation;
131
			case 'checkmerchantresponse':
132
				$merchant = MerchantParser::parse( $document->merchant );
133
134
				return $merchant;
135
			case 'errorresponse':
136
				$sisow_error = ErrorParser::parse( $document->error );
137
138
				$message = sprintf( '%s: %s', $sisow_error->code, $sisow_error->message );
139
140
				throw new \Exception( $message );
141
			case 'invoiceresponse':
142
				$invoice = InvoiceParser::parse( $document->invoice );
143
144
				return $invoice;
145
			case 'statusresponse':
146
			case 'transactionrequest':
147
				$transaction = TransactionParser::parse( $document->transaction );
148
149
				return $transaction;
150
			default:
151
				throw new \Exception(
152
					/* translators: %s: XML document element name */
153
					sprintf( __( 'Unknown Sisow message (%s)', 'pronamic_ideal' ), $name )
154
				);
155
		}
156
	}
157
158
	/**
159
	 * Get directory.
160
	 *
161
	 * @return array<int|string, string>|false
162
	 */
163
	public function get_directory() {
164
		if ( $this->test_mode ) {
165
			return array(
166
				'99' => __( 'Sisow Bank (test)', 'pronamic_ideal' ),
167
			);
168
		}
169
170
		// Request.
171
		$result = $this->send_request( RequestMethods::DIRECTORY_REQUEST );
172
173
		if ( false === $result ) {
174
			return false;
175
		}
176
177
		// Parse.
178
		$directory = array();
179
180
		foreach ( $result->directory->issuer as $issuer ) {
181
			$id   = (string) $issuer->issuerid;
182
			$name = (string) $issuer->issuername;
183
184
			$directory[ $id ] = $name;
185
		}
186
187
		return $directory;
188
	}
189
190
	/**
191
	 * Get merchant.
192
	 *
193
	 * @param MerchantRequest $merchant_request Merchant request.
194
	 *
195
	 * @return Merchant|false
196
	 */
197
	public function get_merchant( MerchantRequest $merchant_request ) {
198
		// Request.
199
		$response = $this->send_request( RequestMethods::CHECK_MERCHANT_REQUEST, $merchant_request );
200
201
		if ( false === $response ) {
202
			return false;
203
		}
204
205
		// Parse.
206
		$message = $this->parse_document( $response );
207
208
		if ( $message instanceof Merchant ) {
209
			return $message;
210
		}
211
212
		return false;
213
	}
214
215
	/**
216
	 * Create an transaction with the specified parameters.
217
	 *
218
	 * @param TransactionRequest $request Transaction request.
219
	 *
220
	 * @return Transaction|false
221
	 *
222
	 * @throws \Exception Throws exception on transaction error.
223
	 */
224
	public function create_transaction( TransactionRequest $request ) {
225
		// Request.
226
		$response = $this->send_request( RequestMethods::TRANSACTION_REQUEST, $request );
227
228
		if ( false === $response ) {
229
			return false;
230
		}
231
232
		// Parse.
233
		$message = $this->parse_document( $response );
234
235
		if ( $message instanceof Transaction ) {
236
			return $message;
237
		}
238
239
		return false;
240
	}
241
242
	/**
243
	 * Create invoice for reservation payment.
244
	 *
245
	 * @param InvoiceRequest $request Invoice request.
246
	 *
247
	 * @return Invoice|false
248
	 *
249
	 * @throws \Exception Throws exception on error.
250
	 */
251
	public function create_invoice( InvoiceRequest $request ) {
252
		// Request.
253
		$response = $this->send_request( RequestMethods::INVOICE_REQUEST, $request );
254
255
		if ( false === $response ) {
256
			return false;
257
		}
258
259
		// Parse.
260
		$message = $this->parse_document( $response );
261
262
		if ( $message instanceof Invoice ) {
263
			return $message;
264
		}
265
266
		return false;
267
	}
268
269
	/**
270
	 * Cancel reservation payment.
271
	 *
272
	 * @param CancelReservationRequest $request Reservation cancellation request.
273
	 *
274
	 * @return Reservation|false
275
	 *
276
	 * @throws \Exception Throws exception on error.
277
	 */
278
	public function cancel_reservation( CancelReservationRequest $request ) {
279
		$request->set_parameter( 'shopid', null );
280
281
		// Request.
282
		$response = $this->send_request( RequestMethods::CANCEL_RESERVATION_REQUEST, $request );
283
284
		if ( false === $response ) {
285
			return false;
286
		}
287
288
		// Parse.
289
		$message = $this->parse_document( $response );
290
291
		if ( $message instanceof Reservation ) {
292
			return $message;
293
		}
294
295
		return false;
296
	}
297
298
	/**
299
	 * Get the status of the specified transaction ID.
300
	 *
301
	 * @param StatusRequest $request Status request object.
302
	 *
303
	 * @return Transaction|false
304
	 *
305
	 * @throws \InvalidArgumentException Throws exception on invalid transaction ID.
306
	 */
307
	public function get_status( StatusRequest $request ) {
308
		$transaction_id = $request->get_parameter( 'trxid' );
309
310
		if ( empty( $transaction_id ) ) {
311
			throw new \InvalidArgumentException( 'Invalid transaction ID.' );
312
		}
313
314
		// Request.
315
		$response = $this->send_request( RequestMethods::STATUS_REQUEST, $request );
316
317
		if ( false === $response ) {
318
			return false;
319
		}
320
321
		// Parse.
322
		$message = $this->parse_document( $response );
323
324
		if ( $message instanceof Transaction ) {
325
			return $message;
326
		}
327
328
		return false;
329
	}
330
}
331