Failed Conditions
Push — develop ( 664d7d...d8db7e )
by Remco
03:03
created

src/Gateway.php (2 issues)

1
<?php
2
/**
3
 * Gateway
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2019 Pronamic
7
 * @license   GPL-3.0-or-later
8
 * @package   Pronamic\WordPress\Pay\Gateways\Adyen
9
 */
10
11
namespace Pronamic\WordPress\Pay\Gateways\Adyen;
12
13
use Pronamic\WordPress\Pay\Core\Gateway as Core_Gateway;
14
use Pronamic\WordPress\Pay\Core\Statuses as Core_Statuses;
15
use Pronamic\WordPress\Pay\Core\PaymentMethods;
16
use Pronamic\WordPress\Pay\Core\Util;
17
use Pronamic\WordPress\Pay\Payments\Payment;
18
use Pronamic\WordPress\Pay\Plugin;
19
20
/**
21
 * Gateway
22
 *
23
 * @author  Remco Tolsma
24
 * @version 1.0.0
25
 * @since   1.0.0
26
 * @link    https://github.com/adyenpayments/php/blob/master/generatepaymentform.php
27
 */
28
class Gateway extends Core_Gateway {
29
	/**
30
	 * Slug of this gateway.
31
	 *
32
	 * @var string
33
	 */
34
	const SLUG = 'adyen';
35
36
	/**
37
	 * Client.
38
	 *
39
	 * @var Client
40
	 */
41
	protected $client;
42
43
	/**
44
	 * Constructs and initializes an Adyen gateway.
45
	 *
46
	 * @param Config $config Config.
47
	 */
48
	public function __construct( Config $config ) {
49
		parent::__construct( $config );
50
51
		$this->set_method( self::METHOD_HTTP_REDIRECT );
52
		$this->set_slug( self::SLUG );
53
54
		$this->client = new Client( $config->api_key, $config->api_live_url_prefix );
55
		$this->client->set_merchant_account( $config->merchant_account );
56
		$this->client->set_mode( $config->mode );
57
	}
58
59
	/**
60
	 * Get supported payment methods
61
	 *
62
	 * @see Core_Gateway::get_supported_payment_methods()
63
	 */
64
	public function get_supported_payment_methods() {
65
		return array(
66
			PaymentMethods::BANCONTACT,
67
			PaymentMethods::CREDIT_CARD,
68
			PaymentMethods::DIRECT_DEBIT,
69
			PaymentMethods::GIROPAY,
70
			PaymentMethods::IDEAL,
71
			PaymentMethods::MAESTRO,
72
			PaymentMethods::SOFORT,
73
		);
74
	}
75
76
	/**
77
	 * Start.
78
	 *
79
	 * @param Payment $payment Payment.
80
	 *
81
	 * @see Plugin::start()
82
	 */
83
	public function start( Payment $payment ) {
84
		// Payment request.
85
		$request = new PaymentRequest();
0 ignored issues
show
The call to Pronamic\WordPress\Pay\G...tRequest::__construct() has too few arguments starting with amount. ( Ignorable by Annotation )

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

85
		$request = /** @scrutinizer ignore-call */ new PaymentRequest();

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
86
87
		$request->merchant_account = $this->config->merchant_account;
88
		$request->return_url       = $payment->get_return_url();
89
		$request->reference        = $payment->get_id();
90
		$request->origin_url       = home_url();
91
		$request->sdk_version      = '1.6.3';
92
		$request->channel          = 'Web';
93
94
		// Amount.
95
		$request->currency     = $payment->get_total_amount()->get_currency()->get_alphabetic_code();
96
		$request->amount_value = $payment->get_total_amount()->get_minor_units();
0 ignored issues
show
The method get_minor_units() does not exist on Pronamic\WordPress\Money\TaxedMoney. ( Ignorable by Annotation )

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

96
		$request->amount_value = $payment->get_total_amount()->/** @scrutinizer ignore-call */ get_minor_units();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
97
98
		// Payment method. Take leap of faith for unknown payment method types.
99
		$adyen_method = PaymentMethodType::transform( $payment->get_method(), $payment->get_method() );
100
101
		$request->payment_method = array(
102
			'type' => $adyen_method,
103
		);
104
105
		switch ( $payment->get_method() ) {
106
			case PaymentMethods::IDEAL:
107
				$request->payment_method['issuer'] = $payment->get_issuer();
108
109
				break;
110
		}
111
112
		// Country.
113
		$locale = get_locale();
114
115
		if ( null !== $payment->get_customer() ) {
116
			$locale = $payment->get_customer()->get_locale();
117
		}
118
119
		$locale = explode( '_', $locale );
120
121
		$request->country_code = strtoupper( substr( $locale[1], 0, 2 ) );
122
123
		// Shopper.
124
		$request->shopper_statement = $payment->get_description();
125
126
		if ( null !== $payment->get_customer() ) {
127
			$request->shopper_ip               = $payment->get_customer()->get_ip_address();
128
			$request->shopper_gender           = $payment->get_customer()->get_gender();
129
			$request->shopper_locale           = $payment->get_customer()->get_locale();
130
			$request->shopper_reference        = $payment->get_customer()->get_user_id();
131
			$request->shopper_telephone_number = $payment->get_customer()->get_phone();
132
133
			if ( null !== $payment->get_customer()->get_name() ) {
134
				$request->shopper_first_name = $payment->get_customer()->get_name()->get_first_name();
135
				$request->shopper_name_infix = $payment->get_customer()->get_name()->get_middle_name();
136
				$request->shopper_last_name  = $payment->get_customer()->get_name()->get_last_name();
137
			}
138
		}
139
140
		// Create payment or payment session.
141
		switch ( $payment->get_method() ) {
142
			case PaymentMethods::IDEAL:
143
			case PaymentMethods::SOFORT:
144
				// API integration.
145
				$result = $this->client->create_payment( $request );
146
147
				break;
148
			default:
149
				// Web SDK integration.
150
				$allowed_methods = array( $adyen_method );
151
152
				// Add all available payment methods if no payment method is given.
153
				if ( empty( $adyen_method ) ) {
154
					$allowed_methods = array();
155
156
					foreach ( $this->get_available_payment_methods() as $method ) {
157
						$allowed_methods[] = PaymentMethodType::transform( $method );
158
					}
159
				}
160
161
				// Set allowed payment methods.
162
				$request->allowed_payment_methods = $allowed_methods;
163
164
				// Create payment session.
165
				$result = $this->client->create_payment_session( $request );
166
		}
167
168
		if ( ! $result ) {
169
			$this->error = $this->client->get_error();
170
171
			return;
172
		}
173
174
		if ( isset( $result->paymentSession ) ) {
175
			// No cache.
176
			Util::no_cache();
177
178
			$redirect_message = '<div id="pronamic-pay-checkout"></div><div style="clear:both;"></div>';
179
180
			include Plugin::$dirname . '/views/redirect-message.php';
181
182
			?>
183
184
			<script type="text/javascript" src="https://checkoutshopper-test.adyen.com/checkoutshopper/assets/js/sdk/checkoutSDK.1.6.3.min.js"></script>
185
186
			<script type="text/javascript">
187
			// Initiate the Adyen Checkout form.
188
			var checkout = chckt.checkout(
189
				'<?php echo esc_html( $result->paymentSession ); ?>',
190
				'#pronamic-pay-checkout',
191
				{ context: '<?php echo( self::MODE_TEST === $this->config->mode ? 'test' : 'live' ); ?>' }
192
			);
193
194
			// Redirect once payment completes.
195
			chckt.hooks.beforeComplete = function ( node, paymentData ) {
196
				if ( "undefined" !== paymentData.payload ) {
197
					window.location.href = '<?php echo $payment->get_return_url(); ?>&payload=' + encodeURIComponent( paymentData.payload );
198
199
					return false;
200
				}
201
			};
202
			</script>
203
204
			<?php
205
206
			exit;
207
		}
208
209
		// Set transaction ID.
210
		if ( isset( $result->pspReference ) ) {
211
			$payment->set_transaction_id( $result->pspReference );
212
		}
213
214
		// Set redirect URL.
215
		if ( isset( $result->redirect->url ) ) {
216
			$payment->set_action_url( $result->redirect->url );
217
		}
218
	}
219
220
	/**
221
	 * Update status of the specified payment.
222
	 *
223
	 * @param Payment $payment Payment.
224
	 *
225
	 * @return void
226
	 */
227
	public function update_status( Payment $payment ) {
228
		// Maybe process stored webhook notification.
229
		$this->maybe_handle_notification( $payment );
230
231
		// Process payload on return.
232
		if ( ! filter_has_var( INPUT_GET, 'payload' ) ) {
233
			return;
234
		}
235
236
		$status = null;
237
238
		$payload = filter_input( INPUT_GET, 'payload', FILTER_SANITIZE_STRING );
239
240
		switch ( $payment->get_method() ) {
241
			case PaymentMethods::IDEAL:
242
			case PaymentMethods::SOFORT:
243
				$result = $this->client->get_payment_details( $payload );
244
245
				break;
246
			default:
247
				$result = $this->client->get_payment_result( $payload );
248
		}
249
250
		if ( $result ) {
251
			$status = ResultCode::transform( $result->resultCode );
252
253
			$psp_reference = $result->pspReference;
254
		}
255
256
		// Handle errors.
257
		if ( empty( $status ) ) {
258
			$payment->set_status( Core_Statuses::FAILURE );
259
260
			$this->error = $this->client->get_error();
261
262
			return;
263
		}
264
265
		// Update status.
266
		$payment->set_status( $status );
267
268
		// Update transaction ID.
269
		if ( isset( $psp_reference ) ) {
270
			$payment->set_transaction_id( $psp_reference );
271
		}
272
	}
273
274
	/**
275
	 * Maybe handle notification.
276
	 *
277
	 * @param Payment $payment      Payment.
278
	 */
279
	public function maybe_handle_notification( Payment $payment ) {
280
		$notification = $payment->get_meta( 'adyen_notification' );
281
282
		if ( empty( $notification ) ) {
283
			return;
284
		}
285
286
		$notification = json_decode( $notification );
287
288
		if ( ! is_object( $notification ) ) {
289
			return;
290
		}
291
292
		switch ( $notification->eventCode ) {
293
			case EventCode::AUTHORIZATION:
294
				$this->handle_authorization_event( $payment, $notification );
295
296
				break;
297
		}
298
299
		$payment->set_meta( 'adyen_notification', null );
300
	}
301
302
	/**
303
	 * Handle authorization event.
304
	 *
305
	 * @param Payment $payment      Payment.
306
	 * @param object  $notification Notification.
307
	 */
308
	public function handle_authorization_event( Payment $payment, $notification ) {
309
		if ( ! is_object( $notification ) ) {
310
			return;
311
		}
312
313
		$success = $notification->success;
314
315
		if ( 'true' === $success ) {
316
			$status = Core_Statuses::SUCCESS;
317
		} else {
318
			$status = Core_Statuses::FAILURE;
319
320
			// Add note.
321
			$note = sprintf(
322
				/* translators: %s: failure reason message */
323
				__( 'Failure reason: %s.', 'pronamic_ideal' ),
324
				esc_html( $notification->reason )
325
			);
326
327
			$payment->add_note( $note );
328
		}
329
330
		$payment->set_status( $status );
331
	}
332
333
	/**
334
	 * Get available payment methods.
335
	 *
336
	 * @see Core_Gateway::get_available_payment_methods()
337
	 */
338
	public function get_available_payment_methods() {
339
		$payment_methods = array();
340
341
		// Get active payment methods for Adyen account.
342
		$methods = $this->client->get_payment_methods();
343
344
		if ( ! $methods ) {
345
			$this->error = $this->client->get_error();
346
347
			return $payment_methods;
348
		}
349
350
		// Transform to WordPress payment methods.
351
		foreach ( $methods as $method => $details ) {
352
			$payment_method = PaymentMethodType::transform_gateway_method( $method );
353
354
			if ( $payment_method ) {
355
				$payment_methods[] = $payment_method;
356
			}
357
		}
358
359
		$payment_methods = array_unique( $payment_methods );
360
361
		return $payment_methods;
362
	}
363
364
	/**
365
	 * Get issuers.
366
	 *
367
	 * @see Pronamic_WP_Pay_Gateway::get_issuers()
368
	 */
369
	public function get_issuers() {
370
		$groups = array();
371
372
		$payment_method = PaymentMethodType::transform( PaymentMethods::IDEAL );
373
374
		$result = $this->client->get_issuers( $payment_method );
375
376
		if ( ! $result ) {
377
			$this->error = $this->client->get_error();
378
379
			return $groups;
380
		}
381
382
		$groups[] = array(
383
			'options' => $result,
384
		);
385
386
		return $groups;
387
	}
388
}
389