[Tut] Stripe One Time Payment with Prebuilt Hosted Checkout in PHP - Printable Version +- Sick Gaming (https://www.sickgaming.net) +-- Forum: Programming (https://www.sickgaming.net/forum-76.html) +--- Forum: PHP Development (https://www.sickgaming.net/forum-82.html) +--- Thread: [Tut] Stripe One Time Payment with Prebuilt Hosted Checkout in PHP (/thread-99038.html) |
[Tut] Stripe One Time Payment with Prebuilt Hosted Checkout in PHP - xSicKxBot - 03-22-2022 Stripe One Time Payment with Prebuilt Hosted Checkout in PHP <div style="margin: 5px 5% 10px 5%;"><img src="https://www.sickgaming.net/blog/wp-content/uploads/2020/10/stripe-one-time-payment-with-prebuilt-hosted-checkout-in-php.jpg" width="550" height="190" title="" alt="" /></div><div><p>Last modified on October 6th, 2020.</p> <p>Stripe provides payment processing to support eCommerce software and mobile APPs. The key features by Stripe are,</p> <ul> <li>fast and interactive checkout experience.</li> <li>secure, smooth payment flow.</li> <li>scope to uplift the conversion rate and business growth.</li> </ul> <p>Stripe is the most popular payment gateway solution supporting card payments along with PayPal. Its complete documentation helps developers to do an effortless integration.</p> <p>Stripe provides different types of payment services to accept payments. It supports accepting one-time payment, recurring payment, in-person payment and more.</p> <p>There are two ways to set up the Stripe one-time payment option in a eCommerce website.</p> <ol> <li>Use the secure <strong>prebuilt hosted checkout page</strong>.</li> <li>Create a <strong>custom payment flow</strong>.</li> </ol> <p>Let us take the first method to integrate Stripe’s one-time payment. The example code redirects customers to the Stripe hosted checkout page. It’s a pre-built page that allows customers to enter payment details.</p> <p>Stripe hosted checkout option piggybacks on the Stripe trust factor. If your website is lesser-known, if you are not popular, then it is best to choose this option. Because the end users may feel uncomfortable to enter their card details on your page.</p> <p>This diagram depicts the Stripe payment flow, redirect and response handling.</p> <p><img loading="lazy" class="alignnone size-large wp-image-12166" src="https://phppot.com/wp-content/uploads/2020/10/stripe-hosted-checkout-block-diagram-550x190.jpg" alt="Stripe Hosted Checkout Block Diagram" width="550" height="190" srcset="https://phppot.com/wp-content/uploads/2020/10/stripe-hosted-checkout-block-diagram-550x190.jpg 550w, https://phppot.com/wp-content/uploads/2020/10/stripe-hosted-checkout-block-diagram-300x103.jpg 300w, https://phppot.com/wp-content/uploads/2020/10/stripe-hosted-checkout-block-diagram-768x265.jpg 768w, https://phppot.com/wp-content/uploads/2020/10/stripe-hosted-checkout-block-diagram-1536x530.jpg 1536w, https://phppot.com/wp-content/uploads/2020/10/stripe-hosted-checkout-block-diagram.jpg 1664w" sizes="(max-width: 550px) 100vw, 550px"></p> <p>In this example, it uses the latest checkout version to set up a one-time payment. If you want to <a href="https://phppot.com/php/manage-recurring-payments-using-stripe-billing-in-php/">create Stripe subscription payment</a>, then the linked article has an example for it.</p> <h2>What is inside?</h2> <ol> <li><a href="https://phppot.com/php/stripe-one-time-payment-with-prebuilt-hosted-checkout-in-php/#about-stripe-checkout">About Stripe Checkout</a></li> <li><a href="https://phppot.com/php/stripe-one-time-payment-with-prebuilt-hosted-checkout-in-php/#steps-to-set-up-stripe-one-time-payment-flow">Steps to set up Stripe one-time payment flow</a></li> <li><a href="https://phppot.com/php/stripe-one-time-payment-with-prebuilt-hosted-checkout-in-php/#about-this-example">About this example</a></li> <li><a href="https://phppot.com/php/stripe-one-time-payment-with-prebuilt-hosted-checkout-in-php/#generate-and-configure-stripe-api-keys">Generate and configure Stripe API keys</a></li> <li><a href="https://phppot.com/php/stripe-one-time-payment-with-prebuilt-hosted-checkout-in-php/#create-webhook-and-map-events">Create webhook and map events</a></li> <li><a href="https://phppot.com/php/stripe-one-time-payment-with-prebuilt-hosted-checkout-in-php/#required-libraries-to-access-stripe-api">Required libraries to access Stripe API</a></li> <li><a href="https://phppot.com/php/stripe-one-time-payment-with-prebuilt-hosted-checkout-in-php/#create-client-server-side-code-to-initiate-checkout">Create client-server-side code to initiate checkout</a></li> <li><a href="https://phppot.com/php/stripe-one-time-payment-with-prebuilt-hosted-checkout-in-php/#capture-and-process-webhook-response">Capture and process webhook response</a></li> <li><a href="https://phppot.com/php/stripe-one-time-payment-with-prebuilt-hosted-checkout-in-php/#evaluate-integration-with-test-data">Evaluate integration with test data</a></li> <li><a href="https://phppot.com/php/stripe-one-time-payment-with-prebuilt-hosted-checkout-in-php/#stripe-one-time-payment-example-output">Stripe one-time payment example output</a></li> </ol> <h2 id="about-stripe-checkout">About Stripe Checkout</h2> <p>Latest Stripe Checkout provides a frictionless smooth checkout experience. The below list shows some features of the latest Stripe checkout version.</p> <ul> <li>Strong Customer Authentication (SCA).</li> <li>Checkout interface fluidity over various devices’ viewport.</li> <li>Multilingual support.</li> <li>Configurable options to enable billing address collection, email receipts, and Button customizations</li> </ul> <p>If you are using the legacy version, it’s so simple to migrate to the latest Stripe Checkout version. The upgraded version supports advanced features like <strong>3D secure</strong>, mobile payments and more.</p> <h2 id="steps-to-set-up-stripe-one-time-payment-flow">Steps to setup Stripe one-time payment flow</h2> <p>The below steps are the least needs to <a href="https://stripe.com/docs/checkout/integration-builder" target="_blank" rel="noopener noreferrer">set up a Stripe one-time payment</a> online.</p> <ol> <li>Register with Stripe and generate API keys.</li> <li>Configure API keys with the application.</li> <li>Install and load the required libraries to access API.</li> <li>Create client and server-side code to make payments.</li> <li>Create endpoints to receive payment response and log into a database.</li> <li>Create a UI template to acknowledge customers.</li> </ol> <p>We will see the above steps in this article with example code and screenshots.</p> <h2 id="about-this-example">About Stripe payment integration example</h2> <p>Stripe API allows applications to access and use its online payment services. It provides Stripe.js a JavaScript library to initiate the payment session flow.</p> <p>This example code imports the Stripe libraries to access the API functions. It sets the endpoint to build the request and receive the response.</p> <p>The client and server-side code redirect customers to the Stripe hosted checkout page. In the callback handlers, it processes the payment response sent by the API.</p> <p>This example uses a database to store payment entries. It uses <a href="https://phppot.com/php/crud-with-mysqli-prepared-statement-using-php/">MySQLi with prepared statements</a> to execute queries.</p> <p>This image shows the simple file architecture of this example<span>.</span></p> <p><img loading="lazy" class="alignnone wp-image-12101 size-full" src="https://phppot.com/wp-content/uploads/2020/10/stripe-hosted-checkout-file-structure.jpg" alt="Stripe Hosted Checkout File Structure" width="350" height="563" srcset="https://phppot.com/wp-content/uploads/2020/10/stripe-hosted-checkout-file-structure.jpg 350w, https://phppot.com/wp-content/uploads/2020/10/stripe-hosted-checkout-file-structure-187x300.jpg 187w" sizes="(max-width: 350px) 100vw, 350px"></p> <h2 id="generate-and-configure-stripe-api-keys">Get and configure Stripe API keys</h2> <p>Register and log in with Stripe to get the API keys. Stripe dashboard will show two keys publishable_key and secret_key.</p> <p>These keys are the reference to validate the request during the authentication process.</p> <p><strong>Note:</strong> Once finish testing in a sandbox mode, Stripe requires to activate the account to get the live API keys.</p> <p><img loading="lazy" class="alignnone wp-image-12114 size-large" src="https://phppot.com/wp-content/uploads/2020/10/get-stripe-api-keys-550x328.png" alt="Get Stripe API Keys" width="550" height="328" srcset="https://phppot.com/wp-content/uploads/2020/10/get-stripe-api-keys-550x328.png 550w, https://phppot.com/wp-content/uploads/2020/10/get-stripe-api-keys-300x179.png 300w, https://phppot.com/wp-content/uploads/2020/10/get-stripe-api-keys.png 600w" sizes="(max-width: 550px) 100vw, 550px"></p> <p>This code shows the constants created to configure the API keys for this example.</p> <pre class="prettyprint lang-php"><?php namespace Phppot; class Config { const ROOT_PATH = "https://your-domain/stripe-hosted"; /* Stripe API test keys */ const STRIPE_PUBLISHIABLE_KEY = ""; const STRIPE_SECRET_KEY = ""; /* PRODUCT CONFIGURATIONS BEGINS */ const PRODUCT_NAME = 'A6900 MirrorLess Camera'; const PRODUCT_IMAGE = Config::ROOT_PATH . '/images/camera.jpg'; const PRODUCT_PRICE = '289.61'; const CURRENCY = 'USD'; const PRODUCT_TYPE = 'good'; } </pre> <h2 id="create-webhook-and-map-events">Create webhook and map events</h2> <p>Creating a webhook is a conventional way to get the payment notifications sent by the API. All payment gateway providers give the option to create webhook for callback.</p> <p>In <a href="https://phppot.com/php/paypal-payment-gateway-integration-in-php/">PayPal payment gateway integration</a> article, we have seen the types of notification mechanisms supported by PayPal.</p> <p>The code has the webhook endpoint registered with Stripe. It handles the API responses based on the event that occurred.</p> <p>The below image shows the screenshot of the add-endpoint dialog. It populates the URL and the mapped events in the form fields.</p> <p>Navigate via <em>Developers->Webhooks</em> and click the <em>Add endpoint</em> button to see the dialog.</p> <p><a href="https://phppot.com/wp-content/uploads/2020/10/add-stripe-webhook-endpoint.jpg"><img loading="lazy" class="alignnone size-large wp-image-12118" src="https://phppot.com/wp-content/uploads/2020/10/add-stripe-webhook-endpoint-550x553.jpg" alt="Add Stripe Webhook Endpoint" width="550" height="553" srcset="https://phppot.com/wp-content/uploads/2020/10/add-stripe-webhook-endpoint-550x553.jpg 550w, https://phppot.com/wp-content/uploads/2020/10/add-stripe-webhook-endpoint-298x300.jpg 298w, https://phppot.com/wp-content/uploads/2020/10/add-stripe-webhook-endpoint-150x150.jpg 150w, https://phppot.com/wp-content/uploads/2020/10/add-stripe-webhook-endpoint.jpg 631w" sizes="(max-width: 550px) 100vw, 550px"></a></p> <h2 id="required-libraries-to-access-stripe-api">Required libraries to access Stripe API</h2> <p>First, download and install the <strong>stripe-php</strong> library. This will help to send flawless payment initiation request to the Stripe API.</p> <p>This command helps to install this library via Composer. It is also available to <a href="https://github.com/stripe/stripe-php/releases">download from GitHub.</a></p> <pre class="prettyprint lang-php">composer require stripe/stripe-php </pre> <p>Load Stripe.js JavaScript library into the page which has the checkout button. Load this file by using https://js.stripe.com/v3/ instead of having it in local.</p> <pre class="prettyprint lang-php"><script src="https://js.stripe.com/v3/"></script> </pre> <h2 id="create-client-server-side-code-to-initiate-checkout">Create client-server code to process checkout</h2> <p>This section includes the steps needed to create the client-server code for setting up the Stripe one-time payment.</p> <ol> <li>Add checkout button and load Stripe.js</li> <li>Create a JavaScript event handler to initiate checkout session</li> <li>Create PHP endpoint to post create-checkout-session request</li> <li>Redirect customers to the Stripe hosted checkout page</li> <li>Get checkout session-id from the response.</li> </ol> <h3>HTML page with Stripe checkout button</h3> <p>This page has HTML code to add the Stripe checkout button. It loads the Stripe.js library.</p> <p>This page loads a JavaScript that initiates the checkout session and redirects the user to the prebuilt Stripe hosted checkout.</p> <p>The Stripe hosted checkout form handles the card validation effectively. We have created a custom car validator for <a href="https://phppot.com/php/authorize-net-payment-gateway-integration-using-php/">Authorize.net payment integration</a> code. Hosted checkout is more secure than handling card details by custom handlers.</p> <p class="code-heading">index.php</p> <pre class="prettyprint lang-php"><?php namespace Phppot; ?> <html> <title>Stripe Prebuilt Hosted Checkout</title> <head> <link href="css/style.css" type="text/css" rel="stylesheet" /> <script src="https://js.stripe.com/v3/"></script> </head> <body> <div class="phppot-container"> <h1>Stripe Prebuilt Hosted Checkout</h1> <div id="payment-box"> <img src="images/camera.jpg" /> <h4 class="txt-title">A6900 MirrorLess Camera</h4> <div class="txt-price">$289.61</div> <button id="checkout-button">Checkout</button> </div> </div> <script> var stripe = Stripe('<?php echo Config::STRIPE_PUBLISHIABLE_KEY; ?>'); var checkoutButton = document.getElementById('checkout-button'); checkoutButton.addEventListener('click', function() { fetch('create-checkout-session.php', { method: 'POST', }) .then(function(response) { return response.json(); }) .then(function(session) { return stripe.redirectToCheckout({ sessionId: session.id }); }) .then(function(result) { if (result.error) { alert(result.error.message); } }) .catch(function(error) { console.error('Error:', error); }); }); </script> </body> </html> </pre> <h3>JavaScript event handler initiates checkout session</h3> <p>In the previous section, it loads a JavaScript to do the following.</p> <ol> <li>Instantiate Stripe Javascript library object with the reference of the Stripe Publishable key.</li> <li>Map the checkout button’s click event to initiate a create-checkout-session.</li> <li>Redirect customers to the Stripe hosted checkout page with the checkout session id.</li> </ol> <p>It calls the PHP endpoint builds the API request params to start a checkout session.</p> <p>Then it receives the checkout-session-id as returned by the PHP endpoint. The <em>redirectToCheckout()</em> method sends customers to the prebuilt checkout to complete the payment.</p> <h3>PHP endpoint processing create-checkout-session request</h3> <p>When clicking the checkout button, the JavaScript executes an AJAX request. It fetches the PHP endpoint processing the create-checkout-session request.</p> <p>The below code shows how to create the Stripe checkout-session via API. The API request is with the required query parameters. It includes the product detail, unit amount, payment method and more.</p> <p>Then the API will return the session object after processing this request. This endpoint parses the response and grab the session-id and return it.</p> <p class="code-heading">ajax-endpoint/create-checkout-session.php</p> <pre class="prettyprint lang-php"><?php namespace Phppot; use Phppot\StripeService; use Phppot\StripePayment; $orderReferenceId = rand(100000, 999999); require_once __DIR__ . "/../lib/StripeService.php"; require_once __DIR__ .'/../Common/Config.php'; require_once __DIR__ . '/../lib/StripePayment.php'; $stripePayment = new StripePayment(); $stripeService = new StripeService(); $currency = Config::CURRENCY; $orderId = $stripePayment->insertOrder(Config::PRODUCT_PRICE, $currency, $orderReferenceId, "Payment in-progress"); $unitAmount = Config::PRODUCT_PRICE * 100; $session = $stripeService->createCheckoutSession($unitAmount, $orderId); echo json_encode($session); </pre> <p>The StripeService is a PHP class created to build API requests and process responses.</p> <p>The createCheckoutSession() function builds the param array for the create-checkout-session request.</p> <p>This service also handles the webhook responses sent by the API. The API sends the response on the occurrences of the events mapped with the webhook endpoint URL.</p> <p class="code-heading">lib/StripeService.php</p> <pre class="prettyprint lang-php"><?php namespace Phppot; require_once __DIR__ . '/../Common/Config.php'; class StripeService { function __construct() { require_once __DIR__ . "/../vendor/autoload.php"; // Set your secret key. Remember to set your live key in production! \Stripe\Stripe::setApiKey(Config::STRIPE_SECRET_KEY); } public function createCheckoutSession($unitAmount, $clientReferenceId) { $checkout_session = \Stripe\Checkout\Session::create([ 'payment_method_types' => ['card'], 'line_items' => [[ 'price_data' => [ 'currency' => Config::CURRENCY, 'unit_amount' => $unitAmount, 'product_data' => [ 'name' => Config::PRODUCT_NAME, 'images' => [Config::PRODUCT_IMAGE], ], ], 'quantity' => 1, ]], 'mode' => 'payment', 'client_reference_id' => $clientReferenceId, 'success_url' => Config::ROOT_PATH . '/success.php?session_id={CHECKOUT_SESSION_ID}', 'cancel_url' => Config::ROOT_PATH . '/index.php?status=cancel', ]); return $checkout_session; } public function captureResponse() { $payload = @file_get_contents('php://input'); $event = json_decode($payload); require_once __DIR__ . "/../lib/StripePayment.php"; $stripePayment = new StripePayment(); switch($event->type) { case "customer.created": $param["stripe_customer_id"] = $event->data->object->id; $param["email"] = $event->data->object->email; $param["customer_created_datetime"] = date("Y,m,d H:i:s", $event->data->object->created); $param["stripe_response"] = json_encode($event->data->object); $stripePayment->insertCustomer($param); break; case "checkout.session.completed": $param["order_id"] = $event->data->object->client_reference_id; $param["customer_id"] = $event->data->object->customer; $param["payment_intent_id"] = $event->data->object->payment_intent; $param["stripe_checkout_response"] = json_encode($event->data->object); $stripePayment->updateOrder($param); break; case "payment_intent.created": $param["payment_intent_id"] = $event->data->object->id; $param["payment_create_at"] = date("Y-m-d H:i:s", $event->data->object->created); $param["payment_status"] = $event->data->object->status; $param["stripe_payment_response"] = json_encode($event->data->object); $stripePayment->insertPayment($param); break; case "payment_intent.succeeded": $param["payment_intent_id"] = $event->data->object->id; $param["billing_name"] = $event->data->object->charges->data[0]->billing_details->name; $param["billing_email"] = $event->data->object->charges->data[0]->billing_details->email; $param["payment_last_updated"] = date("Y-m-d H:i:s", $event->data->object->charges->data[0]->created); $param["payment_status"] = $event->data->object->charges->data[0]->status; $param["stripe_payment_response"] = json_encode($event->data->object); $stripePayment->updatePayment($param); break; case "payment_intent.canceled": $param["payment_intent_id"] = $event->data->object->id; $param["billing_name"] = $event->data->object->charges->data[0]->billing_details->name; $param["billing_email"] = $event->data->object->charges->data[0]->billing_details->email; $param["payment_last_updated"] = date("Y-m-d H:i:s", $event->data->object->charges->data[0]->created); $param["payment_status"] = $event->data->object->charges->data[0]->status; $param["stripe_payment_response"] = json_encode($event->data->object); $stripePayment->updatePayment($param); break; case "payment_intent.payment_failed": $param["payment_intent_id"] = $event->data->object->id; $param["billing_name"] = $event->data->object->charges->data[0]->billing_details->name; $param["billing_email"] = $event->data->object->charges->data[0]->billing_details->email; $param["payment_last_updated"] = date("Y-m-d H:i:s", $event->data->object->charges->data[0]->created); $param["payment_status"] = $event->data->object->charges->data[0]->status; $param["stripe_payment_response"] = json_encode($event->data->object); $stripePayment->updatePayment($param); break; } http_response_code(200); } } </pre> <h2 id="capture-and-process-webhook-response">Capture and process response</h2> <p>The <em>capture-response.php</em> file calls the StripeService class to handle the webhook response.</p> <p>The registered webhook endpoint has the mapping for the events. The figure shows the mapped events and the webhook URL below.</p> <p><img loading="lazy" class="alignnone wp-image-12121 size-large" src="https://phppot.com/wp-content/uploads/2020/10/stripe-developers-webhook-detail-550x200.jpg" alt="Stripe Developers Webhook Detail" width="550" height="200" srcset="https://phppot.com/wp-content/uploads/2020/10/stripe-developers-webhook-detail-550x200.jpg 550w, https://phppot.com/wp-content/uploads/2020/10/stripe-developers-webhook-detail-300x109.jpg 300w, https://phppot.com/wp-content/uploads/2020/10/stripe-developers-webhook-detail-768x279.jpg 768w, https://phppot.com/wp-content/uploads/2020/10/stripe-developers-webhook-detail.jpg 791w" sizes="(max-width: 550px) 100vw, 550px"></p> <p>The captureResponse() function handles the API response based on the events that occurred.</p> <p>On each event, it updates the customer, order database tables. It creates the payment response log to put entries into the tbl_stripe_response table.</p> <p class="code-heading">webhook-ep/capture-response.php</p> <pre class="prettyprint lang-php"><?php namespace Phppot; use Phppot\StriService; require_once __DIR__ . "/../lib/StripeService.php"; $stripeService = new StripeService(); $stripeService->captureResponse(); ?> </pre> <p>It invokes the StripeService function captureResponse(). It calls StripePayment to store Orders, Customers and Payment data into the database.</p> <p>The StripePayment class it uses DataSource to connect the database and access it.</p> <p class="code-heading">lib/StripePayment.php</p> <pre class="prettyprint lang-php"><?php namespace Phppot; use Phppot\DataSource; class StripePayment { private $ds; function __construct() { require_once __DIR__ . "/../lib/DataSource.php"; $this->ds = new DataSource(); } public function insertOrder($unitAmount, $currency, $orderReferenceId, $orderStatus) { $orderAt = date("Y-m-d H:i:s"); $insertQuery = "INSERT INTO tbl_order(order_reference_id, amount, currency, order_at, order_status) VALUES (?, ?, ?, ?, ?) "; $paramValue = array( $orderReferenceId, $unitAmount, $currency, $orderAt, $orderStatus ); $paramType = "sisss"; $insertId = $this->ds->insert($insertQuery, $paramType, $paramValue); return $insertId; } public function updateOrder($param) { $paymentDetails = $this->getPaymentByIntent($param["payment_intent_id"]); if (! empty($paymentDetails)) { if($paymentDetails[0]["payment_status"] == "succeeded") { $paymentStatus = "Paid"; } else if($paymentDetails[0]["payment_status"] == "requires_source") { $paymentStatus = "Payment in-progress"; } $query = "UPDATE tbl_order SET stripe_customer_id = ?, stripe_payment_intent_id = ?, stripe_checkout_response = ?, order_status = ? WHERE id = ?"; $paramValue = array( $param["customer_id"], $param["payment_intent_id"], $param["stripe_checkout_response"], $paymentStatus, $param["order_id"] ); $paramType = "ssssi"; $this->ds->execute($query, $paramType, $paramValue); } } public function insertCustomer($customer) { $insertQuery = "INSERT INTO tbl_customer(stripe_customer_id, email, customer_created_datetime, stripe_response) VALUES (?, ?, ?, ?) "; $paramValue = array( $customer["stripe_customer_id"], $customer["email"], $customer["customer_created_datetime"], $customer["stripe_response"] ); $paramType = "ssss"; $this->ds->insert($insertQuery, $paramType, $paramValue); } public function insertPayment($param) { $insertQuery = "INSERT INTO tbl_payment(stripe_payment_intent_id, payment_create_at, payment_status, stripe_payment_response) VALUES (?, ?, ?, ?) "; $paramValue = array( $param["payment_intent_id"], $param["payment_create_at"], $param["payment_status"], $param["stripe_payment_response"] ); $paramType = "ssss"; $this->ds->insert($insertQuery, $paramType, $paramValue); } public function updatePayment($param) { $query = "UPDATE tbl_payment SET billing_name = ?, billing_email = ?, payment_last_updated = ?, payment_status = ?, stripe_payment_response = ? WHERE stripe_payment_intent_id = ?"; $paramValue = array( $param["billing_name"], $param["billing_email"], $param["payment_last_updated"], $param["payment_status"], $param["stripe_payment_response"], $param["payment_intent_id"] ); $paramType = "ssssss"; $this->ds->execute($query, $paramType, $paramValue); } public function getPaymentByIntent($paymentIntent) { $query = "SELECT * FROM tbl_payment WHERE stripe_payment_intent_id = ?"; $paramValue = array( $paymentIntent ); $paramType = "s"; $result = $this->ds->select($query, $paramType, $paramValue); return $result; } } ?> </pre> <h3>Showing success page after payment</h3> <p>As sent with the create-checkout-session request, Stripe invokes the success page URL after payment.</p> <p>The below code has the payment success message to acknowledge customers.</p> <p class="code-heading">success.php</p> <pre class="prettyprint lang-php"><?php namespace Phppot; require_once __DIR__ . '/Common/Config.php'; ?> <html> <head> <title>Payment Response</title> <link href="./css/style.css" type="text/css" rel="stylesheet" /> </head> <body> <div class="phppot-container"> <h1>Thank you for shopping with us.</h1> <p>You have purchased "<?php echo Config::PRODUCT_NAME; ?>" successfully.</p> <p>You have been notified about the payment status of your purchase shortly.</p> </div> </body> </html> </pre> <h2 id="database-script">Database script</h2> <p>Import the following SQL script to execute this example in your environment. It has the SQL to create tables created for this example and to build a relationship between them.</p> <p>sql/structure.sql</p> <pre class="prettyprint lang-php">-- -- Table structure for table `tbl_customer` -- CREATE TABLE `tbl_customer` ( `id` int(11) NOT NULL, `stripe_customer_id` varchar(255) NOT NULL, `email` varchar(50) NOT NULL, `customer_created_datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `stripe_response` text NOT NULL, `create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- -------------------------------------------------------- -- -- Table structure for table `tbl_order` -- CREATE TABLE `tbl_order` ( `id` int(11) NOT NULL, `order_reference_id` varchar(255) NOT NULL, `stripe_customer_id` varchar(255) DEFAULT NULL, `stripe_payment_intent_id` varchar(255) DEFAULT NULL, `amount` decimal(10,2) NOT NULL, `currency` varchar(10) NOT NULL, `order_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `order_status` varchar(25) NOT NULL, `stripe_checkout_response` text NOT NULL, `create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- -------------------------------------------------------- -- -- Table structure for table `tbl_payment` -- CREATE TABLE `tbl_payment` ( `id` int(11) NOT NULL, `stripe_payment_intent_id` varchar(255) NOT NULL, `payment_create_at` timestamp NULL DEFAULT NULL, `payment_last_updated` timestamp NULL DEFAULT '0000-00-00 00:00:00', `billing_name` varchar(255) NOT NULL, `billing_email` varchar(255) NOT NULL, `payment_status` varchar(255) NOT NULL, `stripe_payment_response` text NOT NULL, `create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- -- Indexes for dumped tables -- -- -- Indexes for table `tbl_customer` -- ALTER TABLE `tbl_customer` ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `stripe_customer_id` (`stripe_customer_id`); -- -- Indexes for table `tbl_order` -- ALTER TABLE `tbl_order` ADD PRIMARY KEY (`id`), ADD KEY `stripe_payment_intent_id` (`stripe_payment_intent_id`), ADD KEY `stripe_customer_id` (`stripe_customer_id`); -- -- Indexes for table `tbl_payment` -- ALTER TABLE `tbl_payment` ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `stripe_payment_intent_id` (`stripe_payment_intent_id`); -- -- AUTO_INCREMENT for dumped tables -- -- -- AUTO_INCREMENT for table `tbl_customer` -- ALTER TABLE `tbl_customer` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; -- -- AUTO_INCREMENT for table `tbl_order` -- ALTER TABLE `tbl_order` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; -- -- AUTO_INCREMENT for table `tbl_payment` -- ALTER TABLE `tbl_payment` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; -- -- Constraints for dumped tables -- -- -- Constraints for table `tbl_order` -- ALTER TABLE `tbl_order` ADD CONSTRAINT `tbl_order_ibfk_1` FOREIGN KEY (`stripe_payment_intent_id`) REFERENCES `tbl_payment` (`stripe_payment_intent_id`), ADD CONSTRAINT `tbl_order_ibfk_2` FOREIGN KEY (`stripe_customer_id`) REFERENCES `tbl_customer` (`stripe_customer_id`); COMMIT; </pre> <h2 id="evaluate-integration-with-test-data">Evaluate integration with test data</h2> <p>After integrating Stripe one-time payment, evaluate the integration with test card details.</p> <p>The following test card details help to try a successful payment flow.</p> <table class="tutorial-table" width="100%"> <tbody> <tr> <td>Card Number</td> <td>4242424242424242</td> </tr> <tr> <td>Expiry Month/Year</td> <td>Any future date</td> </tr> <tr> <td>CVV</td> <td>Three-digit number</td> </tr> </tbody> </table> <p>Stripe provides more <a href="https://stripe.com/docs/testing" target="_blank" rel="noopener noreferrer">test card details</a> to receive more types of responses.</p> <h2 id="stripe-one-time-payment-example-output">Stripe one-time payment example output</h2> <p>This example displays a product tile with the Stripe Checkout button as shown below.</p> <p><img loading="lazy" class="alignnone size-full wp-image-12132" src="https://phppot.com/wp-content/uploads/2020/10/Stripe-Payment-Landing-Page.jpg" alt="Stripe Payment Landing Page" width="305" height="429" srcset="https://phppot.com/wp-content/uploads/2020/10/Stripe-Payment-Landing-Page.jpg 305w, https://phppot.com/wp-content/uploads/2020/10/Stripe-Payment-Landing-Page-213x300.jpg 213w" sizes="(max-width: 305px) 100vw, 305px"></p> <p>On clicking the Checkout button, it redirects customers to the prebuilt Stripe hosted checkout page.</p> <p><img loading="lazy" class="alignnone size-large wp-image-12133" src="https://phppot.com/wp-content/uploads/2020/10/stripe-hosted-checkout-page-550x317.jpg" alt="Stripe Hosted Checkout Page" width="550" height="317" srcset="https://phppot.com/wp-content/uploads/2020/10/stripe-hosted-checkout-page-550x317.jpg 550w, https://phppot.com/wp-content/uploads/2020/10/stripe-hosted-checkout-page-300x173.jpg 300w, https://phppot.com/wp-content/uploads/2020/10/stripe-hosted-checkout-page-768x443.jpg 768w, https://phppot.com/wp-content/uploads/2020/10/stripe-hosted-checkout-page.jpg 800w" sizes="(max-width: 550px) 100vw, 550px"></p> <p>After processing the payment, Stripe will redirect customers to the success page URL.</p> <p><img loading="lazy" class="alignnone size-full wp-image-12170" src="https://phppot.com/wp-content/uploads/2020/10/payment-success-page.jpg" alt="Payment Success Page" width="520" height="148" srcset="https://phppot.com/wp-content/uploads/2020/10/payment-success-page.jpg 520w, https://phppot.com/wp-content/uploads/2020/10/payment-success-page-300x85.jpg 300w" sizes="(max-width: 520px) 100vw, 520px"></p> <h2>Conclusion</h2> <p>We have seen how to integrate the stripe hosted checkout in PHP with an example. Hope it is simple and easy to follow.</p> <p>It helps to have a quick glance with the bullet points pre-requisites, implementation steps. It pinpoints the todo items in short.</p> <p>The downloadable source code has the required vendor files. It is not needed to download libraries and SDK from anywhere.</p> <p>With database intervention, the code is ready to integrate with a full-fledged application.</p> <p>With the latest Stripe checkout version, it provides payment services with SCA and more advanced features.</p> <p><a class="download" href="https://phppot.com/downloads/stripe-hosted-checkout.zip">Download</a></p> <p> <!-- #comments --> </p> <div class="related-articles"> <h2>Popular Articles</h2> </p></div> <p> <a href="https://phppot.com/php/stripe-one-time-payment-with-prebuilt-hosted-checkout-in-php/#top" class="top">↑ Back to Top</a> </p> </div> https://www.sickgaming.net/blog/2020/10/01/stripe-one-time-payment-with-prebuilt-hosted-checkout-in-php/ |