| 1 |
<?php |
| 2 |
/** |
| 3 |
* PayPal Standard Gateway |
| 4 |
* |
| 5 |
* @package Give |
| 6 |
* @subpackage Gateways |
| 7 |
* @copyright Copyright (c) 2016, GiveWP |
| 8 |
* @license https://opensource.org/licenses/gpl-license GNU Public License |
| 9 |
* @since 1.0 |
| 10 |
*/ |
| 11 |
|
| 12 |
if ( ! defined( 'ABSPATH' ) ) { |
| 13 |
exit; |
| 14 |
} |
| 15 |
|
| 16 |
/** |
| 17 |
* Toggle PayPal CC Billing Detail Fieldset. |
| 18 |
* |
| 19 |
* @param int $form_id Form ID. |
| 20 |
* |
| 21 |
* @since 1.8.5 |
| 22 |
* |
| 23 |
* @return bool |
| 24 |
*/ |
| 25 |
function give_paypal_standard_billing_fields( $form_id ) { |
| 26 |
|
| 27 |
if ( give_is_setting_enabled( give_get_option( 'paypal_standard_billing_details' ) ) ) { |
| 28 |
give_default_cc_address_fields( $form_id ); |
| 29 |
|
| 30 |
return true; |
| 31 |
} |
| 32 |
|
| 33 |
return false; |
| 34 |
|
| 35 |
} |
| 36 |
|
| 37 |
add_action( 'give_paypal_cc_form', 'give_paypal_standard_billing_fields' ); |
| 38 |
|
| 39 |
/** |
| 40 |
* Process PayPal Payment. |
| 41 |
* |
| 42 |
* @param array $payment_data Payment data. |
| 43 |
* |
| 44 |
* @since 1.0 |
| 45 |
* |
| 46 |
* @return void |
| 47 |
*/ |
| 48 |
function give_process_paypal_payment( $payment_data ) { |
| 49 |
|
| 50 |
// Validate nonce. |
| 51 |
give_validate_nonce( $payment_data['gateway_nonce'], 'give-gateway' ); |
| 52 |
|
| 53 |
$payment_id = give_create_payment( $payment_data ); |
| 54 |
|
| 55 |
// Check payment. |
| 56 |
if ( empty( $payment_id ) ) { |
| 57 |
// Record the error. |
| 58 |
give_record_gateway_error( __( 'Payment Error', 'give' ), sprintf( /* translators: %s: payment data */ |
| 59 |
__( 'Payment creation failed before sending donor to PayPal. Payment data: %s', 'give' ), json_encode( $payment_data ) ), $payment_id ); |
| 60 |
// Problems? Send back. |
| 61 |
give_send_back_to_checkout( '?payment-mode=' . $payment_data['post_data']['give-gateway'] ); |
| 62 |
} |
| 63 |
|
| 64 |
// Redirect to PayPal. |
| 65 |
wp_redirect( give_build_paypal_url( $payment_id, $payment_data ) ); |
| 66 |
exit; |
| 67 |
} |
| 68 |
|
| 69 |
add_action( 'give_gateway_paypal', 'give_process_paypal_payment' ); |
| 70 |
|
| 71 |
/** |
| 72 |
* Listens for a PayPal IPN requests and then sends to the processing function. |
| 73 |
* |
| 74 |
* @since 1.0 |
| 75 |
* @return void |
| 76 |
*/ |
| 77 |
function give_listen_for_paypal_ipn() { |
| 78 |
|
| 79 |
// Regular PayPal IPN. |
| 80 |
if ( isset( $_GET['give-listener'] ) && 'IPN' === $_GET['give-listener'] ) { |
| 81 |
/** |
| 82 |
* Fires while verifying PayPal IPN |
| 83 |
* |
| 84 |
* @since 1.0 |
| 85 |
*/ |
| 86 |
do_action( 'give_verify_paypal_ipn' ); |
| 87 |
} |
| 88 |
} |
| 89 |
|
| 90 |
add_action( 'init', 'give_listen_for_paypal_ipn' ); |
| 91 |
|
| 92 |
/** |
| 93 |
* Process PayPal IPN |
| 94 |
* |
| 95 |
* @since 1.0 |
| 96 |
* @return void |
| 97 |
*/ |
| 98 |
function give_process_paypal_ipn() { |
| 99 |
|
| 100 |
// Check the request method is POST. |
| 101 |
if ( isset( $_SERVER['REQUEST_METHOD'] ) && 'POST' !== $_SERVER['REQUEST_METHOD'] ) { |
| 102 |
return; |
| 103 |
} |
| 104 |
|
| 105 |
// Set initial post data to empty string. |
| 106 |
$post_data = ''; |
| 107 |
|
| 108 |
// Fallback just in case post_max_size is lower than needed. |
| 109 |
if ( ini_get( 'allow_url_fopen' ) ) { |
| 110 |
$post_data = file_get_contents( 'php://input' ); |
| 111 |
} else { |
| 112 |
// If allow_url_fopen is not enabled, then make sure that post_max_size is large enough. |
| 113 |
ini_set( 'post_max_size', '12M' ); |
| 114 |
} |
| 115 |
// Start the encoded data collection with notification command. |
| 116 |
$encoded_data = 'cmd=_notify-validate'; |
| 117 |
|
| 118 |
// Get current arg separator. |
| 119 |
$arg_separator = give_get_php_arg_separator_output(); |
| 120 |
|
| 121 |
// Verify there is a post_data. |
| 122 |
if ( $post_data || strlen( $post_data ) > 0 ) { |
| 123 |
// Append the data. |
| 124 |
$encoded_data .= $arg_separator . $post_data; |
| 125 |
} else { |
| 126 |
// Check if POST is empty. |
| 127 |
if ( empty( $_POST ) ) { |
| 128 |
// Nothing to do. |
| 129 |
return; |
| 130 |
} else { |
| 131 |
// Loop through each POST. |
| 132 |
foreach ( $_POST as $key => $value ) { |
| 133 |
// Encode the value and append the data. |
| 134 |
$encoded_data .= $arg_separator . "$key=" . urlencode( $value ); |
| 135 |
} |
| 136 |
} |
| 137 |
} |
| 138 |
|
| 139 |
// Convert collected post data to an array. |
| 140 |
parse_str( $encoded_data, $encoded_data_array ); |
| 141 |
|
| 142 |
foreach ( $encoded_data_array as $key => $value ) { |
| 143 |
|
| 144 |
if ( false !== strpos( $key, 'amp;' ) ) { |
| 145 |
$new_key = str_replace( '&', '&', $key ); |
| 146 |
$new_key = str_replace( 'amp;', '&', $new_key ); |
| 147 |
|
| 148 |
unset( $encoded_data_array[ $key ] ); |
| 149 |
$encoded_data_array[ $new_key ] = $value; |
| 150 |
} |
| 151 |
} |
| 152 |
|
| 153 |
$api_response = false; |
| 154 |
|
| 155 |
// Validate IPN request w/ PayPal if user hasn't disabled this security measure. |
| 156 |
if ( give_is_setting_enabled( give_get_option( 'paypal_verification' ) ) ) { |
| 157 |
|
| 158 |
$remote_post_vars = array( |
| 159 |
'method' => 'POST', |
| 160 |
'timeout' => 45, |
| 161 |
'redirection' => 5, |
| 162 |
'httpversion' => '1.1', |
| 163 |
'blocking' => true, |
| 164 |
'headers' => array( |
| 165 |
'host' => 'www.paypal.com', |
| 166 |
'connection' => 'close', |
| 167 |
'content-type' => 'application/x-www-form-urlencoded', |
| 168 |
'post' => '/cgi-bin/webscr HTTP/1.1', |
| 169 |
|
| 170 |
), |
| 171 |
'sslverify' => false, |
| 172 |
'body' => $encoded_data_array, |
| 173 |
); |
| 174 |
|
| 175 |
// Validate the IPN. |
| 176 |
$api_response = wp_remote_post( give_get_paypal_redirect(), $remote_post_vars ); |
| 177 |
|
| 178 |
if ( is_wp_error( $api_response ) ) { |
| 179 |
give_record_gateway_error( __( 'IPN Error', 'give' ), sprintf( /* translators: %s: Paypal IPN response */ |
| 180 |
__( 'Invalid IPN verification response. IPN data: %s', 'give' ), json_encode( $api_response ) ) ); |
| 181 |
|
| 182 |
return; // Something went wrong. |
| 183 |
} |
| 184 |
|
| 185 |
if ( 'VERIFIED' !== $api_response['body'] ) { |
| 186 |
give_record_gateway_error( __( 'IPN Error', 'give' ), sprintf( /* translators: %s: Paypal IPN response */ |
| 187 |
__( 'Invalid IPN verification response. IPN data: %s', 'give' ), json_encode( $api_response ) ) ); |
| 188 |
|
| 189 |
return; // Response not okay. |
| 190 |
} |
| 191 |
}// End if(). |
| 192 |
|
| 193 |
// Check if $post_data_array has been populated. |
| 194 |
if ( ! is_array( $encoded_data_array ) && ! empty( $encoded_data_array ) ) { |
| 195 |
return; |
| 196 |
} |
| 197 |
|
| 198 |
$defaults = array( |
| 199 |
'txn_type' => '', |
| 200 |
'payment_status' => '', |
| 201 |
); |
| 202 |
|
| 203 |
$encoded_data_array = wp_parse_args( $encoded_data_array, $defaults ); |
| 204 |
|
| 205 |
$payment_id = isset( $encoded_data_array['custom'] ) ? absint( $encoded_data_array['custom'] ) : 0; |
| 206 |
$txn_type = $encoded_data_array['txn_type']; |
| 207 |
|
| 208 |
// Check for PayPal IPN Notifications and update data based on it. |
| 209 |
$current_timestamp = current_time( 'timestamp' ); |
| 210 |
$paypal_ipn_vars = array( |
| 211 |
'auth_status' => isset( $api_response['body'] ) ? $api_response['body'] : 'N/A', |
| 212 |
'transaction_id' => isset( $encoded_data_array['txn_id'] ) ? $encoded_data_array['txn_id'] : 'N/A', |
| 213 |
'payment_id' => $payment_id, |
| 214 |
); |
| 215 |
update_option( 'give_last_paypal_ipn_received', $paypal_ipn_vars, false ); |
| 216 |
give_insert_payment_note( $payment_id, sprintf( |
| 217 |
__( 'IPN received on %s at %s', 'give' ), |
| 218 |
date_i18n( 'm/d/Y', $current_timestamp ), |
| 219 |
date_i18n( 'H:i', $current_timestamp ) |
| 220 |
) |
| 221 |
); |
| 222 |
give_update_meta( $payment_id, 'give_last_paypal_ipn_received', $current_timestamp ); |
| 223 |
|
| 224 |
if ( has_action( 'give_paypal_' . $txn_type ) ) { |
| 225 |
/** |
| 226 |
* Fires while processing PayPal IPN $txn_type. |
| 227 |
* |
| 228 |
* Allow PayPal IPN types to be processed separately. |
| 229 |
* |
| 230 |
* @since 1.0 |
| 231 |
* |
| 232 |
* @param array $encoded_data_array Encoded data. |
| 233 |
* @param int $payment_id Payment id. |
| 234 |
*/ |
| 235 |
do_action( "give_paypal_{$txn_type}", $encoded_data_array, $payment_id ); |
| 236 |
} else { |
| 237 |
/** |
| 238 |
* Fires while process PayPal IPN. |
| 239 |
* |
| 240 |
* Fallback to web accept just in case the txn_type isn't present. |
| 241 |
* |
| 242 |
* @since 1.0 |
| 243 |
* |
| 244 |
* @param array $encoded_data_array Encoded data. |
| 245 |
* @param int $payment_id Payment id. |
| 246 |
*/ |
| 247 |
do_action( 'give_paypal_web_accept', $encoded_data_array, $payment_id ); |
| 248 |
} |
| 249 |
exit; |
| 250 |
} |
| 251 |
|
| 252 |
add_action( 'give_verify_paypal_ipn', 'give_process_paypal_ipn' ); |
| 253 |
|
| 254 |
/** |
| 255 |
* Process web accept (one time) payment IPNs. |
| 256 |
* |
| 257 |
* @since 1.0 |
| 258 |
* |
| 259 |
* @param array $data The IPN Data. |
| 260 |
* @param int $payment_id The payment ID from Give. |
| 261 |
* |
| 262 |
* @return void |
| 263 |
*/ |
| 264 |
function give_process_paypal_web_accept( $data, $payment_id ) { |
| 265 |
|
| 266 |
// Only allow through these transaction types. |
| 267 |
if ( 'web_accept' !== $data['txn_type'] && 'cart' !== $data['txn_type'] && 'refunded' !== strtolower( $data['payment_status'] ) ) { |
| 268 |
return; |
| 269 |
} |
| 270 |
|
| 271 |
// Need $payment_id to continue. |
| 272 |
if ( empty( $payment_id ) ) { |
| 273 |
return; |
| 274 |
} |
| 275 |
|
| 276 |
// Collect donation payment details. |
| 277 |
$paypal_amount = $data['mc_gross']; |
| 278 |
$payment_status = strtolower( $data['payment_status'] ); |
| 279 |
$currency_code = strtolower( $data['mc_currency'] ); |
| 280 |
$business_email = isset( $data['business'] ) && is_email( $data['business'] ) ? trim( $data['business'] ) : trim( $data['receiver_email'] ); |
| 281 |
$payment_meta = give_get_payment_meta( $payment_id ); |
| 282 |
|
| 283 |
// Must be a PayPal standard IPN. |
| 284 |
if ( 'paypal' !== give_get_payment_gateway( $payment_id ) ) { |
| 285 |
return; |
| 286 |
} |
| 287 |
|
| 288 |
// Verify payment recipient. |
| 289 |
if ( strcasecmp( $business_email, trim( give_get_option( 'paypal_email' ) ) ) !== 0 ) { |
| 290 |
|
| 291 |
give_record_gateway_error( __( 'IPN Error', 'give' ), sprintf( /* translators: %s: Paypal IPN response */ |
| 292 |
__( 'Invalid business email in IPN response. IPN data: %s', 'give' ), json_encode( $data ) ), $payment_id ); |
| 293 |
give_update_payment_status( $payment_id, 'failed' ); |
| 294 |
give_insert_payment_note( $payment_id, __( 'Payment failed due to invalid PayPal business email.', 'give' ) ); |
| 295 |
|
| 296 |
return; |
| 297 |
} |
| 298 |
|
| 299 |
// Verify payment currency. |
| 300 |
if ( $currency_code !== strtolower( $payment_meta['currency'] ) ) { |
| 301 |
|
| 302 |
give_record_gateway_error( __( 'IPN Error', 'give' ), sprintf( /* translators: %s: Paypal IPN response */ |
| 303 |
__( 'Invalid currency in IPN response. IPN data: %s', 'give' ), json_encode( $data ) ), $payment_id ); |
| 304 |
give_update_payment_status( $payment_id, 'failed' ); |
| 305 |
give_insert_payment_note( $payment_id, __( 'Payment failed due to invalid currency in PayPal IPN.', 'give' ) ); |
| 306 |
|
| 307 |
return; |
| 308 |
} |
| 309 |
|
| 310 |
// Process refunds & reversed. |
| 311 |
if ( 'refunded' === $payment_status || 'reversed' === $payment_status ) { |
| 312 |
give_process_paypal_refund( $data, $payment_id ); |
| 313 |
|
| 314 |
return; |
| 315 |
} |
| 316 |
|
| 317 |
// Only complete payments once. |
| 318 |
if ( 'publish' === get_post_status( $payment_id ) ) { |
| 319 |
return; |
| 320 |
} |
| 321 |
|
| 322 |
// Retrieve the total donation amount (before PayPal). |
| 323 |
$payment_amount = give_donation_amount( $payment_id ); |
| 324 |
|
| 325 |
// Check that the donation PP and local db amounts match. |
| 326 |
if ( number_format( (float) $paypal_amount, 2 ) < number_format( (float) $payment_amount, 2 ) ) { |
| 327 |
// The prices don't match |
| 328 |
give_record_gateway_error( __( 'IPN Error', 'give' ), sprintf( /* translators: %s: Paypal IPN response */ |
| 329 |
__( 'Invalid payment amount in IPN response. IPN data: %s', 'give' ), json_encode( $data ) ), $payment_id ); |
| 330 |
give_update_payment_status( $payment_id, 'failed' ); |
| 331 |
give_insert_payment_note( $payment_id, __( 'Payment failed due to invalid amount in PayPal IPN.', 'give' ) ); |
| 332 |
|
| 333 |
return; |
| 334 |
} |
| 335 |
|
| 336 |
// Process completed donations. |
| 337 |
if ( 'completed' === $payment_status || give_is_test_mode() ) { |
| 338 |
|
| 339 |
give_insert_payment_note( $payment_id, sprintf( /* translators: %s: Paypal transaction ID */ |
| 340 |
__( 'PayPal Transaction ID: %s', 'give' ), $data['txn_id'] ) ); |
| 341 |
give_set_payment_transaction_id( $payment_id, $data['txn_id'] ); |
| 342 |
give_update_payment_status( $payment_id, 'publish' ); |
| 343 |
|
| 344 |
} elseif ( 'pending' === $payment_status && isset( $data['pending_reason'] ) ) { |
| 345 |
|
| 346 |
// Look for possible pending reasons, such as an echeck. |
| 347 |
$note = give_paypal_get_pending_donation_note( strtolower( $data['pending_reason'] ) ); |
| 348 |
|
| 349 |
if ( ! empty( $note ) ) { |
| 350 |
give_insert_payment_note( $payment_id, $note ); |
| 351 |
} |
| 352 |
} |
| 353 |
|
| 354 |
} |
| 355 |
|
| 356 |
add_action( 'give_paypal_web_accept', 'give_process_paypal_web_accept', 10, 2 ); |
| 357 |
|
| 358 |
/** |
| 359 |
* Process PayPal IPN Refunds |
| 360 |
* |
| 361 |
* @since 1.0 |
| 362 |
* |
| 363 |
* @param array $data IPN Data |
| 364 |
* @param int $payment_id The payment ID. |
| 365 |
* |
| 366 |
* @return void |
| 367 |
*/ |
| 368 |
function give_process_paypal_refund( $data, $payment_id = 0 ) { |
| 369 |
|
| 370 |
// Collect payment details. |
| 371 |
if ( empty( $payment_id ) ) { |
| 372 |
return; |
| 373 |
} |
| 374 |
|
| 375 |
// Only refund payments once. |
| 376 |
if ( 'refunded' === get_post_status( $payment_id ) ) { |
| 377 |
return; |
| 378 |
} |
| 379 |
|
| 380 |
$payment_amount = give_donation_amount( $payment_id ); |
| 381 |
$refund_amount = $data['payment_gross'] * - 1; |
| 382 |
|
| 383 |
if ( number_format( (float) $refund_amount, 2 ) < number_format( (float) $payment_amount, 2 ) ) { |
| 384 |
|
| 385 |
give_insert_payment_note( $payment_id, sprintf( /* translators: %s: Paypal parent transaction ID */ |
| 386 |
__( 'Partial PayPal refund processed: %s', 'give' ), $data['parent_txn_id'] ) ); |
| 387 |
|
| 388 |
return; // This is a partial refund |
| 389 |
|
| 390 |
} |
| 391 |
|
| 392 |
give_insert_payment_note( $payment_id, sprintf( /* translators: 1: Paypal parent transaction ID 2. Paypal reason code */ |
| 393 |
__( 'PayPal Payment #%1$s Refunded for reason: %2$s', 'give' ), $data['parent_txn_id'], $data['reason_code'] ) ); |
| 394 |
give_insert_payment_note( $payment_id, sprintf( /* translators: %s: Paypal transaction ID */ |
| 395 |
__( 'PayPal Refund Transaction ID: %s', 'give' ), $data['txn_id'] ) ); |
| 396 |
give_update_payment_status( $payment_id, 'refunded' ); |
| 397 |
} |
| 398 |
|
| 399 |
/** |
| 400 |
* Get PayPal Redirect |
| 401 |
* |
| 402 |
* @since 1.0 |
| 403 |
* |
| 404 |
* @param bool $ssl_check Is SSL? |
| 405 |
* |
| 406 |
* @return string |
| 407 |
*/ |
| 408 |
function give_get_paypal_redirect( $ssl_check = false ) { |
| 409 |
|
| 410 |
if ( is_ssl() || ! $ssl_check ) { |
| 411 |
$protocol = 'https://'; |
| 412 |
} else { |
| 413 |
$protocol = 'http://'; |
| 414 |
} |
| 415 |
|
| 416 |
// Check the current payment mode |
| 417 |
if ( give_is_test_mode() ) { |
| 418 |
// Test mode |
| 419 |
$paypal_uri = $protocol . 'www.sandbox.paypal.com/cgi-bin/webscr'; |
| 420 |
} else { |
| 421 |
// Live mode |
| 422 |
$paypal_uri = $protocol . 'www.paypal.com/cgi-bin/webscr'; |
| 423 |
} |
| 424 |
|
| 425 |
return apply_filters( 'give_paypal_uri', $paypal_uri ); |
| 426 |
} |
| 427 |
|
| 428 |
/** |
| 429 |
* Set the Page Style for offsite PayPal page. |
| 430 |
* |
| 431 |
* @since 1.0 |
| 432 |
* @return string |
| 433 |
*/ |
| 434 |
function give_get_paypal_page_style() { |
| 435 |
$page_style = trim( give_get_option( 'paypal_page_style', 'PayPal' ) ); |
| 436 |
|
| 437 |
return apply_filters( 'give_paypal_page_style', $page_style ); |
| 438 |
} |
| 439 |
|
| 440 |
/** |
| 441 |
* PayPal Success Page |
| 442 |
* |
| 443 |
* Shows "Donation Processing" message for PayPal payments that are still pending on site return |
| 444 |
* |
| 445 |
* @since 1.0 |
| 446 |
* |
| 447 |
* @param $content |
| 448 |
* |
| 449 |
* @return string |
| 450 |
*/ |
| 451 |
function give_paypal_success_page_content( $content ) { |
| 452 |
|
| 453 |
if ( ! isset( $_GET['payment-id'] ) && ! give_get_purchase_session() ) { |
| 454 |
return $content; |
| 455 |
} |
| 456 |
|
| 457 |
$payment_id = isset( $_GET['payment-id'] ) ? absint( $_GET['payment-id'] ) : false; |
| 458 |
|
| 459 |
if ( ! $payment_id ) { |
| 460 |
$session = give_get_purchase_session(); |
| 461 |
$payment_id = give_get_donation_id_by_key( $session['purchase_key'] ); |
| 462 |
} |
| 463 |
|
| 464 |
$payment = get_post( $payment_id ); |
| 465 |
if ( $payment && 'pending' === $payment->post_status ) { |
| 466 |
|
| 467 |
// Payment is still pending so show processing indicator to fix the race condition. |
| 468 |
ob_start(); |
| 469 |
|
| 470 |
give_get_template_part( 'payment', 'processing' ); |
| 471 |
|
| 472 |
$content = ob_get_clean(); |
| 473 |
|
| 474 |
} |
| 475 |
|
| 476 |
return $content; |
| 477 |
|
| 478 |
} |
| 479 |
|
| 480 |
add_filter( 'give_payment_confirm_paypal', 'give_paypal_success_page_content' ); |
| 481 |
|
| 482 |
/** |
| 483 |
* Given a transaction ID, generate a link to the PayPal transaction ID details |
| 484 |
* |
| 485 |
* @since 1.0 |
| 486 |
* |
| 487 |
* @param string $transaction_id The Transaction ID |
| 488 |
* @param int $payment_id The payment ID for this transaction |
| 489 |
* |
| 490 |
* @return string A link to the PayPal transaction details |
| 491 |
*/ |
| 492 |
function give_paypal_link_transaction_id( $transaction_id, $payment_id ) { |
| 493 |
|
| 494 |
$paypal_base_url = 'https://history.paypal.com/cgi-bin/webscr?cmd=_history-details-from-hub&id='; |
| 495 |
$transaction_url = '<a href="' . esc_url( $paypal_base_url . $transaction_id ) . '" target="_blank">' . $transaction_id . '</a>'; |
| 496 |
|
| 497 |
return apply_filters( 'give_paypal_link_payment_details_transaction_id', $transaction_url ); |
| 498 |
|
| 499 |
} |
| 500 |
|
| 501 |
add_filter( 'give_payment_details_transaction_id-paypal', 'give_paypal_link_transaction_id', 10, 2 ); |
| 502 |
|
| 503 |
|
| 504 |
/** |
| 505 |
* Get pending donation note. |
| 506 |
* |
| 507 |
* @since 1.6.3 |
| 508 |
* |
| 509 |
* @param $pending_reason |
| 510 |
* |
| 511 |
* @return string |
| 512 |
*/ |
| 513 |
function give_paypal_get_pending_donation_note( $pending_reason ) { |
| 514 |
|
| 515 |
$note = ''; |
| 516 |
|
| 517 |
switch ( $pending_reason ) { |
| 518 |
|
| 519 |
case 'echeck' : |
| 520 |
|
| 521 |
$note = __( 'Payment made via eCheck and will clear automatically in 5-8 days.', 'give' ); |
| 522 |
|
| 523 |
break; |
| 524 |
|
| 525 |
case 'address' : |
| 526 |
|
| 527 |
$note = __( 'Payment requires a confirmed donor address and must be accepted manually through PayPal.', 'give' ); |
| 528 |
|
| 529 |
break; |
| 530 |
|
| 531 |
case 'intl' : |
| 532 |
|
| 533 |
$note = __( 'Payment must be accepted manually through PayPal due to international account regulations.', 'give' ); |
| 534 |
|
| 535 |
break; |
| 536 |
|
| 537 |
case 'multi-currency' : |
| 538 |
|
| 539 |
$note = __( 'Payment received in non-shop currency and must be accepted manually through PayPal.', 'give' ); |
| 540 |
|
| 541 |
break; |
| 542 |
|
| 543 |
case 'paymentreview' : |
| 544 |
case 'regulatory_review' : |
| 545 |
|
| 546 |
$note = __( 'Payment is being reviewed by PayPal staff as high-risk or in possible violation of government regulations.', 'give' ); |
| 547 |
|
| 548 |
break; |
| 549 |
|
| 550 |
case 'unilateral' : |
| 551 |
|
| 552 |
$note = __( 'Payment was sent to non-confirmed or non-registered email address.', 'give' ); |
| 553 |
|
| 554 |
break; |
| 555 |
|
| 556 |
case 'upgrade' : |
| 557 |
|
| 558 |
$note = __( 'PayPal account must be upgraded before this payment can be accepted.', 'give' ); |
| 559 |
|
| 560 |
break; |
| 561 |
|
| 562 |
case 'verify' : |
| 563 |
|
| 564 |
$note = __( 'PayPal account is not verified. Verify account in order to accept this donation.', 'give' ); |
| 565 |
|
| 566 |
break; |
| 567 |
|
| 568 |
case 'other' : |
| 569 |
|
| 570 |
$note = __( 'Payment is pending for unknown reasons. Contact PayPal support for assistance.', 'give' ); |
| 571 |
|
| 572 |
break; |
| 573 |
|
| 574 |
}// End switch(). |
| 575 |
|
| 576 |
return $note; |
| 577 |
|
| 578 |
} |
| 579 |
|
| 580 |
/** |
| 581 |
* Build paypal url |
| 582 |
* |
| 583 |
* @param int $payment_id Payment ID |
| 584 |
* @param array $payment_data Array of payment data. |
| 585 |
* |
| 586 |
* @return mixed|string |
| 587 |
*/ |
| 588 |
function give_build_paypal_url( $payment_id, $payment_data ) { |
| 589 |
// Only send to PayPal if the pending payment is created successfully. |
| 590 |
$listener_url = add_query_arg( 'give-listener', 'IPN', home_url( 'index.php' ) ); |
| 591 |
|
| 592 |
// Get the success url. |
| 593 |
$return_url = add_query_arg( array( |
| 594 |
'payment-confirmation' => 'paypal', |
| 595 |
'payment-id' => $payment_id, |
| 596 |
|
| 597 |
), get_permalink( give_get_option( 'success_page' ) ) ); |
| 598 |
|
| 599 |
// Get the PayPal redirect uri. |
| 600 |
$paypal_redirect = trailingslashit( give_get_paypal_redirect() ) . '?'; |
| 601 |
|
| 602 |
// Item name. |
| 603 |
$item_name = give_payment_gateway_item_title( $payment_data ); |
| 604 |
|
| 605 |
// Setup PayPal API params. |
| 606 |
$paypal_args = array( |
| 607 |
'business' => give_get_option( 'paypal_email', false ), |
| 608 |
'first_name' => $payment_data['user_info']['first_name'], |
| 609 |
'last_name' => $payment_data['user_info']['last_name'], |
| 610 |
'email' => $payment_data['user_email'], |
| 611 |
'invoice' => $payment_data['purchase_key'], |
| 612 |
'amount' => $payment_data['price'], |
| 613 |
'item_name' => stripslashes( $item_name ), |
| 614 |
'no_shipping' => '1', |
| 615 |
'shipping' => '0', |
| 616 |
'no_note' => '1', |
| 617 |
'currency_code' => give_get_currency( $payment_id, $payment_data ), |
| 618 |
'charset' => get_bloginfo( 'charset' ), |
| 619 |
'custom' => $payment_id, |
| 620 |
'rm' => '2', |
| 621 |
'return' => $return_url, |
| 622 |
'cancel_return' => give_get_failed_transaction_uri( '?payment-id=' . $payment_id ), |
| 623 |
'notify_url' => $listener_url, |
| 624 |
'page_style' => give_get_paypal_page_style(), |
| 625 |
'cbt' => get_bloginfo( 'name' ), |
| 626 |
'bn' => 'givewp_SP', |
| 627 |
); |
| 628 |
|
| 629 |
// Add user address if present. |
| 630 |
if ( ! empty( $payment_data['user_info']['address'] ) ) { |
| 631 |
$default_address = array( |
| 632 |
'line1' => '', |
| 633 |
'line2' => '', |
| 634 |
'city' => '', |
| 635 |
'state' => '', |
| 636 |
'zip' => '', |
| 637 |
'country' => '', |
| 638 |
); |
| 639 |
|
| 640 |
$address = wp_parse_args( $payment_data['user_info']['address'], $default_address ); |
| 641 |
|
| 642 |
$paypal_args['address1'] = $address['line1']; |
| 643 |
$paypal_args['address2'] = $address['line2']; |
| 644 |
$paypal_args['city'] = $address['city']; |
| 645 |
$paypal_args['state'] = $address['state']; |
| 646 |
$paypal_args['zip'] = $address['zip']; |
| 647 |
$paypal_args['country'] = $address['country']; |
| 648 |
} |
| 649 |
|
| 650 |
// Donations or regular transactions? |
| 651 |
$paypal_args['cmd'] = give_get_paypal_button_type(); |
| 652 |
|
| 653 |
/** |
| 654 |
* Filter the paypal redirect args. |
| 655 |
* |
| 656 |
* @param array $paypal_args PayPal Arguments. |
| 657 |
* @param array $payment_data Payment Data. |
| 658 |
* |
| 659 |
* @since 1.8 |
| 660 |
*/ |
| 661 |
$paypal_args = apply_filters( 'give_paypal_redirect_args', $paypal_args, $payment_data ); |
| 662 |
|
| 663 |
// Build query. |
| 664 |
$paypal_redirect .= http_build_query( $paypal_args ); |
| 665 |
|
| 666 |
// Fix for some sites that encode the entities. |
| 667 |
$paypal_redirect = str_replace( '&', '&', $paypal_redirect ); |
| 668 |
|
| 669 |
return $paypal_redirect; |
| 670 |
} |
| 671 |
|
| 672 |
|
| 673 |
/** |
| 674 |
* Get paypal button type. |
| 675 |
* |
| 676 |
* @since 1.8 |
| 677 |
* @return string |
| 678 |
*/ |
| 679 |
function give_get_paypal_button_type() { |
| 680 |
// paypal_button_type can be donation or standard. |
| 681 |
$paypal_button_type = '_donations'; |
| 682 |
if ( 'standard' === give_get_option( 'paypal_button_type' ) ) { |
| 683 |
$paypal_button_type = '_xclick'; |
| 684 |
} |
| 685 |
|
| 686 |
return $paypal_button_type; |
| 687 |
} |
| 688 |
|
| 689 |
/** |
| 690 |
* Update Purchase key for specific gateway. |
| 691 |
* |
| 692 |
* @since 2.2.4 |
| 693 |
* |
| 694 |
* @param string $custom_purchase_key |
| 695 |
* @param string $gateway |
| 696 |
* @param string $purchase_key |
| 697 |
* |
| 698 |
* @return string |
| 699 |
*/ |
| 700 |
function give_paypal_purchase_key( $custom_purchase_key, $gateway, $purchase_key ) { |
| 701 |
|
| 702 |
if ( 'paypal' === $gateway ) { |
| 703 |
$invoice_id_prefix = give_get_option( 'paypal_invoice_prefix', 'GIVE-' ); |
| 704 |
$custom_purchase_key = $invoice_id_prefix . $purchase_key; |
| 705 |
} |
| 706 |
|
| 707 |
return $custom_purchase_key; |
| 708 |
} |
| 709 |
|
| 710 |
add_filter( 'give_donation_purchase_key', 'give_paypal_purchase_key', 10, 3 ); |
| 711 |
|