Passed
Push — master ( ba4e78...47f790 )
by Brian
11:22
created

GetPaid_Paypal_Gateway::admin_settings()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 107
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 19
c 2
b 0
f 0
nc 1
nop 1
dl 0
loc 107
rs 9.6333

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Paypal payment gateway
4
 *
5
 */
6
7
defined( 'ABSPATH' ) || exit;
8
9
/**
10
 * Paypal Payment Gateway class.
11
 *
12
 */
13
class GetPaid_Paypal_Gateway extends GetPaid_Payment_Gateway {
14
15
    /**
16
	 * Payment method id.
17
	 *
18
	 * @var string
19
	 */
20
    public $id = 'paypal';
21
22
    /**
23
	 * An array of features that this gateway supports.
24
	 *
25
	 * @var array
26
	 */
27
    protected $supports = array( 'subscription', 'sandbox', 'single_subscription_group' );
28
29
    /**
30
	 * Payment method order.
31
	 *
32
	 * @var int
33
	 */
34
    public $order = 1;
35
36
    /**
37
	 * Stores line items to send to PayPal.
38
	 *
39
	 * @var array
40
	 */
41
    protected $line_items = array();
42
43
    /**
44
	 * Endpoint for requests from PayPal.
45
	 *
46
	 * @var string
47
	 */
48
	protected $notify_url;
49
50
	/**
51
	 * Endpoint for requests to PayPal.
52
	 *
53
	 * @var string
54
	 */
55
    protected $endpoint;
56
57
    /**
58
	 * Currencies this gateway is allowed for.
59
	 *
60
	 * @var array
61
	 */
62
	public $currencies = array( 'AUD', 'BRL', 'CAD', 'MXN', 'NZD', 'HKD', 'SGD', 'USD', 'EUR', 'JPY', 'TRY', 'NOK', 'CZK', 'DKK', 'HUF', 'ILS', 'MYR', 'PHP', 'PLN', 'SEK', 'CHF', 'TWD', 'THB', 'GBP', 'RMB', 'RUB', 'INR' );
63
64
    /**
65
	 * URL to view a transaction.
66
	 *
67
	 * @var string
68
	 */
69
    public $view_transaction_url = 'https://www.{sandbox}paypal.com/activity/payment/%s';
70
71
    /**
72
	 * URL to view a subscription.
73
	 *
74
	 * @var string
75
	 */
76
	public $view_subscription_url = 'https://www.{sandbox}paypal.com/cgi-bin/webscr?cmd=_profile-recurring-payments&encrypted_profile_id=%s';
77
78
    /**
79
	 * Class constructor.
80
	 */
81
	public function __construct() {
82
83
        $this->title                = __( 'PayPal Standard', 'invoicing' );
84
        $this->method_title         = __( 'PayPal Standard', 'invoicing' );
85
        $this->checkout_button_text = __( 'Proceed to PayPal', 'invoicing' );
86
        $this->notify_url           = wpinv_get_ipn_url( $this->id );
87
88
		add_filter( 'getpaid_paypal_args', array( $this, 'process_subscription' ), 10, 2 );
89
        add_filter( 'getpaid_paypal_sandbox_notice', array( $this, 'sandbox_notice' ) );
90
		add_filter( 'getpaid_get_paypal_connect_url', array( $this, 'maybe_get_connect_url' ), 10, 2 );
91
		add_action( 'getpaid_authenticated_admin_action_connect_paypal', array( $this, 'connect_paypal' ) );
92
93
        parent::__construct();
94
    }
95
96
    /**
97
	 * Process Payment.
98
	 *
99
	 *
100
	 * @param WPInv_Invoice $invoice Invoice.
101
	 * @param array $submission_data Posted checkout fields.
102
	 * @param GetPaid_Payment_Form_Submission $submission Checkout submission.
103
	 * @return array
104
	 */
105
	public function process_payment( $invoice, $submission_data, $submission ) {
106
107
        // Get redirect url.
108
        $paypal_redirect = $this->get_request_url( $invoice );
109
110
        // Add a note about the request url.
111
        $invoice->add_note(
112
            sprintf(
113
                __( 'Redirecting to PayPal: %s', 'invoicing' ),
114
                esc_url( $paypal_redirect )
115
            ),
116
            false,
117
            false,
118
            true
119
        );
120
121
        // Redirect to PayPal
122
        wp_redirect( $paypal_redirect );
123
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
124
125
    }
126
127
    /**
128
	 * Get the PayPal request URL for an invoice.
129
	 *
130
	 * @param  WPInv_Invoice $invoice Invoice object.
131
	 * @return string
132
	 */
133
	public function get_request_url( $invoice ) {
134
135
        // Endpoint for this request
136
		$this->endpoint    = $this->is_sandbox( $invoice ) ? 'https://www.sandbox.paypal.com/cgi-bin/webscr?test_ipn=1&' : 'https://www.paypal.com/cgi-bin/webscr?';
137
138
        // Retrieve paypal args.
139
        $paypal_args       = map_deep( $this->get_paypal_args( $invoice ), 'urlencode' );
140
141
        if ( $invoice->is_recurring() ) {
142
            $paypal_args['bn'] = 'GetPaid_Subscribe_WPS_US';
143
        } else {
144
            $paypal_args['bn'] = 'GetPaid_ShoppingCart_WPS_US';
145
        }
146
147
        return add_query_arg( $paypal_args, $this->endpoint );
148
149
	}
150
151
    /**
152
	 * Get PayPal Args for passing to PP.
153
	 *
154
	 * @param  WPInv_Invoice $invoice Invoice object.
155
	 * @return array
156
	 */
157
	protected function get_paypal_args( $invoice ) {
158
159
        // Whether or not to send the line items as one item.
160
		$force_one_line_item = apply_filters( 'getpaid_paypal_force_one_line_item', true, $invoice );
161
162
		if ( $invoice->is_recurring() || ( wpinv_use_taxes() && wpinv_prices_include_tax() ) ) {
163
			$force_one_line_item = true;
164
		}
165
166
		$paypal_args = apply_filters(
167
			'getpaid_paypal_args',
168
			array_merge(
169
				$this->get_transaction_args( $invoice ),
170
				$this->get_line_item_args( $invoice, $force_one_line_item )
171
			),
172
			$invoice
173
		);
174
175
		return $this->fix_request_length( $invoice, $paypal_args );
176
    }
177
178
    /**
179
	 * Get transaction args for paypal request.
180
	 *
181
	 * @param WPInv_Invoice $invoice Invoice object.
182
	 * @return array
183
	 */
184
	protected function get_transaction_args( $invoice ) {
185
186
		return array(
187
            'cmd'           => '_cart',
188
            'business'      => wpinv_get_option( 'paypal_email', false ),
189
            'no_shipping'   => '1',
190
            'shipping'      => '0',
191
            'no_note'       => '1',
192
            'charset'       => 'utf-8',
193
            'rm'            => is_ssl() ? 2 : 1,
194
            'upload'        => 1,
195
            'currency_code' => $invoice->get_currency(), // https://developer.paypal.com/docs/nvp-soap-api/currency-codes/#paypal
196
            'return'        => esc_url_raw( $this->get_return_url( $invoice ) ),
197
            'cancel_return' => esc_url_raw( $invoice->get_checkout_payment_url() ),
198
            'notify_url'    => getpaid_limit_length( $this->notify_url, 255 ),
199
            'invoice'       => getpaid_limit_length( $invoice->get_number(), 127 ),
200
            'custom'        => $invoice->get_id(),
201
            'first_name'    => getpaid_limit_length( $invoice->get_first_name(), 32 ),
202
            'last_name'     => getpaid_limit_length( $invoice->get_last_name(), 64 ),
203
            'country'       => getpaid_limit_length( $invoice->get_country(), 2 ),
204
            'email'         => getpaid_limit_length( $invoice->get_email(), 127 ),
205
            'cbt'           => get_bloginfo( 'name' )
206
        );
207
208
    }
209
210
    /**
211
	 * Get line item args for paypal request.
212
	 *
213
	 * @param  WPInv_Invoice $invoice Invoice object.
214
	 * @param  bool     $force_one_line_item Create only one item for this invoice.
215
	 * @return array
216
	 */
217
	protected function get_line_item_args( $invoice, $force_one_line_item = false ) {
218
219
        // Maybe send invoice as a single item.
220
		if ( $force_one_line_item ) {
221
            return $this->get_line_item_args_single_item( $invoice );
222
        }
223
224
        // Send each line item individually.
225
        $line_item_args = array();
226
227
        // Prepare line items.
228
        $this->prepare_line_items( $invoice );
229
230
        // Add taxes to the cart
231
        if ( wpinv_use_taxes() && $invoice->is_taxable() ) {
232
            $line_item_args['tax_cart'] = wpinv_sanitize_amount( (float) $invoice->get_total_tax(), 2 );
0 ignored issues
show
Unused Code introduced by
The call to wpinv_sanitize_amount() has too many arguments starting with 2. ( Ignorable by Annotation )

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

232
            $line_item_args['tax_cart'] = /** @scrutinizer ignore-call */ wpinv_sanitize_amount( (float) $invoice->get_total_tax(), 2 );

This check compares calls to functions or methods with their respective definitions. If the call has more 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...
233
        }
234
235
        // Add discount.
236
        if ( $invoice->get_total_discount() > 0 ) {
237
            $line_item_args['discount_amount_cart'] = wpinv_sanitize_amount( (float) $invoice->get_total_discount(), 2 );
238
        }
239
240
		return array_merge( $line_item_args, $this->get_line_items() );
241
242
    }
243
244
    /**
245
	 * Get line item args for paypal request as a single line item.
246
	 *
247
	 * @param  WPInv_Invoice $invoice Invoice object.
248
	 * @return array
249
	 */
250
	protected function get_line_item_args_single_item( $invoice ) {
251
		$this->delete_line_items();
252
253
        $item_name = sprintf( __( 'Invoice #%s', 'invoicing' ), $invoice->get_number() );
254
		$this->add_line_item( $item_name, 1, wpinv_round_amount( (float) $invoice->get_total(), 2, true ), $invoice->get_id() );
0 ignored issues
show
Bug introduced by
It seems like wpinv_round_amount((doub...->get_total(), 2, true) can also be of type string; however, parameter $amount of GetPaid_Paypal_Gateway::add_line_item() does only seem to accept double, 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

254
		$this->add_line_item( $item_name, 1, /** @scrutinizer ignore-type */ wpinv_round_amount( (float) $invoice->get_total(), 2, true ), $invoice->get_id() );
Loading history...
255
256
		return $this->get_line_items();
257
    }
258
259
    /**
260
	 * Return all line items.
261
	 */
262
	protected function get_line_items() {
263
		return $this->line_items;
264
	}
265
266
    /**
267
	 * Remove all line items.
268
	 */
269
	protected function delete_line_items() {
270
		$this->line_items = array();
271
    }
272
273
    /**
274
	 * Prepare line items to send to paypal.
275
	 *
276
	 * @param  WPInv_Invoice $invoice Invoice object.
277
	 */
278
	protected function prepare_line_items( $invoice ) {
279
		$this->delete_line_items();
280
281
		// Items.
282
		foreach ( $invoice->get_items() as $item ) {
283
			$amount   = $item->get_price();
284
			$quantity = $invoice->get_template() == 'amount' ? 1 : $item->get_quantity();
285
			$this->add_line_item( $item->get_raw_name(), $quantity, $amount, $item->get_id() );
286
        }
287
288
        // Fees.
289
		foreach ( $invoice->get_fees() as $fee => $data ) {
290
            $this->add_line_item( $fee, 1, wpinv_sanitize_amount( $data['initial_fee'] ) );
291
        }
292
293
    }
294
295
    /**
296
	 * Add PayPal Line Item.
297
	 *
298
	 * @param  string $item_name Item name.
299
	 * @param  float    $quantity Item quantity.
300
	 * @param  float  $amount Amount.
301
	 * @param  string $item_number Item number.
302
	 */
303
	protected function add_line_item( $item_name, $quantity = 1, $amount = 0.0, $item_number = '' ) {
304
		$index = ( count( $this->line_items ) / 4 ) + 1;
305
306
		$item = apply_filters(
307
			'getpaid_paypal_line_item',
308
			array(
309
				'item_name'   => html_entity_decode( getpaid_limit_length( $item_name ? wp_strip_all_tags( $item_name ) : __( 'Item', 'invoicing' ), 127 ), ENT_NOQUOTES, 'UTF-8' ),
310
				'quantity'    => (float) $quantity,
311
				'amount'      => wpinv_sanitize_amount( (float) $amount, 2 ),
0 ignored issues
show
Unused Code introduced by
The call to wpinv_sanitize_amount() has too many arguments starting with 2. ( Ignorable by Annotation )

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

311
				'amount'      => /** @scrutinizer ignore-call */ wpinv_sanitize_amount( (float) $amount, 2 ),

This check compares calls to functions or methods with their respective definitions. If the call has more 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...
312
				'item_number' => $item_number,
313
			),
314
			$item_name,
315
			$quantity,
316
			$amount,
317
			$item_number
318
		);
319
320
		$this->line_items[ 'item_name_' . $index ]   = getpaid_limit_length( $item['item_name'], 127 );
321
        $this->line_items[ 'quantity_' . $index ]    = $item['quantity'];
322
323
        // The price or amount of the product, service, or contribution, not including shipping, handling, or tax.
324
		$this->line_items[ 'amount_' . $index ]      = $item['amount'] * $item['quantity'];
325
		$this->line_items[ 'item_number_' . $index ] = getpaid_limit_length( $item['item_number'], 127 );
326
    }
327
328
    /**
329
	 * If the default request with line items is too long, generate a new one with only one line item.
330
	 *
331
	 * https://support.microsoft.com/en-us/help/208427/maximum-url-length-is-2-083-characters-in-internet-explorer.
332
	 *
333
	 * @param WPInv_Invoice $invoice Invoice to be sent to Paypal.
334
	 * @param array    $paypal_args Arguments sent to Paypal in the request.
335
	 * @return array
336
	 */
337
	protected function fix_request_length( $invoice, $paypal_args ) {
338
		$max_paypal_length = 2083;
339
		$query_candidate   = http_build_query( $paypal_args, '', '&' );
340
341
		if ( strlen( $this->endpoint . $query_candidate ) <= $max_paypal_length ) {
342
			return $paypal_args;
343
		}
344
345
		return apply_filters(
346
			'getpaid_paypal_args',
347
			array_merge(
348
				$this->get_transaction_args( $invoice ),
349
				$this->get_line_item_args( $invoice, true )
350
			),
351
			$invoice
352
		);
353
354
    }
355
356
    /**
357
	 * Processes recurring invoices.
358
	 *
359
	 * @param  array $paypal_args PayPal args.
360
	 * @param  WPInv_Invoice    $invoice Invoice object.
361
	 */
362
	public function process_subscription( $paypal_args, $invoice ) {
363
364
        // Make sure this is a subscription.
365
        if ( ! $invoice->is_recurring() || ! $subscription = getpaid_get_invoice_subscription( $invoice ) ) {
366
            return $paypal_args;
367
        }
368
369
        // It's a subscription
370
        $paypal_args['cmd'] = '_xclick-subscriptions';
371
372
        // Subscription name.
373
        $paypal_args['item_name'] = sprintf( __( 'Invoice #%s', 'invoicing' ), $invoice->get_number() );
374
375
        // Get subscription args.
376
        $period                 = strtoupper( substr( $subscription->get_period(), 0, 1) );
377
        $interval               = (int) $subscription->get_frequency();
378
        $bill_times             = (int) $subscription->get_bill_times();
379
        $initial_amount         = (float) wpinv_sanitize_amount( $invoice->get_initial_total(), 2 );
0 ignored issues
show
Unused Code introduced by
The call to wpinv_sanitize_amount() has too many arguments starting with 2. ( Ignorable by Annotation )

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

379
        $initial_amount         = (float) /** @scrutinizer ignore-call */ wpinv_sanitize_amount( $invoice->get_initial_total(), 2 );

This check compares calls to functions or methods with their respective definitions. If the call has more 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...
380
        $recurring_amount       = (float) wpinv_sanitize_amount( $invoice->get_recurring_total(), 2 );
381
        $subscription_item      = $invoice->get_recurring( true );
382
383
        if ( $subscription_item->has_free_trial() ) {
384
385
            $paypal_args['a1'] = 0 == $initial_amount ? 0 : $initial_amount;
386
387
			// Trial period length.
388
			$paypal_args['p1'] = $subscription_item->get_trial_interval();
389
390
			// Trial period.
391
			$paypal_args['t1'] = $subscription_item->get_trial_period();
392
393
        } else if ( $initial_amount != $recurring_amount ) {
394
395
            // No trial period, but initial amount includes a sign-up fee and/or other items, so charge it as a separate period.
396
397
            if ( 1 == $bill_times ) {
398
                $param_number = 3;
399
            } else {
400
                $param_number = 1;
401
            }
402
403
            $paypal_args[ 'a' . $param_number ] = $initial_amount ? $initial_amount : 0;
404
405
            // Sign Up interval
406
            $paypal_args[ 'p' . $param_number ] = $interval;
407
408
            // Sign Up unit of duration
409
            $paypal_args[ 't' . $param_number ] = $period;
410
411
        }
412
413
        // We have a recurring payment
414
		if ( ! isset( $param_number ) || 1 == $param_number ) {
415
416
			// Subscription price
417
			$paypal_args['a3'] = $recurring_amount;
418
419
			// Subscription duration
420
			$paypal_args['p3'] = $interval;
421
422
			// Subscription period
423
			$paypal_args['t3'] = $period;
424
425
        }
426
427
        // Recurring payments
428
		if ( 1 == $bill_times || ( $initial_amount != $recurring_amount && ! $subscription_item->has_free_trial() && 2 == $bill_times ) ) {
429
430
			// Non-recurring payments
431
			$paypal_args['src'] = 0;
432
433
		} else {
434
435
			$paypal_args['src'] = 1;
436
437
			if ( $bill_times > 0 ) {
438
439
				// An initial period is being used to charge a sign-up fee
440
				if ( $initial_amount != $recurring_amount && ! $subscription_item->has_free_trial() ) {
441
					$bill_times--;
442
				}
443
444
                // Make sure it's not over the max of 52
445
                $paypal_args['srt'] = ( $bill_times <= 52 ? absint( $bill_times ) : 52 );
446
447
			}
448
        }
449
450
        // Force return URL so that order description & instructions display
451
        $paypal_args['rm'] = 2;
452
453
        // Get rid of redudant items.
454
        foreach ( array( 'item_name_1', 'quantity_1', 'amount_1', 'item_number_1' ) as $arg ) {
455
456
            if ( isset( $paypal_args[ $arg ] ) ) {
457
                unset( $paypal_args[ $arg ] );
458
            }
459
460
        }
461
462
        return apply_filters(
463
			'getpaid_paypal_subscription_args',
464
			$paypal_args,
465
			$invoice
466
        );
467
468
    }
469
470
    /**
471
	 * Processes ipns and marks payments as complete.
472
	 *
473
	 * @return void
474
	 */
475
	public function verify_ipn() {
476
        new GetPaid_Paypal_Gateway_IPN_Handler( $this );
477
    }
478
479
    /**
480
     * Returns a sandbox notice.
481
     */
482
    public function sandbox_notice() {
483
484
        return sprintf(
485
			__( 'SANDBOX ENABLED. You can use sandbox testing accounts only. See the %sPayPal Sandbox Testing Guide%s for more details.', 'invoicing' ),
486
			'<a href="https://developer.paypal.com/docs/classic/lifecycle/ug_sandbox/">',
487
			'</a>'
488
		);
489
490
    }
491
492
	/**
493
	 * Filters the gateway settings.
494
	 *
495
	 * @param array $admin_settings
496
	 */
497
	public function admin_settings( $admin_settings ) {
498
499
        $currencies = sprintf(
500
            __( 'Supported Currencies: %s', 'invoicing' ),
501
            implode( ', ', $this->currencies )
502
        );
503
504
        $admin_settings['paypal_active']['desc'] .= " ($currencies)";
505
        $admin_settings['paypal_desc']['std']     = __( 'Pay via PayPal: you can pay with your credit card if you don\'t have a PayPal account.', 'invoicing' );
506
		/*
507
		// Access tokens.
508
        $live_account    = wpinv_get_option( 'paypal_live_access_token' );
509
        $sandbox_account = wpinv_get_option( 'paypal_test_access_token' );
510
511
		$admin_settings['paypal_connect'] = array(
512
			'type'       => 'raw_html',
513
			'id'         => 'paypal_connect',
514
			'name'       => __( 'Connect to PayPal', 'invoicing' ),
515
			'desc'       => sprintf(
516
				'<div class="wpinv-paypal-connect-live"><a class="button button-primary" href="%s">%s</a><br><strong style="color: green">%s</strong></div><div class="wpinv-paypal-connect-sandbox"><a class="button button-primary" href="%s">%s</a><br><strong style="color: green">%s</strong></div>%s',
517
				esc_url( self::get_connect_url( false ) ),
518
				__( 'Connect to PayPal', 'invoicing' ),
519
				__( 'Connected', 'invoicing' ),
520
				esc_url( self::get_connect_url( true ) ),
521
				__( 'Connect to PayPal Sandox', 'invoicing' ),
522
				__( 'Connected', 'invoicing' ),
523
				$this->get_js()
524
			),
525
		);
526
		
527
		$admin_settings['disable_paypal_connect'] = array(
528
			'type'       => 'checkbox',
529
			'id'         => 'disable_paypal_connect',
530
			'name'       => __( 'Manual Mode', 'invoicing' ),
531
			'desc'       => __( 'Manually enter your credentials', 'invoicing' ),
532
			'std'        => false,
533
		);
534
		*/
535
        $admin_settings['paypal_email'] = array(
536
            'type'  => 'text',
537
			'class' => 'live-auth-data',
538
            'id'    => 'paypal_email',
539
            'name'  => __( 'Live Email Address', 'invoicing' ),
540
            'desc'  => __( 'The email address of your PayPal account.', 'invoicing' ),
541
        );
542
		/*
543
		$admin_settings['paypal_merchant_id'] = array(
544
            'type'  => 'text',
545
			'class' => 'live-auth-data',
546
            'id'    => 'paypal_merchant_id',
547
            'name'  => __( 'Live Merchant ID', 'invoicing' ),
548
        );
549
550
		$admin_settings['paypal_client_id'] = array(
551
            'type'  => 'text',
552
			'class' => 'live-auth-data',
553
            'id'    => 'paypal_client_id',
554
            'name'  => __( 'Live Client ID', 'invoicing' ),
555
        );
556
557
		$admin_settings['paypal_client_secret'] = array(
558
            'type'  => 'text',
559
			'class' => 'live-auth-data',
560
            'id'    => 'paypal_client_secret',
561
            'name'  => __( 'Live Client Secret', 'invoicing' ),
562
        );
563
564
		$admin_settings['paypal_sandbox_email'] = array(
565
            'type'  => 'text',
566
			'class' => 'sandbox-auth-data',
567
            'id'    => 'paypal_sandbox_email',
568
            'name'  => __( 'Sandbox Email Address', 'invoicing' ),
569
            'desc'  => __( 'The email address of your sandbox PayPal account.', 'invoicing' ),
570
			'std'   => wpinv_get_option( 'paypal_email', '' ),
571
        );
572
		
573
		$admin_settings['paypal_sandbox_merchant_id'] = array(
574
            'type'  => 'text',
575
			'class' => 'sandbox-auth-data',
576
            'id'    => 'paypal_sandbox_merchant_id',
577
            'name'  => __( 'Sandbox Merchant ID', 'invoicing' ),
578
        );
579
580
		$admin_settings['paypal_sandbox_client_id'] = array(
581
            'type'  => 'text',
582
			'class' => 'sandbox-auth-data',
583
            'id'    => 'paypal_sandbox_client_id',
584
            'name'  => __( 'Sandbox Client ID', 'invoicing' ),
585
        );
586
587
		$admin_settings['paypal_sandbox_client_secret'] = array(
588
            'type'  => 'text',
589
			'class' => 'sandbox-auth-data',
590
            'id'    => 'paypal_sandbox_client_secret',
591
            'name'  => __( 'Sandbox Client Secret', 'invoicing' ),
592
        );
593
		*/
594
        $admin_settings['paypal_ipn_url'] = array(
595
            'type'     => 'ipn_url',
596
            'id'       => 'paypal_ipn_url',
597
            'name'     => __( 'IPN Url', 'invoicing' ),
598
            'std'      => $this->notify_url,
599
            'desc'     => __( "If you've not enabled IPNs in your paypal account, use the above URL to enable them.", 'invoicing' ) . ' <a href="https://developer.paypal.com/docs/api-basics/notifications/ipn/"><em>' . __( 'Learn more.', 'invoicing' ) . '</em></a>',
600
            'readonly' => true,
601
        );
602
603
		return $admin_settings;
604
	}
605
606
	/**
607
	 * Retrieves the PayPal connect URL when using the setup wizzard.
608
	 *
609
	 *
610
     * @param array $data
611
     * @return string
612
	 */
613
	public static function maybe_get_connect_url( $url = '', $data ) {
614
		return self::get_connect_url( false, urldecode( $data['redirect'] ) );
615
	}
616
617
	/**
618
	 * Retrieves the PayPal connect URL.
619
	 *
620
	 *
621
     * @param bool $is_sandbox
622
	 * @param string $redirect
623
     * @return string
624
	 */
625
	public static function get_connect_url( $is_sandbox, $redirect = '' ) {
626
627
        $redirect_url = add_query_arg(
628
            array(
629
                'getpaid-admin-action' => 'connect_paypal',
630
                'page'                 => 'wpinv-settings',
631
                'live_mode'            => (int) empty( $is_sandbox ),
632
                'tab'                  => 'gateways',
633
                'section'              => 'paypal',
634
                'getpaid-nonce'        => wp_create_nonce( 'getpaid-nonce' ),
635
				'redirect'             => urlencode( $redirect ),
636
            ),
637
            admin_url( 'admin.php' )
638
        );
639
640
        return add_query_arg(
641
            array(
642
                'live_mode'    => (int) empty( $is_sandbox ),
643
                'redirect_url' => urlencode( str_replace( '&amp;', '&', $redirect_url ) )
644
            ),
645
            'https://ayecode.io/oauth/paypal'
646
        );
647
648
    }
649
650
	/**
651
	 * Generates settings page js.
652
	 *
653
     * @return void
654
	 */
655
	public static function get_js() { return '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '' returns the type string which is incompatible with the documented return type void.
Loading history...
656
        ob_start();
0 ignored issues
show
Unused Code introduced by
ob_start() is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
657
        ?>
658
            <script>
659
                jQuery(document).ready(function() {
660
661
					var areAllInputsFilled = function ( el ) {
662
						return jQuery(el).filter(function() {
663
							return jQuery.trim( jQuery(this).val() ).length == 0
664
						}).length == 0;
665
					}
666
667
                    jQuery( '#wpinv-settings-paypal_sandbox' ).on ( 'change', function( e ) {
668
669
						var showing_manual = jQuery( '#wpinv-settings-disable_paypal_connect' ).is(':checked');
670
671
						if ( showing_manual ) {
672
							jQuery ( '.wpinv-paypal-connect-live' ).closest( 'tr' ).hide()
673
							jQuery ( 'tr.sandbox-auth-data' ).toggle( this.checked )
674
							jQuery ( 'tr.live-auth-data' ).toggle( ! this.checked )
675
						} else {
676
							jQuery ( '.wpinv-paypal-connect-live' ).closest( 'tr' ).show()
677
							jQuery ( 'tr.sandbox-auth-data, tr.live-auth-data' ).hide()
678
						}
679
680
						jQuery( '.wpinv-paypal-connect-live' ).toggle( ! this.checked )
681
						jQuery( '.wpinv-paypal-connect-sandbox' ).toggle( this.checked )
682
683
						jQuery( '.wpinv-paypal-connect-live strong' ).toggle( areAllInputsFilled( 'input.live-auth-data' ) )
684
						jQuery( '.wpinv-paypal-connect-sandbox strong' ).toggle( areAllInputsFilled( 'input.sandbox-auth-data' ) )
685
686
                    })
687
688
                    jQuery( '#wpinv-settings-disable_paypal_connect' ).on ( 'change', function( e ) {
689
                        jQuery( '#wpinv-settings-paypal_sandbox' ).trigger( 'change' )
690
                    });
691
692
                    // Set initial state.
693
                    jQuery( '#wpinv-settings-disable_paypal_connect' ).trigger( 'change' )
694
695
                });
696
            </script>
697
        <?php
698
        return ob_get_clean();
699
    }
700
701
	/**
702
	 * Connects to PayPal.
703
	 *
704
	 * @param array $data Connection data.
705
	 * @return void
706
	 */
707
	public function connect_paypal( $data ) {
708
709
		$sandbox      = $this->is_sandbox();
710
		$data         = wp_unslash( $data );
711
		$access_token = empty( $data['access_token'] ) ? '' : sanitize_text_field( $data['access_token'] );
712
713
		if ( isset( $data['live_mode'] ) ) {
714
			$sandbox = empty( $data['live_mode'] );
715
		}
716
717
		wpinv_update_option( 'paypal_sandbox', (int) $sandbox );
718
		wpinv_update_option( 'paypal_active', 1 );
719
720
		if ( ! empty( $data['error_description'] ) ) {
721
			getpaid_admin()->show_error( wp_kses_post( urldecode( $data['error_description'] ) ) );
722
		} else {
723
724
			// Retrieve the user info.
725
			$user_info = wp_remote_get(
726
				! $sandbox ? 'https://api-m.paypal.com/v1/identity/oauth2/userinfo?schema=paypalv1.1' : 'https://api-m.sandbox.paypal.com/v1/identity/oauth2/userinfo?schema=paypalv1.1',
727
				array(
728
729
					'headers' => array(
730
						'Authorization' => 'Bearer ' . $access_token,
731
						'Content-type'  => 'application/json',
732
					)
733
734
				)
735
			);
736
737
			if ( is_wp_error( $user_info ) ) {
738
				getpaid_admin()->show_error( wp_kses_post( $user_info->get_error_message() ) );
739
			} else {
740
741
				// Create application.
742
				$user_info = json_decode( wp_remote_retrieve_body( $user_info ) );
743
				$app       = wp_remote_post(
744
					! $sandbox ? 'https://api-m.paypal.com/v1/identity/applications' : 'https://api-m.sandbox.paypal.com/v1/identity/applications',
745
					array(
746
747
						'body'    => array(
748
							'application_type' => 'web',
749
							'redirect_uris'    => array(
750
								add_query_arg( 'getpaid_oauth', 'paypal', home_url() ),
751
							),
752
							'client_name'      => 'GetPaid',
753
							'contacts'         => array( $user_info->emails[0]->value ),
754
							'payer_id'         => $user_info->payer_id,
755
							'migrated_app'     => '',
756
						),
757
						'headers' => array(
758
							'Authorization' => 'Bearer ' . $access_token,
759
							'Content-type'  => 'application/json',
760
						)
761
762
					)
763
				);
764
765
				if ( is_wp_error( $app ) ) {
766
					getpaid_admin()->show_error( wp_kses_post( $app->get_error_message() ) );
767
				} else {
768
769
					$app = json_decode( wp_remote_retrieve_body( $app ) );
770
					wpinv_error_log( $app );
771
					if ( $sandbox ) {
772
						wpinv_update_option( 'paypal_sandbox_email', sanitize_email( $user_info->emails[0]->value ) );
773
						wpinv_update_option( 'paypal_sandbox_merchant_id', '' );
774
						wpinv_update_option( 'paypal_sandbox_client_id', sanitize_text_field( '' ) );
775
						wpinv_update_option( 'paypal_sandbox_client_secret', sanitize_text_field( '' ) );
776
						wpinv_update_option( 'paypal_sandbox_client_secret_expires_at', sanitize_text_field( '' ) );
777
						wpinv_update_option( 'paypal_sandbox_refresh_token', sanitize_text_field( urldecode( $data['refresh_token'] ) ) );
778
						set_transient( 'getpaid_paypal_sandbox_access_token', sanitize_text_field( urldecode( $data['access_token'] ) ), (int) $data['expires_in'] );
779
						getpaid_admin()->show_success( __( 'Successfully connected your PayPal sandbox account', 'invoicing' ) );
780
					} else {
781
						wpinv_update_option( 'paypal_email', sanitize_email( $user_info->emails[0]->value ) );
782
						wpinv_update_option( 'paypal_merchant_id', '' );
783
						wpinv_update_option( 'paypal_client_id', sanitize_text_field( '' ) );
784
						wpinv_update_option( 'paypal_client_secret', sanitize_text_field( '' ) );
785
						wpinv_update_option( 'paypal_client_secret_expires_at', sanitize_text_field( '' ) );
786
						wpinv_update_option( 'paypal_refresh_token', sanitize_text_field( urldecode( $data['refresh_token'] ) ) );
787
						set_transient( 'getpaid_paypal_access_token', sanitize_text_field( urldecode( $data['access_token'] ) ), (int) $data['expires_in'] );
788
						getpaid_admin()->show_success( __( 'Successfully connected your PayPal account', 'invoicing' ) );
789
					}
790
791
				}
792
793
			}
794
795
		}
796
797
		$redirect = empty( $data['redirect'] ) ? admin_url( 'admin.php?page=wpinv-settings&tab=gateways&section=paypal' ) : urldecode( $data['redirect'] );
798
799
		if ( isset( $data['step'] ) ) {
800
			$redirect = add_query_arg( 'step', $data['step'], $redirect );
801
		}
802
		wp_redirect( $redirect );
803
		exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
804
	}
805
806
}
807