Using PHP to set up and use STRIPE Elements to create a payment form and the request payment

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.

warning WARNING: This code is not 100% working code and has been dropped. See stripe-elements-checkout-onsession for a working replacement.

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 found on https://stripe.com/docs/testing#cards.

Note, because this is a demonstrator, little effort has been put into disabling the UI during processing - when going live you will want to consider patching these kinds of UX issues in order to avoid double-clicking purchase, etc.

To run stand-alone, outside of this explanation frame, click here.

STRIPE fees in the UK are: 1.4% + 20p for UK cards (+1.1% for European Economic Area) / 2.9% + 20p for international cards.

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

Code:

The full code can be found here:

stripe-elements-checkout-xrun.php :: Full code
<?php


include_once('class.const.php');

// class.const.php will contain php config settings:
//
//   class config {
//      Const stripePublicKey='pk_test.....';
//      Const stripeSecretKey='sk_test.....';
//      Const domain='.methodfish.com';
//      Const slash='/'; (or \\ in windows)
//   }



class PaymentForm {

    var $posterUID;
    // --------------------------------------------------------------------------------------

    public function getHTMLAddHeadCSSstyles() {
        return /**@lang CSS */ "
        body {
            font-family:Roboto;
            font-size:13pt;
            line-height:1.6em;   
        }
        #payment_form {
            max-width:600px;
            margin:20px;
            margin-left:auto;
            margin-right:auto;
        }
        pre {
            background-color: #cccccc;
            white-space:pre-wrap;
        }
        iframe, .iframe {
            border:none!important;
            box-shadow: none;
        }
        .frame {
            border:solid 1px #cbcaca;
            background-color:#f8f7f3;
            padding:10px;
        }
        .frame > div {
            max-width:1200px;
            margin:0 20px;
            margin-left:auto;
            margin-right:auto;
        }
        .card {
            max-width:50px;
            border:solid 1px #cfc8c8;
            border-radius:9px;
            vertical-align:middle;
        }
        form > input, form > textarea {
            width:calc(100% - 26px);
            padding:8px;
            margin:4px;
            border:solid 1px grey;
            border-radius:9px;
        }
        input[type='radio'] {
            width:20px!important;
            border-radius: 50%;
            width: 23px;
            height: 23px;
        
            border: 2px solid #999;
            transition: 0.2s all linear;
            margin-top:6px;
            margin-right: 5px;
        
            position: relative;
            top: 3px;
        }
        form > button {
            margin-bottom:10px;
        }
        button, .button {
            font-size:10pt;
            padding:10px;
            margin-top:10px;
            margin-right:10px;
            background-color:#11b4ff;
            color:white;
            border:none;
            cursor:pointer;
            transition:all 0.25s ease-in-out;
            text-decoration: none;
            min-width:100px;
            
            -webkit-touch-callout: none; /* iOS Safari */
            -webkit-user-select: none; /* Safari */
            -khtml-user-select: none; /* Konqueror HTML */
            -moz-user-select: none; /* Old versions of Firefox */
            -ms-user-select: none; /* Internet Explorer/Edge */
            user-select: none; /* Non-prefixed version, currently supported by Chrome, Edge, Opera and Firefox */
  
        }
        button:hover, .button:hover {
            background-color:#087baf;
        }
        button:disabled, .button:disabled {
            background-color:grey;
        }
        .info {
            display:inline-block;
            background-color:#e4f2fb;
            padding:10px;
            border-radius:10px;
            width:calc(100% - 20px);
        }
        .colPaleGreyBg {
            background-color:#d9d8d8!important;
        }
        .small {
            font-size:70%;
        }
        #error-message {
            background-color:red;
            color:white;
            margin-top:10px;
            border-radius:35px;
        }
        .warning { border:solid 1px red; }
        .colRedBg {
            background-color:red;
            color:white;
            padding:10px;
            margin-right:10px;
        }
        .colGreenBg {
            background-color:#19b619;
            color:white;
            padding:10px;
        }
        
        .hourglass {
            position:fixed;
            top:0;
            left:0;
            width:100vw;
            height:100vh;
            background-color:grey;
            opacity:0.5;
        }
        .centerBody {
            margin: 0;
            position: absolute;
            left: 50%;
            top: 20%;
            height: 20px;
            width: 200px;
            margin-right: -50% !important;
            transform: translate(-50%, -50%);
        }
        .spinner {
            font-size:40px!important;
            transform:rotate(-10deg);
        }
        .spinning {
            width:0;
            display: inline-block;
            animation: rotation 0.5s infinite linear;
            text-align:right;
        }
        
        @keyframes rotation {
            0% {
                transform: rotate(0deg);
                transform-origin: 20px 20px;
            }
            100% {
                transform: rotate(-360deg);
                transform-origin: 27px 23px;
            }
        }

        form > table {
            width:100%;
        }
        form > table td {
            white-space:nowrap;
        }
        form label, form input[type='radio'] {
            cursor:pointer;
        }
        ";
    }

    // --------------------------------------------------------------------------------------

    public function getHTMLAddHeadJavascript() {
        return /**@lang Javascript */ "
            //----------------------------
            function doDisableButtons() {
                var elems=document.getElementsByTagName('button');
                for(var e=0; e<elems.length; e++) elems[e].disabled=true;
                
                var elems=document.getElementsByTagName('input');
                for(var e=0; e<elems.length; e++) elems[e].disabled=true;
                
                var div=document.createElement('div');
                div.className='hourglass';
                document.body.appendChild(div);
                
                var div=document.createElement('div');
                div.className='centerBody';
                div.innerHTML='<div class=\"spinning\"><div class=\"material-icons spinner\">cached</div></div>';
                document.body.appendChild(div);
            }
            //----------------------------
            function doEnablePayment() {
                document.getElementById('payment').disabled=false;
            }
         ";
    }

    //----------------------------------------------------------------------------------

    
    public function doHTMLPrehook() {

        if ( !isset($_COOKIE['posterUID']) ) {
            $this->posterUID=date('Ymd').substr(bin2hex(random_bytes(16)),0,16);
            $arr_cookie_options = array (
                'expires' => time() + 60*60*24*1000,
                'path' => '/',
                'domain' => config::domain, // leading dot for compatibility or use subdomain
                'secure' => true,     // or false
                'httponly' => true,    // or false
                'samesite' => 'Lax' // None || Lax  || Strict
            );
            setcookie('posterUID', $this->posterUID, $arr_cookie_options);
        }
        else $this->posterUID=$_COOKIE['posterUID'];


        if ( strcmp($_SERVER['REQUEST_METHOD'], "POST")==0
            and strcmp($_SERVER['CONTENT_TYPE'], "application/json")==0) {
            //echo "<LI>POST detected: ".print_r($_POST, false)."</LI>";

            # retrieve json from POST body
            $json_str = file_get_contents('php://input');
            $json_obj = json_decode($json_str);

            //echo "<LI>Params:".$json_obj->payment_intent_id;
            if ( $json_obj->payment_intent_id ) {
                //echo "<LI>Detected Pii</LI>";

                $stripe_secretkey = config::stripeSecretKey;
                $stripe_publickey = config::stripePublicKey;

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

                $payment_intent = $stripe->paymentIntents->retrieve($json_obj->payment_intent_id);
                $this->doGenerateResponse($payment_intent, $stripe_publickey);
            }
            exit;
        }

    }
    

    //----------------------------------------------------------------------------------
    public function getCardHelperNote(string $last4) {
        $result="";
        switch ($last4) {
            case "3178":$result= "(Authentication Test cards = Insufficient funds)";break;
            case "0446":$result= "(Authentication Test cards = Already set up)";break;
            case "3184":$result= "(Authentication Test cards = Always authenticate)";break;
            case "3155":$result= "(Authentication Test cards = Authenticate unless set up)";break;
            case "0002":$result= "(Declined Test cards: Generic decline)";break;
            case "9995":$result= "(Declined Test cards: Insufficient funds decline)";break;
            case "9987":$result= "(Declined Test cards: Lost card decline)";break;
            case "9979":$result= "(Declined Test cards: Stolen card decline)";break;
            case "0069":$result= "(Declined Test cards: Expired card decline)";break;
            case "0127":$result= "(Declined Test cards: Incorrect CVC decline)";break;
            case "0119":$result= "(Declined Test cards: Processing error decline)";break;
            case "4241":$result= "(Declined Test cards: Incorrect number decline)";break;
            case "0019":$result= "(Fraud prevention - always blocked)";break;
            case "4954":$result= "(Fraud prevention - Highest risk)";break;
            case "9235":$result= "(Fraud prevention - Elevated risk)";break;
            case "0101":$result= "(Fraud prevention - CVC check fails)";break;
            case "0036":$result= "(Fraud prevention - Postal code check fails)";break;
            case "0028":$result= "(Fraud prevention - Line1 check fails)";break;
            case "0010":$result= "(Fraud prevention - Address checks fail)";break;
            case "0044":$result= "(Fraud prevention - Address unavailable)";break;
            case "0259":$result= "(Disputes - Fraudulent)";break;
            case "2685":$result= "(Disputes - Not received)";break;
            case "1976":$result= "(Disputes - Enquiry)";break;
            case "5423":$result= "(Disputes - Warning)";break;
            case "3155":$result= "(Authenticate unless set up)";break;
            case "3184":$result= "(Alway authenticate)";break;
            case "0446":$result= "(Authentication Already set up)";break;
            case "3178":$result= "(Authentication - Insufficient funds)";break;
        }
        if ( strcmp($result, "")!=0 ) return "<span class='small'>$result</span>";
        return "";
    }

    //----------------------------------------------------------------------------------
    public function getAlphaNumericTx($tx, $extraChars="") {
        $x="";
        for($p=0; $p<strlen($extraChars); $p++) {
            $x.="\\".substr($extraChars,$p,1);
        }
        return preg_replace("/[^a-zA-Z0-9$x]+/", "", $tx);
    }

    //----------------------------------------------------------------------------------
    public function getCustomerId(string $customerNm) {
        $fn=config::datFolder.config::slash."customer_$customerNm.dat";
        if ( file_exists($fn) ) {
            return file_get_contents($fn);
        }
        else return "";
    }

    //----------------------------------------------------------------------------------
    public function doStoreCustomer(string $customerNm, string $customerId) {
        file_put_contents(config::datFolder.config::slash."customer_$customerNm.dat", $customerId);
    }

    //----------------------------------------------------------------------------------
    
    function _showContent() {

        // This page will show a list of cards attached to the customer
        // and will offer to make a payment from one of them

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

        $this->doHTMLPrehook();


        // Prevent page from caching
        header("Expires: Tue, 03 Jul 2001 06:00:00 GMT");
        header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
        header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
        header("Cache-Control: post-check=0, pre-check=0", false);
        header("Pragma: no-cache");
        header("Connection: close");


        echo /**@lang HTML */ "<!DOCTYPE html><html lang='en'>";
        if ( 1 ) {

            echo /**@lang HTML */ "
            <head>
                <meta name='viewport' content='width=device-width, initial-scale=0.9, maximum-scale=1.0, user-scalable=no'/>
                <meta name='description' content='STRIPE elements checkout sample PHP/Javascript code'>
                <meta name='Keywords' content='stripe,php,checkout,example,sample,javascript'>
                <meta http-equiv='content-type' content='text/html; charset=utf-8'>
                <link rel=\"icon\" type=\"image/png\" href=\"images/methodfish.ico\">
                <title>STRIPE elements checkout sample PHP/Javascript code</title>
                <style>
                    " . $this->getHTMLAddHeadCSSstyles() . "
                </style>
                <script>
                    " . $this->getHTMLAddHeadJavascript() . "
                </script>
                <link rel='stylesheet preload prefetch' as='style' href='https://fonts.googleapis.com/icon?family=Courier+Prime|Roboto|Material+Icons|Material+Icons+Outlined'>
            </head>";


            echo "<body>";
            if (1) {

                echo "<div class='frame'>";
                if (1) {

                    echo "<div>";
                    if (1) {

                        echo "<h1 style='font-size:16pt'>STRIPE Test on ".date("D M d'y H:i:s")."</h1>";

                        $url="https://methodfish.com/stripe_elements_checkout_x.php";
                        $link="<a href='$url'>methodfish.com</a>";
                        echo "<p>This is a code test for STRIPE elements checkout card collection and payment. </p>";
                        echo "<p id='src-code'>See $link for more information</p>";
                        echo "<p style='background-color:#cbdeeb; padding:10px'><i class='material-icons' style='color:red; vertical-align: middle'>warning</i> 
                        WARNING: This code is not 100% working code and has been dropped. See <a href='stripe-elements-checkout-onsession.php' target='_parent'>stripe-elements-checkout-onsession</a> for a working replacement
                        </p>
                        ";


                        $customerNm = "customer ".$this->getAlphaNumericTx($this->posterUID);
                        echo "<BR>Customer: $customerNm</BR>";
                        $customerId = "";
                        $email = "";
                        $script = $_SERVER['SCRIPT_NAME'];

                        $stripe_secretkey = config::stripeSecretKey;
                        $stripe_publickey = config::stripePublicKey;

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


                        if ( 1 ) {
                            // because stripe search is not 100% reliable, we use own solution to check if customer exists
                            // (see https://stripe.com/docs/search#data-freshness)
                            $customerId = $this->getCustomerId($customerNm);
                        }
                        else {
                            // don't bother using customers->search() as it's unreliable
                            echo "<LI>Searching for $customerNm...</LI>";
                            $json = $stripe->customers->search(['query' => 'name:\'' . $customerNm . '\'']);
                            foreach ($json->data as $key) {
                                echo "<LI>Found id:[" . $key->id . "]";
                                if (strcmp($key->name, $customerNm) == 0) {
                                    $customerId = $key->id;
                                    $email = $key->email;
                                    break;
                                }
                            }
                            echo "<LI>Result to search is <PRE style='margin-left:20px'>$json</PRE>";
                        }
                        echo "<hr>";

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


                        if (strcmp($customerId, "") == 0) {

                            $email = str_replace(" ", "", 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>";
                            $this->doStoreCustomer($customerNm, $customerId);
                        }
                        // else echo "<LI>checkpoint 2: customer found</LI>";


                        $json = $stripe->customers->allPaymentMethods($customerId, ["type" => "card"]);
                        $cardsFound = false;
                        $disabled = "disabled";
                        $selectedPMI = "";


                        if ( strcmp($_SERVER['REQUEST_METHOD'], "GET")==0 ) {

                            echo "<form method='post' action='$script' name='paymentform'>";
                            if (1) {
                                echo "<input type='hidden' name='action' value='payment'>";
                                echo "<input type='hidden' name='step' value='paymentIntent'>";
                                echo "<input type='hidden' name='customerId' value='$customerId'>";

                                if ($json and isset($json->data[0])) {
                                    echo "<table>";
                                    foreach ($json->data as $paymentMethod) {
                                        //echo "<PRE>$paymentMethod</PRE>";
                                        $cardsFound = true;
                                        $id = $paymentMethod->id;
                                        $cardbrand = $paymentMethod->card->brand;
                                        $expy = $paymentMethod->card->exp_year;
                                        $expm = $paymentMethod->card->exp_month;
                                        $last4X = $paymentMethod->card->last4;

                                        $last4 = "**** **** **** $last4X";
                                        $expires = "Expires " . date("M/y", strtotime("$expy-$expm-01"));

                                        if (isset($_POST['selected-card-PMI']) and strcmp($_POST['selected-card-PMI'], $id) == 0) {
                                            $selected = "checked";
                                            $disabled = "";
                                            $selectedPMI = $id;
                                        }
                                        else $selected = "";


                                        $cardlogo = "<img src='https://methodfish.com/images/card_$cardbrand.png' class='card'>";
                                        $note = $this->getCardHelperNote($last4X);
                                        echo "<tr><td>";
                                        echo "<input type='radio' $selected name='selected-card-PMI' id='$id' value='$id' onClick='doEnablePayment()'>";
                                        echo "</td>";
                                        echo "<td>";
                                        echo "<label for='$id'>$cardlogo - $last4 $expires $note</label><br>";
                                        echo "</td></tr>";
                                    }
                                    echo "</table>";
                                }

                                if (!$cardsFound) echo "<p>no cards found</p>";

                                echo "<HR><button id='new' onClick='doDisableButtons(); window.location.href=\"$script?action=add\"'>Add New Card</button>";

                                if ($cardsFound) echo "<button id='payment' $disabled type='submit' onClick='paymentform.submit(); doDisableButtons(); '>Make Payment...</button>"; // This button will submit the form
                            }
                            echo "</form>";

                        }
                        else {

                            if ($json and isset($json->data[0])) {
                                foreach ($json->data as $paymentMethod) {
                                    //echo "<PRE>$paymentMethod</PRE>";
                                    $cardsFound = true;
                                    $id = $paymentMethod->id;

                                    if (isset($_POST['selected-card-PMI']) and strcmp($_POST['selected-card-PMI'], $id) == 0) {
                                        $selectedPMI = $id;
                                    }
                                }
                            }

                        }


                        $action = "";
                        if (isset($_GET['action'])) $action = $_GET['action'];
                        switch ($action) {
                            case "add":
                                $this->doAddCard($stripe, $customerId, $stripe_publickey);
                                break;
                        }

                        $action = "";
                        if (isset($_POST['action'])) $action = $_POST['action'];
                        switch ($action) {
                            case "payment":
                                $this->doMakePayment($stripe, $customerId, $selectedPMI, $stripe_publickey);

                                echo "<br><br><button onClick='window.location.href=window.location.origin+window.location.pathname;'>Restart</button>";
                                break;
                        }

                    }
                    echo "</div>";
                }
                echo "</div>";

                // Hide the src-code link if the code is running inside an iframe
                echo "<script>";
                echo "if ( window!==window.parent ) document.getElementById('src-code').innerHTML='';";
                echo "</script>";

            }
            echo "</body>";
        }
        echo "</html>";

    }
    

    // -----------------------------------------------------------------------------------------

    
    public function doAddCard($stripe, string $customerId, string $stripe_publickey) {

        try {

            $json = $stripe->setupIntents->create(['customer' => $customerId, 'payment_method_types' => ['card']]);

            $intentId = $json->id;
            $clientSecret = $json->client_secret;

            echo /**@lang HTML */ "
            
                <p class='info colPaleGreyBg'>
                HINT: Use the Test card options listed below (e.g. 4242424242424242 - expires 12/33, CVC 123.
                See <a href='https://stripe.com/docs/testing#cards' target='_blank'>STRIPE.com</a> for more test cards.
                </p>
                <p style='color:red'><i class='material-icons' style='vertical-align: middle; color: red'>warning</i> Never use real cards on this test page.</p>

                <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 Card</button>
                    <button id='cancel' type='button'>Cancel</button>
                </form>
                
                ";


            $url=$_SERVER['SCRIPT_NAME'];

            // See https://stripe.com/docs/payments/save-and-reuse?platform=web#web-collect-payment-details
            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');
                paymentElement.on('ready', (e) => paymentElement.focus());
                
                const form = document.getElementById('payment_form');

                document.getElementById('cancel').addEventListener('click', async (event) => {
                    doDisableButtons();
                    event.preventDefault();
                    window.location.href=window.location.origin+window.location.pathname;
                });
                
                
                form.addEventListener('submit', async (event) => {  // <---------------------
                    event.preventDefault();
                    
                    var target=document.getElementById('submit');
                    const messageContainer = document.querySelector('#error-message');
                    messageContainer.style.padding = '';
                    target.disabled=true;
                    target.innerHTML='Checking...';
                    
                    document.getElementById('error-message').innerHTML='';
                    
                    const {error} = await stripe.confirmSetup({ // <-------------------------
                            elements,
                            confirmParams: {
                                return_url: window.location.origin+window.location.pathname+'?card=saved' // It looks like this would ignore an iframe if the processing is in an iframe
                            }
                        });
                    
                    
                    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)
                        messageContainer.textContent = error.message;
                        messageContainer.style.padding = '10px 20px 10px 20px';
                        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();
        }

    }
    

    // -----------------------------------------------------------------------------------------

    
    public function doMakePayment($stripe, string $customerId, string $paymentMethodId, string $stripe_publickey) {
        // NOTE: We have already verified $paymentId belongs to $customerId

        if ( strcmp($_POST['step'], "paymentIntent")==0 ) {
            try {

                $selectedCardPMI=$_POST['selected-card-PMI'];
                $using="";
                $json = $stripe->customers->allPaymentMethods($customerId, ["type" => "card"]);
                if ($json and isset($json->data[0])) {
                    foreach ($json->data as $paymentMethod) {
                        $id = $paymentMethod->id;
                        $cardbrand = $paymentMethod->card->brand;
                        $expy = $paymentMethod->card->exp_year;
                        $expm = $paymentMethod->card->exp_month;
                        $last4X = $paymentMethod->card->last4;

                        $last4 = "**** **** **** $last4X";
                        $expires = "Expires " . date("M/y", strtotime("$expy-$expm-01"));


                        if ( strcmp($selectedCardPMI,$id)==0 ) {
                            $using="$cardbrand - $last4 $expires";
                            break;
                        }
                    }
                }

                if ( strcmp($using, "")==0 ) {
                    echo "<LI>Opps. Something went wrong. Please retry or contact support</LI>";
                    return;
                }

                $ccy="GBP";
                $amt=100 + random_int(0,100);
                $amtX=number_format($amt/100,2);
                $product="Product ABC";

                echo "<p id='notice'>charging $using card : $ccy$amtX for \"$product\"</p>";
                // See https://stripe.com/docs/payments/accept-a-payment-synchronously?platform=web#create-payment-intent
                $intent = $stripe->paymentIntents->create([
                                                              'amount'              => $amt,
                                                              'currency'            => "$ccy",
                                                              'description'         => "$product",
                                                              'customer'            => "$customerId",
                                                              'payment_method'      => "$selectedCardPMI",
                                                              'confirm'             => true,
                                                              'confirmation_method' => 'manual'
                                                          ]);

                //echo "<PRE>".print_r($response)."</PRE>";
//                if ( 1==2 ) {
//                    $newPaymentIntentId = $intent['id'];
//                    // The missing code (see https://stripe.com/docs/payments/accept-a-payment-synchronously?platform=web#create-payment-intent)...
//                    // start
//                    echo "<BR>Retrieving $paymentMethodId";
//                    $intent = $stripe->paymentIntents->retrieve($newPaymentIntentId);
//                    echo "<BR>Confirming..";
//                    $intent->confirm();
//                    echo "<BR>Confirmed";
//                    // end
//                }


                $this->doGenerateResponse($intent, $stripe_publickey);

            }
            catch (\Stripe\Exception\CardException $e) {
                // Error code will be authentication_required if authentication is needed
                echo "<LI>PaymentIntents create Exception.542: Error code is: <span class='colRedBg'>" . $e->getError()->code . "</span></LI>";
                $payment_intent_id = $e->getError()->payment_intent->id;
                echo "<LI>PII: $payment_intent_id</LI>";
                $payment_intent = $stripe->paymentIntents->retrieve($payment_intent_id);
                echo "<LI>PI:".$payment_intent;
            }
        }
        else {
            echo "<LI>MakePayment : $paymentId";
            if (strcmp($_POST['redirect_status'], 'processing') == 0) {
                echo "<h3>Processing payment details. We'll update you when processing is complete.</h3>";
            }

            if (strcmp($_POST['redirect_status'], 'requires_payment_method') == 0) {
                echo "<h3>Failed to process payment details. Please try another payment method.</h3>";
            }

            if (strcmp($_POST['redirect_status'], 'succeeded') == 0) {

                echo "<LI>Succeeded</LI>";

            }
        }

        echo "<LI>Done make payment";
    }
    

    // -----------------------------------------------------------------------------------------

    
    public function doGenerateResponse($intent, $stripe_publickey) {

        //if ( is_array($intent) ) {
        //    echo "<LI>Status:".$intent['status'];
        //}
        if ($intent->status == 'succeeded') {
            // Handle post-payment fulfillment
            //echo "<LI>Generate Response(1) : <span class='colGreenBg'>".$intent->status."</span> ";
            echo json_encode(['success' => true]);
        }
        elseif ($intent->status == 'requires_action') {

            //echo "<LI>Generate Response(2) : <span class='colRedBg'>".$intent->status."</span></LI>";
            # Tell the client to handle the action
            $jse=json_encode([
                                 'requiresAction' => true,
                                 'clientSecret' => $intent->client_secret
                             ]);


            echo /**@lang Javascript*/"
                <script src='https://js.stripe.com/v3/'></script>
                
                <script>
                    function handleServerResponseJS(responseJson) {
                                            
                        if (responseJson.error) {
                        
                            // Show error from server on payment form
                            console.error('ERROR.457: '+responseJson.error);
                            
                        } 
                        else if (responseJson.requiresAction) {
                                                    
                            // Use Stripe.js to handle required card action
                            stripe.handleCardAction(
                                responseJson.clientSecret
                            ).then(function(result) {
                                if (result.error) {
                                    // Show `result.error.message` in payment form
                                } else {
                                    // The card action has been handled
                                    // The PaymentIntent can be confirmed again on the server
                                    
                                    fetch(window.location.origin+window.location.pathname, {
                                        method: 'POST',
                                        headers: { 'Content-Type': 'application/json' },
                                        body: JSON.stringify({ payment_intent_id: result.paymentIntent.id })
                                        
                                    }).then(function(confirmResult) {
                                        return confirmResult.json();
                                    }).then(handleServerResponseJS);
                                }
                            });
                        } else {
                            // Show success message
                            alert('stripe_elements_checkout_x.php : SUCCESS');
                        }
                    }
                    
                    const stripe = Stripe('$stripe_publickey');
                    handleServerResponseJS(JSON.parse('$jse'));
                </script>
            ";
        }
        else {
            // Any other status would be unexpected, so error
            http_response_code(500);
            echo json_encode(['error' => 'Invalid PaymentIntent status : '.$intent->status]); // this returns to handleServerResponseJS()
        }
    }
    
}
try {
    $form = new PaymentForm();
    $form->_showContent(false);
}
catch (Exception $e) {
    echo "<BR>Exception Error.650: ".$e->getMessage();
}

Comments


New Comment

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

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



Sun Dec 04, 22 12:52:48