diff --git a/CRM/Core/Payment/Stripe.php b/CRM/Core/Payment/Stripe.php
index 4f2dcadba3fef1684bcc53aea2829594a238fb8d..e5b5a93e3b96bcad51dff54114394e5d4df22a32 100644
--- a/CRM/Core/Payment/Stripe.php
+++ b/CRM/Core/Payment/Stripe.php
@@ -618,6 +618,9 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
     $recurParams = [
       'id' => $params['contributionRecurID'],
       'trxn_id' => $stripeSubscription->id,
+      // FIXME processor_id is deprecated as it is not guaranteed to be unique, but currently (CiviCRM 5.9)
+      //  it is required by cancelSubscription (where it is called subscription_id)
+      'processor_id' => $stripeSubscription->id,
       'auto_renew' => 1,
       'cycle_day' => date('d'),
       'next_sched_contribution_date' => $this->calculateNextScheduledDate($params),
@@ -632,11 +635,6 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
       }
     }
 
-    // FIXME: Is this required?
-    // Add subscription_id so tests can properly work with recurring
-    // contributions. 
-    $params['subscription_id'] = $stripeSubscription->id;
-
     // Hook to allow modifying recurring contribution params
     CRM_Stripe_Hook::updateRecurringContribution($recurParams);
     // Update the recurring payment
@@ -830,7 +828,7 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
   public function cancelSubscription(&$message = '', $params = []) {
     $this->setAPIParams();
 
-    $contributionRecurId = CRM_Utils_Array::value('crid', $_GET);
+    $contributionRecurId = $this->getRecurringContributionId($params);
     try {
       $contributionRecur = civicrm_api3('ContributionRecur', 'getsingle', array(
         'id' => $contributionRecurId,
@@ -1021,5 +1019,39 @@ INNER JOIN civicrm_contribution con ON ( con.contribution_recur_id = rec.id )
     return isset($this->_paymentProcessor['url_recur']) ? $this->_paymentProcessor['url_recur'] : '';
   }
 
+  /**
+   * Get the recurring contribution ID from parameters passed in to cancelSubscription
+   * Historical the data passed to cancelSubscription is pretty poor and doesn't include much!
+   *
+   * @param array $params
+   *
+   * @return int|null
+   */
+  protected function getRecurringContributionId($params) {
+    // Not yet passed, but could be added via core PR
+    $contributionRecurId = CRM_Utils_Array::value('contribution_recur_id', $params);
+    if (!empty($contributionRecurId)) {
+      return $contributionRecurId;
+    }
+
+    // Not yet passed, but could be added via core PR
+    $contributionId = CRM_Utils_Array::value('contribution_id', $params);
+    try {
+      return civicrm_api3('Contribution', 'getvalue', ['id' => $contributionId, 'return' => 'contribution_recur_id']);
+    }
+    catch (Exception $e) {
+      $subscriptionId = CRM_Utils_Array::value('subscriptionId', $params);
+      if (!empty($subscriptionId)) {
+        try {
+          return civicrm_api3('ContributionRecur', 'getvalue', ['processor_id' => $subscriptionId, 'return' => 'id']);
+        }
+        catch (Exception $e) {
+          return NULL;
+        }
+      }
+      return NULL;
+    }
+  }
+
 }
 
diff --git a/CRM/Stripe/Upgrader.php b/CRM/Stripe/Upgrader.php
index 8a2522110e59636b4b3681accc3ffe03e5f7b401..8e45b14d77280412ee88e4e1711c4994d7b23e0c 100644
--- a/CRM/Stripe/Upgrader.php
+++ b/CRM/Stripe/Upgrader.php
@@ -389,4 +389,12 @@ class CRM_Stripe_Upgrader extends CRM_Stripe_Upgrader_Base {
 
     return TRUE;
   }
+
+  public function upgrade_5021() {
+    $this->ctx->log->info('Applying Stripe update 5021.  Copy trxn_id to processor_id so we can cancel recurring contributions.');
+    civicrm_api3('StripeSubscription', 'copytrxnidtoprocessorid', []);
+
+    return TRUE;
+  }
+
 }
diff --git a/api/v3/StripeSubscription.php b/api/v3/StripeSubscription.php
index 37c4744666e52b544e07fd85cfe404dcba47c464..d1fa2045b011cf06b41ff8c7fce7bd0450d4a7e1 100644
--- a/api/v3/StripeSubscription.php
+++ b/api/v3/StripeSubscription.php
@@ -112,3 +112,31 @@ function civicrm_api3_stripe_subscription_updatetransactionids() {
   }
   return civicrm_api3_create_success($counts);
 }
+
+/**
+ * API function (used in 5021 upgrader) to copy trxn_id to processor_id in civicrm_contribution_recur table
+ * processor_id (named subscriptionId) is the only value available to cancelSubscription in 5.9 (and earlier).
+ * It is not ideal as processor_id is not guaranteed to be unique in the CiviCRM database (trxn_id is unique).
+ *
+ * @return array
+ */
+function civicrm_api3_stripe_subscription_copytrxnidtoprocessorid() {
+  $sql = "SELECT cr.trxn_id, cr.processor_id, cr.payment_processor_id, cpp.class_name FROM civicrm_contribution_recur cr
+LEFT JOIN civicrm_payment_processor AS cpp ON cr.payment_processor_id = cpp.id
+WHERE cpp.class_name = 'Payment_Stripe'";
+  $dao = CRM_Core_DAO::executeQuery($sql);
+  $counts = [
+    'updated' => 0,
+  ];
+  while ($dao->fetch()) {
+    if (!empty($dao->trxn_id) && empty($dao->processor_id)) {
+      $updateSQL = "UPDATE civicrm_contribution_recur
+SET processor_id=%1
+WHERE trxn_id=%1;";
+      $updateParams = [1 => [$dao->trxn_id, 'String']];
+      CRM_Core_DAO::executeQuery($updateSQL, $updateParams);
+      $counts['updated']++;
+    }
+  }
+  return civicrm_api3_create_success($counts);
+}
diff --git a/docs/api.md b/docs/api.md
index 2a30395371ce3b8d10d66976156e0559d26a85e4..299761aed7f382b3284c6a4bd41ffa218b80ec1f 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -20,4 +20,5 @@ The api commands are:
 ### Additionally for upgrading:
 
 * `StripeCustomer.updatecontactids` - Used to migrate civicrm_stripe_customer table to match on contact_id instead of email address.
-* `StripeSubscription.updatetransactionids` - Used to migrate civicrm_stripe_subscriptions to use recurring contributions directly.
\ No newline at end of file
+* `StripeSubscription.updatetransactionids` - Used to migrate civicrm_stripe_subscriptions to use recurring contributions directly.
+* `StripeSubscription.copytrxnidtoprocessorid` - Used to copy trxn_id to processor_id in civicrm_contribution_recur table so we can use cancelSubscription. Hopefully this won't be needed in future versions of CiviCRM if we can pass more sensible values to the cancelSubscription function.
\ No newline at end of file
diff --git a/docs/recur.md b/docs/recur.md
index 3d1e32b7d0adae9eb6b452ba82ebcfcd9b6d17d8..5ab4b66fab6223a47d8e522907a22337950a6a56 100644
--- a/docs/recur.md
+++ b/docs/recur.md
@@ -9,15 +9,11 @@ Stripe notifies CiviCRM every time a recurring contribution is processed / updat
 
 In order to take advantage of this feature, you must configure Stripe with the right "Webhook Endpoint".
 
-You can find the location of this setting in your Stripe Dashboard by clicking the API menu item on the left, and then choose the Webhook tab.
+To do this, log into Stripe Dashboard and from the menu on the left, choose Developers > Webhooks and click Add Endpoint.
 
-Then click Add Endpoint.
+At this point, you need to figure out the "URL to be called" value. To do this, you need to check what ID is assigned to the Stripe payment processor in CiviCRM.
 
-Now, you need to figure out what your end point is.
-
-To figure out the "URL to be called" value, you need to check what ID is assigned to your payment processor.
-
-To determine the correct setting, go back to your CiviCRM screen and click `Administer -> System Settings -> Payment Processor`
+To determine the ID, go back to CiviCRM and click `Administer -> System Settings -> Payment Processor`
 
 Click Edit next to the payment processor you are setting up.
 
diff --git a/info.xml b/info.xml
index a96f4b69bbdfcc15e17e02d8dd9ed1194e4be4bc..8dcaf5fcf037387814fced647453bba493637e5b 100644
--- a/info.xml
+++ b/info.xml
@@ -12,8 +12,8 @@
     <author>Matthew Wire (MJW Consulting)</author>
     <email>mjw@mjwconsult.co.uk</email>
   </maintainer>
-  <releaseDate>2018-11-21</releaseDate>
-  <version>5.2beta1</version>
+  <releaseDate>2018-12-13</releaseDate>
+  <version>5.2beta2</version>
   <develStage>beta</develStage>
   <compatibility>
     <ver>5.3</ver>
diff --git a/js/civicrm_stripe.js b/js/civicrm_stripe.js
index 0455d6d859855c94e4b1bcf9894ec9f09b4310c5..f520c0da269e1de1964ff38f62d248d95895ca85 100644
--- a/js/civicrm_stripe.js
+++ b/js/civicrm_stripe.js
@@ -47,6 +47,9 @@ CRM.$(function($) {
   // Prepare the form.
   var onclickAction = null;
   $(document).ready(function() {
+    // Disable the browser "Leave Page Alert" which is triggered because we mess with the form submit function.
+    window.onbeforeunload = null;
+    // Load Stripe onto the form.
     loadStripeBillingBlock();
     $submit = getBillingSubmit();