diff --git a/css/elements.css b/css/elements.css
index b56a251799674be87c408d9d2bddb5491454b156..ba7d09ee4a622f89370847771b474d9215de0658 100644
--- a/css/elements.css
+++ b/css/elements.css
@@ -20,3 +20,8 @@
   margin: 2%;
   display: none;
 }
+
+#payment-request-button {
+  max-width: 400px;
+  margin: 2% auto;
+}
diff --git a/js/civicrm_stripe.js b/js/civicrm_stripe.js
index 7ea4f8bee876686f057f20ac49a8d0997eedfdff..79f861d2cf3d722898cbbb33666c5b076d00fa75 100644
--- a/js/civicrm_stripe.js
+++ b/js/civicrm_stripe.js
@@ -5,7 +5,10 @@
   // On initial load...
   var scriptName = 'civicrmStripe';
   var stripe = null;
-  var card = null;
+  var elements = {
+    card: null,
+    paymentrequest: null
+  };
   var form;
   var submitButtons;
   var stripeLoading = false;
@@ -131,27 +134,35 @@
     }
   }
 
-  function getPaymentElements() {
+  function getJQueryPaymentElements() {
     return {
-      card: $('div#card-element')
+      card: $('div#card-element'),
+      paymentrequest: $('div#paymentrequest-element')
     };
   }
 
   /**
    * Hide any visible payment elements
    */
-  function hidePaymentElements() {
-    getPaymentElements().card.hide();
+  function hideJQueryPaymentElements() {
+    var jQueryPaymentElements = getJQueryPaymentElements();
+    for (var elementName in jQueryPaymentElements) {
+      var element = jQueryPaymentElements[elementName];
+      element.hide();
+    }
   }
 
   /**
    * Destroy any payment elements we have already created
    */
   function destroyPaymentElements() {
-    if (card !== null) {
-      debugging("destroying card element");
-      card.destroy();
-      card = null;
+    for (var elementName in elements) {
+      var element = elements[elementName];
+      if (element !== null) {
+        debugging("destroying " + elementName + " element");
+        element.destroy();
+        elements[elementName] = null;
+      }
     }
   }
 
@@ -160,17 +171,21 @@
    * @returns {boolean}
    */
   function checkPaymentElementsAreValid() {
-    var elements = getPaymentElements();
-    if ((elements.card.length !== 0) && (elements.card.children().length === 0)) {
-      debugging('card element is empty');
-      return false;
+    var jQueryPaymentElements = getJQueryPaymentElements();
+    for (var elementName in jQueryPaymentElements) {
+      var element = jQueryPaymentElements[elementName];
+      if ((element.length !== 0) && (element.children().length !== 0)) {
+        debugging(elementName + ' element found');
+        return true;
+      }
     }
-    return true;
+    debugging('no valid elements found');
+    return false;
   }
 
   function handleCardPayment() {
     debugging('handle card payment');
-    stripe.createPaymentMethod('card', card).then(function (result) {
+    stripe.createPaymentMethod('card', elements.card).then(function (result) {
       if (result.error) {
         // Show error in payment form
         displayError(result.error.message, true);
@@ -314,45 +329,10 @@
     debugging('New Stripe ID: ' + CRM.vars.stripe.id + ' pubKey: ' + CRM.vars.stripe.publishableKey);
     stripe = Stripe(CRM.vars.stripe.publishableKey);
 
-    debugging('locale: ' + CRM.vars.stripe.locale);
     var stripeElements = stripe.elements({locale: CRM.vars.stripe.locale});
 
-    var style = {
-      base: {
-        fontSize: '1.1em', fontWeight: 'lighter'
-      }
-    };
-
-    var elementsCreateParams = {style: style, value: {}};
-
-    var postCodeElement = document.getElementById('billing_postal_code-' + CRM.vars.stripe.billingAddressID);
-    if (postCodeElement) {
-      var postCode = document.getElementById('billing_postal_code-' + CRM.vars.stripe.billingAddressID).value;
-      debugging('existing postcode: ' + postCode);
-      elementsCreateParams.value.postalCode = postCode;
-    }
-
-    // Cleanup any classes leftover from previous switching payment processors
-    getPaymentElements().card.removeClass();
-    // Create an instance of the card Element.
-    card = stripeElements.create('card', elementsCreateParams);
-    card.mount('#card-element');
-    debugging("created new card element", card);
-
-    if (postCodeElement) {
-      // Hide the CiviCRM postcode field so it will still be submitted but will contain the value set in the stripe card-element.
-      if (document.getElementById('billing_postal_code-5').value) {
-        document.getElementById('billing_postal_code-5')
-          .setAttribute('disabled', true);
-      }
-      else {
-        document.getElementsByClassName('billing_postal_code-' + CRM.vars.stripe.billingAddressID + '-section')[0].setAttribute('hidden', true);
-      }
-    }
-
-    card.addEventListener('change', function (event) {
-      cardElementChanged(event);
-    });
+    createElementCard(stripeElements);
+    //createElementPaymentRequest(stripeElements);
 
     setBillingFieldsRequiredForJQueryValidate();
     submitButtons = getBillingSubmit();
@@ -568,6 +548,100 @@
     return true;
   }
 
+  function createElementCard(stripeElements) {
+    var style = {
+      base: {
+        fontSize: '1.1em', fontWeight: 'lighter'
+      }
+    };
+
+    var elementsCreateParams = {style: style, value: {}};
+
+    var postCodeElement = document.getElementById('billing_postal_code-' + CRM.vars.stripe.billingAddressID);
+    if (postCodeElement) {
+      var postCode = document.getElementById('billing_postal_code-' + CRM.vars.stripe.billingAddressID).value;
+      debugging('existing postcode: ' + postCode);
+      elementsCreateParams.value.postalCode = postCode;
+    }
+
+    // Cleanup any classes leftover from previous switching payment processors
+    getJQueryPaymentElements().card.removeClass();
+    // Create an instance of the card Element.
+    elements.card = stripeElements.create('card', elementsCreateParams);
+    elements.card.mount('#card-element');
+    debugging("created new card element", elements.card);
+
+    if (postCodeElement) {
+      // Hide the CiviCRM postcode field so it will still be submitted but will contain the value set in the stripe card-element.
+      if (document.getElementById('billing_postal_code-5').value) {
+        document.getElementById('billing_postal_code-5')
+          .setAttribute('disabled', true);
+      }
+      else {
+        document.getElementsByClassName('billing_postal_code-' + CRM.vars.stripe.billingAddressID + '-section')[0].setAttribute('hidden', true);
+      }
+    }
+
+    elements.card.addEventListener('change', function (event) {
+      cardElementChanged(event);
+    });
+  }
+
+  function createElementPaymentRequest(stripeElements) {
+    var paymentRequest = null;
+    try {
+      paymentRequest = stripe.paymentRequest({
+        country: CRM.vars.stripe.country,
+        currency: CRM.vars.stripe.currency.toLowerCase(),
+        total: {
+          label: document.title,
+          amount: 0
+        },
+        requestPayerName: true,
+        requestPayerEmail: true
+      });
+    } catch(err) {
+      if (err.name === 'IntegrationError') {
+        debugging('Cannot enable paymentRequestButton: ' + err.message);
+        return;
+      }
+    }
+
+    // Check the availability of the Payment Request API first.
+    paymentRequest.canMakePayment().then(function(result) {
+      elements.paymentrequest = stripeElements.create('paymentRequestButton', {
+        paymentRequest: paymentRequest,
+        style: {
+          paymentRequestButton: {
+            // One of 'default', 'book', 'buy', or 'donate'
+            type: 'default',
+            // One of 'dark', 'light', or 'light-outline'
+            theme: 'dark',
+            // Defaults to '40px'. The width is always '100%'.
+            height: '64px'
+          }
+        }
+      });
+
+      elements.paymentrequest.on('click', function() {
+        debugging('PaymentRequest clicked');
+        paymentRequest.update({
+          total: {
+            label: document.title,
+            amount: CRM.payment.getTotalAmount() * 100
+          }
+        });
+      });
+
+      if (result) {
+        elements.paymentrequest.mount('#paymentrequest-element');
+        document.getElementById('paymentrequest-element').style.display = 'block';
+      } else {
+        document.getElementById('paymentrequest-element').style.display = 'none';
+      }
+    });
+  }
+
   /**
    * Validate a reCaptcha if it exists on the form.
    * Ideally we would use grecaptcha.getResponse() but the reCaptcha is already render()ed by CiviCRM
@@ -773,7 +847,7 @@
    */
   function triggerEventCrmBillingFormReloadFailed() {
     triggerEvent('crmBillingFormReloadFailed');
-    hidePaymentElements();
+    hideJQueryPaymentElements();
     displayError(ts('Could not load payment element - Is there a problem with your network connection?'), true);
   }