Passed
Push — master ( cb75a2...6929e7 )
by Brian
05:54 queued 11s
created

wpinv_checkout_validate_cc_zip()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 16
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 6
c 1
b 0
f 0
dl 0
loc 16
rs 10
cc 4
nc 3
nop 2
1
<?php
2
/**
3
 * Contains functions related to Invoicing plugin.
4
 *
5
 * @since 1.0.0
6
 * @package Invoicing
7
 */
8
 
9
// MUST have WordPress.
10
if ( !defined( 'WPINC' ) ) {
11
    exit( 'Do NOT access this file directly: ' . basename( __FILE__ ) );
12
}
13
14
function wpinv_get_payment_gateways() {
15
    // Default, built-in gateways
16
    $gateways = array(
17
        'paypal' => array(
18
            'admin_label'    => __( 'PayPal Standard', 'invoicing' ),
19
            'checkout_label' => __( 'PayPal Standard', 'invoicing' ),
20
            'ordering'       => 1,
21
        ),
22
        'authorizenet' => array(
23
            'admin_label'    => __( 'Authorize.Net (AIM)', 'invoicing' ),
24
            'checkout_label' => __( 'Authorize.Net - Credit Card / Debit Card', 'invoicing' ),
25
            'ordering'       => 4,
26
        ),
27
        'worldpay' => array(
28
            'admin_label'    => __( 'Worldpay', 'invoicing' ),
29
            'checkout_label' => __( 'Worldpay - Credit Card / Debit Card', 'invoicing' ),
30
            'ordering'       => 5,
31
        ),
32
        'bank_transfer' => array(
33
            'admin_label'    => __( 'Pre Bank Transfer', 'invoicing' ),
34
            'checkout_label' => __( 'Pre Bank Transfer', 'invoicing' ),
35
            'ordering'       => 11,
36
        ),
37
        'manual' => array(
38
            'admin_label'    => __( 'Manual Payment', 'invoicing' ),
39
            'checkout_label' => __( 'Manual Payment', 'invoicing' ),
40
            'ordering'       => 12,
41
        ),
42
    );
43
44
    return apply_filters( 'wpinv_payment_gateways', $gateways );
45
}
46
47
function wpinv_payment_gateway_titles( $all_gateways ) {
48
    global $wpinv_options;
49
50
    $gateways = array();
51
    foreach ( $all_gateways as $key => $gateway ) {
52
        if ( !empty( $wpinv_options[$key . '_title'] ) ) {
53
            $all_gateways[$key]['checkout_label'] = __( $wpinv_options[$key . '_title'], 'invoicing' );
54
        }
55
56
        $gateways[$key] = isset( $wpinv_options[$key . '_ordering'] ) ? $wpinv_options[$key . '_ordering'] : ( isset( $gateway['ordering'] ) ? $gateway['ordering'] : '' );
57
    }
58
59
    asort( $gateways );
60
61
    foreach ( $gateways as $gateway => $key ) {
62
        $gateways[$gateway] = $all_gateways[$gateway];
63
    }
64
65
    return $gateways;
66
}
67
add_filter( 'wpinv_payment_gateways', 'wpinv_payment_gateway_titles', 1000, 1 );
68
69
function wpinv_get_enabled_payment_gateways( $sort = false ) {
70
    $gateways = wpinv_get_payment_gateways();
71
    $enabled  = wpinv_get_option( 'gateways', false );
72
73
    $gateway_list = array();
74
75
    foreach ( $gateways as $key => $gateway ) {
76
        if ( isset( $enabled[ $key ] ) && $enabled[ $key ] == 1 ) {
77
            $gateway_list[ $key ] = $gateway;
78
        }
79
    }
80
81
    if ( true === $sort ) {
82
        uasort( $gateway_list, 'wpinv_sort_gateway_order' );
83
        
84
        // Reorder our gateways so the default is first
85
        $default_gateway_id = wpinv_get_default_gateway();
86
87
        if ( wpinv_is_gateway_active( $default_gateway_id ) ) {
88
            $default_gateway    = array( $default_gateway_id => $gateway_list[ $default_gateway_id ] );
89
            unset( $gateway_list[ $default_gateway_id ] );
90
91
            $gateway_list = array_merge( $default_gateway, $gateway_list );
92
        }
93
    }
94
95
    return apply_filters( 'wpinv_enabled_payment_gateways', $gateway_list );
96
}
97
98
function wpinv_sort_gateway_order( $a, $b ) {
99
    return $a['ordering'] - $b['ordering'];
100
}
101
102
function wpinv_is_gateway_active( $gateway ) {
103
    $gateways = wpinv_get_enabled_payment_gateways();
104
105
    $ret = is_array($gateways) && $gateway ?  array_key_exists( $gateway, $gateways ) : false;
106
107
    return apply_filters( 'wpinv_is_gateway_active', $ret, $gateway, $gateways );
108
}
109
110
function wpinv_get_default_gateway() {
111
    $default = wpinv_get_option( 'default_gateway', 'paypal' );
112
113
    if ( !wpinv_is_gateway_active( $default ) ) {
114
        $gateways = wpinv_get_enabled_payment_gateways();
115
        $gateways = array_keys( $gateways );
116
        $default  = reset( $gateways );
117
    }
118
119
    return apply_filters( 'wpinv_default_gateway', $default );
120
}
121
122
function wpinv_get_gateway_admin_label( $gateway ) {
123
    $gateways = wpinv_get_payment_gateways();
124
    $label    = isset( $gateways[ $gateway ] ) ? $gateways[ $gateway ]['admin_label'] : $gateway;
125
    $payment  = isset( $_GET['id'] ) ? absint( $_GET['id'] ) : false;
126
127
    if( $gateway == 'manual' && $payment ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $payment of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
128
        if( !( (float)wpinv_payment_total( $payment ) > 0 ) ) {
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_payment_total() has been deprecated. ( Ignorable by Annotation )

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

128
        if( !( (float)/** @scrutinizer ignore-deprecated */ wpinv_payment_total( $payment ) > 0 ) ) {
Loading history...
129
            $label = __( 'Free Purchase', 'invoicing' );
130
        }
131
    }
132
133
    return apply_filters( 'wpinv_gateway_admin_label', $label, $gateway );
134
}
135
136
function wpinv_get_gateway_description( $gateway ) {
137
    global $wpinv_options;
138
139
    $description = ! empty( $wpinv_options[$gateway . '_desc'] ) ? $wpinv_options[$gateway . '_desc'] : '';
140
141
    return apply_filters( 'wpinv_gateway_description', $description, $gateway );
142
}
143
144
function wpinv_get_gateway_button_label( $gateway ) {
145
    return apply_filters( 'wpinv_gateway_' . $gateway . '_button_label', '' );
146
}
147
148
function wpinv_get_gateway_checkout_label( $gateway ) {
149
    $gateways = wpinv_get_payment_gateways();
150
    $label    = isset( $gateways[ $gateway ] ) ? $gateways[ $gateway ]['checkout_label'] : $gateway;
151
152
    if( $gateway == 'manual' ) {
153
        $label = __( 'Manual Payment', 'invoicing' );
154
    }
155
156
    return apply_filters( 'wpinv_gateway_checkout_label', $label, $gateway );
157
}
158
159
function wpinv_settings_sections_gateways( $settings ) {
160
    $gateways = wpinv_get_payment_gateways();
161
    
162
    if (!empty($gateways)) {
163
        foreach  ($gateways as $key => $gateway) {
164
            $settings[$key] = $gateway['admin_label'];
165
        }
166
    }
167
    
168
    return $settings;    
169
}
170
add_filter( 'wpinv_settings_sections_gateways', 'wpinv_settings_sections_gateways', 10, 1 );
171
172
function wpinv_settings_gateways( $settings ) {
173
    $gateways = wpinv_get_payment_gateways();
174
    
175
    if (!empty($gateways)) {
176
        foreach  ($gateways as $key => $gateway) {
177
            $setting = array();
178
            $setting[$key . '_header'] = array(
179
                    'id'   => 'gateway_header',
180
                    'name' => '<h3>' . wp_sprintf( __( '%s Settings', 'invoicing' ), $gateway['admin_label'] ) . '</h3>',
181
                    'custom' => $key,
182
                    'type' => 'gateway_header',
183
                );
184
            $setting[$key . '_active'] = array(
185
                    'id'   => $key . '_active',
186
                    'name' => __( 'Active', 'invoicing' ),
187
                    'desc' => wp_sprintf( __( 'Enable %s', 'invoicing' ), $gateway['admin_label'] ),
188
                    'type' => 'checkbox',
189
                );
190
                
191
            $setting[$key . '_title'] = array(
192
                    'id'   => $key . '_title',
193
                    'name' => __( 'Title', 'invoicing' ),
194
                    'desc' => __( 'This controls the title which the user sees during checkout.', 'invoicing' ),
195
                    'type' => 'text',
196
                    'std' => isset($gateway['checkout_label']) ? $gateway['checkout_label'] : ''
197
                );
198
            
199
            $setting[$key . '_desc'] = array(
200
                    'id'   => $key . '_desc',
201
                    'name' => __( 'Description', 'invoicing' ),
202
                    'desc' => __( 'This controls the description which the user sees during checkout.', 'invoicing' ),
203
                    'type' => 'text',
204
                    'size' => 'large'
205
                );
206
                
207
            $setting[$key . '_ordering'] = array(
208
                    'id'   => $key . '_ordering',
209
                    'name' => __( 'Display Order', 'invoicing' ),
210
                    'type' => 'number',
211
                    'size' => 'small',
212
                    'std'  => isset($gateway['ordering']) ? $gateway['ordering'] : '10',
213
                    'min'  => '-100000',
214
                    'max'  => '100000',
215
                    'step' => '1'
216
                );
217
                
218
            $setting = apply_filters( 'wpinv_gateway_settings', $setting, $key );
219
            $setting = apply_filters( 'wpinv_gateway_settings_' . $key, $setting );
220
            
221
            $settings[$key] = $setting;
222
        }
223
    }
224
    
225
    return $settings;    
226
}
227
add_filter( 'wpinv_settings_gateways', 'wpinv_settings_gateways', 10, 1 );
228
229
function wpinv_gateway_header_callback( $args ) {
230
    echo '<input type="hidden" id="wpinv_settings[save_gateway]" name="wpinv_settings[save_gateway]" value="' . esc_attr( $args['custom'] ) . '" />';
231
}
232
233
function wpinv_get_gateway_supports( $gateway ) {
234
    $gateways = wpinv_get_enabled_payment_gateways();
235
    $supports = isset( $gateways[ $gateway ]['supports'] ) ? $gateways[ $gateway ]['supports'] : array();
236
    return apply_filters( 'wpinv_gateway_supports', $supports, $gateway );
237
}
238
239
function wpinv_gateway_supports_buy_now( $gateway ) {
240
    $supports = wpinv_get_gateway_supports( $gateway );
241
    $ret = in_array( 'buy_now', $supports );
242
    return apply_filters( 'wpinv_gateway_supports_buy_now', $ret, $gateway );
243
}
244
245
function wpinv_shop_supports_buy_now() {
246
    $gateways = wpinv_get_enabled_payment_gateways();
247
    $ret      = false;
248
249
    if ( !wpinv_use_taxes()  && $gateways ) {
250
        foreach ( $gateways as $gateway_id => $gateway ) {
251
            if ( wpinv_gateway_supports_buy_now( $gateway_id ) ) {
252
                $ret = true;
253
                break;
254
            }
255
        }
256
    }
257
258
    return apply_filters( 'wpinv_shop_supports_buy_now', $ret );
259
}
260
261
function wpinv_send_to_gateway( $gateway, $payment_data ) {
262
    $payment_data['gateway_nonce'] = wp_create_nonce( 'wpi-gateway' );
263
264
    // $gateway must match the ID used when registering the gateway
265
    do_action( 'wpinv_gateway_' . $gateway, $payment_data );
266
}
267
268
function wpinv_show_gateways() {
269
    $gateways = wpinv_get_enabled_payment_gateways();
270
    $show_gateways = false;
271
272
    $chosen_gateway = isset( $_GET['payment-mode'] ) ? preg_replace('/[^a-zA-Z0-9-_]+/', '', $_GET['payment-mode'] ) : false;
273
274
    if ( count( $gateways ) > 1 && empty( $chosen_gateway ) ) {
275
        $show_gateways = true;
276
        if ( wpinv_get_cart_total() <= 0 ) {
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_get_cart_total() has been deprecated. ( Ignorable by Annotation )

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

276
        if ( /** @scrutinizer ignore-deprecated */ wpinv_get_cart_total() <= 0 ) {
Loading history...
277
            $show_gateways = false;
278
        }
279
    }
280
    
281
    if ( !$show_gateways && wpinv_cart_has_recurring_item() ) {
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_cart_has_recurring_item() has been deprecated. ( Ignorable by Annotation )

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

281
    if ( !$show_gateways && /** @scrutinizer ignore-deprecated */ wpinv_cart_has_recurring_item() ) {
Loading history...
282
        $show_gateways = true;
283
    }
284
285
    return apply_filters( 'wpinv_show_gateways', $show_gateways );
286
}
287
288
function wpinv_get_chosen_gateway( $invoice_id = 0 ) {
289
	$gateways = array_keys( wpinv_get_enabled_payment_gateways() );
290
291
    $chosen = false;
292
    if ( $invoice_id > 0 && $invoice = wpinv_get_invoice( $invoice_id ) ) {
293
        $chosen = $invoice->get_gateway();
294
    }
295
296
	$chosen   = isset( $_REQUEST['payment-mode'] ) ? sanitize_text_field( $_REQUEST['payment-mode'] ) : $chosen;
297
298
	if ( false !== $chosen ) {
299
		$chosen = preg_replace('/[^a-zA-Z0-9-_]+/', '', $chosen );
300
	}
301
302
	if ( ! empty ( $chosen ) ) {
303
		$enabled_gateway = urldecode( $chosen );
304
	} else if (  !empty( $invoice ) && (float)$invoice->get_subtotal() <= 0 ) {
305
		$enabled_gateway = 'manual';
306
	} else {
307
		$enabled_gateway = wpinv_get_default_gateway();
308
	}
309
    
310
    if ( !wpinv_is_gateway_active( $enabled_gateway ) && !empty( $gateways ) ) {
311
        if(wpinv_is_gateway_active( wpinv_get_default_gateway()) ){
312
            $enabled_gateway = wpinv_get_default_gateway();
313
        }else{
314
            $enabled_gateway = $gateways[0];
315
        }
316
317
    }
318
319
	return apply_filters( 'wpinv_chosen_gateway', $enabled_gateway );
320
}
321
322
function wpinv_record_gateway_error( $title = '', $message = '', $parent = 0 ) {
0 ignored issues
show
Unused Code introduced by
The parameter $parent is not used and could be removed. ( Ignorable by Annotation )

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

322
function wpinv_record_gateway_error( $title = '', $message = '', /** @scrutinizer ignore-unused */ $parent = 0 ) {

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

Loading history...
323
    return wpinv_error_log( $message, $title );
0 ignored issues
show
Bug introduced by
Are you sure the usage of wpinv_error_log($message, $title) is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
324
}
325
326
function wpinv_count_sales_by_gateway( $gateway_id = 'paypal', $status = 'publish' ) {
327
	$ret  = 0;
328
	$args = array(
329
		'meta_key'    => '_wpinv_gateway',
330
		'meta_value'  => $gateway_id,
331
		'nopaging'    => true,
332
		'post_type'   => 'wpi_invoice',
333
		'post_status' => $status,
334
		'fields'      => 'ids'
335
	);
336
337
	$payments = new WP_Query( $args );
338
339
	if( $payments )
0 ignored issues
show
introduced by
$payments is of type WP_Query, thus it always evaluated to true.
Loading history...
340
		$ret = $payments->post_count;
341
	return $ret;
342
}
343
344
function wpinv_settings_update_gateways( $input ) {
345
    global $wpinv_options;
346
    
347
    if ( !empty( $input['save_gateway'] ) ) {
348
        $gateways = wpinv_get_option( 'gateways', false );
349
        $gateways = !empty($gateways) ? $gateways : array();
350
        $gateway = $input['save_gateway'];
351
        
352
        if ( !empty( $input[$gateway . '_active'] ) ) {
353
            $gateways[$gateway] = 1;
354
        } else {
355
            if ( isset( $gateways[$gateway] ) ) {
356
                unset( $gateways[$gateway] );
357
            }
358
        }
359
        
360
        $input['gateways'] = $gateways;
361
    }
362
    
363
    if ( !empty( $input['default_gateway'] ) ) {
364
        $gateways = wpinv_get_payment_gateways();
365
        
366
        foreach ( $gateways as $key => $gateway ) {
367
            $active   = 0;
368
            if ( !empty( $input['gateways'] ) && !empty( $input['gateways'][$key] ) ) {
369
                $active = 1;
370
            }
371
            
372
            $input[$key . '_active'] = $active;
373
            
374
            if ( empty( $wpinv_options[$key . '_title'] ) ) {
375
                $input[$key . '_title'] = $gateway['checkout_label'];
376
            }
377
            
378
            if ( !isset( $wpinv_options[$key . '_ordering'] ) && isset( $gateway['ordering'] ) ) {
379
                $input[$key . '_ordering'] = $gateway['ordering'];
380
            }
381
        }
382
    }
383
    
384
    return $input;
385
}
386
add_filter( 'wpinv_settings_tab_gateways_sanitize', 'wpinv_settings_update_gateways', 10, 1 );
387
388
// PayPal Standard settings
389
function wpinv_gateway_settings_paypal( $setting ) {    
390
    $setting['paypal_active']['desc'] = $setting['paypal_active']['desc'] . ' ' . __( '( Supported Currencies: AUD, BRL, CAD, CZK, DKK, EUR, HKD, HUF, ILS, JPY, MYR, MXN, NOK, NZD, PHP, PLN, GBP, SGD, SEK, CHF, TWD, THB, USD )', 'invoicing' );
391
    $setting['paypal_desc']['std'] = __( 'Pay via PayPal: you can pay with your credit card if you don\'t have a PayPal account.', 'invoicing' );
392
    
393
    $setting['paypal_sandbox'] = array(
394
            'type' => 'checkbox',
395
            'id'   => 'paypal_sandbox',
396
            'name' => __( 'PayPal Sandbox', 'invoicing' ),
397
            'desc' => __( 'PayPal sandbox can be used to test payments.', 'invoicing' ),
398
            'std'  => 1
399
        );
400
        
401
    $setting['paypal_email'] = array(
402
            'type' => 'text',
403
            'id'   => 'paypal_email',
404
            'name' => __( 'PayPal Email', 'invoicing' ),
405
            'desc' => __( 'Please enter your PayPal account\'s email address. Ex: [email protected]', 'invoicing' ),
406
            'std' => __( '[email protected]', 'invoicing' ),
407
        );
408
    /*
409
    $setting['paypal_ipn_url'] = array(
410
            'type' => 'text',
411
            'id'   => 'paypal_ipn_url',
412
            'name' => __( 'PayPal IPN Url', 'invoicing' ),
413
            'desc' => __( 'Configure Instant Payment Notifications(IPN) url at PayPal. Ex: http://yoursite.com/?wpi-ipn=paypal', 'invoicing' ),
414
            'size' => 'large'
415
        );
416
    */
417
        
418
    return $setting;
419
}
420
add_filter( 'wpinv_gateway_settings_paypal', 'wpinv_gateway_settings_paypal', 10, 1 );
421
422
// Pre Bank Transfer settings
423
function wpinv_gateway_settings_bank_transfer( $setting ) {
424
    $setting['bank_transfer_desc']['std'] = __( 'Make your payment directly into our bank account. Please use your Invoice ID as the payment reference. Your invoice won\'t be processed until the funds have cleared in our account.', 'invoicing' );
425
    
426
    $setting['bank_transfer_ac_name'] = array(
427
            'type' => 'text',
428
            'id' => 'bank_transfer_ac_name',
429
            'name' => __( 'Account Name', 'invoicing' ),
430
            'desc' => __( 'Enter the bank account name to which you want to transfer payment.', 'invoicing' ),
431
            'std'  =>  __( 'Mr. John Martin', 'invoicing' ),
432
        );
433
    
434
    $setting['bank_transfer_ac_no'] = array(
435
            'type' => 'text',
436
            'id' => 'bank_transfer_ac_no',
437
            'name' => __( 'Account Number', 'invoicing' ),
438
            'desc' => __( 'Enter your bank account number.', 'invoicing' ),
439
            'std'  =>  __( 'TEST1234567890', 'invoicing' ),
440
        );
441
    
442
    $setting['bank_transfer_bank_name'] = array(
443
            'type' => 'text',
444
            'id'   => 'bank_transfer_bank_name',
445
            'name' => __( 'Bank Name', 'invoicing' ),
446
            'desc' => __( 'Enter the bank name to which you want to transfer payment.', 'invoicing' ),
447
            'std' => __( 'ICICI Bank', 'invoicing' ),
448
        );
449
    
450
    $setting['bank_transfer_ifsc'] = array(
451
            'type' => 'text',
452
            'id'   => 'bank_transfer_ifsc',
453
            'name' => __( 'IFSC Code', 'invoicing' ),
454
            'desc' => __( 'Enter your bank IFSC code.', 'invoicing' ),
455
            'std'  =>  __( 'ICIC0001234', 'invoicing' ),
456
        );
457
        
458
    $setting['bank_transfer_iban'] = array(
459
            'type' => 'text',
460
            'id'   => 'bank_transfer_iban',
461
            'name' => __( 'IBAN', 'invoicing' ),
462
            'desc' => __( 'Enter your International Bank Account Number(IBAN).', 'invoicing' ),
463
            'std'  =>  __( 'GB29NWBK60161331926819', 'invoicing' ),
464
        );
465
        
466
    $setting['bank_transfer_bic'] = array(
467
            'type' => 'text',
468
            'id'   => 'bank_transfer_bic',
469
            'name' => __( 'BIC/Swift Code', 'invoicing' ),
470
            'std'  =>  __( 'ICICGB2L129', 'invoicing' ),
471
        );
472
473
    $setting['bank_transfer_sort_code'] = array(
474
        'type' => 'text',
475
        'id'   => 'bank_transfer_sort_code',
476
        'name' => __( 'Sort Code', 'invoicing' ),
477
        'std'  =>  __( '12-34-56', 'invoicing' ),
478
    );
479
        
480
    $setting['bank_transfer_info'] = array(
481
            'id'   => 'bank_transfer_info',
482
            'name' => __( 'Instructions', 'invoicing' ),
483
            'desc' => __( 'Instructions that will be added to the thank you page and emails.', 'invoicing' ),
484
            'type' => 'textarea',
485
            'std' => __( 'Make your payment directly into our bank account. Please use your Invoice ID as the payment reference. Your invoice won\'t be processed until the funds have cleared in our account.', 'invoicing' ),
486
            'cols' => 37,
487
            'rows' => 5
488
        );
489
        
490
    return $setting;
491
}
492
add_filter( 'wpinv_gateway_settings_bank_transfer', 'wpinv_gateway_settings_bank_transfer', 10, 1 );
493
494
// Authorize.Net settings
495
function wpinv_gateway_settings_authorizenet( $setting ) {
496
    $setting['authorizenet_active']['desc'] = $setting['authorizenet_active']['desc'] . ' ' . __( '( Supported Currencies: AUD, CAD, CHF, DKK, EUR, GBP, JPY, NOK, NZD, PLN, SEK, USD, ZAR )', 'invoicing' );
497
    $setting['authorizenet_desc']['std'] = __( 'Pay using a Authorize.Net to process Credit card / Debit card transactions.', 'invoicing' );
498
    
499
    $setting['authorizenet_sandbox'] = array(
500
            'type' => 'checkbox',
501
            'id'   => 'authorizenet_sandbox',
502
            'name' => __( 'Authorize.Net Test Mode', 'invoicing' ),
503
            'desc' => __( 'Enable Authorize.Net test mode to test payments.', 'invoicing' ),
504
            'std'  => 1
505
        );
506
        
507
    $setting['authorizenet_login_id'] = array(
508
            'type' => 'text',
509
            'id'   => 'authorizenet_login_id',
510
            'name' => __( 'API Login ID', 'invoicing' ),
511
            'desc' => __( 'API Login ID can be obtained from Authorize.Net Account > Settings > Security Settings > General Security Settings > API Credentials & Keys. Example : 2j4rBekUnD', 'invoicing' ),
512
            'std' => '2j4rBekUnD',
513
        );
514
    
515
    $setting['authorizenet_transaction_key'] = array(
516
            'type' => 'text',
517
            'id'   => 'authorizenet_transaction_key',
518
            'name' => __( 'Transaction Key', 'invoicing' ),
519
            'desc' => __( 'Transaction Key can be obtained from Authorize.Net Account > Settings > Security Settings > General Security Settings > API Credentials & Keys. Example : 4vyBUOJgR74679xa', 'invoicing' ),
520
            'std' => '4vyBUOJgR74679xa',
521
        );
522
        
523
    $setting['authorizenet_md5_hash'] = array(
524
            'type' => 'text',
525
            'id'   => 'authorizenet_md5_hash',
526
            'name' => __( 'MD5-Hash', 'invoicing' ),
527
            'desc' => __( 'The MD5 Hash security feature allows to authenticate transaction responses from the Authorize.Net for recurring payments. It can be obtained from Authorize.Net Account > Settings > Security Settings > General Settings > MD5 Hash.', 'invoicing' ),
528
            'std' => '',
529
        );
530
531
    $setting['authorizenet_transaction_type'] = array(
532
        'id'          => 'authorizenet_transaction_type',
533
        'name'        => __( 'Transaction Type', 'invoicing' ),
534
        'desc'        => __( 'Choose transaction type.', 'invoicing' ),
535
        'type'        => 'select',
536
        'class'       => 'wpi_select2',
537
        'options'     => array(
538
            'authorize_capture' => __( 'Authorize And Capture', 'invoicing' ),
539
            'authorize_only' => __( 'Authorize Only', 'invoicing' ),
540
        ),
541
        'std'         => 'authorize_capture'
542
    );
543
544
    $setting['authorizenet_transaction_type_recurring'] = array(
545
        'id'          => 'authorizenet_transaction_type_recurring',
546
        'name'        => __( 'Transaction Type for Recurring', 'invoicing' ),
547
        'desc'        => __( 'Choose transaction type for recurring payments.', 'invoicing' ),
548
        'type'        => 'select',
549
        'class'       => 'wpi_select2',
550
        'options'     => array(
551
            'authorize_capture' => __( 'Authorize And Capture', 'invoicing' ),
552
            'authorize_only' => __( 'Authorize Only', 'invoicing' ),
553
        ),
554
        'std'         => 'authorize_only'
555
    );
556
        
557
    $setting['authorizenet_ipn_url'] = array(
558
            'type' => 'ipn_url',
559
            'id'   => 'authorizenet_ipn_url',
560
            'name' => __( 'Silent Post URL', 'invoicing' ),
561
            'std' => wpinv_get_ipn_url( 'authorizenet' ),
562
            'desc' => __( 'If you are accepting recurring payments then you must set this url at Authorize.Net Account > Settings > Transaction Format Settings > Transaction Response Settings > Silent Post URL.', 'invoicing' ),
563
            'size' => 'large',
564
            'custom' => 'authorizenet',
565
            'readonly' => true
566
        );
567
        
568
    return $setting;
569
}
570
add_filter( 'wpinv_gateway_settings_authorizenet', 'wpinv_gateway_settings_authorizenet', 10, 1 );
571
572
// Worldpay settings
573
function wpinv_gateway_settings_worldpay( $setting ) {
574
    $setting['worldpay_active']['desc'] = $setting['worldpay_active']['desc'] . ' ' . __( '( Supported Currencies: AUD, ARS, CAD, CHF, DKK, EUR, HKD, MYR, GBP, NZD, NOK, SGD, LKR, SEK, TRY, USD, ZAR )', 'invoicing' );
575
    $setting['worldpay_desc']['std'] = __( 'Pay using a Worldpay account to process Credit card / Debit card transactions.', 'invoicing' );
576
    
577
    $setting['worldpay_sandbox'] = array(
578
            'type' => 'checkbox',
579
            'id'   => 'worldpay_sandbox',
580
            'name' => __( 'Worldpay Test Mode', 'invoicing' ),
581
            'desc' => __( 'This provides a special Test Environment to enable you to test your installation and integration to your website before going live.', 'invoicing' ),
582
            'std'  => 1
583
        );
584
        
585
    $setting['worldpay_instId'] = array(
586
            'type' => 'text',
587
            'id'   => 'worldpay_instId',
588
            'name' => __( 'Installation Id', 'invoicing' ),
589
            'desc' => __( 'Your installation id. Ex: 211616', 'invoicing' ),
590
            'std' => '211616',
591
        );
592
    /*
593
    $setting['worldpay_accId1'] = array(
594
            'type' => 'text',
595
            'id'   => 'worldpay_accId1',
596
            'name' => __( 'Merchant Code', 'invoicing' ),
597
            'desc' => __( 'Your merchant code. Ex: 12345', 'invoicing' ),
598
            'std' => '12345',
599
        );
600
    */
601
    
602
    $setting['worldpay_ipn_url'] = array(
603
            'type' => 'ipn_url',
604
            'id'   => 'worldpay_ipn_url',
605
            'name' => __( 'Worldpay Callback Url', 'invoicing' ),
606
            'std' => wpinv_get_ipn_url( 'worldpay' ),
607
            'desc' => wp_sprintf( __( 'Login to your Worldpay Merchant Interface then enable Payment Response & Shopper Response. Next, go to the Payment Response URL field and type "%s" or "%s" for a dynamic payment response.', 'invoicing' ), '<font style="color:#000;font-style:normal">' . wpinv_get_ipn_url( 'worldpay' ) . '</font>', '<font style="color:#000;font-style:normal">&lt;wpdisplay item=MC_callback&gt;</font>' ),
608
            'size' => 'large',
609
            'custom' => 'worldpay',
610
            'readonly' => true
611
        );
612
        
613
    return $setting;
614
}
615
add_filter( 'wpinv_gateway_settings_worldpay', 'wpinv_gateway_settings_worldpay', 10, 1 );
616
617
function wpinv_ipn_url_callback( $args ) {    
618
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
619
    
620
    $attrs = $args['readonly'] ? ' readonly' : '';
621
622
    $html = '<input style="background-color:#fefefe" type="text" ' . $attrs . ' value="' . esc_attr( $args['std'] ) . '" name="wpinv_settings[' . $sanitize_id . ']" id="wpinv_settings[' . $sanitize_id . ']" class="large-text">';
623
    $html .= '<label for="wpinv_settings[' . $sanitize_id . ']">'  . $args['desc'] . '</label>';
624
625
    echo $html;
626
}
627
628
function wpinv_is_test_mode( $gateway = '' ) {
629
    if ( empty( $gateway ) ) {
630
        return false;
631
    }
632
    
633
    $is_test_mode = wpinv_get_option( $gateway . '_sandbox', false );
634
    
635
    return apply_filters( 'wpinv_is_test_mode', $is_test_mode, $gateway );
636
}
637
638
function wpinv_get_ipn_url( $gateway = '', $args = array() ) {
639
    $data = array( 'wpi-listener' => 'IPN' );
640
    
641
    if ( !empty( $gateway ) ) {
642
        $data['wpi-gateway'] = wpinv_sanitize_key( $gateway );
643
    }
644
    
645
    $args = !empty( $args ) && is_array( $args ) ? array_merge( $data, $args ) : $data;
646
    
647
    $ipn_url = add_query_arg( $args,  home_url( 'index.php' ) );
648
    
649
    return apply_filters( 'wpinv_ipn_url', $ipn_url );
650
}
651
652
function wpinv_listen_for_payment_ipn() {
653
    // Regular PayPal IPN
654
    if ( isset( $_GET['wpi-listener'] ) && $_GET['wpi-listener'] == 'IPN' ) {
655
        do_action( 'wpinv_verify_payment_ipn' );
656
        
657
        if ( !empty( $_GET['wpi-gateway'] ) ) {
658
            wpinv_error_log( sanitize_text_field( $_GET['wpi-gateway'] ), 'WP Invoicing IPN', __FILE__, __LINE__ );
659
            do_action( 'wpinv_verify_' . sanitize_text_field( $_GET['wpi-gateway'] ) . '_ipn' );
660
        }
661
    }
662
}
663
add_action( 'init', 'wpinv_listen_for_payment_ipn' );
664
665
function wpinv_get_bank_instructions() {
666
    $bank_instructions = wpinv_get_option( 'bank_transfer_info' );
667
    
668
    return apply_filters( 'wpinv_bank_instructions', $bank_instructions );
669
}
670
671
function wpinv_get_bank_info( $filtered = false ) {
672
    $bank_fields = array(
673
        'bank_transfer_ac_name'     => __( 'Account Name', 'invoicing' ),
674
        'bank_transfer_ac_no'       => __( 'Account Number', 'invoicing' ),
675
        'bank_transfer_bank_name'   => __( 'Bank Name', 'invoicing' ),
676
        'bank_transfer_ifsc'        => __( 'IFSC code', 'invoicing' ),
677
        'bank_transfer_iban'        => __( 'IBAN', 'invoicing' ),
678
        'bank_transfer_bic'         => __( 'BIC/Swift code', 'invoicing' ),
679
        'bank_transfer_sort_code'   => __( 'Sort Code', 'invoicing' )
680
    );
681
    
682
    $bank_info = array();
683
    foreach ( $bank_fields as $field => $label ) {
684
        if ( $filtered && !( $value = wpinv_get_option( $field ) ) ) {
685
            continue;
686
        }
687
        
688
        $bank_info[$field] = array( 'label' => $label, 'value' => $value );
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $value seems to be defined later in this foreach loop on line 684. Are you sure it is defined here?
Loading history...
689
    }
690
    
691
    return apply_filters( 'wpinv_bank_info', $bank_info, $filtered );
692
}
693
694
function wpinv_get_post_data( $method = 'request' ) {
695
    $data       = array();
696
    $request    = $_REQUEST;
697
    
698
    if ( $method == 'post' ) {
699
        if ( isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] != 'POST' ) {
700
            return $data;
701
        }
702
        
703
        $request = $_POST;
704
    }
705
    
706
    if ( $method == 'get' ) {
707
        if ( isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] != 'GET' ) {
708
            return $data;
709
        }
710
        
711
        $request = $_GET;
712
    }
713
    
714
    // Set initial post data to empty string
715
    $post_data = '';
716
    
717
    // Fallback just in case post_max_size is lower than needed
718
    if ( ini_get( 'allow_url_fopen' ) ) {
719
        $post_data = file_get_contents( 'php://input' );
720
    } else {
721
        // If allow_url_fopen is not enabled, then make sure that post_max_size is large enough
722
        ini_set( 'post_max_size', '12M' );
723
    }
724
    // Start the encoded data collection with notification command
725
    $encoded_data = 'cmd=_notify-validate';
726
727
    // Get current arg separator
728
    $arg_separator = wpinv_get_php_arg_separator_output();
729
730
    // Verify there is a post_data
731
    if ( $post_data || strlen( $post_data ) > 0 ) {
732
        // Append the data
733
        $encoded_data .= $arg_separator . $post_data;
734
    } else {
735
        // Check if POST is empty
736
        if ( empty( $request ) ) {
737
            // Nothing to do
738
            return;
739
        } else {
740
            // Loop through each POST
741
            foreach ( $request as $key => $value ) {
742
                // Encode the value and append the data
743
                $encoded_data .= $arg_separator . "$key=" . urlencode( $value );
744
            }
745
        }
746
    }
747
748
    // Convert collected post data to an array
749
    wp_parse_str( $encoded_data, $data );
0 ignored issues
show
Security Variable Injection introduced by
$encoded_data can contain request data and is used in variable name context(s) leading to a potential security vulnerability.

3 paths for user data to reach this point

  1. Path: Read from $_REQUEST, and $_REQUEST is assigned to $request in includes/wpinv-gateway-functions.php on line 696
  1. Read from $_REQUEST, and $_REQUEST is assigned to $request
    in includes/wpinv-gateway-functions.php on line 696
  2. $request is assigned to $value
    in includes/wpinv-gateway-functions.php on line 741
  3. Data is passed through urlencode(), and $arg_separator . $key.'=' . urlencode($value) is assigned to $encoded_data
    in includes/wpinv-gateway-functions.php on line 743
  2. Path: Read from $_GET, and $_GET is assigned to $request in includes/wpinv-gateway-functions.php on line 711
  1. Read from $_GET, and $_GET is assigned to $request
    in includes/wpinv-gateway-functions.php on line 711
  2. $request is assigned to $value
    in includes/wpinv-gateway-functions.php on line 741
  3. Data is passed through urlencode(), and $arg_separator . $key.'=' . urlencode($value) is assigned to $encoded_data
    in includes/wpinv-gateway-functions.php on line 743
  3. Path: Read from $_POST, and $_POST is assigned to $request in includes/wpinv-gateway-functions.php on line 703
  1. Read from $_POST, and $_POST is assigned to $request
    in includes/wpinv-gateway-functions.php on line 703
  2. $request is assigned to $value
    in includes/wpinv-gateway-functions.php on line 741
  3. Data is passed through urlencode(), and $arg_separator . $key.'=' . urlencode($value) is assigned to $encoded_data
    in includes/wpinv-gateway-functions.php on line 743

Used in variable context

  1. wp_parse_str() is called
    in includes/wpinv-gateway-functions.php on line 749
  2. Enters via parameter $string
    in wordpress/wp-includes/formatting.php on line 4925
  3. parse_str() is called
    in wordpress/wp-includes/formatting.php on line 4926

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
750
751
    foreach ( $data as $key => $value ) {
752
        if ( false !== strpos( $key, 'amp;' ) ) {
753
            $new_key = str_replace( '&amp;', '&', $key );
754
            $new_key = str_replace( 'amp;', '&' , $new_key );
755
756
            unset( $data[ $key ] );
757
            $data[ $new_key ] = sanitize_text_field( $value );
758
        }
759
    }
760
    
761
    return $data;
762
}
763
764
/**
765
 * Checks if a given gateway supports subscription payments.
766
 */
767
function wpinv_gateway_support_subscription( $gateway ) {
768
    $supports = false;
769
770
    if ( wpinv_is_gateway_active( $gateway ) ) {
771
        $supports = apply_filters( 'wpinv_' . $gateway . '_support_subscription', $supports );
772
        $supports = apply_filters( 'getapid_gateway_supports_subscription', $supports, $gateway );
773
    }
774
775
    return $supports;
776
}
777
778
/**
779
 * Filters payment form gateways.
780
 * 
781
 * @param array $gateways an array of gateways.
782
 * @param GetPaid_Payment_Form $form payment form.
783
 */
784
function wpinv_payment_gateways_on_cart( $gateways, $form ) {
785
786
    if ( $form->is_recurring() ) {
787
788
        foreach ( array_keys( $gateways ) as $gateway ) {
789
790
            if ( ! wpinv_gateway_support_subscription( $gateway ) ) {
791
                unset( $gateways[$gateway] );
792
            }
793
794
        }
795
796
    }
797
798
    return $gateways;
799
}
800
add_filter( 'getpaid_payment_form_gateways', 'wpinv_payment_gateways_on_cart', 10, 2 );
801
802
function wpinv_validate_checkout_fields() {
803
    // Check if there is $_POST
804
    if ( empty( $_POST ) ) {
805
        return false;
806
    }
807
808
    // Start an array to collect valid data
809
    $valid_data = array(
810
        'gateway'          => wpinv_checkout_validate_gateway(), // Gateway fallback
811
        'discount'         => wpinv_checkout_validate_discounts(), // Set default discount
812
        'cc_info'          => wpinv_checkout_validate_cc() // Credit card info
813
    );
814
815
    $valid_data['invoice_user'] = wpinv_checkout_validate_invoice_user();
816
    $valid_data['current_user'] = wpinv_checkout_validate_current_user();
817
818
    // Return collected data
819
    return $valid_data;
820
}
821
822
function wpinv_checkout_validate_gateway() {
823
    $gateway = wpinv_get_default_gateway();
824
    
825
    $invoice = wpinv_get_invoice_cart();
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_get_invoice_cart() has been deprecated. ( Ignorable by Annotation )

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

825
    $invoice = /** @scrutinizer ignore-deprecated */ wpinv_get_invoice_cart();
Loading history...
826
    $has_subscription = $invoice->is_recurring();
827
    if ( empty( $invoice ) ) {
828
        wpinv_set_error( 'invalid_invoice', __( 'Your cart is empty.', 'invoicing' ) );
829
        return $gateway;
830
    }
831
832
    // Check if a gateway value is present
833
    if ( !empty( $_REQUEST['wpi-gateway'] ) ) {
834
        $gateway = sanitize_text_field( $_REQUEST['wpi-gateway'] );
835
836
        if ( $invoice->is_free() ) {
837
            $gateway = 'manual';
838
        } elseif ( !wpinv_is_gateway_active( $gateway ) ) {
839
            wpinv_set_error( 'invalid_gateway', __( 'The selected payment gateway is not enabled', 'invoicing' ) );
840
        } elseif ( $has_subscription && !wpinv_gateway_support_subscription( $gateway ) ) {
841
            if ( apply_filters( 'wpinv_reject_non_recurring_gateway', true ) ) {
842
                wpinv_set_error( 'invalid_gateway', __( 'The selected payment gateway does not support subscription payment', 'invoicing' ) );
843
            }
844
        }
845
    }
846
847
    if ( $has_subscription && count( wpinv_get_cart_contents() ) > 1 ) {
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_get_cart_contents() has been deprecated. ( Ignorable by Annotation )

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

847
    if ( $has_subscription && count( /** @scrutinizer ignore-deprecated */ wpinv_get_cart_contents() ) > 1 ) {
Loading history...
848
        wpinv_set_error( 'subscription_invalid', __( 'Only one subscription may be purchased through payment per checkout.', 'invoicing' ) );
849
    }
850
851
    return $gateway;
852
}
853
854
function wpinv_checkout_validate_discounts() {
855
    global $wpi_cart;
856
    
857
    // Retrieve the discount stored in cookies
858
    $discounts = wpinv_get_cart_discounts();
859
860
    if ( ! is_array( $discounts ) ) {
861
        return NULL;
862
    }
863
864
    $discounts = array_filter( $discounts );
865
    $error    = false;
866
867
    if ( empty( $discounts ) ) {
868
        return NULL;
869
    }
870
871
    // If we have discounts, loop through them
872
    foreach ( $discounts as $discount ) {
873
        // Check if valid
874
        if (  ! wpinv_is_discount_valid( $discount, (int) $wpi_cart->get_user_id() ) ) {
875
            // Discount is not valid
876
            $error = true;
877
        }
878
879
    }
880
881
    if ( $error && ! wpinv_get_errors() ) {
882
        wpinv_set_error( 'invalid_discount', __( 'Discount code you entered is invalid', 'invoicing' ) );
883
    }
884
885
    return implode( ',', $discounts );
886
}
887
888
function wpinv_checkout_validate_cc() {
889
    $card_data = wpinv_checkout_get_cc_info();
890
891
    // Validate the card zip
892
    if ( !empty( $card_data['wpinv_zip'] ) ) {
893
        if ( !wpinv_checkout_validate_cc_zip( $card_data['wpinv_zip'], $card_data['wpinv_country'] ) ) {
894
            wpinv_set_error( 'invalid_cc_zip', __( 'The zip / postcode you entered for your billing address is invalid', 'invoicing' ) );
895
        }
896
    }
897
898
    // This should validate card numbers at some point too
899
    return $card_data;
900
}
901
902
function wpinv_checkout_get_cc_info() {
903
	$cc_info = array();
904
	$cc_info['card_name']      = isset( $_POST['card_name'] )       ? sanitize_text_field( $_POST['card_name'] )       : '';
905
	$cc_info['card_number']    = isset( $_POST['card_number'] )     ? sanitize_text_field( $_POST['card_number'] )     : '';
906
	$cc_info['card_cvc']       = isset( $_POST['card_cvc'] )        ? sanitize_text_field( $_POST['card_cvc'] )        : '';
907
	$cc_info['card_exp_month'] = isset( $_POST['card_exp_month'] )  ? sanitize_text_field( $_POST['card_exp_month'] )  : '';
908
	$cc_info['card_exp_year']  = isset( $_POST['card_exp_year'] )   ? sanitize_text_field( $_POST['card_exp_year'] )   : '';
909
	$cc_info['card_address']   = isset( $_POST['wpinv_address'] )  ? sanitize_text_field( $_POST['wpinv_address'] ) : '';
910
	$cc_info['card_city']      = isset( $_POST['wpinv_city'] )     ? sanitize_text_field( $_POST['wpinv_city'] )    : '';
911
	$cc_info['card_state']     = isset( $_POST['wpinv_state'] )    ? sanitize_text_field( $_POST['wpinv_state'] )   : '';
912
	$cc_info['card_country']   = isset( $_POST['wpinv_country'] )  ? sanitize_text_field( $_POST['wpinv_country'] ) : '';
913
	$cc_info['card_zip']       = isset( $_POST['wpinv_zip'] )      ? sanitize_text_field( $_POST['wpinv_zip'] )     : '';
914
915
	// Return cc info
916
	return $cc_info;
917
}
918
919
/**
920
 * Validates a zip code.
921
 */
922
function wpinv_checkout_validate_cc_zip( $zip = 0, $country_code = '' ) {
923
924
    if ( empty( $zip ) || empty( $country_code ) ){
925
        return false;
926
    }
927
928
    // Prepare the country code.
929
    $country_code = strtoupper( trim( $country_code ) );
930
931
    // Fetch the regexes.
932
    $zip_regex = wpinv_get_data( 'zip-regexes' );
933
934
    // Check if it is valid.
935
    $is_valid = ! isset ( $zip_regex[ $country_code ] ) || preg_match( "/" . $zip_regex[ $country_code ] . "/i", $zip );
936
937
    return apply_filters( 'wpinv_is_zip_valid', $is_valid, $zip, $country_code );
938
}
939
940
function wpinv_checkout_validate_agree_to_terms() {
941
    // Validate agree to terms
942
    if ( ! isset( $_POST['wpi_agree_to_terms'] ) || $_POST['wpi_agree_to_terms'] != 1 ) {
943
        // User did not agree
944
        wpinv_set_error( 'agree_to_terms', apply_filters( 'wpinv_agree_to_terms_text', __( 'You must agree to the terms of use', 'invoicing' ) ) );
945
    }
946
}
947
948
function wpinv_checkout_validate_invoice_user() {
949
    global $wpi_cart, $user_ID;
950
951
    if(empty($wpi_cart)){
952
        $wpi_cart = wpinv_get_invoice_cart();
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_get_invoice_cart() has been deprecated. ( Ignorable by Annotation )

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

952
        $wpi_cart = /** @scrutinizer ignore-deprecated */ wpinv_get_invoice_cart();
Loading history...
953
    }
954
955
    $invoice_user = (int)$wpi_cart->get_user_id();
956
    $valid_user_data = array(
957
        'user_id' => $invoice_user
958
    );
959
960
    // If guest checkout allowed
961
    if ( !wpinv_require_login_to_checkout() ) {
962
        return $valid_user_data;
963
    }
964
    
965
    // Verify there is a user_ID
966
    if ( $user_ID == $invoice_user ) {
967
        // Get the logged in user data
968
        $user_data = get_userdata( $user_ID );
969
        $required_fields  = wpinv_checkout_required_fields();
970
971
        // Loop through required fields and show error messages
972
         if ( !empty( $required_fields ) ) {
973
            foreach ( $required_fields as $field_name => $value ) {
974
                if ( in_array( $value, $required_fields ) && empty( $_POST[ 'wpinv_' . $field_name ] ) ) {
975
                    wpinv_set_error( $value['error_id'], $value['error_message'] );
976
                }
977
            }
978
        }
979
980
        // Verify data
981
        if ( $user_data ) {
982
            // Collected logged in user data
983
            $valid_user_data = array(
984
                'user_id'     => $user_ID,
985
                'email'       => isset( $_POST['wpinv_email'] ) ? sanitize_email( $_POST['wpinv_email'] ) : $user_data->user_email,
986
                'first_name'  => isset( $_POST['wpinv_first_name'] ) && ! empty( $_POST['wpinv_first_name'] ) ? sanitize_text_field( $_POST['wpinv_first_name'] ) : $user_data->first_name,
987
                'last_name'   => isset( $_POST['wpinv_last_name'] ) && ! empty( $_POST['wpinv_last_name']  ) ? sanitize_text_field( $_POST['wpinv_last_name']  ) : $user_data->last_name,
988
            );
989
990
            if ( !empty( $_POST[ 'wpinv_email' ] ) && !is_email( $_POST[ 'wpinv_email' ] ) ) {
991
                wpinv_set_error( 'invalid_email', __( 'Please enter a valid email address', 'invoicing' ) );
992
            }
993
        } else {
994
            // Set invalid user error
995
            wpinv_set_error( 'invalid_user', __( 'The user billing information is invalid', 'invoicing' ) );
996
        }
997
    } else {
998
        // Set invalid user error
999
        wpinv_set_error( 'invalid_user_id', __( 'The invalid invoice user id', 'invoicing' ) );
1000
    }
1001
1002
    // Return user data
1003
    return $valid_user_data;
1004
}
1005
1006
function wpinv_checkout_validate_current_user() {
1007
    global $wpi_cart;
1008
1009
    $data = array();
1010
    
1011
    if ( is_user_logged_in() ) {
1012
        if ( !wpinv_require_login_to_checkout() || ( wpinv_require_login_to_checkout() && (int)$wpi_cart->get_user_id() === (int)get_current_user_id() ) ) {
1013
            $data['user_id'] = (int)get_current_user_id();
1014
        } else {
1015
            wpinv_set_error( 'logged_in_only', __( 'You are not allowed to pay for this invoice', 'invoicing' ) );
1016
        }
1017
    } else {
1018
        // If guest checkout allowed
1019
        if ( !wpinv_require_login_to_checkout() ) {
1020
            $data['user_id'] = 0;
1021
        } else {
1022
            wpinv_set_error( 'logged_in_only', __( 'You must be logged in to pay for this invoice', 'invoicing' ) );
1023
        }
1024
    }
1025
1026
    return $data;
1027
}
1028
1029
function wpinv_checkout_form_get_user( $valid_data = array() ) {
1030
1031
    if ( !empty( $valid_data['current_user']['user_id'] ) ) {
1032
        $user = $valid_data['current_user'];
1033
    } else {
1034
        // Set the valid invoice user
1035
        $user = $valid_data['invoice_user'];
1036
    }
1037
1038
    // Verify invoice have an user
1039
    if ( false === $user || empty( $user ) ) {
1040
        return false;
1041
    }
1042
1043
    $address_fields = array(
1044
        'first_name',
1045
        'last_name',
1046
        'company',
1047
        'vat_number',
1048
        'phone',
1049
        'address',
1050
        'city',
1051
        'state',
1052
        'country',
1053
        'zip',
1054
    );
1055
    
1056
    foreach ( $address_fields as $field ) {
1057
        $user[$field]  = !empty( $_POST['wpinv_' . $field] ) ? sanitize_text_field( $_POST['wpinv_' . $field] ) : false;
1058
        
1059
        if ( !empty( $user['user_id'] ) && !empty( $valid_data['current_user']['user_id'] ) && $valid_data['current_user']['user_id'] == $valid_data['invoice_user']['user_id'] ) {
1060
            update_user_meta( $user['user_id'], '_wpinv_' . $field, $user[$field] );
1061
        }
1062
    }
1063
1064
    // Return valid user
1065
    return $user;
1066
}
1067
1068
function wpinv_process_checkout() {
1069
    global $wpinv_euvat, $wpi_checkout_id, $wpi_cart;
1070
1071
    wpinv_clear_errors();
1072
1073
    $invoice = wpinv_get_invoice_cart();
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_get_invoice_cart() has been deprecated. ( Ignorable by Annotation )

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

1073
    $invoice = /** @scrutinizer ignore-deprecated */ wpinv_get_invoice_cart();
Loading history...
1074
    if ( empty( $invoice ) ) {
1075
        return false;
1076
    }
1077
1078
    $wpi_cart = $invoice;
1079
1080
    $wpi_checkout_id = $invoice->ID;
1081
1082
    do_action( 'wpinv_pre_process_checkout' );
1083
    
1084
    if ( !wpinv_get_cart_contents() ) { // Make sure the cart isn't empty
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_get_cart_contents() has been deprecated. ( Ignorable by Annotation )

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

1084
    if ( !/** @scrutinizer ignore-deprecated */ wpinv_get_cart_contents() ) { // Make sure the cart isn't empty
Loading history...
1085
        $valid_data = false;
1086
        wpinv_set_error( 'empty_cart', __( 'Your cart is empty', 'invoicing' ) );
1087
    } else {
1088
        // Validate the form $_POST data
1089
        $valid_data = wpinv_validate_checkout_fields();
1090
        
1091
        // Allow themes and plugins to hook to errors
1092
        do_action( 'wpinv_checkout_error_checks', $valid_data, $_POST );
1093
    }
1094
    
1095
    $is_ajax    = defined( 'DOING_AJAX' ) && DOING_AJAX;
1096
    
1097
    // Validate the user
1098
    $user = wpinv_checkout_form_get_user( $valid_data );
1099
1100
    // Let extensions validate fields after user is logged in if user has used login/registration form
1101
    do_action( 'wpinv_checkout_user_error_checks', $user, $valid_data, $_POST );
1102
    
1103
    if ( false === $valid_data || wpinv_get_errors() || ! $user ) {
1104
        if ( $is_ajax && 'wpinv_payment_form' != $_REQUEST['action'] ) {
1105
            do_action( 'wpinv_ajax_checkout_errors' );
1106
            die();
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...
1107
        } else {
1108
            return false;
1109
        }
1110
    }
1111
1112
    if ( $is_ajax && 'wpinv_payment_form' != $_REQUEST['action'] ) {
1113
        // Save address fields.
1114
        $address_fields = array( 'first_name', 'last_name', 'phone', 'address', 'city', 'country', 'state', 'zip', 'company' );
1115
        foreach ( $address_fields as $field ) {
1116
            if ( isset( $user[$field] ) ) {
1117
                $invoice->set( $field, $user[$field] );
1118
            }
1119
1120
            $invoice->save();
1121
        }
1122
1123
        $response['success']            = true;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$response was never initialized. Although not strictly required by PHP, it is generally a good practice to add $response = array(); before regardless.
Loading history...
1124
        $response['data']['subtotal']   = $invoice->get_subtotal();
1125
        $response['data']['subtotalf']  = $invoice->get_subtotal( true );
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $context of WPInv_Invoice::get_subtotal(). ( Ignorable by Annotation )

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

1125
        $response['data']['subtotalf']  = $invoice->get_subtotal( /** @scrutinizer ignore-type */ true );
Loading history...
1126
        $response['data']['discount']   = $invoice->get_discount();
1127
        $response['data']['discountf']  = $invoice->get_discount( true );
1128
        $response['data']['tax']        = $invoice->get_tax();
0 ignored issues
show
Bug introduced by
The call to WPInv_Invoice::get_tax() has too few arguments starting with tax. ( Ignorable by Annotation )

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

1128
        /** @scrutinizer ignore-call */ 
1129
        $response['data']['tax']        = $invoice->get_tax();

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

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

Loading history...
1129
        $response['data']['taxf']       = $invoice->get_tax( true );
1130
        $response['data']['total']      = $invoice->get_total();
1131
        $response['data']['totalf']     = $invoice->get_total( true );
0 ignored issues
show
Unused Code introduced by
The call to WPInv_Invoice::get_total() has too many arguments starting with true. ( Ignorable by Annotation )

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

1131
        /** @scrutinizer ignore-call */ 
1132
        $response['data']['totalf']     = $invoice->get_total( true );

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...
1132
	    $response['data']['free']       = $invoice->is_free() && ( ! ( (float) $response['data']['total'] > 0 ) || $invoice->has_free_trial() ) ? true : false;
1133
1134
        wp_send_json( $response );
1135
    }
1136
    
1137
    $user_info = array(
1138
        'user_id'        => $user['user_id'],
1139
        'first_name'     => $user['first_name'],
1140
        'last_name'      => $user['last_name'],
1141
        'email'          => $invoice->get_email(),
1142
        'company'        => $user['company'],
1143
        'phone'          => $user['phone'],
1144
        'address'        => $user['address'],
1145
        'city'           => $user['city'],
1146
        'country'        => $user['country'],
1147
        'state'          => $user['state'],
1148
        'zip'            => $user['zip'],
1149
    );
1150
    
1151
    $cart_items = wpinv_get_cart_contents();
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_get_cart_contents() has been deprecated. ( Ignorable by Annotation )

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

1151
    $cart_items = /** @scrutinizer ignore-deprecated */ wpinv_get_cart_contents();
Loading history...
1152
    $discounts  = wpinv_get_cart_discounts();
1153
    
1154
    // Setup invoice information
1155
    $invoice_data = array(
1156
        'invoice_id'        => !empty( $invoice ) ? $invoice->ID : 0,
1157
        'items'             => $cart_items,
1158
        'cart_discounts'    => $discounts,
1159
        'fees'              => wpinv_get_cart_fees(),        // Any arbitrary fees that have been added to the cart
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_get_cart_fees() has been deprecated. ( Ignorable by Annotation )

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

1159
        'fees'              => /** @scrutinizer ignore-deprecated */ wpinv_get_cart_fees(),        // Any arbitrary fees that have been added to the cart
Loading history...
1160
        'subtotal'          => wpinv_get_cart_subtotal( $cart_items ),    // Amount before taxes and discounts
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_get_cart_subtotal() has been deprecated. ( Ignorable by Annotation )

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

1160
        'subtotal'          => /** @scrutinizer ignore-deprecated */ wpinv_get_cart_subtotal( $cart_items ),    // Amount before taxes and discounts
Loading history...
Unused Code introduced by
The call to wpinv_get_cart_subtotal() has too many arguments starting with $cart_items. ( Ignorable by Annotation )

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

1160
        'subtotal'          => /** @scrutinizer ignore-call */ wpinv_get_cart_subtotal( $cart_items ),    // Amount before taxes and discounts

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...
1161
        'discount'          => wpinv_get_cart_items_discount_amount( $cart_items, $discounts ), // Discounted amount
1162
        'tax'               => wpinv_get_cart_tax( $cart_items, $invoice ),               // Taxed amount
0 ignored issues
show
Unused Code introduced by
The call to wpinv_get_cart_tax() has too many arguments starting with $cart_items. ( Ignorable by Annotation )

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

1162
        'tax'               => /** @scrutinizer ignore-call */ wpinv_get_cart_tax( $cart_items, $invoice ),               // Taxed amount

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...
Deprecated Code introduced by
The function wpinv_get_cart_tax() has been deprecated. ( Ignorable by Annotation )

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

1162
        'tax'               => /** @scrutinizer ignore-deprecated */ wpinv_get_cart_tax( $cart_items, $invoice ),               // Taxed amount
Loading history...
1163
        'price'             => wpinv_get_cart_total( $cart_items, $discounts ),    // Amount after taxes
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_get_cart_total() has been deprecated. ( Ignorable by Annotation )

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

1163
        'price'             => /** @scrutinizer ignore-deprecated */ wpinv_get_cart_total( $cart_items, $discounts ),    // Amount after taxes
Loading history...
Unused Code introduced by
The call to wpinv_get_cart_total() has too many arguments starting with $cart_items. ( Ignorable by Annotation )

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

1163
        'price'             => /** @scrutinizer ignore-call */ wpinv_get_cart_total( $cart_items, $discounts ),    // Amount after taxes

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...
1164
        'invoice_key'       => $invoice->get_key() ? $invoice->get_key() : $invoice->generate_key(),
1165
        'user_email'        => $invoice->get_email(),
1166
        'date'              => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ),
1167
        'user_info'         => stripslashes_deep( $user_info ),
1168
        'post_data'         => $_POST,
1169
        'cart_details'      => $cart_items,
1170
        'gateway'           => $valid_data['gateway'],
1171
        'card_info'         => $valid_data['cc_info']
1172
    );
1173
    
1174
    $vat_info   = $wpinv_euvat->current_vat_data();
1175
    if ( is_array( $vat_info ) ) {
1176
        $invoice_data['user_info']['vat_number']        = $vat_info['number'];
1177
        $invoice_data['user_info']['vat_rate']          = wpinv_get_tax_rate($invoice_data['user_info']['country'], $invoice_data['user_info']['state']);
1178
        $invoice_data['user_info']['adddress_confirmed']    = isset($vat_info['adddress_confirmed']) ? $vat_info['adddress_confirmed'] : false;
1179
1180
        // Add the VAT rate to each item in the cart
1181
        foreach( $invoice_data['cart_details'] as $key => $item_data) {
1182
            $rate = wpinv_get_tax_rate($invoice_data['user_info']['country'], $invoice_data['user_info']['state'], $item_data['id']);
1183
            $invoice_data['cart_details'][$key]['vat_rate'] = wpinv_round_amount( $rate, 4 );
1184
        }
1185
    }
1186
    
1187
    // Save vat fields.
1188
    $address_fields = array( 'vat_number', 'vat_rate', 'adddress_confirmed' );
1189
    foreach ( $address_fields as $field ) {
1190
        if ( isset( $invoice_data['user_info'][$field] ) ) {
1191
            $invoice->set( $field, $invoice_data['user_info'][$field] );
1192
        }
1193
    }
1194
    $invoice->save();
1195
1196
    // Add the user data for hooks
1197
    $valid_data['user'] = $user;
1198
    
1199
    // Allow themes and plugins to hook before the gateway
1200
    do_action( 'wpinv_checkout_before_gateway', $_POST, $user_info, $valid_data );
1201
1202
     // If it is free, abort.
1203
     if ( $invoice->is_free() && ( ! $invoice->is_recurring() || 0 ==  $invoice->get_recurring_details( 'total' ) ) ) {
1204
        $invoice_data['gateway'] = 'manual';
1205
        $_POST['wpi-gateway'] = 'manual';
1206
    }
1207
1208
    // Allow the invoice data to be modified before it is sent to the gateway
1209
    $invoice_data = apply_filters( 'wpinv_data_before_gateway', $invoice_data, $valid_data );
1210
    
1211
    if ( $invoice_data['price'] && $invoice_data['gateway'] == 'manual' ) {
1212
        $mode = 'test';
1213
    } else {
1214
        $mode = wpinv_is_test_mode( $invoice_data['gateway'] ) ? 'test' : 'live';
1215
    }
1216
1217
    // Setup the data we're storing in the purchase session
1218
    $session_data = $invoice_data;
1219
    // Make sure credit card numbers are never stored in sessions
1220
    if ( !empty( $session_data['card_info']['card_number'] ) ) {
1221
        unset( $session_data['card_info']['card_number'] );
1222
    }
1223
    
1224
    // Used for showing item links to non logged-in users after purchase, and for other plugins needing purchase data.
1225
    wpinv_set_checkout_session( $invoice_data );
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_set_checkout_session() has been deprecated. ( Ignorable by Annotation )

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

1225
    /** @scrutinizer ignore-deprecated */ wpinv_set_checkout_session( $invoice_data );
Loading history...
Unused Code introduced by
The call to wpinv_set_checkout_session() has too many arguments starting with $invoice_data. ( Ignorable by Annotation )

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

1225
    /** @scrutinizer ignore-call */ 
1226
    wpinv_set_checkout_session( $invoice_data );

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...
1226
    
1227
    // Set gateway
1228
    $invoice->update_meta( '_wpinv_gateway', $invoice_data['gateway'] );
0 ignored issues
show
Bug introduced by
The method update_meta() does not exist on WPInv_Invoice. Did you maybe mean update_meta_data()? ( Ignorable by Annotation )

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

1228
    $invoice->/** @scrutinizer ignore-call */ 
1229
              update_meta( '_wpinv_gateway', $invoice_data['gateway'] );

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

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

Loading history...
1229
    $invoice->update_meta( '_wpinv_mode', $mode );
1230
    $invoice->update_meta( '_wpinv_checkout', date_i18n( 'Y-m-d H:i:s', current_time( 'timestamp' ) ) );
1231
    
1232
    do_action( 'wpinv_checkout_before_send_to_gateway', $invoice, $invoice_data );
1233
1234
    // Send info to the gateway for payment processing
1235
    wpinv_send_to_gateway( $invoice_data['gateway'], $invoice_data );
1236
    die();
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...
1237
}
1238
add_action( 'wpinv_payment', 'wpinv_process_checkout' );
1239