Using PHP to set up and use setupIntents with the STRIPE payment gateway

This is a walk through of the PHP & Javascript code required for collecting a card payment method using to save the card details ready for collecting payments later.

The code here is using the STRIPE developers test environment and will not collect real funds.

As a pre-requisit for your own coding, you will need to have created a STRIPE account and acquired the public and secret keys from your STRIPE dashboard.
You will also have used composer to install the STRIPE API into your application vendor folders using the command line composer require stripe/stripe-php

The code is broken down into a few steps to set-up a customer on the STRIPE environment and then create a form to collect the credit card details that will be used by a background billing process later; use the STRIPE test cards listed below - or found on https://stripe.com/docs/testing#cards.

Also see Sagepage checkout

Written: July-2022 PHP: 7+ STRIPE.js: v3

Step 1 Code:

Set up your STRIPE keys; these are provided to you from your STRIPE dashboard see https://dashboard.stripe.com/test/apikeys for your own.
NOTE: These are best stored in config files that are different between dev and live environments.

stripe_api.php
stripe_api.php
require 'autoload.php'; // (prerequisite: composer require stripe/stripe-php)

$stripe_secretkey = "sk_test_.....";
$stripe_publickey = "pk_test_.....";

$stripe = new \Stripe\StripeClient($stripe_secretkey);

// Simplistic response to card save post...
if (isset($_GET['confirmed'])) {
    echo "Redirecting after alert...";
    echo "<script>alert('Card Saved');document.location.href='stripe_api.php#step3-result';</script>";
}

Step 2 Code:

Search STRIPE for the customer


stripe_api.php
$json = $stripe->customers->search(['query' => 'name:\'' . $customerNm . '\'']);

foreach ($json->data as $key) {
    //echo "<LI>id:" . $key->id . ", email:" . $key->email . "<br>";
    if (strcmp($key->name, $customerNm) == 0) {
        $customerId = $key->id;
        $email = $key->email;
        break;
    }
}

echo "<UL>Found [$customerId] on STRIPE; attached email is [$email]</UL>";

Step 2 Result:

  • checkpoint 1 : Searching STRIPE for name='customer X'.
      Found [cus_MCbYUK7GS6pCye] on STRIPE; attached email is [abc@customerX.com]
  • Step 3 Code:

    Create the STRIPE customer if it does not already have one.

    In this case we are using customer name as the Unique Identifier, but you would need to consider this when implementing your own solution.


    stripe_api.php
    if (strcmp($customerId, "") == 0) {
        echo "<LI>checkpoint 2</LI>";
        $email = str_replace(" ", "", "abc@$customerNm.com");
        $json = $stripe->customers->create(
            [
                'email' => $email,
                'name'  => $customerNm,
            ]
        );
        //echo "<LI><PRE>" . print_r($json, true) . "</PRE>";
        $customerId = $json->id;
        echo "<UL>Created New STRIPE customer id: [$customerId]</UL>";
    }
    else echo "<LI>checkpoint 2: customer found</LI>";

    Step 3 Result:

  • checkpoint 2: customer found
  • Step 4 Code:

    Create a STRIPE customer intent by creating the <form> using the client-secret created using setupIntents->create, and then using this in the javascript that follows this will tell stripe.js to populate the empty form with some input fields.


    stripe_api.php
    echo "<LI>checkpoint 3: creating a setupintent</LI>";
    try {
    
        $json = $stripe->setupIntents->create(
            ['customer'               => $customerId
             , 'payment_method_types' => ['card'] // ,'bacs_debit'
            ]);
    
    
        $intentId = $json->id;
        $clientSecret = $json->client_secret;
    
        echo /**@lang HTML */"
        
        <LI>setupIntent Id=$intentId</LI>
        <BR><HR>
        
        <p class='info colPaleGreyBg'>HINT: Use the Test card options listed below (e.g. 4242424242424242 - expires 12/33, CVC 123</p><BR><BR>
        
        <form id='payment_form' data-secret='$clientSecret'>
            <div id='payment-element'>
              <!-- Elements will create form elements here-->
            </div>
            
            <div id='error-message'></div>
            <button id='submit'>Save</button>
        </form>
        
        ";
    
        echo "".$this->getCardHelperTable()."";
    
    
        echo /**@lang Javascript */"
        
        <script src='https://js.stripe.com/v3/'></script>
        <script>
    
        const stripe = Stripe('$stripe_publickey');
        const options = {
              clientSecret: '$clientSecret'
            };
            
        // Set up Stripe.js and Elements to use in checkout form, passing the client secret obtained in step 2
        const elements = stripe.elements(options);
        
        // Create and mount the Payment Element
        const paymentElement = elements.create('payment');
        paymentElement.mount('#payment-element');
        
        const form = document.getElementById('payment_form');
    
        form.addEventListener('submit', async (event) => {
            event.preventDefault();
            
            var target=document.getElementById('submit');
            target.disabled=true;
            target.innerHTML='Checking...';
            
            const {error} = await stripe.confirmSetup({
                    //`Elements` instance that was used to create the Payment Element
                    elements,
                    confirmParams: {
                        return_url: 'http://methodfish.com/stripe_api.php?confirmed=Y',
                    }
                });
            
                if (error) {
                    // This point will only be reached if there is an immediate error when
                    // confirming the payment. Show error to your customer (for example, payment
                    // details incomplete)
                    const messageContainer = document.querySelector('#error-message');
                    messageContainer.textContent = error.message;
                    alert(error.message);
                    target.disabled=false;
                    target.innerHTML='Save';
                } else {
                    // Your customer will be redirected to your `return_url`. For some payment
                    // methods like iDEAL, your customer will be redirected to an intermediate
                    // site first to authorize the payment, then redirected to the `return_url`.
                    alert('This never happens');
                }
            }
        );
        </script>
        ";
    }
    catch (Exception $e) {
        echo "<LI>Payment method creation failed " . $e->getMessage();
    }

    Step 4 Result:

  • checkpoint 3: creating a setupintent
  • setupIntent Id=seti_1LV0SCESHvtQP0M8XE6sk2P0


  • HINT: Use the Test card options listed below (e.g. 4242424242424242 - expires 12/33, CVC 123






    expand_more Test card options:

  • See https://stripe.com/docs/testing#cards.
  • Step 5 Code:

    After this - I want to charge the customer using a new process each month - but this is where I can't find any examples to proceed. 🙁

    No code found

    Comments


    New Comment

    NOTE: (Put code blocks in [[[ and ]]] markup to be formatted.)

    (Posted comments will be checked by the administrator before being published)