Intégration de la passerelle de paiement Stripe à l’aide de PHP

Intégration de la passerelle de paiement Stripe à l’aide de PHP

Il existe de nombreux services de paiement disponibles sur le marché. Par exemple, PayPal, Stripe, Sage Pay, CCAvenue, etc. Ils doivent intégrer une passerelle de paiement dans une application.

Tous fournissent une API pour accéder aux services de paiement via la passerelle. Stripe est l’une des passerelles de paiement les plus utilisées parmi les options disponibles. Il est célèbre pour effectuer des transactions fluides avec les cartes de crédit et de débit.

En intégrant l’API de passerelle de paiement, nous pouvons activer les options de paiement dans une application.

Nous devons choisir un fournisseur de paiement populaire et jouissant d’une bonne réputation car il s’agit d’argent réel. C’est pour avoir un soutien professionnel et une fiabilité. Stripe sera la meilleure option pour avoir des transactions garanties.

À propos de cet exemple

Cet article montrera comment intégrer la passerelle de paiement Stripe dans une application PHP. Il contient un exemple de code pour créer une option de paiement unique en PHP.

Il implémente la méthode de formulaire personnalisé de Stripe pour permettre le paiement. Stripe fournit une méthode de paiement hébergée sans code pour accepter les paiements uniques.

Dans un précédent tutoriel, nous avons vu le mode de paiement PayPal en PHP. Si vous recherchez un code d’intégration de la passerelle de paiement PayPal , l’article lié vous sera utile.

La capture d’écran ci-dessous montre le formulaire personnalisé avec l’élément de carte Stripe. Il permet aux utilisateurs de saisir les détails de leur facturation et de leur carte pour effectuer le paiement.

Stripe.js monte l’élément d’interface utilisateur pour accepter les détails de la carte du client. Il atteint l’URL du point de terminaison et envoie la demande de paiement à l’API. Les clés API sont utilisées pour l’authentification avant de traiter le paiement.

Étapes pour intégrer la passerelle de paiement Stripe

  1. Créez un compte Stripe et connectez-vous pour obtenir les clés API.
  2. Créez un formulaire de paiement et affichez l’élément Stripe pour obtenir les détails de la carte de l’utilisateur.
  3. Incluez Stripe.js pour valider, créer et confirmer le paiement par carte de manière sécurisée
  4. Traiter les demandes de paiement Stripe en PHP.
  5. Créez et configurez un webhook pour notifier la réponse.
  6. Analysez l’objet de réponse de paiement et stockez-le dans une base de données.

1. Créez un compte Stripe et obtenez des clés API

Créez un compte Stripe et connectez-vous au tableau de bord. Naviguez dans le menu Développeurs -> Clés API pour obtenir les clés API. Il existe deux types de clés API standard appelées clé secrète et clé publiable . La clé secrète sera masquée par défaut et devra être révélée en cliquant explicitement sur le contrôle du jeton de clé .

Ces clés sont stockées dans un fichier de configuration en tant que constantes PHP et seront utilisées ultérieurement dans le code de paiement Stripe.

2. Créez un formulaire de paiement et affichez un élément Stripe pour obtenir les détails de la carte de l’utilisateur

Ce formulaire HTML comprend des champs tels que le nom du titulaire de la carte, le numéro de carte, le CVC et le mois/année d’expiration pour obtenir la saisie de l’utilisateur. Nous avons déjà créé ce formulaire avec de tels champs pour l’ exemple du validateur de carte de crédit . Il inclut également le numéro_article, le nom_article, le montant et le code_monnaie comme entrée masquée.

L’API Stripe recommande d’utiliser des jetons au lieu de soumettre les détails de la carte de test lors du test de l’intégration du paiement. Les jetons de test sont mappés avec les détails de la carte tokenisée à l’aide de la bibliothèque JavaScript Stripe.

formulaire-de-paiement-ui.php

<?php
namespace Phppot;

require_once __DIR__ . '/config.php';
$currencies = Config::getCurrency();
$country = Config::getAllCountry();

?>
<h1>Stripe payment integration via custom form</h1>
<div class="phppot-container">
    <div id="payment-box"
        data-consumer-key="<?php echo Config::STRIPE_PUBLISHIABLE_KEY; ?>"
        data-create-order-url="<?php echo Config::CREATE_STRIPE_ORDER;?>"
        data-return-url="<?php echo Config::THANKYOU_URL;?>">
        <div class="row">
            <div class="label">
                Name <span class="error-msg" id="name-error"></span>
            </div>
            <input type="text" name="customer_name" class="input-box"
                id="customer_name">
        </div>
        <div class="row">
            <div class="label">
                Email <span class="error-msg" id="email-error"></span>
            </div>
            <input type="text" name="email" class="input-box" id="email">
        </div>
        <div class="row">
            <div class="label">
                Address <span class="error-msg" id="address-error"></span>
            </div>
            <input type="text" name="address" class="input-box"
                id="address">
        </div>
        <div class="row">
            <div class="label">
                Country <span class="error-msg" id="country-error"></span>
            </div>
            <input list="country-list" name="country" class="input-box"
                id="country">
            <datalist id="country-list">
                <?php foreach ($country as $key => $val) { ?>
             <option value="<?php echo $key;?>"><?php echo $val;?></option>
                <?php }?>
                    </datalist>
        </div>
        <div class="row">
            <div class="label">
                Postal code <span class="error-msg" id="postal-error"></span>
            </div>
            <input type="text" name="postal_code" class="input-box"
                id="postal_code">
        </div>
        <div class="row">
            <div class="label">
                Description <span class="error-msg" id="notes-error"></span>
            </div>
            <input type="text" name="notes" class="input-box" id="notes">
        </div>
        <div class="row">
            <div class="label">
                Amount <span class="error-msg" id="price-error"></span>
            </div>
            <input type="text" name="price" class="input-box" id="price">
        </div>
        <div class="row">
            <div class="label">
                Currency <span class="error-msg" id="currency-error"></span>
            </div>
            <input list="currency-list" name="currency"
                class="input-box" id="currency">
            <datalist id="currency-list">
            <?php foreach ($currencies as $key => $val) { ?>
             <option value="<?php echo $key;?>"><?php echo $val;?></option>
                <?php }?>
                    </datalist>

        </div>
        <div class="row">
            <div id="card-element">
                <!--Stripe.js injects the Card Element-->
            </div>
        </div>
        <div class="row">
            <button class="btnAction" id="btn-payment"
                onclick="confirmOrder(event);">
                <div class="spinner hidden" id="spinner"></div>
                <span id="button-text">Send Payment</span>
            </button>
            <p id="card-error" role="alert"></p>
        </div>

    </div>
        <?php
        if (! empty($_GET["action"]) && $_GET["action"] == "success") {
            ?><div class="success">Thank you for the payment.</div>
    <?php
        }
        ?>

<script src="https://js.stripe.com/v3/"></script>
    <script src="./assets/js/card.js"></script>

3. Incluez Stripe.js pour valider, créer et confirmer les paiements par carte de manière sécurisée

Lors de la soumission des détails de la carte, les données saisies seront validées côté client. Une fois la validation renvoyée, les détails de la carte seront envoyés au serveur get Stripe pour obtenir un jeton. L’API Stripe renverra le jeton et sera ajouté aux champs du formulaire de paiement à l’aide de Stripe ResponseHandler. Il s’agit de la fonctionnalité la plus accueillante des détails de la carte de traitement des paiements Stripe et de la validation avec le serveur Stripe via JavaScript.

Après avoir inséré le jeton, le formulaire sera soumis par programme en utilisant Javascript . Lors de la mise en œuvre de l’intégration des paiements Sage Pay , nous avons vu comment envoyer des demandes de paiement à l’aide de JavaScript.

var stripeKey = document.querySelector('#payment-box').dataset.consumerKey;
var createOrderUrl = document.querySelector('#payment-box').dataset.createOrderUrl;
var returnUrl = document.querySelector('#payment-box').dataset.returnUrl;
var stripe = Stripe(stripeKey);
var elements = stripe.elements();
var style = {
	base: {
		color: "#32325d",
		fontFamily: 'Arial, sans-serif',
		fontSmoothing: "antialiased",
		fontSize: "16px",
		"::placeholder": {
			color: "#32325d"
		}
	},
	invalid: {
		fontFamily: 'Arial, sans-serif',
		color: "#fa755a",
		iconColor: "#fa755a"
	}
};
var card = elements.create("card", {
	hidePostalCode: true,
	style: style
});
// Stripe injects an iframe into the DOM
card.mount("#card-element");
card
	.on(
		"change",
		function(event) {
			// Disable the Pay button if there are no card details in
			// the Element
			document.querySelector("button").disabled = event.empty;
			document.querySelector("#card-error").textContent = event.error ? event.error.message
				: "";
		});

function confirmOrder(event) {
	var valid = formValidate();
	if (valid) {
		var purchase = {
			email: document.getElementById("email").value,
			notes: document.getElementById("notes").value,
			unitPrice: document.getElementById("price").value,
			currency: document.getElementById("currency").value,
			name: document.getElementById("customer_name").value,
			address: document.getElementById("address").value,
			country: document.getElementById("country").value,
			postalCode: document.getElementById("postal_code").value
		};

		// Disable the button until we have Stripe set up on the page
		// document.querySelector("btnSubmit").disabled = true;
		fetch(createOrderUrl, {
			method: "POST",
			headers: {
				"Content-Type": "application/json",

			},
			body: JSON.stringify(purchase)
		}).then(function(result) {
			return result.json();
		}).then(function(data) {
			// Complete payment when the submit button is clicked
			payWithCard(stripe, card, data.clientSecret, data.orderHash);
		});
		// Calls stripe.confirmCardPayment
		// If the card requires authentication Stripe shows a pop-up modal
		// to
		// prompt the user to enter authentication details without leaving
		// your
		// page.
		var payWithCard = function(stripe, card, clientSecret, orderHash) {
			loading(true);
			stripe.confirmCardPayment(clientSecret, {
				payment_method: {
					card: card
				}
			}).then(function(result) {
				if (result.error) {
					// Show error to your customer
					showError(result.error.message);
				} else {
					// The payment succeeded!
					orderComplete(result.paymentIntent.id, orderHash);
				}
			});
		};
		/* ------- UI helpers ------- */
		// Shows a success message when the payment is complete
		var orderComplete = function(paymentIntentId, orderHash) {
			loading(false);
			window.location.href = returnUrl + "?orderId=" + orderHash;
		};
		// Show the customer the error from Stripe if their card fails to
		// charge
		var showError = function(errorMsgText) {
			loading(false);
			var errorMsg = document.querySelector("#card-error");
			errorMsg.textContent = errorMsgText;
			setTimeout(function() {
				errorMsg.textContent = "";
			}, 10000);
		};
		// Show a spinner on payment submission
		var loading = function(isLoading) {
			if (isLoading) {
				// Disable the button and show a spinner
				document.querySelector("button").disabled = true;
				document.querySelector("#spinner").classList.remove("hidden");
				document.querySelector("#button-text").classList.add("hidden");
			} else {
				document.querySelector("button").disabled = false;
				document.querySelector("#spinner").classList.add("hidden");
				document.querySelector("#button-text").classList
					.remove("hidden");
			}

		};
	}
}

4. Traiter les demandes de paiement Stripe en PHP

Téléchargez la bibliothèque Stripe PHP , nécessaire au traitement des frais à l’aide du code PHP. Les fonctions liées au paiement sont créées dans la classe PHP StripePayment.php. Il traite les frais Stripe en envoyant le jeton API et d’autres données de demande de paiement telles que l’identifiant client, le montant, la devise, etc. Après avoir traité la demande de paiement, l’API Stripe renverra la réponse de paiement sous forme d’objet JSON .

lib/StripeService.php

<?php
namespace Phppot;

use Stripe\Stripe;
use Stripe\WebhookEndpoint;
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/../Config.php';

class StripeService
{

    private $apiKey;

    private $stripeService;

    public function __construct()
    {
        require_once __DIR__ . '/../Config.php';
        $this->apiKey = Config::STRIPE_SECRET_KEY;
        $this->stripeService = new Stripe();
        $this->stripeService->setVerifySslCerts(false);
        $this->stripeService->setApiKey($this->apiKey);
    }

    public function createPaymentIntent($orderReferenceId, $amount, $currency, $email, $customerDetailsArray, $notes, $metaData)
    {
        try {
            $this->stripeService->setApiKey($this->apiKey);

            $paymentIntent = \Stripe\PaymentIntent::create([
                'description' => $notes,
                'shipping' => [
                    'name' => $customerDetailsArray["name"],
                    'address' => [
                        'line1' => $customerDetailsArray["address"],
                        'postal_code' => $customerDetailsArray["postalCode"],
                        'country' => $customerDetailsArray["country"]
                    ]
                ],
                'amount' => $amount * 100,
                'currency' => $currency,
                'payment_method_types' => [
                    'card'
                ],
                'metadata' => $metaData
            ]);
            $output = array(
                "status" => "success",
                "response" => array('orderHash' => $orderReferenceId, 'clientSecret'=>$paymentIntent->client_secret)
            );
        } catch (\Error $e) {
            $output = array(
                "status" => "error",
                "response" => $e->getMessage()
            );
        }
        return $output;
    }


    public function getToken()
    {
        $token = "";
        $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $codeAlphabet .= "abcdefghijklmnopqrstuvwxyz";
        $codeAlphabet .= "0123456789";
        $max = strlen($codeAlphabet) - 1;
        for ($i = 0; $i < 17; $i ++) {
            $token .= $codeAlphabet[mt_rand(0, $max)];
        }
        return $token;
    }

}

Créer et configurer un webhook pour notifier la réponse

Accédez au menu Stripe Developers->Webhook dans le tableau de bord. Créez ensuite une URL de point de terminaison de webhook pour notifier les occurrences d’événements de paiement à l’application.

La fenêtre de création du webhook nécessitera des événements de mappage pour le point de terminaison du webhook. Cet exemple utilise une URL de webhook mappée pour les événements répertoriés ci-dessous.

  1. payment_intent.succeeded
  2. payment_intent.payment_failed

Après avoir créé le point de terminaison du webhook dans le tableau de bord, configurez-le dans l’application. Cela sera utile pour la vérification dynamique du point de terminaison lors de la demande de l’API.

5. Analysez l’objet de réponse de paiement et stockez-le dans une base de données

L’objet JSON sérialisé est analysé pour obtenir le statut de paiement et la réponse. Les détails tels que l’e-mail, le numéro_article, le nom_article, le statut du paiement et la réponse sont stockés dans la table tbl_payment à l’aide de l’insert MySQL. J’ai utilisé l’ instruction préparée avec MySQLi pour gérer les opérations de base de données.

<?php
namespace Phppot;

use Stripe\Stripe;
use Stripe\WebhookEndpoint;
require_once __DIR__ . '/../vendor/autoload.php';

use Phppot\StripePayment;
\Stripe\Stripe::setApiKey('CLIENT_SECRET_KEY_HERE');

$json = file_get_contents("php://input");
$file = fopen("app.log", "a");

fwrite($file, $json);
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$event = null;
try {
    $event = \Stripe\Webhook::constructEvent($json, $sig_header, "WEBHOOK_SECRET_HERE");
} catch (\UnexpectedValueException $e) {
    // Invalid payload
    http_response_code(400);
    exit();
} catch (\Stripe\Exception\SignatureVerificationException $e) {
    // Invalid signature
    http_response_code(400);
    exit();
}

if (! empty($event)) {

    $eventType = $event->type;
    fwrite($file, $event);

    $orderId = $event->data->object->metadata->order_id;
    $email = $event->data->object->metadata->email;
    $paymentIntentId = $event->data->object->id;
    $amount = $event->data->object->amount;
    $stripePaymentStatus = $event->data->object->status;

    if ($eventType == "payment_intent.payment_failed") {
        $orderStatus = 'Payement Failure';

        $paymentStatus = 'Unpaid';

        $amount = $amount / 100;

        require_once __DIR__ . '/../lib/StripePayment.php';
        $stripePayment = new StripePayment();

        $stripePayment->updateOrder($paymentIntentId, $orderId, $orderStatus, $paymentStatus, $stripePaymentStatus, $event);
    }
    if ($eventType == "payment_intent.succeeded") {
        /*
         * Json values assign to php variables
         *
         */
        $orderStatus = 'Completed';

        $paymentStatus = 'Paid';

        $amount = $amount / 100;

        require_once __DIR__ . '/../lib/StripePayment.php';
        $stripePayment = new StripePayment();

        $stripePayment->updateOrder($paymentIntentId, $orderId, $orderStatus, $paymentStatus, $stripePaymentStatus, $event);

        http_response_code(200);
    }
}

?>

Structure de la base de données de paiement

Le script SQL suivant montre l’instruction de requête permettant de créer la table de base de données de paiement pour stocker les données de paiement renvoyées par l’API Stripe après le traitement de notre demande de paiement.

--
-- Table structure for table `tbl_payment`
--

CREATE TABLE `tbl_payment` (
  `id` int(11) NOT NULL,
  `order_hash` varchar(255) NOT NULL,
  `payer_email` varchar(100) NOT NULL,
  `amount` double(10,2) NOT NULL,
  `currency` varchar(25) NOT NULL,
  `payment_type` varchar(25) NOT NULL,
  `order_date` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  `order_status` varchar(25) NOT NULL,
  `notes` text NOT NULL,
  `name` varchar(25) NOT NULL,
  `address` varchar(255) NOT NULL,
  `country` varchar(25) NOT NULL,
  `postal_code` varchar(25) NOT NULL,
  `stripe_payment_intent_id` varchar(255) NOT NULL,
  `payment_status` varchar(25) NOT NULL,
  `stripe_payment_status` varchar(25) NOT NULL,
  `stripe_payment_response` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

--
-- Indexes for dumped tables
--

--
-- Indexes for table `tbl_payment`
--
ALTER TABLE `tbl_payment`
  ADD PRIMARY KEY (`id`);

--
-- AUTO_INCREMENT for dumped tables
--

--
-- AUTO_INCREMENT for table `tbl_payment`
--
ALTER TABLE `tbl_payment`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;

Test avec Stripe Payment Gateway

Trouvez plus de données de test dans la documentation de test de l’API Stripe . Vous pouvez utiliser les numéros de carte de test pour démontrer l’intégration du paiement Stripe.

Remarque : Avant la mise en ligne, nous devons tester le paiement Stripe en mode données de test. Une fois que nous aurons constaté que tout fonctionne bien avec le mode test, il sera facile de passer en direct en basculant le mode données.

Leave a Reply

Your email address will not be published. Required fields are marked *