Paiement paypal via PHP

Résolu
Programming_018 Messages postés 106 Date d'inscription vendredi 13 janvier 2017 Statut Membre Dernière intervention 14 mars 2024 - 6 mai 2023 à 17:10
Programming_018 Messages postés 106 Date d'inscription vendredi 13 janvier 2017 Statut Membre Dernière intervention 14 mars 2024 - 6 mai 2023 à 17:37

Bonjour, 

J'ai un petit soucis au niveau de mon code.
Je créer un site e-commerce avec HTML, CSS, PHP 8.1, JS et Ajax ainsi que l'API REST de Paypal.

Quand la commande est correcte cela fonctionne super bien, mais lorsque mon article est en rupture de stock et qu'un client essaie de passer une commande avec ce dernier dans le panier et bien je n'arrive pas à annulé l'interaction de l'appel paypal en signalant que l'article est en rupture.

J'ai testé de faire un header('Location: ...'), cependant aucune action ne se fait dans la vue. Juste en mode développeur dans l'onglet réseau j'ai bien mon fichier du header Location qui apparait mais sur l'écran du visiteur cela reste sur le panier sans aucune modification ni information.

Si vous avez des conseils et astuces pour améliorer mon code je suis preneur également :-)

Je vous remercie par avance de votre future aide.

Voici quelques lignes de code qui pourrais vous aidez à m'aider :-)

Mon fichier PaypalPayment.php :

<?php
namespace Parts;

use Model\connectBDD;
use Model\Entity\Cart;
use PayPalCheckoutSdk\Orders\OrdersGetRequest;
use PayPalCheckoutSdk\Payments\AuthorizationsCaptureRequest;
use PayPalHttp\HttpException;
use PayPalHttp\IOException;
use Psr\Http\Message\ServerRequestInterface;

class PaypalPayment
{
    public function __construct(readonly private string $client_id,readonly private  string $client_secret,readonly private bool $isSandbox)
    {

    }

    public function ui(Cart $cart): string
    {
        $clientID = PAYPAL_ID;
        $order = json_encode([
            "purchase_units"=> [[
                "amount"=> [
                    "currency_code"=> "EUR",
                    "value"=> $cart->getTotalPrice(),
                    "breakdown"=> [
                        "item_total"=> [  /* Required when including the items array */
                            "currency_code"=> "EUR",
                            "value"=> $cart->getTotalPrice()
                        ]
                    ]
                ],
                "items" => array_map(function ($product){
                    return [
                        'name' => $product['product']['name'],
                        'quantity' => $product['qty'],
                        'unit_amount' => [
                            'value' => $product['product']['price'],
                            'currency_code' => 'EUR'
                        ]
                    ];

                }, $cart->getProducts())
            ]]
        ]);

        return <<<HTML
            <!-- Replace "test" with your own sandbox Business account app client ID -->
            <script src="https://www.paypal.com/sdk/js?client-id=%7B%24clientID%7D&currency=EUR&intent=authorize"></script>
            <div id="paypal-button-container"></div>
            <script>
              paypal.Buttons({
                // Sets up the transaction when a payment button is clicked
                createOrder: (data, actions) => {
                  // return actions.order.create({})
                    return actions.order.create({$order})
                },
                // Finalize the transaction after payer approval
                onApprove: async (data, actions) => {
                    const authorization = await actions.order.authorize();
                    const authorizationId = authorization.purchase_units[0].payments.authorizations[0].id;
                    await fetch("/assets/parts/paypal.php", {
                        method: "post",
                        headers: {
                            "content-type": "application/json"
                        },
                        body: JSON.stringify({authorizationId})
                    })
                }
              }).render('#paypal-button-container');
            </script>
HTML;
    }

    /**
     * @throws HttpException
     * @throws IOException
     * @throws \PaymentAmountMissMatchException
     * @throws \Exception
     */
    public function handle(ServerRequestInterface $request, Cart $cart)
    {
        require '../../Model/connectBDD.php';
        if($this->isSandbox){
            $environment = new \PayPalCheckoutSdk\Core\SandboxEnvironment(PAYPAL_ID,PAYPAL_SECRET);
        }else{
            $environment = new \PayPalCheckoutSdk\Core\ProductionEnvironment(PAYPAL_ID,PAYPAL_SECRET);
        }

        $client = new \PayPalCheckoutSdk\Core\PayPalHttpClient($environment);

        $authorizationId = $request->getParsedBody()['authorizationId'];

        $request = new \PayPalCheckoutSdk\Payments\AuthorizationsGetRequest($authorizationId);

        $authorizationResponse = $client->execute($request);
        $amount = floatval($authorizationResponse->result->amount->value);
        if($amount !== $cart->getTotalPrice()) {
            throw new \PaymentAmountMissMatchException($amount, $cart->getTotalPrice());
        }

        //Vérifier si le stock est dispo
        foreach ($cart->getProducts() as $cartItem){
            $db = new connectBDD();
            $db = $db::instance();
            if($cartItem['product']['quantity'] >= $cartItem['qty']){
                $requestUpdate = $db->prepare("UPDATE article SET quantity='" . ($cartItem['product']['quantity'] - $cartItem['qty']) . "' WHERE name=:name");
                $requestUpdate->bindValue(":name", $cartItem['product']['name']);
                $requestUpdate->execute();
            }else{
                //Exemple de test pour essayer d'afficher un message à l'utilisateur
                $_SESSION['stock'] = "Plus de stock pour cet article";
                header('Location: notStock.php');
                return false;
            }
        }

        //Verrouiller le stock

        //Sauvegarder les infos de l'utilisateur
        $orderId = $authorizationResponse->result->supplementary_data->related_ids->order_id;
        $request = new OrdersGetRequest($orderId);
        $orderResponse = $client->execute($request);

        //Capturer le paiement
        $request = new AuthorizationsCaptureRequest($authorizationId);
        $response = $client->execute($request);
        $_SESSION['or_id_com'] = $orderId;

        if($response->result->status !== "COMPLETED"){
            //C'est pas ok
            throw new \Exception();
        }
        header('Location: confirmCommand.php');
    }
}

Mon fichier cart.view.php :

<div id="cart">
    <?php
        require_once './Model/Entity/Cart.php';
        require_once './Config.php';
        require_once './assets/parts/PaypalPayment.php';

        use Parts\PaypalPayment;
        use Model\Entity\Cart;

        $totalPriceTTC = 0;
        if(!isset($_SESSION['user'])){
            header("Location: index.php?642=login&error=Merci de vous connectez avant d'accéder au panier !&color=red");
            exit();
        }

        if(!isset($_SESSION['cart']) || empty($_SESSION['cart'])){
            echo "<div id='messageGET'>Le panier est vide !</div>";
        }else{
            $cart = new Cart();
            echo '<pre>';
            var_dump($_SESSION['cart']);
            echo '</pre>';

            foreach ($_SESSION['cart'] as $cartItem){
                $totalPriceTTC = floatval($totalPriceTTC) + floatval($cartItem['total_price']); ?>
                <div class="containsCart">
                    <div class="img">
                        <a href="/index.php?642=shop&choose=items&item=<?= $cartItem['product']['name']?>"><img src="/assets/pictures/uploadArticle/<?= $cartItem['product']['imgSRC']?>" alt="Image de l'article"></a>
                    </div>
                    <div class="text">
                        <div class="title">
                            <a href="/index.php?642=shop&choose=items&item=<?= $cartItem['product']['name']?>"><?= $cartItem['product']['name']?></a>
                            <span class="price"><?= $cartItem['total_price']?> €</span>
                        </div>
                        <div>
                            <p class="description">Description : <?= substr($cartItem['product']['description'], 0, 25) ?>...</p>
                            <p class="quantity">Quantité : <?= $cartItem['qty']?></p>
                            <p><?= $cartItem['product']['price']?> € l'unité</p>
                            <button class="deleteItem" data-product="<?= $cartItem['product']['id']?>">Supprimer</button>
                        </div>

                    </div>
                </div>
            <?php } ?>
            <div id="total">
                <div>
                    <p>Prix HT : <?= number_format($totalPriceTTC / 1.2, 2, ",", " ") ?> €</p>
                    <p>TVA : 20 %</p>
                    <p>Prix TTC : <?= $totalPriceTTC ?> €</p>
                    <?php
                        $payment = new PaypalPayment(PAYPAL_ID, PAYPAL_SECRET, true);
                        $cart = new Cart();
                        echo $payment->ui($cart);
                    ?>
                </div>
            </div>
<?php } ?>
</div>

Mon fichier Paypal.php :

<?php
require '../../vendor/autoload.php';
require '../../Config.php';
require 'PaymentAmountMissMatch.php';
require '../../Model/Entity/Cart.php';
require 'PaypalPayment.php';

$cart = new \Model\Entity\Cart();
session_start();

$psr17Factory = new \Nyholm\Psr7\Factory\Psr17Factory();

$creator = new \Nyholm\Psr7Server\ServerRequestCreator(
    $psr17Factory,
    $psr17Factory,
    $psr17Factory,
    $psr17Factory
);

$request = $creator->fromGlobals();

$payment = new \Parts\PaypalPayment(PAYPAL_ID, PAYPAL_SECRET, true);
$payment->handle($request, $cart);

Et enfin voici ma page confirmCommand.php:

<?php
require '../../Config.php';
require '../../Model/connectBDD.php';
require '../../Model/Entity/User.php';
require '../../vendor/autoload.php';
session_start();

use PayPalCheckoutSdk\Core\PayPalHttpClient;
use PayPalCheckoutSdk\Orders\OrdersGetRequest;
use Model\connectBDD;
use Model\Entity\User;

$environment = new \PayPalCheckoutSdk\Core\SandboxEnvironment(PAYPAL_ID,PAYPAL_SECRET);
$client = new PayPalHttpClient($environment);

$request = new OrdersGetRequest($_SESSION['or_id_com']);
$request->headers["prefer"] = "return=representation";

$request->headers["Paypal-Partner-Attribution-Id"] = PAYPAL_ID;

$response = $client->execute($request);
$order = $response->result;

//Exemple pour récupérer le premier nom de l'article dans la commande.
$name = $order->purchase_units[0]->items[0]->name;
$price = $order->purchase_units[0]->items[0]->unit_amount->value;
$quantity = $order->purchase_units[0]->items[0]->quantity;
$currency_code = $order->purchase_units[0]->items[0]->unit_amount->currency_code;
$user = $_SESSION['user'];

$pdo = connectBDD::instance();

$select = $pdo->prepare("SELECT MAX(numberCommand) FROM command");
$select->execute();
$numberCommand = $select->fetch();
var_dump($numberCommand["MAX(numberCommand)"]);
$numberCommand["MAX(numberCommand)"] += 1;

foreach ($order->purchase_units as $purchase_unit) {
    foreach ($purchase_unit->items as $item) {
        $name = $item->name;
        $price = $item->unit_amount->value;
        $currency_code = $item->unit_amount->currency_code;
        $quantity = $item->quantity;
        $statut = "En attente";

        date_default_timezone_set("Europe/Paris");
        $date = date('Y-m-d H:i:s');
        $stmt = $pdo->prepare("INSERT INTO command (numberCommand, name_article, total_price, currency_code, quantity, date_command, statut, user_id) VALUES (:numberCommand, :name_article, :total_price, :currency_code, :quantity, :date_command, :statut,(SELECT id FROM user WHERE email=:email))");
        $stmt->bindValue(":numberCommand", $numberCommand["MAX(numberCommand)"]);
        $stmt->bindValue(":name_article", $name);
        $stmt->bindValue(":total_price", $price);
        $stmt->bindValue(":currency_code", $currency_code);
        $stmt->bindValue(":quantity", $quantity);
        $stmt->bindValue(":date_command", $date);
        $stmt->bindValue(":statut", $statut);
        $stmt->bindValue(":email", $user->getEmail());

        try {
            $stmt->execute();
            echo "Commande ajoutée à la base de données avec succès !";
        } catch (\PDOException $e) {
            echo "Erreur lors de l'ajout de la commande à la base de données : " . $e->getMessage();
        }
    }
}

unset($_SESSION['cart']);
unset($_SESSION['or_id_com']);



A voir également:

1 réponse

Programming_018 Messages postés 106 Date d'inscription vendredi 13 janvier 2017 Statut Membre Dernière intervention 14 mars 2024 7
Modifié le 6 mai 2023 à 17:38

En fait j'ai réussi gràce à l'ajax et à un alert certe c'est moche mais ça à le mérite de fonctionnait :-)

Si vous avez des suggestions n'hésitez pas.

0