Stripe Payment Element

Created on 18 October 2022, almost 3 years ago
Updated 2 April 2023, over 2 years ago

Problem/Motivation

Stripe provides elements for payment and other ecommerce needs.

This module has Card and Payment Request elements.

Let's add this Payment element: https://stripe.com/docs/payments/payment-element

Steps to reproduce

Proposed resolution

Extend StripeBase Element.

Remaining tasks

Create class, update JS.

โœจ Feature request
Status

Active

Version

2.0

Component

Code

Created by

๐Ÿ‡บ๐Ÿ‡ธUnited States mortona2k Seattle

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • ๐Ÿ‡บ๐Ÿ‡ฆUkraine Anna D

    Anna D โ†’ made their first commit to this issueโ€™s fork.

  • @anna-d opened merge request.
  • @anna-d opened merge request.
  • ๐Ÿ‡บ๐Ÿ‡ฆUkraine Anna D

    Awesome @mortona2k you save my day

    Payment Element allows to add https://stripe.com/docs/payments/buy-now-pay-later methods (Affirm, Afterpay / Clearpay, Klarna).

    They required some return_url option.

    Added controller with Event to process payment intent.

    P.S Sorry I did wrong action to push to the opened MR. So attaching patch instead.

    FYI todo for future Afterpay also requires shipping details for confirmPayment.

  • ๐Ÿ‡บ๐Ÿ‡ฆUkraine Anna D

    Updated patch

  • ๐Ÿ‡บ๐Ÿ‡ฆUkraine Anna D

    Provided string instead of url object

  • Status changed to Needs review over 2 years ago
  • ๐Ÿ‡บ๐Ÿ‡ฆUkraine Anna D

    Combined @mortona2k commit and previous patch(interdiff) for testing

  • Status changed to Needs work over 2 years ago
  • ๐Ÿ‡จ๐Ÿ‡ฆCanada colan Toronto ๐Ÿ‡จ๐Ÿ‡ฆ

    Took a quick look at the code as I was looking for something, and noticed some minor things:

    +++ b/js/stripe.js
    @@ -134,99 +157,112 @@
    +          // if (elementSettings.type == 'paymentrequest') {
    +
    +          //   var paymentRequest = stripe.paymentRequest({
    +          //     country: elementSettings.country,
    +          //     currency: elementSettings.currency,
    +          //     total: {
    +          //       label: elementSettings.label,
    +          //       amount: elementSettings.amount,
    +          //     },
    +          //     requestPayerName: true,
    +          //     requestPayerEmail: true,
    +          //   });
    +
    +          //   stripeElementOptions.paymentRequest = paymentRequest;
    +
    +          //   // Create an instance of the PaymentRequest Element
    +          //   stripeElement = elements.create('paymentRequestButton', stripeElementOptions);
    +
    +          //   // Check the availability of the Payment Request API first.
    +          //   paymentRequest.canMakePayment().then(function($element, result) {
    +          //     if (result) {
    +          //       var $form = $element.closest('form');
    +          //       stripeElement.mount($element.find('.drupal-stripe-element')[0]);
    +
    +          //       stripeElement.on('click', function(event) {
    +          //         event.preventDefault();
    +          //         if (HTMLFormElement.prototype.reportValidity) {
    +          //           if (!$form[0].reportValidity()) {
    +          //             return false;
    +          //           }
    +          //         }
    +          //         $form.trigger('stripe:submit:start');
    +
    +          //         var ajaxId = new Date().getTime();
    +          //         $element.attr('data-drupal-stripe-trigger', ajaxId);
    +          //         $element.find('.drupal-stripe-trigger').val(ajaxId);
    +
    +          //         var formValues = $form.find(':input').not('.drupal-stripe-trigger, input[name="form_build_id"]').serialize();
    +          //         $form.attr('data-stripe-form-submit-last', formValues);
    +
    +          //         $element.find('.drupal-stripe-update').trigger('mousedown');
    +          //       });
    +          //     } else {
    +          //       $element.parent('.form-type-stripe-paymentrequest').hide();
    +          //     }
    +          //   }.bind(null, $element));
    +
    +          //   paymentRequest.on('cancel', function() {
    +          //     $form.trigger('stripe:submit:stop');
    +          //   });
    +
    +          //   paymentRequest.on('paymentmethod', function(ev) {
    +          //     // Confirm the PaymentIntent without handling potential next actions (yet).
    +          //     stripe.confirmCardPayment(
    +          //       client_secret,
    +          //       {payment_method: ev.paymentMethod.id},
    +          //       {handleActions: false}
    +          //     ).then(function(confirmResult) {
    +          //       if (confirmResult.error) {
    +          //         // Report to the browser that the payment failed, prompting it to
    +          //         // re-show the payment interface, or show an error message and close
    +          //         // the payment interface.
    +          //         $element.trigger('stripe:error', confirmResult.error.message);
    +          //         ev.complete('fail');
    +          //         $form.trigger('stripe:submit:stop');
    +          //       } else {
    +          //         // Report to the browser that the confirmation was successful, prompting
    +          //         // it to close the browser payment method collection interface.
    +          //         ev.complete('success');
    +          //         // Check if the PaymentIntent requires any actions and if so let Stripe.js
    +          //         // handle the flow. If using an API version older than "2019-02-11" instead
    +          //         // instead check for: `paymentIntent.status === "requires_source_action"`.
    +          //         if (confirmResult.paymentIntent.status === "requires_action") {
    +          //           // Let Stripe.js handle the rest of the payment flow.
    +          //           stripe.confirmCardPayment(client_secret).then(function(result) {
    +          //             if (result.error) {
    +          //               $element.trigger('stripe:error', result.error.message);
    +          //               // The payment failed -- ask your customer for a new payment method.
    +          //             } else {
    +          //               // The payment has succeeded.
    +          //               $form.trigger('stripe:submit');
    +          //             }
    +          //           });
    +          //         } else {
    +          //           // The payment has succeeded.
    +          //           $form.trigger('stripe:submit');
    +          //         }
    +          //       }
    +          //     });
    +          //   });
    +
    +          // }
    

    Can we remove this stuff that's commented out?

    +++ b/src/Element/Payment.php
    @@ -0,0 +1,27 @@
    +class Payment extends StripeBase {
    +
    +  protected static $type = 'payment';
    +
    +
    +  public static function processStripe(&$element, FormStateInterface $form_state, &$complete_form) {
    

    Double newline here; one can be removed.

  • ๐Ÿ‡จ๐Ÿ‡ฆCanada colan Toronto ๐Ÿ‡จ๐Ÿ‡ฆ

    Fixing title.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States Cellar Door

    Cellar Door โ†’ made their first commit to this issueโ€™s fork.

  • Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 8
    last update over 2 years ago
    Not currently mergeable.
  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 8
    last update over 2 years ago
    1 pass
  • Status changed to Needs review over 2 years ago
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States Cellar Door

    Cleaned up the branch commit history to include @Anna-D's commit and rebased off the project 2.x branch so the MR can be cleanly merged in.

  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 8
    last update over 2 years ago
    1 pass
  • ๐Ÿ‡บ๐Ÿ‡ฆUkraine Anna D

    Added automatic_payment_methods[enabled]=TRUE option

    According to the documentation https://stripe.com/docs/payments/payment-methods/integration-options#cho...

    It means that payment methods will be applied automatically according to Stripe account settings

    Note: testing mode shows all methods

  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 8
    last update over 2 years ago
    1 pass
  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 8
    last update over 2 years ago
    1 pass
  • ๐Ÿ‡บ๐Ÿ‡ฆUkraine Anna D

    Thank @Cellar Door for your help.

    Added some missed changes from #15 patch to the commit.
    Tested Klarna, Affirm and Card payment works.

  • ๐Ÿ‡จ๐Ÿ‡ฆCanada colan Toronto ๐Ÿ‡จ๐Ÿ‡ฆ

    Here's an immutable patch for Composer builds.

  • First commit to issue fork.
  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom jnpwebdeveloper

    Thanks for all the good work so far on this.

    Needed to pass in the stripeElementOptions to the new payment element.

    I hope I did this right. Here is the merge request:

    https://git.drupalcode.org/issue/stripe-3316114/-/merge_requests/2

    Also provided an immutable patch for Composer builds.

  • Status changed to Needs work 9 months ago
  • heddn Nicaragua

    Needs work for a quick rebase

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia prem suthar Ahemdabad- Gujrat , Jodhpur - Rajsthan
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia prem suthar Ahemdabad- Gujrat , Jodhpur - Rajsthan
  • Merge request !17Stripe 3316114 2.x 2 โ†’ (Open) created by Cellar Door
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States Cellar Door

    I rebased the current MR branch and opened a new one just to not squash the previous work with a force push. This should include all the efforts in this thread to date and provide some code cleanup along with allowing not just payment element support but also support setup intents used to do things like card on file, etc. when a payment isn't being created.

    @mortana2k - Want to take a peek and make sure I didn't squash any of the original work? Tested with a local site that's been running the patches in this thread and it seems to work great. Would love further testing/review before we mark it as RTBC.

    Hope this can cleanly merge in and provide some updates for folks wanting to implement this in various ways through custom modules.

  • Pipeline finished with Failed
    6 months ago
    Total: 288s
    #421558
  • Pipeline finished with Failed
    6 months ago
    Total: 150s
    #435210
  • Status changed to Needs review about 1 month ago
  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany n1k

    I applied the patch and changed the example to work with the new render array.

    1. Applied the patch
    2. Changed my Form Example to match the new render key
    3. Enabled Paypal as a Method in my Stripe Sandbox Dashboard
    4. Paypal shows up as a method in my form
    5. Select Paypal as Method
    6. Submit the Form
    -> I'm getting an error "Received unknown parameter: payment_method_data[return_url]".

    I've added a domain to my Paypal Method Configuration in the Stripe Dashboard but with no success.

    Besides that, I'm a bit confused on the documentation.
    It says support for "Stripe Elements" and "Stripe Payment Request Button".
    Stripe Payment Request Button supports Apple Pay, Google Pay and Link, so far understood.
    "Stripe Elements" lists a page, that also includes this element as an example.
    The current implementation provides only a "CC" Plugin, Credit Card, which is also used in the example.

    Am I right to assume there's no possibility to use a payment provider like Paypal without implementing an own Plugin and handle the API Flow on the javascript Side (which currently seems to be hardcoded to card) or waiting for this patch to land?

  • First commit to issue fork.
  • ๐Ÿ‡ง๐Ÿ‡ชBelgium kensae

    @n1k I noticed the same issue, the commit in #32 should resolve your issue.

  • Pipeline finished with Failed
    29 days ago
    Total: 564s
    #556804
  • heddn Nicaragua

    Anyone able to confirm if this makes things happy? If you do, feel free to drop in your steps to testing (similar to #31) and mark this RTBC.

  • Pipeline finished with Failed
    26 days ago
    Total: 152s
    #558692
  • Pipeline finished with Failed
    26 days ago
    Total: 230s
    #558718
  • Pipeline finished with Failed
    26 days ago
    Total: 141s
    #558731
  • Pipeline finished with Failed
    26 days ago
    Total: 140s
    #558737
  • ๐Ÿ‡ง๐Ÿ‡ชBelgium kensae

    We've integrated the 'stripe_payment' form element in a custom module.
    I can confirm it works as expected.

    1. We've used the last version of the branch stripe-3316114
    2. We've created a custom form in a custom module with the stripe_payment element type.
            // Load the payment intent from the form state.
            $payment_intent = $form_state->getValue(['payment', 'payment_intent']) ?? [];
            $payment_intent['description'] = $payment['description'];
            $payment_intent['metadata']['reference'] = $payment['reference'];
            $payment_intent['automatic_payment_methods'] = ['enabled' => true];  
         
            $form['payment'] = [
               '#type' => 'stripe_payment',
               '#stripe_amount' => round($payment['amount']) * 100,
               '#stripe_currency' => 'EUR',
               '#stripe_country' => $payment['billingAddress']['country'],
               '#stripe_paymentintent_unique' => TRUE,
               '#stripe_paymentintent' => $payment_intent,
               '#required' => TRUE,
             ];
         
    3. Enabled Card, Bancontact and Paypal as a payment methods in Stripe Sandbox Dashboard
    4. It shows the following form element:
    5. The card payment is handled onsite, and returns to a confirmation page, we redirect to in the form submit handler
    6. Bancontact and Paypal are handled offsite, and redirect to /stripe/checkout afterwards
Production build 0.71.5 2024