@@ -976,67 +976,67 @@ |
||
| 976 | 976 | function wpinv_tool_merge_fix_taxes() { |
| 977 | 977 | global $wpdb; |
| 978 | 978 | |
| 979 | - $sql = "SELECT DISTINCT p.ID FROM `" . $wpdb->posts . "` AS p LEFT JOIN " . $wpdb->postmeta . " AS pm ON pm.post_id = p.ID WHERE p.post_type = 'wpi_item' AND pm.meta_key = '_wpinv_type' AND pm.meta_value = 'package'"; |
|
| 980 | - $items = $wpdb->get_results( $sql ); |
|
| 979 | + $sql = "SELECT DISTINCT p.ID FROM `" . $wpdb->posts . "` AS p LEFT JOIN " . $wpdb->postmeta . " AS pm ON pm.post_id = p.ID WHERE p.post_type = 'wpi_item' AND pm.meta_key = '_wpinv_type' AND pm.meta_value = 'package'"; |
|
| 980 | + $items = $wpdb->get_results( $sql ); |
|
| 981 | 981 | |
| 982 | - if ( !empty( $items ) ) { |
|
| 983 | - foreach ( $items as $item ) { |
|
| 984 | - if ( get_post_meta( $item->ID, '_wpinv_vat_class', true ) == '_exempt' ) { |
|
| 985 | - update_post_meta( $item->ID, '_wpinv_vat_class', '_standard' ); |
|
| 986 | - } |
|
| 987 | - } |
|
| 988 | - } |
|
| 982 | + if ( !empty( $items ) ) { |
|
| 983 | + foreach ( $items as $item ) { |
|
| 984 | + if ( get_post_meta( $item->ID, '_wpinv_vat_class', true ) == '_exempt' ) { |
|
| 985 | + update_post_meta( $item->ID, '_wpinv_vat_class', '_standard' ); |
|
| 986 | + } |
|
| 987 | + } |
|
| 988 | + } |
|
| 989 | 989 | |
| 990 | 990 | $sql = "SELECT `p`.`ID`, gdi.id AS gdp_id FROM `" . INVOICE_TABLE . "` AS gdi LEFT JOIN `" . $wpdb->posts . "` AS p ON `p`.`ID` = `gdi`.`invoice_id` AND `p`.`post_type` = 'wpi_invoice' WHERE `p`.`ID` IS NOT NULL AND p.post_status NOT IN( 'publish', 'wpi-processing', 'wpi-renewal' ) ORDER BY `gdi`.`id` ASC"; |
| 991 | 991 | $items = $wpdb->get_results( $sql ); |
| 992 | 992 | |
| 993 | - if ( !empty( $items ) ) { |
|
| 994 | - $success = false; |
|
| 993 | + if ( !empty( $items ) ) { |
|
| 994 | + $success = false; |
|
| 995 | 995 | $message = __( 'Taxes fixed for non-paid merged GD invoices.', 'invoicing' ); |
| 996 | 996 | |
| 997 | - global $wpi_userID, $wpinv_ip_address_country, $wpi_tax_rates; |
|
| 997 | + global $wpi_userID, $wpinv_ip_address_country, $wpi_tax_rates; |
|
| 998 | 998 | |
| 999 | - foreach ( $items as $item ) { |
|
| 1000 | - $wpi_tax_rates = NULL; |
|
| 1001 | - $data = wpinv_get_invoice($item->ID); |
|
| 999 | + foreach ( $items as $item ) { |
|
| 1000 | + $wpi_tax_rates = NULL; |
|
| 1001 | + $data = wpinv_get_invoice($item->ID); |
|
| 1002 | 1002 | |
| 1003 | - if ( empty( $data ) ) { |
|
| 1004 | - continue; |
|
| 1005 | - } |
|
| 1003 | + if ( empty( $data ) ) { |
|
| 1004 | + continue; |
|
| 1005 | + } |
|
| 1006 | 1006 | |
| 1007 | - $checkout_session = wpinv_get_checkout_session(); |
|
| 1007 | + $checkout_session = wpinv_get_checkout_session(); |
|
| 1008 | 1008 | |
| 1009 | - $data_session = array(); |
|
| 1010 | - $data_session['invoice_id'] = $data->ID; |
|
| 1011 | - $data_session['cart_discounts'] = $data->get_discounts( true ); |
|
| 1009 | + $data_session = array(); |
|
| 1010 | + $data_session['invoice_id'] = $data->ID; |
|
| 1011 | + $data_session['cart_discounts'] = $data->get_discounts( true ); |
|
| 1012 | 1012 | |
| 1013 | - wpinv_set_checkout_session( $data_session ); |
|
| 1013 | + wpinv_set_checkout_session( $data_session ); |
|
| 1014 | 1014 | |
| 1015 | - $wpi_userID = (int)$data->get_user_id(); |
|
| 1016 | - $_POST['country'] = !empty($data->country) ? $data->country : wpinv_get_default_country(); |
|
| 1015 | + $wpi_userID = (int)$data->get_user_id(); |
|
| 1016 | + $_POST['country'] = !empty($data->country) ? $data->country : wpinv_get_default_country(); |
|
| 1017 | 1017 | |
| 1018 | - $data->country = sanitize_text_field( $_POST['country'] ); |
|
| 1019 | - $data->set( 'country', sanitize_text_field( $_POST['country'] ) ); |
|
| 1018 | + $data->country = sanitize_text_field( $_POST['country'] ); |
|
| 1019 | + $data->set( 'country', sanitize_text_field( $_POST['country'] ) ); |
|
| 1020 | 1020 | |
| 1021 | - $wpinv_ip_address_country = $data->country; |
|
| 1021 | + $wpinv_ip_address_country = $data->country; |
|
| 1022 | 1022 | |
| 1023 | - $data->recalculate_totals(true); |
|
| 1023 | + $data->recalculate_totals(true); |
|
| 1024 | 1024 | |
| 1025 | - wpinv_set_checkout_session( $checkout_session ); |
|
| 1025 | + wpinv_set_checkout_session( $checkout_session ); |
|
| 1026 | 1026 | |
| 1027 | - $update_data = array(); |
|
| 1028 | - $update_data['tax_amount'] = $data->get_tax(); |
|
| 1029 | - $update_data['paied_amount'] = $data->get_total(); |
|
| 1030 | - $update_data['invoice_id'] = $data->ID; |
|
| 1027 | + $update_data = array(); |
|
| 1028 | + $update_data['tax_amount'] = $data->get_tax(); |
|
| 1029 | + $update_data['paied_amount'] = $data->get_total(); |
|
| 1030 | + $update_data['invoice_id'] = $data->ID; |
|
| 1031 | 1031 | |
| 1032 | - $wpdb->update( INVOICE_TABLE, $update_data, array( 'id' => $item->gdp_id ) ); |
|
| 1033 | - } |
|
| 1034 | - } else { |
|
| 1032 | + $wpdb->update( INVOICE_TABLE, $update_data, array( 'id' => $item->gdp_id ) ); |
|
| 1033 | + } |
|
| 1034 | + } else { |
|
| 1035 | 1035 | $success = false; |
| 1036 | 1036 | $message = __( 'No invoices found to fix taxes!', 'invoicing' ); |
| 1037 | 1037 | } |
| 1038 | 1038 | |
| 1039 | - $response = array(); |
|
| 1039 | + $response = array(); |
|
| 1040 | 1040 | $response['success'] = $success; |
| 1041 | 1041 | $response['data']['message'] = $message; |
| 1042 | 1042 | wp_send_json( $response ); |
@@ -65,7 +65,7 @@ discard block |
||
| 65 | 65 | 'notify_url' => $listener_url, |
| 66 | 66 | 'cbt' => get_bloginfo( 'name' ), |
| 67 | 67 | 'bn' => 'WPInvoicing_SP', |
| 68 | - 'lc' => 'US' // this will force paypal site to english |
|
| 68 | + 'lc' => 'US' // this will force paypal site to english |
|
| 69 | 69 | ); |
| 70 | 70 | |
| 71 | 71 | $paypal_args['address1'] = $invoice->get_address(); |
@@ -217,261 +217,261 @@ discard block |
||
| 217 | 217 | add_filter( 'wpinv_paypal_args', 'wpinv_get_paypal_recurring_args', 10, 3 ); |
| 218 | 218 | |
| 219 | 219 | function wpinv_process_paypal_ipn() { |
| 220 | - // Check the request method is POST |
|
| 221 | - if ( isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] != 'POST' ) { |
|
| 222 | - return; |
|
| 223 | - } |
|
| 224 | - |
|
| 225 | - // Set initial post data to empty string |
|
| 226 | - $post_data = ''; |
|
| 227 | - |
|
| 228 | - // Fallback just in case post_max_size is lower than needed |
|
| 229 | - if ( ini_get( 'allow_url_fopen' ) ) { |
|
| 230 | - $post_data = file_get_contents( 'php://input' ); |
|
| 231 | - } else { |
|
| 232 | - // If allow_url_fopen is not enabled, then make sure that post_max_size is large enough |
|
| 233 | - ini_set( 'post_max_size', '12M' ); |
|
| 234 | - } |
|
| 235 | - // Start the encoded data collection with notification command |
|
| 236 | - $encoded_data = 'cmd=_notify-validate'; |
|
| 237 | - |
|
| 238 | - // Get current arg separator |
|
| 239 | - $arg_separator = wpinv_get_php_arg_separator_output(); |
|
| 240 | - |
|
| 241 | - // Verify there is a post_data |
|
| 242 | - if ( $post_data || strlen( $post_data ) > 0 ) { |
|
| 243 | - // Append the data |
|
| 244 | - $encoded_data .= $arg_separator.$post_data; |
|
| 245 | - } else { |
|
| 246 | - // Check if POST is empty |
|
| 247 | - if ( empty( $_POST ) ) { |
|
| 248 | - // Nothing to do |
|
| 249 | - return; |
|
| 250 | - } else { |
|
| 251 | - // Loop through each POST |
|
| 252 | - foreach ( $_POST as $key => $value ) { |
|
| 253 | - // Encode the value and append the data |
|
| 254 | - $encoded_data .= $arg_separator."$key=" . urlencode( $value ); |
|
| 255 | - } |
|
| 256 | - } |
|
| 257 | - } |
|
| 258 | - |
|
| 259 | - // Convert collected post data to an array |
|
| 260 | - parse_str( $encoded_data, $encoded_data_array ); |
|
| 261 | - |
|
| 262 | - foreach ( $encoded_data_array as $key => $value ) { |
|
| 263 | - if ( false !== strpos( $key, 'amp;' ) ) { |
|
| 264 | - $new_key = str_replace( '&', '&', $key ); |
|
| 265 | - $new_key = str_replace( 'amp;', '&' , $new_key ); |
|
| 266 | - |
|
| 267 | - unset( $encoded_data_array[ $key ] ); |
|
| 268 | - $encoded_data_array[ $new_key ] = $value; |
|
| 269 | - } |
|
| 270 | - } |
|
| 271 | - |
|
| 272 | - // Get the PayPal redirect uri |
|
| 273 | - $paypal_redirect = wpinv_get_paypal_redirect( true ); |
|
| 274 | - |
|
| 275 | - if ( !wpinv_get_option( 'disable_paypal_verification', false ) ) { |
|
| 276 | - // Validate the IPN |
|
| 277 | - |
|
| 278 | - $remote_post_vars = array( |
|
| 279 | - 'method' => 'POST', |
|
| 280 | - 'timeout' => 45, |
|
| 281 | - 'redirection' => 5, |
|
| 282 | - 'httpversion' => '1.1', |
|
| 283 | - 'blocking' => true, |
|
| 284 | - 'headers' => array( |
|
| 285 | - 'host' => 'www.paypal.com', |
|
| 286 | - 'connection' => 'close', |
|
| 287 | - 'content-type' => 'application/x-www-form-urlencoded', |
|
| 288 | - 'post' => '/cgi-bin/webscr HTTP/1.1', |
|
| 289 | - |
|
| 290 | - ), |
|
| 291 | - 'sslverify' => false, |
|
| 292 | - 'body' => $encoded_data_array |
|
| 293 | - ); |
|
| 294 | - |
|
| 295 | - // Get response |
|
| 296 | - $api_response = wp_remote_post( wpinv_get_paypal_redirect(), $remote_post_vars ); |
|
| 297 | - |
|
| 298 | - if ( is_wp_error( $api_response ) ) { |
|
| 299 | - wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid IPN verification response. IPN data: %s', 'invoicing' ), json_encode( $api_response ) ) ); |
|
| 300 | - return; // Something went wrong |
|
| 301 | - } |
|
| 302 | - |
|
| 303 | - if ( $api_response['body'] !== 'VERIFIED' && wpinv_get_option( 'disable_paypal_verification', false ) ) { |
|
| 304 | - wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid IPN verification response. IPN data: %s', 'invoicing' ), json_encode( $api_response ) ) ); |
|
| 305 | - return; // Response not okay |
|
| 306 | - } |
|
| 307 | - } |
|
| 308 | - |
|
| 309 | - // Check if $post_data_array has been populated |
|
| 310 | - if ( !is_array( $encoded_data_array ) && !empty( $encoded_data_array ) ) |
|
| 311 | - return; |
|
| 312 | - |
|
| 313 | - $defaults = array( |
|
| 314 | - 'txn_type' => '', |
|
| 315 | - 'payment_status' => '' |
|
| 316 | - ); |
|
| 317 | - |
|
| 318 | - $encoded_data_array = wp_parse_args( $encoded_data_array, $defaults ); |
|
| 319 | - |
|
| 320 | - $invoice_id = isset( $encoded_data_array['custom'] ) ? absint( $encoded_data_array['custom'] ) : 0; |
|
| 220 | + // Check the request method is POST |
|
| 221 | + if ( isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] != 'POST' ) { |
|
| 222 | + return; |
|
| 223 | + } |
|
| 224 | + |
|
| 225 | + // Set initial post data to empty string |
|
| 226 | + $post_data = ''; |
|
| 227 | + |
|
| 228 | + // Fallback just in case post_max_size is lower than needed |
|
| 229 | + if ( ini_get( 'allow_url_fopen' ) ) { |
|
| 230 | + $post_data = file_get_contents( 'php://input' ); |
|
| 231 | + } else { |
|
| 232 | + // If allow_url_fopen is not enabled, then make sure that post_max_size is large enough |
|
| 233 | + ini_set( 'post_max_size', '12M' ); |
|
| 234 | + } |
|
| 235 | + // Start the encoded data collection with notification command |
|
| 236 | + $encoded_data = 'cmd=_notify-validate'; |
|
| 237 | + |
|
| 238 | + // Get current arg separator |
|
| 239 | + $arg_separator = wpinv_get_php_arg_separator_output(); |
|
| 240 | + |
|
| 241 | + // Verify there is a post_data |
|
| 242 | + if ( $post_data || strlen( $post_data ) > 0 ) { |
|
| 243 | + // Append the data |
|
| 244 | + $encoded_data .= $arg_separator.$post_data; |
|
| 245 | + } else { |
|
| 246 | + // Check if POST is empty |
|
| 247 | + if ( empty( $_POST ) ) { |
|
| 248 | + // Nothing to do |
|
| 249 | + return; |
|
| 250 | + } else { |
|
| 251 | + // Loop through each POST |
|
| 252 | + foreach ( $_POST as $key => $value ) { |
|
| 253 | + // Encode the value and append the data |
|
| 254 | + $encoded_data .= $arg_separator."$key=" . urlencode( $value ); |
|
| 255 | + } |
|
| 256 | + } |
|
| 257 | + } |
|
| 258 | + |
|
| 259 | + // Convert collected post data to an array |
|
| 260 | + parse_str( $encoded_data, $encoded_data_array ); |
|
| 261 | + |
|
| 262 | + foreach ( $encoded_data_array as $key => $value ) { |
|
| 263 | + if ( false !== strpos( $key, 'amp;' ) ) { |
|
| 264 | + $new_key = str_replace( '&', '&', $key ); |
|
| 265 | + $new_key = str_replace( 'amp;', '&' , $new_key ); |
|
| 266 | + |
|
| 267 | + unset( $encoded_data_array[ $key ] ); |
|
| 268 | + $encoded_data_array[ $new_key ] = $value; |
|
| 269 | + } |
|
| 270 | + } |
|
| 271 | + |
|
| 272 | + // Get the PayPal redirect uri |
|
| 273 | + $paypal_redirect = wpinv_get_paypal_redirect( true ); |
|
| 274 | + |
|
| 275 | + if ( !wpinv_get_option( 'disable_paypal_verification', false ) ) { |
|
| 276 | + // Validate the IPN |
|
| 277 | + |
|
| 278 | + $remote_post_vars = array( |
|
| 279 | + 'method' => 'POST', |
|
| 280 | + 'timeout' => 45, |
|
| 281 | + 'redirection' => 5, |
|
| 282 | + 'httpversion' => '1.1', |
|
| 283 | + 'blocking' => true, |
|
| 284 | + 'headers' => array( |
|
| 285 | + 'host' => 'www.paypal.com', |
|
| 286 | + 'connection' => 'close', |
|
| 287 | + 'content-type' => 'application/x-www-form-urlencoded', |
|
| 288 | + 'post' => '/cgi-bin/webscr HTTP/1.1', |
|
| 289 | + |
|
| 290 | + ), |
|
| 291 | + 'sslverify' => false, |
|
| 292 | + 'body' => $encoded_data_array |
|
| 293 | + ); |
|
| 294 | + |
|
| 295 | + // Get response |
|
| 296 | + $api_response = wp_remote_post( wpinv_get_paypal_redirect(), $remote_post_vars ); |
|
| 297 | + |
|
| 298 | + if ( is_wp_error( $api_response ) ) { |
|
| 299 | + wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid IPN verification response. IPN data: %s', 'invoicing' ), json_encode( $api_response ) ) ); |
|
| 300 | + return; // Something went wrong |
|
| 301 | + } |
|
| 302 | + |
|
| 303 | + if ( $api_response['body'] !== 'VERIFIED' && wpinv_get_option( 'disable_paypal_verification', false ) ) { |
|
| 304 | + wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid IPN verification response. IPN data: %s', 'invoicing' ), json_encode( $api_response ) ) ); |
|
| 305 | + return; // Response not okay |
|
| 306 | + } |
|
| 307 | + } |
|
| 308 | + |
|
| 309 | + // Check if $post_data_array has been populated |
|
| 310 | + if ( !is_array( $encoded_data_array ) && !empty( $encoded_data_array ) ) |
|
| 311 | + return; |
|
| 312 | + |
|
| 313 | + $defaults = array( |
|
| 314 | + 'txn_type' => '', |
|
| 315 | + 'payment_status' => '' |
|
| 316 | + ); |
|
| 317 | + |
|
| 318 | + $encoded_data_array = wp_parse_args( $encoded_data_array, $defaults ); |
|
| 319 | + |
|
| 320 | + $invoice_id = isset( $encoded_data_array['custom'] ) ? absint( $encoded_data_array['custom'] ) : 0; |
|
| 321 | 321 | |
| 322 | - wpinv_error_log( $encoded_data_array['txn_type'], 'PayPal txn_type', __FILE__, __LINE__ ); |
|
| 323 | - |
|
| 324 | - if ( has_action( 'wpinv_paypal_' . $encoded_data_array['txn_type'] ) ) { |
|
| 325 | - // Allow PayPal IPN types to be processed separately |
|
| 326 | - do_action( 'wpinv_paypal_' . $encoded_data_array['txn_type'], $encoded_data_array, $invoice_id ); |
|
| 327 | - } else { |
|
| 328 | - // Fallback to web accept just in case the txn_type isn't present |
|
| 329 | - do_action( 'wpinv_paypal_web_accept', $encoded_data_array, $invoice_id ); |
|
| 330 | - } |
|
| 331 | - exit; |
|
| 322 | + wpinv_error_log( $encoded_data_array['txn_type'], 'PayPal txn_type', __FILE__, __LINE__ ); |
|
| 323 | + |
|
| 324 | + if ( has_action( 'wpinv_paypal_' . $encoded_data_array['txn_type'] ) ) { |
|
| 325 | + // Allow PayPal IPN types to be processed separately |
|
| 326 | + do_action( 'wpinv_paypal_' . $encoded_data_array['txn_type'], $encoded_data_array, $invoice_id ); |
|
| 327 | + } else { |
|
| 328 | + // Fallback to web accept just in case the txn_type isn't present |
|
| 329 | + do_action( 'wpinv_paypal_web_accept', $encoded_data_array, $invoice_id ); |
|
| 330 | + } |
|
| 331 | + exit; |
|
| 332 | 332 | } |
| 333 | 333 | add_action( 'wpinv_verify_paypal_ipn', 'wpinv_process_paypal_ipn' ); |
| 334 | 334 | |
| 335 | 335 | function wpinv_process_paypal_web_accept_and_cart( $data, $invoice_id ) { |
| 336 | - if ( $data['txn_type'] != 'web_accept' && $data['txn_type'] != 'cart' && $data['payment_status'] != 'Refunded' ) { |
|
| 337 | - return; |
|
| 338 | - } |
|
| 339 | - |
|
| 340 | - if( empty( $invoice_id ) ) { |
|
| 341 | - return; |
|
| 342 | - } |
|
| 343 | - |
|
| 344 | - // Collect payment details |
|
| 345 | - $purchase_key = isset( $data['invoice'] ) ? $data['invoice'] : $data['item_number']; |
|
| 346 | - $paypal_amount = $data['mc_gross']; |
|
| 347 | - $payment_status = strtolower( $data['payment_status'] ); |
|
| 348 | - $currency_code = strtolower( $data['mc_currency'] ); |
|
| 349 | - $business_email = isset( $data['business'] ) && is_email( $data['business'] ) ? trim( $data['business'] ) : trim( $data['receiver_email'] ); |
|
| 350 | - $payment_meta = wpinv_get_invoice_meta( $invoice_id ); |
|
| 351 | - |
|
| 352 | - if ( wpinv_get_payment_gateway( $invoice_id ) != 'paypal' ) { |
|
| 353 | - return; // this isn't a PayPal standard IPN |
|
| 354 | - } |
|
| 355 | - |
|
| 356 | - // Verify payment recipient |
|
| 357 | - if ( strcasecmp( $business_email, trim( wpinv_get_option( 'paypal_email', false ) ) ) != 0 ) { |
|
| 358 | - wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid business email in IPN response. IPN data: %s', 'invoicing' ), json_encode( $data ) ), $invoice_id ); |
|
| 359 | - wpinv_update_payment_status( $invoice_id, 'wpi-failed' ); |
|
| 360 | - wpinv_insert_payment_note( $invoice_id, __( 'Payment failed due to invalid PayPal business email.', 'invoicing' ) ); |
|
| 361 | - return; |
|
| 362 | - } |
|
| 363 | - |
|
| 364 | - // Verify payment currency |
|
| 365 | - if ( $currency_code != strtolower( $payment_meta['currency'] ) ) { |
|
| 366 | - wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid currency in IPN response. IPN data: %s', 'invoicing' ), json_encode( $data ) ), $invoice_id ); |
|
| 367 | - wpinv_update_payment_status( $invoice_id, 'wpi-failed' ); |
|
| 368 | - wpinv_insert_payment_note( $invoice_id, __( 'Payment failed due to invalid currency in PayPal IPN.', 'invoicing' ) ); |
|
| 369 | - return; |
|
| 370 | - } |
|
| 371 | - |
|
| 372 | - if ( !wpinv_get_payment_user_email( $invoice_id ) ) { |
|
| 373 | - // This runs when a Buy Now purchase was made. It bypasses checkout so no personal info is collected until PayPal |
|
| 374 | - // No email associated with purchase, so store from PayPal |
|
| 375 | - wpinv_update_invoice_meta( $invoice_id, '_wpinv_email', $data['payer_email'] ); |
|
| 376 | - |
|
| 377 | - // Setup and store the customer's details |
|
| 378 | - $user_info = array( |
|
| 379 | - 'user_id' => '-1', |
|
| 380 | - 'email' => sanitize_text_field( $data['payer_email'] ), |
|
| 381 | - 'first_name' => sanitize_text_field( $data['first_name'] ), |
|
| 382 | - 'last_name' => sanitize_text_field( $data['last_name'] ), |
|
| 383 | - 'discount' => '', |
|
| 384 | - ); |
|
| 385 | - $user_info['address'] = ! empty( $data['address_street'] ) ? sanitize_text_field( $data['address_street'] ) : false; |
|
| 386 | - $user_info['city'] = ! empty( $data['address_city'] ) ? sanitize_text_field( $data['address_city'] ) : false; |
|
| 387 | - $user_info['state'] = ! empty( $data['address_state'] ) ? sanitize_text_field( $data['address_state'] ) : false; |
|
| 388 | - $user_info['country'] = ! empty( $data['address_country_code'] ) ? sanitize_text_field( $data['address_country_code'] ) : false; |
|
| 389 | - $user_info['zip'] = ! empty( $data['address_zip'] ) ? sanitize_text_field( $data['address_zip'] ) : false; |
|
| 390 | - |
|
| 391 | - $payment_meta['user_info'] = $user_info; |
|
| 392 | - wpinv_update_invoice_meta( $invoice_id, '_wpinv_payment_meta', $payment_meta ); |
|
| 393 | - } |
|
| 394 | - |
|
| 395 | - if ( $payment_status == 'refunded' || $payment_status == 'reversed' ) { |
|
| 396 | - // Process a refund |
|
| 397 | - wpinv_process_paypal_refund( $data, $invoice_id ); |
|
| 398 | - } else { |
|
| 399 | - if ( get_post_status( $invoice_id ) == 'publish' ) { |
|
| 400 | - return; // Only paid payments once |
|
| 401 | - } |
|
| 402 | - |
|
| 403 | - // Retrieve the total purchase amount (before PayPal) |
|
| 404 | - $payment_amount = wpinv_payment_total( $invoice_id ); |
|
| 405 | - |
|
| 406 | - if ( number_format( (float) $paypal_amount, 2 ) < number_format( (float) $payment_amount, 2 ) ) { |
|
| 407 | - // The prices don't match |
|
| 408 | - wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid payment amount in IPN response. IPN data: %s', 'invoicing' ), json_encode( $data ) ), $invoice_id ); |
|
| 409 | - wpinv_update_payment_status( $invoice_id, 'wpi-failed' ); |
|
| 410 | - wpinv_insert_payment_note( $invoice_id, __( 'Payment failed due to invalid amount in PayPal IPN.', 'invoicing' ) ); |
|
| 411 | - return; |
|
| 412 | - } |
|
| 413 | - if ( $purchase_key != wpinv_get_payment_key( $invoice_id ) ) { |
|
| 414 | - // Purchase keys don't match |
|
| 415 | - wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid purchase key in IPN response. IPN data: %s', 'invoicing' ), json_encode( $data ) ), $invoice_id ); |
|
| 416 | - wpinv_update_payment_status( $invoice_id, 'wpi-failed' ); |
|
| 417 | - wpinv_insert_payment_note( $invoice_id, __( 'Payment failed due to invalid purchase key in PayPal IPN.', 'invoicing' ) ); |
|
| 418 | - return; |
|
| 419 | - } |
|
| 420 | - |
|
| 421 | - if ( 'complete' == $payment_status || 'completed' == $payment_status || 'processed' == $payment_status || wpinv_is_test_mode( 'paypal' ) ) { |
|
| 422 | - wpinv_insert_payment_note( $invoice_id, sprintf( __( 'PayPal Transaction ID: %s', 'invoicing' ) , $data['txn_id'] ) ); |
|
| 423 | - wpinv_set_payment_transaction_id( $invoice_id, $data['txn_id'] ); |
|
| 424 | - wpinv_update_payment_status( $invoice_id, 'publish' ); |
|
| 425 | - } else if ( 'pending' == $payment_status && isset( $data['pending_reason'] ) ) { |
|
| 426 | - // Look for possible pending reasons, such as an echeck |
|
| 427 | - $note = ''; |
|
| 428 | - |
|
| 429 | - switch( strtolower( $data['pending_reason'] ) ) { |
|
| 430 | - case 'echeck' : |
|
| 431 | - $note = __( 'Payment made via eCheck and will clear automatically in 5-8 days', 'invoicing' ); |
|
| 432 | - break; |
|
| 336 | + if ( $data['txn_type'] != 'web_accept' && $data['txn_type'] != 'cart' && $data['payment_status'] != 'Refunded' ) { |
|
| 337 | + return; |
|
| 338 | + } |
|
| 339 | + |
|
| 340 | + if( empty( $invoice_id ) ) { |
|
| 341 | + return; |
|
| 342 | + } |
|
| 343 | + |
|
| 344 | + // Collect payment details |
|
| 345 | + $purchase_key = isset( $data['invoice'] ) ? $data['invoice'] : $data['item_number']; |
|
| 346 | + $paypal_amount = $data['mc_gross']; |
|
| 347 | + $payment_status = strtolower( $data['payment_status'] ); |
|
| 348 | + $currency_code = strtolower( $data['mc_currency'] ); |
|
| 349 | + $business_email = isset( $data['business'] ) && is_email( $data['business'] ) ? trim( $data['business'] ) : trim( $data['receiver_email'] ); |
|
| 350 | + $payment_meta = wpinv_get_invoice_meta( $invoice_id ); |
|
| 351 | + |
|
| 352 | + if ( wpinv_get_payment_gateway( $invoice_id ) != 'paypal' ) { |
|
| 353 | + return; // this isn't a PayPal standard IPN |
|
| 354 | + } |
|
| 355 | + |
|
| 356 | + // Verify payment recipient |
|
| 357 | + if ( strcasecmp( $business_email, trim( wpinv_get_option( 'paypal_email', false ) ) ) != 0 ) { |
|
| 358 | + wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid business email in IPN response. IPN data: %s', 'invoicing' ), json_encode( $data ) ), $invoice_id ); |
|
| 359 | + wpinv_update_payment_status( $invoice_id, 'wpi-failed' ); |
|
| 360 | + wpinv_insert_payment_note( $invoice_id, __( 'Payment failed due to invalid PayPal business email.', 'invoicing' ) ); |
|
| 361 | + return; |
|
| 362 | + } |
|
| 363 | + |
|
| 364 | + // Verify payment currency |
|
| 365 | + if ( $currency_code != strtolower( $payment_meta['currency'] ) ) { |
|
| 366 | + wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid currency in IPN response. IPN data: %s', 'invoicing' ), json_encode( $data ) ), $invoice_id ); |
|
| 367 | + wpinv_update_payment_status( $invoice_id, 'wpi-failed' ); |
|
| 368 | + wpinv_insert_payment_note( $invoice_id, __( 'Payment failed due to invalid currency in PayPal IPN.', 'invoicing' ) ); |
|
| 369 | + return; |
|
| 370 | + } |
|
| 371 | + |
|
| 372 | + if ( !wpinv_get_payment_user_email( $invoice_id ) ) { |
|
| 373 | + // This runs when a Buy Now purchase was made. It bypasses checkout so no personal info is collected until PayPal |
|
| 374 | + // No email associated with purchase, so store from PayPal |
|
| 375 | + wpinv_update_invoice_meta( $invoice_id, '_wpinv_email', $data['payer_email'] ); |
|
| 376 | + |
|
| 377 | + // Setup and store the customer's details |
|
| 378 | + $user_info = array( |
|
| 379 | + 'user_id' => '-1', |
|
| 380 | + 'email' => sanitize_text_field( $data['payer_email'] ), |
|
| 381 | + 'first_name' => sanitize_text_field( $data['first_name'] ), |
|
| 382 | + 'last_name' => sanitize_text_field( $data['last_name'] ), |
|
| 383 | + 'discount' => '', |
|
| 384 | + ); |
|
| 385 | + $user_info['address'] = ! empty( $data['address_street'] ) ? sanitize_text_field( $data['address_street'] ) : false; |
|
| 386 | + $user_info['city'] = ! empty( $data['address_city'] ) ? sanitize_text_field( $data['address_city'] ) : false; |
|
| 387 | + $user_info['state'] = ! empty( $data['address_state'] ) ? sanitize_text_field( $data['address_state'] ) : false; |
|
| 388 | + $user_info['country'] = ! empty( $data['address_country_code'] ) ? sanitize_text_field( $data['address_country_code'] ) : false; |
|
| 389 | + $user_info['zip'] = ! empty( $data['address_zip'] ) ? sanitize_text_field( $data['address_zip'] ) : false; |
|
| 390 | + |
|
| 391 | + $payment_meta['user_info'] = $user_info; |
|
| 392 | + wpinv_update_invoice_meta( $invoice_id, '_wpinv_payment_meta', $payment_meta ); |
|
| 393 | + } |
|
| 394 | + |
|
| 395 | + if ( $payment_status == 'refunded' || $payment_status == 'reversed' ) { |
|
| 396 | + // Process a refund |
|
| 397 | + wpinv_process_paypal_refund( $data, $invoice_id ); |
|
| 398 | + } else { |
|
| 399 | + if ( get_post_status( $invoice_id ) == 'publish' ) { |
|
| 400 | + return; // Only paid payments once |
|
| 401 | + } |
|
| 402 | + |
|
| 403 | + // Retrieve the total purchase amount (before PayPal) |
|
| 404 | + $payment_amount = wpinv_payment_total( $invoice_id ); |
|
| 405 | + |
|
| 406 | + if ( number_format( (float) $paypal_amount, 2 ) < number_format( (float) $payment_amount, 2 ) ) { |
|
| 407 | + // The prices don't match |
|
| 408 | + wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid payment amount in IPN response. IPN data: %s', 'invoicing' ), json_encode( $data ) ), $invoice_id ); |
|
| 409 | + wpinv_update_payment_status( $invoice_id, 'wpi-failed' ); |
|
| 410 | + wpinv_insert_payment_note( $invoice_id, __( 'Payment failed due to invalid amount in PayPal IPN.', 'invoicing' ) ); |
|
| 411 | + return; |
|
| 412 | + } |
|
| 413 | + if ( $purchase_key != wpinv_get_payment_key( $invoice_id ) ) { |
|
| 414 | + // Purchase keys don't match |
|
| 415 | + wpinv_record_gateway_error( __( 'IPN Error', 'invoicing' ), sprintf( __( 'Invalid purchase key in IPN response. IPN data: %s', 'invoicing' ), json_encode( $data ) ), $invoice_id ); |
|
| 416 | + wpinv_update_payment_status( $invoice_id, 'wpi-failed' ); |
|
| 417 | + wpinv_insert_payment_note( $invoice_id, __( 'Payment failed due to invalid purchase key in PayPal IPN.', 'invoicing' ) ); |
|
| 418 | + return; |
|
| 419 | + } |
|
| 420 | + |
|
| 421 | + if ( 'complete' == $payment_status || 'completed' == $payment_status || 'processed' == $payment_status || wpinv_is_test_mode( 'paypal' ) ) { |
|
| 422 | + wpinv_insert_payment_note( $invoice_id, sprintf( __( 'PayPal Transaction ID: %s', 'invoicing' ) , $data['txn_id'] ) ); |
|
| 423 | + wpinv_set_payment_transaction_id( $invoice_id, $data['txn_id'] ); |
|
| 424 | + wpinv_update_payment_status( $invoice_id, 'publish' ); |
|
| 425 | + } else if ( 'pending' == $payment_status && isset( $data['pending_reason'] ) ) { |
|
| 426 | + // Look for possible pending reasons, such as an echeck |
|
| 427 | + $note = ''; |
|
| 428 | + |
|
| 429 | + switch( strtolower( $data['pending_reason'] ) ) { |
|
| 430 | + case 'echeck' : |
|
| 431 | + $note = __( 'Payment made via eCheck and will clear automatically in 5-8 days', 'invoicing' ); |
|
| 432 | + break; |
|
| 433 | 433 | |
| 434 | 434 | case 'address' : |
| 435 | - $note = __( 'Payment requires a confirmed customer address and must be accepted manually through PayPal', 'invoicing' ); |
|
| 436 | - break; |
|
| 435 | + $note = __( 'Payment requires a confirmed customer address and must be accepted manually through PayPal', 'invoicing' ); |
|
| 436 | + break; |
|
| 437 | 437 | |
| 438 | 438 | case 'intl' : |
| 439 | - $note = __( 'Payment must be accepted manually through PayPal due to international account regulations', 'invoicing' ); |
|
| 440 | - break; |
|
| 439 | + $note = __( 'Payment must be accepted manually through PayPal due to international account regulations', 'invoicing' ); |
|
| 440 | + break; |
|
| 441 | 441 | |
| 442 | 442 | case 'multi-currency' : |
| 443 | - $note = __( 'Payment received in non-shop currency and must be accepted manually through PayPal', 'invoicing' ); |
|
| 444 | - break; |
|
| 443 | + $note = __( 'Payment received in non-shop currency and must be accepted manually through PayPal', 'invoicing' ); |
|
| 444 | + break; |
|
| 445 | 445 | |
| 446 | 446 | case 'paymentreview' : |
| 447 | 447 | case 'regulatory_review' : |
| 448 | - $note = __( 'Payment is being reviewed by PayPal staff as high-risk or in possible violation of government regulations', 'invoicing' ); |
|
| 449 | - break; |
|
| 448 | + $note = __( 'Payment is being reviewed by PayPal staff as high-risk or in possible violation of government regulations', 'invoicing' ); |
|
| 449 | + break; |
|
| 450 | 450 | |
| 451 | 451 | case 'unilateral' : |
| 452 | - $note = __( 'Payment was sent to non-confirmed or non-registered email address.', 'invoicing' ); |
|
| 453 | - break; |
|
| 452 | + $note = __( 'Payment was sent to non-confirmed or non-registered email address.', 'invoicing' ); |
|
| 453 | + break; |
|
| 454 | 454 | |
| 455 | 455 | case 'upgrade' : |
| 456 | - $note = __( 'PayPal account must be upgraded before this payment can be accepted', 'invoicing' ); |
|
| 457 | - break; |
|
| 456 | + $note = __( 'PayPal account must be upgraded before this payment can be accepted', 'invoicing' ); |
|
| 457 | + break; |
|
| 458 | 458 | |
| 459 | 459 | case 'verify' : |
| 460 | - $note = __( 'PayPal account is not verified. Verify account in order to accept this payment', 'invoicing' ); |
|
| 461 | - break; |
|
| 462 | - |
|
| 463 | - case 'other' : |
|
| 464 | - $note = __( 'Payment is pending for unknown reasons. Contact PayPal support for assistance', 'invoicing' ); |
|
| 465 | - break; |
|
| 466 | - } |
|
| 467 | - |
|
| 468 | - if ( ! empty( $note ) ) { |
|
| 469 | - wpinv_insert_payment_note( $invoice_id, $note ); |
|
| 470 | - } |
|
| 471 | - } else { |
|
| 472 | - wpinv_insert_payment_note( $invoice_id, wp_sprintf( __( 'PayPal IPN has been received with invalid payment status: %s', 'invoicing' ), $payment_status ) ); |
|
| 473 | - } |
|
| 474 | - } |
|
| 460 | + $note = __( 'PayPal account is not verified. Verify account in order to accept this payment', 'invoicing' ); |
|
| 461 | + break; |
|
| 462 | + |
|
| 463 | + case 'other' : |
|
| 464 | + $note = __( 'Payment is pending for unknown reasons. Contact PayPal support for assistance', 'invoicing' ); |
|
| 465 | + break; |
|
| 466 | + } |
|
| 467 | + |
|
| 468 | + if ( ! empty( $note ) ) { |
|
| 469 | + wpinv_insert_payment_note( $invoice_id, $note ); |
|
| 470 | + } |
|
| 471 | + } else { |
|
| 472 | + wpinv_insert_payment_note( $invoice_id, wp_sprintf( __( 'PayPal IPN has been received with invalid payment status: %s', 'invoicing' ), $payment_status ) ); |
|
| 473 | + } |
|
| 474 | + } |
|
| 475 | 475 | } |
| 476 | 476 | add_action( 'wpinv_paypal_web_accept', 'wpinv_process_paypal_web_accept_and_cart', 10, 2 ); |
| 477 | 477 | |
@@ -686,27 +686,27 @@ discard block |
||
| 686 | 686 | } |
| 687 | 687 | |
| 688 | 688 | function wpinv_process_paypal_refund( $data, $invoice_id = 0 ) { |
| 689 | - // Collect payment details |
|
| 689 | + // Collect payment details |
|
| 690 | 690 | |
| 691 | - if( empty( $invoice_id ) ) { |
|
| 692 | - return; |
|
| 693 | - } |
|
| 691 | + if( empty( $invoice_id ) ) { |
|
| 692 | + return; |
|
| 693 | + } |
|
| 694 | 694 | |
| 695 | - if ( get_post_status( $invoice_id ) == 'wpi-refunded' ) { |
|
| 696 | - return; // Only refund payments once |
|
| 697 | - } |
|
| 695 | + if ( get_post_status( $invoice_id ) == 'wpi-refunded' ) { |
|
| 696 | + return; // Only refund payments once |
|
| 697 | + } |
|
| 698 | 698 | |
| 699 | - $payment_amount = wpinv_payment_total( $invoice_id ); |
|
| 700 | - $refund_amount = $data['mc_gross'] * -1; |
|
| 699 | + $payment_amount = wpinv_payment_total( $invoice_id ); |
|
| 700 | + $refund_amount = $data['mc_gross'] * -1; |
|
| 701 | 701 | |
| 702 | - if ( number_format( (float) $refund_amount, 2 ) < number_format( (float) $payment_amount, 2 ) ) { |
|
| 703 | - wpinv_insert_payment_note( $invoice_id, sprintf( __( 'Partial PayPal refund processed: %s', 'invoicing' ), $data['parent_txn_id'] ) ); |
|
| 704 | - return; // This is a partial refund |
|
| 705 | - } |
|
| 702 | + if ( number_format( (float) $refund_amount, 2 ) < number_format( (float) $payment_amount, 2 ) ) { |
|
| 703 | + wpinv_insert_payment_note( $invoice_id, sprintf( __( 'Partial PayPal refund processed: %s', 'invoicing' ), $data['parent_txn_id'] ) ); |
|
| 704 | + return; // This is a partial refund |
|
| 705 | + } |
|
| 706 | 706 | |
| 707 | - wpinv_insert_payment_note( $invoice_id, sprintf( __( 'PayPal Payment #%s Refunded for reason: %s', 'invoicing' ), $data['parent_txn_id'], $data['reason_code'] ) ); |
|
| 708 | - wpinv_insert_payment_note( $invoice_id, sprintf( __( 'PayPal Refund Transaction ID: %s', 'invoicing' ), $data['txn_id'] ) ); |
|
| 709 | - wpinv_update_payment_status( $invoice_id, 'wpi-refunded' ); |
|
| 707 | + wpinv_insert_payment_note( $invoice_id, sprintf( __( 'PayPal Payment #%s Refunded for reason: %s', 'invoicing' ), $data['parent_txn_id'], $data['reason_code'] ) ); |
|
| 708 | + wpinv_insert_payment_note( $invoice_id, sprintf( __( 'PayPal Refund Transaction ID: %s', 'invoicing' ), $data['txn_id'] ) ); |
|
| 709 | + wpinv_update_payment_status( $invoice_id, 'wpi-refunded' ); |
|
| 710 | 710 | } |
| 711 | 711 | |
| 712 | 712 | function wpinv_get_paypal_redirect( $ssl_check = false ) { |