Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

CookieMonster's avatar

Using stripe elements with two submit button in a single form

I want the user to able to select whether to pay by credit or by card(using stripe). I only need form since user will input their address,postcode,time,etc and then submit the payment. I have two submit buttons where it based on which submit button is clicked should inform me which was selected.

<button  name="payment" value="paymentbycredit" type="submit">Pay by Credit</button>
 <button  name="payment" value="paymentbycard" type="submit">Pay by Card</button>

I tested it on a normal form and it will return the values of the button. I tried to integrate stripe into this to handle the submission. Here's how it looks like:


  <h1>Stripe Testing</h1>

  <form id="payment-form" method="POST" action="{{route('payment.success')}}" data-secret="{{ $intent }}" class="pt-40">
    @csrf
    <input type="text" required placeholder="card holder name" name="cardHolderName" class="block mt-1 w-full mb-4"
                 id="card-holder-name"
                 autofocus
                 autocomplete="name"/>
                 
    <div id="card-element">
        <!-- Elements will create input elements here -->
    </div>

    <!-- We'll put the error messages in this element -->
    <div id="card-errors" role="alert" class="text-danger"></div>

    <button  name="payment" value="paymentbycredit" type="submit">Pay by Credit</button>
    <button  name="payment" value="paymentbycard" type="submit">Pay by Card</button>
</form>

<script>
    var stripe = Stripe('{{ env('STRIPE_PUB_KEY') }}');
    var elements = stripe.elements();

    // Set up Stripe.js and Elements to use in checkout form
    var elements = stripe.elements();
    var style = {
        base: {
            color: "#32325d",
        }
    };

    var card = elements.create("card", { style: style });
    card.mount("#card-element");
    const cardHolderName = document.getElementById('card-holder-name');

    card.on('change', ({error}) => {
            let displayError = document.getElementById('card-errors');
            if (error) {
                displayError.textContent = error.message;
            } else {
                displayError.textContent = '';
            }
        });

        var form = document.getElementById('payment-form');

        form.addEventListener('submit', function(ev) {
            ev.preventDefault();
            // If the client secret was rendered server-side as a data-secret attribute
            // on the <form> element, you can retrieve it here by calling `form.dataset.secret`
            stripe.confirmCardPayment(form.dataset.secret, {
                payment_method: {
                    card: card,
                    billing_details: {
                        name: cardHolderName.value
                    }
                }
            }).then(function(result) {
                if (result.error) {
                    // Show error to your customer (e.g., insufficient funds)
                    console.log(result.error.message);
                } else {
                    // The payment has been processed!
                    if (result.paymentIntent.status === 'succeeded') {

                        form.submit();
                        
                        // Show a success message to your customer
                        // There's a risk of the customer closing the window before callback
                        // execution. Set up a webhook or plugin to listen for the
                        // payment_intent.succeeded event that handles any business critical
                        // post-payment actions.
                    }
                }
            });
        });


 </script>

However, once I submit the form, the request only shows cardHolderName but no request from the buttons. I figured something in the JS code might be preventing this from retrieving the button value. What seems to be the issue?

0 likes
5 replies
Snapey's avatar

create two forms, one with stripe, one without

change the ID of one to 'credit-form' so that stripe does not intercept submission

CookieMonster's avatar

Two separate forms but what if I need input data fields from credit-form to be part of the card-form ?

Snapey's avatar

if they are paying from credit balance, what else do you need?

CookieMonster's avatar

It looks something like below:

https://ibb.co/pz16Fvn

Clicking pay by credit brings up a modal and can confirm the payment then it hits my store method and send the input data to process the logic. Similarly clicking pay by credit should open up a modal where I can enter credit card info and confirm payment and hit the same method and process the input data.

Which was why I thought of getting it to work using a single form with two submit button.

Snapey's avatar

The stripe code is quite straightforward


        form.addEventListener('submit', function(ev) {
            ev.preventDefault();
            // If the client secret was rendered server-side as a data-secret attribute
            // on the <form> element, you can retrieve it here by calling `form.dataset.secret`
            stripe.confirmCardPayment(form.dataset.secret, {
                payment_method: {
                    card: card,
                    billing_details: {
                        name: cardHolderName.value
                    }
                }
            }).then(function(result) {
                if (result.error) {
                    // Show error to your customer (e.g., insufficient funds)
                    console.log(result.error.message);
                } else {
                    // The payment has been processed!
                    if (result.paymentIntent.status === 'succeeded') {

                        form.submit();
                        
                        // Show a success message to your customer
                        // There's a risk of the customer closing the window before callback
                        // execution. Set up a webhook or plugin to listen for the
                        // payment_intent.succeeded event that handles any business critical
                        // post-payment actions.
                    }
                }
            });

it listens for the payment form being submitted, then it does its stuff and then shows an error or allows the form to be posted to your site.

Clearly this is not going to work as it is when both methods use the same form.

You could alter the stripe example , and after catching the form submission, check which button was pressed and if it was credit then submit immediately, if not then allow stripe to do its thing.

If both buttons just open a modal, why can't they open different modals?

Please or to participate in this conversation.