From 1b903715a4086300b270a025205cde239491e600 Mon Sep 17 00:00:00 2001
From: "Matthew Wire (MJW Consulting)" <mjw@mjwconsult.co.uk>
Date: Sun, 14 Oct 2018 23:22:17 +0100
Subject: [PATCH] Support Joomla/WP for IDS detection on webhooks

---
 CRM/Core/Payment/StripeIPN.php | 19 +++++++------
 stripe.php                     | 52 +++++++++++++++++++---------------
 2 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/CRM/Core/Payment/StripeIPN.php b/CRM/Core/Payment/StripeIPN.php
index 4ebb20da..e87a7a28 100644
--- a/CRM/Core/Payment/StripeIPN.php
+++ b/CRM/Core/Payment/StripeIPN.php
@@ -270,7 +270,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN {
           'contribution_status_id' => "In Progress"
         ));
 
-        return TRUE;
+        return;
 
       // Failed recurring payment.
       case 'invoice.payment_failed':
@@ -314,7 +314,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN {
           'modified_date' => $fail_date,
         ));
 
-        return TRUE;
+        return;
 
       // Subscription is cancelled
       case 'customer.subscription.deleted':
@@ -331,14 +331,14 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN {
         CRM_Core_DAO::executeQuery("DELETE FROM civicrm_stripe_subscriptions
           WHERE subscription_id = %1", $query_params);
 
-        return TRUE;
+        return;
 
       // One-time donation and per invoice payment.
       case 'charge.succeeded':
         //$this->setInfo();
         // TODO: Implement this so we can mark payments as failed?
         // Not implemented.
-        return TRUE;
+        return;
 
      // Subscription is updated. Delete existing recurring contribution and start a fresh one.
      // This tells a story to site admins over editing a recurring contribution record.
@@ -346,7 +346,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN {
        $this->setInfo();
        if (empty($this->previous_plan_id)) {
          // Not a plan change...don't care.
-         return TRUE;
+         return;
        }
        
        $new_civi_invoice = md5(uniqid(rand(), TRUE));
@@ -430,7 +430,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN {
             ));
           }
         }
-        return TRUE;
+        return;
 
       // Keep plans table in sync with Stripe when a plan is deleted.
      case 'plan.deleted':
@@ -444,10 +444,10 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN {
        CRM_Core_DAO::executeQuery("DELETE FROM civicrm_stripe_plans WHERE
          plan_id = %1 AND  processor_id = %2 and is_live = %3", $query_params);
 
-       return TRUE;
+       return;
     }
     // Unhandled event type.
-    return TRUE;
+    return;
   }
 
   /**
@@ -594,6 +594,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN {
   public function exception($message) {
     $errorMessage = 'StripeIPN Exception: Event: ' . $this->event_type . ' Error: ' . $message;
     Civi::log()->debug($errorMessage);
-    throw new CRM_Core_Exception($errorMessage);
+    //throw new CRM_Core_Exception($errorMessage);
+    exit();
   }
 }
diff --git a/stripe.php b/stripe.php
index cddfa582..8fda3cd6 100644
--- a/stripe.php
+++ b/stripe.php
@@ -39,22 +39,12 @@ function stripe_civicrm_uninstall() {
  * Implementation of hook_civicrm_enable().
  */
 function stripe_civicrm_enable() {
-  $UF_webhook_paths = array(
-    "Drupal"    => "/civicrm/payment/ipn/NN",
-    "Joomla"    => "/index.php/component/civicrm/?task=civicrm/payment/ipn/NN",
-    "WordPress" => "/?page=CiviCRM&q=civicrm/payment/ipn/NN"
-  );
-
-  // Use Drupal path as default if the UF isn't in the map above
-  $webookhook_path = (array_key_exists(CIVICRM_UF, $UF_webhook_paths)) ?
-    CIVICRM_UF_BASEURL . $UF_webhook_paths[CIVICRM_UF] :
-    CIVICRM_UF_BASEURL . $UF_webhook_paths['Drupal'];
-
+  $UFWebhookPath = stripe_get_webhook_path(TRUE);
   CRM_Core_Session::setStatus(
     "
     <br />Don't forget to set up Webhooks in Stripe so that recurring contributions are ended!
     <br />Webhook path to enter in Stripe:
-    <br/><em>$webookhook_path</em>
+    <br/><em>$UFWebhookPath</em>
     <br />Replace NN with the actual payment processor ID configured on your site.
     <br />
     ",
@@ -210,21 +200,37 @@ function stripe_civicrm_buildForm($formName, &$form) {
   }
 }
 
+/**
+ * Get the path of the webhook depending on the UF (eg Drupal, Joomla, Wordpress)
+ *
+ * @param bool $includeBaseUrl
+ *
+ * @return string
+ */
+function stripe_get_webhook_path($includeBaseUrl = TRUE) {
+  $UFWebhookPaths = [
+    "Drupal"    => "civicrm/payment/ipn/NN",
+    "Joomla"    => "?option=com_civicrm&task=civicrm/payment/ipn/NN",
+    "WordPress" => "?page=CiviCRM&q=civicrm/payment/ipn/NN"
+  ];
+
+
+  // Use Drupal path as default if the UF isn't in the map above
+  $UFWebhookPath = (array_key_exists(CIVICRM_UF, $UFWebhookPaths)) ?
+    $UFWebhookPaths[CIVICRM_UF] :
+    $UFWebhookPaths['Drupal'];
+  if ($includeBaseUrl) {
+    return CIVICRM_UF_BASEURL . '/' . $UFWebhookPath;
+  }
+  return $UFWebhookPath;
+}
+
 /*
  * Implementation of hook_idsException.
  *
  * Ensure webhooks don't get caught in the IDS check.
  */
 function stripe_civicrm_idsException(&$skip) {
-  // Handle old method.
-  $skip[] = 'civicrm/stripe/webhook';
-  $result = civicrm_api3('PaymentProcessor', 'get', array(
-    'sequential' => 1,
-    'return' => "id",
-    'class_name' => "Payment_stripe",
-    'is_active' => 1,
-  ));
-  foreach($result['values'] as $value) {
-    $skip[] = 'civicrm/payment/ipn/' . $value['id'];
-  }
+  // Path is always set to civicrm/payment/ipn (checked on Drupal/Joomla)
+  $skip[] = 'civicrm/payment/ipn';
 }
-- 
GitLab