Passed
Push — master ( ca99cf...b0f301 )
by Brian
05:13
created

GetPaid_Payment_Gateway::validate_currency()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 13
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 13
rs 9.6111
cc 5
nc 3
nop 2
1
<?php
2
/**
3
 * Abstract payment gateway
4
 *
5
 */
6
7
defined( 'ABSPATH' ) || exit;
8
9
/**
10
 * Abstaract Payment Gateway class.
11
 *
12
 * Extended by individual payment gateways to handle payments.
13
 */
14
abstract class GetPaid_Payment_Gateway {
15
16
	/**
17
	 * Set if the place checkout button should be renamed on selection.
18
	 *
19
	 * @var string
20
	 */
21
	public $checkout_button_text;
22
23
	/**
24
	 * Boolean whether the method is enabled.
25
	 *
26
	 * @var bool
27
	 */
28
	public $enabled = true;
29
30
	/**
31
	 * Payment method id.
32
	 *
33
	 * @var string
34
	 */
35
	public $id;
36
37
	/**
38
	 * Payment method order.
39
	 *
40
	 * @var int
41
	 */
42
	public $order = 10;
43
44
	/**
45
	 * Payment method title for the frontend.
46
	 *
47
	 * @var string
48
	 */
49
	public $title;
50
51
	/**
52
	 * Payment method description for the frontend.
53
	 *
54
	 * @var string
55
	 */
56
	public $description;
57
58
	/**
59
	 * Gateway title.
60
	 *
61
	 * @var string
62
	 */
63
	public $method_title = '';
64
65
	/**
66
	 * Gateway description.
67
	 *
68
	 * @var string
69
	 */
70
	public $method_description = '';
71
72
	/**
73
	 * Countries this gateway is allowed for.
74
	 *
75
	 * @var array
76
	 */
77
	public $countries;
78
79
	/**
80
	 * Currencies this gateway is allowed for.
81
	 *
82
	 * @var array
83
	 */
84
	public $currencies;
85
86
	/**
87
	 * Currencies this gateway is not allowed for.
88
	 *
89
	 * @var array
90
	 */
91
	public $exclude_currencies;
92
93
	/**
94
	 * Maximum transaction amount, zero does not define a maximum.
95
	 *
96
	 * @var int
97
	 */
98
	public $max_amount = 0;
99
100
	/**
101
	 * Optional URL to view a transaction.
102
	 *
103
	 * @var string
104
	 */
105
	public $view_transaction_url = '';
106
107
	/**
108
	 * Optional URL to view a subscription.
109
	 *
110
	 * @var string
111
	 */
112
	public $view_subscription_url = '';
113
114
	/**
115
	 * Optional label to show for "new payment method" in the payment
116
	 * method/token selection radio selection.
117
	 *
118
	 * @var string
119
	 */
120
	public $new_method_label = '';
121
122
	/**
123
	 * Contains a user's saved tokens for this gateway.
124
	 *
125
	 * @var array
126
	 */
127
	protected $tokens = array();
128
129
	/**
130
	 * An array of features that this gateway supports.
131
	 *
132
	 * @var array
133
	 */
134
	protected $supports = array();
135
136
	/**
137
	 * Class constructor.
138
	 */
139
	public function __construct() {
140
141
		// Register gateway.
142
		add_filter( 'wpinv_payment_gateways', array( $this, 'register_gateway' ) );
143
144
		$this->enabled = wpinv_is_gateway_active( $this->id );
145
146
		// Enable Subscriptions.
147
		if ( $this->supports( 'subscription' ) ) {
148
			add_filter( "wpinv_{$this->id}_support_subscription", '__return_true' );
149
		}
150
151
		// Enable sandbox.
152
		if ( $this->supports( 'sandbox' ) ) {
153
			add_filter( "wpinv_{$this->id}_supports_sandbox", '__return_true' );
154
		}
155
156
		// Invoice addons.
157
		if ( $this->supports( 'addons' ) ) {
158
			add_filter( "getpaid_{$this->id}_supports_addons", '__return_true' );
159
			add_action( "getpaid_process_{$this->id}_invoice_addons", array( $this, 'process_addons' ), 10, 2 );
160
		}
161
162
		// Gateway settings.
163
		add_filter( "wpinv_gateway_settings_{$this->id}", array( $this, 'admin_settings' ) );
164
		
165
166
		// Gateway checkout fiellds.
167
		add_action( "wpinv_{$this->id}_cc_form", array( $this, 'payment_fields' ), 10, 2 );
168
169
		// Process payment.
170
		add_action( "getpaid_gateway_{$this->id}", array( $this, 'process_payment' ), 10, 3 );
171
172
		// Change the checkout button text.
173
		if ( ! empty( $this->checkout_button_text ) ) {
174
			add_filter( "getpaid_gateway_{$this->id}_checkout_button_label", array( $this, 'rename_checkout_button' ) );
175
		}
176
177
		// Check if a gateway is valid for a given currency.
178
		add_filter( "getpaid_gateway_{$this->id}_is_valid_for_currency", array( $this, 'validate_currency' ), 10, 2 );
179
180
		// Generate the transaction url.
181
		add_filter( "getpaid_gateway_{$this->id}_transaction_url", array( $this, 'filter_transaction_url' ), 10, 2 );
182
183
		// Generate the subscription url.
184
		add_filter( 'getpaid_remote_subscription_profile_url', array( $this, 'generate_subscription_url' ), 10, 2 );
185
186
		// Confirm payments.
187
		add_filter( "wpinv_payment_confirm_{$this->id}", array( $this, 'confirm_payment' ), 10, 2 );
188
189
		// Verify IPNs.
190
		add_action( "wpinv_verify_{$this->id}_ipn", array( $this, 'verify_ipn' ) );
191
192
	}
193
194
	/**
195
	 * Checks if this gateway is a given gateway.
196
	 *
197
	 * @since 1.0.19
198
	 * @return bool
199
	 */
200
	public function is( $gateway ) {
201
		return $gateway == $this->id;
202
	}
203
204
	/**
205
	 * Returns a users saved tokens for this gateway.
206
	 *
207
	 * @since 1.0.19
208
	 * @return array
209
	 */
210
	public function get_tokens( $sandbox = null ) {
211
212
		if ( is_user_logged_in() && $this->supports( 'tokens' ) && 0 == count( $this->tokens ) ) {
213
			$tokens = get_user_meta( get_current_user_id(), "getpaid_{$this->id}_tokens", true );
214
215
			if ( is_array( $tokens ) ) {
216
				$this->tokens = $tokens;
217
			}
218
219
		}
220
221
		if ( ! is_bool( $sandbox ) ) {
222
			return $this->tokens;
223
		}
224
225
		$args = array( 'type' => $sandbox ? 'sandbox' : 'live' );
226
		return wp_list_filter( $this->tokens, $args );
227
228
	}
229
230
	/**
231
	 * Saves a token for this gateway.
232
	 *
233
	 * @since 1.0.19
234
	 */
235
	public function save_token( $token ) {
236
237
		$tokens   = $this->get_tokens();
238
		$tokens[] = $token;
239
240
		update_user_meta( get_current_user_id(), "getpaid_{$this->id}_tokens", $tokens );
241
242
		$this->tokens = $tokens;
243
244
	}
245
246
	/**
247
	 * Return the title for admin screens.
248
	 *
249
	 * @return string
250
	 */
251
	public function get_method_title() {
252
		return apply_filters( 'getpaid_gateway_method_title', $this->method_title, $this );
253
	}
254
255
	/**
256
	 * Return the description for admin screens.
257
	 *
258
	 * @return string
259
	 */
260
	public function get_method_description() {
261
		return apply_filters( 'getpaid_gateway_method_description', $this->method_description, $this );
262
	}
263
264
	/**
265
	 * Get the success url.
266
	 *
267
	 * @param WPInv_Invoice $invoice Invoice object.
268
	 * @return string
269
	 */
270
	public function get_return_url( $invoice ) {
271
272
		// Payment success url
273
		$return_url = add_query_arg(
274
			array(
275
				'payment-confirm' => $this->id,
276
				'invoice_key'     => $invoice->get_key(),
277
				'utm_nooverride'  => 1
278
			),
279
			wpinv_get_success_page_uri()
280
		);
281
282
		return apply_filters( 'getpaid_gateway_success_url', $return_url, $invoice, $this );
283
	}
284
285
	/**
286
	 * Confirms payments when rendering the success page.
287
	 *
288
	 * @param string $content Success page content.
289
	 * @return string
290
	 */
291
	public function confirm_payment( $content ) {
292
293
		// Retrieve the invoice.
294
		$invoice_id = getpaid_get_current_invoice_id();
295
		$invoice    = wpinv_get_invoice( $invoice_id );
296
297
		// Ensure that it exists and that it is pending payment.
298
		if ( empty( $invoice_id ) || ! $invoice->needs_payment() ) {
299
			return $content;
300
		}
301
302
		// Can the user view this invoice??
303
		if ( ! wpinv_user_can_view_invoice( $invoice ) ) {
304
			return $content;
305
		}
306
307
		// Show payment processing indicator.
308
		return wpinv_get_template_html( 'wpinv-payment-processing.php', compact( 'invoice' ) );
309
	}
310
311
	/**
312
	 * Processes ipns and marks payments as complete.
313
	 *
314
	 * @return void
315
	 */
316
	public function verify_ipn() {}
317
318
	/**
319
	 * Processes invoice addons.
320
	 *
321
	 * @param WPInv_Invoice $invoice
322
	 * @param GetPaid_Form_Item[] $items
323
	 * @return WPInv_Invoice
324
	 */
325
	public function process_addons( $invoice, $items ) {
326
327
	}
328
329
	/**
330
	 * Get a link to the transaction on the 3rd party gateway site (if applicable).
331
	 *
332
	 * @param string $transaction_url transaction url.
333
	 * @param WPInv_Invoice $invoice Invoice object.
334
	 * @return string transaction URL, or empty string.
335
	 */
336
	public function filter_transaction_url( $transaction_url, $invoice ) {
337
338
		$transaction_id  = $invoice->get_transaction_id();
339
340
		if ( ! empty( $this->view_transaction_url ) && ! empty( $transaction_id ) ) {
341
			$transaction_url = sprintf( $this->view_transaction_url, $transaction_id );
342
			$replace         = $this->is_sandbox( $invoice ) ? 'sandbox' : '';
343
			$transaction_url = str_replace( '{sandbox}', $replace, $transaction_url );
344
		}
345
346
		return $transaction_url;
347
	}
348
349
	/**
350
	 * Get a link to the subscription on the 3rd party gateway site (if applicable).
351
	 *
352
	 * @param string $subscription_url transaction url.
353
	 * @param WPInv_Subscription $subscription Subscription objectt.
354
	 * @return string subscription URL, or empty string.
355
	 */
356
	public function generate_subscription_url( $subscription_url, $subscription ) {
357
358
		$profile_id      = $subscription->get_profile_id();
359
360
		if ( $this->id == $subscription->get_gateway() && ! empty( $this->view_subscription_url ) && ! empty( $profile_id ) ) {
361
362
			$subscription_url = sprintf( $this->view_subscription_url, $profile_id );
363
			$replace          = $this->is_sandbox( $subscription->get_parent_invoice() ) ? 'sandbox' : '';
364
			$subscription_url = str_replace( '{sandbox}', $replace, $subscription_url );
365
366
		}
367
368
		return $subscription_url;
369
	}
370
371
	/**
372
	 * Check if the gateway is available for use.
373
	 *
374
	 * @return bool
375
	 */
376
	public function is_available() {
377
		return ! empty( $this->enabled );
378
	}
379
380
	/**
381
	 * Return the gateway's title.
382
	 *
383
	 * @return string
384
	 */
385
	public function get_title() {
386
		return apply_filters( 'getpaid_gateway_title', $this->title, $this );
387
	}
388
389
	/**
390
	 * Return the gateway's description.
391
	 *
392
	 * @return string
393
	 */
394
	public function get_description() {
395
		return apply_filters( 'getpaid_gateway_description', $this->description, $this );
396
	}
397
398
	/**
399
	 * Process Payment.
400
	 *
401
	 *
402
	 * @param WPInv_Invoice $invoice Invoice.
403
	 * @param array $submission_data Posted checkout fields.
404
	 * @param GetPaid_Payment_Form_Submission $submission Checkout submission.
405
	 * @return void
406
	 */
407
	public function process_payment( $invoice, $submission_data, $submission ) {
408
		// Process the payment then either redirect to the success page or the gateway.
409
		do_action( 'getpaid_process_invoice_payment_' . $this->id, $invoice, $submission_data, $submission );
410
	}
411
412
	/**
413
	 * Process refund.
414
	 *
415
	 * If the gateway declares 'refunds' support, this will allow it to refund.
416
	 * a passed in amount.
417
	 *
418
	 * @param WPInv_Invoice $invoice Invoice.
419
	 * @param  float  $amount Refund amount.
420
	 * @param  string $reason Refund reason.
421
	 * @return WP_Error|bool True or false based on success, or a WP_Error object.
422
	 */
423
	public function process_refund( $invoice, $amount = null, $reason = '' ) {
424
		return apply_filters( 'getpaid_process_invoice_refund_' . $this->id, false, $invoice, $amount, $reason );
425
	}
426
427
	/**
428
	 * Displays the payment fields, credit cards etc.
429
	 * 
430
	 * @param int $invoice_id 0 or invoice id.
431
	 * @param GetPaid_Payment_Form $form Current payment form.
432
	 */
433
	public function payment_fields( $invoice_id, $form ) {
434
		do_action( 'getpaid_getpaid_gateway_payment_fields_' . $this->id, $invoice_id, $form );
435
	}
436
437
	/**
438
	 * Filters the gateway settings.
439
	 * 
440
	 * @param array $admin_settings
441
	 */
442
	public function admin_settings( $admin_settings ) {
443
		return $admin_settings;
444
	}
445
446
	/**
447
	 * Retrieves the value of a gateway setting.
448
	 * 
449
	 * @param string $option
450
	 */
451
	public function get_option( $option, $default = false ) {
452
		return wpinv_get_option( $this->id . '_' . $option, $default );
453
	}
454
455
	/**
456
	 * Check if a gateway supports a given feature.
457
	 *
458
	 * Gateways should override this to declare support (or lack of support) for a feature.
459
	 * For backward compatibility, gateways support 'products' by default, but nothing else.
460
	 *
461
	 * @param string $feature string The name of a feature to test support for.
462
	 * @return bool True if the gateway supports the feature, false otherwise.
463
	 * @since 1.0.19
464
	 */
465
	public function supports( $feature ) {
466
		return apply_filters( 'getpaid_payment_gateway_supports', in_array( $feature, $this->supports ), $feature, $this );
467
	}
468
469
	/**
470
	 * Returns the credit card form html.
471
	 * 
472
	 * @param bool $save whether or not to display the save button.
473
	 */
474
    public function get_cc_form( $save = false ) {
475
476
		ob_start();
477
478
        $id_prefix = esc_attr( uniqid( $this->id ) );
479
480
        $months = array(
481
            '01' => __( 'January', 'invoicing' ),
482
            '02' => __( 'February', 'invoicing' ),
483
            '03' => __( 'March', 'invoicing' ),
484
            '04' => __( 'April', 'invoicing' ),
485
            '05' => __( 'May', 'invoicing' ),
486
            '06' => __( 'June', 'invoicing' ),
487
            '07' => __( 'July', 'invoicing' ),
488
            '08' => __( 'August', 'invoicing' ),
489
            '09' => __( 'September', 'invoicing' ),
490
            '10' => __( 'October', 'invoicing' ),
491
            '11' => __( 'November', 'invoicing' ),
492
            '12' => __( 'December', 'invoicing' ),
493
        );
494
495
        $year  = (int) date( 'Y', current_time( 'timestamp' ) );
496
        $years = array();
497
498
        for ( $i = 0; $i <= 10; $i++ ) {
499
            $years[ $year + $i ] = $year + $i;
500
        }
501
502
        ?>
503
            <div class="<?php echo esc_attr( $this->id );?>-cc-form getpaid-cc-form mt-1">
504
505
506
                <div class="getpaid-cc-card-inner">
507
                    <div class="row">
508
509
                        <div class="col-12">
510
511
							<div class="form-group">
512
								<label for="<?php echo esc_attr( "$id_prefix-cc-number" ) ?>"><?php _e( 'Card number', 'invoicing' ); ?></label>
513
								<div class="input-group input-group-sm">
514
									<div class="input-group-prepend ">
515
										<span class="input-group-text">
516
											<i class="fa fa-credit-card"></i>
517
										</span>
518
									</div>
519
									<input type="text" name="<?php echo esc_attr( $this->id . '[cc_number]' ) ?>authorizenet[cc_number]" id="<?php echo esc_attr( "$id_prefix-cc-number" ) ?>" class="form-control form-control-sm" autocomplete="cc-number">
520
								</div>
521
							</div>
522
523
                        </div>
524
525
                        <div class="col-12">
526
                            <div class="form-group">
527
                                <label><?php _e( 'Expiration', 'invoicing' ); ?></label>
528
                                <div class="form-row">
529
530
                                    <div class="col">
531
                                        <select class="form-control form-control-sm" autocomplete="cc-exp-month" name="<?php echo esc_attr( $this->id );?>[cc_expire_month]">
532
                                            <option disabled selected="selected"><?php _e( 'MM', 'invoicing' ); ?></option>
533
534
                                            <?php
535
                                                foreach ( $months as $key => $month ) {
536
                                                    $key   = esc_attr( $key );
537
                                                    $month = wpinv_clean( $month );
538
                                                    echo "<option value='$key'>$month</option>" . PHP_EOL;
539
                                                }
540
                                            ?>
541
542
                                        </select>
543
                                    </div>
544
545
                                    <div class="col">
546
                                        <select class="form-control form-control-sm" autocomplete="cc-exp-year" name="<?php echo esc_attr( $this->id );?>[cc_expire_year]">
547
                                            <option disabled selected="selected"><?php _e( 'YY', 'invoicing' ); ?></option>
548
549
                                            <?php
550
                                                foreach ( $years as $key => $year ) {
551
                                                    $key   = esc_attr( $key );
552
                                                    $year  = wpinv_clean( $year );
553
                                                    echo "<option value='$key'>$year</option>" . PHP_EOL;
554
                                                }
555
                                            ?>
556
557
                                        </select>
558
                                    </div>
559
            
560
                                </div>
561
                            </div>
562
                        </div>
563
564
                        <div class="col-12">
565
                            <?php
566
                                echo aui()->input(
567
                                    array(
568
                                        'name'              => $this->id . '[cc_cvv2]',
569
                                        'id'                => "$id_prefix-cc-cvv2",
570
                                        'label'             => __( 'CCV', 'invoicing' ),
571
										'label_type'        => 'vertical',
572
										'class'             => 'form-control-sm',
573
										'extra_attributes'  => array(
574
											'autocomplete'  => "cc-csc",
575
										),
576
                                    )
577
                                );
578
                            ?>
579
                        </div>
580
581
					</div>
582
					
583
					<?php
584
585
						if ( $save ) {
586
							echo $this->save_payment_method_checkbox();
587
						}
588
589
					?>
590
                </div>
591
592
            </div>
593
		<?php
594
		
595
		return ob_get_clean();
596
597
    }
598
599
	/**
600
	 * Displays a new payment method entry form.
601
	 *
602
	 * @since 1.0.19
603
	 */
604
	public function new_payment_method_entry( $form ) {
605
		echo "<div class='getpaid-new-payment-method-form' style='display:none;'>$form</div>";
606
	}
607
608
	/**
609
	 * Grab and display our saved payment methods.
610
	 *
611
	 * @since 1.0.19
612
	 */
613
	public function saved_payment_methods() {
614
		$html = '<ul class="getpaid-saved-payment-methods list-unstyled m-0 mt-2" data-count="' . esc_attr( count( $this->get_tokens( $this->is_sandbox() ) ) ) . '">';
615
616
		foreach ( $this->get_tokens( $this->is_sandbox() ) as $token ) {
617
			$html .= $this->get_saved_payment_method_option_html( $token );
618
		}
619
620
		$html .= $this->get_new_payment_method_option_html();
621
		$html .= '</ul>';
622
623
		echo apply_filters( 'getpaid_payment_gateway_form_saved_payment_methods_html', $html, $this );
624
	}
625
626
	/**
627
	 * Gets saved payment method HTML from a token.
628
	 *
629
	 * @since 1.0.19
630
	 * @param  array $token Payment Token.
631
	 * @return string Generated payment method HTML
632
	 */
633
	public function get_saved_payment_method_option_html( $token ) {
634
635
		return sprintf(
636
			'<li class="getpaid-payment-method form-group">
637
				<label>
638
					<input name="getpaid-%1$s-payment-method" type="radio" value="%2$s" style="width:auto;" class="getpaid-saved-payment-method-token-input" %4$s />
639
					<span>%3$s</span>
640
				</label>
641
			</li>',
642
			esc_attr( $this->id ),
643
			esc_attr( $token['id'] ),
644
			esc_html( $token['name'] ),
645
			checked( empty( $token['default'] ), false, false )
646
		);
647
648
	}
649
650
	/**
651
	 * Displays a radio button for entering a new payment method (new CC details) instead of using a saved method.
652
	 *
653
	 * @since 1.0.19
654
	 */
655
	public function get_new_payment_method_option_html() {
656
657
		$label = apply_filters( 'getpaid_new_payment_method_label', $this->new_method_label ? $this->new_method_label : __( 'Use a new payment method', 'invoicing' ), $this );
658
659
		return sprintf(
660
			'<li class="getpaid-new-payment-method">
661
				<label>
662
					<input name="getpaid-%1$s-payment-method" type="radio" value="new" style="width:auto;" />
663
					<span>%2$s</span>
664
				</label>
665
			</li>',
666
			esc_attr( $this->id ),
667
			esc_html( $label )
668
		);
669
670
	}
671
672
	/**
673
	 * Outputs a checkbox for saving a new payment method to the database.
674
	 *
675
	 * @since 1.0.19
676
	 */
677
	public function save_payment_method_checkbox() {
678
679
		return aui()->input(
680
			array(
681
				'type'       => 'checkbox',
682
				'name'       => esc_attr( "getpaid-$this->id-new-payment-method" ),
683
				'id'         => esc_attr( uniqid( $this->id ) ),
684
				'required'   => false,
685
				'label'      => esc_html__( 'Save payment method', 'invoicing' ),
686
				'value'      => 'true',
687
				'checked'    => true,
688
				'wrap_class' => 'getpaid-save-payment-method pt-1 pb-1',
689
			)
690
		);
691
692
	}
693
694
	/**
695
	 * Registers the gateway.
696
	 *
697
	 * @return array
698
	 */
699
	public function register_gateway( $gateways ) {
700
701
		$gateways[ $this->id ] = array(
702
703
			'admin_label'    => $this->method_title,
704
            'checkout_label' => $this->title,
705
			'ordering'       => $this->order,
706
707
		);
708
709
		return $gateways;
710
711
	}
712
713
	/**
714
	 * Checks whether or not this is a sandbox request.
715
	 *
716
	 * @param  WPInv_Invoice|null $invoice Invoice object or null.
717
	 * @return bool
718
	 */
719
	public function is_sandbox( $invoice = null ) {
720
721
		if ( ! empty( $invoice ) && ! $invoice->needs_payment() ) {
722
			return $invoice->get_mode() == 'test';
723
		}
724
725
		return wpinv_is_test_mode( $this->id );
726
727
	}
728
729
	/**
730
	 * Renames the checkout button
731
	 *
732
	 * @return string
733
	 */
734
	public function rename_checkout_button() {
735
		return $this->checkout_button_text;
736
	}
737
738
	/**
739
	 * Validate gateway currency
740
	 *
741
	 * @return bool
742
	 */
743
	public function validate_currency( $validation, $currency ) {
744
745
		// Required currencies.
746
		if ( ! empty( $this->currencies ) && ! in_array( $currency, $this->currencies ) ) {
747
			return false;
748
		}
749
750
		// Excluded currencies.
751
		if ( ! empty( $this->exclude_currencies ) && in_array( $currency, $this->exclude_currencies ) ) {
752
			return false;
753
		}
754
755
		return $validation;
756
	}
757
758
	/**
759
	 * Displays an error
760
	 *
761
	 */
762
	public function show_error( $code, $message, $type ) {
763
764
		if ( is_admin() ) {
765
			getpaid_admin()->{"show_$type"}( $message );
766
		}
767
768
		wpinv_set_error( $code, $message, $type );
769
770
	}
771
772
}
773