/**
  * Handle a call to our IPN listener.
  *
  * @return  string
  * @access  public
  * @static
  * @since   1.0.0
  */
 public static function process_ipn()
 {
     /* We only accept POST requests */
     if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'POST') {
         return false;
     }
     $gateway = new Charitable_Gateway_Paypal();
     $data = $gateway->get_encoded_ipn_data();
     if (empty($data)) {
         return false;
     }
     if (!$gateway->paypal_ipn_verification($data)) {
         return false;
     }
     $defaults = array('txn_type' => '', 'payment_status' => '');
     $data = wp_parse_args($data, $defaults);
     $donation_id = isset($data['custom']) ? absint($data['custom']) : 0;
     if (!$donation_id) {
         return false;
     }
     /**
      * By default, all transactions are handled by the web_accept handler. 
      * To handle other transaction types in a different way, use the 
      * 'charitable_paypal_{transaction_type}' hook.
      *
      * @see Charitable_Gateway_Paypal::process_web_accept()
      */
     $txn_type = strlen($data['txn_type']) ? $data['txn_type'] : 'web_accept';
     if (has_action('charitable_paypal_' . $txn_type)) {
         do_action('charitable_paypal_' . $txn_type, $data, $donation_id);
     } else {
         do_action('charitable_paypal_web_accept', $data, $donation_id);
     }
     exit;
 }
 /**
  * Receives the IPN from PayPal after the sandbox test and attempts to verify the result.
  *
  * @return  void
  * @access  public
  * @static
  * @since   1.4.3
  */
 public static function process_sandbox_test_ipn()
 {
     $gateway = new Charitable_Gateway_Paypal();
     $data = $gateway->get_encoded_ipn_data();
     /* If any of these checks fail, we conclude that this is not a proper IPN from PayPal. */
     if (empty($data) || !is_array($data)) {
         die("empty data");
     }
     /* Compare the token with the one we generated. */
     $token = get_option('charitable_paypal_sandbox_test_token');
     if (!array_key_exists('custom', $data) || $token !== $data['custom']) {
         die("missing or mismatched custom data");
     }
     $remote_post_vars = array('method' => 'POST', 'timeout' => 45, 'redirection' => 5, 'httpversion' => '1.1', 'blocking' => true, 'headers' => array('host' => 'www.paypal.com', 'connection' => 'close', 'content-type' => 'application/x-www-form-urlencoded', 'post' => '/cgi-bin/webscr HTTP/1.1'), 'sslverify' => false, 'body' => $data);
     /* Call the PayPal API to verify the IPN. */
     $protocol = is_ssl() ? 'https://' : 'http://';
     $remote_url = $protocol . 'www.sandbox.paypal.com/cgi-bin/webscr';
     $api_response = wp_remote_post($remote_url, $remote_post_vars);
     $succeeded = !is_wp_error($api_response);
     $message = '';
     if ($succeeded) {
         $result = 'succeeded';
         $subject = __('Your PayPal integration is working', 'charitable');
         $message = __('<p>Good news! We successfuly received the Instant Payment Notification from PayPal and were able to verify it with them.</p>', 'charitable');
         $message .= __('<p>This means that your website is all set to continue receiving donations through PayPal. You should not experience any issues when PayPal upgrades its SSL certificates.</p>', 'charitable');
         $message .= __('<p>Cheers<br />Eric & Wes', 'charitable');
     } else {
         $result = 'failed';
         $subject = __('Your PayPal test failed', 'charitable');
         $message .= __('<p>We received the Instant Payment Notification from PayPal but were not able to verify its authenticity.', 'charitable');
         $message .= __('<p>Our communicaton with PayPal failed with the following errors:</p>', 'charitable');
         $message .= '<ul>';
         foreach ($api_response->get_error_messages() as $error) {
             $message .= sprintf('<li>%s</li>', $error);
         }
         $message .= '</ul>';
         $message .= __('<p>Unfortunately, this means that you are likely to face problems with your PayPal donations from October 2016 onwards. Your donors will still be able to proceed to PayPal and make their donation, but their donations will not be automatically marked as Paid in your WordPress dashboard.</p>', 'charitable');
         $message .= __('<h3>Short-term fix</h3>', 'charitable');
         $message .= __('<p><strong>Disable IPN verification</strong>. This makes your donation verification process less secure, but it will allow your donations to continue getting marked as Paid. To set this up, log into your WordPress dashboard and go to <em>Charitable</em> > <em>Settings</em> > <em>Payment Gateways</em>, select your PayPal settings and enable the "Disable IPN Verification" setting.', 'charitable');
         $message .= __('<h3>Long-term solution</h3>', 'charitable');
         $message .= __('<p><strong>Get in touch with your web host</strong>. Please refer them to <a href="https://www.paypal-knowledge.com/infocenter/index?page=content&widgetview=true&id=FAQ1766&viewlocale=en_US">the upgrade information provided by PayPal</a>. You should also provide them with the error message you received from PayPal above.</p>', 'charitable');
         $message .= __('<p>If your web host is unable to upgrade the software on your server, we strongly recommend switching to a hosting platform that provides a more modern, and secure service.</p>', 'charitable');
         $message .= __('<p>Cheers<br />Eric & Wes', 'charitable');
     }
     /* Store the result. */
     update_option('charitable_paypal_sandbox_test', $result);
     /* Clear the token. */
     delete_option('charitable_paypal_sandbox_test_token');
     /* Set a transient to display the success/failure of the test. */
     set_transient('charitable_paypal-sandbox-test_notice', 1);
     /* Remove the transient about the PayPal upgrade. */
     delete_transient('charitable_release-143-paypal_notice');
     /* Send an email to the site admin. */
     ob_start();
     charitable_template('emails/header.php', array('email' => null, 'headline' => $subject));
     echo $message;
     charitable_template('emails/footer.php');
     $message = ob_get_clean();
     $headers = "From: Charitable <*****@*****.**>\r\n";
     $headers .= "Reply-To: support@wpcharitable.com\r\n";
     $headers .= "Content-Type: text/html; charset=utf-8\r\n";
     /* Send an email to the site administrator letting them know. */
     $sent = wp_mail(get_option('admin_email'), $subject, $message, $headers);
 }