2

I am migrating from Changes API to PaymentIntent API. I setup code successfully.

But I am wonder to see that every time I load the page stripe create a payment intent showing on stripe dashboad with "incomplete" payment status and after clicking payment button with all details this status turn to "successful" status.

PHP code

 $customer = \Stripe\Customer::create(array(
                'email' => $_SESSION['userEmail']
            ));
    $intent = \Stripe\PaymentIntent::create([
    'amount' => $varTotalPrice,
    'currency' => 'eur',
    'customer' => $customer->id,
    'payment_method_types' => ['card'],
    'description' => $arrCreditResult['creditTitle']
    ]);

As you know This provides me client_secret key using in js script.

JS code

<script type="text/javascript">
            var stripe = Stripe('<?php echo $pubkey; ?>');
            var elements = stripe.elements();
            var payBtnHtml = document.getElementById("submit").innerHTML;
            var card = elements.create('card', {
                style: {
                    base: {
                        iconColor: '#666EE8',
                        color: '#31325F',
                        lineHeight: '40px',
                        fontWeight: 600,
                        fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
                        fontSize: '15px',
                        '::placeholder': {
                            color: '#31325F',
                            fontWeight:300,
                            fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
                            fontSize: '15px'
                        }
                    }
                }
            });
            card.mount('#card-element');
            
            var cardholderName = document.querySelector('input[name=cardholder-name]');            
            var form = document.getElementById('payment-form');
            var clientSecret = document.getElementById('payment-form').getAttribute("data-secret");

            card.on('change', function(event) {
                var displayError = document.getElementById('card-errors');
                if (event.error) {
                    displayError.textContent = event.error.message;
                } else {
                    displayError.textContent = '';
                }
            });
                       
            var form = document.getElementById('payment-form');
            
            form.addEventListener('submit', function(ev) {
                ev.preventDefault();
                document.getElementById("submit").disabled = true;
                document.getElementById("submit").innerHTML = WAIT;
                stripe.confirmCardPayment(clientSecret, {
                    payment_method: {
                        card: card,
                        billing_details: {
                            name: cardholderName.value
                        }
                    }
                }).then(function(result) {
                    if (result.error) {
                        // Show error to your customer (e.g., insufficient funds)
                        document.getElementById("submit").disabled = false;
                        console.log(result.error.message);
                    } else {
                        // The payment has been processed!
                        if (result.paymentIntent.status === 'succeeded') {
                            document.getElementById("submit").disabled = false;
                            document.getElementById("payBtn").innerHTML=payBtnHtml
                            alert("paymemt done");
                            debug(result);
                            return false;
                            // 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>

I want to create a payment on stripe only when user hit the pay button. same as with Charges API.

Deepak Dholiyan
  • 1,774
  • 1
  • 20
  • 35
  • Could it be that you are instantiating `$intent` in your PHP-code before the form-submission? Maybe if you share more of the PHP method that handles this form it's easier to find what's wrong – Didier Dec 05 '20 at 15:36
  • @Didier, You are right above code is executing every time on page load. Because I need client_secret using in js code. I just want this should execute only on form submission. – Deepak Dholiyan Dec 08 '20 at 06:55

2 Answers2

0

You can refactor your code to only create a Payment Intent when needed. The steps would be as follows:

  1. Stop creating a Payment Intent every time the page loads and remove the data-secret attribute.
  2. Create a URL on your server that will create a Payment Intent on demand and return its client secret (typically it will return this information in JSON).
  3. In your JavaScript, when your customer presses the pay button, fetch the URL that creates a Payment Intent. Use the client secret in the response instead of the value of data-secret to complete the payment.
Justin Michael
  • 5,634
  • 1
  • 29
  • 32
  • Thanks for the reply. I understand what you said. I can create client secret with $intent = \Stripe\SetupIntent::create([ 'customer' => $customer->id ]); But when I click on payment button this said no payment information provided means (\Stripe\PaymentIntent) – Deepak Dholiyan Dec 08 '20 at 06:58
  • Hope you have worked on this and will provide me a solution. Thanks in advance. – Deepak Dholiyan Dec 08 '20 at 07:02
  • The solution is provided in my answer above; your code needs to be refactored so you only create a Payment Intent when needed. It's not a simple change, so I can't give you complete instructions. I recommend you look at [the accept-a-card-payment sample code](https://github.com/stripe-samples/accept-a-card-payment/tree/master/using-webhooks/server/php/public), but think about how this would work if the `fetch` in `script.js` to create and get the Payment Intent info moved to after you pressed the pay button instead of on load. – Justin Michael Dec 09 '20 at 17:35
0

Thanks for suggestion specially @justinMichael

After little hard work I find a working solution here:-

https://github.com/stripe-samples/accept-a-card-payment

Here I use method "without-webhooks":-

https://github.com/stripe-samples/accept-a-card-payment/tree/master/without-webhooks/server/php

This is easy to implement just need to make little changes.

  1. Change stripe keys.

  2. Check file path in stripe.js if you are renaming folder. Here they are using fetch("stripe-key.php") for keys and other stuff

  3. Make changes in pay.php file as per requirement.

Some more useful links you may need:-

  1. https://stripe.com/docs/js/appendix/supported_locales
  2. https://stripe.com/docs/api/errors/handling
  3. https://stripe.com/docs/api/metadata
Deepak Dholiyan
  • 1,774
  • 1
  • 20
  • 35