Passed
Push — master ( 797927...011c37 )
by Stiofan
06:37
created

paypal.php ➔ wpinv_get_paypal_subscription()   C

Complexity

Conditions 7
Paths 5

Size

Total Lines 27
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 15
nc 5
nop 1
dl 0
loc 27
rs 6.7272
c 0
b 0
f 0
1
<?php
2
// Exit if accessed directly
3
if ( ! defined( 'ABSPATH' ) ) exit;
4
5
add_action( 'wpinv_paypal_cc_form', '__return_false' );
6
add_filter( 'wpinv_paypal_support_subscription', '__return_true' );
7
8
function wpinv_process_paypal_payment( $purchase_data ) {
9
    if( ! wp_verify_nonce( $purchase_data['gateway_nonce'], 'wpi-gateway' ) ) {
10
        wp_die( __( 'Nonce verification has failed', 'invoicing' ), __( 'Error', 'invoicing' ), array( 'response' => 403 ) );
11
    }
12
13
    // Collect payment data
14
    $payment_data = array(
15
        'price'         => $purchase_data['price'],
16
        'date'          => $purchase_data['date'],
17
        'user_email'    => $purchase_data['user_email'],
18
        'invoice_key'   => $purchase_data['invoice_key'],
19
        'currency'      => wpinv_get_currency(),
20
        'items'         => $purchase_data['items'],
21
        'user_info'     => $purchase_data['user_info'],
22
        'cart_details'  => $purchase_data['cart_details'],
23
        'gateway'       => 'paypal',
24
        'status'        => 'wpi-pending'
25
    );
26
27
    // Record the pending payment
28
    $invoice = wpinv_get_invoice( $purchase_data['invoice_id'] );
29
30
    // Check payment
31
    if ( ! $invoice ) {
32
        // Record the error
33
        wpinv_record_gateway_error( __( 'Payment Error', 'invoicing' ), sprintf( __( 'Payment creation failed before sending buyer to PayPal. Payment data: %s', 'invoicing' ), json_encode( $payment_data ) ), $invoice );
34
        // Problems? send back
35
        wpinv_send_back_to_checkout( '?payment-mode=' . $purchase_data['post_data']['wpi-gateway'] );
0 ignored issues
show
Documentation introduced by
'?payment-mode=' . $purc...t_data']['wpi-gateway'] is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
36
    } else {
37
        // Only send to PayPal if the pending payment is created successfully
38
        $listener_url = wpinv_get_ipn_url( 'paypal' );
39
40
        // Get the success url
41
        $return_url = add_query_arg( array(
42
                'payment-confirm' => 'paypal',
43
                'invoice-id' => $invoice->ID
44
            ), get_permalink( wpinv_get_option( 'success_page', false ) ) );
45
46
        // Get the PayPal redirect uri
47
        $paypal_redirect = trailingslashit( wpinv_get_paypal_redirect() ) . '?';
48
49
        // Setup PayPal arguments
50
        $paypal_args = array(
51
            'business'      => wpinv_get_option( 'paypal_email', false ),
52
            'email'         => $invoice->get_email(),
53
            'first_name'    => $invoice->get_first_name(),
54
            'last_name'     => $invoice->get_last_name(),
55
            'invoice'       => $invoice->get_key(),
56
            'no_shipping'   => '1',
57
            'shipping'      => '0',
58
            'no_note'       => '1',
59
            'currency_code' => wpinv_get_currency(),
60
            'charset'       => get_bloginfo( 'charset' ),
61
            'custom'        => $invoice->ID,
62
            'rm'            => '2',
63
            'return'        => $return_url,
64
            'cancel_return' => wpinv_get_failed_transaction_uri( '?invoice-id=' . $invoice->ID ),
0 ignored issues
show
Documentation introduced by
'?invoice-id=' . $invoice->ID is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
65
            'notify_url'    => $listener_url,
66
            'cbt'           => get_bloginfo( 'name' ),
67
            'bn'            => 'WPInvoicing_SP',
68
            'lc'            => 'US', // this will force paypal site to english
69
            'landing_page'  => apply_filters( 'wpinv_paypal_standard_landing_page', 'billing', $invoice ), // 'login' or 'billing'. login - PayPal account login, billing - Non-PayPal account.
70
        );
71
72
        $paypal_args['address1'] = $invoice->get_address();
73
        $paypal_args['city']     = $invoice->user_info['city'];
74
        $paypal_args['state']    = $invoice->user_info['state'];
75
        $paypal_args['country']  = $invoice->user_info['country'];
76
        $paypal_args['zip']      = $invoice->user_info['zip'];
77
78
        $paypal_extra_args = array(
79
            'cmd'    => '_cart',
80
            'upload' => '1'
81
        );
82
83
        $paypal_args = array_merge( $paypal_extra_args, $paypal_args );
84
85
        // Add cart items
86
        $i = 1;
87
        if( is_array( $purchase_data['cart_details'] ) && ! empty( $purchase_data['cart_details'] ) ) {
88
            foreach ( $purchase_data['cart_details'] as $item ) {
89
                $item['quantity'] = $item['quantity'] > 0 ? $item['quantity'] : 1;
90
                $item_amount = wpinv_sanitize_amount( $item['subtotal'] / $item['quantity'], 2 );
91
92
                if ( $item_amount <= 0 ) {
93
                    $item_amount = 0;
94
                }
95
96
                $paypal_args['item_number_' . $i ]      = $item['id'];
97
                $paypal_args['item_name_' . $i ]        = stripslashes_deep( html_entity_decode( wpinv_get_cart_item_name( $item ), ENT_COMPAT, 'UTF-8' ) );
98
                $paypal_args['quantity_' . $i ]         = $item['quantity'];
99
                $paypal_args['amount_' . $i ]           = $item_amount;
100
                $paypal_args['discount_amount_' . $i ]  = wpinv_sanitize_amount( $item['discount'], 2 );
101
102
                $i++;
103
            }
104
        }
105
106
        // Add taxes to the cart
107
        if ( wpinv_use_taxes() ) {
108
            $paypal_args['tax_cart'] = wpinv_sanitize_amount( (float)$invoice->get_tax(), 2 );
109
        }
110
111
        $paypal_args = apply_filters( 'wpinv_paypal_args', $paypal_args, $purchase_data, $invoice );
112
113
        // Build query
114
        $paypal_redirect .= http_build_query( $paypal_args );
115
116
        // Fix for some sites that encode the entities
117
        $paypal_redirect = str_replace( '&amp;', '&', $paypal_redirect );
118
119
        // Get rid of cart contents
120
        wpinv_empty_cart();
121
        
122
        // Redirect to PayPal
123
        wp_redirect( $paypal_redirect );
124
        exit;
125
    }
126
}
127
add_action( 'wpinv_gateway_paypal', 'wpinv_process_paypal_payment' );
128
129
function wpinv_get_paypal_recurring_args( $paypal_args, $purchase_data, $invoice ) {
130
    if ( $invoice->is_recurring() && $item_id = $invoice->get_recurring() ) {
131
        $item   = new WPInv_Item( $item_id );
132
        
133
        if ( empty( $item ) ) {
134
            return $paypal_args;
135
        }
136
137
        $period             = $item->get_recurring_period();
138
        $interval           = $item->get_recurring_interval();
139
        $bill_times         = (int)$item->get_recurring_limit();
140
        
141
        $initial_amount     = wpinv_sanitize_amount( $invoice->get_total(), 2 );
142
        $recurring_amount   = wpinv_sanitize_amount( $invoice->get_recurring_details( 'total' ), 2 );
143
        
144
        $paypal_args['cmd'] = '_xclick-subscriptions';
145
        $paypal_args['sra'] = '1';
146
        $paypal_args['src'] = '1';
147
        
148
        // Set item description
149
        $paypal_args['item_name']   = stripslashes_deep( html_entity_decode( wpinv_get_cart_item_name( array( 'id' => $item->ID ) ), ENT_COMPAT, 'UTF-8' ) );
150
        
151
        if ( $invoice->is_free_trial() && $item->has_free_trial() ) {
152
            $paypal_args['a1']  = $initial_amount;
153
            $paypal_args['p1']  = $item->get_trial_interval();
154
            $paypal_args['t1']  = $item->get_trial_period();
155
            
156
            // Set the recurring amount
157
            $paypal_args['a3']  = $recurring_amount;
158
        } else if ( $initial_amount != $recurring_amount && $bill_times != 1 ) {
159
            $paypal_args['a1']  = $initial_amount;
160
            $paypal_args['p1']  = $interval;
161
            $paypal_args['t1']  = $period;
162
            
163
            // Set the recurring amount
164
            $paypal_args['a3']  = $recurring_amount;
165
            
166
            if ( $bill_times > 1 ) {
167
                $bill_times--;
168
            }
169
        } else {
170
            $paypal_args['a3']  = $initial_amount;
171
        }
172
        
173
        $paypal_args['p3']  = $interval;
174
        $paypal_args['t3']  = $period;
175
        
176
        if ( $bill_times > 1 ) {
177
            // Make sure it's not over the max of 52
178
            $paypal_args['srt'] = ( $bill_times <= 52 ? absint( $bill_times ) : 52 );
179
        }
180
                
181
        // Remove cart items
182
        $i = 1;
183
        if( is_array( $purchase_data['cart_details'] ) && ! empty( $purchase_data['cart_details'] ) ) {
184
            foreach ( $purchase_data['cart_details'] as $item ) {                
185
                if ( isset( $paypal_args['item_number_' . $i] ) ) {
186
                    unset( $paypal_args['item_number_' . $i] );
187
                }
188
                if ( isset( $paypal_args['item_name_' . $i] ) ) {
189
                    unset( $paypal_args['item_name_' . $i] );
190
                }
191
                if ( isset( $paypal_args['quantity_' . $i] ) ) {
192
                    unset( $paypal_args['quantity_' . $i] );
193
                }
194
                if ( isset( $paypal_args['amount_' . $i] ) ) {
195
                    unset( $paypal_args['amount_' . $i] );
196
                }
197
                if ( isset( $paypal_args['discount_amount_' . $i] ) ) {
198
                    unset( $paypal_args['discount_amount_' . $i] );
199
                }
200
201
                $i++;
202
            }
203
        }
204
        
205
        if ( isset( $paypal_args['tax_cart'] ) ) {
206
            unset( $paypal_args['tax_cart'] );
207
        }
208
                
209
        if ( isset( $paypal_args['upload'] ) ) {
210
            unset( $paypal_args['upload'] );
211
        }
212
        
213
        $paypal_args = apply_filters( 'wpinv_paypal_recurring_args', $paypal_args, $purchase_data, $invoice );
214
    }
215
    
216
    return $paypal_args;
217
}
218
add_filter( 'wpinv_paypal_args', 'wpinv_get_paypal_recurring_args', 10, 3 );
219
220
function wpinv_process_paypal_ipn() {
221
	// Check the request method is POST
222
	if ( isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] != 'POST' ) {
223
		return;
224
	}
225
226
	// Set initial post data to empty string
227
	$post_data = '';
228
229
	// Fallback just in case post_max_size is lower than needed
230
	if ( ini_get( 'allow_url_fopen' ) ) {
231
		$post_data = file_get_contents( 'php://input' );
232
	} else {
233
		// If allow_url_fopen is not enabled, then make sure that post_max_size is large enough
234
		ini_set( 'post_max_size', '12M' );
235
	}
236
	// Start the encoded data collection with notification command
237
	$encoded_data = 'cmd=_notify-validate';
238
239
	// Get current arg separator
240
	$arg_separator = wpinv_get_php_arg_separator_output();
241
242
	// Verify there is a post_data
243 View Code Duplication
	if ( $post_data || strlen( $post_data ) > 0 ) {
244
		// Append the data
245
		$encoded_data .= $arg_separator.$post_data;
246
	} else {
247
		// Check if POST is empty
248
		if ( empty( $_POST ) ) {
249
			// Nothing to do
250
			return;
251
		} else {
252
			// Loop through each POST
253
			foreach ( $_POST as $key => $value ) {
254
				// Encode the value and append the data
255
				$encoded_data .= $arg_separator."$key=" . urlencode( $value );
256
			}
257
		}
258
	}
259
260
	// Convert collected post data to an array
261
	parse_str( $encoded_data, $encoded_data_array );
262
263 View Code Duplication
	foreach ( $encoded_data_array as $key => $value ) {
0 ignored issues
show
Bug introduced by
The expression $encoded_data_array of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
264
		if ( false !== strpos( $key, 'amp;' ) ) {
265
			$new_key = str_replace( '&amp;', '&', $key );
266
			$new_key = str_replace( 'amp;', '&' , $new_key );
267
268
			unset( $encoded_data_array[ $key ] );
269
			$encoded_data_array[ $new_key ] = $value;
270
		}
271
	}
272
273
	// Get the PayPal redirect uri
274
	$paypal_redirect = wpinv_get_paypal_redirect( true );
0 ignored issues
show
Unused Code introduced by
$paypal_redirect is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
275
276
	if ( !wpinv_get_option( 'disable_paypal_verification', false ) ) {
277
		// Validate the IPN
278
279
		$remote_post_vars      = array(
280
			'method'           => 'POST',
281
			'timeout'          => 45,
282
			'redirection'      => 5,
283
			'httpversion'      => '1.1',
284
			'blocking'         => true,
285
			'headers'          => array(
286
				'host'         => 'www.paypal.com',
287
				'connection'   => 'close',
288
				'content-type' => 'application/x-www-form-urlencoded',
289
				'post'         => '/cgi-bin/webscr HTTP/1.1',
290
291
			),
292
			'sslverify'        => false,
293
			'body'             => $encoded_data_array
294
		);
295
296
		// Get response
297
		$api_response = wp_remote_post( wpinv_get_paypal_redirect(), $remote_post_vars );
298
299
		if ( is_wp_error( $api_response ) ) {
300
			wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid IPN verification response. IPN data: %s', 'invoicing' ), json_encode( $api_response ) ) );
301
			return; // Something went wrong
302
		}
303
304
		if ( $api_response['body'] !== 'VERIFIED' && wpinv_get_option( 'disable_paypal_verification', false ) ) {
305
			wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid IPN verification response. IPN data: %s', 'invoicing' ), json_encode( $api_response ) ) );
306
			return; // Response not okay
307
		}
308
	}
309
310
	// Check if $post_data_array has been populated
311
	if ( !is_array( $encoded_data_array ) && !empty( $encoded_data_array ) )
312
		return;
313
314
	$defaults = array(
315
		'txn_type'       => '',
316
		'payment_status' => ''
317
	);
318
319
	$encoded_data_array = wp_parse_args( $encoded_data_array, $defaults );
320
321
	$invoice_id = isset( $encoded_data_array['custom'] ) ? absint( $encoded_data_array['custom'] ) : 0;
322
    
323
	wpinv_error_log( $encoded_data_array['txn_type'], 'PayPal txn_type', __FILE__, __LINE__ );
324
	//wpinv_error_log( $encoded_data_array, 'PayPal IPN response', __FILE__, __LINE__ );
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
325
326
	if ( has_action( 'wpinv_paypal_' . $encoded_data_array['txn_type'] ) ) {
327
		// Allow PayPal IPN types to be processed separately
328
		do_action( 'wpinv_paypal_' . $encoded_data_array['txn_type'], $encoded_data_array, $invoice_id );
329
	} else {
330
		// Fallback to web accept just in case the txn_type isn't present
331
		do_action( 'wpinv_paypal_web_accept', $encoded_data_array, $invoice_id );
332
	}
333
	exit;
334
}
335
add_action( 'wpinv_verify_paypal_ipn', 'wpinv_process_paypal_ipn' );
336
337
function wpinv_process_paypal_web_accept_and_cart( $data, $invoice_id ) {
338
	if ( $data['txn_type'] != 'web_accept' && $data['txn_type'] != 'cart' && $data['payment_status'] != 'Refunded' ) {
339
		return;
340
	}
341
342
	if( empty( $invoice_id ) ) {
343
		return;
344
	}
345
346
	// Collect payment details
347
	$purchase_key   = isset( $data['invoice'] ) ? $data['invoice'] : $data['item_number'];
348
	$paypal_amount  = $data['mc_gross'];
349
	$payment_status = strtolower( $data['payment_status'] );
350
	$currency_code  = strtolower( $data['mc_currency'] );
351
	$business_email = isset( $data['business'] ) && is_email( $data['business'] ) ? trim( $data['business'] ) : trim( $data['receiver_email'] );
352
	$payment_meta   = wpinv_get_invoice_meta( $invoice_id );
353
354
	if ( wpinv_get_payment_gateway( $invoice_id ) != 'paypal' ) {
355
		return; // this isn't a PayPal standard IPN
356
	}
357
358
	// Verify payment recipient
359
	if ( strcasecmp( $business_email, trim( wpinv_get_option( 'paypal_email', false ) ) ) != 0 ) {
360
		wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid business email in IPN response. IPN data: %s', 'invoicing' ), json_encode( $data ) ), $invoice_id );
361
		wpinv_update_payment_status( $invoice_id, 'wpi-failed' );
362
		wpinv_insert_payment_note( $invoice_id, __( 'Payment failed due to invalid PayPal business email.', 'invoicing' ), '', '', true );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
363
		return;
364
	}
365
366
	// Verify payment currency
367 View Code Duplication
	if ( $currency_code != strtolower( $payment_meta['currency'] ) ) {
368
		wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid currency in IPN response. IPN data: %s', 'invoicing' ), json_encode( $data ) ), $invoice_id );
369
		wpinv_update_payment_status( $invoice_id, 'wpi-failed' );
370
		wpinv_insert_payment_note( $invoice_id, __( 'Payment failed due to invalid currency in PayPal IPN.', 'invoicing' ), '', '', true );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
371
		return;
372
	}
373
374
	if ( !wpinv_get_payment_user_email( $invoice_id ) ) {
375
		// This runs when a Buy Now purchase was made. It bypasses checkout so no personal info is collected until PayPal
376
		// No email associated with purchase, so store from PayPal
377
		wpinv_update_invoice_meta( $invoice_id, '_wpinv_email', $data['payer_email'] );
378
379
		// Setup and store the customer's details
380
		$user_info = array(
381
			'user_id'    => '-1',
382
			'email'      => sanitize_text_field( $data['payer_email'] ),
383
			'first_name' => sanitize_text_field( $data['first_name'] ),
384
			'last_name'  => sanitize_text_field( $data['last_name'] ),
385
			'discount'   => '',
386
		);
387
		$user_info['address'] = ! empty( $data['address_street']       ) ? sanitize_text_field( $data['address_street'] )       : false;
388
		$user_info['city']    = ! empty( $data['address_city']         ) ? sanitize_text_field( $data['address_city'] )         : false;
389
		$user_info['state']   = ! empty( $data['address_state']        ) ? sanitize_text_field( $data['address_state'] )        : false;
390
		$user_info['country'] = ! empty( $data['address_country_code'] ) ? sanitize_text_field( $data['address_country_code'] ) : false;
391
		$user_info['zip']     = ! empty( $data['address_zip']          ) ? sanitize_text_field( $data['address_zip'] )          : false;
392
393
		$payment_meta['user_info'] = $user_info;
394
		wpinv_update_invoice_meta( $invoice_id, '_wpinv_payment_meta', $payment_meta );
0 ignored issues
show
Documentation introduced by
$payment_meta is of type array<string,array<strin...g,?,{\"zip\":\"?\"}>"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
395
	}
396
397
	if ( $payment_status == 'refunded' || $payment_status == 'reversed' ) {
398
		// Process a refund
399
		wpinv_process_paypal_refund( $data, $invoice_id );
400
	} else {
401
		if ( get_post_status( $invoice_id ) == 'publish' ) {
402
			return; // Only paid payments once
403
		}
404
405
		// Retrieve the total purchase amount (before PayPal)
406
		$payment_amount = wpinv_payment_total( $invoice_id );
407
408
		if ( number_format( (float) $paypal_amount, 2 ) < number_format( (float) $payment_amount, 2 ) ) {
409
			// The prices don't match
410
			wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid payment amount in IPN response. IPN data: %s', 'invoicing' ), json_encode( $data ) ), $invoice_id );
411
			wpinv_update_payment_status( $invoice_id, 'wpi-failed' );
412
			wpinv_insert_payment_note( $invoice_id, __( 'Payment failed due to invalid amount in PayPal IPN.', 'invoicing' ), '', '', true );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
413
			return;
414
		}
415 View Code Duplication
		if ( $purchase_key != wpinv_get_payment_key( $invoice_id ) ) {
416
			// Purchase keys don't match
417
			wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid purchase key in IPN response. IPN data: %s', 'invoicing' ), json_encode( $data ) ), $invoice_id );
418
			wpinv_update_payment_status( $invoice_id, 'wpi-failed' );
419
			wpinv_insert_payment_note( $invoice_id, __( 'Payment failed due to invalid purchase key in PayPal IPN.', 'invoicing' ), '', '', true );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
420
			return;
421
		}
422
423
		if ( 'complete' == $payment_status || 'completed' == $payment_status || 'processed' == $payment_status || wpinv_is_test_mode( 'paypal' ) ) {
424
			wpinv_insert_payment_note( $invoice_id, sprintf( __( 'PayPal Transaction ID: %s', 'invoicing' ) , $data['txn_id'] ), '', '', true );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
425
			wpinv_set_payment_transaction_id( $invoice_id, $data['txn_id'] );
426
			wpinv_update_payment_status( $invoice_id, 'publish' );
427
		} else if ( 'pending' == $payment_status && isset( $data['pending_reason'] ) ) {
428
			// Look for possible pending reasons, such as an echeck
429
			$note = '';
430
431
			switch( strtolower( $data['pending_reason'] ) ) {
432
				case 'echeck' :
433
					$note = __( 'Payment made via eCheck and will clear automatically in 5-8 days', 'invoicing' );
434
					break;
435
				
436
                case 'address' :
437
					$note = __( 'Payment requires a confirmed customer address and must be accepted manually through PayPal', 'invoicing' );
438
					break;
439
				
440
                case 'intl' :
441
					$note = __( 'Payment must be accepted manually through PayPal due to international account regulations', 'invoicing' );
442
					break;
443
				
444
                case 'multi-currency' :
445
					$note = __( 'Payment received in non-shop currency and must be accepted manually through PayPal', 'invoicing' );
446
					break;
447
				
448
                case 'paymentreview' :
449
                case 'regulatory_review' :
450
					$note = __( 'Payment is being reviewed by PayPal staff as high-risk or in possible violation of government regulations', 'invoicing' );
451
					break;
452
				
453
                case 'unilateral' :
454
					$note = __( 'Payment was sent to non-confirmed or non-registered email address.', 'invoicing' );
455
					break;
456
				
457
                case 'upgrade' :
458
					$note = __( 'PayPal account must be upgraded before this payment can be accepted', 'invoicing' );
459
					break;
460
				
461
                case 'verify' :
462
					$note = __( 'PayPal account is not verified. Verify account in order to accept this payment', 'invoicing' );
463
					break;
464
465
				case 'other' :
466
					$note = __( 'Payment is pending for unknown reasons. Contact PayPal support for assistance', 'invoicing' );
467
					break;
468
			}
469
470
			if ( ! empty( $note ) ) {
471
				wpinv_insert_payment_note( $invoice_id, $note, '', '', true );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
472
			}
473
		} else {
474
			wpinv_insert_payment_note( $invoice_id, wp_sprintf( __( 'PayPal IPN has been received with invalid payment status: %s', 'invoicing' ), $payment_status ), '', '', true );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
475
		}
476
	}
477
}
478
add_action( 'wpinv_paypal_web_accept', 'wpinv_process_paypal_web_accept_and_cart', 10, 2 );
479
480
// Process PayPal subscription sign ups
481
add_action( 'wpinv_paypal_subscr_signup', 'wpinv_process_paypal_subscr_signup' );
482
483
// Process PayPal subscription payments
484
add_action( 'wpinv_paypal_subscr_payment', 'wpinv_process_paypal_subscr_payment' );
485
486
// Process PayPal subscription cancellations
487
add_action( 'wpinv_paypal_subscr_cancel', 'wpinv_process_paypal_subscr_cancel' );
488
489
// Process PayPal subscription end of term notices
490
add_action( 'wpinv_paypal_subscr_eot', 'wpinv_process_paypal_subscr_eot' );
491
492
// Process PayPal payment failed
493
add_action( 'wpinv_paypal_subscr_failed', 'wpinv_process_paypal_subscr_failed' );
494
495
496
/**
497
 * Process the subscription started IPN.
498
 */
499
function wpinv_process_paypal_subscr_signup( $ipn_data ) {
500
    $parent_invoice_id = absint( $ipn_data['custom'] );
501
    if( empty( $parent_invoice_id ) ) {
502
        return;
503
    }
504
505
    $invoice = wpinv_get_invoice( $parent_invoice_id );
506
    if ( empty( $invoice ) ) {
507
        return;
508
    }
509
510
    if ( $invoice->is_free_trial() && !empty( $ipn_data['invoice'] ) ) {
511
        wpinv_insert_payment_note( $parent_invoice_id, sprintf( __( 'PayPal Invoice ID: %s', 'invoicing' ) , $ipn_data['invoice'] ), '', '', true);
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
512
        if ( !empty( $ipn_data['txn_id'] ) ) {
513
            wpinv_set_payment_transaction_id( $parent_invoice_id, $ipn_data['txn_id'] );
514
        }
515
    }
516
517
    $subscription = wpinv_get_paypal_subscription( $ipn_data );
518
    if ( false === $subscription ) {
519
        return;
520
    }
521
    
522
    wpinv_update_payment_status( $parent_invoice_id, 'publish' );
523
    sleep(1);
524
    wpinv_insert_payment_note( $parent_invoice_id, sprintf( __( 'PayPal Subscription ID: %s', 'invoicing' ) , $ipn_data['subscr_id'] ), '', '', true );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
525
    update_post_meta($parent_invoice_id,'_wpinv_subscr_profile_id', $ipn_data['subscr_id']);
526
527
    $status     = 'trialling' == $subscription->status ? 'trialling' : 'active';
528
    $diff_days  = absint( ( ( strtotime( $subscription->expiration ) - strtotime( $subscription->created ) ) / DAY_IN_SECONDS ) );
529
    $created    = date_i18n( 'Y-m-d H:i:s' );
530
    $expiration = date_i18n( 'Y-m-d 23:59:59', ( strtotime( $created ) + ( $diff_days * DAY_IN_SECONDS ) ) );
531
532
    // Retrieve pending subscription from database and update it's status to active and set proper profile ID
533
    $subscription->update( array( 'profile_id' => $ipn_data['subscr_id'], 'status' => $status, 'created' => $created, 'expiration' => $expiration ) );
534
}
535
536
/**
537
 * Process the subscription payment received IPN.
538
 */
539
function wpinv_process_paypal_subscr_payment( $ipn_data ) {
540
    $parent_invoice_id = absint( $ipn_data['custom'] );
541
542
    $parent_invoice = wpinv_get_invoice( $parent_invoice_id );
543
    if ( empty( $parent_invoice ) ) {
544
        return;
545
    }
546
547
    $subscription = wpinv_get_paypal_subscription( $ipn_data );
548
    if ( false === $subscription ) {
549
        return;
550
    }
551
552
    $transaction_id = wpinv_get_payment_transaction_id( $parent_invoice_id );
553
    $times_billed   = $subscription->get_times_billed();
554
555
    // Look to see if payment is same day as signup and we have set the transaction ID on the parent payment yet.
556
    if ( empty( $times_billed ) && ( !$transaction_id || $transaction_id == $parent_invoice_id ) ) {
557
        wpinv_update_payment_status( $parent_invoice_id, 'publish' );
558
        sleep(1);
559
        
560
        // This is the very first payment
561
        wpinv_set_payment_transaction_id( $parent_invoice_id, $ipn_data['txn_id'] );
562
        wpinv_insert_payment_note( $parent_invoice_id, sprintf( __( 'PayPal Transaction ID: %s', 'invoicing' ) , $ipn_data['txn_id'] ), '', '', true );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
563
        return;
564
    }
565
    
566
    if ( wpinv_get_id_by_transaction_id( $ipn_data['txn_id'] ) ) {
567
        return; // Payment already recorded
568
    }
569
570
    $currency_code = strtolower( $ipn_data['mc_currency'] );
571
572
    // verify details
573
    if ( $currency_code != strtolower( wpinv_get_currency() ) ) {
574
        // the currency code is invalid
575
        wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid currency in IPN response. IPN data: ', 'invoicing' ), json_encode( $ipn_data ) ) );
576
        return;
577
    }
578
579
    $args = array(
580
        'amount'         => $ipn_data['mc_gross'],
581
        'transaction_id' => $ipn_data['txn_id'],
582
        'gateway'        => 'paypal'
583
    );
584
    
585
    $invoice_id = $subscription->add_payment( $args );
586
587
    if ( $invoice_id > 0 ) {
588
        wpinv_insert_payment_note( $invoice_id, wp_sprintf( __( 'PayPal Transaction ID: %s', 'invoicing' ) , $ipn_data['txn_id'] ), '', '', true );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
589
        wpinv_insert_payment_note( $invoice_id, wp_sprintf( __( 'PayPal Subscription ID: %s', 'invoicing' ) , $ipn_data['subscr_id'] ), '', '', true );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
590
591
        $subscription->renew();
592
    }
593
}
594
595
/**
596
 * Process the subscription canceled IPN.
597
 */
598
function wpinv_process_paypal_subscr_cancel( $ipn_data ) {
599
    $subscription = wpinv_get_paypal_subscription( $ipn_data );
600
601
    if( false === $subscription ) {
602
        return;
603
    }
604
605
    $subscription->cancel();
606
}
607
608
/**
609
 * Process the subscription expired IPN.
610
 */
611
function wpinv_process_paypal_subscr_eot( $ipn_data ) {
612
    $subscription = wpinv_get_paypal_subscription( $ipn_data );
613
614
    if( false === $subscription ) {
615
        return;
616
    }
617
618
    $subscription->complete();
619
}
620
621
/**
622
 * Process the subscription payment failed IPN.
623
 */
624
function wpinv_process_paypal_subscr_failed( $ipn_data ) {
625
    $subscription = wpinv_get_paypal_subscription( $ipn_data );
626
627
    if( false === $subscription ) {
628
        return;
629
    }
630
631
    $subscription->failing();
632
633
    do_action( 'wpinv_recurring_payment_failed', $subscription );
634
}
635
636
/**
637
 * Retrieve the subscription this IPN notice is for.
638
 */
639
function wpinv_get_paypal_subscription( $ipn_data = array() ) {
640
    $parent_invoice_id = absint( $ipn_data['custom'] );
641
642
    if( empty( $parent_invoice_id ) ) {
643
        return false;
644
    }
645
646
    $invoice = wpinv_get_invoice( $parent_invoice_id );
647
    if ( empty( $invoice ) ) {
648
        return false;
649
    }
650
651
    $subscription = new WPInv_Subscription( $ipn_data['subscr_id'], true );
652
653
    if ( ! ( ! empty( $subscription ) && $subscription->id > 0 ) ) {
654
        $subscription = wpinv_get_subscription( $parent_invoice_id );
655
656
        if ( ! empty( $subscription ) && $subscription->id > 0 ) {
657
            $subscription->update( array( 'profile_id' => sanitize_text_field( $ipn_data['subscr_id'] ) ) );
658
        } else {
659
            return false;
660
        }
661
    }
662
663
    return $subscription;
664
665
}
666
667
function wpinv_process_paypal_refund( $data, $invoice_id = 0 ) {
668
	// Collect payment details
669
670
	if( empty( $invoice_id ) ) {
671
		return;
672
	}
673
674
	if ( get_post_status( $invoice_id ) == 'wpi-refunded' ) {
675
		return; // Only refund payments once
676
	}
677
678
	$payment_amount = wpinv_payment_total( $invoice_id );
679
	$refund_amount  = $data['mc_gross'] * -1;
680
681
	do_action( 'wpinv_paypal_refund_request', $data, $invoice_id );
682
683
	if ( number_format( (float) $refund_amount, 2 ) < number_format( (float) $payment_amount, 2 ) ) {
684
		wpinv_insert_payment_note( $invoice_id, wp_sprintf( __( 'PayPal partial refund of %s processed for transaction #%s for reason: %s', 'invoicing' ), (float)$refund_amount . ' '. $data['mc_currency'], $data['parent_txn_id'], $data['reason_code'] ), '', '', true );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
685
686
		do_action( 'wpinv_paypal_invoice_partially_refunded', $data, $invoice_id, $refund_amount );
687
688
		return; // This is a partial refund
689
	}
690
691
	wpinv_insert_payment_note( $invoice_id, sprintf( __( 'PayPal Payment #%s Refunded for reason: %s', 'invoicing' ), $data['parent_txn_id'], $data['reason_code'] ), '', '', true );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
692
	wpinv_insert_payment_note( $invoice_id, sprintf( __( 'PayPal Refund Transaction ID: %s', 'invoicing' ), $data['txn_id'] ), '', '', true );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
693
	wpinv_update_payment_status( $invoice_id, 'wpi-refunded' );
694
695
	do_action( 'wpinv_paypal_invoice_fully_refunded', $data, $invoice_id );
696
}
697
698
function wpinv_get_paypal_redirect( $ssl_check = false ) {
699
    if ( is_ssl() || ! $ssl_check ) {
700
        $protocol = 'https://';
701
    } else {
702
        $protocol = 'http://';
703
    }
704
705
    // Check the current payment mode
706
    if ( wpinv_is_test_mode( 'paypal' ) ) {
707
        // Test mode
708
        $paypal_uri = $protocol . 'www.sandbox.paypal.com/cgi-bin/webscr';
709
    } else {
710
        // Live mode
711
        $paypal_uri = $protocol . 'www.paypal.com/cgi-bin/webscr';
712
    }
713
714
    return apply_filters( 'wpinv_paypal_uri', $paypal_uri );
715
}
716
717
function wpinv_paypal_success_page_content( $content ) {
718
    global $wpi_invoice;
719
    
720
    $session = wpinv_get_checkout_session();
721
722
    if ( empty( $_GET['invoice-id'] ) && empty( $session['invoice_key'] )  ) {
723
        return $content;
724
    }
725
726
    $invoice_id = !empty( $_GET['invoice-id'] ) ? absint( $_GET['invoice-id'] ) : wpinv_get_invoice_id_by_key( $session['invoice_key'] );
727
728
    if ( empty(  $invoice_id ) ) {
729
        return $content;
730
    }
731
732
    $wpi_invoice = wpinv_get_invoice( $invoice_id );
733
    
734
    if ( !empty( $wpi_invoice ) && 'wpi-pending' == $wpi_invoice->status ) {
735
        // Payment is still pending so show processing indicator to fix the Race Condition, issue #
736
        ob_start();
737
        wpinv_get_template_part( 'wpinv-payment-processing' );
738
        $content = ob_get_clean();
739
    }
740
741
    return $content;
742
}
743
add_filter( 'wpinv_payment_confirm_paypal', 'wpinv_paypal_success_page_content' );
744
745
function wpinv_paypal_get_transaction_id( $invoice_id ) {
746
    $transaction_id = '';
747
    $notes = wpinv_get_invoice_notes( $invoice_id );
748
749
    foreach ( $notes as $note ) {
750
        if ( preg_match( '/^PayPal Transaction ID: ([^\s]+)/', $note->comment_content, $match ) ) {
751
            $transaction_id = $match[1];
752
            continue;
753
        }
754
    }
755
756
    return apply_filters( 'wpinv_paypal_set_transaction_id', $transaction_id, $invoice_id );
757
}
758
add_filter( 'wpinv_payment_get_transaction_id-paypal', 'wpinv_paypal_get_transaction_id', 10, 1 );
759
760 View Code Duplication
function wpinv_paypal_link_transaction_id( $transaction_id, $invoice_id, $invoice ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
761
    if ( $transaction_id == $invoice_id ) {
762
        $transaction_link = $transaction_id;
763
    } else {
764
        if ( ! empty( $invoice ) && ! empty( $invoice->mode ) ) {
765
            $mode = $invoice->mode;
766
        } else {
767
            $mode = wpinv_is_test_mode( 'paypal' ) ? 'test' : 'live';
768
        }
769
770
        $sandbox = $mode == 'test' ? '.sandbox' : '';
771
        $transaction_url = 'https://www' . $sandbox . '.paypal.com/webscr?cmd=_history-details-from-hub&id=' . $transaction_id;
772
773
        $transaction_link = '<a href="' . esc_url( $transaction_url ) . '" target="_blank">' . $transaction_id . '</a>';
774
    }
775
776
    return apply_filters( 'wpinv_paypal_link_payment_details_transaction_id', $transaction_link, $transaction_id, $invoice );
777
}
778
add_filter( 'wpinv_payment_details_transaction_id-paypal', 'wpinv_paypal_link_transaction_id', 10, 3 );
779
780 View Code Duplication
function wpinv_paypal_profile_id_link( $profile_id, $subscription ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
781
    $link = $profile_id;
782
783
    if ( ! empty( $profile_id ) && ! empty( $subscription ) && ( $invoice_id = $subscription->get_original_payment_id() ) ) {
784
        $invoice = wpinv_get_invoice( $invoice_id );
785
786
        if ( ! empty( $invoice ) && ! empty( $invoice->mode ) ) {
787
            $mode = $invoice->mode;
788
        } else {
789
            $mode = wpinv_is_test_mode( 'paypal' ) ? 'test' : 'live';
790
        }
791
792
        $sandbox = $mode == 'test' ? '.sandbox' : '';
793
        $url = 'https://www' . $sandbox . '.paypal.com/cgi-bin/webscr?cmd=_profile-recurring-payments&encrypted_profile_id=' . $profile_id;
794
795
        $link = '<a href="' . esc_url( $url ) . '" target="_blank">' . $profile_id . '</a>';
796
    }
797
    
798
    return apply_filters( 'wpinv_paypal_profile_id_link', $link, $profile_id, $subscription );
799
}
800
add_filter( 'wpinv_subscription_profile_link_paypal', 'wpinv_paypal_profile_id_link', 10, 2 );
801
802 View Code Duplication
function wpinv_paypal_transaction_id_link( $transaction_id, $subscription ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
803
    if ( ! empty( $transaction_id ) && ! empty( $subscription ) && ( $invoice_id = $subscription->get_original_payment_id() ) ) {
804
        $invoice = wpinv_get_invoice( $invoice_id );
805
806
        if ( ! empty( $invoice ) ) {
807
            return wpinv_paypal_link_transaction_id( $transaction_id, $invoice_id, $invoice );
808
        }        
809
    }
810
    
811
    return $transaction_id;
812
}
813
add_filter( 'wpinv_subscription_transaction_link_paypal', 'wpinv_paypal_transaction_id_link', 10, 2 );
814
815
function wpinv_is_paypal_valid_for_use() {
816
    return in_array( wpinv_get_currency(), apply_filters( 'wpinv_paypal_supported_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' ) ) );
817
}
818
819
function wpinv_check_paypal_currency_support( $gateway_list ) {
820
    if ( isset( $gateway_list['paypal'] ) && ! wpinv_is_paypal_valid_for_use() ) {
821
        unset( $gateway_list['paypal'] );
822
    }
823
    return $gateway_list;
824
}
825
add_filter( 'wpinv_enabled_payment_gateways', 'wpinv_check_paypal_currency_support', 10, 1 );
826
827
function wpinv_gateway_paypal_button_label( $label ) {
0 ignored issues
show
Unused Code introduced by
The parameter $label is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
828
    return __( 'Proceed to PayPal', 'invoicing' );
829
}
830
add_filter( 'wpinv_gateway_paypal_button_label', 'wpinv_gateway_paypal_button_label', 10, 1 );