Passed
Push — master ( f411ba...4d2fb8 )
by Brian
05:15
created

GetPaid_Paypal_Gateway::admin_settings()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 81
Code Lines 57

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 1 Features 1
Metric Value
cc 1
eloc 57
c 5
b 1
f 1
nc 1
nop 1
dl 0
loc 81
rs 8.9381

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( 'wpinv_subscription_cancel_url', array( $this, 'filter_cancel_subscription_url' ), 10, 2 );
89
		add_filter( 'getpaid_paypal_args', array( $this, 'process_subscription' ), 10, 2 );
90
        add_filter( 'getpaid_paypal_sandbox_notice', array( $this, 'sandbox_notice' ) );
91
		add_filter( 'getpaid_get_paypal_connect_url', array( $this, 'maybe_get_connect_url' ), 10, 2 );
92
		add_action( 'getpaid_authenticated_admin_action_connect_paypal', array( $this, 'connect_paypal' ) );
93
		add_action( 'wpinv_paypal_connect', array( $this, 'display_connect_buttons' ) );
94
		parent::__construct();
95
    }
96
97
    /**
98
	 * Process Payment.
99
	 *
100
	 *
101
	 * @param WPInv_Invoice $invoice Invoice.
102
	 * @param array $submission_data Posted checkout fields.
103
	 * @param GetPaid_Payment_Form_Submission $submission Checkout submission.
104
	 * @return array
105
	 */
106
	public function process_payment( $invoice, $submission_data, $submission ) {
107
108
        // Get redirect url.
109
        $paypal_redirect = $this->get_request_url( $invoice );
110
111
        // Add a note about the request url.
112
        $invoice->add_note(
113
            sprintf(
114
                __( 'Redirecting to PayPal: %s', 'invoicing' ),
115
                esc_url( $paypal_redirect )
116
            ),
117
            false,
118
            false,
119
            true
120
        );
121
122
        // Redirect to PayPal
123
        wp_redirect( $paypal_redirect );
124
        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...
125
126
    }
127
128
    /**
129
	 * Get the PayPal request URL for an invoice.
130
	 *
131
	 * @param  WPInv_Invoice $invoice Invoice object.
132
	 * @return string
133
	 */
134
	public function get_request_url( $invoice ) {
135
136
        // Endpoint for this request
137
		$this->endpoint    = $this->is_sandbox( $invoice ) ? 'https://www.sandbox.paypal.com/cgi-bin/webscr?test_ipn=1&' : 'https://www.paypal.com/cgi-bin/webscr?';
138
139
        // Retrieve paypal args.
140
        $paypal_args       = map_deep( $this->get_paypal_args( $invoice ), 'urlencode' );
141
142
        if ( $invoice->is_recurring() ) {
143
            $paypal_args['bn'] = 'GetPaid_Subscribe_WPS_US';
144
        } else {
145
            $paypal_args['bn'] = 'GetPaid_ShoppingCart_WPS_US';
146
        }
147
148
        return add_query_arg( $paypal_args, $this->endpoint );
149
150
	}
151
152
    /**
153
	 * Get PayPal Args for passing to PP.
154
	 *
155
	 * @param  WPInv_Invoice $invoice Invoice object.
156
	 * @return array
157
	 */
158
	protected function get_paypal_args( $invoice ) {
159
160
        // Whether or not to send the line items as one item.
161
		$force_one_line_item = apply_filters( 'getpaid_paypal_force_one_line_item', true, $invoice );
162
163
		if ( $invoice->is_recurring() || ( wpinv_use_taxes() && wpinv_prices_include_tax() ) ) {
164
			$force_one_line_item = true;
165
		}
166
167
		$paypal_args = apply_filters(
168
			'getpaid_paypal_args',
169
			array_merge(
170
				$this->get_transaction_args( $invoice ),
171
				$this->get_line_item_args( $invoice, $force_one_line_item )
172
			),
173
			$invoice
174
		);
175
176
		return $this->fix_request_length( $invoice, $paypal_args );
177
    }
178
179
    /**
180
	 * Get transaction args for paypal request.
181
	 *
182
	 * @param WPInv_Invoice $invoice Invoice object.
183
	 * @return array
184
	 */
185
	protected function get_transaction_args( $invoice ) {
186
187
		$email = $this->is_sandbox( $invoice ) ? wpinv_get_option( 'paypal_sandbox_email', wpinv_get_option( 'paypal_email', '' ) ) : wpinv_get_option( 'paypal_email', '' );
188
		return array(
189
            'cmd'           => '_cart',
190
            'business'      => $email,
191
            'no_shipping'   => '1',
192
            'shipping'      => '0',
193
            'no_note'       => '1',
194
            'charset'       => 'utf-8',
195
            'rm'            => is_ssl() ? 2 : 1,
196
            'upload'        => 1,
197
            'currency_code' => $invoice->get_currency(), // https://developer.paypal.com/docs/nvp-soap-api/currency-codes/#paypal
198
            'return'        => esc_url_raw( $this->get_return_url( $invoice ) ),
199
            'cancel_return' => esc_url_raw( $invoice->get_checkout_payment_url() ),
200
            'notify_url'    => getpaid_limit_length( $this->notify_url, 255 ),
201
            'invoice'       => getpaid_limit_length( $invoice->get_number(), 127 ),
202
            'custom'        => $invoice->get_id(),
203
            'first_name'    => getpaid_limit_length( $invoice->get_first_name(), 32 ),
204
            'last_name'     => getpaid_limit_length( $invoice->get_last_name(), 64 ),
205
            'country'       => getpaid_limit_length( $invoice->get_country(), 2 ),
206
            'email'         => getpaid_limit_length( $invoice->get_email(), 127 ),
207
            'cbt'           => get_bloginfo( 'name' ),
208
        );
209
210
    }
211
212
    /**
213
	 * Get line item args for paypal request.
214
	 *
215
	 * @param  WPInv_Invoice $invoice Invoice object.
216
	 * @param  bool     $force_one_line_item Create only one item for this invoice.
217
	 * @return array
218
	 */
219
	protected function get_line_item_args( $invoice, $force_one_line_item = false ) {
220
221
        // Maybe send invoice as a single item.
222
		if ( $force_one_line_item ) {
223
            return $this->get_line_item_args_single_item( $invoice );
224
        }
225
226
        // Send each line item individually.
227
        $line_item_args = array();
228
229
        // Prepare line items.
230
        $this->prepare_line_items( $invoice );
231
232
        // Add taxes to the cart
233
        if ( wpinv_use_taxes() && $invoice->is_taxable() ) {
234
            $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

234
            $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...
235
        }
236
237
        // Add discount.
238
        if ( $invoice->get_total_discount() > 0 ) {
239
            $line_item_args['discount_amount_cart'] = wpinv_sanitize_amount( (float) $invoice->get_total_discount(), 2 );
240
        }
241
242
		return array_merge( $line_item_args, $this->get_line_items() );
243
244
    }
245
246
    /**
247
	 * Get line item args for paypal request as a single line item.
248
	 *
249
	 * @param  WPInv_Invoice $invoice Invoice object.
250
	 * @return array
251
	 */
252
	protected function get_line_item_args_single_item( $invoice ) {
253
		$this->delete_line_items();
254
255
        $item_name = sprintf( __( 'Invoice #%s', 'invoicing' ), $invoice->get_number() );
256
		$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

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

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

381
        $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...
382
        $recurring_amount       = (float) wpinv_sanitize_amount( $invoice->get_recurring_total(), 2 );
383
        $subscription_item      = $invoice->get_recurring( true );
384
385
		// Convert 365 days to 1 year.
386
		if ( 'D' == $period && 365 == $interval ) {
387
			$period = 'Y';
388
			$interval = 1;
389
		}
390
391
        if ( $subscription_item->has_free_trial() ) {
392
393
            $paypal_args['a1'] = 0 == $initial_amount ? 0 : $initial_amount;
394
395
			// Trial period length.
396
			$paypal_args['p1'] = $subscription_item->get_trial_interval();
397
398
			// Trial period.
399
			$paypal_args['t1'] = $subscription_item->get_trial_period();
400
401
        } elseif ( $initial_amount != $recurring_amount ) {
402
403
            // No trial period, but initial amount includes a sign-up fee and/or other items, so charge it as a separate period.
404
405
            if ( 1 == $bill_times ) {
406
                $param_number = 3;
407
            } else {
408
                $param_number = 1;
409
            }
410
411
            $paypal_args[ 'a' . $param_number ] = $initial_amount ? $initial_amount : 0;
412
413
            // Sign Up interval
414
            $paypal_args[ 'p' . $param_number ] = $interval;
415
416
            // Sign Up unit of duration
417
            $paypal_args[ 't' . $param_number ] = $period;
418
419
        }
420
421
        // We have a recurring payment
422
		if ( ! isset( $param_number ) || 1 == $param_number ) {
423
424
			// Subscription price
425
			$paypal_args['a3'] = $recurring_amount;
426
427
			// Subscription duration
428
			$paypal_args['p3'] = $interval;
429
430
			// Subscription period
431
			$paypal_args['t3'] = $period;
432
433
        }
434
435
        // Recurring payments
436
		if ( 1 == $bill_times || ( $initial_amount != $recurring_amount && ! $subscription_item->has_free_trial() && 2 == $bill_times ) ) {
437
438
			// Non-recurring payments
439
			$paypal_args['src'] = 0;
440
441
		} else {
442
443
			$paypal_args['src'] = 1;
444
445
			if ( $bill_times > 0 ) {
446
447
				// An initial period is being used to charge a sign-up fee
448
				if ( $initial_amount != $recurring_amount && ! $subscription_item->has_free_trial() ) {
449
					$bill_times--;
450
				}
451
452
                // Make sure it's not over the max of 52
453
                $paypal_args['srt'] = ( $bill_times <= 52 ? absint( $bill_times ) : 52 );
454
455
			}
456
        }
457
458
        // Force return URL so that order description & instructions display
459
        $paypal_args['rm'] = 2;
460
461
        // Get rid of redudant items.
462
        foreach ( array( 'item_name_1', 'quantity_1', 'amount_1', 'item_number_1' ) as $arg ) {
463
464
            if ( isset( $paypal_args[ $arg ] ) ) {
465
                unset( $paypal_args[ $arg ] );
466
            }
467
}
468
469
        return apply_filters(
470
			'getpaid_paypal_subscription_args',
471
			$paypal_args,
472
			$invoice
473
        );
474
475
    }
476
477
    /**
478
	 * Processes ipns and marks payments as complete.
479
	 *
480
	 * @return void
481
	 */
482
	public function verify_ipn() {
483
        new GetPaid_Paypal_Gateway_IPN_Handler( $this );
484
    }
485
486
    /**
487
     * Returns a sandbox notice.
488
     */
489
    public function sandbox_notice() {
490
491
        return sprintf(
492
			__( 'SANDBOX ENABLED. You can use sandbox testing accounts only. See the %1$sPayPal Sandbox Testing Guide%2$s for more details.', 'invoicing' ),
493
			'<a href="https://developer.paypal.com/docs/classic/lifecycle/ug_sandbox/">',
494
			'</a>'
495
		);
496
497
    }
498
499
	/**
500
	 * Filters the gateway settings.
501
	 *
502
	 * @param array $admin_settings
503
	 */
504
	public function admin_settings( $admin_settings ) {
505
506
        $currencies = sprintf(
507
            __( 'Supported Currencies: %s', 'invoicing' ),
508
            implode( ', ', $this->currencies )
509
        );
510
511
        $admin_settings['paypal_active']['desc'] .= " ($currencies)";
512
        $admin_settings['paypal_desc']['std']     = __( 'Pay via PayPal: you can pay with your credit card if you don\'t have a PayPal account.', 'invoicing' );
513
514
		// Access tokens.
515
		$live_email      = wpinv_get_option( 'paypal_email' );
0 ignored issues
show
Unused Code introduced by
The assignment to $live_email is dead and can be removed.
Loading history...
516
		$sandbox_email   = wpinv_get_option( 'paypal_sandbox_email' );
0 ignored issues
show
Unused Code introduced by
The assignment to $sandbox_email is dead and can be removed.
Loading history...
517
518
		$admin_settings['paypal_connect'] = array(
519
			'type' => 'hook',
520
			'id'   => 'paypal_connect',
521
			'name' => __( 'Connect to PayPal', 'invoicing' ),
522
		);
523
524
        $admin_settings['paypal_email'] = array(
525
            'type'  => 'text',
526
			'class' => 'live-auth-data',
527
            'id'    => 'paypal_email',
528
            'name'  => __( 'Live Email Address', 'invoicing' ),
529
            'desc'  => __( 'The email address of your PayPal account.', 'invoicing' ),
530
        );
531
532
		$admin_settings['paypal_sandbox_email'] = array(
533
            'type'  => 'text',
534
			'class' => 'sandbox-auth-data',
535
            'id'    => 'paypal_sandbox_email',
536
            'name'  => __( 'Sandbox Email Address', 'invoicing' ),
537
            'desc'  => __( 'The email address of your sandbox PayPal account.', 'invoicing' ),
538
			'std'   => wpinv_get_option( 'paypal_email', '' ),
539
        );
540
541
		// Client ID and secret.
542
		$admin_settings['paypal_client_id'] = array(
543
			'type'  => 'text',
544
			'class' => 'live-auth-data',
545
			'id'    => 'paypal_client_id',
546
			'name'  => __( 'Live Client ID', 'invoicing' ),
547
			'desc'  => __( 'The client ID of your PayPal account. You can retrieve this from your PayPal developer account.', 'invoicing' ),
548
		);
549
550
		$admin_settings['paypal_sandbox_client_id'] = array(
551
			'type'  => 'text',
552
			'class' => 'sandbox-auth-data',
553
			'id'    => 'paypal_sandbox_client_id',
554
			'name'  => __( 'Sandbox Client ID', 'invoicing' ),
555
			'desc'  => __( 'The client ID of your sandbox PayPal account. You can retrieve this from your PayPal developer account.', 'invoicing' ),
556
			'std'   => wpinv_get_option( 'paypal_client_id', '' ),
557
		);
558
559
		$admin_settings['paypal_secret'] = array(
560
			'type'  => 'text',
561
			'class' => 'live-auth-data',
562
			'id'    => 'paypal_secret',
563
			'name'  => __( 'Live Secret', 'invoicing' ),
564
			'desc'  => __( 'The secret of your PayPal account. You can retrieve this from your PayPal developer account.', 'invoicing' ),
565
		);
566
567
		$admin_settings['paypal_sandbox_secret'] = array(
568
			'type'  => 'text',
569
			'class' => 'sandbox-auth-data',
570
			'id'    => 'paypal_sandbox_secret',
571
			'name'  => __( 'Sandbox Secret', 'invoicing' ),
572
			'desc'  => __( 'The secret of your sandbox PayPal account. You can retrieve this from your PayPal developer account.', 'invoicing' ),
573
		);
574
575
        $admin_settings['paypal_ipn_url'] = array(
576
            'type'     => 'ipn_url',
577
            'id'       => 'paypal_ipn_url',
578
            'name'     => __( 'IPN Url', 'invoicing' ),
579
            'std'      => $this->notify_url,
580
            '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>',
581
            'readonly' => true,
582
        );
583
584
		return $admin_settings;
585
	}
586
587
	/**
588
	 * Retrieves the URL to cancel a subscription.
589
	 *
590
	 * @param string $url
591
	 * @param WPInv_Subscription $subscription
592
	 */
593
	public function filter_cancel_subscription_url( $url, $subscription ) {
594
595
		if ( $this->id !== $subscription->get_gateway() ) {
596
			return $url;
597
		}
598
599
		// Get the PayPal profile ID.
600
		$profile_id = $subscription->get_profile_id();
601
602
		// Bail if no profile ID.
603
		if ( empty( $profile_id ) ) {
604
			return $url;
605
		}
606
607
		$cancel_url = 'https://www.paypal.com/myaccount/autopay/connect/%s/cancel';
608
		if ( $this->is_sandbox( $subscription->get_parent_payment() ) ) {
609
			$cancel_url = 'https://www.sandbox.paypal.com/myaccount/autopay/connect/%s/cancel';
610
		}
611
612
		return sprintf( $cancel_url, $profile_id );
613
	}
614
615
	/**
616
	 * Retrieves the PayPal connect URL when using the setup wizzard.
617
	 *
618
	 *
619
     * @param array $data
620
     * @return string
621
	 */
622
	public static function maybe_get_connect_url( $url = '', $data = array() ) {
623
		return self::get_connect_url( false, urldecode( $data['redirect'] ) );
624
	}
625
626
	/**
627
	 * Retrieves the PayPal connect URL.
628
	 *
629
	 *
630
     * @param bool $is_sandbox
631
	 * @param string $redirect
632
     * @return string
633
	 */
634
	public static function get_connect_url( $is_sandbox, $redirect = '' ) {
635
636
        $redirect_url = add_query_arg(
637
            array(
638
                'getpaid-admin-action' => 'connect_paypal',
639
                'page'                 => 'wpinv-settings',
640
                'live_mode'            => (int) empty( $is_sandbox ),
641
                'tab'                  => 'gateways',
642
                'section'              => 'paypal',
643
                'getpaid-nonce'        => wp_create_nonce( 'getpaid-nonce' ),
644
				'redirect'             => urlencode( $redirect ),
645
            ),
646
            admin_url( 'admin.php' )
647
        );
648
649
        return add_query_arg(
650
            array(
651
                'live_mode'    => (int) empty( $is_sandbox ),
652
                'redirect_url' => urlencode( str_replace( '&amp;', '&', $redirect_url ) ),
653
            ),
654
            'https://ayecode.io/oauth/paypal'
655
        );
656
657
    }
658
659
	/**
660
	 * Generates settings page js.
661
	 *
662
     * @return void
663
	 */
664
	public static function display_connect_buttons() {
665
666
        ?>
667
			<div class="wpinv-paypal-connect-live">
668
				<a class="button button-primary" href="<?php echo esc_url( self::get_connect_url( false ) ); ?>"><?php esc_html_e( 'Connect to PayPal', 'invoicing' ); ?></a>
669
			</div>
670
			<div class="wpinv-paypal-connect-sandbox">
671
				<a class="button button-primary" href="<?php echo esc_url( self::get_connect_url( true ) ); ?>"><?php esc_html_e( 'Connect to PayPal Sandbox', 'invoicing' ); ?></a>
672
			</div>
673
674
            <script>
675
                jQuery(document).ready(function() {
676
677
                    jQuery( '#wpinv-settings-paypal_sandbox' ).on ( 'change', function( e ) {
678
679
						jQuery( '.wpinv-paypal-connect-live, .live-auth-data' ).toggle( ! this.checked )
680
						jQuery( '.wpinv-paypal-connect-sandbox, .sandbox-auth-data' ).toggle( this.checked )
681
682
						if ( this.checked ) {
683
684
							if ( jQuery('#wpinv-settings-paypal_sandbox_email').val().length > 0 ) {
685
								jQuery('.wpinv-paypal-connect-sandbox').closest('tr').hide()
686
							} else {
687
								jQuery('.wpinv-paypal-connect-sandbox').closest('tr').show()
688
							}
689
						} else {
690
							if ( jQuery('#wpinv-settings-paypal_email').val().length > 0 ) {
691
								jQuery('.wpinv-paypal-connect-live').closest('tr').hide()
692
							} else {
693
								jQuery('.wpinv-paypal-connect-live').closest('tr').show()
694
							}
695
						}
696
                    })
697
698
                    // Set initial state.
699
                    jQuery( '#wpinv-settings-paypal_sandbox' ).trigger( 'change' )
700
701
                });
702
            </script>
703
        <?php
704
    }
705
706
	/**
707
	 * Connects to PayPal.
708
	 *
709
	 * @param array $data Connection data.
710
	 * @return void
711
	 */
712
	public function connect_paypal( $data ) {
713
714
		$sandbox      = $this->is_sandbox();
715
		$data         = wp_unslash( $data );
716
		$access_token = empty( $data['access_token'] ) ? '' : sanitize_text_field( $data['access_token'] );
717
718
		if ( isset( $data['live_mode'] ) ) {
719
			$sandbox = empty( $data['live_mode'] );
720
		}
721
722
		wpinv_update_option( 'paypal_sandbox', (int) $sandbox );
723
		wpinv_update_option( 'paypal_active', 1 );
724
725
		if ( ! empty( $data['error_description'] ) ) {
726
			getpaid_admin()->show_error( wp_kses_post( urldecode( $data['error_description'] ) ) );
727
		} else {
728
729
			// Retrieve the user info.
730
			$user_info = wp_remote_get(
731
				! $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',
732
				array(
733
734
					'headers' => array(
735
						'Authorization' => 'Bearer ' . $access_token,
736
						'Content-type'  => 'application/json',
737
					),
738
739
				)
740
			);
741
742
			if ( is_wp_error( $user_info ) ) {
743
				getpaid_admin()->show_error( wp_kses_post( $user_info->get_error_message() ) );
744
			} else {
745
746
				// Create application.
747
				$user_info = json_decode( wp_remote_retrieve_body( $user_info ) );
748
749
				if ( $sandbox ) {
750
					wpinv_update_option( 'paypal_sandbox_email', sanitize_email( $user_info->emails[0]->value ) );
751
					wpinv_update_option( 'paypal_sandbox_refresh_token', sanitize_text_field( urldecode( $data['refresh_token'] ) ) );
752
					set_transient( 'getpaid_paypal_sandbox_access_token', sanitize_text_field( urldecode( $data['access_token'] ) ), (int) $data['expires_in'] );
753
					getpaid_admin()->show_success( __( 'Successfully connected your PayPal sandbox account', 'invoicing' ) );
754
				} else {
755
					wpinv_update_option( 'paypal_email', sanitize_email( $user_info->emails[0]->value ) );
756
					wpinv_update_option( 'paypal_refresh_token', sanitize_text_field( urldecode( $data['refresh_token'] ) ) );
757
					set_transient( 'getpaid_paypal_access_token', sanitize_text_field( urldecode( $data['access_token'] ) ), (int) $data['expires_in'] );
758
					getpaid_admin()->show_success( __( 'Successfully connected your PayPal account', 'invoicing' ) );
759
				}
760
}
761
}
762
763
		$redirect = empty( $data['redirect'] ) ? admin_url( 'admin.php?page=wpinv-settings&tab=gateways&section=paypal' ) : urldecode( $data['redirect'] );
764
765
		if ( isset( $data['step'] ) ) {
766
			$redirect = add_query_arg( 'step', $data['step'], $redirect );
767
		}
768
		wp_redirect( $redirect );
769
		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...
770
	}
771
772
}
773